diff mbox series

[v2] Extend check-function-bodies to allow label and directives

Message ID 20240822210554.1172978-1-hjl.tools@gmail.com
State New
Headers show
Series [v2] Extend check-function-bodies to allow label and directives | expand

Commit Message

H.J. Lu Aug. 22, 2024, 9:05 p.m. UTC
As PR target/116174 shown, we may need to verify labels and the directive
order.  Extend check-function-bodies to support matched output lines to
allow label and directives.

gcc/

	* doc/sourcebuild.texi (check-function-bodies): Add an optional
	argument for matched output lines.

gcc/testsuite/

	* gcc.target/i386/pr116174.c: Use check-function-bodies.
	* lib/scanasm.exp (parse_function_bodies): Append the line if
	$up_config(matched) matches the line.
	(check-function-bodies): Add an argument for matched.  Set
	up_config(matched) to $matched.  Append the expected line without
	$config(line_prefix) to function_regexp if it starts with ".L".

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
---
 gcc/doc/sourcebuild.texi                 |  6 +++++-
 gcc/testsuite/gcc.target/i386/pr116174.c | 18 +++++++++++++++---
 gcc/testsuite/lib/scanasm.exp            | 14 ++++++++++++--
 3 files changed, 32 insertions(+), 6 deletions(-)

Comments

Richard Sandiford Aug. 27, 2024, 9:18 a.m. UTC | #1
"H.J. Lu" <hjl.tools@gmail.com> writes:
> As PR target/116174 shown, we may need to verify labels and the directive
> order.  Extend check-function-bodies to support matched output lines to
> allow label and directives.
>
> gcc/
>
> 	* doc/sourcebuild.texi (check-function-bodies): Add an optional
> 	argument for matched output lines.
>
> gcc/testsuite/
>
> 	* gcc.target/i386/pr116174.c: Use check-function-bodies.
> 	* lib/scanasm.exp (parse_function_bodies): Append the line if
> 	$up_config(matched) matches the line.
> 	(check-function-bodies): Add an argument for matched.  Set
> 	up_config(matched) to $matched.  Append the expected line without
> 	$config(line_prefix) to function_regexp if it starts with ".L".
>
> Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
> ---
>  gcc/doc/sourcebuild.texi                 |  6 +++++-
>  gcc/testsuite/gcc.target/i386/pr116174.c | 18 +++++++++++++++---
>  gcc/testsuite/lib/scanasm.exp            | 14 ++++++++++++--
>  3 files changed, 32 insertions(+), 6 deletions(-)
>
> diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
> index 1a31f00fb65..f7128f445cf 100644
> --- a/gcc/doc/sourcebuild.texi
> +++ b/gcc/doc/sourcebuild.texi
> @@ -3530,7 +3530,7 @@ assembly output.
>  Passes if @var{symbol} is not defined as a hidden symbol in the test's
>  assembly output.
>  
> -@item check-function-bodies @var{prefix} @var{terminator} [@var{options} [@{ target/xfail @var{selector} @}]]
> +@item check-function-bodies @var{prefix} @var{terminator} [@var{options} [@{ target/xfail @var{selector} @} [@var{matched}]]]
>  Looks through the source file for comments that give the expected assembly
>  output for selected functions.  Each line of expected output starts with the
>  prefix string @var{prefix} and the expected output for a function as a whole
> @@ -3544,6 +3544,10 @@ command line.  This can help if a source file is compiled both with
>  and without optimization, since it is rarely useful to check the full
>  function body for unoptimized code.
>  
> +@var{matched}, if specified, is a regular expression which matches a
> +line of the function body.  If @var{matched} isn't specified, lines
> +beginning with labels, directives and comments are ignored.
> +

How about instead splitting:

  Depending on the configuration (see
  @code{configure_check-function-bodies} in
  @file{gcc/testsuite/lib/scanasm.exp}), the test may discard from the
  compiler's assembly output directives such as @code{.cfi_startproc},
  local label definitions such as @code{.LFB0}, and more.
  It then matches the result against the expected
  output for a function as a single regular expression.  This means that
  later lines can use backslashes to refer back to @samp{(@dots{})}
  captures on earlier lines.  For example:

