OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [tags/] [gnu-src/] [newlib-1.18.0/] [newlib-1.18.0-or32-1.0rc1/] [libgloss/] [mep/] [mep-bb.c] - Diff between revs 207 and 345

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 207 Rev 345
/*
/*
 * Copyright (c) 2000-2001  Red Hat, Inc. All rights reserved.
 * Copyright (c) 2000-2001  Red Hat, Inc. All rights reserved.
 *
 *
 * This copyrighted material is made available to anyone wishing to use, modify,
 * This copyrighted material is made available to anyone wishing to use, modify,
 * copy, or redistribute it subject to the terms and conditions of the BSD
 * copy, or redistribute it subject to the terms and conditions of the BSD
 * License.  This program is distributed in the hope that it will be useful,
 * License.  This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY expressed or implied, including the implied
 * but WITHOUT ANY WARRANTY expressed or implied, including the implied
 * warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  A copy
 * warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  A copy
 * of this license is available at http://www.opensource.org/licenses. Any
 * of this license is available at http://www.opensource.org/licenses. Any
 * Red Hat trademarks that are incorporated in the source code or documentation
 * Red Hat trademarks that are incorporated in the source code or documentation
 * are not subject to the BSD License and may only be used or replicated with
 * are not subject to the BSD License and may only be used or replicated with
 * the express permission of Red Hat, Inc.
 * the express permission of Red Hat, Inc.
 */
 */
 
 
/* Structure emitted by -a  */
/* Structure emitted by -a  */
struct bb
struct bb
{
{
  long zero_word;
  long zero_word;
  const char *filename;
  const char *filename;
  long *counts;
  long *counts;
  long ncounts;
  long ncounts;
  struct bb *next;
  struct bb *next;
  const unsigned long *addresses;
  const unsigned long *addresses;
 
 
  /* Older GCC's did not emit these fields.  */
  /* Older GCC's did not emit these fields.  */
  long nwords;
  long nwords;
  const char **functions;
  const char **functions;
  const long *line_nums;
  const long *line_nums;
  const char **filenames;
  const char **filenames;
  char *flags;
  char *flags;
};
};
 
 
/* Simple minded basic block profiling output dumper for
/* Simple minded basic block profiling output dumper for
   systems that don't provide tcov support.  At present,
   systems that don't provide tcov support.  At present,
   it requires atexit and stdio.  */
   it requires atexit and stdio.  */
 
 
