aboutsummaryrefslogtreecommitdiff
path: root/gcc/dwarf2ctf.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/dwarf2ctf.c')
-rw-r--r--gcc/dwarf2ctf.c1018
1 files changed, 0 insertions, 1018 deletions
diff --git a/gcc/dwarf2ctf.c b/gcc/dwarf2ctf.c
deleted file mode 100644
index 747b2f6..0000000
--- a/gcc/dwarf2ctf.c
+++ /dev/null
@@ -1,1018 +0,0 @@
-/* Generate CTF types and objects from the GCC DWARF.
- Copyright (C) 2021-2022 Free Software Foundation, Inc.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 3, or (at your option) any later
-version.
-
-GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "target.h"
-#include "dwarf2out.h"
-#include "dwarf2out.h"
-
-#include "dwarf2ctf.h"
-#include "ctfc.h"
-
-/* Forward declarations for some routines defined in this file. */
-
-static ctf_id_t
-gen_ctf_type (ctf_container_ref, dw_die_ref);
-
-/* All the DIE structures we handle come from the DWARF information
- generated by GCC. However, there are three situations where we need
- to create our own created DIE structures because GCC doesn't
- provide them.
-
- The DWARF spec suggests using a DIE with DW_TAG_unspecified_type
- and name "void" in order to denote the void type. But GCC doesn't
- follow this advice. Still we need a DIE to act as a key for void
- types, we use ctf_void_die.
-
- Also, if a subrange type corresponding to an array index does not
- specify a type then we assume it is `int'.
-
- Finally, for types unrepresentable in CTF, we need a DIE to anchor
- them to a CTF type of kind unknown.
-
- The variables below are initialized in ctf_debug_init and hold
- references to the proper DIEs. */
-
-static GTY (()) dw_die_ref ctf_void_die;
-static GTY (()) dw_die_ref ctf_array_index_die;
-static GTY (()) dw_die_ref ctf_unknown_die;
-
-/* Some DIEs have a type description attribute, stored in a DW_AT_type
- attribute. However, GCC generates no attribute to signify a `void'
- type.
-
- This can happen in many contexts (return type of a function,
- pointed or qualified type, etc) so we use the `ctf_get_AT_type'
- function below abstracts this. */
-
-static dw_die_ref
-ctf_get_AT_type (dw_die_ref die)
-{
- dw_die_ref type_die = get_AT_ref (die, DW_AT_type);
- return (type_die ? type_die : ctf_void_die);
-}
-
-/* Some data member DIEs have location specified as a DWARF expression
- (specifically in DWARF2). Luckily, the expression is a simple
- DW_OP_plus_uconst with one operand set to zero.
-
- Sometimes the data member location may also be negative. In yet some other
- cases (specifically union data members), the data member location is
- non-existent. Handle all these scenarios here to abstract this. */
-
-static HOST_WIDE_INT
-ctf_get_AT_data_member_location (dw_die_ref die)
-{
- HOST_WIDE_INT field_location = 0;
- dw_attr_node * attr;
-
- /* The field location (in bits) can be determined from
- either a DW_AT_data_member_location attribute or a
- DW_AT_data_bit_offset attribute. */
- if (get_AT (die, DW_AT_data_bit_offset))
- field_location = get_AT_unsigned (die, DW_AT_data_bit_offset);
- else
- {
- attr = get_AT (die, DW_AT_data_member_location);
- if (attr && AT_class (attr) == dw_val_class_loc)
- {
- dw_loc_descr_ref descr = AT_loc (attr);
- /* Operand 2 must be zero; the structure is assumed to be on the
- stack in DWARF2. */
- gcc_assert (!descr->dw_loc_oprnd2.v.val_unsigned);
- gcc_assert (descr->dw_loc_oprnd2.val_class
- == dw_val_class_unsigned_const);
- field_location = descr->dw_loc_oprnd1.v.val_unsigned * 8;
- }
- else
- {
- attr = get_AT (die, DW_AT_data_member_location);
- if (attr && AT_class (attr) == dw_val_class_const)
- field_location = AT_int (attr) * 8;
- else
- field_location = (get_AT_unsigned (die,
- DW_AT_data_member_location)
- * 8);
- }
- }
-
- return field_location;
-}
-
-/* CTF Types' and CTF Variables' Location Information. CTF section does not
- emit location information, this is provided for BTF CO-RE use-cases. These
- functions fetch information from DWARF Die directly, as such the location
- information is not buffered in the CTF container. */
-
-const char *
-ctf_get_die_loc_file (dw_die_ref die)
-{
- if (!die)
- return NULL;
-
- struct dwarf_file_data * file;
- file = get_AT_file (die, DW_AT_decl_file);
- if (!file)
- return NULL;
-
- return file->filename;
-}
-
-unsigned int
-ctf_get_die_loc_line (dw_die_ref die)
-{
- if (!die)
- return 0;
-
- return get_AT_unsigned (die, DW_AT_decl_line);
-}
-
-unsigned int
-ctf_get_die_loc_col (dw_die_ref die)
-{
- if (!die)
- return 0;
-
- return get_AT_unsigned (die, DW_AT_decl_column);
-}
-
-/* Generate CTF for the void type. */
-
-static ctf_id_t
-gen_ctf_void_type (ctf_container_ref ctfc)
-{
- ctf_encoding_t ctf_encoding = {0, 0, 0};
-
- /* In CTF the void type is encoded as a 0-byte signed integer
- type. */
-
- ctf_encoding.cte_bits = 0;
- ctf_encoding.cte_format = CTF_INT_SIGNED;
-
- gcc_assert (ctf_void_die != NULL);
- return ctf_add_integer (ctfc, CTF_ADD_ROOT, "void",
- &ctf_encoding, ctf_void_die);
-}
-
-/* Generate CTF type of unknown kind. */
-
-static ctf_id_t
-gen_ctf_unknown_type (ctf_container_ref ctfc)
-{
- ctf_id_t unknown_type_id;
-
- /* In CTF, the unknown type is encoded as a 0 byte sized type with kind
- CTF_K_UNKNOWN. Create an encoding object merely to reuse the underlying
- ctf_add_encoded interface; the CTF encoding object is not 'used' any more
- than just the generation of size from. */
- ctf_encoding_t ctf_encoding = {0, 0, 0};
-
- gcc_assert (ctf_unknown_die != NULL);
- /* Type de-duplication. */
- if (!ctf_type_exists (ctfc, ctf_unknown_die, &unknown_type_id))
- unknown_type_id = ctf_add_unknown (ctfc, CTF_ADD_ROOT, "unknown",
- &ctf_encoding, ctf_unknown_die);
-
- return unknown_type_id;
-}
-
-/* Sizes of entities can be given in bytes or bits. This function
- abstracts this by returning the size in bits of the given entity.
- If no DW_AT_byte_size nor DW_AT_bit_size are defined, this function
- returns 0. */
-
-static uint32_t
-ctf_die_bitsize (dw_die_ref die)
-{
- dw_attr_node *attr_byte_size = get_AT (die, DW_AT_byte_size);
- dw_attr_node *attr_bit_size = get_AT (die, DW_AT_bit_size);
-
- if (attr_bit_size)
- return AT_unsigned (attr_bit_size);
- else if (attr_byte_size)
- return (AT_unsigned (attr_byte_size) * 8);
- else
- return 0;
-}
-
-/* Generate CTF for base type (integer, boolean, real, fixed point and complex).
- Important: the caller of this API must make sure that duplicate types are
- not added. */
-
-static ctf_id_t
-gen_ctf_base_type (ctf_container_ref ctfc, dw_die_ref type)
-{
- ctf_id_t type_id = CTF_NULL_TYPEID;
-
- ctf_encoding_t ctf_encoding = {0, 0, 0};
-
- unsigned int encoding = get_AT_unsigned (type, DW_AT_encoding);
- unsigned int bit_size = ctf_die_bitsize (type);
- const char * name_string = get_AT_string (type, DW_AT_name);
-
- switch (encoding)
- {
- case DW_ATE_void:
-
- ctf_encoding.cte_format = CTF_INT_SIGNED;
- ctf_encoding.cte_bits = 0;
-
- gcc_assert (name_string);
- type_id = ctf_add_integer (ctfc, CTF_ADD_ROOT, name_string,
- &ctf_encoding, type);
-
- break;
- case DW_ATE_boolean:
-
- ctf_encoding.cte_format = CTF_INT_BOOL;
- ctf_encoding.cte_bits = bit_size;
-
- gcc_assert (name_string);
- type_id = ctf_add_integer (ctfc, CTF_ADD_ROOT, name_string,
- &ctf_encoding, type);
- break;
- case DW_ATE_float:
- {
- unsigned int float_bit_size
- = tree_to_uhwi (TYPE_SIZE (float_type_node));
- unsigned int double_bit_size
- = tree_to_uhwi (TYPE_SIZE (double_type_node));
- unsigned int long_double_bit_size
- = tree_to_uhwi (TYPE_SIZE (long_double_type_node));
-
- if (bit_size == float_bit_size)
- ctf_encoding.cte_format = CTF_FP_SINGLE;
- else if (bit_size == double_bit_size)
- ctf_encoding.cte_format = CTF_FP_DOUBLE;
- else if (bit_size == long_double_bit_size)
- ctf_encoding.cte_format = CTF_FP_LDOUBLE;
- else
- /* CTF does not have representation for other types. Skip them. */
- break;
-
- ctf_encoding.cte_bits = bit_size;
- type_id = ctf_add_float (ctfc, CTF_ADD_ROOT, name_string,
- &ctf_encoding, type);
-
- break;
- }
- case DW_ATE_signed_char:
- /* FALLTHROUGH */
- case DW_ATE_unsigned_char:
- /* FALLTHROUGH */
- case DW_ATE_signed:
- /* FALLTHROUGH */
- case DW_ATE_unsigned:
-
- if (encoding == DW_ATE_signed_char
- || encoding == DW_ATE_unsigned_char)
- ctf_encoding.cte_format |= CTF_INT_CHAR;
-
- if (encoding == DW_ATE_signed
- || encoding == DW_ATE_signed_char)
- ctf_encoding.cte_format |= CTF_INT_SIGNED;
-
- ctf_encoding.cte_bits = bit_size;
- type_id = ctf_add_integer (ctfc, CTF_ADD_ROOT, name_string,
- &ctf_encoding, type);
- break;
-
- case DW_ATE_complex_float:
- {
- unsigned int float_bit_size
- = tree_to_uhwi (TYPE_SIZE (float_type_node));
- unsigned int double_bit_size
- = tree_to_uhwi (TYPE_SIZE (double_type_node));
- unsigned int long_double_bit_size
- = tree_to_uhwi (TYPE_SIZE (long_double_type_node));
-
- if (bit_size == float_bit_size * 2)
- ctf_encoding.cte_format = CTF_FP_CPLX;
- else if (bit_size == double_bit_size * 2)
- ctf_encoding.cte_format = CTF_FP_DCPLX;
- else if (bit_size == long_double_bit_size * 2)
- ctf_encoding.cte_format = CTF_FP_LDCPLX;
- else
- /* CTF does not have representation for other types. Skip them. */
- break;
-
- ctf_encoding.cte_bits = bit_size;
- type_id = ctf_add_float (ctfc, CTF_ADD_ROOT, name_string,
- &ctf_encoding, type);
- break;
- }
- default:
- /* Ignore. */
- break;
- }
-
- return type_id;
-}
-
-/* Generate CTF for a pointer type. */
-
-static ctf_id_t
-gen_ctf_pointer_type (ctf_container_ref ctfc, dw_die_ref ptr_type)
-{
- ctf_id_t type_id = CTF_NULL_TYPEID;
- ctf_id_t ptr_type_id = CTF_NULL_TYPEID;
- dw_die_ref pointed_type_die = ctf_get_AT_type (ptr_type);
-
- type_id = gen_ctf_type (ctfc, pointed_type_die);
-
- /* Type de-duplication.
- Consult the ctfc_types hash again before adding the CTF pointer type
- because there can be cases where a pointer type may have been added by
- the gen_ctf_type call above. */
- if (ctf_type_exists (ctfc, ptr_type, &ptr_type_id))
- return ptr_type_id;
-
- ptr_type_id = ctf_add_pointer (ctfc, CTF_ADD_ROOT, type_id, ptr_type);
- return ptr_type_id;
-}
-
-/* Generate CTF for an array type. */
-
-static ctf_id_t
-gen_ctf_array_type (ctf_container_ref ctfc, dw_die_ref array_type)
-{
- dw_die_ref c;
- ctf_id_t array_elems_type_id = CTF_NULL_TYPEID;
-
- int vector_type_p = get_AT_flag (array_type, DW_AT_GNU_vector);
- if (vector_type_p)
- return array_elems_type_id;
-
- dw_die_ref array_elems_type = ctf_get_AT_type (array_type);
-
- /* First, register the type of the array elements if needed. */
- array_elems_type_id = gen_ctf_type (ctfc, array_elems_type);
-
- /* DWARF array types pretend C supports multi-dimensional arrays.
- So for the type int[N][M], the array type DIE contains two
- subrange_type children, the first with upper bound N-1 and the
- second with upper bound M-1.
-
- CTF, on the other hand, just encodes each array type in its own
- array type CTF struct. Therefore we have to iterate on the
- children and create all the needed types. */
-
- c = dw_get_die_child (array_type);
- gcc_assert (c);
- do
- {
- ctf_arinfo_t arinfo;
- dw_die_ref array_index_type;
- uint32_t array_num_elements;
-
- c = dw_get_die_sib (c);
-
- if (dw_get_die_tag (c) == DW_TAG_subrange_type)
- {
- dw_attr_node *upper_bound_at;
-
- array_index_type = ctf_get_AT_type (c);
-
- /* When DW_AT_upper_bound is used to specify the size of an
- array in DWARF, it is usually an unsigned constant
- specifying the upper bound index of the array. However,
- for unsized arrays, such as foo[] or bar[0],
- DW_AT_upper_bound is a signed integer constant
- instead. */
-
- upper_bound_at = get_AT (c, DW_AT_upper_bound);
- if (upper_bound_at
- && AT_class (upper_bound_at) == dw_val_class_unsigned_const)
- /* This is the upper bound index. */
- array_num_elements = get_AT_unsigned (c, DW_AT_upper_bound) + 1;
- else if (get_AT (c, DW_AT_count))
- array_num_elements = get_AT_unsigned (c, DW_AT_count);
- else
- {
- /* This is a VLA of some kind. */
- array_num_elements = 0;
- }
- }
- else if (dw_get_die_tag (c) == DW_TAG_enumeration_type)
- {
- array_index_type = 0;
- array_num_elements = 0;
- /* XXX writeme. */
- gcc_assert (1);
- }
- else
- gcc_unreachable ();
-
- /* Ok, mount and register the array type. Note how the array
- type we register here is the type of the elements in
- subsequent "dimensions", if there are any. */
-
- arinfo.ctr_nelems = array_num_elements;
- if (array_index_type)
- arinfo.ctr_index = gen_ctf_type (ctfc, array_index_type);
- else
- arinfo.ctr_index = gen_ctf_type (ctfc, ctf_array_index_die);
-
- arinfo.ctr_contents = array_elems_type_id;
- if (!ctf_type_exists (ctfc, c, &array_elems_type_id))
- array_elems_type_id = ctf_add_array (ctfc, CTF_ADD_ROOT, &arinfo,
- c);
- }
- while (c != dw_get_die_child (array_type));
-
-#if 0
- /* Type de-duplication.
- Consult the ctfc_types hash again before adding the CTF array type because
- there can be cases where an array_type type may have been added by the
- gen_ctf_type call above. */
- if (!ctf_type_exists (ctfc, array_type, &type_id))
- type_id = ctf_add_array (ctfc, CTF_ADD_ROOT, &arinfo, array_type);
-#endif
-
- return array_elems_type_id;
-}
-
-/* Generate CTF for a typedef. */
-
-static ctf_id_t
-gen_ctf_typedef (ctf_container_ref ctfc, dw_die_ref tdef)
-{
- ctf_id_t tdef_type_id, tid;
- const char *tdef_name = get_AT_string (tdef, DW_AT_name);
- dw_die_ref tdef_type = ctf_get_AT_type (tdef);
-
- tid = gen_ctf_type (ctfc, tdef_type);
-
- /* Type de-duplication.
- This is necessary because the ctf for the typedef may have been already
- added due to the gen_ctf_type call above. */
- if (!ctf_type_exists (ctfc, tdef, &tdef_type_id))
- {
- tdef_type_id = ctf_add_typedef (ctfc, CTF_ADD_ROOT,
- tdef_name,
- tid,
- tdef);
- }
- return tdef_type_id;
-}
-
-/* Generate CTF for a type modifier.
-
- If the given DIE contains a valid C modifier (like _Atomic), which is not
- supported by CTF, then this function skips the modifier die and continues
- with the underlying type.
-
- For all other cases, this function returns a CTF_NULL_TYPEID;
-*/
-
-static ctf_id_t
-gen_ctf_modifier_type (ctf_container_ref ctfc, dw_die_ref modifier)
-{
- uint32_t kind = CTF_K_MAX;
- ctf_id_t modifier_type_id, qual_type_id;
- dw_die_ref qual_type = ctf_get_AT_type (modifier);
-
- switch (dw_get_die_tag (modifier))
- {
- case DW_TAG_const_type: kind = CTF_K_CONST; break;
- case DW_TAG_volatile_type: kind = CTF_K_VOLATILE; break;
- case DW_TAG_restrict_type: kind = CTF_K_RESTRICT; break;
- case DW_TAG_atomic_type: break;
- default:
- return CTF_NULL_TYPEID;
- }
-
- /* Register the type for which this modifier applies. */
- qual_type_id = gen_ctf_type (ctfc, qual_type);
-
- /* Skip generating a CTF modifier record for _Atomic as there is no
- representation for it. */
- if (dw_get_die_tag (modifier) == DW_TAG_atomic_type)
- return qual_type_id;
-
- gcc_assert (kind != CTF_K_MAX);
- /* Now register the modifier itself. */
- if (!ctf_type_exists (ctfc, modifier, &modifier_type_id))
- modifier_type_id = ctf_add_reftype (ctfc, CTF_ADD_ROOT,
- qual_type_id, kind,
- modifier);
-
- return modifier_type_id;
-}
-
-/* Generate CTF for a struct type. */
-
-static ctf_id_t
-gen_ctf_sou_type (ctf_container_ref ctfc, dw_die_ref sou, uint32_t kind)
-{
- uint32_t bit_size = ctf_die_bitsize (sou);
- int declaration_p = get_AT_flag (sou, DW_AT_declaration);
- const char *sou_name = get_AT_string (sou, DW_AT_name);
-
- ctf_id_t sou_type_id;
-
- /* An incomplete structure or union type is represented in DWARF by
- a structure or union DIE that does not have a size attribute and
- that has a DW_AT_declaration attribute. This corresponds to a
- CTF forward type with kind CTF_K_STRUCT. */
- if (bit_size == 0 && declaration_p)
- return ctf_add_forward (ctfc, CTF_ADD_ROOT,
- sou_name, kind, sou);
-
- /* This is a complete struct or union type. Generate a CTF type for
- it if it doesn't exist already. */
- if (!ctf_type_exists (ctfc, sou, &sou_type_id))
- sou_type_id = ctf_add_sou (ctfc, CTF_ADD_ROOT,
- sou_name, kind, bit_size / 8,
- sou);
-
- /* Now process the struct members. */
- {
- dw_die_ref c;
-
- c = dw_get_die_child (sou);
- if (c)
- do
- {
- const char *field_name;
- dw_die_ref field_type;
- HOST_WIDE_INT field_location;
- ctf_id_t field_type_id;
-
- c = dw_get_die_sib (c);
-
- field_name = get_AT_string (c, DW_AT_name);
- field_type = ctf_get_AT_type (c);
- field_location = ctf_get_AT_data_member_location (c);
-
- /* Generate the field type. */
- field_type_id = gen_ctf_type (ctfc, field_type);
-
- /* If this is a bit-field, then wrap the field type
- generated above with a CTF slice. */
- if (get_AT (c, DW_AT_bit_offset)
- || get_AT (c, DW_AT_data_bit_offset))
- {
- dw_attr_node *attr;
- HOST_WIDE_INT bitpos = 0;
- HOST_WIDE_INT bitsize = ctf_die_bitsize (c);
- HOST_WIDE_INT bit_offset;
-
- /* The bit offset is given in bits and it may be
- negative. */
- attr = get_AT (c, DW_AT_bit_offset);
- if (attr)
- {
- if (AT_class (attr) == dw_val_class_unsigned_const)
- bit_offset = AT_unsigned (attr);
- else
- bit_offset = AT_int (attr);
-
- if (BYTES_BIG_ENDIAN)
- bitpos = field_location + bit_offset;
- else
- {
- HOST_WIDE_INT bit_size;
-
- attr = get_AT (c, DW_AT_byte_size);
- if (attr)
- /* Explicit size given in bytes. */
- bit_size = AT_unsigned (attr) * 8;
- else
- /* Infer the size from the member type. */
- bit_size = ctf_die_bitsize (field_type);
-
- bitpos = (field_location
- + bit_size
- - bit_offset
- - bitsize);
- }
- }
-
- /* In DWARF5 a data_bit_offset attribute is given with
- the offset of the data from the beginning of the
- struct. Acknowledge it if present. */
- attr = get_AT (c, DW_AT_data_bit_offset);
- if (attr)
- bitpos += AT_unsigned (attr);
-
- field_type_id = ctf_add_slice (ctfc, CTF_ADD_NONROOT,
- field_type_id,
- bitpos - field_location,
- bitsize,
- c);
- }
-
- /* Add the field type to the struct or union type. */
- ctf_add_member_offset (ctfc, sou,
- field_name,
- field_type_id,
- field_location);
- }
- while (c != dw_get_die_child (sou));
- }
-
- return sou_type_id;
-}
-
-/* Generate CTF for a function type. */
-
-static ctf_id_t
-gen_ctf_function_type (ctf_container_ref ctfc, dw_die_ref function,
- bool from_global_func)
-{
- const char *function_name = get_AT_string (function, DW_AT_name);
- dw_die_ref return_type = ctf_get_AT_type (function);
-
- ctf_funcinfo_t func_info;
- uint32_t num_args = 0;
-
- ctf_id_t return_type_id;
- ctf_id_t function_type_id;
-
- /* First, add the return type. */
- return_type_id = gen_ctf_type (ctfc, return_type);
- func_info.ctc_return = return_type_id;
-
- /* Type de-duplication.
- Consult the ctfc_types hash before adding the CTF function type. */
- if (ctf_type_exists (ctfc, function, &function_type_id))
- return function_type_id;
-
- /* Do a first pass on the formals to determine the number of
- arguments, and whether the function type gets a varargs. */
- {
- dw_die_ref c;
-
- c = dw_get_die_child (function);
- if (c)
- do
- {
- c = dw_get_die_sib (c);
-
- if (dw_get_die_tag (c) == DW_TAG_formal_parameter)
- num_args += 1;
- else if (dw_get_die_tag (c) == DW_TAG_unspecified_parameters)
- {
- func_info.ctc_flags |= CTF_FUNC_VARARG;
- num_args += 1;
- }
- }
- while (c != dw_get_die_child (function));
- }
-
- /* Note the number of typed arguments _includes_ the vararg. */
- func_info.ctc_argc = num_args;
-
- /* Type de-duplication has already been performed by now. */
- function_type_id = ctf_add_function (ctfc, CTF_ADD_ROOT,
- function_name,
- (const ctf_funcinfo_t *)&func_info,
- function,
- from_global_func);
-
- /* Second pass on formals: generate the CTF types corresponding to
- them and add them as CTF function args. */
- {
- dw_die_ref c;
- unsigned int i = 0;
- const char *arg_name;
- ctf_id_t arg_type;
-
- c = dw_get_die_child (function);
- if (c)
- do
- {
- c = dw_get_die_sib (c);
-
- if (dw_get_die_tag (c) == DW_TAG_unspecified_parameters)
- {
- gcc_assert (i == num_args - 1);
- /* Add an argument with type 0 and no name. */
- ctf_add_function_arg (ctfc, function, "", 0);
- }
- else if (dw_get_die_tag (c) == DW_TAG_formal_parameter)
- {
- i++;
- arg_name = get_AT_string (c, DW_AT_name);
- arg_type = gen_ctf_type (ctfc, ctf_get_AT_type (c));
- /* Add the argument to the existing CTF function type. */
- ctf_add_function_arg (ctfc, function, arg_name, arg_type);
- }
- else
- /* This is a local variable. Ignore. */
- continue;
- }
- while (c != dw_get_die_child (function));
- }
-
- return function_type_id;
-}
-
-/* Generate CTF for an enumeration type. */
-
-static ctf_id_t
-gen_ctf_enumeration_type (ctf_container_ref ctfc, dw_die_ref enumeration)
-{
- const char *enum_name = get_AT_string (enumeration, DW_AT_name);
- unsigned int bit_size = ctf_die_bitsize (enumeration);
- int declaration_p = get_AT_flag (enumeration, DW_AT_declaration);
-
- ctf_id_t enumeration_type_id;
-
- /* If this is an incomplete enum, generate a CTF forward for it and
- be done. */
- if (declaration_p)
- {
- gcc_assert (enum_name);
- return ctf_add_forward (ctfc, CTF_ADD_ROOT, enum_name,
- CTF_K_ENUM, enumeration);
- }
-
- /* If the size the enumerators is not specified then use the size of
- the underlying type, which must be a base type. */
- if (bit_size == 0)
- {
- dw_die_ref type = ctf_get_AT_type (enumeration);
- bit_size = ctf_die_bitsize (type);
- }
-
- /* Generate a CTF type for the enumeration. */
- enumeration_type_id = ctf_add_enum (ctfc, CTF_ADD_ROOT,
- enum_name, bit_size / 8, enumeration);
-
- /* Process the enumerators. */
- {
- dw_die_ref c;
-
- c = dw_get_die_child (enumeration);
- if (c)
- do
- {
- const char *enumerator_name;
- dw_attr_node *enumerator_value;
- HOST_WIDE_INT value_wide_int;
-
- c = dw_get_die_sib (c);
-
- enumerator_name = get_AT_string (c, DW_AT_name);
- enumerator_value = get_AT (c, DW_AT_const_value);
-
- /* enumerator_value can be either a signed or an unsigned
- constant value. */
- if (AT_class (enumerator_value) == dw_val_class_unsigned_const
- || (AT_class (enumerator_value)
- == dw_val_class_unsigned_const_implicit))
- value_wide_int = AT_unsigned (enumerator_value);
- else
- value_wide_int = AT_int (enumerator_value);
-
- ctf_add_enumerator (ctfc, enumeration_type_id,
- enumerator_name, value_wide_int, enumeration);
- }
- while (c != dw_get_die_child (enumeration));
- }
-
- return enumeration_type_id;
-}
-
-/* Add a CTF variable record for the given input DWARF DIE. */
-
-static void
-gen_ctf_variable (ctf_container_ref ctfc, dw_die_ref die)
-{
- const char *var_name = get_AT_string (die, DW_AT_name);
- dw_die_ref var_type = ctf_get_AT_type (die);
- unsigned int external_vis = get_AT_flag (die, DW_AT_external);
- ctf_id_t var_type_id;
-
- /* Avoid duplicates. */
- if (ctf_dvd_lookup (ctfc, die))
- return;
-
- /* Add the type of the variable. */
- var_type_id = gen_ctf_type (ctfc, var_type);
-
- /* Generate the new CTF variable and update global counter. */
- (void) ctf_add_variable (ctfc, var_name, var_type_id, die, external_vis);
- ctfc->ctfc_num_global_objts += 1;
-}
-
-/* Add a CTF function record for the given input DWARF DIE. */
-
-static void
-gen_ctf_function (ctf_container_ref ctfc, dw_die_ref die)
-{
- ctf_id_t function_type_id;
- /* Type de-duplication.
- Consult the ctfc_types hash before adding the CTF function type. */
- if (ctf_type_exists (ctfc, die, &function_type_id))
- return;
-
- /* Add the type of the function and update the global functions
- counter. Note that DWARF encodes function types in both
- DW_TAG_subroutine_type and DW_TAG_subprogram in exactly the same
- way. */
- (void) gen_ctf_function_type (ctfc, die, true /* from_global_func */);
- ctfc->ctfc_num_global_funcs += 1;
-}
-
-/* Add CTF type record(s) for the given input DWARF DIE and return its type id.
-
- If there is already a CTF type corresponding to the given DIE, then
- this function returns the type id of the existing type.
-
- If the given DIE is not recognized as a type, then this function
- returns CTF_NULL_TYPEID. */
-
-static ctf_id_t
-gen_ctf_type (ctf_container_ref ctfc, dw_die_ref die)
-{
- ctf_id_t type_id;
- int unrecog_die = false;
-
- if (ctf_type_exists (ctfc, die, &type_id))
- return type_id;
-
- switch (dw_get_die_tag (die))
- {
- case DW_TAG_base_type:
- type_id = gen_ctf_base_type (ctfc, die);
- break;
- case DW_TAG_pointer_type:
- type_id = gen_ctf_pointer_type (ctfc, die);
- break;
- case DW_TAG_typedef:
- type_id = gen_ctf_typedef (ctfc, die);
- break;
- case DW_TAG_array_type:
- type_id = gen_ctf_array_type (ctfc, die);
- break;
- case DW_TAG_structure_type:
- type_id = gen_ctf_sou_type (ctfc, die, CTF_K_STRUCT);
- break;
- case DW_TAG_union_type:
- type_id = gen_ctf_sou_type (ctfc, die, CTF_K_UNION);
- break;
- case DW_TAG_subroutine_type:
- type_id = gen_ctf_function_type (ctfc, die,
- false /* from_global_func */);
- break;
- case DW_TAG_enumeration_type:
- type_id = gen_ctf_enumeration_type (ctfc, die);
- break;
- case DW_TAG_atomic_type:
- /* FALLTHROUGH */
- case DW_TAG_const_type:
- /* FALLTHROUGH */
- case DW_TAG_restrict_type:
- /* FALLTHROUGH */
- case DW_TAG_volatile_type:
- type_id = gen_ctf_modifier_type (ctfc, die);
- break;
- case DW_TAG_unspecified_type:
- {
- const char *name = get_AT_string (die, DW_AT_name);
-
- if (name && strcmp (name, "void") == 0)
- type_id = gen_ctf_void_type (ctfc);
- else
- type_id = CTF_NULL_TYPEID;
-
- break;
- }
- case DW_TAG_reference_type:
- type_id = CTF_NULL_TYPEID;
- break;
- default:
- /* Unrecognized DIE. */
- unrecog_die = true;
- type_id = CTF_NULL_TYPEID;
- break;
- }
-
- /* For all types unrepresented in CTF, use an explicit CTF type of kind
- CTF_K_UNKNOWN. */
- if ((type_id == CTF_NULL_TYPEID) && (!unrecog_die))
- type_id = gen_ctf_unknown_type (ctfc);
-
- return type_id;
-}
-
-/* Prepare for output and write out the CTF debug information. */
-
-static void
-ctf_debug_finalize (const char *filename, bool btf)
-{
- if (btf)
- {
- btf_output (filename);
- btf_finalize ();
- }
-
- else
- {
- /* Emit the collected CTF information. */
- ctf_output (filename);
-
- /* Reset the CTF state. */
- ctf_finalize ();
- }
-}
-
-bool
-ctf_do_die (dw_die_ref die)
-{
- ctf_container_ref tu_ctfc = ctf_get_tu_ctfc ();
-
- /* Note how we tell the caller to continue traversing children DIEs
- if this DIE didn't result in CTF records being added. */
- if (dw_get_die_tag (die) == DW_TAG_variable)
- {
- gen_ctf_variable (tu_ctfc, die);
- return false;
- }
- else if (dw_get_die_tag (die) == DW_TAG_subprogram)
- {
- gen_ctf_function (tu_ctfc, die);
- return false;
- }
- else
- return gen_ctf_type (tu_ctfc, die) == CTF_NULL_TYPEID;
-}
-
-/* Initialize CTF subsystem for CTF debug info generation. */
-
-void
-ctf_debug_init (void)
-{
- /* First, initialize the CTF subsystem. */
- ctf_init ();
-
- /* Create a couple of DIE structures that we may need. */
- ctf_void_die = new_die_raw (DW_TAG_unspecified_type);
- add_name_attribute (ctf_void_die, "void");
- ctf_array_index_die
- = base_type_die (integer_type_node, 0 /* reverse */);
- add_name_attribute (ctf_array_index_die, "int");
- ctf_unknown_die = new_die_raw (DW_TAG_unspecified_type);
- add_name_attribute (ctf_unknown_die, "unknown");
-}
-
-/* Preprocess the CTF debug information after initialization. */
-
-void
-ctf_debug_init_postprocess (bool btf)
-{
- /* Only BTF requires postprocessing right after init. */
- if (btf)
- btf_init_postprocess ();
-}
-
-/* Early finish CTF/BTF debug info. */
-
-void
-ctf_debug_early_finish (const char * filename)
-{
- /* Emit CTF debug info early always. */
- if (ctf_debug_info_level > CTFINFO_LEVEL_NONE
- /* Emit BTF debug info early if CO-RE relocations are not
- required. */
- || (btf_debuginfo_p () && !btf_with_core_debuginfo_p ()))
- ctf_debug_finalize (filename, btf_debuginfo_p ());
-}
-
-/* Finish CTF/BTF debug info emission. */
-
-void
-ctf_debug_finish (const char * filename)
-{
- /* Emit BTF debug info here when CO-RE relocations need to be generated.
- BTF with CO-RE relocations needs to be generated when CO-RE is in effect
- for the BPF target. */
- if (btf_with_core_debuginfo_p ())
- {
- gcc_assert (btf_debuginfo_p ());
- ctf_debug_finalize (filename, btf_debuginfo_p ());
- }
-}
-
-#include "gt-dwarf2ctf.h"