into two paragraphs at "If then", and describing the new behaviour at
the end of the first paragraph:

------------------------------------------------------------------------
Depending on the configuration (see
@code{configure_check-function-bodies} in
@file{gcc/testsuite/lib/scanasm.exp}), the test may discard from the
compiler's assembly output directives such as @code{.cfi_startproc},
local label definitions such as @code{.LFB0}, and more.  This behavior
can be overridden using the optional @var{matched} argument, which
specifies a regexp for lines that should not be discarded in this way.

The test then matches the result against the expected
output for a function as a single regular expression.  This means that
later lines can use backslashes to refer back to @samp{(@dots{})}
captures on earlier lines.  For example:
------------------------------------------------------------------------

>  The first line of the expected output for a function @var{fn} has the form:
>  
>  @smallexample
> diff --git a/gcc/testsuite/gcc.target/i386/pr116174.c b/gcc/testsuite/gcc.target/i386/pr116174.c
> index 8877d0b51af..91ec3288786 100644
> --- a/gcc/testsuite/gcc.target/i386/pr116174.c
> +++ b/gcc/testsuite/gcc.target/i386/pr116174.c
> @@ -1,6 +1,20 @@
>  /* { dg-do compile { target *-*-linux* } } */
> -/* { dg-options "-O2 -fcf-protection=branch" } */
> +/* { dg-options "-O2 -g0 -fcf-protection=branch" } */
> +/* Keep labels and directives ('.p2align', '.cfi_startproc').
> +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {.*} } } */

This works, but matches everything.  Maybe {^\t?\.} would be more precise.
The current version is fine too though, if you think it will work for all
assembly dialects.