#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
#include <stdio.h>
#include <stdio.h>
#include <time.h>
#include <time.h>
char *ctime (const time_t *);
char *ctime (const time_t *);
 
 
/*#include "gbl-ctors.h"*/
/*#include "gbl-ctors.h"*/
#include "gcov-io.h"
#include "gcov-io.h"
#include <string.h>
#include <string.h>
 
 
static struct bb *bb_head;
static struct bb *bb_head;
 
 
static int num_digits (long value, int base) __attribute__ ((const));
static int num_digits (long value, int base) __attribute__ ((const));
 
 
/* Return the number of digits needed to print a value */
/* Return the number of digits needed to print a value */
/* __inline__ */ static int num_digits (long value, int base)
/* __inline__ */ static int num_digits (long value, int base)
{
{
  int minus = (value < 0 && base != 16);
  int minus = (value < 0 && base != 16);
  unsigned long v = (minus) ? -value : value;
  unsigned long v = (minus) ? -value : value;
  int ret = minus;
  int ret = minus;
 
 
  do
  do
    {
    {
      v /= base;
      v /= base;
      ret++;
      ret++;
    }
    }
  while (v);
  while (v);
 
 
  return ret;
  return ret;
}
}
 
 
void
void
__bb_exit_func (void)
__bb_exit_func (void)
{
{
  FILE *da_file, *file;
  FILE *da_file, *file;
  long time_value;
  long time_value;
  int i;
  int i;
 
 
  if (bb_head == 0)
  if (bb_head == 0)
    return;
    return;
 
 
  i = strlen (bb_head->filename) - 3;
  i = strlen (bb_head->filename) - 3;
 
 
  if (!strcmp (bb_head->filename+i, ".da"))
  if (!strcmp (bb_head->filename+i, ".da"))
    {
    {
      /* Must be -fprofile-arcs not -a.
      /* Must be -fprofile-arcs not -a.
         Dump data in a form that gcov expects.  */
         Dump data in a form that gcov expects.  */
 
 
      struct bb *ptr;
      struct bb *ptr;
 
 
      for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
      for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
        {
        {
          int firstchar;
          int firstchar;
 
 
          /* Make sure the output file exists -
          /* Make sure the output file exists -
             but don't clobber exiting data.  */
             but don't clobber exiting data.  */
          if ((da_file = fopen (ptr->filename, "a")) != 0)
          if ((da_file = fopen (ptr->filename, "a")) != 0)
            fclose (da_file);
            fclose (da_file);
 
 
          /* Need to re-open in order to be able to write from the start.  */
          /* Need to re-open in order to be able to write from the start.  */
          da_file = fopen (ptr->filename, "r+b");
          da_file = fopen (ptr->filename, "r+b");
          /* Some old systems might not allow the 'b' mode modifier.
          /* Some old systems might not allow the 'b' mode modifier.
             Therefore, try to open without it.  This can lead to a race
             Therefore, try to open without it.  This can lead to a race
             condition so that when you delete and re-create the file, the
             condition so that when you delete and re-create the file, the
             file might be opened in text mode, but then, you shouldn't
             file might be opened in text mode, but then, you shouldn't
             delete the file in the first place.  */
             delete the file in the first place.  */
          if (da_file == 0)
          if (da_file == 0)
            da_file = fopen (ptr->filename, "r+");
            da_file = fopen (ptr->filename, "r+");
          if (da_file == 0)
          if (da_file == 0)
            {
            {
              fprintf (stderr, "arc profiling: Can't open output file %s.\n",
              fprintf (stderr, "arc profiling: Can't open output file %s.\n",
                       ptr->filename);
                       ptr->filename);
              continue;
              continue;
            }
            }
 
 
          /* After a fork, another process might try to read and/or write
          /* After a fork, another process might try to read and/or write
             the same file simultanously.  So if we can, lock the file to
             the same file simultanously.  So if we can, lock the file to
             avoid race conditions.  */
             avoid race conditions.  */
 
 
          /* If the file is not empty, and the number of counts in it is the
          /* If the file is not empty, and the number of counts in it is the
             same, then merge them in.  */
             same, then merge them in.  */
          firstchar = fgetc (da_file);
          firstchar = fgetc (da_file);
          if (firstchar == EOF)
          if (firstchar == EOF)
            {
            {
              if (ferror (da_file))
              if (ferror (da_file))
                {
                {
                  fprintf (stderr, "arc profiling: Can't read output file ");
                  fprintf (stderr, "arc profiling: Can't read output file ");
                  perror (ptr->filename);
                  perror (ptr->filename);
                }
                }
            }
            }
          else
          else
            {
            {
              long n_counts = 0;
              long n_counts = 0;
 
 
              if (ungetc (firstchar, da_file) == EOF)
              if (ungetc (firstchar, da_file) == EOF)
                rewind (da_file);
                rewind (da_file);
              if (__read_long (&n_counts, da_file, 8) != 0)
              if (__read_long (&n_counts, da_file, 8) != 0)
                {
                {
                  fprintf (stderr, "arc profiling: Can't read output file %s.\n",
                  fprintf (stderr, "arc profiling: Can't read output file %s.\n",
                           ptr->filename);
                           ptr->filename);
                  continue;
                  continue;
                }
                }
 
 
              if (n_counts == ptr->ncounts)
              if (n_counts == ptr->ncounts)
                {
                {
                  int i;
                  int i;
 
 
                  for (i = 0; i < n_counts; i++)
                  for (i = 0; i < n_counts; i++)
                    {
                    {
                      long v = 0;
                      long v = 0;
 
 
                      if (__read_long (&v, da_file, 8) != 0)
                      if (__read_long (&v, da_file, 8) != 0)
                        {
                        {
                          fprintf (stderr, "arc profiling: Can't read output file %s.\n",
                          fprintf (stderr, "arc profiling: Can't read output file %s.\n",
                                   ptr->filename);
                                   ptr->filename);
                          break;
                          break;
                        }
                        }
                      ptr->counts[i] += v;
                      ptr->counts[i] += v;
                    }
                    }
                }
                }
 
 
            }
            }
 
 
          rewind (da_file);
          rewind (da_file);
 
 
          /* ??? Should first write a header to the file.  Preferably, a 4 byte
          /* ??? Should first write a header to the file.  Preferably, a 4 byte
             magic number, 4 bytes containing the time the program was
             magic number, 4 bytes containing the time the program was
             compiled, 4 bytes containing the last modification time of the
             compiled, 4 bytes containing the last modification time of the
             source file, and 4 bytes indicating the compiler options used.
             source file, and 4 bytes indicating the compiler options used.
 
 
             That way we can easily verify that the proper source/executable/
             That way we can easily verify that the proper source/executable/
             data file combination is being used from gcov.  */
             data file combination is being used from gcov.  */
 
 
          if (__write_long (ptr->ncounts, da_file, 8) != 0)
          if (__write_long (ptr->ncounts, da_file, 8) != 0)
            {
            {
 
 
              fprintf (stderr, "arc profiling: Error writing output file %s.\n",
              fprintf (stderr, "arc profiling: Error writing output file %s.\n",
                       ptr->filename);
                       ptr->filename);
            }
            }
          else
          else
            {
            {
              int j;
              int j;
              long *count_ptr = ptr->counts;
              long *count_ptr = ptr->counts;
              int ret = 0;
              int ret = 0;
              for (j = ptr->ncounts; j > 0; j--)
              for (j = ptr->ncounts; j > 0; j--)
                {
                {
                  if (__write_long (*count_ptr, da_file, 8) != 0)
                  if (__write_long (*count_ptr, da_file, 8) != 0)
                    {
                    {
                      ret=1;
                      ret=1;
                      break;
                      break;
                    }
                    }
                  count_ptr++;
                  count_ptr++;
                }
                }
              if (ret)
              if (ret)
                fprintf (stderr, "arc profiling: Error writing output file %s.\n",
                fprintf (stderr, "arc profiling: Error writing output file %s.\n",
                         ptr->filename);
                         ptr->filename);
            }
            }
 
 
          if (fclose (da_file) == EOF)
          if (fclose (da_file) == EOF)
            fprintf (stderr, "arc profiling: Error closing output file %s.\n",
            fprintf (stderr, "arc profiling: Error closing output file %s.\n",
                     ptr->filename);
                     ptr->filename);
        }
        }
 
 
      return;
      return;
    }
    }
 
 
  /* Must be basic block profiling.  Emit a human readable output file.  */
  /* Must be basic block profiling.  Emit a human readable output file.  */
 
 
  file = fopen ("bb.out", "a");
  file = fopen ("bb.out", "a");
 
 
  if (!file)
  if (!file)
    perror ("bb.out");
    perror ("bb.out");
 
 
  else
  else
    {
    {
      struct bb *ptr;
      struct bb *ptr;
 
 
      /* This is somewhat type incorrect, but it avoids worrying about
      /* This is somewhat type incorrect, but it avoids worrying about
         exactly where time.h is included from.  It should be ok unless
         exactly where time.h is included from.  It should be ok unless
         a void * differs from other pointer formats, or if sizeof (long)
         a void * differs from other pointer formats, or if sizeof (long)
         is < sizeof (time_t).  It would be nice if we could assume the
         is < sizeof (time_t).  It would be nice if we could assume the
         use of rationale standards here.  */
         use of rationale standards here.  */
 
 
      time ((void *) &time_value);
      time ((void *) &time_value);
      fprintf (file, "Basic block profiling finished on %s\n", ctime ((void *) &time_value));
      fprintf (file, "Basic block profiling finished on %s\n", ctime ((void *) &time_value));
 
 
      /* We check the length field explicitly in order to allow compatibility
      /* We check the length field explicitly in order to allow compatibility
         with older GCC's which did not provide it.  */
         with older GCC's which did not provide it.  */
 
 
      for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
      for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
        {
        {
          int i;
          int i;
          int func_p    = (ptr->nwords >= (long) sizeof (struct bb)
          int func_p    = (ptr->nwords >= (long) sizeof (struct bb)
                           && ptr->nwords <= 1000
                           && ptr->nwords <= 1000
                           && ptr->functions);
                           && ptr->functions);
          int line_p    = (func_p && ptr->line_nums);
          int line_p    = (func_p && ptr->line_nums);
          int file_p    = (func_p && ptr->filenames);
          int file_p    = (func_p && ptr->filenames);
          int addr_p    = (ptr->addresses != 0);
          int addr_p    = (ptr->addresses != 0);
          long ncounts  = ptr->ncounts;
          long ncounts  = ptr->ncounts;
          long cnt_max  = 0;
          long cnt_max  = 0;
          long line_max = 0;
          long line_max = 0;
          long addr_max = 0;
          long addr_max = 0;
          int file_len  = 0;
          int file_len  = 0;
          int func_len  = 0;
          int func_len  = 0;
          int blk_len   = num_digits (ncounts, 10);
          int blk_len   = num_digits (ncounts, 10);
          int cnt_len;
          int cnt_len;
          int line_len;
          int line_len;
          int addr_len;
          int addr_len;
 
 
          fprintf (file, "File %s, %ld basic blocks \n\n",
          fprintf (file, "File %s, %ld basic blocks \n\n",
                   ptr->filename, ncounts);
                   ptr->filename, ncounts);
 
 
          /* Get max values for each field.  */
          /* Get max values for each field.  */
          for (i = 0; i < ncounts; i++)
          for (i = 0; i < ncounts; i++)
            {
            {
              const char *p;
              const char *p;
              int len;
              int len;
 
 
              if (cnt_max < ptr->counts[i])
              if (cnt_max < ptr->counts[i])
                cnt_max = ptr->counts[i];
                cnt_max = ptr->counts[i];
 
 
              if (addr_p && (unsigned long) addr_max < ptr->addresses[i])
              if (addr_p && (unsigned long) addr_max < ptr->addresses[i])
                addr_max = ptr->addresses[i];
                addr_max = ptr->addresses[i];
 
 
              if (line_p && line_max < ptr->line_nums[i])
              if (line_p && line_max < ptr->line_nums[i])
                line_max = ptr->line_nums[i];
                line_max = ptr->line_nums[i];
 
 
              if (func_p)
              if (func_p)
                {
                {
                  p = (ptr->functions[i]) ? (ptr->functions[i]) : "<none>";
                  p = (ptr->functions[i]) ? (ptr->functions[i]) : "<none>";
                  len = strlen (p);
                  len = strlen (p);
                  if (func_len < len)
                  if (func_len < len)
                    func_len = len;
                    func_len = len;
                }
                }
 
 
              if (file_p)
              if (file_p)
                {
                {
                  p = (ptr->filenames[i]) ? (ptr->filenames[i]) : "<none>";
                  p = (ptr->filenames[i]) ? (ptr->filenames[i]) : "<none>";
                  len = strlen (p);
                  len = strlen (p);
                  if (file_len < len)
                  if (file_len < len)
                    file_len = len;
                    file_len = len;
                }
                }
            }
            }
 
 
          addr_len = num_digits (addr_max, 16);
          addr_len = num_digits (addr_max, 16);
          cnt_len  = num_digits (cnt_max, 10);
          cnt_len  = num_digits (cnt_max, 10);
          line_len = num_digits (line_max, 10);
          line_len = num_digits (line_max, 10);
 
 
          /* Now print out the basic block information.  */
          /* Now print out the basic block information.  */
          for (i = 0; i < ncounts; i++)
          for (i = 0; i < ncounts; i++)
            {
            {
              fprintf (file,
              fprintf (file,
                       "    Block #%*d: executed %*ld time(s)",
                       "    Block #%*d: executed %*ld time(s)",
                       blk_len, i+1,
                       blk_len, i+1,
                       cnt_len, ptr->counts[i]);
                       cnt_len, ptr->counts[i]);
 
 
              if (addr_p)
              if (addr_p)
                fprintf (file, " address= 0x%.*lx", addr_len,
                fprintf (file, " address= 0x%.*lx", addr_len,
                         ptr->addresses[i]);
                         ptr->addresses[i]);
 
 
              if (func_p)
              if (func_p)
                fprintf (file, " function= %-*s", func_len,
                fprintf (file, " function= %-*s", func_len,
                         (ptr->functions[i]) ? ptr->functions[i] : "<none>");
                         (ptr->functions[i]) ? ptr->functions[i] : "<none>");
 
 
              if (line_p)
              if (line_p)
                fprintf (file, " line= %*ld", line_len, ptr->line_nums[i]);
                fprintf (file, " line= %*ld", line_len, ptr->line_nums[i]);
 
 
              if (file_p)
              if (file_p)
                fprintf (file, " file= %s",
                fprintf (file, " file= %s",
                         (ptr->filenames[i]) ? ptr->filenames[i] : "<none>");
                         (ptr->filenames[i]) ? ptr->filenames[i] : "<none>");
 
 
              fprintf (file, "\n");
              fprintf (file, "\n");
            }
            }
 
 
          fprintf (file, "\n");
          fprintf (file, "\n");
          fflush (file);
          fflush (file);
        }
        }
 
 
      fprintf (file, "\n\n");
      fprintf (file, "\n\n");
      fclose (file);
      fclose (file);
    }
    }
}
}
 
 
void
void
__bb_init_func (struct bb *blocks)
__bb_init_func (struct bb *blocks)
{
{
  /* User is supposed to check whether the first word is non-0,
  /* User is supposed to check whether the first word is non-0,
     but just in case....  */
     but just in case....  */
 
 
  if (blocks->zero_word)
  if (blocks->zero_word)
    return;
    return;
 
 
  /* Initialize destructor.  */
  /* Initialize destructor.  */
  if (!bb_head)
  if (!bb_head)
    atexit (__bb_exit_func);
    atexit (__bb_exit_func);
 
 
  /* Set up linked list.  */
  /* Set up linked list.  */
  blocks->zero_word = 1;
  blocks->zero_word = 1;
  blocks->next = bb_head;
  blocks->next = bb_head;
  bb_head = blocks;
  bb_head = blocks;
}
}
 
 
/* Called before fork or exec - write out profile information gathered so
/* Called before fork or exec - write out profile information gathered so
   far and reset it to zero.  This avoids duplication or loss of the
   far and reset it to zero.  This avoids duplication or loss of the
   profile information gathered so far.  */
   profile information gathered so far.  */
