]>
Commit | Line | Data |
---|---|---|
b7e215a8 | 1 | /* Generate CTF. |
7adcbafe | 2 | Copyright (C) 2019-2022 Free Software Foundation, Inc. |
b7e215a8 IB |
3 | |
4 | This file is part of GCC. | |
5 | ||
6 | GCC is free software; you can redistribute it and/or modify it under | |
7 | the terms of the GNU General Public License as published by the Free | |
8 | Software Foundation; either version 3, or (at your option) any later | |
9 | version. | |
10 | ||
11 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
12 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 | for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with GCC; see the file COPYING3. If not see | |
18 | <http://www.gnu.org/licenses/>. */ | |
19 | ||
20 | #include "config.h" | |
21 | #include "system.h" | |
22 | #include "coretypes.h" | |
23 | #include "target.h" | |
24 | #include "toplev.h" | |
25 | #include "ctfc.h" | |
26 | #include "diagnostic-core.h" | |
27 | ||
28 | /* A CTF container object - one per translation unit. */ | |
29 | ||
30 | ctf_container_ref tu_ctfc; | |
31 | ||
32 | ctf_container_ref | |
33 | ctf_get_tu_ctfc (void) | |
34 | { | |
35 | return tu_ctfc; | |
36 | } | |
37 | ||
38 | /* If the next ctf type id is still set to the init value, no ctf records to | |
39 | report. */ | |
40 | bool | |
41 | ctfc_is_empty_container (ctf_container_ref ctfc) | |
42 | { | |
43 | return ((ctfc)->ctfc_nextid == CTF_INIT_TYPEID); | |
44 | } | |
45 | ||
46 | /* Get the total number of CTF types in the container. */ | |
47 | ||
48 | unsigned int | |
49 | ctfc_get_num_ctf_types (ctf_container_ref ctfc) | |
50 | { | |
51 | return ctfc->ctfc_types->elements (); | |
52 | } | |
53 | ||
54 | /* Get the total number of CTF variables in the container. */ | |
55 | ||
56 | unsigned int ctfc_get_num_ctf_vars (ctf_container_ref ctfc) | |
57 | { | |
58 | return ctfc->ctfc_vars->elements (); | |
59 | } | |
60 | ||
61 | /* Get reference to the CTF string table or the CTF auxilliary | |
62 | string table. */ | |
63 | ||
64 | ctf_strtable_t * | |
65 | ctfc_get_strtab (ctf_container_ref ctfc, int aux) | |
66 | { | |
67 | return aux ? &(ctfc)->ctfc_aux_strtable : &(ctfc->ctfc_strtable); | |
68 | } | |
69 | ||
70 | /* Get the length of the specified string table of the CTF container. */ | |
71 | ||
72 | size_t | |
73 | ctfc_get_strtab_len (ctf_container_ref ctfc, int aux) | |
74 | { | |
75 | ctf_strtable_t * strtab = ctfc_get_strtab (ctfc, aux); | |
76 | return strtab->ctstab_len; | |
77 | } | |
78 | ||
79 | /* Get the number of bytes to represent the variable length portion of all CTF | |
80 | types in the CTF container. */ | |
81 | ||
82 | size_t ctfc_get_num_vlen_bytes (ctf_container_ref ctfc) | |
83 | { | |
84 | return ctfc->ctfc_num_vlen_bytes; | |
85 | } | |
86 | ||
87 | /* Return which member of the union is used in CTFTYPE. Used for garbage | |
88 | collection. */ | |
89 | ||
90 | enum ctf_dtu_d_union_enum | |
91 | ctf_dtu_d_union_selector (ctf_dtdef_ref ctftype) | |
92 | { | |
93 | uint32_t kind = CTF_V2_INFO_KIND (ctftype->dtd_data.ctti_info); | |
94 | switch (kind) | |
95 | { | |
96 | case CTF_K_UNKNOWN: | |
97 | case CTF_K_INTEGER: | |
98 | case CTF_K_FLOAT: | |
99 | return CTF_DTU_D_ENCODING; | |
100 | case CTF_K_STRUCT: | |
101 | case CTF_K_UNION: | |
102 | case CTF_K_ENUM: | |
103 | return CTF_DTU_D_MEMBERS; | |
104 | case CTF_K_ARRAY: | |
105 | return CTF_DTU_D_ARRAY; | |
106 | case CTF_K_FUNCTION: | |
107 | return CTF_DTU_D_ARGUMENTS; | |
108 | case CTF_K_SLICE: | |
109 | return CTF_DTU_D_SLICE; | |
110 | default: | |
111 | /* The largest member as default. */ | |
112 | return CTF_DTU_D_ARRAY; | |
113 | } | |
114 | } | |
115 | ||
116 | /* Insert CTF type into the CTF container. */ | |
117 | ||
118 | static void | |
119 | ctf_dtd_insert (ctf_container_ref ctfc, ctf_dtdef_ref dtd) | |
120 | { | |
121 | bool existed = false; | |
122 | ctf_dtdef_ref entry = dtd; | |
123 | ||
124 | ctf_dtdef_ref * item = ctfc->ctfc_types->find_slot (entry, INSERT); | |
125 | if (*item == NULL) | |
126 | *item = dtd; | |
127 | else | |
128 | existed = true; | |
129 | /* Duplicate CTF type records not expected to be inserted. */ | |
130 | gcc_assert (!existed); | |
131 | } | |
132 | ||
133 | /* Lookup CTF type given a DWARF die for the type. */ | |
134 | ||
44e4ed6a | 135 | ctf_dtdef_ref |
b7e215a8 IB |
136 | ctf_dtd_lookup (const ctf_container_ref ctfc, const dw_die_ref type) |
137 | { | |
138 | ctf_dtdef_t entry; | |
139 | entry.dtd_key = type; | |
140 | ||
141 | ctf_dtdef_ref * slot = ctfc->ctfc_types->find_slot (&entry, NO_INSERT); | |
142 | ||
143 | if (slot) | |
144 | return (ctf_dtdef_ref)*slot; | |
145 | ||
146 | return NULL; | |
147 | } | |
148 | ||
149 | /* Insert CTF variable into the CTF container. */ | |
150 | ||
151 | static void | |
152 | ctf_dvd_insert (ctf_container_ref ctfc, ctf_dvdef_ref dvd) | |
153 | { | |
154 | bool existed = false; | |
155 | ctf_dvdef_ref entry = dvd; | |
156 | ||
157 | ctf_dvdef_ref * item = ctfc->ctfc_vars->find_slot (entry, INSERT); | |
158 | if (*item == NULL) | |
159 | *item = dvd; | |
160 | else | |
161 | existed = true; | |
162 | /* Duplicate variable records not expected to be inserted. */ | |
163 | gcc_assert (!existed); | |
164 | } | |
165 | ||
166 | /* Lookup CTF variable given a DWARF die for the decl. */ | |
167 | ||
168 | ctf_dvdef_ref | |
169 | ctf_dvd_lookup (const ctf_container_ref ctfc, dw_die_ref die) | |
170 | { | |
171 | ctf_dvdef_t entry; | |
172 | entry.dvd_key = die; | |
173 | ||
174 | ctf_dvdef_ref * slot = ctfc->ctfc_vars->find_slot (&entry, NO_INSERT); | |
175 | ||
176 | if (slot) | |
177 | return (ctf_dvdef_ref)*slot; | |
178 | ||
179 | return NULL; | |
180 | } | |
181 | ||
d0b00e74 IB |
182 | /* Insert a dummy CTF variable into the list of variables to be ignored. */ |
183 | ||
184 | static void | |
185 | ctf_dvd_ignore_insert (ctf_container_ref ctfc, ctf_dvdef_ref dvd) | |
186 | { | |
187 | bool existed = false; | |
188 | ctf_dvdef_ref entry = dvd; | |
189 | ||
190 | ctf_dvdef_ref * item = ctfc->ctfc_ignore_vars->find_slot (entry, INSERT); | |
191 | if (*item == NULL) | |
192 | *item = dvd; | |
193 | else | |
194 | existed = true; | |
195 | /* Duplicate variable records not expected to be inserted. */ | |
196 | gcc_assert (!existed); | |
197 | } | |
198 | ||
199 | /* Lookup the dummy CTF variable given the DWARF die for the non-defining | |
200 | decl to be ignored. */ | |
201 | ||
202 | bool | |
203 | ctf_dvd_ignore_lookup (const ctf_container_ref ctfc, dw_die_ref die) | |
204 | { | |
205 | ctf_dvdef_t entry; | |
206 | entry.dvd_key = die; | |
207 | ||
208 | ctf_dvdef_ref * slot = ctfc->ctfc_ignore_vars->find_slot (&entry, NO_INSERT); | |
209 | ||
210 | if (slot) | |
211 | return true; | |
212 | ||
213 | return false; | |
214 | } | |
215 | ||
b7e215a8 IB |
216 | /* Append member definition to the list. Member list is a singly-linked list |
217 | with list start pointing to the head. */ | |
218 | ||
219 | static void | |
220 | ctf_dmd_list_append (ctf_dmdef_t ** dmd, ctf_dmdef_t * elem) | |
221 | { | |
222 | ctf_dmdef_t * tail = (dmd && *dmd) ? *dmd : NULL; | |
223 | if (tail) | |
224 | { | |
225 | while (tail->dmd_next) | |
226 | tail = tail->dmd_next; | |
227 | ||
228 | tail->dmd_next = elem; | |
229 | } | |
230 | else | |
231 | *dmd = elem; | |
232 | ||
233 | elem->dmd_next = NULL; | |
234 | } | |
235 | ||
236 | /* Append function argument to the list. Member list is a singly-linked list | |
237 | with list start pointing to the head. */ | |
238 | ||
239 | static void | |
240 | ctf_farg_list_append (ctf_func_arg_t ** farg, ctf_func_arg_t * elem) | |
241 | { | |
242 | ctf_func_arg_t * tail = (farg && *farg) ? *farg : NULL; | |
243 | if (tail) | |
244 | { | |
245 | while (tail->farg_next) | |
246 | tail = tail->farg_next; | |
247 | ||
248 | tail->farg_next = elem; | |
249 | } | |
250 | else | |
251 | *farg = elem; | |
252 | ||
253 | elem->farg_next = NULL; | |
254 | } | |
255 | ||
256 | /* Append str to the CTF string table. */ | |
257 | ||
258 | static void | |
259 | ctfc_strtable_append_str (ctf_strtable_t * str_table, const char * str) | |
260 | { | |
261 | ctf_string_t * ctf_string = ggc_cleared_alloc<ctf_string_t> (); | |
262 | /* Keep a reference to the input STR. */ | |
263 | ctf_string->cts_str = str; | |
264 | ctf_string->cts_next = NULL; | |
265 | ||
266 | if (!str_table->ctstab_head) | |
267 | str_table->ctstab_head = ctf_string; | |
268 | ||
269 | /* Append to the end of the list. */ | |
270 | if (str_table->ctstab_tail) | |
271 | str_table->ctstab_tail->cts_next = ctf_string; | |
272 | ||
273 | str_table->ctstab_tail = ctf_string; | |
274 | } | |
275 | ||
276 | /* Wrapper function to add str to the CTF string table. No de-duplication of | |
277 | CTF strings is done by the compiler. */ | |
278 | ||
279 | static const char * | |
280 | ctfc_strtable_add_str (ctf_strtable_t * str_table, const char * name, | |
281 | uint32_t * name_offset) | |
282 | { | |
283 | size_t len; | |
284 | char * ctf_string; | |
285 | /* Return value is the offset to the string in the string table. */ | |
286 | uint32_t str_offset = str_table->ctstab_len; | |
287 | ||
288 | /* Add empty string only once at the beginning of the string table. Also, do | |
289 | not add null strings, return the offset to the empty string for them. */ | |
290 | if ((!name || (name != NULL && !strcmp (name, ""))) && str_offset) | |
291 | { | |
292 | ctf_string = CONST_CAST (char *, str_table->ctstab_estr); | |
293 | str_offset = 0; | |
294 | } | |
295 | else | |
296 | { | |
297 | gcc_assert (name); | |
298 | /* Add null-terminated strings to the string table. */ | |
299 | len = strlen (name) + 1; | |
300 | ctf_string = CONST_CAST (char *, ggc_strdup (name)); | |
301 | ||
302 | ctfc_strtable_append_str (str_table, ctf_string); | |
303 | /* Add string to the string table. Keep number of strings updated. */ | |
304 | str_table->ctstab_num++; | |
305 | /* Keep the number of bytes contained in the string table updated. */ | |
306 | str_table->ctstab_len += len; | |
307 | } | |
308 | ||
309 | *name_offset = str_offset; | |
310 | ||
311 | return (const char *) ctf_string; | |
312 | ||
313 | } | |
314 | ||
315 | /* Add string to the appropriate string table in the CTF container. */ | |
316 | ||
317 | const char * | |
318 | ctf_add_string (ctf_container_ref ctfc, const char * name, | |
319 | uint32_t * name_offset, int aux_str = CTF_STRTAB) | |
320 | { | |
321 | /* Get the CTF string table or the CTF auxilliary string table, | |
322 | as applicable. */ | |
323 | ctf_strtable_t *str_table = ctfc_get_strtab (ctfc, aux_str); | |
324 | return ctfc_strtable_add_str (str_table, name, name_offset); | |
325 | } | |
326 | ||
a8bb495a | 327 | /* Add the compilation unit (CU) name string to the CTF string table. The |
b7e215a8 IB |
328 | CU name has a prepended pwd string if it is a relative path. Also set the |
329 | CU name offset in the CTF container. */ | |
330 | ||
331 | void | |
332 | ctf_add_cuname (ctf_container_ref ctfc, const char * filename) | |
333 | { | |
334 | char * cuname = NULL; | |
335 | ||
336 | /* (filename at this point of compilation cannot be null). */ | |
337 | ||
338 | if (!IS_DIR_SEPARATOR (filename[0])) | |
339 | { | |
340 | /* Filename is a relative path. */ | |
341 | const char * cu_pwd = get_src_pwd (); | |
342 | const int cu_pwd_len = strlen (cu_pwd); | |
343 | ||
344 | /* Add a DIR_SEPARATOR char before the filename. */ | |
345 | const int len = cu_pwd_len + 2 + strlen (filename); | |
346 | ||
347 | cuname = (char *) ggc_alloc_atomic (len); | |
348 | memset (cuname, 0, len); | |
349 | ||
350 | strcpy (cuname, cu_pwd); | |
351 | cuname[cu_pwd_len] = DIR_SEPARATOR; | |
352 | cuname[cu_pwd_len+1] = 0; | |
353 | strcat (cuname, filename); | |
354 | } | |
355 | else | |
356 | /* Filename is an absolute path. */ | |
357 | cuname = CONST_CAST (char *, ggc_strdup (filename)); | |
358 | ||
359 | ctf_add_string (ctfc, cuname, &(ctfc->ctfc_cuname_offset)); | |
360 | /* Add 1 as CTF strings in the CTF string table are null-terminated | |
361 | strings. */ | |
362 | ctfc->ctfc_strlen += strlen (cuname) + 1; | |
363 | ||
364 | /* Mark cuname for garbage collection. */ | |
365 | cuname = NULL; | |
366 | } | |
367 | ||
368 | /* Functions to create CTF types. | |
369 | ||
370 | These functions perform the task of adding CTF types to the CTF container. | |
371 | No de-duplication is done by them; the onus is on the calling function to do | |
372 | so. The caller must first do a lookup via ctf_dtd_lookup or | |
373 | ctf_dvd_lookup, as applicable, to ascertain that the CTF type or the CTF | |
374 | variable respectively does not already exist, and then add it. */ | |
375 | ||
376 | static ctf_id_t | |
377 | ctf_add_generic (ctf_container_ref ctfc, uint32_t flag, const char * name, | |
378 | ctf_dtdef_ref * rp, dw_die_ref die) | |
379 | { | |
380 | ctf_dtdef_ref dtd; | |
381 | ctf_id_t type; | |
382 | ||
383 | gcc_assert (flag == CTF_ADD_NONROOT || flag == CTF_ADD_ROOT); | |
384 | ||
385 | dtd = ggc_cleared_alloc<ctf_dtdef_t> (); | |
386 | ||
387 | type = ctfc->ctfc_nextid++; | |
388 | gcc_assert (type < CTF_MAX_TYPE); /* CTF type ID overflow. */ | |
389 | ||
390 | /* Buffer the strings in the CTF string table. */ | |
391 | dtd->dtd_name = ctf_add_string (ctfc, name, &(dtd->dtd_data.ctti_name)); | |
392 | dtd->dtd_type = type; | |
393 | dtd->dtd_key = die; | |
394 | ||
395 | if ((name != NULL) && strcmp (name, "")) | |
396 | ctfc->ctfc_strlen += strlen (name) + 1; | |
397 | ||
398 | ctf_dtd_insert (ctfc, dtd); | |
399 | ||
400 | *rp = dtd; | |
401 | return type; | |
402 | } | |
403 | ||
404 | static ctf_id_t | |
405 | ctf_add_encoded (ctf_container_ref ctfc, uint32_t flag, const char * name, | |
406 | const ctf_encoding_t * ep, uint32_t kind, dw_die_ref die) | |
407 | { | |
408 | ctf_dtdef_ref dtd; | |
409 | ctf_id_t type; | |
410 | ||
411 | type = ctf_add_generic (ctfc, flag, name, &dtd, die); | |
412 | ||
413 | dtd->dtd_data.ctti_info = CTF_TYPE_INFO (kind, flag, 0); | |
414 | ||
415 | uint32_t roundup_nbytes = (ROUND_UP (ep->cte_bits, BITS_PER_UNIT) | |
416 | / BITS_PER_UNIT); | |
417 | ||
418 | /* FIXME, stay close to what libctf does. But by getting next power of two, | |
419 | aren't we conveying less precise information. E.g. floating point mode | |
420 | XF has a size of 12 bytes. */ | |
421 | dtd->dtd_data.ctti_size = roundup_nbytes ? (1 << ceil_log2 (roundup_nbytes)) | |
422 | : roundup_nbytes; | |
423 | dtd->dtd_u.dtu_enc = *ep; | |
424 | ||
425 | ctfc->ctfc_num_stypes++; | |
426 | ||
427 | return type; | |
428 | } | |
429 | ||
430 | ctf_id_t | |
431 | ctf_add_reftype (ctf_container_ref ctfc, uint32_t flag, ctf_id_t ref, | |
432 | uint32_t kind, dw_die_ref die) | |
433 | { | |
434 | ctf_dtdef_ref dtd; | |
435 | ctf_id_t type; | |
436 | ||
437 | gcc_assert (ref <= CTF_MAX_TYPE); | |
438 | ||
439 | type = ctf_add_generic (ctfc, flag, NULL, &dtd, die); | |
440 | dtd->dtd_data.ctti_info = CTF_TYPE_INFO (kind, flag, 0); | |
441 | /* Caller of this API must guarantee that a CTF type with id = ref already | |
442 | exists. This will also be validated for us at link-time. */ | |
443 | dtd->dtd_data.ctti_type = (uint32_t) ref; | |
444 | ||
445 | ctfc->ctfc_num_stypes++; | |
446 | ||
447 | return type; | |
448 | } | |
449 | ||
450 | ctf_id_t | |
451 | ctf_add_forward (ctf_container_ref ctfc, uint32_t flag, const char * name, | |
452 | uint32_t kind, dw_die_ref die) | |
453 | { | |
454 | ctf_dtdef_ref dtd; | |
455 | ctf_id_t type = 0; | |
456 | ||
457 | type = ctf_add_generic (ctfc, flag, name, &dtd, die); | |
458 | ||
459 | dtd->dtd_data.ctti_info = CTF_TYPE_INFO (CTF_K_FORWARD, flag, 0); | |
460 | dtd->dtd_data.ctti_type = kind; | |
461 | ||
462 | ctfc->ctfc_num_stypes++; | |
463 | ||
464 | return type; | |
465 | } | |
466 | ||
467 | ctf_id_t | |
468 | ctf_add_typedef (ctf_container_ref ctfc, uint32_t flag, const char * name, | |
469 | ctf_id_t ref, dw_die_ref die) | |
470 | { | |
471 | ctf_dtdef_ref dtd; | |
472 | ctf_id_t type; | |
473 | ||
474 | gcc_assert (ref <= CTF_MAX_TYPE); | |
475 | /* Nameless Typedefs are not expected. */ | |
476 | gcc_assert ((name != NULL) && strcmp (name, "")); | |
477 | ||
478 | type = ctf_add_generic (ctfc, flag, name, &dtd, die); | |
479 | dtd->dtd_data.ctti_info = CTF_TYPE_INFO (CTF_K_TYPEDEF, flag, 0); | |
480 | /* Caller of this API must guarantee that a CTF type with id = ref already | |
481 | exists. This will also be validated for us at link-time. */ | |
482 | dtd->dtd_data.ctti_type = (uint32_t) ref; | |
483 | ||
484 | gcc_assert (dtd->dtd_type != dtd->dtd_data.ctti_type); | |
485 | ||
486 | ctfc->ctfc_num_stypes++; | |
487 | ||
488 | return type; | |
489 | } | |
490 | ||
491 | ctf_id_t | |
492 | ctf_add_slice (ctf_container_ref ctfc, uint32_t flag, ctf_id_t ref, | |
493 | uint32_t bit_offset, uint32_t bit_size, dw_die_ref die) | |
494 | { | |
495 | ctf_dtdef_ref dtd; | |
496 | ctf_id_t type; | |
497 | uint32_t roundup_nbytes; | |
498 | ||
499 | gcc_assert ((bit_size <= 255) && (bit_offset <= 255)); | |
500 | ||
501 | gcc_assert (ref <= CTF_MAX_TYPE); | |
502 | ||
503 | type = ctf_add_generic (ctfc, flag, NULL, &dtd, die); | |
504 | ||
505 | dtd->dtd_data.ctti_info = CTF_TYPE_INFO (CTF_K_SLICE, flag, 0); | |
506 | ||
507 | roundup_nbytes = (ROUND_UP (bit_size, BITS_PER_UNIT) / BITS_PER_UNIT); | |
508 | /* FIXME, stay close to what libctf does. But by getting next power of two, | |
509 | aren't we conveying less precise information, especially for bitfields. | |
510 | For example, cte_bits = 33, roundup_nbytes = 5, ctti_size = 8 in the | |
511 | implementation below. */ | |
512 | dtd->dtd_data.ctti_size = roundup_nbytes ? (1 << ceil_log2 (roundup_nbytes)) | |
513 | : 0; | |
514 | ||
515 | /* Caller of this API must guarantee that a CTF type with id = ref already | |
516 | exists. This will also be validated for us at link-time. */ | |
517 | dtd->dtd_u.dtu_slice.cts_type = (uint32_t) ref; | |
518 | dtd->dtd_u.dtu_slice.cts_bits = bit_size; | |
519 | dtd->dtd_u.dtu_slice.cts_offset = bit_offset; | |
520 | ||
521 | ctfc->ctfc_num_stypes++; | |
522 | ||
523 | return type; | |
524 | } | |
525 | ||
526 | ctf_id_t | |
527 | ctf_add_float (ctf_container_ref ctfc, uint32_t flag, | |
528 | const char * name, const ctf_encoding_t * ep, dw_die_ref die) | |
529 | { | |
530 | return (ctf_add_encoded (ctfc, flag, name, ep, CTF_K_FLOAT, die)); | |
531 | } | |
532 | ||
533 | ctf_id_t | |
534 | ctf_add_integer (ctf_container_ref ctfc, uint32_t flag, | |
535 | const char * name, const ctf_encoding_t * ep, dw_die_ref die) | |
536 | { | |
537 | return (ctf_add_encoded (ctfc, flag, name, ep, CTF_K_INTEGER, die)); | |
538 | } | |
539 | ||
540 | ctf_id_t | |
541 | ctf_add_unknown (ctf_container_ref ctfc, uint32_t flag, | |
542 | const char * name, const ctf_encoding_t * ep, dw_die_ref die) | |
543 | { | |
544 | return (ctf_add_encoded (ctfc, flag, name, ep, CTF_K_UNKNOWN, die)); | |
545 | } | |
546 | ||
547 | ctf_id_t | |
548 | ctf_add_pointer (ctf_container_ref ctfc, uint32_t flag, ctf_id_t ref, | |
549 | dw_die_ref die) | |
550 | { | |
551 | return (ctf_add_reftype (ctfc, flag, ref, CTF_K_POINTER, die)); | |
552 | } | |
553 | ||
554 | ctf_id_t | |
555 | ctf_add_array (ctf_container_ref ctfc, uint32_t flag, const ctf_arinfo_t * arp, | |
556 | dw_die_ref die) | |
557 | { | |
558 | ctf_dtdef_ref dtd; | |
559 | ctf_id_t type; | |
560 | ||
561 | gcc_assert (arp); | |
562 | ||
563 | /* Caller of this API must make sure CTF type for arp->ctr_contents and | |
564 | arp->ctr_index are already added. This will also be validated for us at | |
565 | link-time. */ | |
566 | ||
567 | type = ctf_add_generic (ctfc, flag, NULL, &dtd, die); | |
568 | ||
569 | dtd->dtd_data.ctti_info = CTF_TYPE_INFO (CTF_K_ARRAY, flag, 0); | |
570 | dtd->dtd_data.ctti_size = 0; | |
571 | dtd->dtd_u.dtu_arr = *arp; | |
572 | ||
573 | ctfc->ctfc_num_stypes++; | |
574 | ||
575 | return type; | |
576 | } | |
577 | ||
578 | ctf_id_t | |
579 | ctf_add_enum (ctf_container_ref ctfc, uint32_t flag, const char * name, | |
580 | HOST_WIDE_INT size, dw_die_ref die) | |
581 | { | |
582 | ctf_dtdef_ref dtd; | |
583 | ctf_id_t type; | |
584 | ||
585 | /* In the compiler, no need to handle the case of promoting forwards to | |
586 | enums. This comment is simply to note a divergence from libctf. */ | |
587 | ||
588 | /* The compiler does, however, update any previously existing forward types | |
589 | to non-root. CTF does not allow existence of two root types with the same | |
590 | name. */ | |
591 | ctf_dtdef_ref enum_fwd_type = ctf_dtd_lookup (ctfc, die); | |
592 | if (enum_fwd_type) | |
593 | { | |
594 | enum_fwd_type->dtd_data.ctti_info | |
595 | = CTF_TYPE_INFO (CTF_K_FORWARD, CTF_ADD_NONROOT, 0); | |
596 | } | |
597 | ||
598 | type = ctf_add_generic (ctfc, flag, name, &dtd, die); | |
599 | ||
600 | dtd->dtd_data.ctti_info = CTF_TYPE_INFO (CTF_K_ENUM, flag, 0); | |
601 | ||
602 | /* Size in bytes should always fit, of course. | |
603 | TBD WARN - warn instead? */ | |
604 | gcc_assert (size <= CTF_MAX_SIZE); | |
605 | ||
606 | dtd->dtd_data.ctti_size = size; | |
607 | ||
608 | ctfc->ctfc_num_stypes++; | |
609 | ||
610 | return type; | |
611 | } | |
612 | ||
613 | int | |
614 | ctf_add_enumerator (ctf_container_ref ctfc, ctf_id_t enid, const char * name, | |
615 | HOST_WIDE_INT value, dw_die_ref die) | |
616 | { | |
617 | ctf_dmdef_t * dmd; | |
618 | uint32_t kind, vlen, root; | |
619 | ||
620 | /* Callers of this API must make sure that CTF_K_ENUM with enid has been | |
621 | addded. This will also be validated for us at link-time. */ | |
622 | ctf_dtdef_ref dtd = ctf_dtd_lookup (ctfc, die); | |
623 | gcc_assert (dtd); | |
624 | gcc_assert (dtd->dtd_type == enid); | |
625 | gcc_assert (name); | |
626 | ||
627 | kind = CTF_V2_INFO_KIND (dtd->dtd_data.ctti_info); | |
628 | root = CTF_V2_INFO_ISROOT (dtd->dtd_data.ctti_info); | |
629 | vlen = CTF_V2_INFO_VLEN (dtd->dtd_data.ctti_info); | |
630 | ||
631 | gcc_assert (kind == CTF_K_ENUM && vlen < CTF_MAX_VLEN); | |
632 | ||
633 | /* Enum value is of type HOST_WIDE_INT in the compiler, dmd_value is int32_t | |
634 | on the other hand. Check bounds and skip adding this enum value if out of | |
635 | bounds. */ | |
636 | if ((value > INT_MAX) || (value < INT_MIN)) | |
637 | { | |
638 | /* FIXME - Note this TBD_CTF_REPRESENTATION_LIMIT. */ | |
639 | return (1); | |
640 | } | |
641 | ||
642 | dmd = ggc_cleared_alloc<ctf_dmdef_t> (); | |
643 | ||
644 | /* Buffer the strings in the CTF string table. */ | |
645 | dmd->dmd_name = ctf_add_string (ctfc, name, &(dmd->dmd_name_offset)); | |
646 | dmd->dmd_type = CTF_NULL_TYPEID; | |
647 | dmd->dmd_offset = 0; | |
648 | ||
649 | dmd->dmd_value = value; | |
650 | ||
651 | dtd->dtd_data.ctti_info = CTF_TYPE_INFO (kind, root, vlen + 1); | |
652 | ctf_dmd_list_append (&dtd->dtd_u.dtu_members, dmd); | |
653 | ||
654 | if ((name != NULL) && strcmp (name, "")) | |
655 | ctfc->ctfc_strlen += strlen (name) + 1; | |
656 | ||
657 | return (0); | |
658 | } | |
659 | ||
660 | int | |
661 | ctf_add_member_offset (ctf_container_ref ctfc, dw_die_ref sou, | |
662 | const char * name, ctf_id_t type, | |
663 | uint64_t bit_offset) | |
664 | { | |
665 | ctf_dtdef_ref dtd = ctf_dtd_lookup (ctfc, sou); | |
666 | ctf_dmdef_t * dmd; | |
667 | ||
668 | uint32_t kind, vlen, root; | |
669 | ||
670 | /* The type of the member being added must already exist. */ | |
671 | gcc_assert (dtd); | |
672 | ||
673 | kind = CTF_V2_INFO_KIND (dtd->dtd_data.ctti_info); | |
674 | root = CTF_V2_INFO_ISROOT (dtd->dtd_data.ctti_info); | |
675 | vlen = CTF_V2_INFO_VLEN (dtd->dtd_data.ctti_info); | |
676 | ||
677 | gcc_assert (kind == CTF_K_STRUCT || kind == CTF_K_UNION); | |
678 | gcc_assert (vlen < CTF_MAX_VLEN); | |
679 | ||
680 | dmd = ggc_cleared_alloc<ctf_dmdef_t> (); | |
681 | ||
682 | /* Buffer the strings in the CTF string table. */ | |
683 | dmd->dmd_name = ctf_add_string (ctfc, name, &(dmd->dmd_name_offset)); | |
684 | dmd->dmd_type = type; | |
685 | dmd->dmd_value = -1; | |
686 | ||
687 | if (kind == CTF_K_STRUCT && vlen != 0) | |
688 | dmd->dmd_offset = bit_offset; | |
689 | else | |
690 | dmd->dmd_offset = 0; | |
691 | ||
692 | dtd->dtd_data.ctti_info = CTF_TYPE_INFO (kind, root, vlen + 1); | |
693 | ctf_dmd_list_append (&dtd->dtd_u.dtu_members, dmd); | |
694 | ||
695 | if ((name != NULL) && strcmp (name, "")) | |
696 | ctfc->ctfc_strlen += strlen (name) + 1; | |
697 | ||
698 | return 0; | |
699 | } | |
700 | ||
701 | int | |
702 | ctf_add_variable (ctf_container_ref ctfc, const char * name, ctf_id_t ref, | |
d0b00e74 IB |
703 | dw_die_ref die, unsigned int external_vis, |
704 | dw_die_ref die_var_decl) | |
b7e215a8 | 705 | { |
d0b00e74 | 706 | ctf_dvdef_ref dvd, dvd_ignore; |
b7e215a8 IB |
707 | |
708 | gcc_assert (name); | |
709 | ||
710 | if (name != NULL) | |
711 | { | |
712 | dvd = ggc_cleared_alloc<ctf_dvdef_t> (); | |
713 | dvd->dvd_key = die; | |
714 | /* Buffer the strings in the CTF string table. */ | |
715 | dvd->dvd_name = ctf_add_string (ctfc, name, &(dvd->dvd_name_offset)); | |
716 | dvd->dvd_visibility = external_vis; | |
717 | dvd->dvd_type = ref; | |
d0b00e74 IB |
718 | |
719 | /* If DW_AT_specification attribute exists, keep track of it as this is | |
720 | the non-defining declaration corresponding to the variable. We will | |
721 | skip emitting CTF variable for such incomplete, non-defining | |
722 | declarations. | |
723 | There could be some non-defining declarations, however, for which a | |
724 | defining declaration does not show up in the same CU. For such | |
725 | cases, the compiler continues to emit CTF variable record as | |
726 | usual. */ | |
727 | if (die_var_decl) | |
728 | { | |
729 | dvd_ignore = ggc_cleared_alloc<ctf_dvdef_t> (); | |
730 | dvd_ignore->dvd_key = die_var_decl; | |
731 | /* It's alright to leave other fields as zero. No valid CTF | |
732 | variable will be added for these DW_TAG_variable DIEs. */ | |
733 | ctf_dvd_ignore_insert (ctfc, dvd_ignore); | |
734 | } | |
735 | ||
b7e215a8 IB |
736 | ctf_dvd_insert (ctfc, dvd); |
737 | ||
738 | if (strcmp (name, "")) | |
739 | ctfc->ctfc_strlen += strlen (name) + 1; | |
740 | } | |
741 | ||
742 | return 0; | |
743 | } | |
744 | ||
745 | int | |
746 | ctf_add_function_arg (ctf_container_ref ctfc, dw_die_ref func, | |
747 | const char * name, ctf_id_t type) | |
748 | { | |
749 | ctf_dtdef_ref dtd = ctf_dtd_lookup (ctfc, func); | |
750 | ctf_func_arg_t * farg; | |
751 | uint32_t vlen; | |
752 | ||
753 | /* The function to which argument is being added must already exist. */ | |
754 | gcc_assert (dtd); | |
755 | /* The number of args must have been non-zero. */ | |
756 | vlen = CTF_V2_INFO_VLEN (dtd->dtd_data.ctti_info); | |
757 | gcc_assert (vlen); | |
758 | ||
759 | farg = ggc_cleared_alloc<ctf_func_arg_t> (); | |
760 | ||
761 | /* Buffer the strings in the auxilliary string table. CTF V3 format does not | |
762 | require function argument names. Use auxilliary string table to keep | |
763 | these strings to avoid unnecessary bloat in CTF section in CTF V3. */ | |
764 | farg->farg_name = ctf_add_string (ctfc, name, &(farg->farg_name_offset), | |
765 | CTF_AUX_STRTAB); | |
766 | farg->farg_type = type; | |
767 | ||
768 | ctf_farg_list_append (&dtd->dtd_u.dtu_argv, farg); | |
769 | ||
770 | /* For aux_str, keep ctfc_aux_strlen updated for debugging. */ | |
771 | if ((name != NULL) && strcmp (name, "")) | |
772 | ctfc->ctfc_aux_strlen += strlen (name) + 1; | |
773 | ||
774 | return 0; | |
775 | } | |
776 | ||
777 | ctf_id_t | |
778 | ctf_add_function (ctf_container_ref ctfc, uint32_t flag, const char * name, | |
779 | const ctf_funcinfo_t * ctc, dw_die_ref die, | |
32566720 | 780 | bool from_global_func, int linkage) |
b7e215a8 IB |
781 | { |
782 | ctf_dtdef_ref dtd; | |
783 | ctf_id_t type; | |
784 | uint32_t vlen; | |
785 | ||
786 | gcc_assert (ctc); | |
787 | ||
788 | vlen = ctc->ctc_argc; | |
789 | gcc_assert (vlen <= CTF_MAX_VLEN); | |
790 | ||
791 | type = ctf_add_generic (ctfc, flag, name, &dtd, die); | |
792 | ||
793 | dtd->from_global_func = from_global_func; | |
32566720 | 794 | dtd->linkage = linkage; |
b7e215a8 IB |
795 | dtd->dtd_data.ctti_info = CTF_TYPE_INFO (CTF_K_FUNCTION, flag, vlen); |
796 | /* Caller must make sure CTF types for ctc->ctc_return are already added. */ | |
797 | dtd->dtd_data.ctti_type = (uint32_t) ctc->ctc_return; | |
798 | /* Caller must make sure CTF types for function arguments are already added | |
799 | via ctf_add_function_arg () API. */ | |
800 | ||
801 | ctfc->ctfc_num_stypes++; | |
802 | ||
803 | return type; | |
804 | } | |
805 | ||
806 | ctf_id_t | |
807 | ctf_add_sou (ctf_container_ref ctfc, uint32_t flag, const char * name, | |
808 | uint32_t kind, size_t size, dw_die_ref die) | |
809 | { | |
810 | ctf_dtdef_ref dtd; | |
811 | ctf_id_t type = 0; | |
812 | ||
813 | gcc_assert ((kind == CTF_K_STRUCT) || (kind == CTF_K_UNION)); | |
814 | ||
815 | /* In the compiler, no need to handle the case of promoting forwards to | |
816 | structs. This comment is simply to note a divergence from libctf. */ | |
817 | ||
818 | /* The compiler does, however, update any previously existing forward types | |
819 | to non-root. CTF does not allow existence of two root types with the same | |
820 | name. */ | |
821 | ctf_dtdef_ref sou_fwd_type = ctf_dtd_lookup (ctfc, die); | |
822 | if (sou_fwd_type) | |
823 | { | |
824 | sou_fwd_type->dtd_data.ctti_info | |
825 | = CTF_TYPE_INFO (CTF_K_FORWARD, CTF_ADD_NONROOT, 0); | |
826 | } | |
827 | ||
828 | type = ctf_add_generic (ctfc, flag, name, &dtd, die); | |
829 | ||
830 | dtd->dtd_data.ctti_info = CTF_TYPE_INFO (kind, flag, 0); | |
831 | ||
832 | if (size > CTF_MAX_SIZE) | |
833 | { | |
834 | dtd->dtd_data.ctti_size = CTF_LSIZE_SENT; | |
835 | dtd->dtd_data.ctti_lsizehi = CTF_SIZE_TO_LSIZE_HI (size); | |
836 | dtd->dtd_data.ctti_lsizelo = CTF_SIZE_TO_LSIZE_LO (size); | |
837 | ctfc->ctfc_num_types++; | |
838 | } | |
839 | else | |
840 | { | |
841 | dtd->dtd_data.ctti_size = (uint32_t) size; | |
842 | ctfc->ctfc_num_stypes++; | |
843 | } | |
844 | ||
845 | return type; | |
846 | } | |
847 | ||
5b723401 DF |
848 | /* Given a TREE_TYPE node, return the CTF type ID for that type. */ |
849 | ||
850 | ctf_id_t | |
851 | ctf_lookup_tree_type (ctf_container_ref ctfc, const tree type) | |
852 | { | |
853 | dw_die_ref die = lookup_type_die (type); | |
854 | if (die == NULL) | |
855 | return CTF_NULL_TYPEID; | |
856 | ||
857 | ctf_dtdef_ref dtd = ctf_dtd_lookup (ctfc, die); | |
858 | if (dtd == NULL) | |
859 | return CTF_NULL_TYPEID; | |
860 | ||
861 | return dtd->dtd_type; | |
862 | } | |
863 | ||
b7e215a8 IB |
864 | /* Check if CTF for TYPE has already been generated. Mainstay for |
865 | de-duplication. If CTF type already exists, returns TRUE and updates | |
866 | the TYPE_ID for the caller. */ | |
867 | ||
868 | bool | |
869 | ctf_type_exists (ctf_container_ref ctfc, dw_die_ref type, | |
870 | ctf_id_t * type_id) | |
871 | { | |
872 | bool exists = false; | |
873 | ctf_dtdef_ref ctf_type_seen = ctf_dtd_lookup (ctfc, type); | |
874 | ||
875 | if (ctf_type_seen) | |
876 | { | |
877 | exists = true; | |
878 | /* CTF type for this type exists. */ | |
879 | *type_id = ctf_type_seen->dtd_type; | |
880 | } | |
881 | ||
882 | return exists; | |
883 | } | |
884 | ||
885 | /* Location information for CTF Types and CTF Variables. CTF section does not | |
886 | emit location information; at this time, location information is needed for | |
887 | BTF CO-RE use-cases. */ | |
888 | ||
889 | int | |
890 | ctfc_get_dtd_srcloc (ctf_dtdef_ref dtd, ctf_srcloc_ref loc) | |
891 | { | |
892 | loc->ctsloc_file = ctf_get_die_loc_file (dtd->dtd_key); | |
893 | loc->ctsloc_line = ctf_get_die_loc_line (dtd->dtd_key); | |
894 | loc->ctsloc_col = ctf_get_die_loc_col (dtd->dtd_key); | |
895 | ||
896 | if (loc->ctsloc_file == NULL) | |
897 | return 1; | |
898 | ||
899 | return 0; | |
900 | } | |
901 | ||
902 | int | |
903 | ctfc_get_dvd_srcloc (ctf_dvdef_ref dvd, ctf_srcloc_ref loc) | |
904 | { | |
905 | loc->ctsloc_file = ctf_get_die_loc_file (dvd->dvd_key); | |
906 | loc->ctsloc_line = ctf_get_die_loc_line (dvd->dvd_key); | |
907 | loc->ctsloc_col = ctf_get_die_loc_col (dvd->dvd_key); | |
908 | ||
909 | if (loc->ctsloc_file == NULL) | |
910 | return 1; | |
911 | ||
912 | return 0; | |
913 | } | |
914 | ||
915 | /* CTF container setup and teardown routines. */ | |
916 | ||
917 | /* Initialize the CTF string table. | |
918 | The first entry in the CTF string table (empty string) is added. */ | |
919 | ||
920 | static void | |
921 | init_ctf_strtable (ctf_strtable_t * strtab) | |
922 | { | |
923 | strtab->ctstab_head = NULL; | |
924 | strtab->ctstab_tail = NULL; | |
925 | strtab->ctstab_num = 0; | |
926 | strtab->ctstab_len = 0; | |
927 | ||
928 | /* The first entry in the CTF string table is an empty string. E.g., CTF | |
929 | type records with no name (like CTF_K_CONST, CTF_K_VOLATILE etc) point to | |
930 | this string. */ | |
931 | uint32_t estr_offset = 0; | |
932 | strtab->ctstab_estr = ctfc_strtable_add_str (strtab, "", &estr_offset); | |
933 | } | |
934 | ||
935 | /* Initialize the string tables in the CTF container. */ | |
936 | ||
937 | static void | |
938 | init_ctf_string_table (ctf_container_ref ctfc) | |
939 | { | |
940 | init_ctf_strtable (&ctfc->ctfc_strtable); | |
941 | ctfc->ctfc_strlen++; | |
942 | ||
943 | init_ctf_strtable (&ctfc->ctfc_aux_strtable); | |
944 | ctfc->ctfc_aux_strlen++; | |
945 | } | |
946 | ||
947 | /* Allocate a new CTF container with the desired flags. */ | |
948 | ||
949 | static inline ctf_container_ref | |
950 | new_ctf_container (void) | |
951 | { | |
952 | tu_ctfc = ggc_cleared_alloc<ctf_container_t> (); | |
953 | tu_ctfc->ctfc_types | |
954 | = hash_table<ctfc_dtd_hasher>::create_ggc (100); | |
955 | tu_ctfc->ctfc_vars | |
956 | = hash_table<ctfc_dvd_hasher>::create_ggc (100); | |
d0b00e74 IB |
957 | tu_ctfc->ctfc_ignore_vars |
958 | = hash_table<ctfc_dvd_hasher>::create_ggc (10); | |
b7e215a8 IB |
959 | |
960 | return tu_ctfc; | |
961 | } | |
962 | ||
963 | /* Initialize a CTF container per translation unit. */ | |
964 | ||
965 | static void | |
966 | init_ctf_container (void) | |
967 | { | |
968 | tu_ctfc = new_ctf_container (); | |
969 | ||
970 | tu_ctfc->ctfc_magic = CTF_MAGIC; | |
971 | tu_ctfc->ctfc_version = CTF_VERSION; | |
972 | tu_ctfc->ctfc_flags = CTF_F_NEWFUNCINFO; | |
973 | tu_ctfc->ctfc_nextid = CTF_INIT_TYPEID; | |
974 | ||
975 | init_ctf_string_table (tu_ctfc); | |
976 | } | |
977 | ||
978 | void | |
979 | ctfc_delete_strtab (ctf_strtable_t * strtab) | |
980 | { | |
981 | ctf_string_t * str = NULL; | |
982 | ctf_string_t * next_str = NULL; | |
983 | ||
984 | str = strtab->ctstab_head; | |
985 | next_str = str; | |
986 | while (next_str != NULL) | |
987 | { | |
988 | next_str = str->cts_next; | |
989 | ggc_free (str); | |
990 | str = next_str; | |
991 | } | |
992 | ||
993 | strtab->ctstab_head = NULL; | |
994 | strtab->ctstab_tail = NULL; | |
995 | strtab->ctstab_estr = NULL; | |
996 | } | |
997 | ||
998 | /* Delete the CTF container's resources. */ | |
999 | ||
1000 | void | |
1001 | ctfc_delete_container (ctf_container_ref ctfc) | |
1002 | { | |
b7e215a8 IB |
1003 | if (ctfc) |
1004 | { | |
1848fbf0 IB |
1005 | ctfc->ctfc_types->empty (); |
1006 | ctfc->ctfc_types = NULL; | |
1007 | ||
1008 | ctfc->ctfc_vars->empty (); | |
1009 | ctfc->ctfc_types = NULL; | |
1010 | ||
d0b00e74 IB |
1011 | ctfc->ctfc_ignore_vars->empty (); |
1012 | ctfc->ctfc_ignore_vars = NULL; | |
1013 | ||
b7e215a8 IB |
1014 | ctfc_delete_strtab (&ctfc->ctfc_strtable); |
1015 | ctfc_delete_strtab (&ctfc->ctfc_aux_strtable); | |
1016 | if (ctfc->ctfc_vars_list) | |
1017 | { | |
1018 | ggc_free (ctfc->ctfc_vars_list); | |
1019 | ctfc->ctfc_vars_list = NULL; | |
1020 | } | |
1021 | if (ctfc->ctfc_types_list) | |
1022 | { | |
1023 | ggc_free (ctfc->ctfc_types_list); | |
1024 | ctfc->ctfc_types_list = NULL; | |
1025 | } | |
1026 | if (ctfc->ctfc_gfuncs_list) | |
1027 | { | |
1028 | ggc_free (ctfc->ctfc_gfuncs_list); | |
1029 | ctfc->ctfc_gfuncs_list = NULL; | |
1030 | } | |
1031 | if (ctfc->ctfc_gobjts_list) | |
1032 | { | |
1033 | ggc_free (ctfc->ctfc_gobjts_list); | |
1034 | ctfc->ctfc_gobjts_list = NULL; | |
1035 | } | |
1036 | ||
1037 | ctfc= NULL; | |
1038 | } | |
1039 | } | |
1040 | ||
1041 | /* CTF routines interfacing to the compiler. */ | |
1042 | ||
1043 | void | |
1044 | ctf_init (void) | |
1045 | { | |
1046 | init_ctf_container (); | |
1047 | } |