OSDN Git Service

PR c++/9623
[pf3gnuchains/gcc-fork.git] / gcc / libgcc2.c
index a47dfd1..069aedb 100644 (file)
@@ -29,10 +29,14 @@ along with GCC; see the file COPYING.  If not, write to the Free
 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 02111-1307, USA.  */
 
+
+/* We include auto-host.h here to get HAVE_GAS_HIDDEN.  This is
+   supposedly valid even though this is a "target" file.  */
+#include "auto-host.h"
+
 /* It is incorrect to include config.h here, because this file is being
    compiled for the target, and hence definitions concerning only the host
    do not apply.  */
-
 #include "tconfig.h"
 #include "tsystem.h"
 #include "coretypes.h"
@@ -43,6 +47,12 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #undef abort
 #endif
 
+#ifdef HAVE_GAS_HIDDEN
+#define ATTRIBUTE_HIDDEN  __attribute__ ((__visibility__ ("hidden")))
+#else
+#define ATTRIBUTE_HIDDEN
+#endif
+
 #include "libgcc2.h"
 \f
 #ifdef DECLARE_LIBRARY_RENAMES
@@ -119,7 +129,7 @@ DWtype
 __subvdi3 (DWtype a, DWtype b)
 {
 #ifdef L_addvdi3
-  return (a, (-b));
+  return __addvdi3 (a, (-b));
 #else
   DWtype w;
 
@@ -330,9 +340,27 @@ __ashrdi3 (DWtype u, word_type b)
 }
 #endif
 \f
+#ifdef L_ffssi2
+#undef int
+extern int __ffsSI2 (UWtype u);
+int
+__ffsSI2 (UWtype u)
+{
+  UWtype count;
+
+  if (u == 0)
+    return 0;
+
+  count_trailing_zeros (count, u);
+  return count + 1;
+}
+#endif
+\f
 #ifdef L_ffsdi2
-DWtype
-__ffsdi2 (DWtype u)
+#undef int
+extern int __ffsDI2 (DWtype u);
+int
+__ffsDI2 (DWtype u)
 {
   DWunion uu;
   UWtype word, count, add;
@@ -508,6 +536,175 @@ const UQItype __clz_tab[] =
   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
 };
 #endif