>  
> +/*
> +**foo:
> +**.LFB0:
> +**	.cfi_startproc
> +** (
> +**	endbr64
> +**	.p2align 5
> +** |
> +**	endbr32
> +** )
> +**...
> +*/
>  char *
>  foo (char *dest, const char *src)
>  {
> @@ -8,5 +22,3 @@ foo (char *dest, const char *src)
>      /* nothing */;
>    return --dest;
>  }
> -
> -/* { dg-final { scan-assembler "\t\.cfi_startproc\n\tendbr(32|64)\n" } } */
> diff --git a/gcc/testsuite/lib/scanasm.exp b/gcc/testsuite/lib/scanasm.exp
> index 42c719c512c..9dc99836762 100644
> --- a/gcc/testsuite/lib/scanasm.exp
> +++ b/gcc/testsuite/lib/scanasm.exp
> @@ -952,6 +952,8 @@ proc parse_function_bodies { config filename result } {
>  		verbose "parse_function_bodies: $function_name:\n$function_body"
>  		set up_result($function_name) $function_body
>  		set in_function 0
> +	    } elseif { $up_config(matched) ne "" && [regexp $up_config(matched) $line] } {

Nit: long line:

	    } elseif { $up_config(matched) ne ""
		       && [regexp $up_config(matched) $line] } {

> +		append function_body $line "\n"
>  	    } elseif { [regexp $up_config(fluff) $line] } {
>  		verbose "parse_function_bodies: $function_name: ignoring fluff line: $line"
>  	    } else {
> @@ -982,7 +984,7 @@ proc check_function_body { functions name body_regexp } {
>  
>  # Check the implementations of functions against expected output.  Used as:
>  #
> -# { dg-do { check-function-bodies PREFIX TERMINATOR[ OPTION[ SELECTOR]] } }
> +# { dg-do { check-function-bodies PREFIX TERMINATOR[ OPTION[ SELECTOR [MATCHED]]] } }
>  #
>  # See sourcebuild.texi for details.
>  
> @@ -990,7 +992,7 @@ proc check-function-bodies { args } {
>      if { [llength $args] < 2 } {
>  	error "too few arguments to check-function-bodies"
>      }
> -    if { [llength $args] > 4 } {
> +    if { [llength $args] > 5 } {
>  	error "too many arguments to check-function-bodies"
>      }
>  
> @@ -1029,6 +1031,11 @@ proc check-function-bodies { args } {
>  	}
>      }
>  
> +    set matched ""
> +    if { [llength $args] >= 5 } {
> +	set matched [lindex $args 4]
> +    }
> +
>      set testcase [testname-for-summary]
>      # The name might include a list of options; extract the file name.
>      set filename [lindex $testcase 0]
> @@ -1048,6 +1055,7 @@ proc check-function-bodies { args } {
>      # (name in \1).  This may be different from '$config(start)'.
>      set start_expected {^(\S+):$}
>  
> +    set config(matched) $matched
>      configure_check-function-bodies config
>      set have_bodies 0
>      if { [is_remote host] } {
> @@ -1090,6 +1098,8 @@ proc check-function-bodies { args } {
>  		append function_regexp ")"
>  	    } elseif { [string equal $line "..."] } {
>  		append function_regexp ".*"
> +	    } elseif { [regexp "^.L.*" $line] } {

{^\.L} would be more precise than "^.L.*".

OK with those changes, thanks, and also without the suggested change
to pr116174.c.

Richard

> +		append function_regexp $line "\n"
>  	    } else {
>  		append function_regexp $config(line_prefix) $line "\n"
>  	    }
H.J. Lu Aug. 27, 2024, 1:50 p.m. UTC | #2
On Tue, Aug 27, 2024 at 2:18 AM Richard Sandiford
<richard.sandiford@arm.com> wrote:
>
> "H.J. Lu" <hjl.tools@gmail.com> writes:
> > As PR target/116174 shown, we may need to verify labels and the directive
> > order.  Extend check-function-bodies to support matched output lines to
> > allow label and directives.
> >
> > gcc/
> >
> >       * doc/sourcebuild.texi (check-function-bodies): Add an optional
> >       argument for matched output lines.
> >
> > gcc/testsuite/
> >
> >       * gcc.target/i386/pr116174.c: Use check-function-bodies.
> >       * lib/scanasm.exp (parse_function_bodies): Append the line if
> >       $up_config(matched) matches the line.
> >       (check-function-bodies): Add an argument for matched.  Set
> >       up_config(matched) to $matched.  Append the expected line without
> >       $config(line_prefix) to function_regexp if it starts with ".L".
> >
> > Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
> > ---
> >  gcc/doc/sourcebuild.texi                 |  6 +++++-
> >  gcc/testsuite/gcc.target/i386/pr116174.c | 18 +++++++++++++++---
> >  gcc/testsuite/lib/scanasm.exp            | 14 ++++++++++++--
> >  3 files changed, 32 insertions(+), 6 deletions(-)
> >
> > diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
> > index 1a31f00fb65..f7128f445cf 100644
> > --- a/gcc/doc/sourcebuild.texi
> > +++ b/gcc/doc/sourcebuild.texi
> > @@ -3530,7 +3530,7 @@ assembly output.
> >  Passes if @var{symbol} is not defined as a hidden symbol in the test's
> >  assembly output.
> >
> > -@item check-function-bodies @var{prefix} @var{terminator} [@var{options} [@{ target/xfail @var{selector} @}]]
> > +@item check-function-bodies @var{prefix} @var{terminator} [@var{options} [@{ target/xfail @var{selector} @} [@var{matched}]]]
> >  Looks through the source file for comments that give the expected assembly
> >  output for selected functions.  Each line of expected output starts with the
> >  prefix string @var{prefix} and the expected output for a function as a whole
> > @@ -3544,6 +3544,10 @@ command line.  This can help if a source file is compiled both with
> >  and without optimization, since it is rarely useful to check the full
> >  function body for unoptimized code.
> >
> > +@var{matched}, if specified, is a regular expression which matches a
> > +line of the function body.  If @var{matched} isn't specified, lines
> > +beginning with labels, directives and comments are ignored.
> > +
>
> How about instead splitting:
>
>   Depending on the configuration (see
>   @code{configure_check-function-bodies} in
>   @file{gcc/testsuite/lib/scanasm.exp}), the test may discard from the
>   compiler's assembly output directives such as @code{.cfi_startproc},
>   local label definitions such as @code{.LFB0}, and more.
>   It then matches the result against the expected
>   output for a function as a single regular expression.  This means that
>   later lines can use backslashes to refer back to @samp{(@dots{})}
>   captures on earlier lines.  For example:
>
> into two paragraphs at "If then", and describing the new behaviour at
> the end of the first paragraph:
>
> ------------------------------------------------------------------------
> Depending on the configuration (see
> @code{configure_check-function-bodies} in
> @file{gcc/testsuite/lib/scanasm.exp}), the test may discard from the
> compiler's assembly output directives such as @code{.cfi_startproc},
> local label definitions such as @code{.LFB0}, and more.  This behavior
> can be overridden using the optional @var{matched} argument, which
> specifies a regexp for lines that should not be discarded in this way.
>
> The test then matches the result against the expected
> output for a function as a single regular expression.  This means that
> later lines can use backslashes to refer back to @samp{(@dots{})}
> captures on earlier lines.  For example:
> ------------------------------------------------------------------------

Fixed in v3.

> >  The first line of the expected output for a function @var{fn} has the form:
> >
> >  @smallexample
> > diff --git a/gcc/testsuite/gcc.target/i386/pr116174.c b/gcc/testsuite/gcc.target/i386/pr116174.c
> > index 8877d0b51af..91ec3288786 100644
> > --- a/gcc/testsuite/gcc.target/i386/pr116174.c
> > +++ b/gcc/testsuite/gcc.target/i386/pr116174.c
> > @@ -1,6 +1,20 @@
> >  /* { dg-do compile { target *-*-linux* } } */
> > -/* { dg-options "-O2 -fcf-protection=branch" } */
> > +/* { dg-options "-O2 -g0 -fcf-protection=branch" } */
> > +/* Keep labels and directives ('.p2align', '.cfi_startproc').
> > +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {.*} } } */
>
> This works, but matches everything.  Maybe {^\t?\.} would be more precise.

Fixed in v3.

> The current version is fine too though, if you think it will work for all
> assembly dialects.
>
> >
> > +/*
> > +**foo:
> > +**.LFB0:
> > +**   .cfi_startproc
> > +** (
> > +**   endbr64
> > +**   .p2align 5
> > +** |
> > +**   endbr32
> > +** )
> > +**...
> > +*/
> >  char *
> >  foo (char *dest, const char *src)
> >  {
> > @@ -8,5 +22,3 @@ foo (char *dest, const char *src)
> >      /* nothing */;
> >    return --dest;
> >  }
> > -
> > -/* { dg-final { scan-assembler "\t\.cfi_startproc\n\tendbr(32|64)\n" } } */
> > diff --git a/gcc/testsuite/lib/scanasm.exp b/gcc/testsuite/lib/scanasm.exp
> > index 42c719c512c..9dc99836762 100644
> > --- a/gcc/testsuite/lib/scanasm.exp
> > +++ b/gcc/testsuite/lib/scanasm.exp
> > @@ -952,6 +952,8 @@ proc parse_function_bodies { config filename result } {
> >               verbose "parse_function_bodies: $function_name:\n$function_body"
> >               set up_result($function_name) $function_body
> >               set in_function 0
> > +         } elseif { $up_config(matched) ne "" && [regexp $up_config(matched) $line] } {
>
> Nit: long line:

Fixed in v3.

>
>             } elseif { $up_config(matched) ne ""
>                        && [regexp $up_config(matched) $line] } {
>
> > +             append function_body $line "\n"
> >           } elseif { [regexp $up_config(fluff) $line] } {
> >               verbose "parse_function_bodies: $function_name: ignoring fluff line: $line"
> >           } else {
> > @@ -982,7 +984,7 @@ proc check_function_body { functions name body_regexp } {
> >
> >  # Check the implementations of functions against expected output.  Used as:
> >  #
> > -# { dg-do { check-function-bodies PREFIX TERMINATOR[ OPTION[ SELECTOR]] } }
> > +# { dg-do { check-function-bodies PREFIX TERMINATOR[ OPTION[ SELECTOR [MATCHED]]] } }
> >  #
> >  # See sourcebuild.texi for details.
> >
> > @@ -990,7 +992,7 @@ proc check-function-bodies { args } {
> >      if { [llength $args] < 2 } {
> >       error "too few arguments to check-function-bodies"
> >      }
> > -    if { [llength $args] > 4 } {
> > +    if { [llength $args] > 5 } {
> >       error "too many arguments to check-function-bodies"
> >      }
> >
> > @@ -1029,6 +1031,11 @@ proc check-function-bodies { args } {
> >       }
> >      }
> >
> > +    set matched ""
> > +    if { [llength $args] >= 5 } {
> > +     set matched [lindex $args 4]
> > +    }
> > +
> >      set testcase [testname-for-summary]
> >      # The name might include a list of options; extract the file name.
> >      set filename [lindex $testcase 0]
> > @@ -1048,6 +1055,7 @@ proc check-function-bodies { args } {
> >      # (name in \1).  This may be different from '$config(start)'.
> >      set start_expected {^(\S+):$}
> >
> > +    set config(matched) $matched
> >      configure_check-function-bodies config
> >      set have_bodies 0
> >      if { [is_remote host] } {
> > @@ -1090,6 +1098,8 @@ proc check-function-bodies { args } {
> >               append function_regexp ")"
> >           } elseif { [string equal $line "..."] } {
> >               append function_regexp ".*"
> > +         } elseif { [regexp "^.L.*" $line] } {
>
> {^\.L} would be more precise than "^.L.*".

I tried  {^\.L}.  It didn't work.  I used "^.L" in v3.

> OK with those changes, thanks, and also without the suggested change
> to pr116174.c.

The v3 patch is at

https://gcc.gnu.org/pipermail/gcc-patches/2024-August/661580.html

Thanks.
Richard Sandiford Aug. 27, 2024, 1:54 p.m. UTC | #3
"H.J. Lu" <hjl.tools@gmail.com> writes:
>> >               append function_regexp ")"
>> >           } elseif { [string equal $line "..."] } {
>> >               append function_regexp ".*"
>> > +         } elseif { [regexp "^.L.*" $line] } {
>>
>> {^\.L} would be more precise than "^.L.*".
>
> I tried  {^\.L}.  It didn't work.  I used "^.L" in v3.

Why didn't it work though?  "^.L.*" matches "ALL" as well as ".L".

Richard
H.J. Lu Aug. 27, 2024, 2:04 p.m. UTC | #4
On Tue, Aug 27, 2024 at 6:54 AM Richard Sandiford
<richard.sandiford@arm.com> wrote:
>
> "H.J. Lu" <hjl.tools@gmail.com> writes:
> >> >               append function_regexp ")"
> >> >           } elseif { [string equal $line "..."] } {
> >> >               append function_regexp ".*"
> >> > +         } elseif { [regexp "^.L.*" $line] } {
> >>
> >> {^\.L} would be more precise than "^.L.*".
> >
> > I tried  {^\.L}.  It didn't work.  I used "^.L" in v3.
>
> Why didn't it work though?  "^.L.*" matches "ALL" as well as ".L".
>
> Richard

I tried it again by typing it by hand.  It works now.  Fixed in v4:

https://gcc.gnu.org/pipermail/gcc-patches/2024-August/661586.html

Thanks.


--
H.J.
diff mbox series

Patch

diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
index 1a31f00fb65..f7128f445cf 100644
--- a/gcc/doc/sourcebuild.texi
+++ b/gcc/doc/sourcebuild.texi
@@ -3530,7 +3530,7 @@  assembly output.
 Passes if @var{symbol} is not defined as a hidden symbol in the test's
 assembly output.
 
-@item check-function-bodies @var{prefix} @var{terminator} [@var{options} [@{ target/xfail @var{selector} @}]]
+@item check-function-bodies @var{prefix} @var{terminator} [@var{options} [@{ target/xfail @var{selector} @} [@var{matched}]]]
 Looks through the source file for comments that give the expected assembly
 output for selected functions.  Each line of expected output starts with the
 prefix string @var{prefix} and the expected output for a function as a whole
@@ -3544,6 +3544,10 @@  command line.  This can help if a source file is compiled both with
 and without optimization, since it is rarely useful to check the full
 function body for unoptimized code.
 
+@var{matched}, if specified, is a regular expression which matches a
+line of the function body.  If @var{matched} isn't specified, lines
+beginning with labels, directives and comments are ignored.
+
 The first line of the expected output for a function @var{fn} has the form:
 
 @smallexample
diff --git a/gcc/testsuite/gcc.target/i386/pr116174.c b/gcc/testsuite/gcc.target/i386/pr116174.c
index 8877d0b51af..91ec3288786 100644
--- a/gcc/testsuite/gcc.target/i386/pr116174.c
+++ b/gcc/testsuite/gcc.target/i386/pr116174.c
@@ -1,6 +1,20 @@ 
 /* { dg-do compile { target *-*-linux* } } */
-/* { dg-options "-O2 -fcf-protection=branch" } */
+/* { dg-options "-O2 -g0 -fcf-protection=branch" } */
+/* Keep labels and directives ('.p2align', '.cfi_startproc').
+/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {.*} } } */
 
+/*
+**foo:
+**.LFB0:
+**	.cfi_startproc
+** (
+**	endbr64
+**	.p2align 5
+** |
+**	endbr32
+** )
+**...
+*/
 char *
 foo (char *dest, const char *src)
 {
@@ -8,5 +22,3 @@  foo (char *dest, const char *src)
     /* nothing */;
   return --dest;
 }
-
-/* { dg-final { scan-assembler "\t\.cfi_startproc\n\tendbr(32|64)\n" } } */
diff --git a/gcc/testsuite/lib/scanasm.exp b/gcc/testsuite/lib/scanasm.exp
index 42c719c512c..9dc99836762 100644
--- a/gcc/testsuite/lib/scanasm.exp
+++ b/gcc/testsuite/lib/scanasm.exp
@@ -952,6 +952,8 @@  proc parse_function_bodies { config filename result } {
 		verbose "parse_function_bodies: $function_name:\n$function_body"
 		set up_result($function_name) $function_body
 		set in_function 0
+	    } elseif { $up_config(matched) ne "" && [regexp $up_config(matched) $line] } {
+		append function_body $line "\n"
 	    } elseif { [regexp $up_config(fluff) $line] } {
 		verbose "parse_function_bodies: $function_name: ignoring fluff line: $line"
 	    } else {
@@ -982,7 +984,7 @@  proc check_function_body { functions name body_regexp } {
 
 # Check the implementations of functions against expected output.  Used as:
 #
-# { dg-do { check-function-bodies PREFIX TERMINATOR[ OPTION[ SELECTOR]] } }
+# { dg-do { check-function-bodies PREFIX TERMINATOR[ OPTION[ SELECTOR [MATCHED]]] } }
 #
 # See sourcebuild.texi for details.
 
@@ -990,7 +992,7 @@  proc check-function-bodies { args } {
     if { [llength $args] < 2 } {
 	error "too few arguments to check-function-bodies"
     }
-    if { [llength $args] > 4 } {
+    if { [llength $args] > 5 } {
 	error "too many arguments to check-function-bodies"
     }
 
@@ -1029,6 +1031,11 @@  proc check-function-bodies { args } {
 	}
     }
 
+    set matched ""
+    if { [llength $args] >= 5 } {
+	set matched [lindex $args 4]
+    }
+
     set testcase [testname-for-summary]
     # The name might include a list of options; extract the file name.
     set filename [lindex $testcase 0]
@@ -1048,6 +1055,7 @@  proc check-function-bodies { args } {
     # (name in \1).  This may be different from '$config(start)'.
     set start_expected {^(\S+):$}
 
+    set config(matched) $matched
     configure_check-function-bodies config
     set have_bodies 0
     if { [is_remote host] } {
@@ -1090,6 +1098,8 @@  proc check-function-bodies { args } {
 		append function_regexp ")"
 	    } elseif { [string equal $line "..."] } {
 		append function_regexp ".*"
+	    } elseif { [regexp "^.L.*" $line] } {
+		append function_regexp $line "\n"
 	    } else {
 		append function_regexp $config(line_prefix) $line "\n"
 	    }