Back to index

cell-binutils  2.17cvs20070401
Defines | Functions | Variables
cg_print.c File Reference
#include "libiberty.h"
#include "gprof.h"
#include "search_list.h"
#include "source.h"
#include "symtab.h"
#include "cg_arcs.h"
#include "cg_print.h"
#include "hist.h"
#include "utils.h"
#include "corefile.h"

Go to the source code of this file.

Defines

#define LESSTHAN   -1
#define EQUALTO   0
#define GREATERTHAN   1
#define MOST   0.99

Functions

static void print_header (void)
static void print_cycle (Sym *)
static int cmp_member (Sym *, Sym *)
static void sort_members (Sym *)
static void print_members (Sym *)
static int cmp_arc (Arc *, Arc *)
static void sort_parents (Sym *)
static void print_parents (Sym *)
static void sort_children (Sym *)
static void print_children (Sym *)
static void print_line (Sym *)
static int cmp_name (const PTR, const PTR)
static int cmp_arc_count (const PTR, const PTR)
static int cmp_fun_nuses (const PTR, const PTR)
static void order_and_dump_functions_by_arcs (Arc **, unsigned long, int, Arc **, unsigned long *)
void bsd_callg_blurb (FILE *fp)
void fsf_callg_blurb (FILE *fp)
void cg_print (Sym **timesortsym)
void cg_print_index ()
void cg_print_function_ordering ()
void cg_print_file_ordering ()

Variables

double print_time = 0.0

Define Documentation

#define EQUALTO   0

Definition at line 35 of file cg_print.c.

#define GREATERTHAN   1

Definition at line 36 of file cg_print.c.

#define LESSTHAN   -1

Definition at line 34 of file cg_print.c.

#define MOST   0.99

Definition at line 984 of file cg_print.c.


Function Documentation

void bsd_callg_blurb ( FILE *  fp)

Here is the caller graph for this function:

void cg_print ( Sym **  timesortsym)

Definition at line 499 of file cg_print.c.