+\f
+#ifdef L_clzsi2
+#undef int
+extern int __clzSI2 (UWtype x);
+int
+__clzSI2 (UWtype x)
+{
+  Wtype ret;
+
+  count_leading_zeros (ret, x);
+
+  return ret;
+}
+#endif
+\f
+#ifdef L_clzdi2
+#undef int
+extern int __clzDI2 (UDWtype x);
+int
+__clzDI2 (UDWtype x)
+{
+  DWunion uu;
+  UWtype word;
+  Wtype ret, add;
+
+  uu.ll = x;
+  if (uu.s.high)
+    word = uu.s.high, add = 0;
+  else
+    word = uu.s.low, add = W_TYPE_SIZE;
+
+  count_leading_zeros (ret, word);
+  return ret + add;
+}
+#endif
+\f
+#ifdef L_ctzsi2
+#undef int
+extern int __ctzSI2 (UWtype x);
+int
+__ctzSI2 (UWtype x)
+{
+  Wtype ret;
+
+  count_trailing_zeros (ret, x);
+
+  return ret;
+}
+#endif
+\f
+#ifdef L_ctzdi2
+#undef int
+extern int __ctzDI2 (UDWtype x);
+int
+__ctzDI2 (UDWtype x)
+{
+  DWunion uu;
+  UWtype word;
+  Wtype ret, add;
+
+  uu.ll = x;
+  if (uu.s.low)
+    word = uu.s.low, add = 0;
+  else
+    word = uu.s.high, add = W_TYPE_SIZE;
+
+  count_trailing_zeros (ret, word);
+  return ret + add;
+}
+#endif
+
+#if (defined (L_popcountsi2) || defined (L_popcountdi2)        \
+     || defined (L_popcount_tab))
+extern const UQItype __popcount_tab[] ATTRIBUTE_HIDDEN;
+#endif
+
+#ifdef L_popcount_tab
+const UQItype __popcount_tab[] =
+{
+    0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
+    1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+    1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+    2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+    1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+    2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+    2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+    3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
+};
+#endif
+\f
+#ifdef L_popcountsi2
+#undef int
+extern int __popcountSI2 (UWtype x);
+int
+__popcountSI2 (UWtype x)
+{
+  UWtype i, ret = 0;
+
+  for (i = 0; i < W_TYPE_SIZE; i += 8)
+    ret += __popcount_tab[(x >> i) & 0xff];
+
+  return ret;
+}
+#endif
+\f
+#ifdef L_popcountdi2
+#undef int
+extern int __popcountDI2 (UDWtype x);
+int
+__popcountDI2 (UDWtype x)
+{
+  UWtype i, ret = 0;
+
+  for (i = 0; i < 2*W_TYPE_SIZE; i += 8)
+    ret += __popcount_tab[(x >> i) & 0xff];
+
+  return ret;
+}
+#endif
+\f
+#ifdef L_paritysi2
+#undef int
+extern int __paritySI2 (UWtype x);
+int
+__paritySI2 (UWtype x)
+{
+#if W_TYPE_SIZE > 64
+# error "fill out the table"
+#endif
+#if W_TYPE_SIZE > 32
+  x ^= x >> 32;
+#endif
+#if W_TYPE_SIZE > 16
+  x ^= x >> 16;
+#endif
+  x ^= x >> 8;
+  x ^= x >> 4;
+  x &= 0xf;
+  return (0x6996 >> x) & 1;
+}
+#endif
+\f
+#ifdef L_paritydi2
+#undef int
+extern int __parityDI2 (UDWtype x);
+int
+__parityDI2 (UDWtype x)
+{
+  DWunion uu;
+  UWtype nx;
+
+  uu.ll = x;
+  nx = uu.s.low ^ uu.s.high;
+
+#if W_TYPE_SIZE > 64
+# error "fill out the table"
+#endif
+#if W_TYPE_SIZE > 32
+  nx ^= nx >> 32;
+#endif
+#if W_TYPE_SIZE > 16
+  nx ^= nx >> 16;
+#endif
+  nx ^= nx >> 8;
+  nx ^= nx >> 4;
+  nx &= 0xf;
+  return (0x6996 >> nx) & 1;
+}
+#endif
 
 #ifdef L_udivmoddi4
 
