Skip to content

Commit 8e427a3

Browse files
committed
test/codegen: add README file for the codegen test harness
This change adds a README file inside the test/codegen directory, explaining how to run the codegen tests and the syntax of the regexps comments used to match assembly instructions. Change-Id: Ica4eb3ffa9c6975371538cc8ae0ac3c1a3a03baf Reviewed-on: https://go-review.googlesource.com/99156 Reviewed-by: Keith Randall <[email protected]>
1 parent 1c6144d commit 8e427a3

File tree

1 file changed

+129
-0
lines changed

1 file changed

+129
-0
lines changed

test/codegen/README

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
// Copyright 2018 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
The codegen directory contains code generation tests for the gc
6+
compiler.
7+
8+
9+
- Introduction
10+
11+
The test harness compiles Go code inside files in this directory and
12+
then matches the generated assembly (the output of `go tool compile -S`)
13+
against a set of regexps specified in comments that follow a special
14+
syntax (described below). The test driver is implemented as a step of
15+
the top-level test/run.go suite, called "asmcheck".
16+
17+
The codegen tests run during all.bash, but can also be run in
18+
isolation by using
19+
20+
$ ../bin/go run run.go -v codegen
21+
22+
in the top-level test directory.
23+
24+
The test harness compiles the tests with the same go toolchain that is
25+
used to run run.go. After writing tests for a newly added codegen
26+
transformation, it can be useful to first run the test harness with a
27+
toolchain from a released Go version (and verify that the new tests
28+
fail), and then re-runnig the tests using the devel toolchain.
29+
30+
31+
- Regexps comments syntax
32+
33+
Instructions to match are specified inside plain comments that start
34+
with an architecture tag, followed by a colon and a quoted Go-style
35+
regexp to be matched. For example, the following test:
36+
37+
func Sqrt(x float64) float64 {
38+
// amd64:"SQRTSD"
39+
// arm64:"FSQRTD"
40+
return math.Sqrt(x)
41+
}
42+
43+
verifies that math.Sqrt calls are intrinsified to a SQRTSD instruction
44+
on amd64, and to a FSQRTD instruction on arm64.
45+
46+
It is possible to put multiple architectures checks into the same
47+
line, as:
48+
49+
// amd64:"SQRTSD" arm64:"FSQRTD"
50+
51+
although this form should be avoided when doing so would make the
52+
regexps line excessively long and difficult to read.
53+
54+
Comments that are on their own line will be matched against the first
55+
subsequent non-comment line. Inline comments are also supported; the
56+
regexp will be matched against the code found on the same line:
57+
58+
func Sqrt(x float64) float64 {
59+
return math.Sqrt(x) // arm:"SQRTD"
60+
}
61+
62+
It's possible to specify a comma-separated list of regexps to be
63+
matched. For example, the following test:
64+
65+
func TZ8(n uint8) int {
66+
// amd64:"BSFQ","ORQ\t\\$256"
67+
return bits.TrailingZeros8(n)
68+
}
69+
70+
verifies that the code generated for a bits.TrailingZeros8 call on
71+
amd64 contains both a "BSFQ" instruction and an "ORQ $256".
72+
73+
Note how the ORQ regex includes a tab char (\t). In the Go assembly
74+
syntax, operands are separated from opcodes by a tabulation.
75+
76+
Regexps can be quoted using either " or `. Special characters must be
77+
escaped accordingly. Both of these are accepted, and equivalent:
78+
79+
// amd64:"ADDQ\t\\$3"
80+
// amd64:`ADDQ\t\$3`
81+
82+
and they'll match this assembly line:
83+
84+
ADDQ $3
85+
86+
Negative matches can be specified using a - before the quoted regexp.
87+
For example:
88+
89+
func MoveSmall() {
90+
x := [...]byte{1, 2, 3, 4, 5, 6, 7}
91+
copy(x[1:], x[:]) // arm64:-".*memmove"
92+
}
93+
94+
verifies that NO memmove call is present in the assembly generated for
95+
the copy() line.
96+
97+
98+
- Remarks, and Caveats
99+
100+
-- Write small test functions
101+
102+
As a general guideline, test functions should be small, to avoid
103+
possible interactions between unrelated lines of code that may be
104+
introduced, for example, by the compiler's optimization passes.
105+
106+
Any given line of Go code could get assigned more instructions that it
107+
may appear from reading the source. In particular, matching all MOV
108+
instructions should be avoided; the compiler may add them for
109+
unrelated reasons and this may render the test ineffective.
110+
111+
-- Line matching logic
112+
113+
Regexps are always matched from the start of the instructions line.
114+
This means, for example, that the "MULQ" regexp is equivalent to
115+
"^MULQ" (^ representing the start of the line), and it will NOT match
116+
the following assembly line:
117+
118+
IMULQ $99, AX
119+
120+
To force a match at any point of the line, ".*MULQ" should be used.
121+
122+
For the same reason, a negative regexp like -"memmove" is not enough
123+
to make sure that no memmove call is included in the assembly. A
124+
memmove call looks like this:
125+
126+
CALL runtime.memmove(SB)
127+
128+
To make sure that the "memmove" symbol does not appear anywhere in the
129+
assembly, the negative regexp to be used is -".*memmove".

0 commit comments

Comments
 (0)