Sorry for the slow review.

Matthieu Longo <matthieu.lo...@arm.com> writes:
> GNU properties are emitted to provide some information about the features
> used in the generated code like PAC, BTI, or GCS. However, no debug
> comment are emitted in the generated assembly even if -dA is provided.
> This makes understanding the information stored in the .note.gnu.property
> section more difficult than needed.
>
> This patch adds assembly comments (if -dA is provided) next to the GNU
> properties. For instance, if PAC and BTI are enabled, it will emit:
>   .word  3  // GNU_PROPERTY_AARCH64_FEATURE_1_AND (BTI, PAC)
>
> gcc/ChangeLog:
>
>     * config/aarch64/aarch64.cc
>     (aarch64_file_end_indicate_exec_stack): Emit assembly comments.
>
> gcc/testsuite/ChangeLog:
>
>     * gcc.target/aarch64/bti-1.c: Emit assembly comments, and update
>       test assertion.
> ---
>  gcc/config/aarch64/aarch64.cc            | 41 +++++++++++++++++++++++-
>  gcc/testsuite/gcc.target/aarch64/bti-1.c |  5 +--
>  2 files changed, 43 insertions(+), 3 deletions(-)
>
> diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
> index 4b2e7a690c6..6d9075011ec 100644
> --- a/gcc/config/aarch64/aarch64.cc
> +++ b/gcc/config/aarch64/aarch64.cc
> @@ -98,6 +98,8 @@
>  #include "ipa-fnsummary.h"
>  #include "hash-map.h"
>  
> +#include <numeric>
> +

If we do keep this, it needs to be done via a new INCLUDE_NUMERIC
in system.h, which aarch64.cc would then define before including
any files.  This avoids clashes between GCC and system headers
on some hosts.  But see below.

>  /* This file should be included last.  */
>  #include "target-def.h"
>  
> @@ -29129,8 +29131,45 @@ aarch64_file_end_indicate_exec_stack ()
>        data   = feature_1_and.  */
>        assemble_integer (GEN_INT (GNU_PROPERTY_AARCH64_FEATURE_1_AND), 4, 32, 
> 1);
>        assemble_integer (GEN_INT (4), 4, 32, 1);
> -      assemble_integer (GEN_INT (feature_1_and), 4, 32, 1);
>  
> +      if (!flag_debug_asm)
> +     assemble_integer (GEN_INT (feature_1_and), 4, 32, 1);
> +      else
> +     {
> +       asm_fprintf (asm_out_file, "\t.word\t%u", feature_1_and);

It's probably better to use integer_asm_op (4, 1) rather than
hard-coding .word.

> +
> +       auto join_s = [] (std::string s1,
> +                         const std::string &s2,
> +                         const std::string &separator = ", ") -> std::string
> +       {
> +         return std::move (s1)
> +           .append (separator)
> +           .append (s2);
> +       };
> +
> +       auto features_to_string
> +         = [&join_s] (unsigned feature_1_and) -> std::string
> +       {
> +         std::vector<std::string> feature_bits;
> +         if (feature_1_and & GNU_PROPERTY_AARCH64_FEATURE_1_BTI)
> +           feature_bits.push_back ("BTI");
> +         if (feature_1_and & GNU_PROPERTY_AARCH64_FEATURE_1_PAC)
> +           feature_bits.push_back ("PAC");
> +         if (feature_1_and & GNU_PROPERTY_AARCH64_FEATURE_1_GCS)
> +           feature_bits.push_back ("GCS");
> +
> +         if (feature_bits.empty ())
> +           return {};
> +         return std::accumulate(std::next(feature_bits.cbegin()),
> +                                feature_bits.cend(),
> +                                feature_bits[0],
> +                                join_s);
> +       };
> +       auto const& s_features = features_to_string (feature_1_and);

I do like this!  But I wonder whether it would be simpler to go for
the more prosaic:

          struct flag_name { unsigned int mask; const char *name; };
          static const flag_name flags[] =
          {
            { GNU_PROPERTY_AARCH64_FEATURE_1_BTI, "BTI" },
            { GNU_PROPERTY_AARCH64_FEATURE_1_PAC, "PAC" }
          };

          const char *separator = "";
          std::string s_features;
          for (auto &flag : flags)
            if (feature_1_and & flag.mask)
              {
                s_features.append (separator).append (flag.name);
                separator = ", ";
              }

It's slightly shorter, but also means that there's a bit less
cut-&-paste for each flag.  (In principle, the table could even
be generated from the same source as the definitions of the
GNU_PROPERTY_*s, but that's probaby overkill.)

> +       asm_fprintf (asm_out_file,
> +         "\t%s GNU_PROPERTY_AARCH64_FEATURE_1_AND (%s)\n",
> +         ASM_COMMENT_START, s_features.c_str ());
> +     }

Formatting:

          asm_fprintf (asm_out_file,
                       "\t%s GNU_PROPERTY_AARCH64_FEATURE_1_AND (%s)\n",
                       ASM_COMMENT_START, s_features.c_str ());

Thanks,
Richard

>        /* Pad the size of the note to the required alignment.  */
>        assemble_align (POINTER_SIZE);
>      }
> diff --git a/gcc/testsuite/gcc.target/aarch64/bti-1.c 
> b/gcc/testsuite/gcc.target/aarch64/bti-1.c
> index 5a556b08ed1..e48017abc35 100644
> --- a/gcc/testsuite/gcc.target/aarch64/bti-1.c
> +++ b/gcc/testsuite/gcc.target/aarch64/bti-1.c
> @@ -1,6 +1,6 @@
>  /* { dg-do compile } */
>  /* -Os to create jump table.  */
> -/* { dg-options "-Os" } */
> +/* { dg-options "-Os -dA" } */
>  /* { dg-require-effective-target lp64 } */
>  /* If configured with --enable-standard-branch-protection, don't use
>     command line option.  */
> @@ -61,4 +61,5 @@ lab2:
>  }
>  /* { dg-final { scan-assembler-times "hint\t34" 1 } } */
>  /* { dg-final { scan-assembler-times "hint\t36" 12 } } */
> -/* { dg-final { scan-assembler ".note.gnu.property" { target *-*-linux* } } 
> } */
> +/* { dg-final { scan-assembler "\.section\t\.note\.gnu\.property" { target 
> *-*-linux* } } } */
> +/* { dg-final { scan-assembler "\.word\t7\t\/\/ 
> GNU_PROPERTY_AARCH64_FEATURE_1_AND \\(BTI, PAC, GCS\\)" { target *-*-linux* } 
> } } */
> \ No newline at end of file

Reply via email to