Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /* Routines required for instrumenting a program.  */
  2. /* Compile this one with gcc.  */
  3. /* Copyright (C) 1989-2015 Free Software Foundation, Inc.
  4.  
  5. This file is part of GCC.
  6.  
  7. GCC is free software; you can redistribute it and/or modify it under
  8. the terms of the GNU General Public License as published by the Free
  9. Software Foundation; either version 3, or (at your option) any later
  10. version.
  11.  
  12. GCC is distributed in the hope that it will be useful, but WITHOUT ANY
  13. WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  15. for more details.
  16.  
  17. Under Section 7 of GPL version 3, you are granted additional
  18. permissions described in the GCC Runtime Library Exception, version
  19. 3.1, as published by the Free Software Foundation.
  20.  
  21. You should have received a copy of the GNU General Public License and
  22. a copy of the GCC Runtime Library Exception along with this program;
  23. see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
  24. <http://www.gnu.org/licenses/>.  */
  25.  
  26. #include "libgcov.h"
  27.  
  28. #if defined(inhibit_libc)
  29. /* If libc and its header files are not available, provide dummy functions.  */
  30.  
  31. #ifdef L_gcov_merge_add
  32. void __gcov_merge_add (gcov_type *counters  __attribute__ ((unused)),
  33.                        unsigned n_counters __attribute__ ((unused))) {}
  34. #endif
  35.  
  36. #ifdef L_gcov_merge_single
  37. void __gcov_merge_single (gcov_type *counters  __attribute__ ((unused)),
  38.                           unsigned n_counters __attribute__ ((unused))) {}
  39. #endif
  40.  
  41. #ifdef L_gcov_merge_delta
  42. void __gcov_merge_delta (gcov_type *counters  __attribute__ ((unused)),
  43.                          unsigned n_counters __attribute__ ((unused))) {}
  44. #endif
  45.  
  46. #else
  47.  
  48. #ifdef L_gcov_merge_add
  49. /* The profile merging function that just adds the counters.  It is given
  50.    an array COUNTERS of N_COUNTERS old counters and it reads the same number
  51.    of counters from the gcov file.  */
  52. void
  53. __gcov_merge_add (gcov_type *counters, unsigned n_counters)
  54. {
  55.   for (; n_counters; counters++, n_counters--)
  56.     *counters += gcov_get_counter ();
  57. }
  58. #endif /* L_gcov_merge_add */
  59.  
  60. #ifdef L_gcov_merge_ior
  61. /* The profile merging function that just adds the counters.  It is given
  62.    an array COUNTERS of N_COUNTERS old counters and it reads the same number
  63.    of counters from the gcov file.  */
  64. void
  65. __gcov_merge_ior (gcov_type *counters, unsigned n_counters)
  66. {
  67.   for (; n_counters; counters++, n_counters--)
  68.     *counters |= gcov_get_counter_target ();
  69. }
  70. #endif
  71.  
  72. #ifdef L_gcov_merge_time_profile
  73. /* Time profiles are merged so that minimum from all valid (greater than zero)
  74.    is stored. There could be a fork that creates new counters. To have
  75.    the profile stable, we chosen to pick the smallest function visit time.  */
  76. void
  77. __gcov_merge_time_profile (gcov_type *counters, unsigned n_counters)
  78. {
  79.   unsigned int i;
  80.   gcov_type value;
  81.  
  82.   for (i = 0; i < n_counters; i++)
  83.     {
  84.       value = gcov_get_counter_target ();
  85.  
  86.       if (value && (!counters[i] || value < counters[i]))
  87.         counters[i] = value;
  88.     }
  89. }
  90. #endif /* L_gcov_merge_time_profile */
  91.  
  92. #ifdef L_gcov_merge_single
  93. /* The profile merging function for choosing the most common value.
  94.    It is given an array COUNTERS of N_COUNTERS old counters and it
  95.    reads the same number of counters from the gcov file.  The counters
  96.    are split into 3-tuples where the members of the tuple have
  97.    meanings:
  98.  
  99.    -- the stored candidate on the most common value of the measured entity
  100.    -- counter
  101.    -- total number of evaluations of the value  */
  102. void
  103. __gcov_merge_single (gcov_type *counters, unsigned n_counters)
  104. {
  105.   unsigned i, n_measures;
  106.   gcov_type value, counter, all;
  107.  
  108.   gcc_assert (!(n_counters % 3));
  109.   n_measures = n_counters / 3;
  110.   for (i = 0; i < n_measures; i++, counters += 3)
  111.     {
  112.       value = gcov_get_counter_target ();
  113.       counter = gcov_get_counter ();
  114.       all = gcov_get_counter ();
  115.  
  116.       if (counters[0] == value)
  117.         counters[1] += counter;
  118.       else if (counter > counters[1])
  119.         {
  120.           counters[0] = value;
  121.           counters[1] = counter - counters[1];
  122.         }
  123.       else
  124.         counters[1] -= counter;
  125.       counters[2] += all;
  126.     }
  127. }
  128. #endif /* L_gcov_merge_single */
  129.  
  130. #ifdef L_gcov_merge_delta
  131. /* The profile merging function for choosing the most common
  132.    difference between two consecutive evaluations of the value.  It is
  133.    given an array COUNTERS of N_COUNTERS old counters and it reads the
  134.    same number of counters from the gcov file.  The counters are split
  135.    into 4-tuples where the members of the tuple have meanings:
  136.  
  137.    -- the last value of the measured entity
  138.    -- the stored candidate on the most common difference
  139.    -- counter
  140.    -- total number of evaluations of the value  */
  141. void
  142. __gcov_merge_delta (gcov_type *counters, unsigned n_counters)
  143. {
  144.   unsigned i, n_measures;
  145.   gcov_type value, counter, all;
  146.  
  147.   gcc_assert (!(n_counters % 4));
  148.   n_measures = n_counters / 4;
  149.   for (i = 0; i < n_measures; i++, counters += 4)
  150.     {
  151.       /* last = */ gcov_get_counter ();
  152.       value = gcov_get_counter_target ();
  153.       counter = gcov_get_counter ();
  154.       all = gcov_get_counter ();
  155.  
  156.       if (counters[1] == value)
  157.         counters[2] += counter;
  158.       else if (counter > counters[2])
  159.         {
  160.           counters[1] = value;
  161.           counters[2] = counter - counters[2];
  162.         }
  163.       else
  164.         counters[2] -= counter;
  165.       counters[3] += all;
  166.     }
  167. }
  168. #endif /* L_gcov_merge_delta */
  169.  
  170. #ifdef L_gcov_merge_icall_topn
  171. /* The profile merging function used for merging indirect call counts
  172.    This function is given array COUNTERS of N_COUNTERS old counters and it
  173.    reads the same number of counters from the gcov file.  */
  174.  
  175. void
  176. __gcov_merge_icall_topn (gcov_type *counters, unsigned n_counters)
  177. {
  178.   unsigned i, j, k, m;
  179.  
  180.   gcc_assert (!(n_counters % GCOV_ICALL_TOPN_NCOUNTS));
  181.   for (i = 0; i < n_counters; i += GCOV_ICALL_TOPN_NCOUNTS)
  182.     {
  183.       gcov_type *value_array = &counters[i + 1];
  184.       unsigned tmp_size = 2 * (GCOV_ICALL_TOPN_NCOUNTS - 1);
  185.       gcov_type *tmp_array
  186.           = (gcov_type *) alloca (tmp_size * sizeof (gcov_type));
  187.  
  188.       for (j = 0; j < tmp_size; j++)
  189.         tmp_array[j] = 0;
  190.  
  191.       for (j = 0; j < GCOV_ICALL_TOPN_NCOUNTS - 1; j += 2)
  192.         {
  193.           tmp_array[j] = value_array[j];
  194.           tmp_array[j + 1] = value_array [j + 1];
  195.         }
  196.  
  197.       /* Skip the number_of_eviction entry.  */
  198.       gcov_get_counter ();
  199.       for (k = 0; k < GCOV_ICALL_TOPN_NCOUNTS - 1; k += 2)
  200.         {
  201.           int found = 0;
  202.           gcov_type global_id = gcov_get_counter_target ();
  203.           gcov_type call_count = gcov_get_counter ();
  204.           for (m = 0; m < j; m += 2)
  205.             {
  206.               if (tmp_array[m] == global_id)
  207.                 {
  208.                   found = 1;
  209.                   tmp_array[m + 1] += call_count;
  210.                   break;
  211.                 }
  212.             }
  213.           if (!found)
  214.             {
  215.               tmp_array[j] = global_id;
  216.               tmp_array[j + 1] = call_count;
  217.               j += 2;
  218.             }
  219.         }
  220.       /* Now sort the temp array */
  221.       gcov_sort_n_vals (tmp_array, j);
  222.  
  223.       /* Now copy back the top half of the temp array */
  224.       for (k = 0; k < GCOV_ICALL_TOPN_NCOUNTS - 1; k += 2)
  225.         {
  226.           value_array[k] = tmp_array[k];
  227.           value_array[k + 1] = tmp_array[k + 1];
  228.         }
  229.     }
  230. }
  231. #endif /* L_gcov_merge_icall_topn */
  232. #endif /* inhibit_libc */
  233.