void
void
__bb_fork_func (void)
__bb_fork_func (void)
{
{
  struct bb *ptr;
  struct bb *ptr;
 
 
  __bb_exit_func ();
  __bb_exit_func ();
  for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
  for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
    {
    {
      long i;
      long i;
      for (i = ptr->ncounts - 1; i >= 0; i--)
      for (i = ptr->ncounts - 1; i >= 0; i--)
        ptr->counts[i] = 0;
        ptr->counts[i] = 0;
    }
    }
}
}
 
 
#ifndef MACHINE_STATE_SAVE
#ifndef MACHINE_STATE_SAVE
#define MACHINE_STATE_SAVE(ID)
#define MACHINE_STATE_SAVE(ID)
#endif
#endif
#ifndef MACHINE_STATE_RESTORE
#ifndef MACHINE_STATE_RESTORE
#define MACHINE_STATE_RESTORE(ID)
#define MACHINE_STATE_RESTORE(ID)
#endif
#endif
 
 
/* Number of buckets in hashtable of basic block addresses.  */
/* Number of buckets in hashtable of basic block addresses.  */
 
 
#define BB_BUCKETS 311
#define BB_BUCKETS 311
 
 
/* Maximum length of string in file bb.in.  */
/* Maximum length of string in file bb.in.  */
 
 
#define BBINBUFSIZE 500
#define BBINBUFSIZE 500
 
 
struct bb_edge
struct bb_edge
{
{
  struct bb_edge *next;
  struct bb_edge *next;
  unsigned long src_addr;
  unsigned long src_addr;
  unsigned long dst_addr;
  unsigned long dst_addr;
  unsigned long count;
  unsigned long count;
};
};
 
 
enum bb_func_mode
enum bb_func_mode
{
{
  TRACE_KEEP = 0, TRACE_ON = 1, TRACE_OFF = 2
  TRACE_KEEP = 0, TRACE_ON = 1, TRACE_OFF = 2
};
};
 
 
struct bb_func
struct bb_func
{
{
  struct bb_func *next;
  struct bb_func *next;
  char *funcname;
  char *funcname;
  char *filename;
  char *filename;
  enum bb_func_mode mode;
  enum bb_func_mode mode;
};
};
 
 
/* This is the connection to the outside world.
/* This is the connection to the outside world.
   The BLOCK_PROFILER macro must set __bb.blocks
   The BLOCK_PROFILER macro must set __bb.blocks
   and __bb.blockno.  */
   and __bb.blockno.  */
 
 