{
  unsigned int index;
  Sym *parent;

  if (print_descriptions && bsd_style_output)
    bsd_callg_blurb (stdout);

  print_header ();

  for (index = 0; index < symtab.len + num_cycles; ++index)
    {
      parent = timesortsym[index];

      if ((ignore_zeros && parent->ncalls == 0
          && parent->cg.self_calls == 0 && parent->cg.prop.self == 0
          && parent->cg.prop.child == 0)
         || !parent->cg.print_flag
         || (line_granularity && ! parent->is_func))
       continue;

      if (!parent->name && parent->cg.cyc.num != 0)
       {
         /* Cycle header.  */
         print_cycle (parent);
         print_members (parent);
       }
      else
       {
         print_parents (parent);
         print_line (parent);
         print_children (parent);
       }

      if (bsd_style_output)
       printf ("\n");

      printf ("-----------------------------------------------\n");

      if (bsd_style_output)
       printf ("\n");
    }

  free (timesortsym);

  if (print_descriptions && !bsd_style_output)
    fsf_callg_blurb (stdout);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void cg_print_file_ordering ( void  )

Definition at line 1225 of file cg_print.c.

{
  unsigned long scratch_arc_count, index;
  Arc **scratch_arcs;
  char *last;

  scratch_arc_count = 0;

  scratch_arcs = (Arc **) xmalloc (numarcs * sizeof (Arc *));
  for (index = 0; index < numarcs; index++)
    {
      if (! arcs[index]->parent->mapped
         || ! arcs[index]->child->mapped)
       arcs[index]->has_been_placed = 1;
    }

  order_and_dump_functions_by_arcs (arcs, numarcs, 0,
                                scratch_arcs, &scratch_arc_count);

  /* Output .o's not handled by the main placement algorithm.  */
  for (index = 0; index < symtab.len; index++)
    {
      if (symtab.base[index].mapped
         && ! symtab.base[index].has_been_placed)
       printf ("%s\n", symtab.base[index].name);
    }

  /* Now output any .o's that didn't have any text symbols.  */
  last = NULL;
  for (index = 0; index < symbol_map_count; index++)
    {
      unsigned int index2;

      /* Don't bother searching if this symbol
        is the same as the previous one.  */
      if (last && !strcmp (last, symbol_map[index].file_name))
       continue;

      for (index2 = 0; index2 < symtab.len; index2++)
       {
         if (! symtab.base[index2].mapped)
           continue;

         if (!strcmp (symtab.base[index2].name, symbol_map[index].file_name))
           break;
       }

      /* If we didn't find it in the symbol table, then it must
        be a .o with no text symbols.  Output it last.  */
      if (index2 == symtab.len)
       printf ("%s\n", symbol_map[index].file_name);
      last = symbol_map[index].file_name;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void cg_print_function_ordering ( void  )

Definition at line 773 of file cg_print.c.

{
  unsigned long index, used, unused, scratch_index;
  unsigned long  unplaced_arc_count, high_arc_count, scratch_arc_count;
#ifdef __GNUC__
  unsigned long long total_arcs, tmp_arcs_count;
#else
  unsigned long total_arcs, tmp_arcs_count;
#endif
  Sym **unused_syms, **used_syms, **scratch_syms;
  Arc **unplaced_arcs, **high_arcs, **scratch_arcs;

  index = 0;
  used = 0;
  unused = 0;
  scratch_index = 0;
  unplaced_arc_count = 0;
  high_arc_count = 0;
  scratch_arc_count = 0;

  /* First group all the unused functions together.  */
  unused_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
  used_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
  scratch_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
  high_arcs = (Arc **) xmalloc (numarcs * sizeof (Arc *));
  scratch_arcs = (Arc **) xmalloc (numarcs * sizeof (Arc *));
  unplaced_arcs = (Arc **) xmalloc (numarcs * sizeof (Arc *));

  /* Walk through all the functions; mark those which are never
     called as placed (we'll emit them as a group later).  */
  for (index = 0, used = 0, unused = 0; index < symtab.len; index++)
    {
      if (symtab.base[index].ncalls == 0)
       {
         /* Filter out gprof generated names.  */
         if (strcmp (symtab.base[index].name, "<locore>")
             && strcmp (symtab.base[index].name, "<hicore>"))
           {
             unused_syms[unused++] = &symtab.base[index];
             symtab.base[index].has_been_placed = 1;
           }
       }
      else
       {
         used_syms[used++] = &symtab.base[index];
         symtab.base[index].has_been_placed = 0;
         symtab.base[index].next = 0;
         symtab.base[index].prev = 0;
         symtab.base[index].nuses = 0;
       }
    }

  /* Sort the arcs from most used to least used.  */
  qsort (arcs, numarcs, sizeof (Arc *), cmp_arc_count);

  /* Compute the total arc count.  Also mark arcs as unplaced.

     Note we don't compensate for overflow if that happens!
     Overflow is much less likely when this file is compiled
     with GCC as it can double-wide integers via long long.  */
  total_arcs = 0;
  for (index = 0; index < numarcs; index++)
    {
      total_arcs += arcs[index]->count;
      arcs[index]->has_been_placed = 0;
    }

  /* We want to pull out those functions which are referenced
     by many highly used arcs and emit them as a group.  This
     could probably use some tuning.  */
  tmp_arcs_count = 0;
  for (index = 0; index < numarcs; index++)
    {
      tmp_arcs_count += arcs[index]->count;

      /* Count how many times each parent and child are used up
        to our threshhold of arcs (90%).  */
      if ((double)tmp_arcs_count / (double)total_arcs > 0.90)
       break;

      arcs[index]->child->nuses++;
    }

  /* Now sort a temporary symbol table based on the number of
     times each function was used in the highest used arcs.  */
  memcpy (scratch_syms, used_syms, used * sizeof (Sym *));
  qsort (scratch_syms, used, sizeof (Sym *), cmp_fun_nuses);

  /* Now pick out those symbols we're going to emit as
     a group.  We take up to 1.25% of the used symbols.  */
  for (index = 0; index < used / 80; index++)
    {
      Sym *sym = scratch_syms[index];
      Arc *arc;

      /* If we hit symbols that aren't used from many call sites,
        then we can quit.  We choose five as the low limit for
        no particular reason.  */
      if (sym->nuses == 5)
       break;

      /* We're going to need the arcs between these functions.
        Unfortunately, we don't know all these functions
        until we're done.  So we keep track of all the arcs
        to the functions we care about, then prune out those
        which are uninteresting.

        An interesting variation would be to quit when we found
        multi-call site functions which account for some percentage
        of the arcs.  */
      arc = sym->cg.children;

      while (arc)
       {
         if (arc->parent != arc->child)
           scratch_arcs[scratch_arc_count++] = arc;
         arc->has_been_placed = 1;
         arc = arc->next_child;
       }

      arc = sym->cg.parents;

      while (arc)
       {
         if (arc->parent != arc->child)
           scratch_arcs[scratch_arc_count++] = arc;
         arc->has_been_placed = 1;
         arc = arc->next_parent;
       }

      /* Keep track of how many symbols we're going to place.  */
      scratch_index = index;

      /* A lie, but it makes identifying
        these functions easier later.  */
      sym->has_been_placed = 1;
    }

  /* Now walk through the temporary arcs and copy
     those we care about into the high arcs array.  */
  for (index = 0; index < scratch_arc_count; index++)
    {
      Arc *arc = scratch_arcs[index];

      /* If this arc refers to highly used functions, then
        then we want to keep it.  */
      if (arc->child->has_been_placed
         && arc->parent->has_been_placed)
       {
         high_arcs[high_arc_count++] = scratch_arcs[index];

         /* We need to turn of has_been_placed since we're going to
            use the main arc placement algorithm on these arcs.  */
         arc->child->has_been_placed = 0;
         arc->parent->has_been_placed = 0;
       }
    }

  /* Dump the multi-site high usage functions which are not
     going to be ordered by the main ordering algorithm.  */
  for (index = 0; index < scratch_index; index++)
    {
      if (scratch_syms[index]->has_been_placed)
       printf ("%s\n", scratch_syms[index]->name);
    }

  /* Now we can order the multi-site high use
     functions based on the arcs between them.  */
  qsort (high_arcs, high_arc_count, sizeof (Arc *), cmp_arc_count);
  order_and_dump_functions_by_arcs (high_arcs, high_arc_count, 1,
                                unplaced_arcs, &unplaced_arc_count);

  /* Order and dump the high use functions left,
     these typically have only a few call sites.  */
  order_and_dump_functions_by_arcs (arcs, numarcs, 0,
                                unplaced_arcs, &unplaced_arc_count);

  /* Now place the rarely used functions.  */
  order_and_dump_functions_by_arcs (unplaced_arcs, unplaced_arc_count, 1,
                                scratch_arcs, &scratch_arc_count);

  /* Output any functions not emitted by the order_and_dump calls.  */
  for (index = 0; index < used; index++)
    if (used_syms[index]->has_been_placed == 0)
      printf("%s\n", used_syms[index]->name);

  /* Output the unused functions.  */
  for (index = 0; index < unused; index++)
    printf("%s\n", unused_syms[index]->name);

  unused_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
  used_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
  scratch_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
  high_arcs = (Arc **) xmalloc (numarcs * sizeof (Arc *));
  scratch_arcs = (Arc **) xmalloc (numarcs * sizeof (Arc *));
  unplaced_arcs = (Arc **) xmalloc (numarcs * sizeof (Arc *));

  free (unused_syms);
  free (used_syms);
  free (scratch_syms);
  free (high_arcs);
  free (scratch_arcs);
  free (unplaced_arcs);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void cg_print_index ( void  )

Definition at line 560 of file cg_print.c.

{
  unsigned int index;
  unsigned int nnames, todo, i, j;
  int col, starting_col;
  Sym **name_sorted_syms, *sym;
  const char *filename;
  char buf[20];
  int column_width = (output_width - 1) / 3;     /* Don't write in last col!  */

  /* Now, sort regular function name
     alphabetically to create an index.  */
  name_sorted_syms = (Sym **) xmalloc ((symtab.len + num_cycles) * sizeof (Sym *));

  for (index = 0, nnames = 0; index < symtab.len; index++)
    {
      if (ignore_zeros && symtab.base[index].ncalls == 0
         && symtab.base[index].hist.time == 0)
       continue;

      name_sorted_syms[nnames++] = &symtab.base[index];
    }

  qsort (name_sorted_syms, nnames, sizeof (Sym *), cmp_name);

  for (index = 1, todo = nnames; index <= num_cycles; index++)
    name_sorted_syms[todo++] = &cycle_header[index];

  printf ("\f\n");
  printf (_("Index by function name\n\n"));
  index = (todo + 2) / 3;

  for (i = 0; i < index; i++)
    {
      col = 0;
      starting_col = 0;

      for (j = i; j < todo; j += index)
       {
         sym = name_sorted_syms[j];

         if (sym->cg.print_flag)
           sprintf (buf, "[%d]", sym->cg.index);
         else
           sprintf (buf, "(%d)", sym->cg.index);

         if (j < nnames)
           {
             if (bsd_style_output)
              {
                printf ("%6.6s %-19.19s", buf, sym->name);
              }
             else
              {
                col += strlen (buf);

                for (; col < starting_col + 5; ++col)
                  putchar (' ');

                printf (" %s ", buf);
                col += print_name_only (sym);

                if (!line_granularity && sym->is_static && sym->file)
                  {
                    filename = sym->file->name;

                    if (!print_path)
                     {
                       filename = strrchr (filename, '/');

                       if (filename)
                         ++filename;
                       else
                         filename = sym->file->name;
                     }

                    printf (" (%s)", filename);
                    col += strlen (filename) + 3;
                  }
              }
           }
         else
           {
             if (bsd_style_output)
              {
                printf ("%6.6s ", buf);
                sprintf (buf, _("<cycle %d>"), sym->cg.cyc.num);
                printf ("%-19.19s", buf);
              }
             else
              {
                col += strlen (buf);
                for (; col < starting_col + 5; ++col)
                  putchar (' ');
                printf (" %s ", buf);
                sprintf (buf, _("<cycle %d>"), sym->cg.cyc.num);
                printf ("%s", buf);
                col += strlen (buf);
              }
           }

         starting_col += column_width;
       }

      printf ("\n");
    }

  free (name_sorted_syms);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int cmp_arc ( Arc left,
Arc right 
) [static]

Definition at line 221 of file cg_print.c.

{
  Sym *left_parent = left->parent;
  Sym *left_child = left->child;
  Sym *right_parent = right->parent;
  Sym *right_child = right->child;
  double left_time, right_time;

  DBG (TIMEDEBUG,
       printf ("[cmp_arc] ");
       print_name (left_parent);
       printf (" calls ");
       print_name (left_child);
       printf (" %f + %f %lu/%lu\n", left->time, left->child_time,
              left->count, left_child->ncalls);
       printf ("[cmp_arc] ");
       print_name (right_parent);
       printf (" calls ");
       print_name (right_child);
       printf (" %f + %f %lu/%lu\n", right->time, right->child_time,
              right->count, right_child->ncalls);
       printf ("\n");
    );

  if (left_parent == left_child)
    return LESSTHAN;        /* Left is a self call.  */

  if (right_parent == right_child)
    return GREATERTHAN;            /* Right is a self call.  */

  if (left_parent->cg.cyc.num != 0 && left_child->cg.cyc.num != 0
      && left_parent->cg.cyc.num == left_child->cg.cyc.num)
    {
      /* Left is a call within a cycle.  */
      if (right_parent->cg.cyc.num != 0 && right_child->cg.cyc.num != 0
         && right_parent->cg.cyc.num == right_child->cg.cyc.num)
       {
         /* Right is a call within the cycle, too.  */
         if (left->count < right->count)
           return LESSTHAN;

         if (left->count > right->count)
           return GREATERTHAN;

         return EQUALTO;
       }
      else
       {
         /* Right isn't a call within the cycle.  */
         return LESSTHAN;
       }
    }
  else
    {
      /* Left isn't a call within a cycle.  */
      if (right_parent->cg.cyc.num != 0 && right_child->cg.cyc.num != 0
         && right_parent->cg.cyc.num == right_child->cg.cyc.num)
       {
         /* Right is a call within a cycle.  */
         return GREATERTHAN;
       }
      else
       {
         /* Neither is a call within a cycle.  */
         left_time = left->time + left->child_time;
         right_time = right->time + right->child_time;

         if (left_time < right_time)
           return LESSTHAN;

         if (left_time > right_time)
           return GREATERTHAN;

         if (left->count < right->count)
           return LESSTHAN;

         if (left->count > right->count)
           return GREATERTHAN;

         return EQUALTO;
       }
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int cmp_arc_count ( const PTR  left,
const PTR  right 
) [static]

Definition at line 674 of file cg_print.c.

{
  const Arc **npp1 = (const Arc **) left;
  const Arc **npp2 = (const Arc **) right;

  if ((*npp1)->count > (*npp2)->count)
    return -1;
  else if ((*npp1)->count < (*npp2)->count)
    return 1;
  else
    return 0;
}

Here is the caller graph for this function:

static int cmp_fun_nuses ( const PTR  left,
const PTR  right 
) [static]

Definition at line 691 of file cg_print.c.

{
  const Sym **npp1 = (const Sym **) left;
  const Sym **npp2 = (const Sym **) right;

  if ((*npp1)->nuses > (*npp2)->nuses)
    return -1;
  else if ((*npp1)->nuses < (*npp2)->nuses)
    return 1;
  else
    return 0;
}

Here is the caller graph for this function:

static int cmp_member ( Sym left,
Sym right 
) [static]

Definition at line 135 of file cg_print.c.

{
  double left_time = left->cg.prop.self + left->cg.prop.child;
  double right_time = right->cg.prop.self + right->cg.prop.child;
  unsigned long left_calls = left->ncalls + left->cg.self_calls;
  unsigned long right_calls = right->ncalls + right->cg.self_calls;

  if (left_time > right_time)
    return GREATERTHAN;

  if (left_time < right_time)
    return LESSTHAN;

  if (left_calls > right_calls)
    return GREATERTHAN;

  if (left_calls < right_calls)
    return LESSTHAN;

  return EQUALTO;
}

Here is the caller graph for this function:

static int cmp_name ( const PTR  left,
const PTR  right 
) [static]

Definition at line 550 of file cg_print.c.

{
  const Sym **npp1 = (const Sym **) left;
  const Sym **npp2 = (const Sym **) right;

  return strcmp ((*npp1)->name, (*npp2)->name);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void fsf_callg_blurb ( FILE *  fp)

Here is the caller graph for this function:

static void order_and_dump_functions_by_arcs ( Arc **  the_arcs,
unsigned long  arc_count,
int  all,
Arc **  unplaced_arcs,
unsigned long unplaced_arc_count 
) [static]

Definition at line 986 of file cg_print.c.

{
#ifdef __GNUC__
  unsigned long long tmp_arcs, total_arcs;
#else
  unsigned long tmp_arcs, total_arcs;
#endif
  unsigned int index;

  /* If needed, compute the total arc count.

     Note we don't compensate for overflow if that happens!  */
  if (! all)
    {
      total_arcs = 0;
      for (index = 0; index < arc_count; index++)
       total_arcs += the_arcs[index]->count;
    }
  else
    total_arcs = 0;

  tmp_arcs = 0;

  for (index = 0; index < arc_count; index++)
    {
      Sym *sym1, *sym2;
      Sym *child, *parent;

      tmp_arcs += the_arcs[index]->count;

      /* Ignore this arc if it's already been placed.  */
      if (the_arcs[index]->has_been_placed)
       continue;

      child = the_arcs[index]->child;
      parent = the_arcs[index]->parent;

      /* If we're not using all arcs, and this is a rarely used
        arc, then put it on the unplaced_arc list.  Similarly
        if both the parent and child of this arc have been placed.  */
      if ((! all && (double)tmp_arcs / (double)total_arcs > MOST)
         || child->has_been_placed || parent->has_been_placed)
       {
         unplaced_arcs[(*unplaced_arc_count)++] = the_arcs[index];
         continue;
       }

      /* If all slots in the parent and child are full, then there isn't
        anything we can do right now.  We'll place this arc on the
        unplaced arc list in the hope that a global positioning
        algorithm can use it to place function chains.  */
      if (parent->next && parent->prev && child->next && child->prev)
       {
         unplaced_arcs[(*unplaced_arc_count)++] = the_arcs[index];
         continue;
       }

      /* If the parent is unattached, then find the closest
        place to attach it onto child's chain.   Similarly
        for the opposite case.  */
      if (!parent->next && !parent->prev)
       {
         int next_count = 0;
         int prev_count = 0;
         Sym *prev = child;
         Sym *next = child;

         /* Walk to the beginning and end of the child's chain.  */
         while (next->next)
           {
             next = next->next;
             next_count++;
           }

         while (prev->prev)
           {
             prev = prev->prev;
             prev_count++;
           }

         /* Choose the closest.  */
         child = next_count < prev_count ? next : prev;
       }
      else if (! child->next && !child->prev)
       {
         int next_count = 0;
         int prev_count = 0;
         Sym *prev = parent;
         Sym *next = parent;

         while (next->next)
           {
             next = next->next;
             next_count++;
           }

         while (prev->prev)
           {
             prev = prev->prev;
             prev_count++;
           }

         parent = prev_count < next_count ? prev : next;
       }
      else
       {
         /* Couldn't find anywhere to attach the functions,
            put the arc on the unplaced arc list.  */
         unplaced_arcs[(*unplaced_arc_count)++] = the_arcs[index];
         continue;
       }

      /* Make sure we don't tie two ends together.  */
      sym1 = parent;
      if (sym1->next)
       while (sym1->next)
         sym1 = sym1->next;
      else
       while (sym1->prev)
         sym1 = sym1->prev;

      sym2 = child;
      if (sym2->next)
       while (sym2->next)
         sym2 = sym2->next;
      else
       while (sym2->prev)
         sym2 = sym2->prev;

      if (sym1 == child
         && sym2 == parent)
       {
         /* This would tie two ends together.  */
         unplaced_arcs[(*unplaced_arc_count)++] = the_arcs[index];
         continue;
       }

      if (parent->next)
       {
         /* Must attach to the parent's prev field.  */
         if (! child->next)
           {
             /* parent-prev and child-next */
             parent->prev = child;
             child->next = parent;
             the_arcs[index]->has_been_placed = 1;
           }
       }
      else if (parent->prev)
       {
         /* Must attach to the parent's next field.  */
         if (! child->prev)
           {
             /* parent-next and child-prev */
             parent->next = child;
             child->prev = parent;
             the_arcs[index]->has_been_placed = 1;
           }
       }
      else
       {
         /* Can attach to either field in the parent, depends
            on where we've got space in the child.  */
         if (child->prev)
           {
             /* parent-prev and child-next.  */
             parent->prev = child;
             child->next = parent;
             the_arcs[index]->has_been_placed = 1;
           }
         else
           {
             /* parent-next and child-prev.  */
             parent->next = child;
             child->prev = parent;
             the_arcs[index]->has_been_placed = 1;
           }
       }
    }

  /* Dump the chains of functions we've made.  */
  for (index = 0; index < arc_count; index++)
    {
      Sym *sym;
      if (the_arcs[index]->parent->has_been_placed
         || the_arcs[index]->child->has_been_placed)
       continue;

      sym = the_arcs[index]->parent;

      /* If this symbol isn't attached to any other
        symbols, then we've got a rarely used arc.

        Skip it for now, we'll deal with them later.  */
      if (sym->next == NULL
         && sym->prev == NULL)
       continue;

      /* Get to the start of this chain.  */
      while (sym->prev)
       sym = sym->prev;

      while (sym)
       {
         /* Mark it as placed.  */
         sym->has_been_placed = 1;
         printf ("%s\n", sym->name);
         sym = sym->next;
       }
    }

  /* If we want to place all the arcs, then output
     those which weren't placed by the main algorithm.  */
  if (all)
    for (index = 0; index < arc_count; index++)
      {
       Sym *sym;
       if (the_arcs[index]->parent->has_been_placed
           || the_arcs[index]->child->has_been_placed)
         continue;

       sym = the_arcs[index]->parent;

       sym->has_been_placed = 1;
       printf ("%s\n", sym->name);
      }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void print_children ( Sym parent) [static]

Definition at line 427 of file cg_print.c.

{
  Sym *child;
  Arc *arc;

  sort_children (parent);
  arc = parent->cg.children;

  for (arc = parent->cg.children; arc; arc = arc->next_child)
    {
      child = arc->child;
      if (child == parent || (child->cg.cyc.num != 0
                           && child->cg.cyc.num == parent->cg.cyc.num))
       {
         /* Self call or call to sibling.  */
         printf (bsd_style_output
                ? "%6.6s %5.5s %7.7s %11.11s %7lu %7.7s     "
                : "%6.6s %5.5s %7.7s %7.7s %7lu %7.7s     ",
                "", "", "", "", arc->count, "");
         print_name (child);
         printf ("\n");
       }
      else
       {
         /* Regular child of parent.  */
         printf (bsd_style_output
                ? "%6.6s %5.5s %7.2f %11.2f %7lu/%-7lu     "
                : "%6.6s %5.5s %7.2f %7.2f %7lu/%-7lu     ",
                "", "",
                arc->time / hz, arc->child_time / hz,
                arc->count, child->cg.cyc.head->ncalls);
         print_name (child);
         printf ("\n");
       }
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void print_cycle ( Sym cyc) [static]

Definition at line 112 of file cg_print.c.

{
  char buf[BUFSIZ];

  sprintf (buf, "[%d]", cyc->cg.index);
  printf (bsd_style_output
         ? "%-6.6s %5.1f %7.2f %11.2f %7lu"
         : "%-6.6s %5.1f %7.2f %7.2f %7lu", buf,
         100 * (cyc->cg.prop.self + cyc->cg.prop.child) / print_time,
         cyc->cg.prop.self / hz, cyc->cg.prop.child / hz, cyc->ncalls);

  if (cyc->cg.self_calls != 0)
    printf ("+%-7lu", cyc->cg.self_calls);
  else
    printf (" %7.7s", "");

  printf (_(" <cycle %d as a whole> [%d]\n"), cyc->cg.cyc.num, cyc->cg.index);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void print_header ( void  ) [static]

Definition at line 63 of file cg_print.c.

{
  if (first_output)
    first_output = FALSE;
  else
    printf ("\f\n");

  if (!bsd_style_output)
    {
      if (print_descriptions)
       printf (_("\t\t     Call graph (explanation follows)\n\n"));
      else
       printf (_("\t\t\tCall graph\n\n"));
    }

  printf (_("\ngranularity: each sample hit covers %ld byte(s)"),
         (long) hist_scale * sizeof (UNIT));

  if (print_time > 0.0)
    printf (_(" for %.2f%% of %.2f seconds\n\n"),
           100.0 / print_time, print_time / hz);
  else
    {
      printf (_(" no time propagated\n\n"));

      /* This doesn't hurt, since all the numerators will be 0.0.  */
      print_time = 1.0;
    }

  if (bsd_style_output)
    {
      printf ("%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s     %-8.8s\n",
             "", "", "", "", _("called"), _("total"), _("parents"));
      printf ("%-6.6s %5.5s %7.7s %11.11s %7.7s+%-7.7s %-8.8s\t%5.5s\n",
             _("index"), _("%time"), _("self"), _("descendants"),
             _("called"), _("self"), _("name"), _("index"));
      printf ("%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s     %-8.8s\n",
             "", "", "", "", _("called"), _("total"), _("children"));
      printf ("\n");
    }
  else
    {
      printf (_("index %% time    self  children    called     name\n"));
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void print_line ( Sym np) [static]

Definition at line 466 of file cg_print.c.

{
  char buf[BUFSIZ];

  sprintf (buf, "[%d]", np->cg.index);
  printf (bsd_style_output
         ? "%-6.6s %5.1f %7.2f %11.2f"
         : "%-6.6s %5.1f %7.2f %7.2f", buf,
         100 * (np->cg.prop.self + np->cg.prop.child) / print_time,
         np->cg.prop.self / hz, np->cg.prop.child / hz);

  if ((np->ncalls + np->cg.self_calls) != 0)
    {
      printf (" %7lu", np->ncalls);

      if (np->cg.self_calls != 0)
         printf ("+%-7lu ", np->cg.self_calls);
      else
         printf (" %7.7s ", "");
    }
  else
    {
      printf (" %7.7s %7.7s ", "", "");
    }

  print_name (np);
  printf ("\n");
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void print_members ( Sym cyc) [static]

Definition at line 187 of file cg_print.c.

{
  Sym *member;

  sort_members (cyc);

  for (member = cyc->cg.cyc.next; member; member = member->cg.cyc.next)
    {
      printf (bsd_style_output
             ? "%6.6s %5.5s %7.2f %11.2f %7lu"
             : "%6.6s %5.5s %7.2f %7.2f %7lu",
             "", "", member->cg.prop.self / hz, member->cg.prop.child / hz,
             member->ncalls);

      if (member->cg.self_calls != 0)
       printf ("+%-7lu", member->cg.self_calls);
      else
       printf (" %7.7s", "");

      printf ("     ");
      print_name (member);
      printf ("\n");
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void print_parents ( Sym child) [static]

Definition at line 340 of file cg_print.c.

{
  Sym *parent;
  Arc *arc;
  Sym *cycle_head;

  if (child->cg.cyc.head != 0)
    cycle_head = child->cg.cyc.head;
  else
    cycle_head = child;

  if (!child->cg.parents)
    {
      printf (bsd_style_output
             ? _("%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s     <spontaneous>\n")
             : _("%6.6s %5.5s %7.7s %7.7s %7.7s %7.7s     <spontaneous>\n"),
             "", "", "", "", "", "");
      return;
    }

  sort_parents (child);

  for (arc = child->cg.parents; arc; arc = arc->next_parent)
    {
      parent = arc->parent;
      if (child == parent || (child->cg.cyc.num != 0
                           && parent->cg.cyc.num == child->cg.cyc.num))
       {
         /* Selfcall or call among siblings.  */
         printf (bsd_style_output
                ? "%6.6s %5.5s %7.7s %11.11s %7lu %7.7s     "
                : "%6.6s %5.5s %7.7s %7.7s %7lu %7.7s     ",
                "", "", "", "",
                arc->count, "");
         print_name (parent);
         printf ("\n");
       }
      else
       {
         /* Regular parent of child.  */
         printf (bsd_style_output
                ? "%6.6s %5.5s %7.2f %11.2f %7lu/%-7lu     "
                : "%6.6s %5.5s %7.2f %7.2f %7lu/%-7lu     ",
                "", "",
                arc->time / hz, arc->child_time / hz,
                arc->count, cycle_head->ncalls);
         print_name (parent);
         printf ("\n");
       }
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void sort_children ( Sym parent) [static]

Definition at line 394 of file cg_print.c.

{
  Arc *arc, *detached, sorted, *prev;

  /* Unlink children from parent, then insertion sort back on to
     sorted's children.
         *arc        the arc you have detached and are inserting.
         *detached   the rest of the arcs to be sorted.
         sorted      arc list onto which you insertion sort.
         *prev       arc before the arc you are comparing.  */
  sorted.next_child = 0;

  for (arc = parent->cg.children; arc; arc = detached)
    {
      detached = arc->next_child;

      /* Consider *arc as disconnected; insert it into sorted.  */
      for (prev = &sorted; prev->next_child; prev = prev->next_child)
       {
         if (cmp_arc (arc, prev->next_child) != LESSTHAN)
           break;
       }

      arc->next_child = prev->next_child;
      prev->next_child = arc;
    }

  /* Reattach sorted children to parent.  */
  parent->cg.children = sorted.next_child;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void sort_members ( Sym cyc) [static]

Definition at line 160 of file cg_print.c.

{
  Sym *todo, *doing, *prev;

  /* Detach cycle members from cyclehead,
     and insertion sort them back on.  */
  todo = cyc->cg.cyc.next;
  cyc->cg.cyc.next = 0;

  for (doing = todo; doing && doing->cg.cyc.next; doing = todo)
    {
      todo = doing->cg.cyc.next;

      for (prev = cyc; prev->cg.cyc.next; prev = prev->cg.cyc.next)
       {
         if (cmp_member (doing, prev->cg.cyc.next) == GREATERTHAN)
           break;
       }

      doing->cg.cyc.next = prev->cg.cyc.next;
      prev->cg.cyc.next = doing;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void sort_parents ( Sym child) [static]

Definition at line 307 of file cg_print.c.

{
  Arc *arc, *detached, sorted, *prev;

  /* Unlink parents from child, then insertion sort back on to
     sorted's parents.
         *arc        the arc you have detached and are inserting.
         *detached   the rest of the arcs to be sorted.
         sorted      arc list onto which you insertion sort.
         *prev       arc before the arc you are comparing.  */
  sorted.next_parent = 0;

  for (arc = child->cg.parents; arc; arc = detached)
    {
      detached = arc->next_parent;

      /* Consider *arc as disconnected; insert it into sorted.  */
      for (prev = &sorted; prev->next_parent; prev = prev->next_parent)
       {
         if (cmp_arc (arc, prev->next_parent) != GREATERTHAN)
           break;
       }

      arc->next_parent = prev->next_parent;
      prev->next_parent = arc;
    }

  /* Reattach sorted arcs to child.  */
  child->cg.parents = sorted.next_parent;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

Definition at line 59 of file cg_print.c.