mirror of
				https://github.com/golang/go
				synced 2025-10-31 00:25:51 +00:00 
			
		
		
		
	This took me a while to figure out. The relevant code is in
test/run.go (note the "linux" hard-coded strings):
	var arch, subarch, os string
	switch {
	case archspec[2] != "": // 3 components: "linux/386/sse2"
		os, arch, subarch = archspec[0], archspec[1][1:], archspec[2][1:]
	case archspec[1] != "": // 2 components: "386/sse2"
		os, arch, subarch = "linux", archspec[0], archspec[1][1:]
	default: // 1 component: "386"
		os, arch, subarch = "linux", archspec[0], ""
		if arch == "wasm" {
			os = "js"
		}
	}
Change-Id: I92ba280025d2072e17532a5e43cf1d676789c167
Reviewed-on: https://go-review.googlesource.com/c/go/+/222819
Reviewed-by: Keith Randall <khr@golang.org>
		
	
		
			
				
	
	
		
			154 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			154 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| // 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 a
 | |
| step of the top-level test/run.go 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 run run.go -all_codegen -v codegen
 | |
| 
 | |
| in the top-level test directory. 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 run.go. 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".
 |