summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/libgcc2.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/gcc/libgcc2.c')
-rw-r--r--contrib/gcc/libgcc2.c593
1 files changed, 268 insertions, 325 deletions
diff --git a/contrib/gcc/libgcc2.c b/contrib/gcc/libgcc2.c
index dd5eee7..dea803d 100644
--- a/contrib/gcc/libgcc2.c
+++ b/contrib/gcc/libgcc2.c
@@ -43,10 +43,11 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "libgcc2.h"
-#if defined (L_negdi2) || defined (L_divdi3) || defined (L_moddi3)
-#if defined (L_divdi3) || defined (L_moddi3)
-static inline
+#ifdef DECLARE_LIBRARY_RENAMES
+ DECLARE_LIBRARY_RENAMES
#endif
+
+#if defined (L_negdi2)
DWtype
__negdi2 (DWtype u)
{
@@ -149,9 +150,9 @@ __mulvsi3 (Wtype a, Wtype b)
Wtype
__negvsi2 (Wtype a)
{
- Wtype w;
+ Wtype w;
- w = -a;
+ w = -a;
if (a >= 0 ? w > 0 : w < 0)
abort ();
@@ -164,14 +165,14 @@ __negvsi2 (Wtype a)
DWtype
__negvdi2 (DWtype a)
{
- DWtype w;
+ DWtype w;
- w = -a;
+ w = -a;
if (a >= 0 ? w > 0 : w < 0)
abort ();
- return w;
+ return w;
}
#endif
@@ -179,16 +180,16 @@ __negvdi2 (DWtype a)
Wtype
__absvsi2 (Wtype a)
{
- Wtype w = a;
+ Wtype w = a;
- if (a < 0)
+ if (a < 0)
#ifdef L_negvsi2
- w = __negvsi2 (a);
+ w = __negvsi2 (a);
#else
- w = -a;
+ w = -a;
- if (w < 0)
- abort ();
+ if (w < 0)
+ abort ();
#endif
return w;
@@ -199,19 +200,19 @@ __absvsi2 (Wtype a)
DWtype
__absvdi2 (DWtype a)
{
- DWtype w = a;
+ DWtype w = a;
- if (a < 0)
+ if (a < 0)
#ifdef L_negvsi2
- w = __negvsi2 (a);
+ w = __negvsi2 (a);
#else
- w = -a;
+ w = -a;
- if (w < 0)
- abort ();
+ if (w < 0)
+ abort ();
#endif
- return w;
+ return w;
}
#endif
@@ -219,7 +220,7 @@ __absvdi2 (DWtype a)
DWtype
__mulvdi3 (DWtype u, DWtype v)
{
- DWtype w;
+ DWtype w;
w = u * v;
@@ -365,8 +366,19 @@ __muldi3 (DWtype u, DWtype v)
}
#endif
+#if (defined (L_udivdi3) || defined (L_divdi3) || \
+ defined (L_umoddi3) || defined (L_moddi3))
+#if defined (sdiv_qrnnd)
+#define L_udiv_w_sdiv
+#endif
+#endif
+
#ifdef L_udiv_w_sdiv
#if defined (sdiv_qrnnd)
+#if (defined (L_udivdi3) || defined (L_divdi3) || \
+ defined (L_umoddi3) || defined (L_moddi3))
+static inline __attribute__ ((__always_inline__))
+#endif
UWtype
__udiv_w_sdiv (UWtype *rp, UWtype a1, UWtype a0, UWtype d)
{
@@ -499,7 +511,7 @@ const UQItype __clz_tab[] =
#if (defined (L_udivdi3) || defined (L_divdi3) || \
defined (L_umoddi3) || defined (L_moddi3))
-static inline
+static inline __attribute__ ((__always_inline__))
#endif
UDWtype
__udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp)
@@ -732,14 +744,14 @@ __divdi3 (DWtype u, DWtype v)
if (uu.s.high < 0)
c = ~c,
- uu.ll = __negdi2 (uu.ll);
+ uu.ll = -uu.ll;
if (vv.s.high < 0)
c = ~c,
- vv.ll = __negdi2 (vv.ll);
+ vv.ll = -vv.ll;
w = __udivmoddi4 (uu.ll, vv.ll, (UDWtype *) 0);
if (c)
- w = __negdi2 (w);
+ w = -w;
return w;
}
@@ -758,13 +770,13 @@ __moddi3 (DWtype u, DWtype v)
if (uu.s.high < 0)
c = ~c,
- uu.ll = __negdi2 (uu.ll);
+ uu.ll = -uu.ll;
if (vv.s.high < 0)
- vv.ll = __negdi2 (vv.ll);
+ vv.ll = -vv.ll;
(void) __udivmoddi4 (uu.ll, vv.ll, &w);
if (c)
- w = __negdi2 (w);
+ w = -w;
return w;
}
@@ -1063,35 +1075,10 @@ __floatdidf (DWtype u)
#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
#define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2))
#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
-#define DI_SIZE (sizeof (DWtype) * BITS_PER_UNIT)
-
-/* Define codes for all the float formats that we know of. Note
- that this is copied from real.h. */
-
-#define UNKNOWN_FLOAT_FORMAT 0
-#define IEEE_FLOAT_FORMAT 1
-#define VAX_FLOAT_FORMAT 2
-#define IBM_FLOAT_FORMAT 3
-
-/* Default to IEEE float if not specified. Nearly all machines use it. */
-#ifndef HOST_FLOAT_FORMAT
-#define HOST_FLOAT_FORMAT IEEE_FLOAT_FORMAT
-#endif
-#if HOST_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
-#define DF_SIZE 53
-#define SF_SIZE 24
-#endif
-
-#if HOST_FLOAT_FORMAT == IBM_FLOAT_FORMAT
-#define DF_SIZE 56
-#define SF_SIZE 24
-#endif
-
-#if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT
-#define DF_SIZE 56
-#define SF_SIZE 24
-#endif
+#define DI_SIZE (sizeof (DWtype) * BITS_PER_UNIT)
+#define DF_SIZE DBL_MANT_DIG
+#define SF_SIZE FLT_MANT_DIG
SFtype
__floatdisf (DWtype u)
@@ -1264,14 +1251,13 @@ __eprintf (const char *string, const char *expression,
#ifdef L_bb
-#if LONG_TYPE_SIZE == GCOV_TYPE_SIZE
-typedef long gcov_type;
-#else
-typedef long long gcov_type;
-#endif
-
+struct bb_function_info {
+ long checksum;
+ int arc_count;
+ const char *name;
+};
-/* Structure emitted by -a */
+/* Structure emitted by --profile-arcs */
struct bb
{
long zero_word;
@@ -1279,26 +1265,19 @@ struct bb
gcov_type *counts;
long ncounts;
struct bb *next;
- const unsigned long *addresses;
/* Older GCC's did not emit these fields. */
- long nwords;
- const char **functions;
- const long *line_nums;
- const char **filenames;
- char *flags;
+ long sizeof_bb;
+ struct bb_function_info *function_infos;
};
#ifndef inhibit_libc
-/* Simple minded basic block profiling output dumper for
- systems that don't provide tcov support. At present,
- it requires atexit and stdio. */
+/* Arc profile dumper. Requires atexit and stdio. */
#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
#include <stdio.h>
-#include "gbl-ctors.h"
#include "gcov-io.h"
#include <string.h>
#ifdef TARGET_HAS_F_SETLKW
@@ -1306,162 +1285,272 @@ struct bb
#include <errno.h>
#endif
+/* Chain of per-object file bb structures. */
static struct bb *bb_head;
+/* Dump the coverage counts. We merge with existing counts when
+ possible, to avoid growing the .da files ad infinitum. */
+
void
__bb_exit_func (void)
{
- FILE *da_file;
- int i;
struct bb *ptr;
+ int i;
+ gcov_type program_sum = 0;
+ gcov_type program_max = 0;
+ long program_arcs = 0;
+ gcov_type merged_sum = 0;
+ gcov_type merged_max = 0;
+ long merged_arcs = 0;
+
+#if defined (TARGET_HAS_F_SETLKW)
+ struct flock s_flock;
- if (bb_head == 0)
- return;
-
- i = strlen (bb_head->filename) - 3;
-
+ s_flock.l_type = F_WRLCK;
+ s_flock.l_whence = SEEK_SET;
+ s_flock.l_start = 0;
+ s_flock.l_len = 0; /* Until EOF. */
+ s_flock.l_pid = getpid ();
+#endif
- for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
+ /* Non-merged stats for this program. */
+ for (ptr = bb_head; ptr; ptr = ptr->next)
{
- int firstchar;
-
- /* Make sure the output file exists -
- but don't clobber exiting data. */
- if ((da_file = fopen (ptr->filename, "a")) != 0)
- fclose (da_file);
+ for (i = 0; i < ptr->ncounts; i++)
+ {
+ program_sum += ptr->counts[i];
- /* Need to re-open in order to be able to write from the start. */
+ if (ptr->counts[i] > program_max)
+ program_max = ptr->counts[i];
+ }
+ program_arcs += ptr->ncounts;
+ }
+
+ for (ptr = bb_head; ptr; ptr = ptr->next)
+ {
+ FILE *da_file;
+ gcov_type object_max = 0;
+ gcov_type object_sum = 0;
+ long object_functions = 0;
+ int merging = 0;
+ int error = 0;
+ struct bb_function_info *fn_info;
+ gcov_type *count_ptr;
+
+ /* Open for modification */
da_file = fopen (ptr->filename, "r+b");
- /* Some old systems might not allow the 'b' mode modifier.
- Therefore, try to open without it. This can lead to a race
- condition so that when you delete and re-create the file, the
- file might be opened in text mode, but then, you shouldn't
- delete the file in the first place. */
- if (da_file == 0)
- da_file = fopen (ptr->filename, "r+");
- if (da_file == 0)
+
+ if (da_file)
+ merging = 1;
+ else
+ {
+ /* Try for appending */
+ da_file = fopen (ptr->filename, "ab");
+ /* Some old systems might not allow the 'b' mode modifier.
+ Therefore, try to open without it. This can lead to a
+ race condition so that when you delete and re-create the
+ file, the file might be opened in text mode, but then,
+ you shouldn't delete the file in the first place. */
+ if (!da_file)
+ da_file = fopen (ptr->filename, "a");
+ }
+
+ if (!da_file)
{
fprintf (stderr, "arc profiling: Can't open output file %s.\n",
ptr->filename);
+ ptr->filename = 0;
continue;
}
+#if defined (TARGET_HAS_F_SETLKW)
/* After a fork, another process might try to read and/or write
the same file simultanously. So if we can, lock the file to
avoid race conditions. */
-#if defined (TARGET_HAS_F_SETLKW)
- {
- struct flock s_flock;
-
- s_flock.l_type = F_WRLCK;
- s_flock.l_whence = SEEK_SET;
- s_flock.l_start = 0;
- s_flock.l_len = 1;
- s_flock.l_pid = getpid ();
-
- while (fcntl (fileno (da_file), F_SETLKW, &s_flock)
- && errno == EINTR);
- }
+ while (fcntl (fileno (da_file), F_SETLKW, &s_flock)
+ && errno == EINTR)
+ continue;
#endif
+ for (fn_info = ptr->function_infos; fn_info->arc_count != -1; fn_info++)
+ object_functions++;
- /* If the file is not empty, and the number of counts in it is the
- same, then merge them in. */
- firstchar = fgetc (da_file);
- if (firstchar == EOF)
+ if (merging)
{
- if (ferror (da_file))
+ /* Merge data from file. */
+ long tmp_long;
+ gcov_type tmp_gcov;
+
+ if (/* magic */
+ (__read_long (&tmp_long, da_file, 4) || tmp_long != -123l)
+ /* functions in object file. */
+ || (__read_long (&tmp_long, da_file, 4)
+ || tmp_long != object_functions)
+ /* extension block, skipped */
+ || (__read_long (&tmp_long, da_file, 4)
+ || fseek (da_file, tmp_long, SEEK_CUR)))
{
- fprintf (stderr, "arc profiling: Can't read output file ");
- perror (ptr->filename);
- }
- }
- else
- {
- long n_counts = 0;
-
- if (ungetc (firstchar, da_file) == EOF)
- rewind (da_file);
- if (__read_long (&n_counts, da_file, 8) != 0)
- {
- fprintf (stderr, "arc profiling: Can't read output file %s.\n",
+ read_error:;
+ fprintf (stderr, "arc profiling: Error merging output file %s.\n",
ptr->filename);
- continue;
+ clearerr (da_file);
}
-
- if (n_counts == ptr->ncounts)
+ else
{
- int i;
-
- for (i = 0; i < n_counts; i++)
+ /* Merge execution counts for each function. */
+ count_ptr = ptr->counts;
+
+ for (fn_info = ptr->function_infos; fn_info->arc_count != -1;
+ fn_info++)
{
- gcov_type v = 0;
-
- if (__read_gcov_type (&v, da_file, 8) != 0)
- {
- fprintf (stderr,
- "arc profiling: Can't read output file %s.\n",
- ptr->filename);
- break;
- }
- ptr->counts[i] += v;
+ if (/* function name delim */
+ (__read_long (&tmp_long, da_file, 4)
+ || tmp_long != -1)
+ /* function name length */
+ || (__read_long (&tmp_long, da_file, 4)
+ || tmp_long != (long) strlen (fn_info->name))
+ /* skip string */
+ || fseek (da_file, ((tmp_long + 1) + 3) & ~3, SEEK_CUR)
+ /* function name delim */
+ || (__read_long (&tmp_long, da_file, 4)
+ || tmp_long != -1))
+ goto read_error;
+
+ if (/* function checksum */
+ (__read_long (&tmp_long, da_file, 4)
+ || tmp_long != fn_info->checksum)
+ /* arc count */
+ || (__read_long (&tmp_long, da_file, 4)
+ || tmp_long != fn_info->arc_count))
+ goto read_error;
+
+ for (i = fn_info->arc_count; i > 0; i--, count_ptr++)
+ if (__read_gcov_type (&tmp_gcov, da_file, 8))
+ goto read_error;
+ else
+ *count_ptr += tmp_gcov;
}
}
-
+ fseek (da_file, 0, SEEK_SET);
}
-
- rewind (da_file);
-
- /* ??? Should first write a header to the file. Preferably, a 4 byte
- magic number, 4 bytes containing the time the program was
- compiled, 4 bytes containing the last modification time of the
- source file, and 4 bytes indicating the compiler options used.
-
- That way we can easily verify that the proper source/executable/
- data file combination is being used from gcov. */
-
- if (__write_gcov_type (ptr->ncounts, da_file, 8) != 0)
+
+ /* Calculate the per-object statistics. */
+ for (i = 0; i < ptr->ncounts; i++)
{
+ object_sum += ptr->counts[i];
+ if (ptr->counts[i] > object_max)
+ object_max = ptr->counts[i];
+ }
+ merged_sum += object_sum;
+ if (merged_max < object_max)
+ merged_max = object_max;
+ merged_arcs += ptr->ncounts;
+
+ /* Write out the data. */
+ if (/* magic */
+ __write_long (-123, da_file, 4)
+ /* number of functions in object file. */
+ || __write_long (object_functions, da_file, 4)
+ /* length of extra data in bytes. */
+ || __write_long ((4 + 8 + 8) + (4 + 8 + 8), da_file, 4)
+
+ /* whole program statistics. If merging write per-object
+ now, rewrite later */
+ /* number of instrumented arcs. */
+ || __write_long (merging ? ptr->ncounts : program_arcs, da_file, 4)
+ /* sum of counters. */
+ || __write_gcov_type (merging ? object_sum : program_sum, da_file, 8)
+ /* maximal counter. */
+ || __write_gcov_type (merging ? object_max : program_max, da_file, 8)
+
+ /* per-object statistics. */
+ /* number of counters. */
+ || __write_long (ptr->ncounts, da_file, 4)
+ /* sum of counters. */
+ || __write_gcov_type (object_sum, da_file, 8)
+ /* maximal counter. */
+ || __write_gcov_type (object_max, da_file, 8))
+ {
+ write_error:;
fprintf (stderr, "arc profiling: Error writing output file %s.\n",
ptr->filename);
+ error = 1;
}
else
{
- int j;
- gcov_type *count_ptr = ptr->counts;
- int ret = 0;
- for (j = ptr->ncounts; j > 0; j--)
+ /* Write execution counts for each function. */
+ count_ptr = ptr->counts;
+
+ for (fn_info = ptr->function_infos; fn_info->arc_count != -1;
+ fn_info++)
{
- if (__write_gcov_type (*count_ptr, da_file, 8) != 0)
- {
- ret = 1;
- break;
- }
- count_ptr++;
+ if (__write_gcov_string (fn_info->name,
+ strlen (fn_info->name), da_file, -1)
+ || __write_long (fn_info->checksum, da_file, 4)
+ || __write_long (fn_info->arc_count, da_file, 4))
+ goto write_error;
+
+ for (i = fn_info->arc_count; i > 0; i--, count_ptr++)
+ if (__write_gcov_type (*count_ptr, da_file, 8))
+ goto write_error; /* RIP Edsger Dijkstra */
}
- if (ret)
- fprintf (stderr, "arc profiling: Error writing output file %s.\n",
- ptr->filename);
}
- if (fclose (da_file) == EOF)
- fprintf (stderr, "arc profiling: Error closing output file %s.\n",
- ptr->filename);
+ if (fclose (da_file))
+ {
+ fprintf (stderr, "arc profiling: Error closing output file %s.\n",
+ ptr->filename);
+ error = 1;
+ }
+ if (error || !merging)
+ ptr->filename = 0;
}
- return;
+ /* Upate whole program statistics. */
+ for (ptr = bb_head; ptr; ptr = ptr->next)
+ if (ptr->filename)
+ {
+ FILE *da_file;
+
+ da_file = fopen (ptr->filename, "r+b");
+ if (!da_file)
+ {
+ fprintf (stderr, "arc profiling: Cannot reopen %s.\n",
+ ptr->filename);
+ continue;
+ }
+
+#if defined (TARGET_HAS_F_SETLKW)
+ while (fcntl (fileno (da_file), F_SETLKW, &s_flock)
+ && errno == EINTR)
+ continue;
+#endif
+
+ if (fseek (da_file, 4 * 3, SEEK_SET)
+ /* number of instrumented arcs. */
+ || __write_long (merged_arcs, da_file, 4)
+ /* sum of counters. */
+ || __write_gcov_type (merged_sum, da_file, 8)
+ /* maximal counter. */
+ || __write_gcov_type (merged_max, da_file, 8))
+ fprintf (stderr, "arc profiling: Error updating program header %s.\n",
+ ptr->filename);
+ if (fclose (da_file))
+ fprintf (stderr, "arc profiling: Error reclosing %s\n",
+ ptr->filename);
+ }
}
+/* Add a new object file onto the bb chain. Invoked automatically
+ when running an object file's global ctors. */
+
void
__bb_init_func (struct bb *blocks)
{
- /* User is supposed to check whether the first word is non-0,
- but just in case.... */
-
if (blocks->zero_word)
return;
- /* Initialize destructor. */
+ /* Initialize destructor and per-thread data. */
if (!bb_head)
atexit (__bb_exit_func);
@@ -1474,6 +1563,7 @@ __bb_init_func (struct bb *blocks)
/* Called before fork or exec - write out profile information gathered so
far and reset it to zero. This avoids duplication or loss of the
profile information gathered so far. */
+
void
__bb_fork_func (void)
{
@@ -1656,102 +1746,6 @@ mprotect (char *addr, int len, int prot)
TRANSFER_FROM_TRAMPOLINE
#endif
-#if defined (NeXT) && defined (__MACH__)
-
-/* Make stack executable so we can call trampolines on stack.
- This is called from INITIALIZE_TRAMPOLINE in next.h. */
-#ifdef NeXTStep21
- #include <mach.h>
-#else
- #include <mach/mach.h>
-#endif
-
-void
-__enable_execute_stack (char *addr)
-{
- kern_return_t r;
- char *eaddr = addr + TRAMPOLINE_SIZE;
- vm_address_t a = (vm_address_t) addr;
-
- /* turn on execute access on stack */
- r = vm_protect (task_self (), a, TRAMPOLINE_SIZE, FALSE, VM_PROT_ALL);
- if (r != KERN_SUCCESS)
- {
- mach_error("vm_protect VM_PROT_ALL", r);
- exit(1);
- }
-
- /* We inline the i-cache invalidation for speed */
-
-#ifdef CLEAR_INSN_CACHE
- CLEAR_INSN_CACHE (addr, eaddr);
-#else
- __clear_cache ((int) addr, (int) eaddr);
-#endif
-}
-
-#endif /* defined (NeXT) && defined (__MACH__) */
-
-#ifdef __convex__
-
-/* Make stack executable so we can call trampolines on stack.
- This is called from INITIALIZE_TRAMPOLINE in convex.h. */
-
-#include <sys/mman.h>
-#include <sys/vmparam.h>
-#include <machine/machparam.h>
-
-void
-__enable_execute_stack (void)
-{
- int fp;
- static unsigned lowest = USRSTACK;
- unsigned current = (unsigned) &fp & -NBPG;
-
- if (lowest > current)
- {
- unsigned len = lowest - current;
- mremap (current, &len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE);
- lowest = current;
- }
-
- /* Clear instruction cache in case an old trampoline is in it. */
- asm ("pich");
-}
-#endif /* __convex__ */
-
-#ifdef __sysV88__
-
-/* Modified from the convex -code above. */
-
-#include <sys/param.h>
-#include <errno.h>
-#include <sys/m88kbcs.h>
-
-void
-__enable_execute_stack (void)
-{
- int save_errno;
- static unsigned long lowest = USRSTACK;
- unsigned long current = (unsigned long) &save_errno & -NBPC;
-
- /* Ignore errno being set. memctl sets errno to EINVAL whenever the
- address is seen as 'negative'. That is the case with the stack. */
-
- save_errno=errno;
- if (lowest > current)
- {
- unsigned len=lowest-current;
- memctl(current,len,MCT_TEXT);
- lowest = current;
- }
- else
- memctl(current,NBPC,MCT_TEXT);
- errno=save_errno;
-}
-
-#endif /* __sysV88__ */
-
#ifdef __sysV68__
#include <sys/signal.h>
@@ -1796,57 +1790,6 @@ __clear_insn_cache (void)
}
#endif /* __sysV68__ */
-
-#ifdef __pyr__
-
-#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
-#include <stdio.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/vmmac.h>
-
-/* Modified from the convex -code above.
- mremap promises to clear the i-cache. */
-
-void
-__enable_execute_stack (void)
-{
- int fp;
- if (mprotect (((unsigned int)&fp/PAGSIZ)*PAGSIZ, PAGSIZ,
- PROT_READ|PROT_WRITE|PROT_EXEC))
- {
- perror ("mprotect in __enable_execute_stack");
- fflush (stderr);
- abort ();
- }
-}
-#endif /* __pyr__ */
-
-#if defined (sony_news) && defined (SYSTYPE_BSD)
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/param.h>
-#include <syscall.h>
-#include <machine/sysnews.h>
-
-/* cacheflush function for NEWS-OS 4.2.
- This function is called from trampoline-initialize code
- defined in config/mips/mips.h. */
-
-void
-cacheflush (char *beg, int size, int flag)
-{
- if (syscall (SYS_sysnews, NEWS_CACHEFLUSH, beg, size, FLUSH_BCACHE))
- {
- perror ("cache_flush");
- fflush (stderr);
- abort ();
- }
-}
-
-#endif /* sony_news */
#endif /* L_trampoline */
#ifndef __CYGWIN__
OpenPOWER on IntegriCloud