struct {
struct {
  unsigned long blockno;
  unsigned long blockno;
  struct bb *blocks;
  struct bb *blocks;
} __bb;
} __bb;
 
 
/* Vars to store addrs of source and destination basic blocks
/* Vars to store addrs of source and destination basic blocks
   of a jump.  */
   of a jump.  */
 
 
static unsigned long bb_src = 0;
static unsigned long bb_src = 0;
static unsigned long bb_dst = 0;
static unsigned long bb_dst = 0;
 
 
static FILE *bb_tracefile = (FILE *) 0;
static FILE *bb_tracefile = (FILE *) 0;
static struct bb_edge **bb_hashbuckets = (struct bb_edge **) 0;
static struct bb_edge **bb_hashbuckets = (struct bb_edge **) 0;
static struct bb_func *bb_func_head = (struct bb_func *) 0;
static struct bb_func *bb_func_head = (struct bb_func *) 0;
static unsigned long bb_callcount = 0;
static unsigned long bb_callcount = 0;
static int bb_mode = 0;
static int bb_mode = 0;
 
 
static unsigned long *bb_stack = (unsigned long *) 0;
static unsigned long *bb_stack = (unsigned long *) 0;
static size_t bb_stacksize = 0;
static size_t bb_stacksize = 0;
 
 
static int reported = 0;
static int reported = 0;
 
 
/* Trace modes:
/* Trace modes:
Always             :   Print execution frequencies of basic blocks
Always             :   Print execution frequencies of basic blocks
                       to file bb.out.
                       to file bb.out.
bb_mode & 1 != 0   :   Dump trace of basic blocks to file bbtrace[.gz]
bb_mode & 1 != 0   :   Dump trace of basic blocks to file bbtrace[.gz]
bb_mode & 2 != 0   :   Print jump frequencies to file bb.out.
bb_mode & 2 != 0   :   Print jump frequencies to file bb.out.
bb_mode & 4 != 0   :   Cut call instructions from basic block flow.
bb_mode & 4 != 0   :   Cut call instructions from basic block flow.
bb_mode & 8 != 0   :   Insert return instructions in basic block flow.
bb_mode & 8 != 0   :   Insert return instructions in basic block flow.
*/
*/
 
 
#ifdef HAVE_POPEN
#ifdef HAVE_POPEN
 
 
/*#include <sys/types.h>*/
/*#include <sys/types.h>*/
#include <sys/stat.h>
#include <sys/stat.h>
/*#include <malloc.h>*/
/*#include <malloc.h>*/
 
 
/* Commands executed by gopen.  */
/* Commands executed by gopen.  */
 
 
#define GOPENDECOMPRESS "gzip -cd "
#define GOPENDECOMPRESS "gzip -cd "
#define GOPENCOMPRESS "gzip -c >"
#define GOPENCOMPRESS "gzip -c >"
 
 
/* Like fopen but pipes through gzip.  mode may only be "r" or "w".
/* Like fopen but pipes through gzip.  mode may only be "r" or "w".
   If it does not compile, simply replace gopen by fopen and delete
   If it does not compile, simply replace gopen by fopen and delete
   '.gz' from any first parameter to gopen.  */
   '.gz' from any first parameter to gopen.  */
 
 
