On 3/5/24 00:47, Indu Bhagat wrote:
> From: Cupertino Miranda <cupertino.mira...@oracle.com>
>
> [Changes from V2]
> - Fixed aarch64 new FAILs reported by Linaro CI.
> - Fixed typos and other nits pointed out in V2.
> [End of changes from V2]
OK, thanks.
>
> PR debug/114186
>
> DWARF DIEs of type DW_TAG_subrange_type are linked together to represent
> the information about the subsequent dimensions. The CTF processing was
> so far working through them in the opposite (incorrect) order.
>
> While fixing the issue, refactor the code a bit for readability.
>
> co-authored-By: Indu Bhagat <indu.bha...@oracle.com>
>
> gcc/
> PR debug/114186
> * dwarf2ctf.cc (gen_ctf_array_type): Invoke the ctf_add_array ()
> in the correct order of the dimensions.
> (gen_ctf_subrange_type): Refactor out handling of
> DW_TAG_subrange_type DIE to here.
>
> gcc/testsuite/
> PR debug/114186
> * gcc.dg/debug/ctf/ctf-array-6.c: Add test.
> ---
>
> Testing notes:
> - Linaro CI reported three new FAILs introduced by ctf-array-6.c due to
> presence of char '#' on aarch64 where the ASM_COMMENT_START differs.
> Fixed and regression tested on aarch64.
> - Regression tested on x86_64-linux-gnu default target.
> - Regression tested for target bpf-unknown-none (btf.exp, ctf.exp, bpf.exp).
> - Kernel build with -gctf shows healthier CTF types for arrays.
>
> ---
> gcc/dwarf2ctf.cc | 158 +++++++++----------
> gcc/testsuite/gcc.dg/debug/ctf/ctf-array-6.c | 14 ++
> 2 files changed, 89 insertions(+), 83 deletions(-)
> create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-array-6.c
>
> diff --git a/gcc/dwarf2ctf.cc b/gcc/dwarf2ctf.cc
> index dca86edfffa9..77d6bf896893 100644
> --- a/gcc/dwarf2ctf.cc
> +++ b/gcc/dwarf2ctf.cc
> @@ -349,105 +349,97 @@ gen_ctf_pointer_type (ctf_container_ref ctfc,
> dw_die_ref ptr_type)
> return ptr_type_id;
> }
>
> -/* Generate CTF for an array type. */
> +/* Recursively generate CTF for array dimensions starting at DIE C (of type
> + DW_TAG_subrange_type) until DIE LAST (of type DW_TAG_subrange_type) is
> + reached. ARRAY_ELEMS_TYPE_ID is base type for the array. */
>
> static ctf_id_t
> -gen_ctf_array_type (ctf_container_ref ctfc, dw_die_ref array_type)
> +gen_ctf_subrange_type (ctf_container_ref ctfc, ctf_id_t array_elems_type_id,
> + dw_die_ref c, dw_die_ref last)
> {
> - dw_die_ref c;
> - ctf_id_t array_elems_type_id = CTF_NULL_TYPEID;
> + ctf_arinfo_t arinfo;
> + ctf_id_t array_node_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_attr_node *upper_bound_at;
> + dw_die_ref array_index_type;
> + uint32_t array_num_elements;
>
> - dw_die_ref array_elems_type = ctf_get_AT_type (array_type);
> + if (dw_get_die_tag (c) == DW_TAG_subrange_type)
> + {
> + /* 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
> + gcc_unreachable ();
>
> - /* First, register the type of the array elements if needed. */
> - array_elems_type_id = gen_ctf_type (ctfc, array_elems_type);
> + /* 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;
>
> - /* 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.
> + array_index_type = ctf_get_AT_type (c);
> + arinfo.ctr_index = gen_ctf_type (ctfc, array_index_type);
>
> - 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. */
> + if (c == last)
> + arinfo.ctr_contents = array_elems_type_id;
> + else
> + arinfo.ctr_contents = gen_ctf_subrange_type (ctfc, array_elems_type_id,
> + dw_get_die_sib (c), last);
>
> - 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;
> + if (!ctf_type_exists (ctfc, c, &array_node_type_id))
> + array_node_type_id = ctf_add_array (ctfc, CTF_ADD_ROOT, &arinfo, c);
>
> - c = dw_get_die_sib (c);
> + return array_node_type_id;
> +}
>
> - 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 ();
> +/* Generate CTF for an ARRAY_TYPE. */
>
> - /* 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. */
> +static ctf_id_t
> +gen_ctf_array_type (ctf_container_ref ctfc,
> + dw_die_ref array_type)
> +{
> + dw_die_ref first, last, array_elems_type;
> + ctf_id_t array_elems_type_id = CTF_NULL_TYPEID;
> + ctf_id_t array_type_id = CTF_NULL_TYPEID;
>
> - 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);
> + int vector_type_p = get_AT_flag (array_type, DW_AT_GNU_vector);
> + if (vector_type_p)
> + return array_elems_type_id;
>
> - 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));
> + /* Find the first and last array dimension DIEs. */
> + last = dw_get_die_child (array_type);
> + first = dw_get_die_sib (last);
>
> -#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;
> + Consult the ctfc_types before adding CTF type for the first dimension.
> */
> + if (!ctf_type_exists (ctfc, first, &array_type_id))
> + {
> + 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);
> +
> + array_type_id = gen_ctf_subrange_type (ctfc, array_elems_type_id,
> first,
> + last);
> + }
> +
> + return array_type_id;
> }
>
> /* Generate CTF for a typedef. */
> diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-array-6.c
> b/gcc/testsuite/gcc.dg/debug/ctf/ctf-array-6.c
> new file mode 100644
> index 000000000000..5564cb8865db
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-array-6.c
> @@ -0,0 +1,14 @@
> +/* CTF generation for multidimensional array. */
> +
> +/* { dg-do compile ) */
> +/* { dg-options "-O0 -gctf -dA" } */
> +
> +/* { dg-final { scan-assembler-times "\[\t \]+0x2\[\t \]+\[^\n\]*cta_nelems"
> 1 } } */
> +/* { dg-final { scan-assembler-times "\[\t \]+0x3\[\t \]+\[^\n\]*cta_nelems"
> 1 } } */
> +/* { dg-final { scan-assembler-times "\[\t \]+0x4\[\t \]+\[^\n\]*cta_nelems"
> 1 } } */
> +
> +/* { dg-final { scan-assembler-times "\[\t \]+0x1\[\t
> \]+\[^\n\]*cta_contents\[\\r\\n\]+\[^\\r\\n\]*\[\\r\\n\]+\[^\\r\\n\]*0x4\[\t
> \]+\[^\n\]*cta_nelems" 1 } } */
> +/* { dg-final { scan-assembler-times "\[\t \]+0x3\[\t
> \]+\[^\n\]*cta_contents\[\\r\\n\]+\[^\\r\\n\]*\[\\r\\n\]+\[^\\r\\n\]*0x3\[\t
> \]+\[^\n\]*cta_nelems" 1 } } */
> +/* { dg-final { scan-assembler-times "\[\t \]+0x4\[\t
> \]+\[^\n\]*cta_contents\[\\r\\n\]+\[^\\r\\n\]*\[\\r\\n\]+\[^\\r\\n\]*0x2\[\t
> \]+\[^\n\]*cta_nelems" 1 } } */
> +
> +int a[2][3][4];