summaryrefslogtreecommitdiffstats
path: root/test/codegen/README
diff options
context:
space:
mode:
Diffstat (limited to 'test/codegen/README')
-rw-r--r--test/codegen/README152
1 files changed, 152 insertions, 0 deletions
diff --git a/test/codegen/README b/test/codegen/README
new file mode 100644
index 0000000..5a46842
--- /dev/null
+++ b/test/codegen/README
@@ -0,0 +1,152 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+The codegen directory contains code generation tests for the gc
+compiler.
+
+
+- Introduction
+
+The test harness compiles Go code inside files in this directory and
+matches the generated assembly (the output of `go tool compile -S`)
+against a set of regexps to be specified in comments that follow a
+special syntax (described below). The test driver is implemented as
+an action within the GOROOT/test test suite, called "asmcheck".
+
+The codegen harness is part of the all.bash test suite, but for
+performance reasons only the codegen tests for the host machine's
+GOARCH are enabled by default, and only on GOOS=linux.
+
+To perform comprehensive tests for all the supported architectures
+(even on a non-Linux system), one can run the following command:
+
+ $ ../../bin/go test cmd/internal/testdir -run='Test/codegen' -all_codegen -v
+
+This is recommended after any change that affect the compiler's code.
+
+The test harness compiles the tests with the same go toolchain that is
+used to run the test. After writing tests for a newly added codegen
+transformation, it can be useful to first run the test harness with a
+toolchain from a released Go version (and verify that the new tests
+fail), and then re-runnig the tests using the devel toolchain.
+
+
+- Regexps comments syntax
+
+Instructions to match are specified inside plain comments that start
+with an architecture tag, followed by a colon and a quoted Go-style
+regexp to be matched. For example, the following test:
+
+ func Sqrt(x float64) float64 {
+ // amd64:"SQRTSD"
+ // arm64:"FSQRTD"
+ return math.Sqrt(x)
+ }
+
+verifies that math.Sqrt calls are intrinsified to a SQRTSD instruction
+on amd64, and to a FSQRTD instruction on arm64.
+
+It is possible to put multiple architectures checks into the same
+line, as:
+
+ // amd64:"SQRTSD" arm64:"FSQRTD"
+
+although this form should be avoided when doing so would make the
+regexps line excessively long and difficult to read.
+
+Comments that are on their own line will be matched against the first
+subsequent non-comment line. Inline comments are also supported; the
+regexp will be matched against the code found on the same line:
+
+ func Sqrt(x float64) float64 {
+ return math.Sqrt(x) // arm:"SQRTD"
+ }
+
+It's possible to specify a comma-separated list of regexps to be
+matched. For example, the following test:
+
+ func TZ8(n uint8) int {
+ // amd64:"BSFQ","ORQ\t\\$256"
+ return bits.TrailingZeros8(n)
+ }
+
+verifies that the code generated for a bits.TrailingZeros8 call on
+amd64 contains both a "BSFQ" instruction and an "ORQ $256".
+
+Note how the ORQ regex includes a tab char (\t). In the Go assembly
+syntax, operands are separated from opcodes by a tabulation.
+
+Regexps can be quoted using either " or `. Special characters must be
+escaped accordingly. Both of these are accepted, and equivalent:
+
+ // amd64:"ADDQ\t\\$3"
+ // amd64:`ADDQ\t\$3`
+
+and they'll match this assembly line:
+
+ ADDQ $3
+
+Negative matches can be specified using a - before the quoted regexp.
+For example:
+
+ func MoveSmall() {
+ x := [...]byte{1, 2, 3, 4, 5, 6, 7}
+ copy(x[1:], x[:]) // arm64:-".*memmove"
+ }
+
+verifies that NO memmove call is present in the assembly generated for
+the copy() line.
+
+
+- Architecture specifiers
+
+There are three different ways to specify on which architecture a test
+should be run:
+
+* Specify only the architecture (eg: "amd64"). This indicates that the
+ check should be run on all the supported architecture variants. For
+ instance, arm checks will be run against all supported GOARM
+ variations (5,6,7).
+* Specify both the architecture and a variant, separated by a slash
+ (eg: "arm/7"). This means that the check will be run only on that
+ specific variant.
+* Specify the operating system, the architecture and the variant,
+ separated by slashes (eg: "plan9/386/sse2", "plan9/amd64/"). This is
+ needed in the rare case that you need to do a codegen test affected
+ by a specific operating system; by default, tests are compiled only
+ targeting linux.
+
+
+- Remarks, and Caveats
+
+-- Write small test functions
+
+As a general guideline, test functions should be small, to avoid
+possible interactions between unrelated lines of code that may be
+introduced, for example, by the compiler's optimization passes.
+
+Any given line of Go code could get assigned more instructions than it
+may appear from reading the source. In particular, matching all MOV
+instructions should be avoided; the compiler may add them for
+unrelated reasons and this may render the test ineffective.
+
+-- Line matching logic
+
+Regexps are always matched from the start of the instructions line.
+This means, for example, that the "MULQ" regexp is equivalent to
+"^MULQ" (^ representing the start of the line), and it will NOT match
+the following assembly line:
+
+ IMULQ $99, AX
+
+To force a match at any point of the line, ".*MULQ" should be used.
+
+For the same reason, a negative regexp like -"memmove" is not enough
+to make sure that no memmove call is included in the assembly. A
+memmove call looks like this:
+
+ CALL runtime.memmove(SB)
+
+To make sure that the "memmove" symbol does not appear anywhere in the
+assembly, the negative regexp to be used is -".*memmove".