@@ -1235,445 +1432,6 @@ __eprintf (const char *string, const char *expression,
 #endif
 #endif
 
-#ifdef L_gcov
-
-/* Gcov profile dumper. Requires atexit and stdio.  */
-
-#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
-#include <stdio.h>
-
-#include "gcov-io.h"
-#include <string.h>
-#if defined (TARGET_HAS_F_SETLKW)
-#include <fcntl.h>
-#include <errno.h>
-#endif
-
-/* Chain of per-object gcov structures.  */
-static struct gcov_info *gcov_list;
-
-/* A program checksum allows us to distinguish program data for an
-   object file included in multiple programs.  */
-static unsigned gcov_crc32;
-
-static void
-gcov_version_mismatch (struct gcov_info *ptr, unsigned version)
-{
-  unsigned expected = GCOV_VERSION;
-  unsigned ix;
-  char e[4], v[4];
-
-  for (ix = 4; ix--; expected >>= 8, version >>= 8)
-    {
-      e[ix] = expected;
-      v[ix] = version;
-    }
-  
-  fprintf (stderr,
-          "profiling:%s:Version mismatch - expected %.4s got %.4s\n",
-          ptr->filename, e, v);
-}
-
-/* Dump the coverage counts. We merge with existing counts when
-   possible, to avoid growing the .da files ad infinitum. We use this
-   program's checksum to make sure we only accumulate whole program
-   statistics to the correct summary. An object file might be embedded
-   in two separate programs, and we must keep the two program
-   summaries separate.  */
-
-static void
-gcov_exit (void)
-{
-  struct gcov_info *ptr;
-  unsigned ix, jx;
-  struct gcov_summary program;
-  gcov_type program_max_one = 0;
-  gcov_type program_max_sum = 0;
-  gcov_type program_sum = 0;
-  unsigned program_arcs = 0;
-  
-#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 = 0; /* Until EOF.  */
-  s_flock.l_pid = getpid ();
-#endif
-
-  memset (&program, 0, sizeof (program));
-  program.checksum = gcov_crc32;
-  
-  for (ptr = gcov_list; ptr; ptr = ptr->next)
-    {
-      FILE *da_file;
-      struct gcov_summary object;
-      struct gcov_summary local_prg;
-      int merging = 0;
-      long base;
-      const struct function_info *fn_info;
-      gcov_type *count_ptr;
-      gcov_type object_max_one = 0;
-
-      ptr->wkspc = 0;
-      if (!ptr->filename)
-       continue;
-
-      for (ix = ptr->n_arc_counts, count_ptr = ptr->arc_counts; ix--;)
-       {
-         gcov_type count = *count_ptr++;
-
-         if (count > object_max_one)
-           object_max_one = count;
-       }
-      if (object_max_one > program_max_one)
-       program_max_one = object_max_one;
-      
-      memset (&local_prg, 0, sizeof (local_prg));
-      memset (&object, 0, sizeof (object));
-      
-      /* Open for modification */
-      if ((da_file = fopen (ptr->filename, "r+b")))
-       merging = 1;
-      else if ((da_file = fopen (ptr->filename, "w+b")))
-       ;
-      else
-       {
-         fprintf (stderr, "profiling:%s:Cannot open\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 simultaneously.  So if we can, lock the file to
-         avoid race conditions.  */
-      while (fcntl (fileno (da_file), F_SETLKW, &s_flock)
-            && errno == EINTR)
-       continue;
-#endif
-      if (merging)
-       {
-         /* Merge data from file.  */
-         unsigned tag, length;
-             
-         if (gcov_read_unsigned (da_file, &tag) || tag != GCOV_DATA_MAGIC)
-           {
-             fprintf (stderr, "profiling:%s:Not a gcov data file\n",
-                      ptr->filename);
-           read_fatal:;
-             fclose (da_file);
-             ptr->filename = 0;
-             continue;
-           }
-         if (gcov_read_unsigned (da_file, &length) || length != GCOV_VERSION)
-           {
-             gcov_version_mismatch (ptr, length);
-             goto read_fatal;
-           }
-         
-         /* Merge execution counts for each function.  */
-         count_ptr = ptr->arc_counts;
-         for (ix = ptr->n_functions, fn_info = ptr->functions;
-              ix--; fn_info++)
-           {
-             if (gcov_read_unsigned (da_file, &tag)
-                 || gcov_read_unsigned (da_file, &length))
-               {
-               read_error:;
-                 fprintf (stderr, "profiling:%s:Error merging\n",
-                          ptr->filename);
-                 goto read_fatal;
-               }
-
-             /* Check function */
-             if (tag != GCOV_TAG_FUNCTION)
-               {
-               read_mismatch:;
-                 fprintf (stderr, "profiling:%s:Merge mismatch at %s\n",
-                          ptr->filename, fn_info->name);
-                 goto read_fatal;
-               }
-             {
-               unsigned flength, checksum;
-               
-               if (gcov_read_unsigned (da_file, &flength)
-                   || gcov_skip_string (da_file, flength)
-                   || gcov_read_unsigned (da_file, &checksum))
-                 goto read_error;
-               if (flength != strlen (fn_info->name)
-                   || checksum != fn_info->checksum)
-                 goto read_mismatch;
-             }
-             /* Check arc counts */
-             if (gcov_read_unsigned (da_file, &tag)
-                 || gcov_read_unsigned (da_file, &length))
-               goto read_error;
-             if (tag != GCOV_TAG_ARC_COUNTS
-                 || length / 8 != fn_info->n_arc_counts)
-               goto read_mismatch;
-             {
-               gcov_type count;
-               
-               for (jx = fn_info->n_arc_counts; jx--; count_ptr++)
-                 if (gcov_read_counter (da_file, &count))
-                   goto read_error;
-                 else
-                   *count_ptr += count;
-             }
-           }
-
-         /* Check object summary */
-         if (gcov_read_unsigned (da_file, &tag)
-             || gcov_read_unsigned (da_file, &length))
-           goto read_error;
-         if (tag != GCOV_TAG_OBJECT_SUMMARY)
-           goto read_mismatch;
-         if (gcov_read_summary (da_file, &object))
-           goto read_error;
-
-         /* Check program summary */
-         while (1)
-           {
-             long base = ftell (da_file);
-             
-             if (gcov_read_unsigned (da_file, &tag)
-                 || gcov_read_unsigned (da_file, &length))
-               {
-                 if (feof (da_file))
-                   break;
-                 goto read_error;
-               }
-             if (tag != GCOV_TAG_PROGRAM_SUMMARY
-                 && tag != GCOV_TAG_PLACEHOLDER_SUMMARY
-                 && tag != GCOV_TAG_INCORRECT_SUMMARY)
-               goto read_mismatch;
-             if (gcov_read_summary (da_file, &local_prg))
-               goto read_error;
-             if (local_prg.checksum != program.checksum)
-               continue;
-             if (tag == GCOV_TAG_PLACEHOLDER_SUMMARY)
-               {
-                 fprintf (stderr,
-                          "profiling:%s:Concurrent race detected\n",
-                          ptr->filename);
-                 goto read_fatal;
-               }
-             merging = -1;
-             if (tag != GCOV_TAG_PROGRAM_SUMMARY)
-               break;
-             
-             if (program.runs
-                 && memcmp (&program, &local_prg, sizeof (program)))
-               {
-                 fprintf (stderr, "profiling:%s:Invocation mismatch\n",
-                          ptr->filename);
-                 local_prg.runs = 0;
-               }
-             else
-               memcpy (&program, &local_prg, sizeof (program));
-             ptr->wkspc = base;
-             break;
-           }
-         fseek (da_file, 0, SEEK_SET);
-       }
-
-      object.runs++;
-      object.arcs = ptr->n_arc_counts;
-      object.arc_sum = 0;
-      if (object.arc_max_one < object_max_one)
-       object.arc_max_one = object_max_one;
-      object.arc_sum_max += object_max_one;
-      
-      /* Write out the data.  */
-      if (/* magic */
-         gcov_write_unsigned (da_file, GCOV_DATA_MAGIC)
-         /* version number */
-         || gcov_write_unsigned (da_file, GCOV_VERSION))
-       {
-       write_error:;
-         fclose (da_file);
-         fprintf (stderr, "profiling:%s:Error writing\n", ptr->filename);
-         ptr->filename = 0;
-         continue;
-       }
-      
-      /* Write execution counts for each function.  */
-      count_ptr = ptr->arc_counts;
-      for (ix = ptr->n_functions, fn_info = ptr->functions; ix--; fn_info++)
-       {
-         /* Announce function.  */
-         if (gcov_write_unsigned (da_file, GCOV_TAG_FUNCTION)
-             || !(base = gcov_reserve_length (da_file))
-             /* function name */
-             || gcov_write_string (da_file, fn_info->name,
-                                   strlen (fn_info->name))
-             /* function checksum */
-             || gcov_write_unsigned (da_file, fn_info->checksum)
-             || gcov_write_length (da_file, base))
-           goto write_error;
-         
-         /* arc counts.  */
-         if (gcov_write_unsigned (da_file, GCOV_TAG_ARC_COUNTS)
-             || !(base = gcov_reserve_length (da_file)))
-           goto write_error;
-         
-         for (jx = fn_info->n_arc_counts; jx--;)
-           {
-             gcov_type count = *count_ptr++;
-             
-             object.arc_sum += count;
-             if (object.arc_max_sum < count)
-               object.arc_max_sum = count;
-             if (gcov_write_counter (da_file, count))
-               goto write_error; /* RIP Edsger Dijkstra */
-           }
-         if (gcov_write_length (da_file, base))
-           goto write_error;
-       }
-
-      /* Object file summary.  */
-      if (gcov_write_summary (da_file, GCOV_TAG_OBJECT_SUMMARY, &object))
-       goto write_error;
-
-      if (merging >= 0)
-       {
-         if (fseek (da_file, 0, SEEK_END))
-           goto write_error;
-         ptr->wkspc = ftell (da_file);
-         if (gcov_write_summary (da_file, GCOV_TAG_PLACEHOLDER_SUMMARY,
-                                 &program))
-           goto write_error;
-       }
-      else if (ptr->wkspc)
-       {
-         /* Zap trailing program summary */
-         if (fseek (da_file, ptr->wkspc, SEEK_SET))
-           goto write_error;
-         if (!local_prg.runs)
-           ptr->wkspc = 0;
-         if (gcov_write_unsigned (da_file,
-                            local_prg.runs ? GCOV_TAG_PLACEHOLDER_SUMMARY
-                            : GCOV_TAG_INCORRECT_SUMMARY))
-           goto write_error;
-       }
-      if (fflush (da_file))
-       goto write_error;
-
-      if (fclose (da_file))
-       {
-         fprintf (stderr, "profiling:%s:Error closing\n", ptr->filename);
-         ptr->filename = 0;
-       }
-      else
-       {
-         program_arcs += ptr->n_arc_counts;
-         program_sum += object.arc_sum;
-         if (program_max_sum < object.arc_max_sum)
-           program_max_sum = object.arc_max_sum;
-       }
-    }
-
-  /* Generate whole program statistics.  */
-  program.runs++;
-  program.arcs = program_arcs;
-  program.arc_sum = program_sum;
-  if (program.arc_max_one < program_max_one)
-    program.arc_max_one = program_max_one;
-  if (program.arc_max_sum < program_max_sum)
-    program.arc_max_sum = program_max_sum;
-  program.arc_sum_max += program_max_one;
-  
-  /* Upate whole program statistics.  */
-  for (ptr = gcov_list; ptr; ptr = ptr->next)
-    if (ptr->filename && ptr->wkspc)
-      {
-       FILE *da_file;
-       
-       da_file = fopen (ptr->filename, "r+b");
-       if (!da_file)
-         {
-           fprintf (stderr, "profiling:%s:Cannot open\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, ptr->wkspc, SEEK_SET)
-           || gcov_write_summary (da_file, GCOV_TAG_PROGRAM_SUMMARY, &program)
-           || fflush (da_file))
-         fprintf (stderr, "profiling:%s:Error writing\n", ptr->filename);
-       if (fclose (da_file))
-         fprintf (stderr, "profiling:%s:Error closing\n", ptr->filename);
-      }
-}
-
-/* Add a new object file onto the bb chain.  Invoked automatically
-   when running an object file's global ctors.  */
-
-void
-__gcov_init (struct gcov_info *info)
-{
-  if (!info->version)
-    return;
-  if (info->version != GCOV_VERSION)
-    gcov_version_mismatch (info, info->version);
-  else
-    {
-      const char *ptr = info->filename;
-      unsigned crc32 = gcov_crc32;
-  
-      do
-       {
-         unsigned ix;
-         unsigned value = *ptr << 24;
-
-         for (ix = 8; ix--; value <<= 1)
-           {
-             unsigned feedback;
-
-             feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0;
-             crc32 <<= 1;
-             crc32 ^= feedback;
-           }
-       }
-      while (*ptr++);
-      
-      gcov_crc32 = crc32;
-      
-      if (!gcov_list)
-       atexit (gcov_exit);
-      
-      info->next = gcov_list;
-      gcov_list = info;
-    }
-  info->version = 0;
-}
-
-/* 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
-__gcov_flush (void)
-{
-  struct gcov_info *ptr;
-
-  gcov_exit ();
-  for (ptr = gcov_list; ptr; ptr = ptr->next)
-    {
-      unsigned i;
-      
-      for (i = ptr->n_arc_counts; i--;)
-       ptr->arc_counts[i] = 0;
-    }
-}
-
-#endif /* L_gcov */
 \f
 #ifdef L_clear_cache
 /* Clear part of an instruction cache.  */