Backport upstream patches to fix ICEs when using -fdebug-types-section.
[official-gcc.git] / gcc-4_7-mobile / libgcc / pmu-profile.c
blobd6a63b85a252cc3c40d2c51082b8a564d0d32400
1 /* Performance monitoring unit (PMU) profiler. If available, use an
2 external tool to collect hardware performance counter data and
3 write it in the .gcda files.
5 Copyright (C) 2011. Free Software Foundation, Inc.
6 Contributed by Sharad Singhai <singhai@google.com>.
8 This file is part of GCC.
10 GCC is free software; you can redistribute it and/or modify it under
11 the terms of the GNU General Public License as published by the Free
12 Software Foundation; either version 3, or (at your option) any later
13 version.
15 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16 WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 for more details.
20 Under Section 7 of GPL version 3, you are granted additional
21 permissions described in the GCC Runtime Library Exception, version
22 3.1, as published by the Free Software Foundation.
24 You should have received a copy of the GNU General Public License and
25 a copy of the GCC Runtime Library Exception along with this program;
26 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
27 <http://www.gnu.org/licenses/>. */
29 #include "tconfig.h"
30 #include "tsystem.h"
31 #include "coretypes.h"
32 #include "tm.h"
33 #if (defined (__x86_64__) || defined (__i386__))
34 #include "cpuid.h"
35 #endif
37 #if defined(inhibit_libc)
38 #define IN_LIBGCOV (-1)
39 #else
40 #include <stdio.h>
41 #include <stdlib.h>
42 #define IN_LIBGCOV 1
43 #if defined(L_gcov)
44 #define GCOV_LINKAGE /* nothing */
45 #endif
46 #endif
47 #include "gcov-io.h"
48 #ifdef TARGET_POSIX_IO
49 #include <fcntl.h>
50 #include <signal.h>
51 #include <sys/stat.h>
52 #include <sys/types.h>
53 #endif
55 #if defined(inhibit_libc)
56 #else
57 #include <errno.h>
58 #include <stdio.h>
59 #include <stdlib.h>
60 #include <unistd.h>
62 #include <sys/types.h>
63 #include <sys/wait.h>
65 #define XNEWVEC(type,ne) (type *)calloc((ne),sizeof(type))
66 #define XNEW(type) (type *)malloc(sizeof(type))
67 #define XDELETEVEC(p) free(p)
68 #define XDELETE(p) free(p)
70 static unsigned convert_pct_to_unsigned (float pct);
71 static void *init_pmu_load_latency (void);
72 static void *init_pmu_branch_mispredict (void);
73 static void destroy_load_latency_infos (void *info);
74 static void destroy_branch_mispredict_infos (void *info);
75 static gcov_unsigned_t gcov_tag_pmu_tool_header_length (gcov_pmu_tool_header_t
76 *header);
78 /* Convert a fractional PCT to an unsigned integer after
79 muliplying by 100. */
81 static unsigned
82 convert_pct_to_unsigned (float pct)
84 return (unsigned)(pct * 100.0f);
87 /* Delete load latency info structures INFO. */
89 static void
90 destroy_load_latency_infos (void *info)
92 unsigned i;
93 ll_infos_t* ll_infos = (ll_infos_t *)info;
95 /* delete each element */
96 for (i = 0; i < ll_infos->ll_count; ++i)
97 XDELETE (ll_infos->ll_array[i]);
98 /* delete the array itself */
99 XDELETE (ll_infos->ll_array);
100 __destroy_pmu_tool_header (ll_infos->pmu_tool_header);
101 free (ll_infos->pmu_tool_header);
102 ll_infos->ll_array = 0;
103 ll_infos->ll_count = 0;
106 /* Delete branch mispredict structure INFO. */
108 static void
109 destroy_branch_mispredict_infos (void *info)
111 unsigned i;
112 brm_infos_t* brm_infos = (brm_infos_t *)info;
114 /* delete each element */
115 for (i = 0; i < brm_infos->brm_count; ++i)
116 XDELETE (brm_infos->brm_array[i]);
117 /* delete the array itself */
118 XDELETE (brm_infos->brm_array);
119 __destroy_pmu_tool_header (brm_infos->pmu_tool_header);
120 free (brm_infos->pmu_tool_header);
121 brm_infos->brm_array = 0;
122 brm_infos->brm_count = 0;
125 /* Allocate and initialize pmu load latency structure. */
127 static void *
128 init_pmu_load_latency (void)
130 ll_infos_t *load_latency = XNEWVEC (ll_infos_t, 1);
131 load_latency->ll_count = 0;
132 load_latency->alloc_ll_count = 64;
133 load_latency->ll_array = XNEWVEC (gcov_pmu_ll_info_t *,
134 load_latency->alloc_ll_count);
135 return (void *)load_latency;
138 /* Allocate and initialize pmu branch mispredict structure. */
140 static void *
141 init_pmu_branch_mispredict (void)
143 brm_infos_t *brm_info = XNEWVEC (brm_infos_t, 1);
144 brm_info->brm_count = 0;
145 brm_info->alloc_brm_count = 64;
146 brm_info->brm_array = XNEWVEC (gcov_pmu_brm_info_t *,
147 brm_info->alloc_brm_count);
148 return (void *)brm_info;
151 /* Write the load latency information LL_INFO into the gcda file. */
153 void
154 gcov_write_ll_line (const gcov_pmu_ll_info_t *ll_info)
156 gcov_write_tag_length (GCOV_TAG_PMU_LOAD_LATENCY_INFO,
157 GCOV_TAG_PMU_LOAD_LATENCY_LENGTH);
158 gcov_write_unsigned (ll_info->counts);
159 gcov_write_unsigned (ll_info->self);
160 gcov_write_unsigned (ll_info->cum);
161 gcov_write_unsigned (ll_info->lt_10);
162 gcov_write_unsigned (ll_info->lt_32);
163 gcov_write_unsigned (ll_info->lt_64);
164 gcov_write_unsigned (ll_info->lt_256);
165 gcov_write_unsigned (ll_info->lt_1024);
166 gcov_write_unsigned (ll_info->gt_1024);
167 gcov_write_unsigned (ll_info->wself);
168 gcov_write_counter (ll_info->code_addr);
169 gcov_write_unsigned (ll_info->line);
170 gcov_write_unsigned (ll_info->discriminator);
171 gcov_write_unsigned (ll_info->filetag);
175 /* Write the branch mispredict information BRM_INFO into the gcda file. */
177 void
178 gcov_write_branch_mispredict_line (const gcov_pmu_brm_info_t *brm_info)
180 gcov_write_tag_length (GCOV_TAG_PMU_BRANCH_MISPREDICT_INFO,
181 GCOV_TAG_PMU_BRANCH_MISPREDICT_LENGTH);
182 gcov_write_unsigned (brm_info->counts);
183 gcov_write_unsigned (brm_info->self);
184 gcov_write_unsigned (brm_info->cum);
185 gcov_write_counter (brm_info->code_addr);
186 gcov_write_unsigned (brm_info->line);
187 gcov_write_unsigned (brm_info->discriminator);
188 gcov_write_unsigned (brm_info->filetag);
191 /* Write the string table entry ST_ENTRY into the gcda file. */
193 void
194 gcov_write_string_table_entry (const gcov_pmu_st_entry_t *st_entry)
196 gcov_write_tag_length (GCOV_TAG_PMU_STRING_TABLE_ENTRY,
197 GCOV_TAG_PMU_STRING_TABLE_ENTRY_LENGTH(
198 st_entry->str));
199 gcov_write_unsigned(st_entry->index);
200 gcov_write_string(st_entry->str);
203 /* Compute TOOL_HEADER length for writing into the gcov file. */
205 static gcov_unsigned_t
206 gcov_tag_pmu_tool_header_length (gcov_pmu_tool_header_t *header)
208 gcov_unsigned_t len = 0;
209 if (header)
211 len += gcov_string_length (header->host_cpu);
212 len += gcov_string_length (header->hostname);
213 len += gcov_string_length (header->kernel_version);
214 len += gcov_string_length (header->column_header);
215 len += gcov_string_length (header->column_description);
216 len += gcov_string_length (header->full_header);
218 return len;
221 /* Write tool header into the gcda file. It assumes that the gcda file
222 has already been opened and is available for writing. */
224 void
225 gcov_write_tool_header (gcov_pmu_tool_header_t *header)
227 gcov_unsigned_t len = gcov_tag_pmu_tool_header_length (header);
228 gcov_write_tag_length (GCOV_TAG_PMU_TOOL_HEADER, len);
229 gcov_write_string (header->host_cpu);
230 gcov_write_string (header->hostname);
231 gcov_write_string (header->kernel_version);
232 gcov_write_string (header->column_header);
233 gcov_write_string (header->column_description);
234 gcov_write_string (header->full_header);
237 #endif