* Add dg test for matching function bodies
@ 2019-07-16 14:14 Richard Sandiford
2019-07-21 20:16 ` Jeff Law
2023-09-04 21:05 ` [WIP] testsuite: Port 'check-function-bodies' to nvptx (was: Add dg test for matching function bodies) Thomas Schwinge
0 siblings, 2 replies; 6+ messages in thread
From: Richard Sandiford @ 2019-07-16 14:14 UTC (permalink / raw)
To: gcc-patches
There isn't a 1:1 mapping from SVE intrinsics to SVE instructions,
but the intrinsics are still close enough to the instructions for
there to be a specific preferred sequence (or sometimes choice of
preferred sequences) for a given combination of operands. Sometimes
these sequences will be one instruction, sometimes they'll be several.
I therefore wanted a convenient way of matching the exact assembly
implementation of a given function. It's possible to do that using
single scan-assembler lines, but:
(a) they become hard to read for multiline matches
(b) the PASS/FAIL lines tend to be long
(c) it's useful to have a single place that skips over uninteresting
lines, such as entry block labels and .cfi_* directives, without
being overly broad
This patch therefore adds a new check-function-bodies dg-final test
that looks for specially-formatted comments. As a demo, the patch
converts the SVE vec_init tests to use the new harness instead of
scan-assembler.
The regexps in parse_function_bodies are fairly general, but might
still need to be extended in future for targets like Darwin or AIX.
Tested on aarch64-linux-gnu (and x86_64-linux-gnu, somewhat pointlessly
given the contents of the patch). OK to install?
Richard
2019-07-16 Richard Sandiford <richard.sandiford@arm.com>
gcc/
* doc/sourcebuild.texi (check-function-bodies): Document.
gcc/testsuite/
* lib/scanasm.exp (parse_function_bodies, check_function_body)
(check-function-bodies): New procedures.
* gcc.target/aarch64/sve/init_1.c: Use check-function-bodies
instead of scan-assembler.
* gcc.target/aarch64/sve/init_2.c: Likewise.
* gcc.target/aarch64/sve/init_3.c: Likewise.
* gcc.target/aarch64/sve/init_4.c: Likewise.
* gcc.target/aarch64/sve/init_5.c: Likewise.
* gcc.target/aarch64/sve/init_6.c: Likewise.
* gcc.target/aarch64/sve/init_7.c: Likewise.
* gcc.target/aarch64/sve/init_8.c: Likewise.
* gcc.target/aarch64/sve/init_9.c: Likewise.
* gcc.target/aarch64/sve/init_10.c: Likewise.
* gcc.target/aarch64/sve/init_11.c: Likewise.
* gcc.target/aarch64/sve/init_12.c: Likewise.
Index: gcc/doc/sourcebuild.texi
===================================================================
--- gcc/doc/sourcebuild.texi 2019-07-01 09:37:04.424547899 +0100
+++ gcc/doc/sourcebuild.texi 2019-07-16 14:57:25.602820637 +0100
@@ -2669,6 +2669,91 @@ assembly output.
@item scan-not-hidden @var{symbol} [@{ target/xfail @var{selector} @}]
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{option}]
+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
+is followed by a line that starts with the string @var{terminator}.
+Specifying an empty terminator is equivalent to specifying @samp{"*/"}.
+
+If @var{option} is specified, the test only applies to command lines
+that contain @var{option}. This can be useful if a source file is compiled
+both with and without optimization, since it is rarely useful to check the
+assembly output for unoptimized code.
+
+The first line of the expected output for a function @var{fn} has the form:
+
+@smallexample
+@var{prefix} @var{fn}: [@{ target/xfail @var{selector} @}]
+@end smallexample
+
+Subsequent lines of the expected output also start with @var{prefix}.
+In both cases, whitespace after @var{prefix} is not significant.
+
+The test discards assembly directives such as @code{.cfi_startproc}
+and local label definitions such as @code{.LFB0} from the compiler's
+assembly output. 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:
+
+@smallexample
+/* @{ dg-final @{ check-function-bodies "**" "" "-DCHECK_ASM" @} @} */
+@dots{}
+/*
+** add_w0_s8_m:
+** mov (z[0-9]+\.b), w0
+** add z0\.b, p0/m, z0\.b, \1
+** ret
+*/
+svint8_t add_w0_s8_m (@dots{}) @{ @dots{} @}
+@dots{}
+/*
+** add_b0_s8_m:
+** mov (z[0-9]+\.b), b0
+** add z1\.b, p0/m, z1\.b, \1
+** ret
+*/
+svint8_t add_b0_s8_m (@dots{}) @{ @dots{} @}
+@end smallexample
+
+checks whether the implementations of @code{add_w0_s8_m} and
+@code{add_b0_s8_m} match the regular expressions given. The test only
+runs when @samp{-DCHECK_ASM} is passed on the command line.
+
+It is possible to create non-capturing multi-line regular expression
+groups of the form @samp{(@var{a}|@var{b}|@dots{})} by putting the
+@samp{(}, @samp{|} and @samp{)} on separate lines (each still using
+@var{prefix}). For example:
+
+@smallexample
+/*
+** cmple_f16_tied:
+** (
+** fcmge p0\.h, p0/z, z1\.h, z0\.h
+** |
+** fcmle p0\.h, p0/z, z0\.h, z1\.h
+** )
+** ret
+*/
+svbool_t cmple_f16_tied (@dots{}) @{ @dots{} @}
+@end smallexample
+
+checks whether @code{cmple_f16_tied} is implemented by the
+@code{fcmge} instruction followed by @code{ret} or by the
+@code{fcmle} instruction followed by @code{ret}. The test is
+still a single regular rexpression.
+
+A line containing just:
+
+@smallexample
+@var{prefix} ...
+@end smallexample
+
+stands for zero or more unmatched lines; the whitespace after
+@var{prefix} is again not significant.
+
@end table
@subsubsection Scan optimization dump files
Index: gcc/testsuite/lib/scanasm.exp
===================================================================
--- gcc/testsuite/lib/scanasm.exp 2019-06-18 09:35:53.045884968 +0100
+++ gcc/testsuite/lib/scanasm.exp 2019-07-16 14:57:25.602820637 +0100
@@ -546,3 +546,169 @@ proc scan-lto-assembler { args } {
verbose "output_file: $output_file"
dg-scan "scan-lto-assembler" 1 $testcase $output_file $args
}
+
+# Read assembly file FILENAME and store a mapping from function names
+# to function bodies in array RESULT. FILENAME has already been uploaded
+# locally where necessary and is known to exist.
+
+proc parse_function_bodies { filename result } {
+ upvar $result up_result
+
+ # Regexp for the start of a function definition (name in \1).
+ set label {^([a-zA-Z_]\S+):$}
+
+ # Regexp for the end of a function definition.
+ set terminator {^\s*\.size}
+
+ # Regexp for lines that aren't interesting.
+ set fluff {^\s*(?:\.|//)}
+
+ set fd [open $filename r]
+ set in_function 0
+ while { [gets $fd line] >= 0 } {
+ if { [regexp $label $line dummy function_name] } {
+ set in_function 1
+ set function_body ""
+ } elseif { $in_function } {
+ if { [regexp $terminator $line] } {
+ set up_result($function_name) $function_body
+ set in_function 0
+ } elseif { ![regexp $fluff $line] } {
+ append function_body $line "\n"
+ }
+ }
+ }
+ close $fd
+}
+
+# FUNCTIONS is an array that maps function names to function bodies.
+# Return true if it contains a definition of function NAME and if
+# that definition matches BODY_REGEXP.
+
+proc check_function_body { functions name body_regexp } {
+ upvar $functions up_functions
+
+ if { ![info exists up_functions($name)] } {
+ return 0
+ }
+ return [regexp "^$body_regexp\$" $up_functions($name)]
+}
+
+# Check the implementations of functions against expected output. Used as:
+#
+# { dg-do { check-function-bodies PREFIX TERMINATOR[ OPTION] } }
+#
+# See sourcebuild.texi for details.
+
+proc check-function-bodies { args } {
+ if { [llength $args] < 2 } {
+ error "too few arguments to check-function-bodies"
+ }
+ if { [llength $args] > 3 } {
+ error "too many arguments to check-function-bodies"
+ }
+
+ if { [llength $args] == 3 } {
+ set required_flag [lindex $args 2]
+
+ upvar 2 dg-extra-tool-flags extra_tool_flags
+ set flags $extra_tool_flags
+
+ global torture_current_flags
+ if { [info exists torture_current_flags] } {
+ append flags " " $torture_current_flags
+ }
+ if { ![regexp " $required_flag " $flags] } {
+ return
+ }
+ }
+
+ set testcase [testname-for-summary]
+ # The name might include a list of options; extract the file name.
+ set filename [lindex $testcase 0]
+
+ global srcdir
+ set input_filename "$srcdir/$filename"
+ set output_filename "[file rootname [file tail $filename]].s"
+
+ set prefix [lindex $args 0]
+ set prefix_len [string length $prefix]
+ set terminator [lindex $args 1]
+ if { [string equal $terminator ""] } {
+ set terminator "*/"
+ }
+ set terminator_len [string length $terminator]
+
+ set have_bodies 0
+ if { [is_remote host] } {
+ remote_upload host "$filename"
+ }
+ if { [file exists $output_filename] } {
+ parse_function_bodies $output_filename functions
+ set have_bodies 1
+ } else {
+ verbose -log "$testcase: output file does not exist"
+ }
+
+ set count 0
+ set function_regexp ""
+ set label {^(\S+):$}
+
+ set lineno 1
+ set fd [open $input_filename r]
+ set in_function 0
+ while { [gets $fd line] >= 0 } {
+ if { [string equal -length $prefix_len $line $prefix] } {
+ set line [string trim [string range $line $prefix_len end]]
+ if { !$in_function } {
+ if { [regexp "^(.*\\S)\\s+{(.*)}\$" $line dummy \
+ line selector] } {
+ set selector [dg-process-target $selector]
+ } else {
+ set selector "P"
+ }
+ if { ![regexp $label $line dummy function_name] } {
+ close $fd
+ error "check-function-bodies: line $lineno does not have a function label"
+ }
+ set in_function 1
+ set function_regexp ""
+ } elseif { [string equal $line "("] } {
+ append function_regexp "(?:"
+ } elseif { [string equal $line "|"] } {
+ append function_regexp "|"
+ } elseif { [string equal $line ")"] } {
+ append function_regexp ")"
+ } elseif { [string equal $line "..."] } {
+ append function_regexp ".*"
+ } else {
+ append function_regexp "\t" $line "\n"
+ }
+ } elseif { [string equal -length $terminator_len $line $terminator] } {
+ if { ![string equal $selector "N"] } {
+ if { [string equal $selector "F"] } {
+ setup_xfail "*-*-*"
+ }
+ set testname "$testcase check-function-bodies $function_name"
+ if { !$have_bodies } {
+ unresolved $testname
+ } elseif { [check_function_body functions $function_name \
+ $function_regexp] } {
+ pass $testname
+ } else {
+ fail $testname
+ }
+ }
+ set in_function 0
+ incr count
+ }
+ incr lineno
+ }
+ close $fd
+ if { $in_function } {
+ error "check-function-bodies: missing \"$terminator\""
+ }
+ if { $count == 0 } {
+ error "check-function-bodies: no matches found"
+ }
+}
Index: gcc/testsuite/gcc.target/aarch64/sve/init_1.c
===================================================================
--- gcc/testsuite/gcc.target/aarch64/sve/init_1.c 2019-06-18 09:35:52.945885794 +0100
+++ gcc/testsuite/gcc.target/aarch64/sve/init_1.c 2019-07-16 14:57:25.602820637 +0100
@@ -1,5 +1,6 @@
/* { dg-do assemble { target aarch64_asm_sve_ok } } */
/* { dg-options "-O -msve-vector-bits=256 --save-temps" } */
+/* { dg-final { check-function-bodies "**" "" } } */
/* Case 1.1: Trailing constants with stepped sequence. */
@@ -7,20 +8,15 @@
typedef int32_t vnx4si __attribute__((vector_size (32)));
+/*
+** foo:
+** index (z[0-9]+\.s), #1, #1
+** insr \1, w1
+** insr \1, w0
+** ...
+*/
__attribute__((noipa))
vnx4si foo(int a, int b)
{
return (vnx4si) { a, b, 1, 2, 3, 4, 5, 6 };
}
-
-/*
-foo:
-.LFB0:
- .cfi_startproc
- index z0.s, #1, #1
- insr z0.s, w1
- insr z0.s, w0
- ret
-*/
-
-/* { dg-final { scan-assembler {\tindex\t(z[0-9]+\.s), #1, #1\n\tinsr\t\1, w1\n\tinsr\t\1, w0} } } */
Index: gcc/testsuite/gcc.target/aarch64/sve/init_2.c
===================================================================
--- gcc/testsuite/gcc.target/aarch64/sve/init_2.c 2019-06-18 09:35:52.945885794 +0100
+++ gcc/testsuite/gcc.target/aarch64/sve/init_2.c 2019-07-16 14:57:25.602820637 +0100
@@ -1,5 +1,6 @@
/* { dg-do assemble { target aarch64_asm_sve_ok } } */
/* { dg-options "-O -msve-vector-bits=256 --save-temps" } */
+/* { dg-final { check-function-bodies "**" "" } } */
/* Case 1.2: Trailing constants with repeating sequence. */
@@ -7,23 +8,16 @@
typedef int32_t vnx4si __attribute__((vector_size (32)));
+/*
+** foo:
+** ...
+** ld1w (z[0-9]+\.s), p[0-9]+/z, \[x[0-9]+\]
+** insr \1, w1
+** insr \1, w0
+** ...
+*/
__attribute__((noipa))
vnx4si foo(int a, int b)
{
return (vnx4si) { a, b, 2, 3, 2, 3, 2, 3 };
}
-
-/*
-foo:
-.LFB0:
- .cfi_startproc
- ptrue p0.s, vl8
- adrp x2, .LANCHOR0
- add x2, x2, :lo12:.LANCHOR0
- ld1w z0.s, p0/z, [x2]
- insr z0.s, w1
- insr z0.s, w0
- ret
-*/
-
-/* { dg-final { scan-assembler {\tld1w\t(z[0-9]+\.s), p[0-9]+/z, \[x[0-9]+\]\n\tinsr\t\1, w1\n\tinsr\t\1, w0} } } */
Index: gcc/testsuite/gcc.target/aarch64/sve/init_3.c
===================================================================
--- gcc/testsuite/gcc.target/aarch64/sve/init_3.c 2019-06-18 09:35:52.945885794 +0100
+++ gcc/testsuite/gcc.target/aarch64/sve/init_3.c 2019-07-16 14:57:25.602820637 +0100
@@ -1,5 +1,6 @@
/* { dg-do assemble { target aarch64_asm_sve_ok } } */
/* { dg-options "-O -msve-vector-bits=256 --save-temps" } */
+/* { dg-final { check-function-bodies "**" "" } } */
/* Case 2.1: Leading constants with stepped sequence. */
@@ -7,21 +8,17 @@
typedef int32_t vnx4si __attribute__((vector_size (32)));
+/*
+** foo:
+** index (z[0-9]+\.s), #6, #-1
+** insr \1, w0
+** insr \1, w1
+** rev \1, \1
+** ...
+*/
__attribute__((noipa))
vnx4si foo(int a, int b)
{
return (vnx4si) { 1, 2, 3, 4, 5, 6, a, b };
}
-/*
-foo:
-.LFB0:
- .cfi_startproc
- index z0.s, #6, #-1
- insr z0.s, w0
- insr z0.s, w1
- rev z0.s, z0.s
- ret
-*/
-
-/* { dg-final { scan-assembler {\tindex\t(z[0-9]+\.s), #6, #-1\n\tinsr\t\1, w0\n\tinsr\t\1, w1\n\trev\t\1, \1} } } */
Index: gcc/testsuite/gcc.target/aarch64/sve/init_4.c
===================================================================
--- gcc/testsuite/gcc.target/aarch64/sve/init_4.c 2019-06-18 09:35:52.949885761 +0100
+++ gcc/testsuite/gcc.target/aarch64/sve/init_4.c 2019-07-16 14:57:25.602820637 +0100
@@ -1,5 +1,6 @@
/* { dg-do assemble { target aarch64_asm_sve_ok } } */
/* { dg-options "-O -msve-vector-bits=256 --save-temps" } */
+/* { dg-final { check-function-bodies "**" "" } } */
/* Case 2.2: Leading constants with stepped sequence. */
@@ -7,24 +8,17 @@
typedef int32_t vnx4si __attribute__((vector_size (32)));
+/*
+** foo:
+** ...
+** ld1w (z[0-9]+\.s), p[0-9]+/z, \[x[0-9]+\]
+** insr \1, w1
+** insr \1, w0
+** rev \1, \1
+** ...
+*/
__attribute__((noipa))
vnx4si foo(int a, int b)
{
return (vnx4si) { 3, 2, 3, 2, 3, 2, b, a };
}
-
-/*
-foo:
-.LFB0:
- .cfi_startproc
- ptrue p0.s, vl8
- adrp x2, .LANCHOR0
- add x2, x2, :lo12:.LANCHOR0
- ld1w z0.s, p0/z, [x2]
- insr z0.s, w1
- insr z0.s, w0
- rev z0.s, z0.s
- ret
-*/
-
-/* { dg-final { scan-assembler {\tld1w\t(z[0-9]+\.s), p[0-9]+/z, \[x[0-9]+\]\n\tinsr\t\1, w1\n\tinsr\t\1, w0\n\trev\t\1, \1} } } */
Index: gcc/testsuite/gcc.target/aarch64/sve/init_5.c
===================================================================
--- gcc/testsuite/gcc.target/aarch64/sve/init_5.c 2019-06-18 09:35:52.949885761 +0100
+++ gcc/testsuite/gcc.target/aarch64/sve/init_5.c 2019-07-16 14:57:25.602820637 +0100
@@ -1,5 +1,6 @@
/* { dg-do assemble { target aarch64_asm_sve_ok } } */
/* { dg-options "-O -msve-vector-bits=256 --save-temps" } */
+/* { dg-final { check-function-bodies "**" "" } } */
/* Case 3: Trailing same element. */
@@ -7,20 +8,15 @@
typedef int32_t vnx4si __attribute__((vector_size (32)));
+/*
+** foo:
+** mov (z[0-9]+\.s), w2
+** insr \1, w1
+** insr \1, w0
+** ...
+*/
__attribute__((noipa))
vnx4si foo(int a, int b, int c)
{
return (vnx4si) { a, b, c, c, c, c, c, c };
}
-
-/*
-foo:
-.LFB0:
- .cfi_startproc
- mov z0.s, w2
- insr z0.s, w1
- insr z0.s, w0
- ret
-*/
-
-/* { dg-final { scan-assembler {\tmov\t(z[0-9]+\.s), w2\n\tinsr\t\1, w1\n\tinsr\t\1, w0} } } */
Index: gcc/testsuite/gcc.target/aarch64/sve/init_6.c
===================================================================
--- gcc/testsuite/gcc.target/aarch64/sve/init_6.c 2019-06-18 09:35:52.949885761 +0100
+++ gcc/testsuite/gcc.target/aarch64/sve/init_6.c 2019-07-16 14:57:25.602820637 +0100
@@ -1,5 +1,6 @@
/* { dg-do assemble { target aarch64_asm_sve_ok } } */
/* { dg-options "-O -msve-vector-bits=256 --save-temps" } */
+/* { dg-final { check-function-bodies "**" "" } } */
/* Case 3: Trailing same element. */
@@ -7,21 +8,16 @@
typedef int32_t vnx4si __attribute__((vector_size (32)));
+/*
+** foo:
+** mov (z[0-9]+\.s), w2
+** insr \1, w1
+** insr \1, w0
+** rev \1, \1
+** ...
+*/
__attribute__((noipa))
vnx4si foo(int a, int b, int c)
{
return (vnx4si) { c, c, c, c, c, c, b, a };
}
-
-/*
-foo:
-.LFB0:
- .cfi_startproc
- mov z0.s, w2
- insr z0.s, w1
- insr z0.s, w0
- rev z0.s, z0.s
- ret
-*/
-
-/* { dg-final { scan-assembler {\tmov\t(z[0-9]+\.s), w2\n\tinsr\t\1, w1\n\tinsr\t\1, w0\n\trev\t\1, \1} } } */
Index: gcc/testsuite/gcc.target/aarch64/sve/init_7.c
===================================================================
--- gcc/testsuite/gcc.target/aarch64/sve/init_7.c 2019-06-18 09:35:52.949885761 +0100
+++ gcc/testsuite/gcc.target/aarch64/sve/init_7.c 2019-07-16 14:57:25.602820637 +0100
@@ -1,5 +1,6 @@
/* { dg-do assemble { target aarch64_asm_sve_ok } } */
/* { dg-options "-O -msve-vector-bits=256 --save-temps" } */
+/* { dg-final { check-function-bodies "**" "" } } */
/* Case 5.1: All elements. */
@@ -7,25 +8,20 @@
typedef int32_t vnx4si __attribute__((vector_size (32)));
+/*
+** foo:
+** mov (z[0-9]+\.s), w7
+** insr \1, w6
+** insr \1, w5
+** insr \1, w4
+** insr \1, w3
+** insr \1, w2
+** insr \1, w1
+** insr \1, w0
+** ...
+*/
__attribute__((noipa))
vnx4si foo(int a, int b, int c, int d, int e, int f, int g, int h)
{
return (vnx4si) { a, b, c, d, e, f, g, h };
}
-
-/*
-foo:
-.LFB0:
- .cfi_startproc
- mov z0.s, w7
- insr z0.s, w6
- insr z0.s, w5
- insr z0.s, w4
- insr z0.s, w3
- insr z0.s, w2
- insr z0.s, w1
- insr z0.s, w0
- ret
-*/
-
-/* { dg-final { scan-assembler {\tmov\t(z[0-9]+\.s), w7\n\tinsr\t\1, w6\n\tinsr\t\1, w5\n\tinsr\t\1, w4\n\tinsr\t\1, w3\n\tinsr\t\1, w2\n\tinsr\t\1, w1\n\tinsr\t\1, w0} } } */
Index: gcc/testsuite/gcc.target/aarch64/sve/init_8.c
===================================================================
--- gcc/testsuite/gcc.target/aarch64/sve/init_8.c 2019-06-18 09:35:52.945885794 +0100
+++ gcc/testsuite/gcc.target/aarch64/sve/init_8.c 2019-07-16 14:57:25.602820637 +0100
@@ -1,5 +1,6 @@
/* { dg-do assemble { target aarch64_asm_sve_ok } } */
/* { dg-options "-O -msve-vector-bits=256 --save-temps" } */
+/* { dg-final { scan-assembler {\tld1w\t(z[0-9]+\.s), p[0-9]+/z, \[x[0-9]+\]\n\tmov\t(z[0-9]+\.s), w3\n\tinsr\t\2, w2\n\tinsr\t\2, w1\n\tinsr\t\2, w0\n\tzip1\t\2, \2, \1} } } */
/* Case 5.2: Interleaved elements and constants. */
@@ -7,26 +8,19 @@
typedef int32_t vnx4si __attribute__((vector_size (32)));
+/*
+** foo:
+** ...
+** ld1w (z[0-9]+\.s), p[0-9]+/z, \[x[0-9]+\]
+** mov (z[0-9]+\.s), w3
+** insr \2, w2
+** insr \2, w1
+** insr \2, w0
+** zip1 \2, \2, \1
+** ...
+*/
__attribute__((noipa))
vnx4si foo(int a, int b, int c, int d)
{
return (vnx4si) { a, 1, b, 2, c, 3, d, 4 };
}
-
-/*
-foo:
-.LFB0:
- .cfi_startproc
- ptrue p0.s, vl8
- adrp x4, .LANCHOR0
- add x4, x4, :lo12:.LANCHOR0
- ld1w z1.s, p0/z, [x4]
- mov z0.s, w3
- insr z0.s, w2
- insr z0.s, w1
- insr z0.s, w0
- zip1 z0.s, z0.s, z1.s
- ret
-*/
-
-/* { dg-final { scan-assembler {\tld1w\t(z[0-9]+\.s), p[0-9]+/z, \[x[0-9]+\]\n\tmov\t(z[0-9]+\.s), w3\n\tinsr\t\2, w2\n\tinsr\t\2, w1\n\tinsr\t\2, w0\n\tzip1\t\2, \2, \1} } } */
Index: gcc/testsuite/gcc.target/aarch64/sve/init_9.c
===================================================================
--- gcc/testsuite/gcc.target/aarch64/sve/init_9.c 2019-06-18 09:35:52.945885794 +0100
+++ gcc/testsuite/gcc.target/aarch64/sve/init_9.c 2019-07-16 14:57:25.602820637 +0100
@@ -1,5 +1,6 @@
/* { dg-do assemble { target aarch64_asm_sve_ok } } */
/* { dg-options "-O -msve-vector-bits=256 --save-temps" } */
+/* { dg-final { check-function-bodies "**" "" } } */
/* Case 5.3: Repeated elements. */
@@ -7,20 +8,15 @@
typedef int32_t vnx4si __attribute__((vector_size (32)));
+/*
+** foo:
+** mov (z[0-9]+\.s), w0
+** mov (z[0-9]+\.s), w1
+** zip1 \1, \1, \2
+** ...
+*/
__attribute__((noipa))
vnx4si foo(int a, int b)
{
return (vnx4si) { a, b, a, b, a, b, a, b };
}
-
-/*
-foo:
-.LFB0:
- .cfi_startproc
- mov z0.s, w0
- mov z1.s, w1
- zip1 z0.s, z0.s, z1.s
- ret
-*/
-
-/* { dg-final { scan-assembler {\tmov\t(z[0-9]+\.s), w0\n\tmov\t(z[0-9]+\.s), w1\n\tzip1\t\1, \1, \2} } } */
Index: gcc/testsuite/gcc.target/aarch64/sve/init_10.c
===================================================================
--- gcc/testsuite/gcc.target/aarch64/sve/init_10.c 2019-06-18 09:35:52.945885794 +0100
+++ gcc/testsuite/gcc.target/aarch64/sve/init_10.c 2019-07-16 14:57:25.602820637 +0100
@@ -1,5 +1,6 @@
/* { dg-do assemble { target aarch64_asm_sve_ok } } */
/* { dg-options "-O -msve-vector-bits=256 --save-temps" } */
+/* { dg-final { check-function-bodies "**" "" } } */
/* Case 5.4: Interleaved repeating elements and non-repeating elements. */
@@ -7,22 +8,17 @@
typedef int32_t vnx4si __attribute__((vector_size (32)));
+/*
+** foo:
+** mov (z[0-9]+\.s), w3
+** mov (z[0-9]+\.s), w2
+** insr \2, w1
+** insr \2, w0
+** zip1 \2, \2, \1
+** ...
+*/
__attribute__((noipa))
vnx4si foo(int a, int b, int c, int f)
{
return (vnx4si) { a, f, b, f, c, f, c, f };
}
-
-/*
-foo:
-.LFB0:
- .cfi_startproc
- mov z1.s, w3
- mov z0.s, w2
- insr z0.s, w1
- insr z0.s, w0
- zip1 z0.s, z0.s, z1.s
- ret
-*/
-
-/* { dg-final { scan-assembler {\tmov\t(z[0-9]+\.s), w3\n\tmov\t(z[0-9]+\.s), w2\n\tinsr\t\2, w1\n\tinsr\t\2, w0\n\tzip1\t\2, \2, \1} } } */
Index: gcc/testsuite/gcc.target/aarch64/sve/init_11.c
===================================================================
--- gcc/testsuite/gcc.target/aarch64/sve/init_11.c 2019-06-18 09:35:52.949885761 +0100
+++ gcc/testsuite/gcc.target/aarch64/sve/init_11.c 2019-07-16 14:57:25.602820637 +0100
@@ -1,5 +1,6 @@
/* { dg-do assemble { target aarch64_asm_sve_ok } } */
/* { dg-options "-O -msve-vector-bits=256 --save-temps" } */
+/* { dg-final { check-function-bodies "**" "" } } */
/* Case 5.5: Interleaved repeating elements and trailing same elements. */
@@ -7,21 +8,16 @@
typedef int32_t vnx4si __attribute__((vector_size (32)));
+/*
+** foo:
+** mov (z[0-9]+\.s), w1
+** insr \1, w0
+** mov (z[0-9]+\.s), w2
+** zip1 \1, \1, \2
+** ...
+*/
__attribute__((noipa))
vnx4si foo(int a, int b, int f)
{
return (vnx4si) { a, f, b, f, b, f, b, f };
}
-
-/*
-foo:
-.LFB0:
- .cfi_startproc
- mov z0.s, w1
- insr z0.s, w0
- mov z1.s, w2
- zip1 z0.s, z0.s, z1.s
- ret
-*/
-
-/* { dg-final { scan-assembler {\tmov\t(z[0-9]+\.s), w1\n\tinsr\t\1, w0\n\tmov\t(z[0-9]+\.s), w2\n\tzip1\t\1, \1, \2} } } */
Index: gcc/testsuite/gcc.target/aarch64/sve/init_12.c
===================================================================
--- gcc/testsuite/gcc.target/aarch64/sve/init_12.c 2019-06-18 09:35:52.949885761 +0100
+++ gcc/testsuite/gcc.target/aarch64/sve/init_12.c 2019-07-16 14:57:25.602820637 +0100
@@ -1,5 +1,6 @@
/* { dg-do assemble { target aarch64_asm_sve_ok } } */
/* { dg-options "-O -msve-vector-bits=256 --save-temps" } */
+/* { dg-final { check-function-bodies "**" "" } } */
/* Case 5.5: Interleaved repeating elements and trailing same elements. */
@@ -7,23 +8,18 @@
typedef int32_t vnx4si __attribute__((vector_size (32)));
+/*
+** foo:
+** mov (z[0-9]+\.s), w2
+** mov (z[0-9]+\.s), w0
+** insr \2, w1
+** insr \2, w1
+** insr \2, w1
+** zip1 \2, \2, \1
+** ...
+*/
__attribute__((noipa))
vnx4si foo(int a, int b, int f)
{
return (vnx4si) { b, f, b, f, b, f, a, f };
}
-
-/*
-foo:
-.LFB0:
- .cfi_startproc
- mov z1.s, w2
- mov z0.s, w0
- insr z0.s, w1
- insr z0.s, w1
- insr z0.s, w1
- zip1 z0.s, z0.s, z1.s
- ret
-*/
-
-/* { dg-final { scan-assembler {\tmov\t(z[0-9]+\.s), w2\n\tmov\t(z[0-9]+\.s), w0\n\tinsr\t\2, w1\n\tinsr\t\2, w1\n\tinsr\t\2, w1\n\tzip1\t\2, \2, \1} } } */
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Add dg test for matching function bodies
2019-07-16 14:14 Add dg test for matching function bodies Richard Sandiford
@ 2019-07-21 20:16 ` Jeff Law
2023-09-04 21:05 ` [WIP] testsuite: Port 'check-function-bodies' to nvptx (was: Add dg test for matching function bodies) Thomas Schwinge
1 sibling, 0 replies; 6+ messages in thread
From: Jeff Law @ 2019-07-21 20:16 UTC (permalink / raw)
To: gcc-patches, richard.sandiford
On 7/16/19 8:04 AM, Richard Sandiford wrote:
> There isn't a 1:1 mapping from SVE intrinsics to SVE instructions,
> but the intrinsics are still close enough to the instructions for
> there to be a specific preferred sequence (or sometimes choice of
> preferred sequences) for a given combination of operands. Sometimes
> these sequences will be one instruction, sometimes they'll be several.
>
> I therefore wanted a convenient way of matching the exact assembly
> implementation of a given function. It's possible to do that using
> single scan-assembler lines, but:
>
> (a) they become hard to read for multiline matches
> (b) the PASS/FAIL lines tend to be long
> (c) it's useful to have a single place that skips over uninteresting
> lines, such as entry block labels and .cfi_* directives, without
> being overly broad
>
> This patch therefore adds a new check-function-bodies dg-final test
> that looks for specially-formatted comments. As a demo, the patch
> converts the SVE vec_init tests to use the new harness instead of
> scan-assembler.
>
> The regexps in parse_function_bodies are fairly general, but might
> still need to be extended in future for targets like Darwin or AIX.
>
> Tested on aarch64-linux-gnu (and x86_64-linux-gnu, somewhat pointlessly
> given the contents of the patch). OK to install?
>
> Richard
>
>
> 2019-07-16 Richard Sandiford <richard.sandiford@arm.com>
>
> gcc/
> * doc/sourcebuild.texi (check-function-bodies): Document.
>
> gcc/testsuite/
> * lib/scanasm.exp (parse_function_bodies, check_function_body)
> (check-function-bodies): New procedures.
> * gcc.target/aarch64/sve/init_1.c: Use check-function-bodies
> instead of scan-assembler.
> * gcc.target/aarch64/sve/init_2.c: Likewise.
> * gcc.target/aarch64/sve/init_3.c: Likewise.
> * gcc.target/aarch64/sve/init_4.c: Likewise.
> * gcc.target/aarch64/sve/init_5.c: Likewise.
> * gcc.target/aarch64/sve/init_6.c: Likewise.
> * gcc.target/aarch64/sve/init_7.c: Likewise.
> * gcc.target/aarch64/sve/init_8.c: Likewise.
> * gcc.target/aarch64/sve/init_9.c: Likewise.
> * gcc.target/aarch64/sve/init_10.c: Likewise.
> * gcc.target/aarch64/sve/init_11.c: Likewise.
> * gcc.target/aarch64/sve/init_12.c: Likewise.
OK
jeff
^ permalink raw reply [flat|nested] 6+ messages in thread
* [WIP] testsuite: Port 'check-function-bodies' to nvptx (was: Add dg test for matching function bodies)
2019-07-16 14:14 Add dg test for matching function bodies Richard Sandiford
2019-07-21 20:16 ` Jeff Law
@ 2023-09-04 21:05 ` Thomas Schwinge
2023-09-05 12:20 ` Thomas Schwinge
1 sibling, 1 reply; 6+ messages in thread
From: Thomas Schwinge @ 2023-09-04 21:05 UTC (permalink / raw)
To: Richard Sandiford, gcc-patches; +Cc: Tom de Vries, Roger Sayle
[-- Attachment #1: Type: text/plain, Size: 2677 bytes --]
Hi!
On 2019-07-16T15:04:49+0100, Richard Sandiford <richard.sandiford@arm.com> wrote:
> There isn't a 1:1 mapping from SVE intrinsics to SVE instructions,
> but the intrinsics are still close enough to the instructions for
> there to be a specific preferred sequence (or sometimes choice of
> preferred sequences) for a given combination of operands. Sometimes
> these sequences will be one instruction, sometimes they'll be several.
>
> I therefore wanted a convenient way of matching the exact assembly
> implementation of a given function. It's possible to do that using
> single scan-assembler lines, but:
>
> (a) they become hard to read for multiline matches
> (b) the PASS/FAIL lines tend to be long
> (c) it's useful to have a single place that skips over uninteresting
> lines, such as entry block labels and .cfi_* directives, without
> being overly broad
>
> This patch therefore adds a new check-function-bodies dg-final test
> that looks for specially-formatted comments. As a demo, the patch
> converts the SVE vec_init tests to use the new harness instead of
> scan-assembler.
Great, thanks, belatedly!
> The regexps in parse_function_bodies are fairly general, but might
> still need to be extended in future for targets like Darwin or AIX.
..., or nvptx. As an example, I'm attaching the 'abort.s' generated for
'gcc.target/nvptx/abort.c'.
I'm further attaching a crude ;-) (obviously, not intending to push in
this form) "[WIP] testsuite: Port 'check-function-bodies' to nvptx" to
illustrate that (a) it can be made work for nvptx, but (b) there are a
number of TODO items.
In particular how to parameterize regular expressions for the different
syntax used by nvptx: for example, parameterize via global variables,
initialized accordingly (where?)? Thinking about it, maybe simply
conditionalizing the current local initializations by
'if { [istarget nvptx-*-*] } { [...] } else { [...] }' will do, simple
enough!
Regarding whitespace prefixed, I think I'll go with the current
'append function_regexp "\t" $line "\n"', that is, prefix expected output
lines with '\t' (as done in 'gcc.target/nvptx/abort.c'), and also for
nvptx handle labels as "fluff" (until we solve that issue generally).
(I'll look into all that later, but wanted to post this now, in case
anyone has different ideas.)
Grüße
Thomas
-----------------
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht München, HRB 106955
[-- Attachment #2: abort.s --]
[-- Type: text/plain, Size: 733 bytes --]
// BEGIN PREAMBLE
.version 6.0
.target sm_30
.address_size 64
// END PREAMBLE
// BEGIN GLOBAL FUNCTION DECL: main
.visible .func (.param.u32 %value_out) main (.param.u32 %in_ar0, .param.u64 %in_ar1);
// BEGIN GLOBAL FUNCTION DEF: main
.visible .func (.param.u32 %value_out) main (.param.u32 %in_ar0, .param.u64 %in_ar1)
{
.reg.u32 %value;
.reg.u32 %ar0;
ld.param.u32 %ar0, [%in_ar0];
.reg.u64 %ar1;
ld.param.u64 %ar1, [%in_ar1];
.reg.u32 %r23;
.reg.pred %r25;
mov.u32 %r23, %ar0;
setp.le.s32 %r25, %r23, 2;
@%r25 bra $L2;
{
call abort;
trap; // (noreturn)
exit; // (noreturn)
}
$L2:
mov.u32 %value, 0;
st.param.u32 [%value_out], %value;
ret;
}
// BEGIN GLOBAL FUNCTION DECL: abort
.extern .func abort;
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: 0001-WIP-testsuite-Port-check-function-bodies-to-nvptx.patch --]
[-- Type: text/x-diff, Size: 4647 bytes --]
From 1a15a9dbd8cfc3c2f5df72653614c5c70a0c6018 Mon Sep 17 00:00:00 2001
From: Thomas Schwinge <thomas@codesourcery.com>
Date: Mon, 4 Sep 2023 22:28:12 +0200
Subject: [PATCH] [WIP] testsuite: Port 'check-function-bodies' to nvptx
This extends commit 4d706ff86ea86868615558e92407674a4f4b4af9
"Add dg test for matching function bodies" for nvptx.
---
gcc/doc/sourcebuild.texi | 2 ++
gcc/testsuite/gcc.target/nvptx/abort.c | 19 +++++++++++++++++--
gcc/testsuite/lib/scanasm.exp | 21 +++++++++++++++++----
3 files changed, 36 insertions(+), 6 deletions(-)
diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
index 60a708e88c0..d83da89f9ba 100644
--- a/gcc/doc/sourcebuild.texi
+++ b/gcc/doc/sourcebuild.texi
@@ -3319,6 +3319,7 @@ function body for unoptimized code.
The first line of the expected output for a function @var{fn} has the form:
+@c TODO
@smallexample
@var{prefix} @var{fn}: [@{ target/xfail @var{selector} @}]
@end smallexample
@@ -3326,6 +3327,7 @@ The first line of the expected output for a function @var{fn} has the form:
Subsequent lines of the expected output also start with @var{prefix}.
In both cases, whitespace after @var{prefix} is not significant.
+@c TODO
The test discards assembly directives such as @code{.cfi_startproc}
and local label definitions such as @code{.LFB0} from the compiler's
assembly output. It then matches the result against the expected
diff --git a/gcc/testsuite/gcc.target/nvptx/abort.c b/gcc/testsuite/gcc.target/nvptx/abort.c
index d3220687400..aae90e38872 100644
--- a/gcc/testsuite/gcc.target/nvptx/abort.c
+++ b/gcc/testsuite/gcc.target/nvptx/abort.c
@@ -1,4 +1,6 @@
/* { dg-do compile} */
+/* { dg-final { check-function-bodies {**} {} } } */
+
/* Annotate no return functions with a trailing 'trap'. */
extern void abort ();
@@ -9,5 +11,18 @@ int main (int argc, char **argv)
abort ();
return 0;
}
-
-/* { dg-final { scan-assembler "call abort;\[\r\n\t \]+trap;" } } */
+/*
+** // BEGIN GLOBAL FUNCTION DEF: main
+** ...
+** \.reg\.pred (%r[0-9]+);
+** ...
+** @\1 bra (\$L[0-9]+);
+** {
+** \tcall abort;
+** \ttrap; // \(noreturn\)
+** \texit; // \(noreturn\)
+** }
+TODO** \2:
+TODO This label currently cannot be matched.
+** ...
+*/
diff --git a/gcc/testsuite/lib/scanasm.exp b/gcc/testsuite/lib/scanasm.exp
index 0685de1d641..7cc9f7cae7d 100644
--- a/gcc/testsuite/lib/scanasm.exp
+++ b/gcc/testsuite/lib/scanasm.exp
@@ -785,13 +785,16 @@ proc parse_function_bodies { filename result } {
upvar $result up_result
# Regexp for the start of a function definition (name in \1).
- set label {^([a-zA-Z_]\S+):$}
+ #TODO
+ set label {^// BEGIN GLOBAL FUNCTION DEF: ([a-zA-Z_]\S+)$}
# Regexp for the end of a function definition.
- set terminator {^\s*\.size}
+ #TODO
+ set terminator {^\}$}
# Regexp for lines that aren't interesting.
- set fluff {^\s*(?:\.|//|@|$)}
+ #TODO n/a -- or still TODO
+ set fluff {^\s*$}
set fd [open $filename r]
set in_function 0
@@ -801,6 +804,7 @@ proc parse_function_bodies { filename result } {
set function_body ""
} elseif { $in_function } {
if { [regexp $terminator $line] } {
+ #verbose -log "parse_function_bodies: $function_name\n$function_body"
set up_result($function_name) $function_body
set in_function 0
} elseif { ![regexp $fluff $line] } {
@@ -907,7 +911,8 @@ proc check-function-bodies { args } {
set count 0
set function_regexp ""
- set label {^(\S+):$}
+ #TODO
+ set label {^// BEGIN GLOBAL FUNCTION DEF: ([a-zA-Z_]\S+)$}
set lineno 1
set fd [open $input_filename r]
@@ -937,7 +942,15 @@ proc check-function-bodies { args } {
} elseif { [string equal $line "..."] } {
append function_regexp ".*"
} else {
+ #TODO
+ # Certain (predicable) nvptx instructions are emitted with additional whitespace prefixed.
+ # Prune that here, or include in expected output lines?
+ # On the other hand, labels are emitted in column zero (for no particular reason as far as I can tell; could be changed).
+ # (Whitespace is not significant there.)
+ # But: labels are also in column zero for x86_64 assembly, for example, so that's a pre-existing issue, to be solved generally.
+ # Actually, they're filtered out as "fluff", so that's generally a non-issue vs. TODO item.
append function_regexp "\t" $line "\n"
+ #append function_regexp {\s*} $line {\n}
}
} elseif { [string equal -length $terminator_len $line $terminator] } {
if { ![string equal $selector "N"] } {
--
2.34.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* testsuite: Port 'check-function-bodies' to nvptx (was: Add dg test for matching function bodies)
2023-09-04 21:05 ` [WIP] testsuite: Port 'check-function-bodies' to nvptx (was: Add dg test for matching function bodies) Thomas Schwinge
@ 2023-09-05 12:20 ` Thomas Schwinge
2023-09-05 14:28 ` testsuite: Port 'check-function-bodies' to nvptx Richard Sandiford
0 siblings, 1 reply; 6+ messages in thread
From: Thomas Schwinge @ 2023-09-05 12:20 UTC (permalink / raw)
To: Richard Sandiford, gcc-patches; +Cc: Tom de Vries, Roger Sayle
[-- Attachment #1: Type: text/plain, Size: 2143 bytes --]
Hi!
On 2023-09-04T23:05:05+0200, I wrote:
> On 2019-07-16T15:04:49+0100, Richard Sandiford <richard.sandiford@arm.com> wrote:
>> This patch therefore adds a new check-function-bodies dg-final test
>> The regexps in parse_function_bodies are fairly general, but might
>> still need to be extended in future for targets like Darwin or AIX.
>
> ..., or nvptx. [...]
> number of TODO items.
>
> In particular how to parameterize regular expressions for the different
> syntax used by nvptx: for example, parameterize via global variables,
> initialized accordingly (where?)? Thinking about it, maybe simply
> conditionalizing the current local initializations by
> 'if { [istarget nvptx-*-*] } { [...] } else { [...] }' will do, simple
> enough!
Indeed that works fine.
> Regarding whitespace prefixed, I think I'll go with the current
> 'append function_regexp "\t" $line "\n"', that is, prefix expected output
> lines with '\t' (as done in 'gcc.target/nvptx/abort.c'), and also for
> nvptx handle labels as "fluff" (until we solve that issue generally).
I changed my mind about that: instead of '\t', use '\t*' for nvptx, which
means that both instructions emitted with additional whitespace prefixed
and labels in column zero work nicely.
> --- a/gcc/testsuite/lib/scanasm.exp
> +++ b/gcc/testsuite/lib/scanasm.exp
> @@ -907,7 +911,8 @@ proc check-function-bodies { args } {
>
> set count 0
> set function_regexp ""
> - set label {^(\S+):$}
> + #TODO
> + set label {^// BEGIN GLOBAL FUNCTION DEF: ([a-zA-Z_]\S+)$}
There's actually no reason that the expected output syntax (this one) has
to match the assembly -- so I restored that, to use the same syntax for
nvptx here, too.
Any comments before I push the attached
"testsuite: Port 'check-function-bodies' to nvptx"?
Grüße
Thomas
-----------------
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht München, HRB 106955
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-testsuite-Port-check-function-bodies-to-nvptx.patch --]
[-- Type: text/x-diff, Size: 7576 bytes --]
From bdaf7572d9d4c1988274405840de4071ded3733f Mon Sep 17 00:00:00 2001
From: Thomas Schwinge <thomas@codesourcery.com>
Date: Mon, 4 Sep 2023 22:28:12 +0200
Subject: [PATCH] testsuite: Port 'check-function-bodies' to nvptx
This extends commit 4d706ff86ea86868615558e92407674a4f4b4af9
"Add dg test for matching function bodies" for nvptx.
gcc/testsuite/
* lib/scanasm.exp (configure_check-function-bodies): New proc.
(parse_function_bodies, check-function-bodies): Use it.
* gcc.target/nvptx/abort.c: Use 'check-function-bodies'.
gcc/
* doc/sourcebuild.texi (check-function-bodies): Update.
---
gcc/doc/sourcebuild.texi | 9 ++-
gcc/testsuite/gcc.target/nvptx/abort.c | 19 ++++++-
gcc/testsuite/lib/scanasm.exp | 76 ++++++++++++++++++++------
3 files changed, 83 insertions(+), 21 deletions(-)
diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
index 1a78b3c1abb..8aec6b6592c 100644
--- a/gcc/doc/sourcebuild.texi
+++ b/gcc/doc/sourcebuild.texi
@@ -3327,9 +3327,12 @@ The first line of the expected output for a function @var{fn} has the form:
Subsequent lines of the expected output also start with @var{prefix}.
In both cases, whitespace after @var{prefix} is not significant.
-The test discards assembly directives such as @code{.cfi_startproc}
-and local label definitions such as @code{.LFB0} from the compiler's
-assembly output. It then matches the result against the expected
+Depending on the configuration (see
+@code{gcc/testsuite/lib/scanasm.exp:configure_check-function-bodies}),
+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:
diff --git a/gcc/testsuite/gcc.target/nvptx/abort.c b/gcc/testsuite/gcc.target/nvptx/abort.c
index d3220687400..ae9dbf45a9b 100644
--- a/gcc/testsuite/gcc.target/nvptx/abort.c
+++ b/gcc/testsuite/gcc.target/nvptx/abort.c
@@ -1,4 +1,6 @@
/* { dg-do compile} */
+/* { dg-final { check-function-bodies {**} {} } } */
+
/* Annotate no return functions with a trailing 'trap'. */
extern void abort ();
@@ -9,5 +11,18 @@ int main (int argc, char **argv)
abort ();
return 0;
}
-
-/* { dg-final { scan-assembler "call abort;\[\r\n\t \]+trap;" } } */
+/*
+** main:
+** ...
+** \.reg\.pred (%r[0-9]+);
+** ...
+** @\1 bra (\$L[0-9]+);
+** {
+** call abort;
+** trap; // \(noreturn\)
+** exit; // \(noreturn\)
+** }
+** \2:
+** \tmov\.u32 %r[0-9]+, 0;
+** ...
+*/
diff --git a/gcc/testsuite/lib/scanasm.exp b/gcc/testsuite/lib/scanasm.exp
index 0685de1d641..5df80325dff 100644
--- a/gcc/testsuite/lib/scanasm.exp
+++ b/gcc/testsuite/lib/scanasm.exp
@@ -777,33 +777,73 @@ proc scan-lto-assembler { args } {
dg-scan "scan-lto-assembler" 1 $testcase $output_file $args
}
-# Read assembly file FILENAME and store a mapping from function names
-# to function bodies in array RESULT. FILENAME has already been uploaded
-# locally where necessary and is known to exist.
-proc parse_function_bodies { filename result } {
- upvar $result up_result
+# Set up CONFIG for check-function-bodies.
+
+proc configure_check-function-bodies { config } {
+ upvar $config up_config
# Regexp for the start of a function definition (name in \1).
- set label {^([a-zA-Z_]\S+):$}
+ if { [istarget nvptx*-*-*] } {
+ set up_config(start) {^// BEGIN(?: GLOBAL|) FUNCTION DEF: ([a-zA-Z_]\S+)$}
+ } else {
+ set up_config(start) {^([a-zA-Z_]\S+):$}
+ }
# Regexp for the end of a function definition.
- set terminator {^\s*\.size}
-
+ if { [istarget nvptx*-*-*] } {
+ set up_config(end) {^\}$}
+ } else {
+ set up_config(end) {^\s*\.size}
+ }
+
# Regexp for lines that aren't interesting.
- set fluff {^\s*(?:\.|//|@|$)}
+ if { [istarget nvptx*-*-*] } {
+ # Skip lines beginning with '//' comments ('-fverbose-asm', for
+ # example).
+ set up_config(fluff) {^\s*(?://)}
+ } else {
+ # Skip lines beginning with labels ('.L[...]:') or other directives
+ # ('.align', '.cfi_startproc', '.quad [...]', '.text', etc.), '//' or
+ # '@' comments ('-fverbose-asm' or ARM-style, for example), or empty
+ # lines.
+ set up_config(fluff) {^\s*(?:\.|//|@|$)}
+ }
+
+ # Regexp for expected output lines prefix.
+ if { [istarget nvptx*-*-*] } {
+ # Certain instructions (such as predicable ones) are emitted with
+ # additional whitespace prefixed. On the other hand, labels don't get
+ # any whitespace prefixed, and we'd like to be able to match these,
+ # too. We thereare expect any amount of whitespace here.
+ set up_config(line_prefix) {\t*}
+ } else {
+ set up_config(line_prefix) {\t}
+ }
+}
+
+# Per CONFIG, read assembly file FILENAME and store a mapping from function
+# names to function bodies in array RESULT. FILENAME has already been uploaded
+# locally where necessary and is known to exist.
+
+proc parse_function_bodies { config filename result } {
+ upvar $config up_config
+ upvar $result up_result
set fd [open $filename r]
set in_function 0
while { [gets $fd line] >= 0 } {
- if { [regexp $label $line dummy function_name] } {
+ if { [regexp $up_config(start) $line dummy function_name] } {
set in_function 1
set function_body ""
} elseif { $in_function } {
- if { [regexp $terminator $line] } {
+ if { [regexp $up_config(end) $line] } {
+ verbose "parse_function_bodies: $function_name:\n$function_body"
set up_result($function_name) $function_body
set in_function 0
- } elseif { ![regexp $fluff $line] } {
+ } elseif { [regexp $up_config(fluff) $line] } {
+ verbose "parse_function_bodies: $function_name: ignoring fluff line: $line"
+ } else {
append function_body $line "\n"
}
}
@@ -893,13 +933,18 @@ proc check-function-bodies { args } {
set terminator "*/"
}
set terminator_len [string length $terminator]
+ # Regexp for the start of a function definition in expected output lines
+ # (name in \1). This may be different from '$config(start)'.
+ set start_expected {^(\S+):$}
+
+ configure_check-function-bodies config
set have_bodies 0
if { [is_remote host] } {
remote_upload host "$filename"
}
if { [file exists $output_filename] } {
- parse_function_bodies $output_filename functions
+ parse_function_bodies config $output_filename functions
set have_bodies 1
} else {
verbose -log "$testcase: output file does not exist"
@@ -907,7 +952,6 @@ proc check-function-bodies { args } {
set count 0
set function_regexp ""
- set label {^(\S+):$}
set lineno 1
set fd [open $input_filename r]
@@ -922,7 +966,7 @@ proc check-function-bodies { args } {
} else {
set selector "P"
}
- if { ![regexp $label $line dummy function_name] } {
+ if { ![regexp $start_expected $line dummy function_name] } {
close $fd
error "check-function-bodies: line $lineno does not have a function label"
}
@@ -937,7 +981,7 @@ proc check-function-bodies { args } {
} elseif { [string equal $line "..."] } {
append function_regexp ".*"
} else {
- append function_regexp "\t" $line "\n"
+ append function_regexp $config(line_prefix) $line "\n"
}
} elseif { [string equal -length $terminator_len $line $terminator] } {
if { ![string equal $selector "N"] } {
--
2.34.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: testsuite: Port 'check-function-bodies' to nvptx
2023-09-05 12:20 ` Thomas Schwinge
@ 2023-09-05 14:28 ` Richard Sandiford
2023-09-12 8:45 ` Thomas Schwinge
0 siblings, 1 reply; 6+ messages in thread
From: Richard Sandiford @ 2023-09-05 14:28 UTC (permalink / raw)
To: Thomas Schwinge; +Cc: gcc-patches, Tom de Vries, Roger Sayle
Thomas Schwinge <thomas@codesourcery.com> writes:
> Hi!
>
> On 2023-09-04T23:05:05+0200, I wrote:
>> On 2019-07-16T15:04:49+0100, Richard Sandiford <richard.sandiford@arm.com> wrote:
>>> This patch therefore adds a new check-function-bodies dg-final test
>
>>> The regexps in parse_function_bodies are fairly general, but might
>>> still need to be extended in future for targets like Darwin or AIX.
>>
>> ..., or nvptx. [...]
>
>> number of TODO items.
>>
>> In particular how to parameterize regular expressions for the different
>> syntax used by nvptx: for example, parameterize via global variables,
>> initialized accordingly (where?)? Thinking about it, maybe simply
>> conditionalizing the current local initializations by
>> 'if { [istarget nvptx-*-*] } { [...] } else { [...] }' will do, simple
>> enough!
>
> Indeed that works fine.
>
>> Regarding whitespace prefixed, I think I'll go with the current
>> 'append function_regexp "\t" $line "\n"', that is, prefix expected output
>> lines with '\t' (as done in 'gcc.target/nvptx/abort.c'), and also for
>> nvptx handle labels as "fluff" (until we solve that issue generally).
>
> I changed my mind about that: instead of '\t', use '\t*' for nvptx, which
> means that both instructions emitted with additional whitespace prefixed
> and labels in column zero work nicely.
>
>> --- a/gcc/testsuite/lib/scanasm.exp
>> +++ b/gcc/testsuite/lib/scanasm.exp
>
>> @@ -907,7 +911,8 @@ proc check-function-bodies { args } {
>>
>> set count 0
>> set function_regexp ""
>> - set label {^(\S+):$}
>> + #TODO
>> + set label {^// BEGIN GLOBAL FUNCTION DEF: ([a-zA-Z_]\S+)$}
>
> There's actually no reason that the expected output syntax (this one) has
> to match the assembly -- so I restored that, to use the same syntax for
> nvptx here, too.
>
> Any comments before I push the attached
> "testsuite: Port 'check-function-bodies' to nvptx"?
>
>
> Grüße
> Thomas
>
>
> -----------------
> Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht München, HRB 106955
>
> From bdaf7572d9d4c1988274405840de4071ded3733f Mon Sep 17 00:00:00 2001
> From: Thomas Schwinge <thomas@codesourcery.com>
> Date: Mon, 4 Sep 2023 22:28:12 +0200
> Subject: [PATCH] testsuite: Port 'check-function-bodies' to nvptx
>
> This extends commit 4d706ff86ea86868615558e92407674a4f4b4af9
> "Add dg test for matching function bodies" for nvptx.
>
> gcc/testsuite/
> * lib/scanasm.exp (configure_check-function-bodies): New proc.
> (parse_function_bodies, check-function-bodies): Use it.
> * gcc.target/nvptx/abort.c: Use 'check-function-bodies'.
> gcc/
> * doc/sourcebuild.texi (check-function-bodies): Update.
LGTM. Just a minor comment:
> ---
> gcc/doc/sourcebuild.texi | 9 ++-
> gcc/testsuite/gcc.target/nvptx/abort.c | 19 ++++++-
> gcc/testsuite/lib/scanasm.exp | 76 ++++++++++++++++++++------
> 3 files changed, 83 insertions(+), 21 deletions(-)
>
> diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
> index 1a78b3c1abb..8aec6b6592c 100644
> --- a/gcc/doc/sourcebuild.texi
> +++ b/gcc/doc/sourcebuild.texi
> @@ -3327,9 +3327,12 @@ The first line of the expected output for a function @var{fn} has the form:
> Subsequent lines of the expected output also start with @var{prefix}.
> In both cases, whitespace after @var{prefix} is not significant.
>
> -The test discards assembly directives such as @code{.cfi_startproc}
> -and local label definitions such as @code{.LFB0} from the compiler's
> -assembly output. It then matches the result against the expected
> +Depending on the configuration (see
> +@code{gcc/testsuite/lib/scanasm.exp:configure_check-function-bodies}),
I can imagine such a long string wouldn't format well in the output.
How about: @code{configure_check-function-bodies} in
@filename{gcc/testsuite/lib/scanasm.exp}?
OK from my POV with that change.
Thanks,
Richard
> +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:
> diff --git a/gcc/testsuite/gcc.target/nvptx/abort.c b/gcc/testsuite/gcc.target/nvptx/abort.c
> index d3220687400..ae9dbf45a9b 100644
> --- a/gcc/testsuite/gcc.target/nvptx/abort.c
> +++ b/gcc/testsuite/gcc.target/nvptx/abort.c
> @@ -1,4 +1,6 @@
> /* { dg-do compile} */
> +/* { dg-final { check-function-bodies {**} {} } } */
> +
> /* Annotate no return functions with a trailing 'trap'. */
>
> extern void abort ();
> @@ -9,5 +11,18 @@ int main (int argc, char **argv)
> abort ();
> return 0;
> }
> -
> -/* { dg-final { scan-assembler "call abort;\[\r\n\t \]+trap;" } } */
> +/*
> +** main:
> +** ...
> +** \.reg\.pred (%r[0-9]+);
> +** ...
> +** @\1 bra (\$L[0-9]+);
> +** {
> +** call abort;
> +** trap; // \(noreturn\)
> +** exit; // \(noreturn\)
> +** }
> +** \2:
> +** \tmov\.u32 %r[0-9]+, 0;
> +** ...
> +*/
> diff --git a/gcc/testsuite/lib/scanasm.exp b/gcc/testsuite/lib/scanasm.exp
> index 0685de1d641..5df80325dff 100644
> --- a/gcc/testsuite/lib/scanasm.exp
> +++ b/gcc/testsuite/lib/scanasm.exp
> @@ -777,33 +777,73 @@ proc scan-lto-assembler { args } {
> dg-scan "scan-lto-assembler" 1 $testcase $output_file $args
> }
>
> -# Read assembly file FILENAME and store a mapping from function names
> -# to function bodies in array RESULT. FILENAME has already been uploaded
> -# locally where necessary and is known to exist.
>
> -proc parse_function_bodies { filename result } {
> - upvar $result up_result
> +# Set up CONFIG for check-function-bodies.
> +
> +proc configure_check-function-bodies { config } {
> + upvar $config up_config
>
> # Regexp for the start of a function definition (name in \1).
> - set label {^([a-zA-Z_]\S+):$}
> + if { [istarget nvptx*-*-*] } {
> + set up_config(start) {^// BEGIN(?: GLOBAL|) FUNCTION DEF: ([a-zA-Z_]\S+)$}
> + } else {
> + set up_config(start) {^([a-zA-Z_]\S+):$}
> + }
>
> # Regexp for the end of a function definition.
> - set terminator {^\s*\.size}
> -
> + if { [istarget nvptx*-*-*] } {
> + set up_config(end) {^\}$}
> + } else {
> + set up_config(end) {^\s*\.size}
> + }
> +
> # Regexp for lines that aren't interesting.
> - set fluff {^\s*(?:\.|//|@|$)}
> + if { [istarget nvptx*-*-*] } {
> + # Skip lines beginning with '//' comments ('-fverbose-asm', for
> + # example).
> + set up_config(fluff) {^\s*(?://)}
> + } else {
> + # Skip lines beginning with labels ('.L[...]:') or other directives
> + # ('.align', '.cfi_startproc', '.quad [...]', '.text', etc.), '//' or
> + # '@' comments ('-fverbose-asm' or ARM-style, for example), or empty
> + # lines.
> + set up_config(fluff) {^\s*(?:\.|//|@|$)}
> + }
> +
> + # Regexp for expected output lines prefix.
> + if { [istarget nvptx*-*-*] } {
> + # Certain instructions (such as predicable ones) are emitted with
> + # additional whitespace prefixed. On the other hand, labels don't get
> + # any whitespace prefixed, and we'd like to be able to match these,
> + # too. We thereare expect any amount of whitespace here.
> + set up_config(line_prefix) {\t*}
> + } else {
> + set up_config(line_prefix) {\t}
> + }
> +}
> +
> +# Per CONFIG, read assembly file FILENAME and store a mapping from function
> +# names to function bodies in array RESULT. FILENAME has already been uploaded
> +# locally where necessary and is known to exist.
> +
> +proc parse_function_bodies { config filename result } {
> + upvar $config up_config
> + upvar $result up_result
>
> set fd [open $filename r]
> set in_function 0
> while { [gets $fd line] >= 0 } {
> - if { [regexp $label $line dummy function_name] } {
> + if { [regexp $up_config(start) $line dummy function_name] } {
> set in_function 1
> set function_body ""
> } elseif { $in_function } {
> - if { [regexp $terminator $line] } {
> + if { [regexp $up_config(end) $line] } {
> + verbose "parse_function_bodies: $function_name:\n$function_body"
> set up_result($function_name) $function_body
> set in_function 0
> - } elseif { ![regexp $fluff $line] } {
> + } elseif { [regexp $up_config(fluff) $line] } {
> + verbose "parse_function_bodies: $function_name: ignoring fluff line: $line"
> + } else {
> append function_body $line "\n"
> }
> }
> @@ -893,13 +933,18 @@ proc check-function-bodies { args } {
> set terminator "*/"
> }
> set terminator_len [string length $terminator]
> + # Regexp for the start of a function definition in expected output lines
> + # (name in \1). This may be different from '$config(start)'.
> + set start_expected {^(\S+):$}
> +
> + configure_check-function-bodies config
>
> set have_bodies 0
> if { [is_remote host] } {
> remote_upload host "$filename"
> }
> if { [file exists $output_filename] } {
> - parse_function_bodies $output_filename functions
> + parse_function_bodies config $output_filename functions
> set have_bodies 1
> } else {
> verbose -log "$testcase: output file does not exist"
> @@ -907,7 +952,6 @@ proc check-function-bodies { args } {
>
> set count 0
> set function_regexp ""
> - set label {^(\S+):$}
>
> set lineno 1
> set fd [open $input_filename r]
> @@ -922,7 +966,7 @@ proc check-function-bodies { args } {
> } else {
> set selector "P"
> }
> - if { ![regexp $label $line dummy function_name] } {
> + if { ![regexp $start_expected $line dummy function_name] } {
> close $fd
> error "check-function-bodies: line $lineno does not have a function label"
> }
> @@ -937,7 +981,7 @@ proc check-function-bodies { args } {
> } elseif { [string equal $line "..."] } {
> append function_regexp ".*"
> } else {
> - append function_regexp "\t" $line "\n"
> + append function_regexp $config(line_prefix) $line "\n"
> }
> } elseif { [string equal -length $terminator_len $line $terminator] } {
> if { ![string equal $selector "N"] } {
^ permalink raw reply [flat|nested] 6+ messages in thread
* testsuite: Port 'check-function-bodies' to nvptx
2023-09-05 14:28 ` testsuite: Port 'check-function-bodies' to nvptx Richard Sandiford
@ 2023-09-12 8:45 ` Thomas Schwinge
0 siblings, 0 replies; 6+ messages in thread
From: Thomas Schwinge @ 2023-09-12 8:45 UTC (permalink / raw)
To: Richard Sandiford, gcc-patches; +Cc: Roger Sayle, Tom de Vries
[-- Attachment #1: Type: text/plain, Size: 2156 bytes --]
Hi!
On 2023-09-05T15:28:20+0100, Richard Sandiford via Gcc-patches <gcc-patches@gcc.gnu.org> wrote:
> Thomas Schwinge <thomas@codesourcery.com> writes:
>> On 2023-09-04T23:05:05+0200, I wrote:
>>> On 2019-07-16T15:04:49+0100, Richard Sandiford <richard.sandiford@arm.com> wrote:
>>>> This patch therefore adds a new check-function-bodies dg-final test
>>
>>>> The regexps in parse_function_bodies are fairly general, but might
>>>> still need to be extended in future for targets like Darwin or AIX.
>>>
>>> ..., or nvptx. [...]
>> Any comments before I push the attached
>> "testsuite: Port 'check-function-bodies' to nvptx"?
> LGTM. Just a minor comment:
>> --- a/gcc/doc/sourcebuild.texi
>> +++ b/gcc/doc/sourcebuild.texi
>> @@ -3327,9 +3327,12 @@ The first line of the expected output for a function @var{fn} has the form:
>> Subsequent lines of the expected output also start with @var{prefix}.
>> In both cases, whitespace after @var{prefix} is not significant.
>>
>> -The test discards assembly directives such as @code{.cfi_startproc}
>> -and local label definitions such as @code{.LFB0} from the compiler's
>> -assembly output. It then matches the result against the expected
>> +Depending on the configuration (see
>> +@code{gcc/testsuite/lib/scanasm.exp:configure_check-function-bodies}),
>
> I can imagine such a long string wouldn't format well in the output.
> How about: @code{configure_check-function-bodies} in
> @filename{gcc/testsuite/lib/scanasm.exp}?
Thanks, good suggestion.
Also, I've backed out the 'gcc.target/nvptx/abort.c' change to use
'check-function-bodies', leaving that for a later commit to translate
more of 'gcc.target/nvptx/[...]'.
Pushed to master branch commit 50410234a3d2e1b85203d97fe6f65fd9d1f0e100
"testsuite: Port 'check-function-bodies' to nvptx", see attached.
Grüße
Thomas
-----------------
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht München, HRB 106955
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-testsuite-Port-check-function-bodies-to-nvptx.patch --]
[-- Type: text/x-diff, Size: 6697 bytes --]
From 50410234a3d2e1b85203d97fe6f65fd9d1f0e100 Mon Sep 17 00:00:00 2001
From: Thomas Schwinge <thomas@codesourcery.com>
Date: Mon, 4 Sep 2023 22:28:12 +0200
Subject: [PATCH] testsuite: Port 'check-function-bodies' to nvptx
This extends commit 4d706ff86ea86868615558e92407674a4f4b4af9
"Add dg test for matching function bodies" for nvptx.
gcc/testsuite/
* lib/scanasm.exp (configure_check-function-bodies): New proc.
(parse_function_bodies, check-function-bodies): Use it.
gcc/
* doc/sourcebuild.texi (check-function-bodies): Update.
---
gcc/doc/sourcebuild.texi | 9 +++--
gcc/testsuite/lib/scanasm.exp | 76 +++++++++++++++++++++++++++--------
2 files changed, 66 insertions(+), 19 deletions(-)
diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
index 1a78b3c1abb..de1aa8c2dba 100644
--- a/gcc/doc/sourcebuild.texi
+++ b/gcc/doc/sourcebuild.texi
@@ -3327,9 +3327,12 @@ The first line of the expected output for a function @var{fn} has the form:
Subsequent lines of the expected output also start with @var{prefix}.
In both cases, whitespace after @var{prefix} is not significant.
-The test discards assembly directives such as @code{.cfi_startproc}
-and local label definitions such as @code{.LFB0} from the compiler's
-assembly output. It then matches the result against the expected
+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:
diff --git a/gcc/testsuite/lib/scanasm.exp b/gcc/testsuite/lib/scanasm.exp
index 0685de1d641..5df80325dff 100644
--- a/gcc/testsuite/lib/scanasm.exp
+++ b/gcc/testsuite/lib/scanasm.exp
@@ -777,33 +777,73 @@ proc scan-lto-assembler { args } {
dg-scan "scan-lto-assembler" 1 $testcase $output_file $args
}
-# Read assembly file FILENAME and store a mapping from function names
-# to function bodies in array RESULT. FILENAME has already been uploaded
-# locally where necessary and is known to exist.
-proc parse_function_bodies { filename result } {
- upvar $result up_result
+# Set up CONFIG for check-function-bodies.
+
+proc configure_check-function-bodies { config } {
+ upvar $config up_config
# Regexp for the start of a function definition (name in \1).
- set label {^([a-zA-Z_]\S+):$}
+ if { [istarget nvptx*-*-*] } {
+ set up_config(start) {^// BEGIN(?: GLOBAL|) FUNCTION DEF: ([a-zA-Z_]\S+)$}
+ } else {
+ set up_config(start) {^([a-zA-Z_]\S+):$}
+ }
# Regexp for the end of a function definition.
- set terminator {^\s*\.size}
-
+ if { [istarget nvptx*-*-*] } {
+ set up_config(end) {^\}$}
+ } else {
+ set up_config(end) {^\s*\.size}
+ }
+
# Regexp for lines that aren't interesting.
- set fluff {^\s*(?:\.|//|@|$)}
+ if { [istarget nvptx*-*-*] } {
+ # Skip lines beginning with '//' comments ('-fverbose-asm', for
+ # example).
+ set up_config(fluff) {^\s*(?://)}
+ } else {
+ # Skip lines beginning with labels ('.L[...]:') or other directives
+ # ('.align', '.cfi_startproc', '.quad [...]', '.text', etc.), '//' or
+ # '@' comments ('-fverbose-asm' or ARM-style, for example), or empty
+ # lines.
+ set up_config(fluff) {^\s*(?:\.|//|@|$)}
+ }
+
+ # Regexp for expected output lines prefix.
+ if { [istarget nvptx*-*-*] } {
+ # Certain instructions (such as predicable ones) are emitted with
+ # additional whitespace prefixed. On the other hand, labels don't get
+ # any whitespace prefixed, and we'd like to be able to match these,
+ # too. We thereare expect any amount of whitespace here.
+ set up_config(line_prefix) {\t*}
+ } else {
+ set up_config(line_prefix) {\t}
+ }
+}
+
+# Per CONFIG, read assembly file FILENAME and store a mapping from function
+# names to function bodies in array RESULT. FILENAME has already been uploaded
+# locally where necessary and is known to exist.
+
+proc parse_function_bodies { config filename result } {
+ upvar $config up_config
+ upvar $result up_result
set fd [open $filename r]
set in_function 0
while { [gets $fd line] >= 0 } {
- if { [regexp $label $line dummy function_name] } {
+ if { [regexp $up_config(start) $line dummy function_name] } {
set in_function 1
set function_body ""
} elseif { $in_function } {
- if { [regexp $terminator $line] } {
+ if { [regexp $up_config(end) $line] } {
+ verbose "parse_function_bodies: $function_name:\n$function_body"
set up_result($function_name) $function_body
set in_function 0
- } elseif { ![regexp $fluff $line] } {
+ } elseif { [regexp $up_config(fluff) $line] } {
+ verbose "parse_function_bodies: $function_name: ignoring fluff line: $line"
+ } else {
append function_body $line "\n"
}
}
@@ -893,13 +933,18 @@ proc check-function-bodies { args } {
set terminator "*/"
}
set terminator_len [string length $terminator]
+ # Regexp for the start of a function definition in expected output lines
+ # (name in \1). This may be different from '$config(start)'.
+ set start_expected {^(\S+):$}
+
+ configure_check-function-bodies config
set have_bodies 0
if { [is_remote host] } {
remote_upload host "$filename"
}
if { [file exists $output_filename] } {
- parse_function_bodies $output_filename functions
+ parse_function_bodies config $output_filename functions
set have_bodies 1
} else {
verbose -log "$testcase: output file does not exist"
@@ -907,7 +952,6 @@ proc check-function-bodies { args } {
set count 0
set function_regexp ""
- set label {^(\S+):$}
set lineno 1
set fd [open $input_filename r]
@@ -922,7 +966,7 @@ proc check-function-bodies { args } {
} else {
set selector "P"
}
- if { ![regexp $label $line dummy function_name] } {
+ if { ![regexp $start_expected $line dummy function_name] } {
close $fd
error "check-function-bodies: line $lineno does not have a function label"
}
@@ -937,7 +981,7 @@ proc check-function-bodies { args } {
} elseif { [string equal $line "..."] } {
append function_regexp ".*"
} else {
- append function_regexp "\t" $line "\n"
+ append function_regexp $config(line_prefix) $line "\n"
}
} elseif { [string equal -length $terminator_len $line $terminator] } {
if { ![string equal $selector "N"] } {
--
2.34.1
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2023-09-12 8:45 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-07-16 14:14 Add dg test for matching function bodies Richard Sandiford
2019-07-21 20:16 ` Jeff Law
2023-09-04 21:05 ` [WIP] testsuite: Port 'check-function-bodies' to nvptx (was: Add dg test for matching function bodies) Thomas Schwinge
2023-09-05 12:20 ` Thomas Schwinge
2023-09-05 14:28 ` testsuite: Port 'check-function-bodies' to nvptx Richard Sandiford
2023-09-12 8:45 ` Thomas Schwinge
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).