static FILE *
static FILE *
gopen (char *fn, char *mode)
gopen (char *fn, char *mode)
{
{
  int use_gzip;
  int use_gzip;
  char *p;
  char *p;
 
 
  if (mode[1])
  if (mode[1])
    return (FILE *) 0;
    return (FILE *) 0;
 
 
  if (mode[0] != 'r' && mode[0] != 'w')
  if (mode[0] != 'r' && mode[0] != 'w')
    return (FILE *) 0;
    return (FILE *) 0;
 
 
  p = fn + strlen (fn)-1;
  p = fn + strlen (fn)-1;
  use_gzip = ((p[-1] == '.' && (p[0] == 'Z' || p[0] == 'z'))
  use_gzip = ((p[-1] == '.' && (p[0] == 'Z' || p[0] == 'z'))
              || (p[-2] == '.' && p[-1] == 'g' && p[0] == 'z'));
              || (p[-2] == '.' && p[-1] == 'g' && p[0] == 'z'));
 
 
  if (use_gzip)
  if (use_gzip)
    {
    {
      if (mode[0]=='r')
      if (mode[0]=='r')
        {
        {
          FILE *f;
          FILE *f;
          char *s = (char *) malloc (sizeof (char) * strlen (fn)
          char *s = (char *) malloc (sizeof (char) * strlen (fn)
                                     + sizeof (GOPENDECOMPRESS));
                                     + sizeof (GOPENDECOMPRESS));
          strcpy (s, GOPENDECOMPRESS);
          strcpy (s, GOPENDECOMPRESS);
          strcpy (s + (sizeof (GOPENDECOMPRESS)-1), fn);
          strcpy (s + (sizeof (GOPENDECOMPRESS)-1), fn);
          f = popen (s, mode);
          f = popen (s, mode);
          free (s);
          free (s);
          return f;
          return f;
        }
        }
 
 
      else
      else
        {
        {
          FILE *f;
          FILE *f;
          char *s = (char *) malloc (sizeof (char) * strlen (fn)
          char *s = (char *) malloc (sizeof (char) * strlen (fn)
                                     + sizeof (GOPENCOMPRESS));
                                     + sizeof (GOPENCOMPRESS));
          strcpy (s, GOPENCOMPRESS);
          strcpy (s, GOPENCOMPRESS);
          strcpy (s + (sizeof (GOPENCOMPRESS)-1), fn);
          strcpy (s + (sizeof (GOPENCOMPRESS)-1), fn);
          if (!(f = popen (s, mode)))
          if (!(f = popen (s, mode)))
            f = fopen (s, mode);
            f = fopen (s, mode);
          free (s);
          free (s);
          return f;
          return f;
        }
        }
    }
    }
 
 
  else
  else
    return fopen (fn, mode);
    return fopen (fn, mode);
}
}
 
 
static int
static int
gclose (FILE *f)
gclose (FILE *f)
{
{
  struct stat buf;
  struct stat buf;
 
 
  if (f != 0)
  if (f != 0)
    {
    {
      if (!fstat (fileno (f), &buf) && S_ISFIFO (buf.st_mode))
      if (!fstat (fileno (f), &buf) && S_ISFIFO (buf.st_mode))
        return pclose (f);
        return pclose (f);
 
 
      return fclose (f);
      return fclose (f);
    }
    }
  return 0;
  return 0;
}
}
 
 
#endif /* HAVE_POPEN */
#endif /* HAVE_POPEN */
 
 
/* Called once per program.  */
/* Called once per program.  */
 
 
static void
static void
__bb_exit_trace_func (void)
__bb_exit_trace_func (void)
{
{
  FILE *file = fopen ("bb.out", "a");
  FILE *file = fopen ("bb.out", "a");
  struct bb_func *f;
  struct bb_func *f;
  struct bb *b;
  struct bb *b;
 
 
  if (!file)
  if (!file)
    perror ("bb.out");
    perror ("bb.out");
 
 
  if (bb_mode & 1)
  if (bb_mode & 1)
    {
    {
      if (!bb_tracefile)
      if (!bb_tracefile)
        perror ("bbtrace");
        perror ("bbtrace");
      else
      else
#ifdef HAVE_POPEN
#ifdef HAVE_POPEN
        gclose (bb_tracefile);
        gclose (bb_tracefile);
#else
#else
        fclose (bb_tracefile);
        fclose (bb_tracefile);
#endif /* HAVE_POPEN */
#endif /* HAVE_POPEN */
    }
    }
 
 
  /* Check functions in `bb.in'.  */
  /* Check functions in `bb.in'.  */
 
 
  if (file)
  if (file)
    {
    {
      long time_value;
      long time_value;
      const struct bb_func *p;
      const struct bb_func *p;
      int printed_something = 0;
      int printed_something = 0;
      struct bb *ptr;
      struct bb *ptr;
      long blk;
      long blk;
 
 
      /* This is somewhat type incorrect.  */
      /* This is somewhat type incorrect.  */
      time ((void *) &time_value);
      time ((void *) &time_value);
 
 
      for (p = bb_func_head; p != (struct bb_func *) 0; p = p->next)
      for (p = bb_func_head; p != (struct bb_func *) 0; p = p->next)
        {
        {
          for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
          for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
            {
            {
              if (!ptr->filename || (p->filename != (char *) 0 && strcmp (p->filename, ptr->filename)))
              if (!ptr->filename || (p->filename != (char *) 0 && strcmp (p->filename, ptr->filename)))
                continue;
                continue;
              for (blk = 0; blk < ptr->ncounts; blk++)
              for (blk = 0; blk < ptr->ncounts; blk++)
                {
                {
                  if (!strcmp (p->funcname, ptr->functions[blk]))
                  if (!strcmp (p->funcname, ptr->functions[blk]))
                    goto found;
                    goto found;
                }
                }
            }
            }
 
 
          if (!printed_something)
          if (!printed_something)
            {
            {
              fprintf (file, "Functions in `bb.in' not executed during basic block profiling on %s\n", ctime ((void *) &time_value));
              fprintf (file, "Functions in `bb.in' not executed during basic block profiling on %s\n", ctime ((void *) &time_value));
              printed_something = 1;
              printed_something = 1;
            }
            }
 
 
          fprintf (file, "\tFunction %s", p->funcname);
          fprintf (file, "\tFunction %s", p->funcname);
          if (p->filename)
          if (p->filename)
              fprintf (file, " of file %s", p->filename);
              fprintf (file, " of file %s", p->filename);
          fprintf (file, "\n" );
          fprintf (file, "\n" );
 
 
found:        ;
found:        ;
        }
        }
 
 
      if (printed_something)
      if (printed_something)
       fprintf (file, "\n");
       fprintf (file, "\n");
 
 
    }
    }
 
 
  if (bb_mode & 2)
  if (bb_mode & 2)
    {
    {
      if (!bb_hashbuckets)
      if (!bb_hashbuckets)
        {
        {
          if (!reported)
          if (!reported)
            {
            {
              fprintf (stderr, "Profiler: out of memory\n");
              fprintf (stderr, "Profiler: out of memory\n");
              reported = 1;
              reported = 1;
            }
            }
          return;
          return;
        }
        }
 
 
      else if (file)
      else if (file)
        {
        {
          long time_value;
          long time_value;
          int i;
          int i;
          unsigned long addr_max = 0;
          unsigned long addr_max = 0;
          unsigned long cnt_max  = 0;
          unsigned long cnt_max  = 0;
          int cnt_len;
          int cnt_len;
          int addr_len;
          int addr_len;
 
 
          /* This is somewhat type incorrect, but it avoids worrying about
          /* This is somewhat type incorrect, but it avoids worrying about
             exactly where time.h is included from.  It should be ok unless
             exactly where time.h is included from.  It should be ok unless
             a void * differs from other pointer formats, or if sizeof (long)
             a void * differs from other pointer formats, or if sizeof (long)
             is < sizeof (time_t).  It would be nice if we could assume the
             is < sizeof (time_t).  It would be nice if we could assume the
             use of rationale standards here.  */
             use of rationale standards here.  */
 
 
          time ((void *) &time_value);
          time ((void *) &time_value);
          fprintf (file, "Basic block jump tracing");
          fprintf (file, "Basic block jump tracing");
 
 
          switch (bb_mode & 12)
          switch (bb_mode & 12)
            {
            {
              case 0:
              case 0:
                fprintf (file, " (with call)");
                fprintf (file, " (with call)");
              break;
              break;
 
 
              case 4:
              case 4:
                /* Print nothing.  */
                /* Print nothing.  */
              break;
              break;
 
 
              case 8:
              case 8:
                fprintf (file, " (with call & ret)");
                fprintf (file, " (with call & ret)");
              break;
              break;
 
 
              case 12:
              case 12:
                fprintf (file, " (with ret)");
                fprintf (file, " (with ret)");
              break;
              break;
            }
            }
 
 
          fprintf (file, " finished on %s\n", ctime ((void *) &time_value));
          fprintf (file, " finished on %s\n", ctime ((void *) &time_value));
 
 
          for (i = 0; i < BB_BUCKETS; i++)
          for (i = 0; i < BB_BUCKETS; i++)
            {
            {
               struct bb_edge *bucket = bb_hashbuckets[i];
               struct bb_edge *bucket = bb_hashbuckets[i];
               for ( ; bucket; bucket = bucket->next )
               for ( ; bucket; bucket = bucket->next )
                 {
                 {
                   if (addr_max < bucket->src_addr)
                   if (addr_max < bucket->src_addr)
                     addr_max = bucket->src_addr;
                     addr_max = bucket->src_addr;
                   if (addr_max < bucket->dst_addr)
                   if (addr_max < bucket->dst_addr)
                     addr_max = bucket->dst_addr;
                     addr_max = bucket->dst_addr;
                   if (cnt_max < bucket->count)
                   if (cnt_max < bucket->count)
                     cnt_max = bucket->count;
                     cnt_max = bucket->count;
                 }
                 }
            }
            }
          addr_len = num_digits (addr_max, 16);
          addr_len = num_digits (addr_max, 16);
          cnt_len  = num_digits (cnt_max, 10);
          cnt_len  = num_digits (cnt_max, 10);
 
 
          for ( i = 0; i < BB_BUCKETS; i++)
          for ( i = 0; i < BB_BUCKETS; i++)
            {
            {
               struct bb_edge *bucket = bb_hashbuckets[i];
               struct bb_edge *bucket = bb_hashbuckets[i];
               for ( ; bucket; bucket = bucket->next )
               for ( ; bucket; bucket = bucket->next )
                 {
                 {
                   fprintf (file,
                   fprintf (file,
        "Jump from block 0x%.*lx to block 0x%.*lx executed %*lu time(s)\n",
        "Jump from block 0x%.*lx to block 0x%.*lx executed %*lu time(s)\n",
                            addr_len, bucket->src_addr,
                            addr_len, bucket->src_addr,
                            addr_len, bucket->dst_addr,
                            addr_len, bucket->dst_addr,
                            cnt_len, bucket->count);
                            cnt_len, bucket->count);
                 }
                 }
            }
            }
 
 
          fprintf (file, "\n");
          fprintf (file, "\n");
 
 
        }
        }
    }
    }
 
 
   if (file)
   if (file)
     fclose (file);
     fclose (file);
 
 
   /* Free allocated memory.  */
   /* Free allocated memory.  */
 
 
   f = bb_func_head;
   f = bb_func_head;
   while (f)
   while (f)
     {
     {
       struct bb_func *old = f;
       struct bb_func *old = f;
 
 
       f = f->next;
       f = f->next;
       if (old->funcname) free (old->funcname);
       if (old->funcname) free (old->funcname);
       if (old->filename) free (old->filename);
       if (old->filename) free (old->filename);
       free (old);
       free (old);
     }
     }
 
 
   if (bb_stack)
   if (bb_stack)
     free (bb_stack);
     free (bb_stack);
 
 
   if (bb_hashbuckets)
   if (bb_hashbuckets)
     {
     {
       int i;
       int i;
 
 
       for (i = 0; i < BB_BUCKETS; i++)
       for (i = 0; i < BB_BUCKETS; i++)
         {
         {
           struct bb_edge *old, *bucket = bb_hashbuckets[i];
           struct bb_edge *old, *bucket = bb_hashbuckets[i];
 
 
           while (bucket)
           while (bucket)
             {
             {
               old = bucket;
               old = bucket;
               bucket = bucket->next;
               bucket = bucket->next;
               free (old);
               free (old);
             }
             }
         }
         }
       free (bb_hashbuckets);
       free (bb_hashbuckets);
     }
     }
 
 
   for (b = bb_head; b; b = b->next)
   for (b = bb_head; b; b = b->next)
     if (b->flags) free (b->flags);
     if (b->flags) free (b->flags);
}
}
 
 
/* Called once per program.  */
/* Called once per program.  */
 
 
static void
static void
__bb_init_prg (void)
__bb_init_prg (void)
{
{
  FILE *file;
  FILE *file;
  char buf[BBINBUFSIZE];
  char buf[BBINBUFSIZE];
  const char *p;
  const char *p;
  const char *pos;
  const char *pos;
  enum bb_func_mode m;
  enum bb_func_mode m;
  int i;
  int i;
 
 
  /* Initialize destructor.  */
  /* Initialize destructor.  */
  atexit (__bb_exit_func);
  atexit (__bb_exit_func);
 
 
  if (!(file = fopen ("bb.in", "r")))
  if (!(file = fopen ("bb.in", "r")))
    return;
    return;
 
 
  while(fgets (buf, BBINBUFSIZE, file) != 0)
  while(fgets (buf, BBINBUFSIZE, file) != 0)
    {
    {
      i = strlen (buf);
      i = strlen (buf);
      if (buf[i-1] == '\n')
      if (buf[i-1] == '\n')
        buf[--i] = '\0';
        buf[--i] = '\0';
 
 
      p = buf;
      p = buf;
      if (*p == '-')
      if (*p == '-')
        {
        {
          m = TRACE_OFF;
          m = TRACE_OFF;
          p++;
          p++;
        }
        }
      else
      else
        {
        {
          m = TRACE_ON;
          m = TRACE_ON;
        }
        }
      if (!strcmp (p, "__bb_trace__"))
      if (!strcmp (p, "__bb_trace__"))
        bb_mode |= 1;
        bb_mode |= 1;
      else if (!strcmp (p, "__bb_jumps__"))
      else if (!strcmp (p, "__bb_jumps__"))
        bb_mode |= 2;
        bb_mode |= 2;
      else if (!strcmp (p, "__bb_hidecall__"))
      else if (!strcmp (p, "__bb_hidecall__"))
        bb_mode |= 4;
        bb_mode |= 4;
      else if (!strcmp (p, "__bb_showret__"))
      else if (!strcmp (p, "__bb_showret__"))
        bb_mode |= 8;
        bb_mode |= 8;
      else
      else
        {
        {
          struct bb_func *f = (struct bb_func *) malloc (sizeof (struct bb_func));
          struct bb_func *f = (struct bb_func *) malloc (sizeof (struct bb_func));
          if (f)
          if (f)
            {
            {
              unsigned long l;
              unsigned long l;
              f->next = bb_func_head;
              f->next = bb_func_head;
              if ((pos = strchr (p, ':')))
              if ((pos = strchr (p, ':')))
                {
                {
                  if (!(f->funcname = (char *) malloc (strlen (pos+1)+1)))
                  if (!(f->funcname = (char *) malloc (strlen (pos+1)+1)))
                    continue;
                    continue;
                  strcpy (f->funcname, pos+1);
                  strcpy (f->funcname, pos+1);
                  l = pos-p;
                  l = pos-p;
                  if ((f->filename = (char *) malloc (l+1)))
                  if ((f->filename = (char *) malloc (l+1)))
                    {
                    {
                      strncpy (f->filename, p, l);
                      strncpy (f->filename, p, l);
                      f->filename[l] = '\0';
                      f->filename[l] = '\0';
                    }
                    }
                  else
                  else
                    f->filename = (char *) 0;
                    f->filename = (char *) 0;
                }
                }
              else
              else
                {
                {
                  if (!(f->funcname = (char *) malloc (strlen (p)+1)))
                  if (!(f->funcname = (char *) malloc (strlen (p)+1)))
                    continue;
                    continue;
                  strcpy (f->funcname, p);
                  strcpy (f->funcname, p);
                  f->filename = (char *) 0;
                  f->filename = (char *) 0;
                }
                }
              f->mode = m;
              f->mode = m;
              bb_func_head = f;
              bb_func_head = f;
            }
            }
         }
         }
    }
    }
  fclose (file);
  fclose (file);
 
 
#ifdef HAVE_POPEN 
#ifdef HAVE_POPEN 
 
 
  if (bb_mode & 1)
  if (bb_mode & 1)
      bb_tracefile = gopen ("bbtrace.gz", "w");
      bb_tracefile = gopen ("bbtrace.gz", "w");
 
 
#else
#else
 
 
  if (bb_mode & 1)
  if (bb_mode & 1)
      bb_tracefile = fopen ("bbtrace", "w");
      bb_tracefile = fopen ("bbtrace", "w");
 
 
#endif /* HAVE_POPEN */
#endif /* HAVE_POPEN */
 
 
  if (bb_mode & 2)
  if (bb_mode & 2)
    {
    {
      bb_hashbuckets = (struct bb_edge **)
      bb_hashbuckets = (struct bb_edge **)
                   malloc (BB_BUCKETS * sizeof (struct bb_edge *));
                   malloc (BB_BUCKETS * sizeof (struct bb_edge *));
      if (bb_hashbuckets)
      if (bb_hashbuckets)
        /* Use a loop here rather than calling bzero to avoid having to
        /* Use a loop here rather than calling bzero to avoid having to
           conditionalize its existance.  */
           conditionalize its existance.  */
        for (i = 0; i < BB_BUCKETS; i++)
        for (i = 0; i < BB_BUCKETS; i++)
          bb_hashbuckets[i] = 0;
          bb_hashbuckets[i] = 0;
    }
    }
 
 
  if (bb_mode & 12)
  if (bb_mode & 12)
    {
    {
      bb_stacksize = 10;
      bb_stacksize = 10;
      bb_stack = (unsigned long *) malloc (bb_stacksize * sizeof (*bb_stack));
      bb_stack = (unsigned long *) malloc (bb_stacksize * sizeof (*bb_stack));
    }
    }
 
 
  /* Initialize destructor.  */
  /* Initialize destructor.  */
  atexit (__bb_exit_trace_func);
  atexit (__bb_exit_trace_func);
}
}
 
 
/* Called upon entering a basic block.  */
/* Called upon entering a basic block.  */
 
 
void
void
__bb_trace_func (void)
__bb_trace_func (void)
{
{
  struct bb_edge *bucket;
  struct bb_edge *bucket;
 
 
  MACHINE_STATE_SAVE("1")
  MACHINE_STATE_SAVE("1")
 
 
  if (!bb_callcount || (__bb.blocks->flags && (__bb.blocks->flags[__bb.blockno] & TRACE_OFF)))
  if (!bb_callcount || (__bb.blocks->flags && (__bb.blocks->flags[__bb.blockno] & TRACE_OFF)))
    goto skip;
    goto skip;
 
 
  bb_dst = __bb.blocks->addresses[__bb.blockno];
  bb_dst = __bb.blocks->addresses[__bb.blockno];
  __bb.blocks->counts[__bb.blockno]++;
  __bb.blocks->counts[__bb.blockno]++;
 
 
  if (bb_tracefile)
  if (bb_tracefile)
    {
    {
      fwrite (&bb_dst, sizeof (unsigned long), 1, bb_tracefile);
      fwrite (&bb_dst, sizeof (unsigned long), 1, bb_tracefile);
    }
    }
 
 
  if (bb_hashbuckets)
  if (bb_hashbuckets)
    {
    {
      struct bb_edge **startbucket, **oldnext;
      struct bb_edge **startbucket, **oldnext;
 
 
      oldnext = startbucket
      oldnext = startbucket
        = & bb_hashbuckets[ (((int) bb_src*8) ^ (int) bb_dst) % BB_BUCKETS ];
        = & bb_hashbuckets[ (((int) bb_src*8) ^ (int) bb_dst) % BB_BUCKETS ];
      bucket = *startbucket;
      bucket = *startbucket;
 
 
      for (bucket = *startbucket; bucket;
      for (bucket = *startbucket; bucket;
           oldnext = &(bucket->next), bucket = *oldnext)
           oldnext = &(bucket->next), bucket = *oldnext)
        {
        {
          if (bucket->src_addr == bb_src
          if (bucket->src_addr == bb_src
              && bucket->dst_addr == bb_dst)
              && bucket->dst_addr == bb_dst)
            {
            {
              bucket->count++;
              bucket->count++;
              *oldnext = bucket->next;
              *oldnext = bucket->next;
              bucket->next = *startbucket;
              bucket->next = *startbucket;
              *startbucket = bucket;
              *startbucket = bucket;
              goto ret;
              goto ret;
            }
            }
        }
        }
 
 
      bucket = (struct bb_edge *) malloc (sizeof (struct bb_edge));
      bucket = (struct bb_edge *) malloc (sizeof (struct bb_edge));
 
 
      if (!bucket)
      if (!bucket)
        {
        {
          if (!reported)
          if (!reported)
            {
            {
              fprintf (stderr, "Profiler: out of memory\n");
              fprintf (stderr, "Profiler: out of memory\n");
              reported = 1;
              reported = 1;
            }
            }
        }
        }
 
 
      else
      else
        {
        {
          bucket->src_addr = bb_src;
          bucket->src_addr = bb_src;
          bucket->dst_addr = bb_dst;
          bucket->dst_addr = bb_dst;
          bucket->next = *startbucket;
          bucket->next = *startbucket;
          *startbucket = bucket;
          *startbucket = bucket;
          bucket->count = 1;
          bucket->count = 1;
        }
        }
    }
    }
 
 
ret:
ret:
  bb_src = bb_dst;
  bb_src = bb_dst;
 
 
skip:
skip:
  ;
  ;
 
 
  MACHINE_STATE_RESTORE("1")
  MACHINE_STATE_RESTORE("1")
 
 
}
}
 
 
/* Called when returning from a function and `__bb_showret__' is set.  */
/* Called when returning from a function and `__bb_showret__' is set.  */
 
 
static void
static void
__bb_trace_func_ret (void)
__bb_trace_func_ret (void)
{
{
  struct bb_edge *bucket;
  struct bb_edge *bucket;
 
 
  if (!bb_callcount || (__bb.blocks->flags && (__bb.blocks->flags[__bb.blockno] & TRACE_OFF)))
  if (!bb_callcount || (__bb.blocks->flags && (__bb.blocks->flags[__bb.blockno] & TRACE_OFF)))
    goto skip;
    goto skip;
 
 
  if (bb_hashbuckets)
  if (bb_hashbuckets)
    {
    {
      struct bb_edge **startbucket, **oldnext;
      struct bb_edge **startbucket, **oldnext;
 
 
      oldnext = startbucket
      oldnext = startbucket
        = & bb_hashbuckets[ (((int) bb_dst * 8) ^ (int) bb_src) % BB_BUCKETS ];
        = & bb_hashbuckets[ (((int) bb_dst * 8) ^ (int) bb_src) % BB_BUCKETS ];
      bucket = *startbucket;
      bucket = *startbucket;
 
 
      for (bucket = *startbucket; bucket;
      for (bucket = *startbucket; bucket;
           oldnext = &(bucket->next), bucket = *oldnext)
           oldnext = &(bucket->next), bucket = *oldnext)
        {
        {
          if (bucket->src_addr == bb_dst
          if (bucket->src_addr == bb_dst
               && bucket->dst_addr == bb_src)
               && bucket->dst_addr == bb_src)
            {
            {
              bucket->count++;
              bucket->count++;
              *oldnext = bucket->next;
              *oldnext = bucket->next;
              bucket->next = *startbucket;
              bucket->next = *startbucket;
              *startbucket = bucket;
              *startbucket = bucket;
              goto ret;
              goto ret;
            }
            }
        }
        }
 
 
      bucket = (struct bb_edge *) malloc (sizeof (struct bb_edge));
      bucket = (struct bb_edge *) malloc (sizeof (struct bb_edge));
 
 
      if (!bucket)
      if (!bucket)
        {
        {
          if (!reported)
          if (!reported)
            {
            {
              fprintf (stderr, "Profiler: out of memory\n");
              fprintf (stderr, "Profiler: out of memory\n");
              reported = 1;
              reported = 1;
            }
            }
        }
        }
 
 
      else
      else
        {
        {
          bucket->src_addr = bb_dst;
          bucket->src_addr = bb_dst;
          bucket->dst_addr = bb_src;
          bucket->dst_addr = bb_src;
          bucket->next = *startbucket;
          bucket->next = *startbucket;
          *startbucket = bucket;
          *startbucket = bucket;
          bucket->count = 1;
          bucket->count = 1;
        }
        }
    }
    }
 
 
ret:
ret:
  bb_dst = bb_src;
  bb_dst = bb_src;
 
 
skip:
skip:
  ;
  ;
 
 
}
}
 
 
/* Called upon entering the first function of a file.  */
/* Called upon entering the first function of a file.  */
 
 
static void
static void
__bb_init_file (struct bb *blocks)
__bb_init_file (struct bb *blocks)
{
{
 
 
  const struct bb_func *p;
  const struct bb_func *p;
  long blk, ncounts = blocks->ncounts;
  long blk, ncounts = blocks->ncounts;
  const char **functions = blocks->functions;
  const char **functions = blocks->functions;
 
 
  /* Set up linked list.  */
  /* Set up linked list.  */
  blocks->zero_word = 1;
  blocks->zero_word = 1;
  blocks->next = bb_head;
  blocks->next = bb_head;
  bb_head = blocks;
  bb_head = blocks;
 
 
  blocks->flags = 0;
  blocks->flags = 0;
  if (!bb_func_head
  if (!bb_func_head
      || !(blocks->flags = (char *) malloc (sizeof (char) * blocks->ncounts)))
      || !(blocks->flags = (char *) malloc (sizeof (char) * blocks->ncounts)))
    return;
    return;
 
 
  for (blk = 0; blk < ncounts; blk++)
  for (blk = 0; blk < ncounts; blk++)
    blocks->flags[blk] = 0;
    blocks->flags[blk] = 0;
 
 
  for (blk = 0; blk < ncounts; blk++)
  for (blk = 0; blk < ncounts; blk++)
    {
    {
      for (p = bb_func_head; p; p = p->next)
      for (p = bb_func_head; p; p = p->next)
        {
        {
          if (!strcmp (p->funcname, functions[blk])
          if (!strcmp (p->funcname, functions[blk])
              && (!p->filename || !strcmp (p->filename, blocks->filename)))
              && (!p->filename || !strcmp (p->filename, blocks->filename)))
            {
            {
              blocks->flags[blk] |= p->mode;
              blocks->flags[blk] |= p->mode;
            }
            }
        }
        }
    }
    }
 
 
}
}
 
 
/* Called when exiting from a function.  */
/* Called when exiting from a function.  */
 
 
void
void
__bb_trace_ret (void)
__bb_trace_ret (void)
{
{
 
 
  MACHINE_STATE_SAVE("2")
  MACHINE_STATE_SAVE("2")
 
 
  if (bb_callcount)
  if (bb_callcount)
    {
    {
      if ((bb_mode & 12) && bb_stacksize > bb_callcount)
      if ((bb_mode & 12) && bb_stacksize > bb_callcount)
        {
        {
          bb_src = bb_stack[bb_callcount];
          bb_src = bb_stack[bb_callcount];
          if (bb_mode & 8)
          if (bb_mode & 8)
            __bb_trace_func_ret ();
            __bb_trace_func_ret ();
        }
        }
 
 
      bb_callcount -= 1;
      bb_callcount -= 1;
    }
    }
 
 
  MACHINE_STATE_RESTORE("2")
  MACHINE_STATE_RESTORE("2")
 
 
}
}
 
 
/* Called when entering a function.  */
/* Called when entering a function.  */
 
 
void
void
__bb_init_trace_func (struct bb *blocks, unsigned long blockno)
__bb_init_trace_func (struct bb *blocks, unsigned long blockno)
{
{
  static int trace_init = 0;
  static int trace_init = 0;
 
 
  MACHINE_STATE_SAVE("3")
  MACHINE_STATE_SAVE("3")
 
 
  if (!blocks->zero_word)
  if (!blocks->zero_word)
    {
    {
      if (!trace_init)
      if (!trace_init)
        {
        {
          trace_init = 1;
          trace_init = 1;
          __bb_init_prg ();
          __bb_init_prg ();
        }
        }
      __bb_init_file (blocks);
      __bb_init_file (blocks);
    }
    }
 
 
  if (bb_callcount)
  if (bb_callcount)
    {
    {
 
 
      bb_callcount += 1;
      bb_callcount += 1;
 
 
      if (bb_mode & 12)
      if (bb_mode & 12)
        {
        {
          if (bb_callcount >= bb_stacksize)
          if (bb_callcount >= bb_stacksize)
            {
            {
              size_t newsize = bb_callcount + 100;
              size_t newsize = bb_callcount + 100;
 
 
              bb_stack = (unsigned long *) realloc (bb_stack, newsize);
              bb_stack = (unsigned long *) realloc (bb_stack, newsize);
              if (! bb_stack)
              if (! bb_stack)
                {
                {
                  if (!reported)
                  if (!reported)
                    {
                    {
                      fprintf (stderr, "Profiler: out of memory\n");
                      fprintf (stderr, "Profiler: out of memory\n");
                      reported = 1;
                      reported = 1;
                    }
                    }
                  bb_stacksize = 0;
                  bb_stacksize = 0;
                  goto stack_overflow;
                  goto stack_overflow;
                }
                }
              bb_stacksize = newsize;
              bb_stacksize = newsize;
            }
            }
          bb_stack[bb_callcount] = bb_src;
          bb_stack[bb_callcount] = bb_src;
 
 
          if (bb_mode & 4)
          if (bb_mode & 4)
            bb_src = 0;
            bb_src = 0;
 
 
        }
        }
 
 
stack_overflow:;
stack_overflow:;
 
 
    }
    }
 
 
  else if (blocks->flags && (blocks->flags[blockno] & TRACE_ON))
  else if (blocks->flags && (blocks->flags[blockno] & TRACE_ON))
    {
    {
      bb_callcount = 1;
      bb_callcount = 1;
      bb_src = 0;
      bb_src = 0;
 
 
      if (bb_stack)
      if (bb_stack)
          bb_stack[bb_callcount] = bb_src;
          bb_stack[bb_callcount] = bb_src;
    }
    }
 
 
  MACHINE_STATE_RESTORE("3")
  MACHINE_STATE_RESTORE("3")
}
}
 
 
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.