From 813c9523a92fbc8e6c3cf1e17de78f2d7ab905a5 Mon Sep 17 00:00:00 2001 From: shaquilleq Date: Wed, 3 Jun 2020 18:25:46 -0700 Subject: [PATCH 01/34] doc/go1.15: add release notes for fmt Updates #37419 Change-Id: I344dd93ed7a75f88e7f937c80f5a6ad6c0327a07 Reviewed-on: https://go-review.googlesource.com/c/go/+/236417 Reviewed-by: Dmitri Shuralyov --- doc/go1.15.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/go1.15.html b/doc/go1.15.html index 492cac0b09..ea96dcfe5f 100644 --- a/doc/go1.15.html +++ b/doc/go1.15.html @@ -390,7 +390,8 @@ TODO
fmt

- TODO: https://golang.org/cl/215001: do not remove trailing zeros for %g and %G with #(sharp) flag + The printing verbs %#g and %#G now preserve + trailing zeros for floating-point values.

From fca286bed3ed0e12336532cc711875ae5b3cb02a Mon Sep 17 00:00:00 2001 From: Carlos Amedee Date: Fri, 5 Jun 2020 18:12:22 -0400 Subject: [PATCH 02/34] doc/go1.15: remove TODO intended for the Core library section The TODO was added durring the initial creation of the document. In the current location, it makes it seem like the tzdata documents are incomplete when they are complete. It is understood that the entire Core library section will be a work in progress until the release. For #37419 Change-Id: Ic857eb0ec2583781c701985ea62e519e9d940090 Reviewed-on: https://go-review.googlesource.com/c/go/+/236760 Reviewed-by: Dmitri Shuralyov --- doc/go1.15.html | 4 ---- 1 file changed, 4 deletions(-) diff --git a/doc/go1.15.html b/doc/go1.15.html index ea96dcfe5f..e376379827 100644 --- a/doc/go1.15.html +++ b/doc/go1.15.html @@ -299,10 +299,6 @@ TODO Either approach increases the size of the program by about 800 KB.

-

-TODO -

-

Cgo

From acdd111e320363c77eb04a761f0b7d4a9dd64c22 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Thu, 4 Jun 2020 18:14:06 -0400 Subject: [PATCH 03/34] doc/go1.15: document toolchain changes Updates #37419. Change-Id: I403cb12083d37359187b45c392046f307054a5b8 Reviewed-on: https://go-review.googlesource.com/c/go/+/236618 Reviewed-by: Alex Brainman Reviewed-by: Dmitri Shuralyov Reviewed-by: David Chase --- doc/go1.15.html | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/doc/go1.15.html b/doc/go1.15.html index e376379827..19f124ae00 100644 --- a/doc/go1.15.html +++ b/doc/go1.15.html @@ -55,6 +55,13 @@ Do not send CLs removing the interior tags from such phrases. on Windows.

+

+ The -race and -msan flags now always + enable -d=checkptr, which checks uses + of unsafe.Pointer. This was previously the case on all + OSes except Windows. +

+

Go-built DLLs no longer cause the process to exit when it receives a signal (such as Ctrl-C at a terminal). @@ -245,6 +252,15 @@ TODO aggressively eliminating unused type metadata.

+

+ The toolchain now mitigates + Intel + CPU erratum SKX102 on GOARCH=amd64 by aligning + functions to 32 byte boundaries and padding jump instructions. While + this padding increases binary sizes, this is more than made up for + by the binary size improvements mentioned above. +

+

Go 1.15 adds a -spectre flag to both the compiler and the assembler, to allow enabling Spectre mitigations. @@ -253,6 +269,19 @@ TODO See the Spectre wiki page for details.

+

+ The compiler now rejects //go: compiler directives that + have no meaning for the declaration they are applied to with a + "misplaced compiler directive" error. Such misapplied directives + were broken before, but were silently ignored by the compiler. +

+ +

+ The compiler's -json optimization logging now reports + large (>= 128 byte) copies and includes explanations of escape + analysis decisions. +

+

Linker

@@ -283,6 +312,14 @@ TODO improvements expected in future releases.

+

Objdump

+ +

+ The objdump tool now supports + disassembling in GNU assembler syntax with the -gnu + flag. +

+

Core library

New embedded tzdata package

From 666448abebed5c165b90814a0f4146a8ae084fb0 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Fri, 5 Jun 2020 09:46:21 -0400 Subject: [PATCH 04/34] doc/go1.15: rationalize runtime sections Use the "Core library -> runtime" section for changes that affect the runtime package API and use the top-level "Runtime" section for package-independent behavior changes. Also, move the one change that's really about os (and net) into the "os" package section and reword it to be more accurate. Updates #37419. Change-Id: I32896b039f29ac67308badd0d0b36e8c6e39f64f Reviewed-on: https://go-review.googlesource.com/c/go/+/236718 Reviewed-by: Michael Knyszek --- doc/go1.15.html | 72 ++++++++++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 37 deletions(-) diff --git a/doc/go1.15.html b/doc/go1.15.html index 19f124ae00..34ce3e58ce 100644 --- a/doc/go1.15.html +++ b/doc/go1.15.html @@ -218,10 +218,24 @@ Do not send CLs removing the interior tags from such phrases.

Runtime

-

- Go now retries system calls that return EINTR. This - became more common in Go 1.14 with the addition of asynchronous - preemption, but is now handled transparently. +

+ If panic is invoked with a value whose type is derived from any + of: bool, complex64, complex128, float32, float64, + int, int8, int16, int32, int64, string, + uint, uint8, uint16, uint32, uint64, uintptr, + then the value will be printed, instead of just its address. + Previously, this was only true for values of exactly these types. +

+ +

+ On a Unix system, if the kill command + or kill system call is used to send + a SIGSEGV, SIGBUS, + or SIGFPE signal to a Go program, and if the signal + is not being handled via + os/signal.Notify, + the Go program will now reliably crash with a stack trace. + In earlier releases the behavior was unpredictable.

@@ -229,8 +243,14 @@ Do not send CLs removing the interior tags from such phrases. counts, and has lower worst-case latency.

-

-TODO +

+ Converting a small integer value into an interface value no longer + causes allocation. +

+ +

+ Non-blocking receives on closed channels now perform as well as + non-blocking receives on open channels.

Compiler

@@ -540,6 +560,14 @@ TODO which Timeout returns true although a deadline has not been exceeded.

+ +

+ Packages os and net now automatically + retry system calls that fail with EINTR. Previously + this led to spurious failures, which became more common in Go + 1.14 with the addition of asynchronous preemption. Now this is + handled transparently. +

@@ -559,7 +587,7 @@ TODO
reflect

- Package reflect now disallows accessing methods of all + Package reflect now disallows accessing methods of all non-exported fields, whereas previously it allowed accessing those of non-exported, embedded fields. Code that relies on the previous behavior should be updated to instead access the @@ -580,26 +608,6 @@ TODO

runtime
-

- If panic is invoked with a value whose type is derived from any - of: bool, complex64, complex128, float32, float64, - int, int8, int16, int32, int64, string, - uint, uint8, uint16, uint32, uint64, uintptr, - then the value will be printed, instead of just its address. - Previously, this was only true for values of exactly these types. -

- -

- On a Unix system, if the kill command - or kill system call is used to send - a SIGSEGV, SIGBUS, - or SIGFPE signal to a Go program, and if the signal - is not being handled via - os/signal.Notify, - the Go program will now reliably crash with a stack trace. - In earlier releases the behavior was unpredictable. -

-

Several functions, including ReadMemStats @@ -607,16 +615,6 @@ TODO GoroutineProfile, no longer block if a garbage collection is in progress.

- -

- Converting small integer values into an interface value no - longer causes allocation. -

- -

- Non-blocking receives on closed channels now perform as well as - non-blocking receives on open channels. -

From 608cdcaede1e7133dc994b5e8894272c2dce744b Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Sat, 6 Jun 2020 20:59:12 -0400 Subject: [PATCH 05/34] all: replace usages of whitelist/blacklist and master/slave There's been plenty of discussion on the usage of these terms in tech. I'm not trying to have yet another debate. It's clear that there are people who are hurt by them and who are made to feel unwelcome by their use due not to technical reasons but to their historical and social context. That's simply enough reason to replace them. Anyway, allowlist and blocklist are more self-explanatory than whitelist and blacklist, so this change has negative cost. Didn't change vendored, bundled, and minified files. Nearly all changes are tests or comments, with a couple renames in cmd/link and cmd/oldlink which are extremely safe. This should be fine to land during the freeze without even asking for an exception. Change-Id: I8fc54a3c8f9cc1973b710bbb9558a9e45810b896 Reviewed-on: https://go-review.googlesource.com/c/go/+/236857 Reviewed-by: Brad Fitzpatrick Reviewed-by: Khosrow Moossavi Reviewed-by: Leigh McCulloch Reviewed-by: Urban Ishimwe --- doc/go1.10.html | 4 +- src/cmd/cgo/doc.go | 2 +- src/cmd/compile/fmt_test.go | 16 ++++---- src/cmd/compile/internal/gc/esc.go | 12 +++--- src/cmd/go/internal/work/gc.go | 2 +- src/cmd/link/internal/loader/loader.go | 6 +-- src/cmd/oldlink/internal/objfile/objfile.go | 6 +-- src/html/template/html.go | 2 +- src/net/http/request.go | 2 +- src/net/http/server.go | 4 +- src/os/signal/internal/pty/pty.go | 8 ++-- src/os/signal/signal_cgo_test.go | 44 ++++++++++----------- src/runtime/cgo_sigaction.go | 2 +- src/runtime/debugcall.go | 2 +- 14 files changed, 56 insertions(+), 56 deletions(-) diff --git a/doc/go1.10.html b/doc/go1.10.html index 41db36ab1e..95871e0e5c 100644 --- a/doc/go1.10.html +++ b/doc/go1.10.html @@ -30,7 +30,7 @@ adds caching of successful test results, runs vet automatically during tests, and permits passing string values directly between Go and C using cgo. -A new compiler option whitelist may cause +A new hard-coded set of safe compiler options may cause unexpected invalid flag errors in code that built successfully with older releases. @@ -267,7 +267,7 @@ and the test2json documentation.

Options specified by cgo using #cgo CFLAGS and the like -are now checked against a whitelist of permitted options. +are now checked against an allowlist of permitted options. This closes a security hole in which a downloaded package uses compiler options like -fplugin diff --git a/src/cmd/cgo/doc.go b/src/cmd/cgo/doc.go index 4366df4b55..ca18c45d9d 100644 --- a/src/cmd/cgo/doc.go +++ b/src/cmd/cgo/doc.go @@ -990,7 +990,7 @@ produces a file named a.out, even if cmd/link does so by invoking the host linker in external linking mode. By default, cmd/link will decide the linking mode as follows: if the only -packages using cgo are those on a whitelist of standard library +packages using cgo are those on a list of known standard library packages (net, os/user, runtime/cgo), cmd/link will use internal linking mode. Otherwise, there are non-standard cgo packages involved, and cmd/link will use external linking mode. The first rule means that a build of diff --git a/src/cmd/compile/fmt_test.go b/src/cmd/compile/fmt_test.go index f1af6473c7..768ca7fc89 100644 --- a/src/cmd/compile/fmt_test.go +++ b/src/cmd/compile/fmt_test.go @@ -96,7 +96,7 @@ func TestFormats(t *testing.T) { } importPath := filepath.Join("cmd/compile", path) - if blacklistedPackages[filepath.ToSlash(importPath)] { + if blocklistedPackages[filepath.ToSlash(importPath)] { return filepath.SkipDir } @@ -344,8 +344,8 @@ func collectPkgFormats(t *testing.T, pkg *build.Package) { for index, file := range files { ast.Inspect(file, func(n ast.Node) bool { if call, ok := n.(*ast.CallExpr); ok { - // ignore blacklisted functions - if blacklistedFunctions[nodeString(call.Fun)] { + // ignore blocklisted functions + if blocklistedFunctions[nodeString(call.Fun)] { return true } // look for an arguments that might be a format string @@ -354,7 +354,7 @@ func collectPkgFormats(t *testing.T, pkg *build.Package) { // make sure we have enough arguments n := numFormatArgs(s) if i+1+n > len(call.Args) { - t.Errorf("%s: not enough format args (blacklist %s?)", posString(call), nodeString(call.Fun)) + t.Errorf("%s: not enough format args (blocklist %s?)", posString(call), nodeString(call.Fun)) break // ignore this call } // assume last n arguments are to be formatted; @@ -549,14 +549,14 @@ func formatReplace(in string, f func(i int, s string) string) string { return string(append(buf, in[i0:]...)) } -// blacklistedPackages is the set of packages which can +// blocklistedPackages is the set of packages which can // be ignored. -var blacklistedPackages = map[string]bool{} +var blocklistedPackages = map[string]bool{} -// blacklistedFunctions is the set of functions which may have +// blocklistedFunctions is the set of functions which may have // format-like arguments but which don't do any formatting and // thus may be ignored. -var blacklistedFunctions = map[string]bool{} +var blocklistedFunctions = map[string]bool{} func init() { // verify that knownFormats entries are correctly formatted diff --git a/src/cmd/compile/internal/gc/esc.go b/src/cmd/compile/internal/gc/esc.go index 8e781a7997..f3e9ab78ef 100644 --- a/src/cmd/compile/internal/gc/esc.go +++ b/src/cmd/compile/internal/gc/esc.go @@ -141,13 +141,13 @@ func isSelfAssign(dst, src *Node) bool { return samesafeexpr(dst.Left, src.Left) } -// mayAffectMemory reports whether n evaluation may affect program memory state. -// If expression can't affect it, then it can be safely ignored by the escape analysis. +// mayAffectMemory reports whether evaluation of n may affect the program's +// memory state. If the expression can't affect memory state, then it can be +// safely ignored by the escape analysis. func mayAffectMemory(n *Node) bool { - // We may want to use "memory safe" black list instead of general - // "side-effect free", which can include all calls and other ops - // that can affect allocate or change global state. - // It's safer to start from a whitelist for now. + // We may want to use a list of "memory safe" ops instead of generally + // "side-effect free", which would include all calls and other ops that can + // allocate or change global state. For now, it's safer to start with the latter. // // We're ignoring things like division by zero, index out of range, // and nil pointer dereference here. diff --git a/src/cmd/go/internal/work/gc.go b/src/cmd/go/internal/work/gc.go index 318d688d2e..9a4fdcda5f 100644 --- a/src/cmd/go/internal/work/gc.go +++ b/src/cmd/go/internal/work/gc.go @@ -168,7 +168,7 @@ func gcBackendConcurrency(gcflags []string) int { CheckFlags: for _, flag := range gcflags { // Concurrent compilation is presumed incompatible with any gcflags, - // except for a small whitelist of commonly used flags. + // except for a small allowlist of commonly used flags. // If the user knows better, they can manually add their own -c to the gcflags. switch flag { case "-N", "-l", "-S", "-B", "-C", "-I": diff --git a/src/cmd/link/internal/loader/loader.go b/src/cmd/link/internal/loader/loader.go index ab38bc3f5c..b871f664ea 100644 --- a/src/cmd/link/internal/loader/loader.go +++ b/src/cmd/link/internal/loader/loader.go @@ -634,15 +634,15 @@ func (l *Loader) checkdup(name string, r *oReader, li int, dup Sym) { } fmt.Fprintf(os.Stderr, "cmd/link: while reading object for '%v': duplicate symbol '%s', previous def at '%v', with mismatched payload: %s\n", r.unit.Lib, name, rdup.unit.Lib, reason) - // For the moment, whitelist DWARF subprogram DIEs for + // For the moment, allowlist DWARF subprogram DIEs for // auto-generated wrapper functions. What seems to happen // here is that we get different line numbers on formal // params; I am guessing that the pos is being inherited // from the spot where the wrapper is needed. - whitelist := strings.HasPrefix(name, "go.info.go.interface") || + allowlist := strings.HasPrefix(name, "go.info.go.interface") || strings.HasPrefix(name, "go.info.go.builtin") || strings.HasPrefix(name, "go.debuglines") - if !whitelist { + if !allowlist { l.strictDupMsgs++ } } diff --git a/src/cmd/oldlink/internal/objfile/objfile.go b/src/cmd/oldlink/internal/objfile/objfile.go index 6882b7694b..ae28e9673a 100644 --- a/src/cmd/oldlink/internal/objfile/objfile.go +++ b/src/cmd/oldlink/internal/objfile/objfile.go @@ -411,16 +411,16 @@ overwrite: } fmt.Fprintf(os.Stderr, "cmd/link: while reading object for '%v': duplicate symbol '%s', previous def at '%v', with mismatched payload: %s\n", r.lib, dup, dup.Unit.Lib, reason) - // For the moment, whitelist DWARF subprogram DIEs for + // For the moment, allowlist DWARF subprogram DIEs for // auto-generated wrapper functions. What seems to happen // here is that we get different line numbers on formal // params; I am guessing that the pos is being inherited // from the spot where the wrapper is needed. - whitelist := (strings.HasPrefix(dup.Name, "go.info.go.interface") || + allowlist := (strings.HasPrefix(dup.Name, "go.info.go.interface") || strings.HasPrefix(dup.Name, "go.info.go.builtin") || strings.HasPrefix(dup.Name, "go.isstmt.go.builtin") || strings.HasPrefix(dup.Name, "go.debuglines")) - if !whitelist { + if !allowlist { r.strictDupMsgs++ } } diff --git a/src/html/template/html.go b/src/html/template/html.go index 13a0cd0436..d3359cac0a 100644 --- a/src/html/template/html.go +++ b/src/html/template/html.go @@ -240,7 +240,7 @@ func htmlNameFilter(args ...interface{}) string { } s = strings.ToLower(s) if t := attrType(s); t != contentTypePlain { - // TODO: Split attr and element name part filters so we can whitelist + // TODO: Split attr and element name part filters so we can allowlist // attributes. return filterFailsafe } diff --git a/src/net/http/request.go b/src/net/http/request.go index e924e2a07f..e4a00dd569 100644 --- a/src/net/http/request.go +++ b/src/net/http/request.go @@ -503,7 +503,7 @@ func valueOrDefault(value, def string) string { // NOTE: This is not intended to reflect the actual Go version being used. // It was changed at the time of Go 1.1 release because the former User-Agent -// had ended up on a blacklist for some intrusion detection systems. +// had ended up on a blocklist for some intrusion detection systems. // See https://codereview.appspot.com/7532043. const defaultUserAgent = "Go-http-client/1.1" diff --git a/src/net/http/server.go b/src/net/http/server.go index b613c21f16..a75dd1461f 100644 --- a/src/net/http/server.go +++ b/src/net/http/server.go @@ -1698,8 +1698,8 @@ func (c *conn) closeWriteAndWait() { time.Sleep(rstAvoidanceDelay) } -// validNextProto reports whether the proto is not a blacklisted ALPN -// protocol name. Empty and built-in protocol types are blacklisted +// validNextProto reports whether the proto is not a blocklisted ALPN +// protocol name. Empty and built-in protocol types are blocklisted // and can't be overridden with alternate implementations. func validNextProto(proto string) bool { switch proto { diff --git a/src/os/signal/internal/pty/pty.go b/src/os/signal/internal/pty/pty.go index fb3ee1ea7a..f8813ce6be 100644 --- a/src/os/signal/internal/pty/pty.go +++ b/src/os/signal/internal/pty/pty.go @@ -40,8 +40,8 @@ func (e *PtyError) Error() string { func (e *PtyError) Unwrap() error { return e.Errno } -// Open returns a master pty and the name of the linked slave tty. -func Open() (master *os.File, slave string, err error) { +// Open returns a control pty and the name of the linked process tty. +func Open() (pty *os.File, processTTY string, err error) { m, err := C.posix_openpt(C.O_RDWR) if err != nil { return nil, "", ptyError("posix_openpt", err) @@ -54,6 +54,6 @@ func Open() (master *os.File, slave string, err error) { C.close(m) return nil, "", ptyError("unlockpt", err) } - slave = C.GoString(C.ptsname(m)) - return os.NewFile(uintptr(m), "pty-master"), slave, nil + processTTY = C.GoString(C.ptsname(m)) + return os.NewFile(uintptr(m), "pty"), processTTY, nil } diff --git a/src/os/signal/signal_cgo_test.go b/src/os/signal/signal_cgo_test.go index 849a96ec0e..a117221400 100644 --- a/src/os/signal/signal_cgo_test.go +++ b/src/os/signal/signal_cgo_test.go @@ -19,7 +19,7 @@ import ( "io" "os" "os/exec" - "os/signal/internal/pty" + ptypkg "os/signal/internal/pty" "strconv" "strings" "sync" @@ -71,20 +71,20 @@ func TestTerminalSignal(t *testing.T) { // The test only fails when using a "slow device," in this // case a pseudo-terminal. - master, sname, err := pty.Open() + pty, procTTYName, err := ptypkg.Open() if err != nil { - ptyErr := err.(*pty.PtyError) + ptyErr := err.(*ptypkg.PtyError) if ptyErr.FuncName == "posix_openpt" && ptyErr.Errno == syscall.EACCES { t.Skip("posix_openpt failed with EACCES, assuming chroot and skipping") } t.Fatal(err) } - defer master.Close() - slave, err := os.OpenFile(sname, os.O_RDWR, 0) + defer pty.Close() + procTTY, err := os.OpenFile(procTTYName, os.O_RDWR, 0) if err != nil { t.Fatal(err) } - defer slave.Close() + defer procTTY.Close() // Start an interactive shell. ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) @@ -92,9 +92,9 @@ func TestTerminalSignal(t *testing.T) { cmd := exec.CommandContext(ctx, bash, "--norc", "--noprofile", "-i") // Clear HISTFILE so that we don't read or clobber the user's bash history. cmd.Env = append(os.Environ(), "HISTFILE=") - cmd.Stdin = slave - cmd.Stdout = slave - cmd.Stderr = slave + cmd.Stdin = procTTY + cmd.Stdout = procTTY + cmd.Stderr = procTTY cmd.SysProcAttr = &syscall.SysProcAttr{ Setsid: true, Setctty: true, @@ -105,21 +105,21 @@ func TestTerminalSignal(t *testing.T) { t.Fatal(err) } - if err := slave.Close(); err != nil { - t.Errorf("closing slave: %v", err) + if err := procTTY.Close(); err != nil { + t.Errorf("closing procTTY: %v", err) } progReady := make(chan bool) sawPrompt := make(chan bool, 10) const prompt = "prompt> " - // Read data from master in the background. + // Read data from pty in the background. var wg sync.WaitGroup wg.Add(1) defer wg.Wait() go func() { defer wg.Done() - input := bufio.NewReader(master) + input := bufio.NewReader(pty) var line, handled []byte for { b, err := input.ReadByte() @@ -130,11 +130,11 @@ func TestTerminalSignal(t *testing.T) { if perr, ok := err.(*os.PathError); ok { err = perr.Err } - // EOF means master is closed. + // EOF means pty is closed. // EIO means child process is done. - // "file already closed" means deferred close of master has happened. + // "file already closed" means deferred close of pty has happened. if err != io.EOF && err != syscall.EIO && !strings.Contains(err.Error(), "file already closed") { - t.Logf("error reading from master: %v", err) + t.Logf("error reading from pty: %v", err) } return } @@ -161,7 +161,7 @@ func TestTerminalSignal(t *testing.T) { }() // Set the bash prompt so that we can see it. - if _, err := master.Write([]byte("PS1='" + prompt + "'\n")); err != nil { + if _, err := pty.Write([]byte("PS1='" + prompt + "'\n")); err != nil { t.Fatalf("setting prompt: %v", err) } select { @@ -172,7 +172,7 @@ func TestTerminalSignal(t *testing.T) { // Start a small program that reads from stdin // (namely the code at the top of this function). - if _, err := master.Write([]byte("GO_TEST_TERMINAL_SIGNALS=1 " + os.Args[0] + " -test.run=TestTerminalSignal\n")); err != nil { + if _, err := pty.Write([]byte("GO_TEST_TERMINAL_SIGNALS=1 " + os.Args[0] + " -test.run=TestTerminalSignal\n")); err != nil { t.Fatal(err) } @@ -190,7 +190,7 @@ func TestTerminalSignal(t *testing.T) { time.Sleep(pause) // Send a ^Z to stop the program. - if _, err := master.Write([]byte{26}); err != nil { + if _, err := pty.Write([]byte{26}); err != nil { t.Fatalf("writing ^Z to pty: %v", err) } @@ -202,7 +202,7 @@ func TestTerminalSignal(t *testing.T) { } // Restart the stopped program. - if _, err := master.Write([]byte("fg\n")); err != nil { + if _, err := pty.Write([]byte("fg\n")); err != nil { t.Fatalf("writing %q to pty: %v", "fg", err) } @@ -217,7 +217,7 @@ func TestTerminalSignal(t *testing.T) { // Write some data for the program to read, // which should cause it to exit. - if _, err := master.Write([]byte{'\n'}); err != nil { + if _, err := pty.Write([]byte{'\n'}); err != nil { t.Fatalf("writing %q to pty: %v", "\n", err) } @@ -229,7 +229,7 @@ func TestTerminalSignal(t *testing.T) { } // Exit the shell with the program's exit status. - if _, err := master.Write([]byte("exit $?\n")); err != nil { + if _, err := pty.Write([]byte("exit $?\n")); err != nil { t.Fatalf("writing %q to pty: %v", "exit", err) } diff --git a/src/runtime/cgo_sigaction.go b/src/runtime/cgo_sigaction.go index bc5e0786d9..967b8b9a0d 100644 --- a/src/runtime/cgo_sigaction.go +++ b/src/runtime/cgo_sigaction.go @@ -18,7 +18,7 @@ var _cgo_sigaction unsafe.Pointer //go:nosplit //go:nowritebarrierrec func sigaction(sig uint32, new, old *sigactiont) { - // The runtime package is explicitly blacklisted from sanitizer + // The runtime package is explicitly blocklisted from sanitizer // instrumentation in racewalk.go, but we might be calling into instrumented C // functions here — so we need the pointer parameters to be properly marked. // diff --git a/src/runtime/debugcall.go b/src/runtime/debugcall.go index 5cbe382ce7..496e6ce8cc 100644 --- a/src/runtime/debugcall.go +++ b/src/runtime/debugcall.go @@ -61,7 +61,7 @@ func debugCallCheck(pc uintptr) string { "debugCall16384", "debugCall32768", "debugCall65536": - // These functions are whitelisted so that the debugger can initiate multiple function calls. + // These functions are allowlisted so that the debugger can initiate multiple function calls. // See: https://golang.org/cl/161137/ return } From 5c6b2b14db8264a8cdc3634e68c7ae65307df0ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= Date: Sat, 6 Jun 2020 13:39:11 +0100 Subject: [PATCH 06/34] doc/go1.15: document two noteworthy json changes I had a look at the changes between 1.14 and master, and these are the only two that seem relevant enough for the changelog. There was also CL 179337 to reuse values when decoding map elements, but it got reverted in CL 234559 and is not being included in 1.15. Updates #37419. Change-Id: Ib125415a953471ce29553a413d85aaf4b18a7a12 Reviewed-on: https://go-review.googlesource.com/c/go/+/236523 Reviewed-by: Dmitri Shuralyov --- doc/go1.15.html | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/doc/go1.15.html b/doc/go1.15.html index 34ce3e58ce..73dbf89c2d 100644 --- a/doc/go1.15.html +++ b/doc/go1.15.html @@ -417,6 +417,21 @@ TODO

+
encoding/json
+
+

+ Decoding a JSON array into a slice no longer reuses any existing slice elements, + following the rules that the package documentation already stated. +

+ +

+ Introduce an internal limit to the maximum depth of nesting when decoding. + This reduces the possibility that a deeply nested input could use large quantities + of stack memory, or even cause a "goroutine stack exceeds limit" panic. +

+
+
+
encoding/xml

From ee379d2b08ce12c24042da18d711e2a1bd7943f0 Mon Sep 17 00:00:00 2001 From: Dmitri Shuralyov Date: Thu, 4 Jun 2020 00:35:09 -0400 Subject: [PATCH 07/34] all: treat all files as binary, but check in .bat with CRLF MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a followup to CL 96495. It should be simpler and more robust to achieve .bat files having CRLF line endings by treating it as a binary file, like all other files, and checking it in with the desired CRLF line endings. A test is used to check the entire Go tree, short of directories starting with "." and named "testdata", for any .bat files that have anything other than strict CRLF line endings. This will help catch any accidental modifications to existing .bat files or check ins of new .bat files. Importantly, this is compatible with how Gerrit serves .tar.gz files, making it so that CRLF line endings are preserved. The Go project is supported on many different environments, some of which may have limited git implementations available, or none at all. Relying on fewer git features and special rules makes it easier to have confidence in the exact content of all files. Additionally, Go development started in Subversion, moved to Perforce, then Mercurial, and now uses Git.¹ Reducing its reliance on git-specific features will help if there will be another transition in the project's future. There are only 5 .bat files in the entire Go source tree, so a new one being added is a rare event, and we prefer to do things in Go instead. We still have the option of improving the experience for developers by adding a pre-commit converter for .bat files to the git-codereview tool. ¹ https://groups.google.com/d/msg/golang-dev/sckirqOWepg/YmyT7dWJiocJ Fixes #39391. For #37791. Change-Id: I6e202216322872f0307ac96f1b8d3f57cb901e6b Reviewed-on: https://go-review.googlesource.com/c/go/+/236437 Reviewed-by: Bryan C. Mills --- .gitattributes | 20 ++-- src/all.bat | 54 ++++----- src/clean.bat | 64 +++++----- src/make.bat | 305 +++++++++++++++++++++++------------------------ src/race.bat | 102 ++++++++-------- src/run.bat | 118 +++++++++--------- test/winbatch.go | 54 +++++++-- 7 files changed, 377 insertions(+), 340 deletions(-) diff --git a/.gitattributes b/.gitattributes index bcea0290f4..cabbb1732c 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,16 +1,16 @@ # Treat all files in the Go repo as binary, with no git magic updating -# line endings. Windows users contributing to Go will need to use a -# modern version of git and editors capable of LF line endings. +# line endings. This produces predictable results in different environments. +# +# Windows users contributing to Go will need to use a modern version +# of git and editors capable of LF line endings. +# +# Windows .bat files are known to have multiple bugs when run with LF +# endings, and so they are checked in with CRLF endings, with a test +# in test/winbatch.go to catch problems. (See golang.org/issue/37791.) # # We'll prevent accidental CRLF line endings from entering the repo -# via the git-review gofmt checks. +# via the git-codereview gofmt checks and tests. # -# See golang.org/issue/9281 +# See golang.org/issue/9281. * -text - -# The only exception is Windows files that must absolutely be CRLF or -# might not work. Batch files are known to have multiple bugs when run -# with LF endings. See golang.org/issue/37791 for more information. - -*.bat text eol=crlf diff --git a/src/all.bat b/src/all.bat index 8bbd6b1b5d..ae835d992f 100644 --- a/src/all.bat +++ b/src/all.bat @@ -1,27 +1,27 @@ -:: Copyright 2012 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. - -@echo off - -setlocal - -if exist make.bat goto ok -echo all.bat must be run from go\src -:: cannot exit: would kill parent command interpreter -goto end -:ok - -set OLDPATH=%PATH% -call make.bat --no-banner --no-local -if %GOBUILDFAIL%==1 goto end -call run.bat --no-rebuild --no-local -if %GOBUILDFAIL%==1 goto end -:: we must restore %PATH% before running "dist banner" so that the latter -:: can get the original %PATH% and give suggestion to add %GOROOT%/bin -:: to %PATH% if necessary. -set PATH=%OLDPATH% -"%GOTOOLDIR%/dist" banner - -:end -if x%GOBUILDEXIT%==x1 exit %GOBUILDFAIL% +:: Copyright 2012 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. + +@echo off + +setlocal + +if exist make.bat goto ok +echo all.bat must be run from go\src +:: cannot exit: would kill parent command interpreter +goto end +:ok + +set OLDPATH=%PATH% +call make.bat --no-banner --no-local +if %GOBUILDFAIL%==1 goto end +call run.bat --no-rebuild --no-local +if %GOBUILDFAIL%==1 goto end +:: we must restore %PATH% before running "dist banner" so that the latter +:: can get the original %PATH% and give suggestion to add %GOROOT%/bin +:: to %PATH% if necessary. +set PATH=%OLDPATH% +"%GOTOOLDIR%/dist" banner + +:end +if x%GOBUILDEXIT%==x1 exit %GOBUILDFAIL% diff --git a/src/clean.bat b/src/clean.bat index 0954dcd67f..c957353d0f 100644 --- a/src/clean.bat +++ b/src/clean.bat @@ -1,32 +1,32 @@ -:: Copyright 2012 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. - -@echo off - -setlocal - -set GOBUILDFAIL=0 - -go tool dist env -w -p >env.bat -if errorlevel 1 goto fail -call env.bat -del env.bat -echo. - -if exist %GOTOOLDIR%\dist.exe goto distok -echo cannot find %GOTOOLDIR%\dist; nothing to clean -goto fail -:distok - -"%GOBIN%\go" clean -i std -"%GOBIN%\go" tool dist clean -"%GOBIN%\go" clean -i cmd - -goto end - -:fail -set GOBUILDFAIL=1 - -:end -if x%GOBUILDEXIT%==x1 exit %GOBUILDFAIL% +:: Copyright 2012 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. + +@echo off + +setlocal + +set GOBUILDFAIL=0 + +go tool dist env -w -p >env.bat +if errorlevel 1 goto fail +call env.bat +del env.bat +echo. + +if exist %GOTOOLDIR%\dist.exe goto distok +echo cannot find %GOTOOLDIR%\dist; nothing to clean +goto fail +:distok + +"%GOBIN%\go" clean -i std +"%GOBIN%\go" tool dist clean +"%GOBIN%\go" clean -i cmd + +goto end + +:fail +set GOBUILDFAIL=1 + +:end +if x%GOBUILDEXIT%==x1 exit %GOBUILDFAIL% diff --git a/src/make.bat b/src/make.bat index f7955ec88a..277a34d5d7 100644 --- a/src/make.bat +++ b/src/make.bat @@ -1,153 +1,152 @@ -:: Copyright 2012 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. - -:: Environment variables that control make.bat: -:: -:: GOROOT_FINAL: The expected final Go root, baked into binaries. -:: The default is the location of the Go tree during the build. -:: -:: GOHOSTARCH: The architecture for host tools (compilers and -:: binaries). Binaries of this type must be executable on the current -:: system, so the only common reason to set this is to set -:: GOHOSTARCH=386 on an amd64 machine. -:: -:: GOARCH: The target architecture for installed packages and tools. -:: -:: GOOS: The target operating system for installed packages and tools. -:: -:: GO_GCFLAGS: Additional go tool compile arguments to use when -:: building the packages and commands. -:: -:: GO_LDFLAGS: Additional go tool link arguments to use when -:: building the commands. -:: -:: CGO_ENABLED: Controls cgo usage during the build. Set it to 1 -:: to include all cgo related files, .c and .go file with "cgo" -:: build directive, in the build. Set it to 0 to ignore them. -:: -:: CC: Command line to run to compile C code for GOHOSTARCH. -:: Default is "gcc". -:: -:: CC_FOR_TARGET: Command line to run compile C code for GOARCH. -:: This is used by cgo. Default is CC. -:: -:: FC: Command line to run to compile Fortran code. -:: This is used by cgo. Default is "gfortran". - -@echo off - -:: Keep environment variables within this script -:: unless invoked with --no-local. -if x%1==x--no-local goto nolocal -if x%2==x--no-local goto nolocal -if x%3==x--no-local goto nolocal -if x%4==x--no-local goto nolocal -setlocal -:nolocal - -set GOENV=off -set GOBUILDFAIL=0 -set GOFLAGS= -set GO111MODULE= - -if exist make.bat goto ok -echo Must run make.bat from Go src directory. -goto fail -:ok - -:: Clean old generated file that will cause problems in the build. -del /F ".\pkg\runtime\runtime_defs.go" 2>NUL - -:: Set GOROOT for build. -cd .. -set GOROOT_TEMP=%CD% -set GOROOT= -cd src -set vflag= -if x%1==x-v set vflag=-v -if x%2==x-v set vflag=-v -if x%3==x-v set vflag=-v -if x%4==x-v set vflag=-v - -if not exist ..\bin\tool mkdir ..\bin\tool - -:: Calculating GOROOT_BOOTSTRAP -if not "x%GOROOT_BOOTSTRAP%"=="x" goto bootstrapset -for /f "tokens=*" %%g in ('where go 2^>nul') do ( - if "x%GOROOT_BOOTSTRAP%"=="x" ( - for /f "tokens=*" %%i in ('%%g env GOROOT 2^>nul') do ( - if /I not %%i==%GOROOT_TEMP% ( - set GOROOT_BOOTSTRAP=%%i - ) - ) - ) -) -if "x%GOROOT_BOOTSTRAP%"=="x" set GOROOT_BOOTSTRAP=%HOMEDRIVE%%HOMEPATH%\Go1.4 - -:bootstrapset -if not exist "%GOROOT_BOOTSTRAP%\bin\go.exe" goto bootstrapfail -set GOROOT=%GOROOT_TEMP% -set GOROOT_TEMP= - -echo Building Go cmd/dist using %GOROOT_BOOTSTRAP% -if x%vflag==x-v echo cmd/dist -setlocal -set GOROOT=%GOROOT_BOOTSTRAP% -set GOOS= -set GOARCH= -set GOBIN= -set GO111MODULE=off -"%GOROOT_BOOTSTRAP%\bin\go.exe" build -o cmd\dist\dist.exe .\cmd\dist -endlocal -if errorlevel 1 goto fail -.\cmd\dist\dist.exe env -w -p >env.bat -if errorlevel 1 goto fail -call env.bat -del env.bat -if x%vflag==x-v echo. - -if x%1==x--dist-tool goto copydist -if x%2==x--dist-tool goto copydist -if x%3==x--dist-tool goto copydist -if x%4==x--dist-tool goto copydist - -set buildall=-a -if x%1==x--no-clean set buildall= -if x%2==x--no-clean set buildall= -if x%3==x--no-clean set buildall= -if x%4==x--no-clean set buildall= -if x%1==x--no-banner set buildall=%buildall% --no-banner -if x%2==x--no-banner set buildall=%buildall% --no-banner -if x%3==x--no-banner set buildall=%buildall% --no-banner -if x%4==x--no-banner set buildall=%buildall% --no-banner - -:: Run dist bootstrap to complete make.bash. -:: Bootstrap installs a proper cmd/dist, built with the new toolchain. -:: Throw ours, built with Go 1.4, away after bootstrap. -.\cmd\dist\dist.exe bootstrap %vflag% %buildall% -if errorlevel 1 goto fail -del .\cmd\dist\dist.exe -goto end - -:: DO NOT ADD ANY NEW CODE HERE. -:: The bootstrap+del above are the final step of make.bat. -:: If something must be added, add it to cmd/dist's cmdbootstrap, -:: to avoid needing three copies in three different shell languages -:: (make.bash, make.bat, make.rc). - -:copydist -mkdir "%GOTOOLDIR%" 2>NUL -copy cmd\dist\dist.exe "%GOTOOLDIR%\" -goto end - -:bootstrapfail -echo ERROR: Cannot find %GOROOT_BOOTSTRAP%\bin\go.exe -echo Set GOROOT_BOOTSTRAP to a working Go tree ^>= Go 1.4. - -:fail -set GOBUILDFAIL=1 -if x%GOBUILDEXIT%==x1 exit %GOBUILDFAIL% - -:end - +:: Copyright 2012 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. + +:: Environment variables that control make.bat: +:: +:: GOROOT_FINAL: The expected final Go root, baked into binaries. +:: The default is the location of the Go tree during the build. +:: +:: GOHOSTARCH: The architecture for host tools (compilers and +:: binaries). Binaries of this type must be executable on the current +:: system, so the only common reason to set this is to set +:: GOHOSTARCH=386 on an amd64 machine. +:: +:: GOARCH: The target architecture for installed packages and tools. +:: +:: GOOS: The target operating system for installed packages and tools. +:: +:: GO_GCFLAGS: Additional go tool compile arguments to use when +:: building the packages and commands. +:: +:: GO_LDFLAGS: Additional go tool link arguments to use when +:: building the commands. +:: +:: CGO_ENABLED: Controls cgo usage during the build. Set it to 1 +:: to include all cgo related files, .c and .go file with "cgo" +:: build directive, in the build. Set it to 0 to ignore them. +:: +:: CC: Command line to run to compile C code for GOHOSTARCH. +:: Default is "gcc". +:: +:: CC_FOR_TARGET: Command line to run compile C code for GOARCH. +:: This is used by cgo. Default is CC. +:: +:: FC: Command line to run to compile Fortran code. +:: This is used by cgo. Default is "gfortran". + +@echo off + +:: Keep environment variables within this script +:: unless invoked with --no-local. +if x%1==x--no-local goto nolocal +if x%2==x--no-local goto nolocal +if x%3==x--no-local goto nolocal +if x%4==x--no-local goto nolocal +setlocal +:nolocal + +set GOENV=off +set GOBUILDFAIL=0 +set GOFLAGS= +set GO111MODULE= + +if exist make.bat goto ok +echo Must run make.bat from Go src directory. +goto fail +:ok + +:: Clean old generated file that will cause problems in the build. +del /F ".\pkg\runtime\runtime_defs.go" 2>NUL + +:: Set GOROOT for build. +cd .. +set GOROOT_TEMP=%CD% +set GOROOT= +cd src +set vflag= +if x%1==x-v set vflag=-v +if x%2==x-v set vflag=-v +if x%3==x-v set vflag=-v +if x%4==x-v set vflag=-v + +if not exist ..\bin\tool mkdir ..\bin\tool + +:: Calculating GOROOT_BOOTSTRAP +if not "x%GOROOT_BOOTSTRAP%"=="x" goto bootstrapset +for /f "tokens=*" %%g in ('where go 2^>nul') do ( + if "x%GOROOT_BOOTSTRAP%"=="x" ( + for /f "tokens=*" %%i in ('%%g env GOROOT 2^>nul') do ( + if /I not %%i==%GOROOT_TEMP% ( + set GOROOT_BOOTSTRAP=%%i + ) + ) + ) +) +if "x%GOROOT_BOOTSTRAP%"=="x" set GOROOT_BOOTSTRAP=%HOMEDRIVE%%HOMEPATH%\Go1.4 + +:bootstrapset +if not exist "%GOROOT_BOOTSTRAP%\bin\go.exe" goto bootstrapfail +set GOROOT=%GOROOT_TEMP% +set GOROOT_TEMP= + +echo Building Go cmd/dist using %GOROOT_BOOTSTRAP% +if x%vflag==x-v echo cmd/dist +setlocal +set GOROOT=%GOROOT_BOOTSTRAP% +set GOOS= +set GOARCH= +set GOBIN= +set GO111MODULE=off +"%GOROOT_BOOTSTRAP%\bin\go.exe" build -o cmd\dist\dist.exe .\cmd\dist +endlocal +if errorlevel 1 goto fail +.\cmd\dist\dist.exe env -w -p >env.bat +if errorlevel 1 goto fail +call env.bat +del env.bat +if x%vflag==x-v echo. + +if x%1==x--dist-tool goto copydist +if x%2==x--dist-tool goto copydist +if x%3==x--dist-tool goto copydist +if x%4==x--dist-tool goto copydist + +set buildall=-a +if x%1==x--no-clean set buildall= +if x%2==x--no-clean set buildall= +if x%3==x--no-clean set buildall= +if x%4==x--no-clean set buildall= +if x%1==x--no-banner set buildall=%buildall% --no-banner +if x%2==x--no-banner set buildall=%buildall% --no-banner +if x%3==x--no-banner set buildall=%buildall% --no-banner +if x%4==x--no-banner set buildall=%buildall% --no-banner + +:: Run dist bootstrap to complete make.bash. +:: Bootstrap installs a proper cmd/dist, built with the new toolchain. +:: Throw ours, built with Go 1.4, away after bootstrap. +.\cmd\dist\dist.exe bootstrap %vflag% %buildall% +if errorlevel 1 goto fail +del .\cmd\dist\dist.exe +goto end + +:: DO NOT ADD ANY NEW CODE HERE. +:: The bootstrap+del above are the final step of make.bat. +:: If something must be added, add it to cmd/dist's cmdbootstrap, +:: to avoid needing three copies in three different shell languages +:: (make.bash, make.bat, make.rc). + +:copydist +mkdir "%GOTOOLDIR%" 2>NUL +copy cmd\dist\dist.exe "%GOTOOLDIR%\" +goto end + +:bootstrapfail +echo ERROR: Cannot find %GOROOT_BOOTSTRAP%\bin\go.exe +echo Set GOROOT_BOOTSTRAP to a working Go tree ^>= Go 1.4. + +:fail +set GOBUILDFAIL=1 +if x%GOBUILDEXIT%==x1 exit %GOBUILDFAIL% + +:end diff --git a/src/race.bat b/src/race.bat index d26f3180a3..8f0355612c 100644 --- a/src/race.bat +++ b/src/race.bat @@ -1,51 +1,51 @@ -:: Copyright 2013 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. - -:: race.bash tests the standard library under the race detector. -:: https://golang.org/doc/articles/race_detector.html - -@echo off - -setlocal - -if exist make.bat goto ok -echo race.bat must be run from go\src -:: cannot exit: would kill parent command interpreter -goto end -:ok - -set GOROOT=%CD%\.. -call make.bat --dist-tool >NUL -if errorlevel 1 goto fail -.\cmd\dist\dist.exe env -w -p >env.bat -if errorlevel 1 goto fail -call env.bat -del env.bat - -if %GOHOSTARCH% == amd64 goto continue -echo Race detector is only supported on windows/amd64. -goto fail - -:continue -call make.bat --no-banner --no-local -if %GOBUILDFAIL%==1 goto end -echo # go install -race std -go install -race std -if errorlevel 1 goto fail - -go tool dist test -race - -if errorlevel 1 goto fail -goto succ - -:fail -set GOBUILDFAIL=1 -echo Fail. -goto end - -:succ -echo All tests passed. - -:end -if x%GOBUILDEXIT%==x1 exit %GOBUILDFAIL% +:: Copyright 2013 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. + +:: race.bash tests the standard library under the race detector. +:: https://golang.org/doc/articles/race_detector.html + +@echo off + +setlocal + +if exist make.bat goto ok +echo race.bat must be run from go\src +:: cannot exit: would kill parent command interpreter +goto end +:ok + +set GOROOT=%CD%\.. +call make.bat --dist-tool >NUL +if errorlevel 1 goto fail +.\cmd\dist\dist.exe env -w -p >env.bat +if errorlevel 1 goto fail +call env.bat +del env.bat + +if %GOHOSTARCH% == amd64 goto continue +echo Race detector is only supported on windows/amd64. +goto fail + +:continue +call make.bat --no-banner --no-local +if %GOBUILDFAIL%==1 goto end +echo # go install -race std +go install -race std +if errorlevel 1 goto fail + +go tool dist test -race + +if errorlevel 1 goto fail +goto succ + +:fail +set GOBUILDFAIL=1 +echo Fail. +goto end + +:succ +echo All tests passed. + +:end +if x%GOBUILDEXIT%==x1 exit %GOBUILDFAIL% diff --git a/src/run.bat b/src/run.bat index 69c181854b..90602b68cb 100644 --- a/src/run.bat +++ b/src/run.bat @@ -1,59 +1,59 @@ -:: Copyright 2012 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. - -@echo off - -if exist ..\bin\go.exe goto ok -echo Must run run.bat from Go src directory after installing cmd/go. -goto fail -:ok - -:: Keep environment variables within this script -:: unless invoked with --no-local. -if x%1==x--no-local goto nolocal -if x%2==x--no-local goto nolocal -setlocal -:nolocal - -set GOBUILDFAIL=0 - -:: we disallow local import for non-local packages, if %GOROOT% happens -:: to be under %GOPATH%, then some tests below will fail -set GOPATH= -:: Issue 14340: ignore GOBIN during all.bat. -set GOBIN= -set GOFLAGS= -set GO111MODULE= - -rem TODO avoid rebuild if possible - -if x%1==x--no-rebuild goto norebuild -echo ##### Building packages and commands. -..\bin\go install -a -v std cmd -if errorlevel 1 goto fail -echo. -:norebuild - -:: we must unset GOROOT_FINAL before tests, because runtime/debug requires -:: correct access to source code, so if we have GOROOT_FINAL in effect, -:: at least runtime/debug test will fail. -set GOROOT_FINAL= - -:: get CGO_ENABLED -..\bin\go env > env.bat -if errorlevel 1 goto fail -call env.bat -del env.bat -echo. - -..\bin\go tool dist test -if errorlevel 1 goto fail -echo. - -goto end - -:fail -set GOBUILDFAIL=1 - -:end +:: Copyright 2012 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. + +@echo off + +if exist ..\bin\go.exe goto ok +echo Must run run.bat from Go src directory after installing cmd/go. +goto fail +:ok + +:: Keep environment variables within this script +:: unless invoked with --no-local. +if x%1==x--no-local goto nolocal +if x%2==x--no-local goto nolocal +setlocal +:nolocal + +set GOBUILDFAIL=0 + +:: we disallow local import for non-local packages, if %GOROOT% happens +:: to be under %GOPATH%, then some tests below will fail +set GOPATH= +:: Issue 14340: ignore GOBIN during all.bat. +set GOBIN= +set GOFLAGS= +set GO111MODULE= + +rem TODO avoid rebuild if possible + +if x%1==x--no-rebuild goto norebuild +echo ##### Building packages and commands. +..\bin\go install -a -v std cmd +if errorlevel 1 goto fail +echo. +:norebuild + +:: we must unset GOROOT_FINAL before tests, because runtime/debug requires +:: correct access to source code, so if we have GOROOT_FINAL in effect, +:: at least runtime/debug test will fail. +set GOROOT_FINAL= + +:: get CGO_ENABLED +..\bin\go env > env.bat +if errorlevel 1 goto fail +call env.bat +del env.bat +echo. + +..\bin\go tool dist test +if errorlevel 1 goto fail +echo. + +goto end + +:fail +set GOBUILDFAIL=1 + +:end diff --git a/test/winbatch.go b/test/winbatch.go index 30e0e3c982..c3b48d385c 100644 --- a/test/winbatch.go +++ b/test/winbatch.go @@ -4,8 +4,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Check that batch files are maintained as CRLF files (consistent behaviour -// on all operating systems). See https://github.com/golang/go/issues/37791 +// Check that batch files are maintained as CRLF files (consistent +// behavior on all operating systems). See golang.org/issue/37791. package main @@ -13,18 +13,56 @@ import ( "bytes" "fmt" "io/ioutil" + "log" "os" "path/filepath" "runtime" + "strings" ) func main() { - batches, _ := filepath.Glob(runtime.GOROOT() + "/src/*.bat") - for _, bat := range batches { - body, _ := ioutil.ReadFile(bat) - if !bytes.Contains(body, []byte("\r\n")) { - fmt.Printf("Windows batch file %s does not contain CRLF line termination.\nTry running git checkout src/*.bat to fix this.\n", bat) - os.Exit(1) + // Ensure that the GOROOT/src/all.bat file exists and has strict CRLF line endings. + enforceBatchStrictCRLF(filepath.Join(runtime.GOROOT(), "src", "all.bat")) + + // Walk the entire Go repository source tree (without GOROOT/pkg), + // skipping directories that start with "." and named "testdata", + // and ensure all .bat files found have exact CRLF line endings. + err := filepath.Walk(runtime.GOROOT(), func(path string, fi os.FileInfo, err error) error { + if err != nil { + return err } + if fi.IsDir() && (strings.HasPrefix(fi.Name(), ".") || fi.Name() == "testdata") { + return filepath.SkipDir + } + if path == filepath.Join(runtime.GOROOT(), "pkg") { + // GOROOT/pkg is known to contain generated artifacts, not source code. + // Skip it to avoid false positives. (Also see golang.org/issue/37929.) + return filepath.SkipDir + } + if filepath.Ext(fi.Name()) == ".bat" { + enforceBatchStrictCRLF(path) + } + return nil + }) + if err != nil { + log.Fatalln(err) + } +} + +func enforceBatchStrictCRLF(path string) { + b, err := ioutil.ReadFile(path) + if err != nil { + log.Fatalln(err) + } + cr, lf := bytes.Count(b, []byte{13}), bytes.Count(b, []byte{10}) + crlf := bytes.Count(b, []byte{13, 10}) + if cr != crlf || lf != crlf { + if rel, err := filepath.Rel(runtime.GOROOT(), path); err == nil { + // Make the test failure more readable by showing a path relative to GOROOT. + path = rel + } + fmt.Printf("Windows batch file %s does not use strict CRLF line termination.\n", path) + fmt.Printf("Please convert it to CRLF before checking it in due to golang.org/issue/37791.\n") + os.Exit(1) } } From bb8901456cec0baa0b0ad894cfe412ee6275ec5c Mon Sep 17 00:00:00 2001 From: Dmitri Shuralyov Date: Thu, 4 Jun 2020 19:20:01 -0400 Subject: [PATCH 08/34] cmd/internal/moddeps: don't skip directories if there are unusual files Previously, if there was a non-directory file with the name vendor or testdata in the Go source tree, it was possible for some directories to be skipped by filepath.Walk performed in findGorootModules. As unusual and unlikely as such non-directory files are, it's better to ensure all directories are visited, and all modules in the GOROOT source tree are found. This increases confidence that tests relying on findGorootModule will not have unexpected false negatives. For #36851. For #36907. Change-Id: I468e80d8f57119e2c72d546b3fd1e23c31fd6e6c Reviewed-on: https://go-review.googlesource.com/c/go/+/236600 Run-TryBot: Dmitri Shuralyov TryBot-Result: Gobot Gobot Reviewed-by: Bryan C. Mills --- src/cmd/internal/moddeps/moddeps_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/internal/moddeps/moddeps_test.go b/src/cmd/internal/moddeps/moddeps_test.go index 5d73edd318..2e6167322e 100644 --- a/src/cmd/internal/moddeps/moddeps_test.go +++ b/src/cmd/internal/moddeps/moddeps_test.go @@ -36,7 +36,7 @@ func findGorootModules(t *testing.T) []gorootModule { if err != nil { return err } - if info.Name() == "vendor" || info.Name() == "testdata" { + if info.IsDir() && (info.Name() == "vendor" || info.Name() == "testdata") { return filepath.SkipDir } if path == filepath.Join(runtime.GOROOT(), "pkg") { From 5b9304e0be5b5e11a82e65ecc626be98b0755e3d Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Sun, 7 Jun 2020 08:32:28 -0700 Subject: [PATCH 09/34] crypto/x509: match RFC suggested SKID generation method Rather than hashing the encoding of the SPKI structure, hash the bytes of the public key itself. Fixes #39429 Change-Id: I55a0f8f08ab1f1b5702590b47d8b9a92d1dbcc1f Reviewed-on: https://go-review.googlesource.com/c/go/+/236878 Run-TryBot: Katie Hockman TryBot-Result: Gobot Gobot Reviewed-by: Filippo Valsorda --- src/crypto/x509/x509.go | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/crypto/x509/x509.go b/src/crypto/x509/x509.go index 288c9c666f..338b48861c 100644 --- a/src/crypto/x509/x509.go +++ b/src/crypto/x509/x509.go @@ -2129,16 +2129,13 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv authorityKeyId = parent.SubjectKeyId } - encodedPublicKey := asn1.BitString{BitLength: len(publicKeyBytes) * 8, Bytes: publicKeyBytes} - pki := publicKeyInfo{nil, publicKeyAlgorithm, encodedPublicKey} subjectKeyId := template.SubjectKeyId if len(subjectKeyId) == 0 && template.IsCA { - // SubjectKeyId generated using method 1 in RFC 5280, Section 4.2.1.2 - b, err := asn1.Marshal(pki) - if err != nil { - return nil, err - } - h := sha1.Sum(b) + // SubjectKeyId generated using method 1 in RFC 5280, Section 4.2.1.2: + // (1) The keyIdentifier is composed of the 160-bit SHA-1 hash of the + // value of the BIT STRING subjectPublicKey (excluding the tag, + // length, and number of unused bits). + h := sha1.Sum(publicKeyBytes) subjectKeyId = h[:] } @@ -2147,6 +2144,7 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv return } + encodedPublicKey := asn1.BitString{BitLength: len(publicKeyBytes) * 8, Bytes: publicKeyBytes} c := tbsCertificate{ Version: 2, SerialNumber: template.SerialNumber, @@ -2154,7 +2152,7 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv Issuer: asn1.RawValue{FullBytes: asn1Issuer}, Validity: validity{template.NotBefore.UTC(), template.NotAfter.UTC()}, Subject: asn1.RawValue{FullBytes: asn1Subject}, - PublicKey: pki, + PublicKey: publicKeyInfo{nil, publicKeyAlgorithm, encodedPublicKey}, Extensions: extensions, } From 886caba73ca3d895ecb8f17ea6866b34f2f7e8c1 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Fri, 5 Jun 2020 22:01:25 -0400 Subject: [PATCH 10/34] runtime: always mark span when marking an object MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The page sweeper depends on spans being marked if any object in the span is marked, but currently only greyobject does this. gcmarknewobject and wbBufFlush1 also mark objects, but neither set span marks. As a result, if there are live objects on a span, but they're all marked via allocation or write barriers, then the span itself won't be marked and the page reclaimer will free the span, ultimately leading to memory corruption when the memory for those live allocations gets reused. Fix this by making gcmarknewobject and wbBufFlush1 also mark pages. No test because I have no idea how to reliably (or even unreliably) trigger this. Fixes #39432. Performance is a wash or very slightly worse. I benchmarked the gcmarknewobject and wbBufFlush1 changes independently and both showed a slight performance improvement, so I'm going to call this noise. name old time/op new time/op delta BiogoIgor 15.9s ± 2% 15.9s ± 2% ~ (p=0.758 n=25+25) BiogoKrishna 15.7s ± 3% 15.7s ± 3% ~ (p=0.382 n=21+21) BleveIndexBatch100 4.94s ± 3% 5.07s ± 4% +2.63% (p=0.000 n=25+25) CompileTemplate 204ms ± 1% 205ms ± 1% +0.43% (p=0.000 n=21+23) CompileUnicode 77.8ms ± 1% 78.1ms ± 1% ~ (p=0.130 n=23+23) CompileGoTypes 731ms ± 1% 733ms ± 1% +0.30% (p=0.006 n=22+22) CompileCompiler 3.64s ± 2% 3.65s ± 3% ~ (p=0.179 n=24+25) CompileSSA 8.44s ± 1% 8.46s ± 1% +0.30% (p=0.003 n=22+23) CompileFlate 132ms ± 1% 133ms ± 1% ~ (p=0.098 n=22+22) CompileGoParser 164ms ± 1% 164ms ± 1% +0.37% (p=0.000 n=21+23) CompileReflect 455ms ± 1% 457ms ± 2% +0.50% (p=0.002 n=20+22) CompileTar 182ms ± 2% 182ms ± 1% ~ (p=0.382 n=22+22) CompileXML 245ms ± 3% 245ms ± 1% ~ (p=0.070 n=21+23) CompileStdCmd 16.5s ± 2% 16.5s ± 3% ~ (p=0.486 n=23+23) FoglemanFauxGLRenderRotateBoat 12.9s ± 1% 13.0s ± 1% +0.97% (p=0.000 n=21+24) FoglemanPathTraceRenderGopherIter1 18.6s ± 1% 18.7s ± 0% ~ (p=0.083 n=23+24) GopherLuaKNucleotide 28.4s ± 1% 29.3s ± 1% +2.84% (p=0.000 n=25+25) MarkdownRenderXHTML 252ms ± 0% 251ms ± 1% -0.50% (p=0.000 n=23+24) Tile38WithinCircle100kmRequest 516µs ± 2% 516µs ± 2% ~ (p=0.763 n=24+25) Tile38IntersectsCircle100kmRequest 689µs ± 2% 689µs ± 2% ~ (p=0.617 n=24+24) Tile38KNearestLimit100Request 608µs ± 1% 606µs ± 2% -0.35% (p=0.030 n=19+22) [Geo mean] 522ms 524ms +0.41% https://perf.golang.org/search?q=upload:20200606.4 Change-Id: I8b331f310dbfaba0468035f207467c8403005bf5 Reviewed-on: https://go-review.googlesource.com/c/go/+/236817 Run-TryBot: Austin Clements TryBot-Result: Gobot Gobot Reviewed-by: Michael Knyszek --- src/runtime/malloc.go | 20 ++++++++++---------- src/runtime/mgcmark.go | 14 ++++++++++++-- src/runtime/mwbbuf.go | 7 +++++++ 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/src/runtime/malloc.go b/src/runtime/malloc.go index 77a5a38768..eaf8db7220 100644 --- a/src/runtime/malloc.go +++ b/src/runtime/malloc.go @@ -976,6 +976,7 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer { throw("malloc called with no P") } } + var span *mspan var x unsafe.Pointer noscan := typ == nil || typ.ptrdata == 0 if size <= maxSmallSize { @@ -1028,10 +1029,10 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer { return x } // Allocate a new maxTinySize block. - span := c.alloc[tinySpanClass] + span = c.alloc[tinySpanClass] v := nextFreeFast(span) if v == 0 { - v, _, shouldhelpgc = c.nextFree(tinySpanClass) + v, span, shouldhelpgc = c.nextFree(tinySpanClass) } x = unsafe.Pointer(v) (*[2]uint64)(x)[0] = 0 @@ -1052,7 +1053,7 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer { } size = uintptr(class_to_size[sizeclass]) spc := makeSpanClass(sizeclass, noscan) - span := c.alloc[spc] + span = c.alloc[spc] v := nextFreeFast(span) if v == 0 { v, span, shouldhelpgc = c.nextFree(spc) @@ -1063,15 +1064,14 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer { } } } else { - var s *mspan shouldhelpgc = true systemstack(func() { - s = largeAlloc(size, needzero, noscan) + span = largeAlloc(size, needzero, noscan) }) - s.freeindex = 1 - s.allocCount = 1 - x = unsafe.Pointer(s.base()) - size = s.elemsize + span.freeindex = 1 + span.allocCount = 1 + x = unsafe.Pointer(span.base()) + size = span.elemsize } var scanSize uintptr @@ -1112,7 +1112,7 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer { // This may be racing with GC so do it atomically if there can be // a race marking the bit. if gcphase != _GCoff { - gcmarknewobject(uintptr(x), size, scanSize) + gcmarknewobject(span, uintptr(x), size, scanSize) } if raceenabled { diff --git a/src/runtime/mgcmark.go b/src/runtime/mgcmark.go index dafb4634b4..fe988c46d9 100644 --- a/src/runtime/mgcmark.go +++ b/src/runtime/mgcmark.go @@ -1627,11 +1627,21 @@ func gcDumpObject(label string, obj, off uintptr) { // //go:nowritebarrier //go:nosplit -func gcmarknewobject(obj, size, scanSize uintptr) { +func gcmarknewobject(span *mspan, obj, size, scanSize uintptr) { if useCheckmark { // The world should be stopped so this should not happen. throw("gcmarknewobject called while doing checkmark") } - markBitsForAddr(obj).setMarked() + + // Mark object. + objIndex := span.objIndex(obj) + span.markBitsForIndex(objIndex).setMarked() + + // Mark span. + arena, pageIdx, pageMask := pageIndexOf(span.base()) + if arena.pageMarks[pageIdx]&pageMask == 0 { + atomic.Or8(&arena.pageMarks[pageIdx], pageMask) + } + gcw := &getg().m.p.ptr().gcw gcw.bytesMarked += uint64(size) gcw.scanWork += int64(scanSize) diff --git a/src/runtime/mwbbuf.go b/src/runtime/mwbbuf.go index f444452bab..632769c114 100644 --- a/src/runtime/mwbbuf.go +++ b/src/runtime/mwbbuf.go @@ -296,6 +296,13 @@ func wbBufFlush1(_p_ *p) { continue } mbits.setMarked() + + // Mark span. + arena, pageIdx, pageMask := pageIndexOf(span.base()) + if arena.pageMarks[pageIdx]&pageMask == 0 { + atomic.Or8(&arena.pageMarks[pageIdx], pageMask) + } + if span.spanclass.noscan() { gcw.bytesMarked += uint64(span.elemsize) continue From 5716ae6c9610f31e2cdefd07eea78174414c3dca Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Tue, 2 Jun 2020 15:52:51 -0400 Subject: [PATCH 11/34] doc/go1.15: add release notes for crypto/tls Updates #37419 Change-Id: Ie81c0b03716799c132e90dc231ab816e6ae43469 Reviewed-on: https://go-review.googlesource.com/c/go/+/236166 Reviewed-by: Filippo Valsorda Reviewed-by: Dmitri Shuralyov --- doc/go1.15.html | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/doc/go1.15.html b/doc/go1.15.html index 73dbf89c2d..7506a6aa49 100644 --- a/doc/go1.15.html +++ b/doc/go1.15.html @@ -406,6 +406,20 @@ TODO DialContext method permits using a context to both connect and handshake with a TLS server.

+ +

+ The new + VerifyConnection + callback on the Config type + allows custom verification logic for every connection. It has access to the + ConnectionState + which includes peer certificates, SCTs, and stapled OCSP responses. +

+ +

+ Auto-generated session ticket keys are now automatically rotated every 24 hours, + with a lifetime of 7 days, to limit their impact on forward secrecy. +

From 063ce0f2f774563ff2143bd8b974ce7f89caa365 Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Fri, 5 Jun 2020 12:48:26 -0400 Subject: [PATCH 12/34] doc/go1.15: add release notes for crypto/x509 Updates #37419 Change-Id: Iedfd4b238980675be115c7e6e0a327d7745b5bed Reviewed-on: https://go-review.googlesource.com/c/go/+/236737 Reviewed-by: Katie Hockman Reviewed-by: Dmitri Shuralyov --- doc/go1.15.html | 47 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/doc/go1.15.html b/doc/go1.15.html index 7506a6aa49..10b245fd8f 100644 --- a/doc/go1.15.html +++ b/doc/go1.15.html @@ -425,8 +425,53 @@ TODO
crypto/x509
+

+ If either the name on the certificate or the name being verified (with + VerifyOptions.DNSName + or VerifyHostname) + are invalid, they will now be compared case-insensitively without further + processing (without honoring wildcards or stripping trailing dots). + Invalid names include those with any characters other than letters, + digits, hyphens and underscores, those with empty labels, and names on + certificates with trailing dots. +

+ +

+ The deprecated, legacy behavior of treating the CommonName + field as a hostname when no Subject Alternative Names are present is now + disabled by default. It can be temporarily re-enabled by adding the value + x509ignoreCN=0 to the GODEBUG environment + variable. If the CommonName is an invalid hostname, it's + always ignored. +

+ +

+ The new CreateRevocationList + function and RevocationList type + allow creating RFC 5280-compliant X.509 v2 Certificate Revocation Lists. +

+ +

+ CreateCertificate + now automatically generates the SubjectKeyId if the template + is a CA and doesn't explicitly specify one. +

+ +

+ CreateCertificate + now returns an error if the template specifies MaxPathLen but is not a CA. +

+

- TODO: https://golang.org/cl/205237: load roots from colon separated SSL_CERT_DIR in loadSystemRoots + On Unix systems other than macOS, the SSL_CERT_DIR + environment variable can now be a colon-separated list. +

+ +

+ On macOS, binaries are now always linked against + Security.framework to extract the system trust roots, + regardless of whether cgo is available. The resulting behavior should be + more consistent with the OS verifier.

From 2603d9a89ae1eb06386b9dd68fdb9f185aca4804 Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Mon, 8 Jun 2020 13:07:39 -0400 Subject: [PATCH 13/34] doc/go1.15: add release notes for crypto and math/big Updates #37419 Change-Id: I12f073697dc319e439f4ffe4e0aac7f6afb19a74 Reviewed-on: https://go-review.googlesource.com/c/go/+/236918 Reviewed-by: Katie Hockman --- doc/go1.15.html | 59 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/doc/go1.15.html b/doc/go1.15.html index 10b245fd8f..1e39493cba 100644 --- a/doc/go1.15.html +++ b/doc/go1.15.html @@ -389,10 +389,53 @@ TODO +
crypto
+
+

+ The PrivateKey and PublicKey types in the + crypto/rsa, + crypto/ecdsa, and + crypto/ed25519 packages + now have an Equal method to compare keys for equivalence + or to make type-safe interfaces for public keys. The method signature + is compatible with + go-cmp's + definition of equality. +

+ +

+ Hash now implements + fmt.Stringer. +

+
+
+ +
crypto/ecdsa
+
+

+ The new SignASN1 + and VerifyASN1 + functions allow generating and verifying ECDSA signatures in the standard + ASN.1 DER encoding. +

+
+
+ +
crypto/elliptic
+
+

+ The new MarshalCompressed + and UnmarshalCompressed + functions allow encoding and decoding NIST elliptic curve points in compressed format. +

+
+
+
crypto/rsa

- VerifyPKCS1v15 now rejects invalid short signatures with missing leading zeroes. + VerifyPKCS1v15 + now rejects invalid short signatures with missing leading zeroes, according to RFC 8017.

@@ -476,6 +519,17 @@ TODO +
crypto/x509/pkix
+
+

+ Name.String + now prints non-standard attributes from + Names if + ExtraNames is empty. +

+
+
+
encoding/json

@@ -538,7 +592,8 @@ TODO

math/big

- TODO: https://golang.org/cl/230397: add (*Int).FillBytes + The new Int.FillBytes + method allows serializing to fixed-size pre-allocated byte slices.

From 8891b82332de4afa23f935b58263d08a3a5c6d95 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Fri, 5 Jun 2020 22:35:18 -0400 Subject: [PATCH 14/34] cmd/go: remove a bogus assertion in mod_convert_dep The removed line assumed that the script's WORK directory is not a child of any directory containing version-control metadata. While that assumption does hold in most cases, it does not hold when, for example, $TMPDIR is $HOME/tmp and $HOME/.git/config exists. A similar situation may or may not arise when using golang.org/x/build/cmd/release. Either way, the assertion is incorrect and was interfering with local testing for #39385. Updates #39385 Fixes #39431 Change-Id: I67813d7ce455aa9b56a6eace6eddebf48d0f7fa6 Reviewed-on: https://go-review.googlesource.com/c/go/+/236818 Reviewed-by: Dmitri Shuralyov --- src/cmd/go/testdata/script/mod_convert_dep.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/src/cmd/go/testdata/script/mod_convert_dep.txt b/src/cmd/go/testdata/script/mod_convert_dep.txt index 267c90eb3c..ad22aca5be 100644 --- a/src/cmd/go/testdata/script/mod_convert_dep.txt +++ b/src/cmd/go/testdata/script/mod_convert_dep.txt @@ -20,7 +20,6 @@ cd $WORK/gopkgdir/x ! go list . stderr 'cannot find main module' ! stderr 'Gopkg.lock' -! stderr 'go mod init' -- $WORK/test/Gopkg.lock -- -- $WORK/test/x/x.go -- From bddf75d88859b8454f67de32510d8488329d0f2b Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Mon, 8 Jun 2020 13:58:12 -0400 Subject: [PATCH 15/34] doc/go1.15: add more release notes for crypto/tls Updates #37419 Change-Id: I5e03adbf6d215d65aedbdeb7bdfe1ead8a838877 Reviewed-on: https://go-review.googlesource.com/c/go/+/236921 Reviewed-by: Katie Hockman --- doc/go1.15.html | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/doc/go1.15.html b/doc/go1.15.html index 1e39493cba..7a49e1fa1f 100644 --- a/doc/go1.15.html +++ b/doc/go1.15.html @@ -463,8 +463,27 @@ TODO Auto-generated session ticket keys are now automatically rotated every 24 hours, with a lifetime of 7 days, to limit their impact on forward secrecy.

+ +

+ Session ticket lifetimes in TLS 1.2 and earlier, where the session keys + are reused for resumed connections, are now limited to 7 days, also to + limit their impact on forward secrecy. +

+ +

+ The client-side downgrade protection checks specified in RFC 8446 are now + enforced. This has the potential to cause connection errors for clients + encountering middleboxes that behave like unauthorized downgrade attacks. +

+ +

+ SignatureScheme, + CurveID, and + ClientAuthType + now implement fmt.Stringer. +

-
+
crypto/x509
From 2cd2ff6f564dce5be0c4fb7f06338ff7af3fc9a9 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 8 Jun 2020 12:39:56 -0400 Subject: [PATCH 16/34] all: avoid awkward wording from CL 236857 CL 236857 removed all uses of whitelist/blacklist, which is great. But it substituted awkward phrasing using allowlist/blocklist, especially as verbs or participles. This CL uses more standard English, like "allow the function" or "blocked functions" instead of "allowlist the function" or "blocklisted functions". Change-Id: I9106a2fdbd62751c4cbda3a77181358a8a6d0f13 Reviewed-on: https://go-review.googlesource.com/c/go/+/236917 Run-TryBot: Russ Cox Reviewed-by: Ian Lance Taylor --- doc/go1.10.html | 2 +- src/cmd/compile/fmt_test.go | 15 +++++++-------- src/cmd/go/internal/work/gc.go | 2 +- src/cmd/link/internal/loader/loader.go | 6 +++--- src/cmd/oldlink/internal/objfile/objfile.go | 6 +++--- src/html/template/html.go | 3 +-- src/net/http/request.go | 2 +- src/net/http/server.go | 6 +++--- src/runtime/cgo_sigaction.go | 10 +++++----- src/runtime/debugcall.go | 2 +- 10 files changed, 26 insertions(+), 28 deletions(-) diff --git a/doc/go1.10.html b/doc/go1.10.html index 95871e0e5c..853f874ded 100644 --- a/doc/go1.10.html +++ b/doc/go1.10.html @@ -267,7 +267,7 @@ and the test2json documentation.

Options specified by cgo using #cgo CFLAGS and the like -are now checked against an allowlist of permitted options. +are now checked against a list of permitted options. This closes a security hole in which a downloaded package uses compiler options like -fplugin diff --git a/src/cmd/compile/fmt_test.go b/src/cmd/compile/fmt_test.go index 768ca7fc89..e372259c78 100644 --- a/src/cmd/compile/fmt_test.go +++ b/src/cmd/compile/fmt_test.go @@ -96,7 +96,7 @@ func TestFormats(t *testing.T) { } importPath := filepath.Join("cmd/compile", path) - if blocklistedPackages[filepath.ToSlash(importPath)] { + if ignoredPackages[filepath.ToSlash(importPath)] { return filepath.SkipDir } @@ -344,8 +344,7 @@ func collectPkgFormats(t *testing.T, pkg *build.Package) { for index, file := range files { ast.Inspect(file, func(n ast.Node) bool { if call, ok := n.(*ast.CallExpr); ok { - // ignore blocklisted functions - if blocklistedFunctions[nodeString(call.Fun)] { + if ignoredFunctions[nodeString(call.Fun)] { return true } // look for an arguments that might be a format string @@ -354,7 +353,7 @@ func collectPkgFormats(t *testing.T, pkg *build.Package) { // make sure we have enough arguments n := numFormatArgs(s) if i+1+n > len(call.Args) { - t.Errorf("%s: not enough format args (blocklist %s?)", posString(call), nodeString(call.Fun)) + t.Errorf("%s: not enough format args (ignore %s?)", posString(call), nodeString(call.Fun)) break // ignore this call } // assume last n arguments are to be formatted; @@ -549,14 +548,14 @@ func formatReplace(in string, f func(i int, s string) string) string { return string(append(buf, in[i0:]...)) } -// blocklistedPackages is the set of packages which can +// ignoredPackages is the set of packages which can // be ignored. -var blocklistedPackages = map[string]bool{} +var ignoredPackages = map[string]bool{} -// blocklistedFunctions is the set of functions which may have +// ignoredFunctions is the set of functions which may have // format-like arguments but which don't do any formatting and // thus may be ignored. -var blocklistedFunctions = map[string]bool{} +var ignoredFunctions = map[string]bool{} func init() { // verify that knownFormats entries are correctly formatted diff --git a/src/cmd/go/internal/work/gc.go b/src/cmd/go/internal/work/gc.go index 9a4fdcda5f..f1d08e0268 100644 --- a/src/cmd/go/internal/work/gc.go +++ b/src/cmd/go/internal/work/gc.go @@ -168,7 +168,7 @@ func gcBackendConcurrency(gcflags []string) int { CheckFlags: for _, flag := range gcflags { // Concurrent compilation is presumed incompatible with any gcflags, - // except for a small allowlist of commonly used flags. + // except for known commonly used flags. // If the user knows better, they can manually add their own -c to the gcflags. switch flag { case "-N", "-l", "-S", "-B", "-C", "-I": diff --git a/src/cmd/link/internal/loader/loader.go b/src/cmd/link/internal/loader/loader.go index b871f664ea..32c342e545 100644 --- a/src/cmd/link/internal/loader/loader.go +++ b/src/cmd/link/internal/loader/loader.go @@ -634,15 +634,15 @@ func (l *Loader) checkdup(name string, r *oReader, li int, dup Sym) { } fmt.Fprintf(os.Stderr, "cmd/link: while reading object for '%v': duplicate symbol '%s', previous def at '%v', with mismatched payload: %s\n", r.unit.Lib, name, rdup.unit.Lib, reason) - // For the moment, allowlist DWARF subprogram DIEs for + // For the moment, allow DWARF subprogram DIEs for // auto-generated wrapper functions. What seems to happen // here is that we get different line numbers on formal // params; I am guessing that the pos is being inherited // from the spot where the wrapper is needed. - allowlist := strings.HasPrefix(name, "go.info.go.interface") || + allowed := strings.HasPrefix(name, "go.info.go.interface") || strings.HasPrefix(name, "go.info.go.builtin") || strings.HasPrefix(name, "go.debuglines") - if !allowlist { + if !allowed { l.strictDupMsgs++ } } diff --git a/src/cmd/oldlink/internal/objfile/objfile.go b/src/cmd/oldlink/internal/objfile/objfile.go index ae28e9673a..fbd7eb740b 100644 --- a/src/cmd/oldlink/internal/objfile/objfile.go +++ b/src/cmd/oldlink/internal/objfile/objfile.go @@ -411,16 +411,16 @@ overwrite: } fmt.Fprintf(os.Stderr, "cmd/link: while reading object for '%v': duplicate symbol '%s', previous def at '%v', with mismatched payload: %s\n", r.lib, dup, dup.Unit.Lib, reason) - // For the moment, allowlist DWARF subprogram DIEs for + // For the moment, allow DWARF subprogram DIEs for // auto-generated wrapper functions. What seems to happen // here is that we get different line numbers on formal // params; I am guessing that the pos is being inherited // from the spot where the wrapper is needed. - allowlist := (strings.HasPrefix(dup.Name, "go.info.go.interface") || + allowed := (strings.HasPrefix(dup.Name, "go.info.go.interface") || strings.HasPrefix(dup.Name, "go.info.go.builtin") || strings.HasPrefix(dup.Name, "go.isstmt.go.builtin") || strings.HasPrefix(dup.Name, "go.debuglines")) - if !allowlist { + if !allowed { r.strictDupMsgs++ } } diff --git a/src/html/template/html.go b/src/html/template/html.go index d3359cac0a..356b8298ae 100644 --- a/src/html/template/html.go +++ b/src/html/template/html.go @@ -240,8 +240,7 @@ func htmlNameFilter(args ...interface{}) string { } s = strings.ToLower(s) if t := attrType(s); t != contentTypePlain { - // TODO: Split attr and element name part filters so we can allowlist - // attributes. + // TODO: Split attr and element name part filters so we can recognize known attributes. return filterFailsafe } for _, r := range s { diff --git a/src/net/http/request.go b/src/net/http/request.go index e4a00dd569..fe6b60982c 100644 --- a/src/net/http/request.go +++ b/src/net/http/request.go @@ -503,7 +503,7 @@ func valueOrDefault(value, def string) string { // NOTE: This is not intended to reflect the actual Go version being used. // It was changed at the time of Go 1.1 release because the former User-Agent -// had ended up on a blocklist for some intrusion detection systems. +// had ended up blocked by some intrusion detection systems. // See https://codereview.appspot.com/7532043. const defaultUserAgent = "Go-http-client/1.1" diff --git a/src/net/http/server.go b/src/net/http/server.go index a75dd1461f..a995a50658 100644 --- a/src/net/http/server.go +++ b/src/net/http/server.go @@ -1698,9 +1698,9 @@ func (c *conn) closeWriteAndWait() { time.Sleep(rstAvoidanceDelay) } -// validNextProto reports whether the proto is not a blocklisted ALPN -// protocol name. Empty and built-in protocol types are blocklisted -// and can't be overridden with alternate implementations. +// validNextProto reports whether the proto is a valid ALPN protocol name. +// Everything is valid except the empty string and built-in protocol types, +// so that those can't be overridden with alternate implementations. func validNextProto(proto string) bool { switch proto { case "", "http/1.1", "http/1.0": diff --git a/src/runtime/cgo_sigaction.go b/src/runtime/cgo_sigaction.go index 967b8b9a0d..de634dc957 100644 --- a/src/runtime/cgo_sigaction.go +++ b/src/runtime/cgo_sigaction.go @@ -18,12 +18,12 @@ var _cgo_sigaction unsafe.Pointer //go:nosplit //go:nowritebarrierrec func sigaction(sig uint32, new, old *sigactiont) { - // The runtime package is explicitly blocklisted from sanitizer - // instrumentation in racewalk.go, but we might be calling into instrumented C - // functions here — so we need the pointer parameters to be properly marked. + // racewalk.go avoids adding sanitizing instrumentation to package runtime, + // but we might be calling into instrumented C functions here, + // so we need the pointer parameters to be properly marked. // - // Mark the input as having been written before the call and the output as - // read after. + // Mark the input as having been written before the call + // and the output as read after. if msanenabled && new != nil { msanwrite(unsafe.Pointer(new), unsafe.Sizeof(*new)) } diff --git a/src/runtime/debugcall.go b/src/runtime/debugcall.go index 496e6ce8cc..6c285ec829 100644 --- a/src/runtime/debugcall.go +++ b/src/runtime/debugcall.go @@ -61,7 +61,7 @@ func debugCallCheck(pc uintptr) string { "debugCall16384", "debugCall32768", "debugCall65536": - // These functions are allowlisted so that the debugger can initiate multiple function calls. + // These functions are allowed so that the debugger can initiate multiple function calls. // See: https://golang.org/cl/161137/ return } From e64675a79fef5924f268425de021372df874010e Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Mon, 8 Jun 2020 14:35:07 -0700 Subject: [PATCH 17/34] os: always check for EINTR in calls to open For #11180 For #20400 For #39237 Change-Id: I8de97517c8f92c08f0c8a51f651a17e31617979b Reviewed-on: https://go-review.googlesource.com/c/go/+/236997 Reviewed-by: Bryan C. Mills --- src/os/file_unix.go | 6 ++---- src/os/removeall_at.go | 3 +-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/os/file_unix.go b/src/os/file_unix.go index b93e2bd56a..f2c00ae0cb 100644 --- a/src/os/file_unix.go +++ b/src/os/file_unix.go @@ -202,10 +202,8 @@ func openFileNolog(name string, flag int, perm FileMode) (*File, error) { break } - // On OS X, sigaction(2) doesn't guarantee that SA_RESTART will cause - // open(2) to be restarted for regular files. This is easy to reproduce on - // fuse file systems (see https://golang.org/issue/11180). - if runtime.GOOS == "darwin" && e == syscall.EINTR { + // We have to check EINTR here, per issues 11180 and 39237. + if e == syscall.EINTR { continue } diff --git a/src/os/removeall_at.go b/src/os/removeall_at.go index e619851f9c..37bf1b8f2f 100644 --- a/src/os/removeall_at.go +++ b/src/os/removeall_at.go @@ -9,7 +9,6 @@ package os import ( "internal/syscall/unix" "io" - "runtime" "syscall" ) @@ -178,7 +177,7 @@ func openFdAt(dirfd int, name string) (*File, error) { } // See comment in openFileNolog. - if runtime.GOOS == "darwin" && e == syscall.EINTR { + if e == syscall.EINTR { continue } From cacac8bdc5c93e7bc71df71981fdf32dded017bf Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Fri, 5 Jun 2020 16:08:08 -0400 Subject: [PATCH 18/34] cmd/dist: do not unset GOROOT_FINAL prior to running tests Also do not unset it by default in the tests for cmd/go. GOROOT_FINAL affects the GOROOT value embedded in binaries, such as 'cmd/cgo'. If its value changes and a build command is performed that depends on one of those binaries, the binary would be spuriously rebuilt. Instead, only unset it in the specific tests that make assumptions about the GOROOT paths embedded in specific compiled binaries. That may cause those tests to do a little extra rebuilding when GOROOT_FINAL is set, but that little bit of extra rebuilding seems preferable to spuriously-stale binaries. Fixes #39385 Change-Id: I7c87b1519bb5bcff64babf1505fd1033ffa4f4fb Reviewed-on: https://go-review.googlesource.com/c/go/+/236819 Run-TryBot: Bryan C. Mills TryBot-Result: Gobot Gobot Reviewed-by: Dmitri Shuralyov --- src/cmd/addr2line/addr2line_test.go | 14 +++++++++++--- src/cmd/dist/test.go | 9 --------- src/cmd/go/go_test.go | 12 +++++++++--- src/cmd/go/script_test.go | 1 + src/cmd/go/testdata/script/README | 1 + src/cmd/go/testdata/script/build_trimpath.txt | 4 ++++ src/cmd/go/testdata/script/goroot_executable.txt | 7 +++++++ src/cmd/link/dwarf_test.go | 4 ++-- src/cmd/objdump/objdump_test.go | 6 +++++- 9 files changed, 40 insertions(+), 18 deletions(-) diff --git a/src/cmd/addr2line/addr2line_test.go b/src/cmd/addr2line/addr2line_test.go index 22bf1379bb..e12f0ae814 100644 --- a/src/cmd/addr2line/addr2line_test.go +++ b/src/cmd/addr2line/addr2line_test.go @@ -74,18 +74,26 @@ func testAddr2Line(t *testing.T, exepath, addr string) { t.Fatalf("Stat failed: %v", err) } fi2, err := os.Stat(srcPath) + if gorootFinal := os.Getenv("GOROOT_FINAL"); gorootFinal != "" && strings.HasPrefix(srcPath, gorootFinal) { + if os.IsNotExist(err) || (err == nil && !os.SameFile(fi1, fi2)) { + // srcPath has had GOROOT_FINAL substituted for GOROOT, and it doesn't + // match the actual file. GOROOT probably hasn't been moved to its final + // location yet, so try the original location instead. + fi2, err = os.Stat(runtime.GOROOT() + strings.TrimPrefix(srcPath, gorootFinal)) + } + } if err != nil { t.Fatalf("Stat failed: %v", err) } if !os.SameFile(fi1, fi2) { t.Fatalf("addr2line_test.go and %s are not same file", srcPath) } - if srcLineNo != "89" { - t.Fatalf("line number = %v; want 89", srcLineNo) + if srcLineNo != "97" { + t.Fatalf("line number = %v; want 97", srcLineNo) } } -// This is line 88. The test depends on that. +// This is line 96. The test depends on that. func TestAddr2Line(t *testing.T) { testenv.MustHaveGoBuild(t) diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go index 08ef056164..e1cd4965c3 100644 --- a/src/cmd/dist/test.go +++ b/src/cmd/dist/test.go @@ -178,15 +178,6 @@ func (t *tester) run() { return } - // We must unset GOROOT_FINAL before tests, because runtime/debug requires - // correct access to source code, so if we have GOROOT_FINAL in effect, - // at least runtime/debug test will fail. - // If GOROOT_FINAL was set before, then now all the commands will appear stale. - // Nothing we can do about that other than not checking them below. - // (We call checkNotStale but only with "std" not "cmd".) - os.Setenv("GOROOT_FINAL_OLD", os.Getenv("GOROOT_FINAL")) // for cmd/link test - os.Unsetenv("GOROOT_FINAL") - for _, name := range t.runNames { if !t.isRegisteredTestName(name) { fatalf("unknown test %q", name) diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go index 4c30de4781..021930a8a8 100644 --- a/src/cmd/go/go_test.go +++ b/src/cmd/go/go_test.go @@ -124,7 +124,6 @@ func TestMain(m *testing.M) { fmt.Printf("SKIP\n") return } - os.Unsetenv("GOROOT_FINAL") flag.Parse() @@ -180,6 +179,11 @@ func TestMain(m *testing.M) { } testGOROOT = goEnv("GOROOT") os.Setenv("TESTGO_GOROOT", testGOROOT) + // Ensure that GOROOT is set explicitly. + // Otherwise, if the toolchain was built with GOROOT_FINAL set but has not + // yet been moved to its final location, programs that invoke runtime.GOROOT + // may accidentally use the wrong path. + os.Setenv("GOROOT", testGOROOT) // The whole GOROOT/pkg tree was installed using the GOHOSTOS/GOHOSTARCH // toolchain (installed in GOROOT/pkg/tool/GOHOSTOS_GOHOSTARCH). @@ -216,8 +220,10 @@ func TestMain(m *testing.M) { } testCC = strings.TrimSpace(string(out)) - if out, err := exec.Command(testGo, "env", "CGO_ENABLED").Output(); err != nil { - fmt.Fprintf(os.Stderr, "running testgo failed: %v\n", err) + cmd := exec.Command(testGo, "env", "CGO_ENABLED") + cmd.Stderr = new(strings.Builder) + if out, err := cmd.Output(); err != nil { + fmt.Fprintf(os.Stderr, "running testgo failed: %v\n%s", err, cmd.Stderr) canRun = false } else { canCgo, err = strconv.ParseBool(strings.TrimSpace(string(out))) diff --git a/src/cmd/go/script_test.go b/src/cmd/go/script_test.go index a49a705fa6..2e8f18a897 100644 --- a/src/cmd/go/script_test.go +++ b/src/cmd/go/script_test.go @@ -130,6 +130,7 @@ func (ts *testScript) setup() { "GOPROXY=" + proxyURL, "GOPRIVATE=", "GOROOT=" + testGOROOT, + "GOROOT_FINAL=" + os.Getenv("GOROOT_FINAL"), // causes spurious rebuilds and breaks the "stale" built-in if not propagated "TESTGO_GOROOT=" + testGOROOT, "GOSUMDB=" + testSumDBVerifierKey, "GONOPROXY=", diff --git a/src/cmd/go/testdata/script/README b/src/cmd/go/testdata/script/README index c7fa7cfef5..76d6651718 100644 --- a/src/cmd/go/testdata/script/README +++ b/src/cmd/go/testdata/script/README @@ -34,6 +34,7 @@ Scripts also have access to these other environment variables: GOPATH=$WORK/gopath GOPROXY= GOROOT= + GOROOT_FINAL= TESTGO_GOROOT= HOME=/no-home PATH= diff --git a/src/cmd/go/testdata/script/build_trimpath.txt b/src/cmd/go/testdata/script/build_trimpath.txt index cfab80743e..ad78bcf2b2 100644 --- a/src/cmd/go/testdata/script/build_trimpath.txt +++ b/src/cmd/go/testdata/script/build_trimpath.txt @@ -1,5 +1,9 @@ [short] skip +# If GOROOT_FINAL is set, 'go build -trimpath' bakes that into the resulting +# binary instead of GOROOT. Explicitly unset it here. +env GOROOT_FINAL= + # Set up two identical directories that can be used as GOPATH. env GO111MODULE=on mkdir $WORK/a/src/paths $WORK/b/src/paths diff --git a/src/cmd/go/testdata/script/goroot_executable.txt b/src/cmd/go/testdata/script/goroot_executable.txt index 4e04bad69b..fdbcde06cb 100644 --- a/src/cmd/go/testdata/script/goroot_executable.txt +++ b/src/cmd/go/testdata/script/goroot_executable.txt @@ -2,6 +2,13 @@ mkdir $WORK/new/bin +# In this test, we are specifically checking the logic for deriving +# the value of GOROOT from runtime.GOROOT. +# GOROOT_FINAL changes the default behavior of runtime.GOROOT, +# and will thus cause the test to fail if it is set when our +# new cmd/go is built. +env GOROOT_FINAL= + go build -o $WORK/new/bin/go$GOEXE cmd/go & go build -o $WORK/bin/check$GOEXE check.go & wait diff --git a/src/cmd/link/dwarf_test.go b/src/cmd/link/dwarf_test.go index 5926f09e4a..a9f58db230 100644 --- a/src/cmd/link/dwarf_test.go +++ b/src/cmd/link/dwarf_test.go @@ -33,8 +33,8 @@ func testDWARF(t *testing.T, buildmode string, expectDWARF bool, env ...string) t.Fatalf("go list: %v\n%s", err, out) } if string(out) != "false\n" { - if os.Getenv("GOROOT_FINAL_OLD") != "" { - t.Skip("cmd/link is stale, but $GOROOT_FINAL_OLD is set") + if strings.HasPrefix(testenv.Builder(), "darwin-") { + t.Skipf("cmd/link is spuriously stale on Darwin builders - see #33598") } t.Fatalf("cmd/link is stale - run go install cmd/link") } diff --git a/src/cmd/objdump/objdump_test.go b/src/cmd/objdump/objdump_test.go index c974d6707b..a9dc7d1a5e 100644 --- a/src/cmd/objdump/objdump_test.go +++ b/src/cmd/objdump/objdump_test.go @@ -138,7 +138,11 @@ func testDisasm(t *testing.T, printCode bool, printGnuAsm bool, flags ...string) args = append(args, flags...) args = append(args, "fmthello.go") cmd := exec.Command(testenv.GoToolPath(t), args...) - cmd.Dir = "testdata" // "Bad line" bug #36683 is sensitive to being run in the source directory + // "Bad line" bug #36683 is sensitive to being run in the source directory. + cmd.Dir = "testdata" + // Ensure that the source file location embedded in the binary matches our + // actual current GOROOT, instead of GOROOT_FINAL if set. + cmd.Env = append(os.Environ(), "GOROOT_FINAL=") t.Logf("Running %v", cmd.Args) out, err := cmd.CombinedOutput() if err != nil { From bdcf33f1c0597bf18924c17ab2644310d204bf23 Mon Sep 17 00:00:00 2001 From: Dmitri Shuralyov Date: Tue, 9 Jun 2020 14:26:09 +0000 Subject: [PATCH 19/34] doc/go1.15: remove TODO in minor library changes section The minor changes to the library section has been populated with TODOs for individual packages using relnote in CL 235757, and they've been resolved in the following CLs. We will look things over as part of finishing touches on the release notes, but this TODO is resolved for beta 1. For #37419. Change-Id: I942f81a957fe8df8f630b4406ca29f73602d080a Reviewed-on: https://go-review.googlesource.com/c/go/+/237157 Reviewed-by: Alexander Rakoczy Reviewed-by: Carlos Amedee --- doc/go1.15.html | 4 ---- 1 file changed, 4 deletions(-) diff --git a/doc/go1.15.html b/doc/go1.15.html index 7a49e1fa1f..fc8ee2d31f 100644 --- a/doc/go1.15.html +++ b/doc/go1.15.html @@ -374,10 +374,6 @@ Do not send CLs removing the interior tags from such phrases. in mind.

-

-TODO -

-
debug/pe

From e031318ca6da8db8a08ecff734ae72290dfb5f2d Mon Sep 17 00:00:00 2001 From: Xiangdong Ji Date: Mon, 1 Jun 2020 11:01:14 +0000 Subject: [PATCH 20/34] cmd/compile: ARM comparisons with 0 incorrect on overflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some ARM rewriting rules convert 'comparing to zero' conditions of if statements to a simplified version utilizing CMN and CMP instructions to branch over condition flags, in order to save one Add or Sub caculation. Such optimizations lead to wrong branching in case an overflow/underflow occurs when executing CMN or CMP. Fix the issue by introducing new block opcodes that don't honor the overflow/underflow flag: Block-Op Meaning ARM condition codes 1. LTnoov less than MI 2. GEnoov greater than or equal PL 3. LEnoov less than or equal MI || EQ 4. GTnoov greater than NEQ & PL The patch also adds a few test cases to cover scenarios that are specific to ARM and fine-tunes the code generation tests for 'x-const'. For more details please refer to the previous fix on 64-bit ARM: https://go-review.googlesource.com/c/go/+/233097 Go1 perf, 'old' is the non-optimized version, that is removing all concerned rewriting rules. name old time/op new time/op delta BinaryTree17-8 7.73s ± 0% 7.81s ± 0% +0.97% (p=0.000 n=7+8) Fannkuch11-8 7.06s ± 0% 7.00s ± 0% -0.83% (p=0.000 n=8+8) FmtFprintfEmpty-8 181ns ± 1% 183ns ± 1% +1.31% (p=0.001 n=8+8) FmtFprintfString-8 319ns ± 1% 325ns ± 2% +1.71% (p=0.009 n=7+8) FmtFprintfInt-8 358ns ± 1% 359ns ± 1% ~ (p=0.293 n=7+7) FmtFprintfIntInt-8 459ns ± 3% 456ns ± 1% ~ (p=0.869 n=8+8) FmtFprintfPrefixedInt-8 535ns ± 4% 538ns ± 4% ~ (p=0.572 n=8+8) FmtFprintfFloat-8 1.01µs ± 2% 1.01µs ± 2% ~ (p=0.625 n=8+8) FmtManyArgs-8 1.93µs ± 2% 1.93µs ± 1% ~ (p=0.979 n=8+7) GobDecode-8 16.1ms ± 1% 16.5ms ± 1% +2.32% (p=0.000 n=8+8) GobEncode-8 15.9ms ± 0% 15.8ms ± 1% -1.00% (p=0.000 n=8+7) Gzip-8 690ms ± 1% 670ms ± 0% -2.90% (p=0.000 n=8+8) Gunzip-8 109ms ± 1% 109ms ± 1% ~ (p=0.694 n=7+8) HTTPClientServer-8 149µs ± 3% 146µs ± 2% -1.70% (p=0.028 n=8+8) JSONEncode-8 50.5ms ± 1% 49.2ms ± 0% -2.60% (p=0.001 n=7+7) JSONDecode-8 135ms ± 2% 137ms ± 1% ~ (p=0.054 n=8+7) Mandelbrot200-8 951ms ± 0% 952ms ± 0% ~ (p=0.852 n=6+8) GoParse-8 9.47ms ± 1% 9.66ms ± 1% +2.01% (p=0.000 n=8+8) RegexpMatchEasy0_32-8 288ns ± 2% 277ns ± 2% -3.61% (p=0.000 n=8+8) RegexpMatchEasy0_1K-8 1.66µs ± 1% 1.69µs ± 2% +2.21% (p=0.001 n=7+7) RegexpMatchEasy1_32-8 334ns ± 1% 305ns ± 2% -8.86% (p=0.000 n=8+8) RegexpMatchEasy1_1K-8 2.14µs ± 2% 2.15µs ± 0% ~ (p=0.099 n=8+8) RegexpMatchMedium_32-8 13.3ns ± 1% 13.3ns ± 0% ~ (p=1.000 n=7+7) RegexpMatchMedium_1K-8 81.1µs ± 3% 80.7µs ± 1% ~ (p=0.955 n=7+8) RegexpMatchHard_32-8 4.26µs ± 0% 4.26µs ± 0% ~ (p=0.933 n=7+8) RegexpMatchHard_1K-8 124µs ± 0% 124µs ± 0% +0.31% (p=0.000 n=8+8) Revcomp-8 14.7ms ± 2% 14.5ms ± 1% -1.66% (p=0.003 n=8+8) Template-8 197ms ± 2% 200ms ± 3% +1.62% (p=0.021 n=8+8) TimeParse-8 1.33µs ± 1% 1.30µs ± 1% -1.86% (p=0.002 n=8+8) TimeFormat-8 3.04µs ± 1% 3.02µs ± 0% -0.60% (p=0.000 n=8+8) name old speed new speed delta GobDecode-8 47.6MB/s ± 1% 46.5MB/s ± 1% -2.28% (p=0.000 n=8+8) GobEncode-8 48.1MB/s ± 0% 48.6MB/s ± 1% +1.02% (p=0.000 n=8+7) Gzip-8 28.1MB/s ± 1% 29.0MB/s ± 0% +2.97% (p=0.000 n=8+8) Gunzip-8 178MB/s ± 1% 179MB/s ± 2% ~ (p=0.694 n=7+8) JSONEncode-8 38.4MB/s ± 1% 39.4MB/s ± 0% +2.67% (p=0.001 n=7+7) JSONDecode-8 14.3MB/s ± 2% 14.2MB/s ± 1% -0.81% (p=0.043 n=8+7) GoParse-8 6.12MB/s ± 1% 5.99MB/s ± 1% -2.00% (p=0.000 n=8+8) RegexpMatchEasy0_32-8 111MB/s ± 2% 115MB/s ± 2% +3.77% (p=0.000 n=8+8) RegexpMatchEasy0_1K-8 618MB/s ± 1% 604MB/s ± 2% -2.16% (p=0.001 n=7+7) RegexpMatchEasy1_32-8 95.7MB/s ± 1% 105.1MB/s ± 2% +9.76% (p=0.000 n=8+8) RegexpMatchEasy1_1K-8 479MB/s ± 2% 477MB/s ± 0% ~ (p=0.105 n=8+8) RegexpMatchMedium_32-8 75.2MB/s ± 1% 75.2MB/s ± 0% ~ (p=0.247 n=7+7) RegexpMatchMedium_1K-8 12.6MB/s ± 3% 12.7MB/s ± 1% ~ (p=0.538 n=7+8) RegexpMatchHard_32-8 7.52MB/s ± 0% 7.52MB/s ± 0% ~ (p=0.968 n=7+8) RegexpMatchHard_1K-8 8.26MB/s ± 0% 8.24MB/s ± 0% -0.30% (p=0.001 n=8+8) Revcomp-8 173MB/s ± 2% 176MB/s ± 1% +1.68% (p=0.003 n=8+8) Template-8 9.85MB/s ± 2% 9.69MB/s ± 3% -1.59% (p=0.021 n=8+8) Fixes #39303 Updates #38740 Change-Id: I0a5f87bfda679f66414c0041ace2ca2e28363f36 Reviewed-on: https://go-review.googlesource.com/c/go/+/236637 Run-TryBot: Keith Randall TryBot-Result: Gobot Gobot Reviewed-by: Keith Randall --- src/cmd/compile/fmtmap_test.go | 2 + src/cmd/compile/internal/arm/ssa.go | 43 ++- src/cmd/compile/internal/ssa/gen/ARM.rules | 148 ++++---- src/cmd/compile/internal/ssa/gen/ARMOps.go | 4 + src/cmd/compile/internal/ssa/opGen.go | 28 +- src/cmd/compile/internal/ssa/rewriteARM.go | 324 ++++++++++-------- .../compile/internal/ssa/rewriteCond_test.go | 95 ++++- test/codegen/comparisons.go | 33 +- 8 files changed, 418 insertions(+), 259 deletions(-) diff --git a/src/cmd/compile/fmtmap_test.go b/src/cmd/compile/fmtmap_test.go index 6f69abf4fb..cb7a7d9af8 100644 --- a/src/cmd/compile/fmtmap_test.go +++ b/src/cmd/compile/fmtmap_test.go @@ -140,6 +140,7 @@ var knownFormats = map[string]string{ "float64 %.3f": "", "float64 %.6g": "", "float64 %g": "", + "int %#x": "", "int %-12d": "", "int %-6d": "", "int %-8o": "", @@ -203,6 +204,7 @@ var knownFormats = map[string]string{ "uint64 %b": "", "uint64 %d": "", "uint64 %x": "", + "uint8 %#x": "", "uint8 %d": "", "uint8 %v": "", "uint8 %x": "", diff --git a/src/cmd/compile/internal/arm/ssa.go b/src/cmd/compile/internal/arm/ssa.go index 9935616f41..1da72aaf56 100644 --- a/src/cmd/compile/internal/arm/ssa.go +++ b/src/cmd/compile/internal/arm/ssa.go @@ -888,16 +888,30 @@ var condBits = map[ssa.Op]uint8{ var blockJump = map[ssa.BlockKind]struct { asm, invasm obj.As }{ - ssa.BlockARMEQ: {arm.ABEQ, arm.ABNE}, - ssa.BlockARMNE: {arm.ABNE, arm.ABEQ}, - ssa.BlockARMLT: {arm.ABLT, arm.ABGE}, - ssa.BlockARMGE: {arm.ABGE, arm.ABLT}, - ssa.BlockARMLE: {arm.ABLE, arm.ABGT}, - ssa.BlockARMGT: {arm.ABGT, arm.ABLE}, - ssa.BlockARMULT: {arm.ABLO, arm.ABHS}, - ssa.BlockARMUGE: {arm.ABHS, arm.ABLO}, - ssa.BlockARMUGT: {arm.ABHI, arm.ABLS}, - ssa.BlockARMULE: {arm.ABLS, arm.ABHI}, + ssa.BlockARMEQ: {arm.ABEQ, arm.ABNE}, + ssa.BlockARMNE: {arm.ABNE, arm.ABEQ}, + ssa.BlockARMLT: {arm.ABLT, arm.ABGE}, + ssa.BlockARMGE: {arm.ABGE, arm.ABLT}, + ssa.BlockARMLE: {arm.ABLE, arm.ABGT}, + ssa.BlockARMGT: {arm.ABGT, arm.ABLE}, + ssa.BlockARMULT: {arm.ABLO, arm.ABHS}, + ssa.BlockARMUGE: {arm.ABHS, arm.ABLO}, + ssa.BlockARMUGT: {arm.ABHI, arm.ABLS}, + ssa.BlockARMULE: {arm.ABLS, arm.ABHI}, + ssa.BlockARMLTnoov: {arm.ABMI, arm.ABPL}, + ssa.BlockARMGEnoov: {arm.ABPL, arm.ABMI}, +} + +// To model a 'LEnoov' ('<=' without overflow checking) branching +var leJumps = [2][2]gc.IndexJump{ + {{Jump: arm.ABEQ, Index: 0}, {Jump: arm.ABPL, Index: 1}}, // next == b.Succs[0] + {{Jump: arm.ABMI, Index: 0}, {Jump: arm.ABEQ, Index: 0}}, // next == b.Succs[1] +} + +// To model a 'GTnoov' ('>' without overflow checking) branching +var gtJumps = [2][2]gc.IndexJump{ + {{Jump: arm.ABMI, Index: 1}, {Jump: arm.ABEQ, Index: 1}}, // next == b.Succs[0] + {{Jump: arm.ABEQ, Index: 1}, {Jump: arm.ABPL, Index: 0}}, // next == b.Succs[1] } func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) { @@ -941,7 +955,8 @@ func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) { ssa.BlockARMLT, ssa.BlockARMGE, ssa.BlockARMLE, ssa.BlockARMGT, ssa.BlockARMULT, ssa.BlockARMUGT, - ssa.BlockARMULE, ssa.BlockARMUGE: + ssa.BlockARMULE, ssa.BlockARMUGE, + ssa.BlockARMLTnoov, ssa.BlockARMGEnoov: jmp := blockJump[b.Kind] switch next { case b.Succs[0].Block(): @@ -958,6 +973,12 @@ func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) { } } + case ssa.BlockARMLEnoov: + s.CombJump(b, next, &leJumps) + + case ssa.BlockARMGTnoov: + s.CombJump(b, next, >Jumps) + default: b.Fatalf("branch not implemented: %s", b.LongString()) } diff --git a/src/cmd/compile/internal/ssa/gen/ARM.rules b/src/cmd/compile/internal/ssa/gen/ARM.rules index a8cea68c5f..5b3179acbe 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM.rules +++ b/src/cmd/compile/internal/ssa/gen/ARM.rules @@ -704,6 +704,10 @@ (UGE (InvertFlags cmp) yes no) -> (ULE cmp yes no) (EQ (InvertFlags cmp) yes no) -> (EQ cmp yes no) (NE (InvertFlags cmp) yes no) -> (NE cmp yes no) +(LTnoov (InvertFlags cmp) yes no) => (GTnoov cmp yes no) +(GEnoov (InvertFlags cmp) yes no) => (LEnoov cmp yes no) +(LEnoov (InvertFlags cmp) yes no) => (GEnoov cmp yes no) +(GTnoov (InvertFlags cmp) yes no) => (LTnoov cmp yes no) // absorb flag constants into boolean values (Equal (FlagEQ)) -> (MOVWconst [1]) @@ -1417,42 +1421,42 @@ (NE (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 -> (NE (TEQshiftLLreg x y z) yes no) (NE (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 -> (NE (TEQshiftRLreg x y z) yes no) (NE (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 -> (NE (TEQshiftRAreg x y z) yes no) -(LT (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 -> (LT (CMP x y) yes no) -(LT (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 -> (LT (CMP a (MUL x y)) yes no) -(LT (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 -> (LT (CMPconst [c] x) yes no) -(LT (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) && l.Uses==1 -> (LT (CMPshiftLL x y [c]) yes no) -(LT (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) && l.Uses==1 -> (LT (CMPshiftRL x y [c]) yes no) -(LT (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) && l.Uses==1 -> (LT (CMPshiftRA x y [c]) yes no) -(LT (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) && l.Uses==1 -> (LT (CMPshiftLLreg x y z) yes no) -(LT (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) && l.Uses==1 -> (LT (CMPshiftRLreg x y z) yes no) -(LT (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) && l.Uses==1 -> (LT (CMPshiftRAreg x y z) yes no) -(LE (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 -> (LE (CMP x y) yes no) -(LE (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 -> (LE (CMP a (MUL x y)) yes no) -(LE (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 -> (LE (CMPconst [c] x) yes no) -(LE (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) && l.Uses==1 -> (LE (CMPshiftLL x y [c]) yes no) -(LE (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) && l.Uses==1 -> (LE (CMPshiftRL x y [c]) yes no) -(LE (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) && l.Uses==1 -> (LE (CMPshiftRA x y [c]) yes no) -(LE (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) && l.Uses==1 -> (LE (CMPshiftLLreg x y z) yes no) -(LE (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) && l.Uses==1 -> (LE (CMPshiftRLreg x y z) yes no) -(LE (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) && l.Uses==1 -> (LE (CMPshiftRAreg x y z) yes no) -(LT (CMPconst [0] l:(ADD x y)) yes no) && l.Uses==1 -> (LT (CMN x y) yes no) -(LT (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 -> (LT (CMN a (MUL x y)) yes no) -(LT (CMPconst [0] l:(ADDconst [c] x)) yes no) && l.Uses==1 -> (LT (CMNconst [c] x) yes no) -(LT (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) && l.Uses==1 -> (LT (CMNshiftLL x y [c]) yes no) -(LT (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) && l.Uses==1 -> (LT (CMNshiftRL x y [c]) yes no) -(LT (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) && l.Uses==1 -> (LT (CMNshiftRA x y [c]) yes no) -(LT (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 -> (LT (CMNshiftLLreg x y z) yes no) -(LT (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 -> (LT (CMNshiftRLreg x y z) yes no) -(LT (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 -> (LT (CMNshiftRAreg x y z) yes no) -(LE (CMPconst [0] l:(ADD x y)) yes no) && l.Uses==1 -> (LE (CMN x y) yes no) -(LE (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 -> (LE (CMN a (MUL x y)) yes no) -(LE (CMPconst [0] l:(ADDconst [c] x)) yes no) && l.Uses==1 -> (LE (CMNconst [c] x) yes no) -(LE (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) && l.Uses==1 -> (LE (CMNshiftLL x y [c]) yes no) -(LE (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) && l.Uses==1 -> (LE (CMNshiftRL x y [c]) yes no) -(LE (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) && l.Uses==1 -> (LE (CMNshiftRA x y [c]) yes no) -(LE (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 -> (LE (CMNshiftLLreg x y z) yes no) -(LE (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 -> (LE (CMNshiftRLreg x y z) yes no) -(LE (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 -> (LE (CMNshiftRAreg x y z) yes no) +(LT (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 -> (LTnoov (CMP x y) yes no) +(LT (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 -> (LTnoov (CMP a (MUL x y)) yes no) +(LT (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 -> (LTnoov (CMPconst [c] x) yes no) +(LT (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) && l.Uses==1 -> (LTnoov (CMPshiftLL x y [c]) yes no) +(LT (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) && l.Uses==1 -> (LTnoov (CMPshiftRL x y [c]) yes no) +(LT (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) && l.Uses==1 -> (LTnoov (CMPshiftRA x y [c]) yes no) +(LT (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) && l.Uses==1 -> (LTnoov (CMPshiftLLreg x y z) yes no) +(LT (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) && l.Uses==1 -> (LTnoov (CMPshiftRLreg x y z) yes no) +(LT (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) && l.Uses==1 -> (LTnoov (CMPshiftRAreg x y z) yes no) +(LE (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 -> (LEnoov (CMP x y) yes no) +(LE (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 -> (LEnoov (CMP a (MUL x y)) yes no) +(LE (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 -> (LEnoov (CMPconst [c] x) yes no) +(LE (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) && l.Uses==1 -> (LEnoov (CMPshiftLL x y [c]) yes no) +(LE (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) && l.Uses==1 -> (LEnoov (CMPshiftRL x y [c]) yes no) +(LE (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) && l.Uses==1 -> (LEnoov (CMPshiftRA x y [c]) yes no) +(LE (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) && l.Uses==1 -> (LEnoov (CMPshiftLLreg x y z) yes no) +(LE (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) && l.Uses==1 -> (LEnoov (CMPshiftRLreg x y z) yes no) +(LE (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) && l.Uses==1 -> (LEnoov (CMPshiftRAreg x y z) yes no) +(LT (CMPconst [0] l:(ADD x y)) yes no) && l.Uses==1 -> (LTnoov (CMN x y) yes no) +(LT (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 -> (LTnoov (CMN a (MUL x y)) yes no) +(LT (CMPconst [0] l:(ADDconst [c] x)) yes no) && l.Uses==1 -> (LTnoov (CMNconst [c] x) yes no) +(LT (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) && l.Uses==1 -> (LTnoov (CMNshiftLL x y [c]) yes no) +(LT (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) && l.Uses==1 -> (LTnoov (CMNshiftRL x y [c]) yes no) +(LT (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) && l.Uses==1 -> (LTnoov (CMNshiftRA x y [c]) yes no) +(LT (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 -> (LTnoov (CMNshiftLLreg x y z) yes no) +(LT (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 -> (LTnoov (CMNshiftRLreg x y z) yes no) +(LT (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 -> (LTnoov (CMNshiftRAreg x y z) yes no) +(LE (CMPconst [0] l:(ADD x y)) yes no) && l.Uses==1 -> (LEnoov (CMN x y) yes no) +(LE (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 -> (LEnoov (CMN a (MUL x y)) yes no) +(LE (CMPconst [0] l:(ADDconst [c] x)) yes no) && l.Uses==1 -> (LEnoov (CMNconst [c] x) yes no) +(LE (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) && l.Uses==1 -> (LEnoov (CMNshiftLL x y [c]) yes no) +(LE (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) && l.Uses==1 -> (LEnoov (CMNshiftRL x y [c]) yes no) +(LE (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) && l.Uses==1 -> (LEnoov (CMNshiftRA x y [c]) yes no) +(LE (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 -> (LEnoov (CMNshiftLLreg x y z) yes no) +(LE (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 -> (LEnoov (CMNshiftRLreg x y z) yes no) +(LE (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 -> (LEnoov (CMNshiftRAreg x y z) yes no) (LT (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 -> (LT (TST x y) yes no) (LT (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 -> (LT (TSTconst [c] x) yes no) (LT (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 -> (LT (TSTshiftLL x y [c]) yes no) @@ -1485,43 +1489,43 @@ (LE (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 -> (LE (TEQshiftLLreg x y z) yes no) (LE (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 -> (LE (TEQshiftRLreg x y z) yes no) (LE (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 -> (LE (TEQshiftRAreg x y z) yes no) -(GT (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 -> (GT (CMP x y) yes no) -(GT (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 -> (GT (CMP a (MUL x y)) yes no) -(GT (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 -> (GT (CMPconst [c] x) yes no) -(GT (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) && l.Uses==1 -> (GT (CMPshiftLL x y [c]) yes no) -(GT (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) && l.Uses==1 -> (GT (CMPshiftRL x y [c]) yes no) -(GT (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) && l.Uses==1 -> (GT (CMPshiftRA x y [c]) yes no) -(GT (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) && l.Uses==1 -> (GT (CMPshiftLLreg x y z) yes no) -(GT (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) && l.Uses==1 -> (GT (CMPshiftRLreg x y z) yes no) -(GT (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) && l.Uses==1 -> (GT (CMPshiftRAreg x y z) yes no) -(GE (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 -> (GE (CMP x y) yes no) -(GE (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 -> (GE (CMP a (MUL x y)) yes no) -(GE (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 -> (GE (CMPconst [c] x) yes no) -(GE (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) && l.Uses==1 -> (GE (CMPshiftLL x y [c]) yes no) -(GE (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) && l.Uses==1 -> (GE (CMPshiftRL x y [c]) yes no) -(GE (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) && l.Uses==1 -> (GE (CMPshiftRA x y [c]) yes no) -(GE (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) && l.Uses==1 -> (GE (CMPshiftLLreg x y z) yes no) -(GE (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) && l.Uses==1 -> (GE (CMPshiftRLreg x y z) yes no) -(GE (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) && l.Uses==1 -> (GE (CMPshiftRAreg x y z) yes no) -(GT (CMPconst [0] l:(ADD x y)) yes no) && l.Uses==1 -> (GT (CMN x y) yes no) -(GT (CMPconst [0] l:(ADDconst [c] x)) yes no) && l.Uses==1 -> (GT (CMNconst [c] x) yes no) -(GT (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) && l.Uses==1 -> (GT (CMNshiftLL x y [c]) yes no) -(GT (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) && l.Uses==1 -> (GT (CMNshiftRL x y [c]) yes no) -(GT (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) && l.Uses==1 -> (GT (CMNshiftRA x y [c]) yes no) -(GT (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 -> (GT (CMNshiftLLreg x y z) yes no) -(GT (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 -> (GT (CMNshiftRLreg x y z) yes no) -(GT (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 -> (GT (CMNshiftRAreg x y z) yes no) -(GE (CMPconst [0] l:(ADD x y)) yes no) && l.Uses==1 -> (GE (CMN x y) yes no) -(GE (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 -> (GE (CMN a (MUL x y)) yes no) -(GE (CMPconst [0] l:(ADDconst [c] x)) yes no) && l.Uses==1 -> (GE (CMNconst [c] x) yes no) -(GE (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) && l.Uses==1 -> (GE (CMNshiftLL x y [c]) yes no) -(GE (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) && l.Uses==1 -> (GE (CMNshiftRL x y [c]) yes no) -(GE (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) && l.Uses==1 -> (GE (CMNshiftRA x y [c]) yes no) -(GE (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 -> (GE (CMNshiftLLreg x y z) yes no) -(GE (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 -> (GE (CMNshiftRLreg x y z) yes no) -(GE (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 -> (GE (CMNshiftRAreg x y z) yes no) +(GT (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 -> (GTnoov (CMP x y) yes no) +(GT (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 -> (GTnoov (CMP a (MUL x y)) yes no) +(GT (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 -> (GTnoov (CMPconst [c] x) yes no) +(GT (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) && l.Uses==1 -> (GTnoov (CMPshiftLL x y [c]) yes no) +(GT (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) && l.Uses==1 -> (GTnoov (CMPshiftRL x y [c]) yes no) +(GT (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) && l.Uses==1 -> (GTnoov (CMPshiftRA x y [c]) yes no) +(GT (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) && l.Uses==1 -> (GTnoov (CMPshiftLLreg x y z) yes no) +(GT (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) && l.Uses==1 -> (GTnoov (CMPshiftRLreg x y z) yes no) +(GT (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) && l.Uses==1 -> (GTnoov (CMPshiftRAreg x y z) yes no) +(GE (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 -> (GEnoov (CMP x y) yes no) +(GE (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 -> (GEnoov (CMP a (MUL x y)) yes no) +(GE (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 -> (GEnoov (CMPconst [c] x) yes no) +(GE (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) && l.Uses==1 -> (GEnoov (CMPshiftLL x y [c]) yes no) +(GE (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) && l.Uses==1 -> (GEnoov (CMPshiftRL x y [c]) yes no) +(GE (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) && l.Uses==1 -> (GEnoov (CMPshiftRA x y [c]) yes no) +(GE (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) && l.Uses==1 -> (GEnoov (CMPshiftLLreg x y z) yes no) +(GE (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) && l.Uses==1 -> (GEnoov (CMPshiftRLreg x y z) yes no) +(GE (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) && l.Uses==1 -> (GEnoov (CMPshiftRAreg x y z) yes no) +(GT (CMPconst [0] l:(ADD x y)) yes no) && l.Uses==1 -> (GTnoov (CMN x y) yes no) +(GT (CMPconst [0] l:(ADDconst [c] x)) yes no) && l.Uses==1 -> (GTnoov (CMNconst [c] x) yes no) +(GT (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) && l.Uses==1 -> (GTnoov (CMNshiftLL x y [c]) yes no) +(GT (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) && l.Uses==1 -> (GTnoov (CMNshiftRL x y [c]) yes no) +(GT (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) && l.Uses==1 -> (GTnoov (CMNshiftRA x y [c]) yes no) +(GT (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 -> (GTnoov (CMNshiftLLreg x y z) yes no) +(GT (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 -> (GTnoov (CMNshiftRLreg x y z) yes no) +(GT (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 -> (GTnoov (CMNshiftRAreg x y z) yes no) +(GE (CMPconst [0] l:(ADD x y)) yes no) && l.Uses==1 -> (GEnoov (CMN x y) yes no) +(GE (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 -> (GEnoov (CMN a (MUL x y)) yes no) +(GE (CMPconst [0] l:(ADDconst [c] x)) yes no) && l.Uses==1 -> (GEnoov (CMNconst [c] x) yes no) +(GE (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) && l.Uses==1 -> (GEnoov (CMNshiftLL x y [c]) yes no) +(GE (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) && l.Uses==1 -> (GEnoov (CMNshiftRL x y [c]) yes no) +(GE (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) && l.Uses==1 -> (GEnoov (CMNshiftRA x y [c]) yes no) +(GE (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 -> (GEnoov (CMNshiftLLreg x y z) yes no) +(GE (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 -> (GEnoov (CMNshiftRLreg x y z) yes no) +(GE (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 -> (GEnoov (CMNshiftRAreg x y z) yes no) (GT (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 -> (GT (TST x y) yes no) -(GT (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 -> (GT (CMN a (MUL x y)) yes no) +(GT (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 -> (GTnoov (CMN a (MUL x y)) yes no) (GT (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 -> (GT (TSTconst [c] x) yes no) (GT (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 -> (GT (TSTshiftLL x y [c]) yes no) (GT (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 -> (GT (TSTshiftRL x y [c]) yes no) diff --git a/src/cmd/compile/internal/ssa/gen/ARMOps.go b/src/cmd/compile/internal/ssa/gen/ARMOps.go index 4abe5c9a8b..14407feaa2 100644 --- a/src/cmd/compile/internal/ssa/gen/ARMOps.go +++ b/src/cmd/compile/internal/ssa/gen/ARMOps.go @@ -584,6 +584,10 @@ func init() { {name: "ULE", controls: 1}, {name: "UGT", controls: 1}, {name: "UGE", controls: 1}, + {name: "LTnoov", controls: 1}, // 'LT' but without honoring overflow + {name: "LEnoov", controls: 1}, // 'LE' but without honoring overflow + {name: "GTnoov", controls: 1}, // 'GT' but without honoring overflow + {name: "GEnoov", controls: 1}, // 'GE' but without honoring overflow } archs = append(archs, arch{ diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 4a83a46be2..7f6bf3e15b 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -61,6 +61,10 @@ const ( BlockARMULE BlockARMUGT BlockARMUGE + BlockARMLTnoov + BlockARMLEnoov + BlockARMGTnoov + BlockARMGEnoov BlockARM64EQ BlockARM64NE @@ -185,16 +189,20 @@ var blockString = [...]string{ BlockAMD64ORD: "ORD", BlockAMD64NAN: "NAN", - BlockARMEQ: "EQ", - BlockARMNE: "NE", - BlockARMLT: "LT", - BlockARMLE: "LE", - BlockARMGT: "GT", - BlockARMGE: "GE", - BlockARMULT: "ULT", - BlockARMULE: "ULE", - BlockARMUGT: "UGT", - BlockARMUGE: "UGE", + BlockARMEQ: "EQ", + BlockARMNE: "NE", + BlockARMLT: "LT", + BlockARMLE: "LE", + BlockARMGT: "GT", + BlockARMGE: "GE", + BlockARMULT: "ULT", + BlockARMULE: "ULE", + BlockARMUGT: "UGT", + BlockARMUGE: "UGE", + BlockARMLTnoov: "LTnoov", + BlockARMLEnoov: "LEnoov", + BlockARMGTnoov: "GTnoov", + BlockARMGEnoov: "GEnoov", BlockARM64EQ: "EQ", BlockARM64NE: "NE", diff --git a/src/cmd/compile/internal/ssa/rewriteARM.go b/src/cmd/compile/internal/ssa/rewriteARM.go index 5c8dd0f2ed..be5f56a1f7 100644 --- a/src/cmd/compile/internal/ssa/rewriteARM.go +++ b/src/cmd/compile/internal/ssa/rewriteARM.go @@ -17514,7 +17514,7 @@ func rewriteBlockARM(b *Block) bool { } // match: (GE (CMPconst [0] l:(SUB x y)) yes no) // cond: l.Uses==1 - // result: (GE (CMP x y) yes no) + // result: (GEnoov (CMP x y) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -17531,12 +17531,12 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMCMP, types.TypeFlags) v0.AddArg2(x, y) - b.resetWithControl(BlockARMGE, v0) + b.resetWithControl(BlockARMGEnoov, v0) return true } // match: (GE (CMPconst [0] l:(MULS x y a)) yes no) // cond: l.Uses==1 - // result: (GE (CMP a (MUL x y)) yes no) + // result: (GEnoov (CMP a (MUL x y)) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -17556,12 +17556,12 @@ func rewriteBlockARM(b *Block) bool { v1 := b.NewValue0(v_0.Pos, OpARMMUL, x.Type) v1.AddArg2(x, y) v0.AddArg2(a, v1) - b.resetWithControl(BlockARMGE, v0) + b.resetWithControl(BlockARMGEnoov, v0) return true } // match: (GE (CMPconst [0] l:(SUBconst [c] x)) yes no) // cond: l.Uses==1 - // result: (GE (CMPconst [c] x) yes no) + // result: (GEnoov (CMPconst [c] x) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -17579,12 +17579,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMCMPconst, types.TypeFlags) v0.AuxInt = c v0.AddArg(x) - b.resetWithControl(BlockARMGE, v0) + b.resetWithControl(BlockARMGEnoov, v0) return true } // match: (GE (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) // cond: l.Uses==1 - // result: (GE (CMPshiftLL x y [c]) yes no) + // result: (GEnoov (CMPshiftLL x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -17603,12 +17603,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftLL, types.TypeFlags) v0.AuxInt = c v0.AddArg2(x, y) - b.resetWithControl(BlockARMGE, v0) + b.resetWithControl(BlockARMGEnoov, v0) return true } // match: (GE (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) // cond: l.Uses==1 - // result: (GE (CMPshiftRL x y [c]) yes no) + // result: (GEnoov (CMPshiftRL x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -17627,12 +17627,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRL, types.TypeFlags) v0.AuxInt = c v0.AddArg2(x, y) - b.resetWithControl(BlockARMGE, v0) + b.resetWithControl(BlockARMGEnoov, v0) return true } // match: (GE (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) // cond: l.Uses==1 - // result: (GE (CMPshiftRA x y [c]) yes no) + // result: (GEnoov (CMPshiftRA x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -17651,12 +17651,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRA, types.TypeFlags) v0.AuxInt = c v0.AddArg2(x, y) - b.resetWithControl(BlockARMGE, v0) + b.resetWithControl(BlockARMGEnoov, v0) return true } // match: (GE (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) // cond: l.Uses==1 - // result: (GE (CMPshiftLLreg x y z) yes no) + // result: (GEnoov (CMPshiftLLreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -17674,12 +17674,12 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftLLreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMGE, v0) + b.resetWithControl(BlockARMGEnoov, v0) return true } // match: (GE (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) // cond: l.Uses==1 - // result: (GE (CMPshiftRLreg x y z) yes no) + // result: (GEnoov (CMPshiftRLreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -17697,12 +17697,12 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRLreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMGE, v0) + b.resetWithControl(BlockARMGEnoov, v0) return true } // match: (GE (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) // cond: l.Uses==1 - // result: (GE (CMPshiftRAreg x y z) yes no) + // result: (GEnoov (CMPshiftRAreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -17720,12 +17720,12 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRAreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMGE, v0) + b.resetWithControl(BlockARMGEnoov, v0) return true } // match: (GE (CMPconst [0] l:(ADD x y)) yes no) // cond: l.Uses==1 - // result: (GE (CMN x y) yes no) + // result: (GEnoov (CMN x y) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -17746,14 +17746,14 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMCMN, types.TypeFlags) v0.AddArg2(x, y) - b.resetWithControl(BlockARMGE, v0) + b.resetWithControl(BlockARMGEnoov, v0) return true } break } // match: (GE (CMPconst [0] l:(MULA x y a)) yes no) // cond: l.Uses==1 - // result: (GE (CMN a (MUL x y)) yes no) + // result: (GEnoov (CMN a (MUL x y)) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -17773,12 +17773,12 @@ func rewriteBlockARM(b *Block) bool { v1 := b.NewValue0(v_0.Pos, OpARMMUL, x.Type) v1.AddArg2(x, y) v0.AddArg2(a, v1) - b.resetWithControl(BlockARMGE, v0) + b.resetWithControl(BlockARMGEnoov, v0) return true } // match: (GE (CMPconst [0] l:(ADDconst [c] x)) yes no) // cond: l.Uses==1 - // result: (GE (CMNconst [c] x) yes no) + // result: (GEnoov (CMNconst [c] x) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -17796,12 +17796,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMCMNconst, types.TypeFlags) v0.AuxInt = c v0.AddArg(x) - b.resetWithControl(BlockARMGE, v0) + b.resetWithControl(BlockARMGEnoov, v0) return true } // match: (GE (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) // cond: l.Uses==1 - // result: (GE (CMNshiftLL x y [c]) yes no) + // result: (GEnoov (CMNshiftLL x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -17820,12 +17820,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftLL, types.TypeFlags) v0.AuxInt = c v0.AddArg2(x, y) - b.resetWithControl(BlockARMGE, v0) + b.resetWithControl(BlockARMGEnoov, v0) return true } // match: (GE (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) // cond: l.Uses==1 - // result: (GE (CMNshiftRL x y [c]) yes no) + // result: (GEnoov (CMNshiftRL x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -17844,12 +17844,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRL, types.TypeFlags) v0.AuxInt = c v0.AddArg2(x, y) - b.resetWithControl(BlockARMGE, v0) + b.resetWithControl(BlockARMGEnoov, v0) return true } // match: (GE (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) // cond: l.Uses==1 - // result: (GE (CMNshiftRA x y [c]) yes no) + // result: (GEnoov (CMNshiftRA x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -17868,12 +17868,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRA, types.TypeFlags) v0.AuxInt = c v0.AddArg2(x, y) - b.resetWithControl(BlockARMGE, v0) + b.resetWithControl(BlockARMGEnoov, v0) return true } // match: (GE (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) // cond: l.Uses==1 - // result: (GE (CMNshiftLLreg x y z) yes no) + // result: (GEnoov (CMNshiftLLreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -17891,12 +17891,12 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftLLreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMGE, v0) + b.resetWithControl(BlockARMGEnoov, v0) return true } // match: (GE (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) // cond: l.Uses==1 - // result: (GE (CMNshiftRLreg x y z) yes no) + // result: (GEnoov (CMNshiftRLreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -17914,12 +17914,12 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRLreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMGE, v0) + b.resetWithControl(BlockARMGEnoov, v0) return true } // match: (GE (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) // cond: l.Uses==1 - // result: (GE (CMNshiftRAreg x y z) yes no) + // result: (GEnoov (CMNshiftRAreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -17937,7 +17937,7 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRAreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMGE, v0) + b.resetWithControl(BlockARMGEnoov, v0) return true } // match: (GE (CMPconst [0] l:(AND x y)) yes no) @@ -18324,6 +18324,15 @@ func rewriteBlockARM(b *Block) bool { b.resetWithControl(BlockARMGE, v0) return true } + case BlockARMGEnoov: + // match: (GEnoov (InvertFlags cmp) yes no) + // result: (LEnoov cmp yes no) + for b.Controls[0].Op == OpARMInvertFlags { + v_0 := b.Controls[0] + cmp := v_0.Args[0] + b.resetWithControl(BlockARMLEnoov, cmp) + return true + } case BlockARMGT: // match: (GT (FlagEQ) yes no) // result: (First no yes) @@ -18368,7 +18377,7 @@ func rewriteBlockARM(b *Block) bool { } // match: (GT (CMPconst [0] l:(SUB x y)) yes no) // cond: l.Uses==1 - // result: (GT (CMP x y) yes no) + // result: (GTnoov (CMP x y) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -18385,12 +18394,12 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMCMP, types.TypeFlags) v0.AddArg2(x, y) - b.resetWithControl(BlockARMGT, v0) + b.resetWithControl(BlockARMGTnoov, v0) return true } // match: (GT (CMPconst [0] l:(MULS x y a)) yes no) // cond: l.Uses==1 - // result: (GT (CMP a (MUL x y)) yes no) + // result: (GTnoov (CMP a (MUL x y)) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -18410,12 +18419,12 @@ func rewriteBlockARM(b *Block) bool { v1 := b.NewValue0(v_0.Pos, OpARMMUL, x.Type) v1.AddArg2(x, y) v0.AddArg2(a, v1) - b.resetWithControl(BlockARMGT, v0) + b.resetWithControl(BlockARMGTnoov, v0) return true } // match: (GT (CMPconst [0] l:(SUBconst [c] x)) yes no) // cond: l.Uses==1 - // result: (GT (CMPconst [c] x) yes no) + // result: (GTnoov (CMPconst [c] x) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -18433,12 +18442,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMCMPconst, types.TypeFlags) v0.AuxInt = c v0.AddArg(x) - b.resetWithControl(BlockARMGT, v0) + b.resetWithControl(BlockARMGTnoov, v0) return true } // match: (GT (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) // cond: l.Uses==1 - // result: (GT (CMPshiftLL x y [c]) yes no) + // result: (GTnoov (CMPshiftLL x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -18457,12 +18466,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftLL, types.TypeFlags) v0.AuxInt = c v0.AddArg2(x, y) - b.resetWithControl(BlockARMGT, v0) + b.resetWithControl(BlockARMGTnoov, v0) return true } // match: (GT (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) // cond: l.Uses==1 - // result: (GT (CMPshiftRL x y [c]) yes no) + // result: (GTnoov (CMPshiftRL x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -18481,12 +18490,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRL, types.TypeFlags) v0.AuxInt = c v0.AddArg2(x, y) - b.resetWithControl(BlockARMGT, v0) + b.resetWithControl(BlockARMGTnoov, v0) return true } // match: (GT (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) // cond: l.Uses==1 - // result: (GT (CMPshiftRA x y [c]) yes no) + // result: (GTnoov (CMPshiftRA x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -18505,12 +18514,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRA, types.TypeFlags) v0.AuxInt = c v0.AddArg2(x, y) - b.resetWithControl(BlockARMGT, v0) + b.resetWithControl(BlockARMGTnoov, v0) return true } // match: (GT (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) // cond: l.Uses==1 - // result: (GT (CMPshiftLLreg x y z) yes no) + // result: (GTnoov (CMPshiftLLreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -18528,12 +18537,12 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftLLreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMGT, v0) + b.resetWithControl(BlockARMGTnoov, v0) return true } // match: (GT (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) // cond: l.Uses==1 - // result: (GT (CMPshiftRLreg x y z) yes no) + // result: (GTnoov (CMPshiftRLreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -18551,12 +18560,12 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRLreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMGT, v0) + b.resetWithControl(BlockARMGTnoov, v0) return true } // match: (GT (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) // cond: l.Uses==1 - // result: (GT (CMPshiftRAreg x y z) yes no) + // result: (GTnoov (CMPshiftRAreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -18574,12 +18583,12 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRAreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMGT, v0) + b.resetWithControl(BlockARMGTnoov, v0) return true } // match: (GT (CMPconst [0] l:(ADD x y)) yes no) // cond: l.Uses==1 - // result: (GT (CMN x y) yes no) + // result: (GTnoov (CMN x y) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -18600,14 +18609,14 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMCMN, types.TypeFlags) v0.AddArg2(x, y) - b.resetWithControl(BlockARMGT, v0) + b.resetWithControl(BlockARMGTnoov, v0) return true } break } // match: (GT (CMPconst [0] l:(ADDconst [c] x)) yes no) // cond: l.Uses==1 - // result: (GT (CMNconst [c] x) yes no) + // result: (GTnoov (CMNconst [c] x) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -18625,12 +18634,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMCMNconst, types.TypeFlags) v0.AuxInt = c v0.AddArg(x) - b.resetWithControl(BlockARMGT, v0) + b.resetWithControl(BlockARMGTnoov, v0) return true } // match: (GT (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) // cond: l.Uses==1 - // result: (GT (CMNshiftLL x y [c]) yes no) + // result: (GTnoov (CMNshiftLL x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -18649,12 +18658,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftLL, types.TypeFlags) v0.AuxInt = c v0.AddArg2(x, y) - b.resetWithControl(BlockARMGT, v0) + b.resetWithControl(BlockARMGTnoov, v0) return true } // match: (GT (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) // cond: l.Uses==1 - // result: (GT (CMNshiftRL x y [c]) yes no) + // result: (GTnoov (CMNshiftRL x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -18673,12 +18682,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRL, types.TypeFlags) v0.AuxInt = c v0.AddArg2(x, y) - b.resetWithControl(BlockARMGT, v0) + b.resetWithControl(BlockARMGTnoov, v0) return true } // match: (GT (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) // cond: l.Uses==1 - // result: (GT (CMNshiftRA x y [c]) yes no) + // result: (GTnoov (CMNshiftRA x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -18697,12 +18706,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRA, types.TypeFlags) v0.AuxInt = c v0.AddArg2(x, y) - b.resetWithControl(BlockARMGT, v0) + b.resetWithControl(BlockARMGTnoov, v0) return true } // match: (GT (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) // cond: l.Uses==1 - // result: (GT (CMNshiftLLreg x y z) yes no) + // result: (GTnoov (CMNshiftLLreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -18720,12 +18729,12 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftLLreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMGT, v0) + b.resetWithControl(BlockARMGTnoov, v0) return true } // match: (GT (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) // cond: l.Uses==1 - // result: (GT (CMNshiftRLreg x y z) yes no) + // result: (GTnoov (CMNshiftRLreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -18743,12 +18752,12 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRLreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMGT, v0) + b.resetWithControl(BlockARMGTnoov, v0) return true } // match: (GT (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) // cond: l.Uses==1 - // result: (GT (CMNshiftRAreg x y z) yes no) + // result: (GTnoov (CMNshiftRAreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -18766,7 +18775,7 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRAreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMGT, v0) + b.resetWithControl(BlockARMGTnoov, v0) return true } // match: (GT (CMPconst [0] l:(AND x y)) yes no) @@ -18799,7 +18808,7 @@ func rewriteBlockARM(b *Block) bool { } // match: (GT (CMPconst [0] l:(MULA x y a)) yes no) // cond: l.Uses==1 - // result: (GT (CMN a (MUL x y)) yes no) + // result: (GTnoov (CMN a (MUL x y)) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -18819,7 +18828,7 @@ func rewriteBlockARM(b *Block) bool { v1 := b.NewValue0(v_0.Pos, OpARMMUL, x.Type) v1.AddArg2(x, y) v0.AddArg2(a, v1) - b.resetWithControl(BlockARMGT, v0) + b.resetWithControl(BlockARMGTnoov, v0) return true } // match: (GT (CMPconst [0] l:(ANDconst [c] x)) yes no) @@ -19178,6 +19187,15 @@ func rewriteBlockARM(b *Block) bool { b.resetWithControl(BlockARMGT, v0) return true } + case BlockARMGTnoov: + // match: (GTnoov (InvertFlags cmp) yes no) + // result: (LTnoov cmp yes no) + for b.Controls[0].Op == OpARMInvertFlags { + v_0 := b.Controls[0] + cmp := v_0.Args[0] + b.resetWithControl(BlockARMLTnoov, cmp) + return true + } case BlockIf: // match: (If (Equal cc) yes no) // result: (EQ cc yes no) @@ -19312,7 +19330,7 @@ func rewriteBlockARM(b *Block) bool { } // match: (LE (CMPconst [0] l:(SUB x y)) yes no) // cond: l.Uses==1 - // result: (LE (CMP x y) yes no) + // result: (LEnoov (CMP x y) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -19329,12 +19347,12 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMCMP, types.TypeFlags) v0.AddArg2(x, y) - b.resetWithControl(BlockARMLE, v0) + b.resetWithControl(BlockARMLEnoov, v0) return true } // match: (LE (CMPconst [0] l:(MULS x y a)) yes no) // cond: l.Uses==1 - // result: (LE (CMP a (MUL x y)) yes no) + // result: (LEnoov (CMP a (MUL x y)) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -19354,12 +19372,12 @@ func rewriteBlockARM(b *Block) bool { v1 := b.NewValue0(v_0.Pos, OpARMMUL, x.Type) v1.AddArg2(x, y) v0.AddArg2(a, v1) - b.resetWithControl(BlockARMLE, v0) + b.resetWithControl(BlockARMLEnoov, v0) return true } // match: (LE (CMPconst [0] l:(SUBconst [c] x)) yes no) // cond: l.Uses==1 - // result: (LE (CMPconst [c] x) yes no) + // result: (LEnoov (CMPconst [c] x) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -19377,12 +19395,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMCMPconst, types.TypeFlags) v0.AuxInt = c v0.AddArg(x) - b.resetWithControl(BlockARMLE, v0) + b.resetWithControl(BlockARMLEnoov, v0) return true } // match: (LE (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) // cond: l.Uses==1 - // result: (LE (CMPshiftLL x y [c]) yes no) + // result: (LEnoov (CMPshiftLL x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -19401,12 +19419,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftLL, types.TypeFlags) v0.AuxInt = c v0.AddArg2(x, y) - b.resetWithControl(BlockARMLE, v0) + b.resetWithControl(BlockARMLEnoov, v0) return true } // match: (LE (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) // cond: l.Uses==1 - // result: (LE (CMPshiftRL x y [c]) yes no) + // result: (LEnoov (CMPshiftRL x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -19425,12 +19443,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRL, types.TypeFlags) v0.AuxInt = c v0.AddArg2(x, y) - b.resetWithControl(BlockARMLE, v0) + b.resetWithControl(BlockARMLEnoov, v0) return true } // match: (LE (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) // cond: l.Uses==1 - // result: (LE (CMPshiftRA x y [c]) yes no) + // result: (LEnoov (CMPshiftRA x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -19449,12 +19467,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRA, types.TypeFlags) v0.AuxInt = c v0.AddArg2(x, y) - b.resetWithControl(BlockARMLE, v0) + b.resetWithControl(BlockARMLEnoov, v0) return true } // match: (LE (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) // cond: l.Uses==1 - // result: (LE (CMPshiftLLreg x y z) yes no) + // result: (LEnoov (CMPshiftLLreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -19472,12 +19490,12 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftLLreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMLE, v0) + b.resetWithControl(BlockARMLEnoov, v0) return true } // match: (LE (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) // cond: l.Uses==1 - // result: (LE (CMPshiftRLreg x y z) yes no) + // result: (LEnoov (CMPshiftRLreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -19495,12 +19513,12 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRLreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMLE, v0) + b.resetWithControl(BlockARMLEnoov, v0) return true } // match: (LE (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) // cond: l.Uses==1 - // result: (LE (CMPshiftRAreg x y z) yes no) + // result: (LEnoov (CMPshiftRAreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -19518,12 +19536,12 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRAreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMLE, v0) + b.resetWithControl(BlockARMLEnoov, v0) return true } // match: (LE (CMPconst [0] l:(ADD x y)) yes no) // cond: l.Uses==1 - // result: (LE (CMN x y) yes no) + // result: (LEnoov (CMN x y) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -19544,14 +19562,14 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMCMN, types.TypeFlags) v0.AddArg2(x, y) - b.resetWithControl(BlockARMLE, v0) + b.resetWithControl(BlockARMLEnoov, v0) return true } break } // match: (LE (CMPconst [0] l:(MULA x y a)) yes no) // cond: l.Uses==1 - // result: (LE (CMN a (MUL x y)) yes no) + // result: (LEnoov (CMN a (MUL x y)) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -19571,12 +19589,12 @@ func rewriteBlockARM(b *Block) bool { v1 := b.NewValue0(v_0.Pos, OpARMMUL, x.Type) v1.AddArg2(x, y) v0.AddArg2(a, v1) - b.resetWithControl(BlockARMLE, v0) + b.resetWithControl(BlockARMLEnoov, v0) return true } // match: (LE (CMPconst [0] l:(ADDconst [c] x)) yes no) // cond: l.Uses==1 - // result: (LE (CMNconst [c] x) yes no) + // result: (LEnoov (CMNconst [c] x) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -19594,12 +19612,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMCMNconst, types.TypeFlags) v0.AuxInt = c v0.AddArg(x) - b.resetWithControl(BlockARMLE, v0) + b.resetWithControl(BlockARMLEnoov, v0) return true } // match: (LE (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) // cond: l.Uses==1 - // result: (LE (CMNshiftLL x y [c]) yes no) + // result: (LEnoov (CMNshiftLL x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -19618,12 +19636,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftLL, types.TypeFlags) v0.AuxInt = c v0.AddArg2(x, y) - b.resetWithControl(BlockARMLE, v0) + b.resetWithControl(BlockARMLEnoov, v0) return true } // match: (LE (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) // cond: l.Uses==1 - // result: (LE (CMNshiftRL x y [c]) yes no) + // result: (LEnoov (CMNshiftRL x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -19642,12 +19660,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRL, types.TypeFlags) v0.AuxInt = c v0.AddArg2(x, y) - b.resetWithControl(BlockARMLE, v0) + b.resetWithControl(BlockARMLEnoov, v0) return true } // match: (LE (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) // cond: l.Uses==1 - // result: (LE (CMNshiftRA x y [c]) yes no) + // result: (LEnoov (CMNshiftRA x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -19666,12 +19684,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRA, types.TypeFlags) v0.AuxInt = c v0.AddArg2(x, y) - b.resetWithControl(BlockARMLE, v0) + b.resetWithControl(BlockARMLEnoov, v0) return true } // match: (LE (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) // cond: l.Uses==1 - // result: (LE (CMNshiftLLreg x y z) yes no) + // result: (LEnoov (CMNshiftLLreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -19689,12 +19707,12 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftLLreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMLE, v0) + b.resetWithControl(BlockARMLEnoov, v0) return true } // match: (LE (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) // cond: l.Uses==1 - // result: (LE (CMNshiftRLreg x y z) yes no) + // result: (LEnoov (CMNshiftRLreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -19712,12 +19730,12 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRLreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMLE, v0) + b.resetWithControl(BlockARMLEnoov, v0) return true } // match: (LE (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) // cond: l.Uses==1 - // result: (LE (CMNshiftRAreg x y z) yes no) + // result: (LEnoov (CMNshiftRAreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -19735,7 +19753,7 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRAreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMLE, v0) + b.resetWithControl(BlockARMLEnoov, v0) return true } // match: (LE (CMPconst [0] l:(AND x y)) yes no) @@ -20122,6 +20140,15 @@ func rewriteBlockARM(b *Block) bool { b.resetWithControl(BlockARMLE, v0) return true } + case BlockARMLEnoov: + // match: (LEnoov (InvertFlags cmp) yes no) + // result: (GEnoov cmp yes no) + for b.Controls[0].Op == OpARMInvertFlags { + v_0 := b.Controls[0] + cmp := v_0.Args[0] + b.resetWithControl(BlockARMGEnoov, cmp) + return true + } case BlockARMLT: // match: (LT (FlagEQ) yes no) // result: (First no yes) @@ -20166,7 +20193,7 @@ func rewriteBlockARM(b *Block) bool { } // match: (LT (CMPconst [0] l:(SUB x y)) yes no) // cond: l.Uses==1 - // result: (LT (CMP x y) yes no) + // result: (LTnoov (CMP x y) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -20183,12 +20210,12 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMCMP, types.TypeFlags) v0.AddArg2(x, y) - b.resetWithControl(BlockARMLT, v0) + b.resetWithControl(BlockARMLTnoov, v0) return true } // match: (LT (CMPconst [0] l:(MULS x y a)) yes no) // cond: l.Uses==1 - // result: (LT (CMP a (MUL x y)) yes no) + // result: (LTnoov (CMP a (MUL x y)) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -20208,12 +20235,12 @@ func rewriteBlockARM(b *Block) bool { v1 := b.NewValue0(v_0.Pos, OpARMMUL, x.Type) v1.AddArg2(x, y) v0.AddArg2(a, v1) - b.resetWithControl(BlockARMLT, v0) + b.resetWithControl(BlockARMLTnoov, v0) return true } // match: (LT (CMPconst [0] l:(SUBconst [c] x)) yes no) // cond: l.Uses==1 - // result: (LT (CMPconst [c] x) yes no) + // result: (LTnoov (CMPconst [c] x) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -20231,12 +20258,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMCMPconst, types.TypeFlags) v0.AuxInt = c v0.AddArg(x) - b.resetWithControl(BlockARMLT, v0) + b.resetWithControl(BlockARMLTnoov, v0) return true } // match: (LT (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) // cond: l.Uses==1 - // result: (LT (CMPshiftLL x y [c]) yes no) + // result: (LTnoov (CMPshiftLL x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -20255,12 +20282,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftLL, types.TypeFlags) v0.AuxInt = c v0.AddArg2(x, y) - b.resetWithControl(BlockARMLT, v0) + b.resetWithControl(BlockARMLTnoov, v0) return true } // match: (LT (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) // cond: l.Uses==1 - // result: (LT (CMPshiftRL x y [c]) yes no) + // result: (LTnoov (CMPshiftRL x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -20279,12 +20306,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRL, types.TypeFlags) v0.AuxInt = c v0.AddArg2(x, y) - b.resetWithControl(BlockARMLT, v0) + b.resetWithControl(BlockARMLTnoov, v0) return true } // match: (LT (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) // cond: l.Uses==1 - // result: (LT (CMPshiftRA x y [c]) yes no) + // result: (LTnoov (CMPshiftRA x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -20303,12 +20330,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRA, types.TypeFlags) v0.AuxInt = c v0.AddArg2(x, y) - b.resetWithControl(BlockARMLT, v0) + b.resetWithControl(BlockARMLTnoov, v0) return true } // match: (LT (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) // cond: l.Uses==1 - // result: (LT (CMPshiftLLreg x y z) yes no) + // result: (LTnoov (CMPshiftLLreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -20326,12 +20353,12 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftLLreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMLT, v0) + b.resetWithControl(BlockARMLTnoov, v0) return true } // match: (LT (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) // cond: l.Uses==1 - // result: (LT (CMPshiftRLreg x y z) yes no) + // result: (LTnoov (CMPshiftRLreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -20349,12 +20376,12 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRLreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMLT, v0) + b.resetWithControl(BlockARMLTnoov, v0) return true } // match: (LT (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) // cond: l.Uses==1 - // result: (LT (CMPshiftRAreg x y z) yes no) + // result: (LTnoov (CMPshiftRAreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -20372,12 +20399,12 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRAreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMLT, v0) + b.resetWithControl(BlockARMLTnoov, v0) return true } // match: (LT (CMPconst [0] l:(ADD x y)) yes no) // cond: l.Uses==1 - // result: (LT (CMN x y) yes no) + // result: (LTnoov (CMN x y) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -20398,14 +20425,14 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMCMN, types.TypeFlags) v0.AddArg2(x, y) - b.resetWithControl(BlockARMLT, v0) + b.resetWithControl(BlockARMLTnoov, v0) return true } break } // match: (LT (CMPconst [0] l:(MULA x y a)) yes no) // cond: l.Uses==1 - // result: (LT (CMN a (MUL x y)) yes no) + // result: (LTnoov (CMN a (MUL x y)) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -20425,12 +20452,12 @@ func rewriteBlockARM(b *Block) bool { v1 := b.NewValue0(v_0.Pos, OpARMMUL, x.Type) v1.AddArg2(x, y) v0.AddArg2(a, v1) - b.resetWithControl(BlockARMLT, v0) + b.resetWithControl(BlockARMLTnoov, v0) return true } // match: (LT (CMPconst [0] l:(ADDconst [c] x)) yes no) // cond: l.Uses==1 - // result: (LT (CMNconst [c] x) yes no) + // result: (LTnoov (CMNconst [c] x) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -20448,12 +20475,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMCMNconst, types.TypeFlags) v0.AuxInt = c v0.AddArg(x) - b.resetWithControl(BlockARMLT, v0) + b.resetWithControl(BlockARMLTnoov, v0) return true } // match: (LT (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) // cond: l.Uses==1 - // result: (LT (CMNshiftLL x y [c]) yes no) + // result: (LTnoov (CMNshiftLL x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -20472,12 +20499,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftLL, types.TypeFlags) v0.AuxInt = c v0.AddArg2(x, y) - b.resetWithControl(BlockARMLT, v0) + b.resetWithControl(BlockARMLTnoov, v0) return true } // match: (LT (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) // cond: l.Uses==1 - // result: (LT (CMNshiftRL x y [c]) yes no) + // result: (LTnoov (CMNshiftRL x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -20496,12 +20523,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRL, types.TypeFlags) v0.AuxInt = c v0.AddArg2(x, y) - b.resetWithControl(BlockARMLT, v0) + b.resetWithControl(BlockARMLTnoov, v0) return true } // match: (LT (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) // cond: l.Uses==1 - // result: (LT (CMNshiftRA x y [c]) yes no) + // result: (LTnoov (CMNshiftRA x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -20520,12 +20547,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRA, types.TypeFlags) v0.AuxInt = c v0.AddArg2(x, y) - b.resetWithControl(BlockARMLT, v0) + b.resetWithControl(BlockARMLTnoov, v0) return true } // match: (LT (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) // cond: l.Uses==1 - // result: (LT (CMNshiftLLreg x y z) yes no) + // result: (LTnoov (CMNshiftLLreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -20543,12 +20570,12 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftLLreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMLT, v0) + b.resetWithControl(BlockARMLTnoov, v0) return true } // match: (LT (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) // cond: l.Uses==1 - // result: (LT (CMNshiftRLreg x y z) yes no) + // result: (LTnoov (CMNshiftRLreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -20566,12 +20593,12 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRLreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMLT, v0) + b.resetWithControl(BlockARMLTnoov, v0) return true } // match: (LT (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) // cond: l.Uses==1 - // result: (LT (CMNshiftRAreg x y z) yes no) + // result: (LTnoov (CMNshiftRAreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if v_0.AuxInt != 0 { @@ -20589,7 +20616,7 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRAreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMLT, v0) + b.resetWithControl(BlockARMLTnoov, v0) return true } // match: (LT (CMPconst [0] l:(AND x y)) yes no) @@ -20976,6 +21003,15 @@ func rewriteBlockARM(b *Block) bool { b.resetWithControl(BlockARMLT, v0) return true } + case BlockARMLTnoov: + // match: (LTnoov (InvertFlags cmp) yes no) + // result: (GTnoov cmp yes no) + for b.Controls[0].Op == OpARMInvertFlags { + v_0 := b.Controls[0] + cmp := v_0.Args[0] + b.resetWithControl(BlockARMGTnoov, cmp) + return true + } case BlockARMNE: // match: (NE (CMPconst [0] (Equal cc)) yes no) // result: (EQ cc yes no) diff --git a/src/cmd/compile/internal/ssa/rewriteCond_test.go b/src/cmd/compile/internal/ssa/rewriteCond_test.go index 6536d3a7d7..2c26fdf142 100644 --- a/src/cmd/compile/internal/ssa/rewriteCond_test.go +++ b/src/cmd/compile/internal/ssa/rewriteCond_test.go @@ -7,24 +7,26 @@ package ssa import ( "math" "math/rand" - "runtime" "testing" ) var ( - x64 int64 = math.MaxInt64 - 2 - x64b int64 = math.MaxInt64 - 2 - x64c int64 = math.MaxInt64 - 2 - y64 int64 = math.MinInt64 + 1 - x32 int32 = math.MaxInt32 - 2 - x32b int32 = math.MaxInt32 - 2 - y32 int32 = math.MinInt32 + 1 - one64 int64 = 1 - one32 int32 = 1 - v64 int64 = 11 // ensure it's not 2**n +/- 1 - v64_n int64 = -11 - v32 int32 = 11 - v32_n int32 = -11 + x64 int64 = math.MaxInt64 - 2 + x64b int64 = math.MaxInt64 - 2 + x64c int64 = math.MaxInt64 - 2 + y64 int64 = math.MinInt64 + 1 + x32 int32 = math.MaxInt32 - 2 + x32b int32 = math.MaxInt32 - 2 + x32c int32 = math.MaxInt32 - 2 + y32 int32 = math.MinInt32 + 1 + one64 int64 = 1 + one32 int32 = 1 + v64 int64 = 11 // ensure it's not 2**n +/- 1 + v64_n int64 = -11 + v32 int32 = 11 + v32_n int32 = -11 + uv32 uint32 = 19 + uz uint8 = 1 // for lowering to SLL/SRL/SRA ) var crTests = []struct { @@ -39,6 +41,8 @@ var crTests = []struct { {"MAddVar32", testMAddVar32}, {"MSubVar64", testMSubVar64}, {"MSubVar32", testMSubVar32}, + {"AddShift32", testAddShift32}, + {"SubShift32", testSubShift32}, } var crBenches = []struct { @@ -58,9 +62,6 @@ var crBenches = []struct { // and machine code sequences are covered. // It's for arm64 initially, please see https://github.com/golang/go/issues/38740 func TestCondRewrite(t *testing.T) { - if runtime.GOARCH == "arm" { - t.Skip("fix on arm expected!") - } for _, test := range crTests { t.Run(test.name, test.tf) } @@ -408,6 +409,66 @@ func testMSubVar32(t *testing.T) { } } +// 32-bit ADDshift, pick up 1~2 scenarios randomly for each condition +func testAddShift32(t *testing.T) { + if x32+v32<<1 < 0 { + } else { + t.Errorf("'%#x + %#x<<%#x < 0' failed", x32, v32, 1) + } + + if x32+v32>>1 <= 0 { + } else { + t.Errorf("'%#x + %#x>>%#x <= 0' failed", x32, v32, 1) + } + + if x32+int32(uv32>>1) > 0 { + t.Errorf("'%#x + int32(%#x>>%#x) > 0' failed", x32, uv32, 1) + } + + if x32+v32<= 0 { + t.Errorf("'%#x + %#x<<%#x >= 0' failed", x32, v32, uz) + } + + if x32+v32>>uz > 0 { + t.Errorf("'%#x + %#x>>%#x > 0' failed", x32, v32, uz) + } + + if x32+int32(uv32>>uz) < 0 { + } else { + t.Errorf("'%#x + int32(%#x>>%#x) < 0' failed", x32, uv32, uz) + } +} + +// 32-bit SUBshift, pick up 1~2 scenarios randomly for each condition +func testSubShift32(t *testing.T) { + if y32-v32<<1 > 0 { + } else { + t.Errorf("'%#x - %#x<<%#x > 0' failed", y32, v32, 1) + } + + if y32-v32>>1 < 0 { + t.Errorf("'%#x - %#x>>%#x < 0' failed", y32, v32, 1) + } + + if y32-int32(uv32>>1) >= 0 { + } else { + t.Errorf("'%#x - int32(%#x>>%#x) >= 0' failed", y32, uv32, 1) + } + + if y32-v32<>uz >= 0 { + } else { + t.Errorf("'%#x - %#x>>%#x >= 0' failed", y32, v32, uz) + } + + if y32-int32(uv32>>uz) <= 0 { + t.Errorf("'%#x - int32(%#x>>%#x) <= 0' failed", y32, uv32, uz) + } +} + var rnd = rand.New(rand.NewSource(0)) var sink int64 diff --git a/test/codegen/comparisons.go b/test/codegen/comparisons.go index eb2f3317c9..90808573c2 100644 --- a/test/codegen/comparisons.go +++ b/test/codegen/comparisons.go @@ -253,6 +253,8 @@ func CmpLogicalToZero(a, b, c uint32, d, e uint64) uint64 { // 'comparing to zero' expressions // var + const +// 'x-const' might be canonicalized to 'x+(-const)', so we check both +// CMN and CMP for subtraction expressions to make the pattern robust. func CmpToZero_ex1(a int64, e int32) int { // arm64:`CMN`,-`ADD`,`(BMI|BPL)` if a+3 < 0 { @@ -269,37 +271,41 @@ func CmpToZero_ex1(a int64, e int32) int { return 2 } - // arm64:`CMP`,-`SUB`,`(BMI|BPL)` + // arm64:`CMP|CMN`,-`(ADD|SUB)`,`(BMI|BPL)` if a-7 < 0 { return 3 } - // arm64:`CMP`,-`SUB`,`(BMI|BPL)` + // arm64:`CMP|CMN`,-`(ADD|SUB)`,`(BMI|BPL)` if a-11 >= 0 { return 4 } - // arm64:`CMP`,-`SUB`,`BEQ`,`(BMI|BPL)` + // arm64:`CMP|CMN`,-`(ADD|SUB)`,`BEQ`,`(BMI|BPL)` if a-19 > 0 { return 4 } // arm64:`CMNW`,-`ADDW`,`(BMI|BPL)` + // arm:`CMN`,-`ADD`,`(BMI|BPL)` if e+3 < 0 { return 5 } // arm64:`CMNW`,-`ADDW`,`(BMI|BPL)` + // arm:`CMN`,-`ADD`,`(BMI|BPL)` if e+13 >= 0 { return 6 } - // arm64:`CMPW`,-`SUBW`,`(BMI|BPL)` + // arm64:`CMPW|CMNW`,`(BMI|BPL)` + // arm:`CMP|CMN`, -`(ADD|SUB)`, `(BMI|BPL)` if e-7 < 0 { return 7 } - // arm64:`CMPW`,-`SUBW`,`(BMI|BPL)` + // arm64:`CMPW|CMNW`,`(BMI|BPL)` + // arm:`CMP|CMN`, -`(ADD|SUB)`, `(BMI|BPL)` if e-11 >= 0 { return 8 } @@ -326,11 +332,13 @@ func CmpToZero_ex2(a, b, c int64, e, f, g int32) int { } // arm64:`CMNW`,-`ADDW`,`(BMI|BPL)` + // arm:`CMN`,-`ADD`,`(BMI|BPL)` if e+f < 0 { return 5 } // arm64:`CMNW`,-`ADDW`,`(BMI|BPL)` + // arm:`CMN`,-`ADD`,`(BMI|BPL)` if f+g >= 0 { return 6 } @@ -350,11 +358,13 @@ func CmpToZero_ex3(a, b, c, d int64, e, f, g, h int32) int { } // arm64:`CMNW`,-`MADDW`,`MULW`,`BEQ`,`(BMI|BPL)` + // arm:`CMN`,-`MULA`,`MUL`,`BEQ`,`(BMI|BPL)` if e+f*g > 0 { return 5 } // arm64:`CMNW`,-`MADDW`,`MULW`,`BEQ`,`(BMI|BPL)` + // arm:`CMN`,-`MULA`,`MUL`,`BEQ`,`(BMI|BPL)` if f+g*h <= 0 { return 6 } @@ -384,3 +394,16 @@ func CmpToZero_ex4(a, b, c, d int64, e, f, g, h int32) int { } return 0 } + +func CmpToZero_ex5(e, f int32, u uint32) int { + // arm:`CMN`,-`ADD`,`BEQ`,`(BMI|BPL)` + if e+f<<1 > 0 { + return 1 + } + + // arm:`CMP`,-`SUB`,`(BMI|BPL)` + if f-int32(u>>2) >= 0 { + return 2 + } + return 0 +} From e5e386938f4ace00c00de86ead47ed5c02961e5b Mon Sep 17 00:00:00 2001 From: eric fang Date: Mon, 8 Jun 2020 03:19:43 +0000 Subject: [PATCH 21/34] cmd/asm: fix the encoding error of VCNT instruction for arm64 When the arrangement specifier is "B16", the 30-bit should be 1 rather than 0. This CL fixes this error. Fixes #39445 Change-Id: Ib44881cdb8b3aab855cb30f2c52a085cd73a6a2c Reviewed-on: https://go-review.googlesource.com/c/go/+/236638 Run-TryBot: eric fang TryBot-Result: Gobot Gobot Reviewed-by: Cherry Zhang --- src/cmd/asm/internal/asm/testdata/arm64enc.s | 1 + src/cmd/internal/obj/arm64/asm7.go | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/cmd/asm/internal/asm/testdata/arm64enc.s b/src/cmd/asm/internal/asm/testdata/arm64enc.s index a483c731b8..56cf51c303 100644 --- a/src/cmd/asm/internal/asm/testdata/arm64enc.s +++ b/src/cmd/asm/internal/asm/testdata/arm64enc.s @@ -420,6 +420,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8 UXTBW R2, R6 // 461c0053 UXTHW R7, R20 // f43c0053 VCNT V0.B8, V0.B8 // 0058200e + VCNT V0.B16, V0.B16 // 0058204e WFE // 5f2003d5 WFI // 7f2003d5 YIELD // 3f2003d5 diff --git a/src/cmd/internal/obj/arm64/asm7.go b/src/cmd/internal/obj/arm64/asm7.go index 7f5cba645a..df17729a76 100644 --- a/src/cmd/internal/obj/arm64/asm7.go +++ b/src/cmd/internal/obj/arm64/asm7.go @@ -460,7 +460,6 @@ var optab = []Optab{ {AFCVTZSD, C_FREG, C_NONE, C_NONE, C_REG, 29, 4, 0, 0, 0}, {ASCVTFD, C_REG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0}, {AFCVTSD, C_FREG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0}, - {AVCNT, C_ARNG, C_NONE, C_NONE, C_ARNG, 29, 4, 0, 0, 0}, {AVMOV, C_ELEM, C_NONE, C_NONE, C_REG, 73, 4, 0, 0, 0}, {AVMOV, C_ELEM, C_NONE, C_NONE, C_ELEM, 92, 4, 0, 0, 0}, {AVMOV, C_ELEM, C_NONE, C_NONE, C_VREG, 80, 4, 0, 0, 0}, @@ -2773,6 +2772,7 @@ func buildop(ctxt *obj.Link) { oprangeset(AVSRI, t) case AVREV32: + oprangeset(AVCNT, t) oprangeset(AVRBIT, t) oprangeset(AVREV64, t) oprangeset(AVREV16, t) @@ -4523,7 +4523,7 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) { c.ctxt.Diag("invalid arrangement: %v\n", p) } - if (p.As == AVMOV || p.As == AVRBIT) && (af != ARNG_16B && af != ARNG_8B) { + if (p.As == AVMOV || p.As == AVRBIT || p.As == AVCNT) && (af != ARNG_16B && af != ARNG_8B) { c.ctxt.Diag("invalid arrangement: %v", p) } From cd8f8026bb3bf78889e406e3253aad047e49b2e4 Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Mon, 8 Jun 2020 21:19:01 -0400 Subject: [PATCH 22/34] doc/go1.15: add remaining release notes for net/http and net/http/httputil Updates #37419 Change-Id: I3e37b650475aad4430aacd4655c02e5081ca6f5e Reviewed-on: https://go-review.googlesource.com/c/go/+/237019 Reviewed-by: Dmitri Shuralyov --- doc/go1.15.html | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/doc/go1.15.html b/doc/go1.15.html index fc8ee2d31f..50f4fea5bc 100644 --- a/doc/go1.15.html +++ b/doc/go1.15.html @@ -639,8 +639,10 @@ Do not send CLs removing the interior tags from such phrases.

net/http
-

- TODO: https://golang.org/cl/231418: only support "chunked" in inbound Transfer-Encoding headers +

+ Parsing is now stricter as a hardening measure against request smuggling attacks: + non-ASCII white space is no longer trimmed like SP and HTAB, and support for the + "identity" Transfer-Encoding was dropped.

@@ -655,7 +657,9 @@ Do not send CLs removing the interior tags from such phrases.

- TODO: https://golang.org/cl/224897: make Switching Protocol requests (e.g. Websockets) cancelable + When a Switching Protocol (like WebSocket) request handled by + ReverseProxy + is canceled, the backend connection is now correctly closed.

From 281f0ed7bf671e6bb65ade4aa3146bc572d64560 Mon Sep 17 00:00:00 2001 From: Vee Zhang Date: Tue, 9 Jun 2020 08:03:13 +0000 Subject: [PATCH 23/34] internal/poll: correct function name in comment Change-Id: I3b28a45e942a6d6032855758fcc41e4edd64aa32 GitHub-Last-Rev: 9c994bbee7420861b5dc83e71e50fc43d7f6650b GitHub-Pull-Request: golang/go#39467 Reviewed-on: https://go-review.googlesource.com/c/go/+/237059 Reviewed-by: Ian Lance Taylor --- src/internal/poll/fd_unix.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/internal/poll/fd_unix.go b/src/internal/poll/fd_unix.go index 85c79bbebb..4872fa9851 100644 --- a/src/internal/poll/fd_unix.go +++ b/src/internal/poll/fd_unix.go @@ -479,7 +479,7 @@ func DupCloseOnExec(fd int) (int, string, error) { return dupCloseOnExecOld(fd) } -// dupCloseOnExecUnixOld is the traditional way to dup an fd and +// dupCloseOnExecOld is the traditional way to dup an fd and // set its O_CLOEXEC bit, using two system calls. func dupCloseOnExecOld(fd int) (int, string, error) { syscall.ForkLock.RLock() From 619072be4138e3fc092a9b77d57a9abc5333a4ab Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Tue, 9 Jun 2020 09:11:11 -0700 Subject: [PATCH 24/34] runtime: fix typo in comment (object -> objects) Change-Id: I2af1f9dcd1a9609681e58ab07e73e6d7a5f8a12b Reviewed-on: https://go-review.googlesource.com/c/go/+/237160 Reviewed-by: Ian Lance Taylor --- src/runtime/mstats.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/mstats.go b/src/runtime/mstats.go index ba508729c5..6a8a34d1ed 100644 --- a/src/runtime/mstats.go +++ b/src/runtime/mstats.go @@ -529,7 +529,7 @@ func updatememstats() { // Calculate memory allocator stats. // During program execution we only count number of frees and amount of freed memory. - // Current number of alive object in the heap and amount of alive heap memory + // Current number of alive objects in the heap and amount of alive heap memory // are calculated by scanning all spans. // Total number of mallocs is calculated as number of frees plus number of alive objects. // Similarly, total amount of allocated memory is calculated as amount of freed memory From c4f77b11df3ab8c3a717ef7f57f957c491d57c8e Mon Sep 17 00:00:00 2001 From: Alexander Rakoczy Date: Tue, 9 Jun 2020 16:17:46 -0400 Subject: [PATCH 25/34] api: promote next to go1.15 Change-Id: I42e0d096b28614b95b0af21144f8f118e3eafcd5 Reviewed-on: https://go-review.googlesource.com/c/go/+/237297 Run-TryBot: Alexander Rakoczy TryBot-Result: Gobot Gobot Reviewed-by: Brad Fitzpatrick Reviewed-by: Dmitri Shuralyov Reviewed-by: Carlos Amedee --- api/go1.15.txt | 133 +++++++++++++++++++++++++++++++++++++++++++++++++ api/next.txt | 3 -- 2 files changed, 133 insertions(+), 3 deletions(-) create mode 100644 api/go1.15.txt diff --git a/api/go1.15.txt b/api/go1.15.txt new file mode 100644 index 0000000000..f16faa0780 --- /dev/null +++ b/api/go1.15.txt @@ -0,0 +1,133 @@ +pkg bufio, var ErrBadReadCount error +pkg crypto, method (Hash) String() string +pkg crypto/ecdsa, func SignASN1(io.Reader, *PrivateKey, []uint8) ([]uint8, error) +pkg crypto/ecdsa, func VerifyASN1(*PublicKey, []uint8, []uint8) bool +pkg crypto/ecdsa, method (*PrivateKey) Equal(crypto.PrivateKey) bool +pkg crypto/ecdsa, method (*PublicKey) Equal(crypto.PublicKey) bool +pkg crypto/ed25519, method (PrivateKey) Equal(crypto.PrivateKey) bool +pkg crypto/ed25519, method (PublicKey) Equal(crypto.PublicKey) bool +pkg crypto/elliptic, func MarshalCompressed(Curve, *big.Int, *big.Int) []uint8 +pkg crypto/elliptic, func UnmarshalCompressed(Curve, []uint8) (*big.Int, *big.Int) +pkg crypto/rsa, method (*PrivateKey) Equal(crypto.PrivateKey) bool +pkg crypto/rsa, method (*PublicKey) Equal(crypto.PublicKey) bool +pkg crypto/tls, method (*Dialer) Dial(string, string) (net.Conn, error) +pkg crypto/tls, method (*Dialer) DialContext(context.Context, string, string) (net.Conn, error) +pkg crypto/tls, method (ClientAuthType) String() string +pkg crypto/tls, method (CurveID) String() string +pkg crypto/tls, method (SignatureScheme) String() string +pkg crypto/tls, type Config struct, VerifyConnection func(ConnectionState) error +pkg crypto/tls, type Dialer struct +pkg crypto/tls, type Dialer struct, Config *Config +pkg crypto/tls, type Dialer struct, NetDialer *net.Dialer +pkg crypto/x509, func CreateRevocationList(io.Reader, *RevocationList, *Certificate, crypto.Signer) ([]uint8, error) +pkg crypto/x509, type RevocationList struct +pkg crypto/x509, type RevocationList struct, ExtraExtensions []pkix.Extension +pkg crypto/x509, type RevocationList struct, NextUpdate time.Time +pkg crypto/x509, type RevocationList struct, Number *big.Int +pkg crypto/x509, type RevocationList struct, RevokedCertificates []pkix.RevokedCertificate +pkg crypto/x509, type RevocationList struct, SignatureAlgorithm SignatureAlgorithm +pkg crypto/x509, type RevocationList struct, ThisUpdate time.Time +pkg database/sql, method (*DB) SetConnMaxIdleTime(time.Duration) +pkg database/sql, method (*Row) Err() error +pkg database/sql, type DBStats struct, MaxIdleTimeClosed int64 +pkg database/sql/driver, type Validator interface { IsValid } +pkg database/sql/driver, type Validator interface, IsValid() bool +pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_APPCONTAINER = 4096 +pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_APPCONTAINER ideal-int +pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE = 64 +pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE ideal-int +pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY = 128 +pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY ideal-int +pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_GUARD_CF = 16384 +pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_GUARD_CF ideal-int +pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA = 32 +pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA ideal-int +pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_NO_BIND = 2048 +pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_NO_BIND ideal-int +pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_NO_ISOLATION = 512 +pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_NO_ISOLATION ideal-int +pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_NO_SEH = 1024 +pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_NO_SEH ideal-int +pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_NX_COMPAT = 256 +pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_NX_COMPAT ideal-int +pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE = 32768 +pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE ideal-int +pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_WDM_DRIVER = 8192 +pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_WDM_DRIVER ideal-int +pkg debug/pe, const IMAGE_FILE_32BIT_MACHINE = 256 +pkg debug/pe, const IMAGE_FILE_32BIT_MACHINE ideal-int +pkg debug/pe, const IMAGE_FILE_AGGRESIVE_WS_TRIM = 16 +pkg debug/pe, const IMAGE_FILE_AGGRESIVE_WS_TRIM ideal-int +pkg debug/pe, const IMAGE_FILE_BYTES_REVERSED_HI = 32768 +pkg debug/pe, const IMAGE_FILE_BYTES_REVERSED_HI ideal-int +pkg debug/pe, const IMAGE_FILE_BYTES_REVERSED_LO = 128 +pkg debug/pe, const IMAGE_FILE_BYTES_REVERSED_LO ideal-int +pkg debug/pe, const IMAGE_FILE_DEBUG_STRIPPED = 512 +pkg debug/pe, const IMAGE_FILE_DEBUG_STRIPPED ideal-int +pkg debug/pe, const IMAGE_FILE_DLL = 8192 +pkg debug/pe, const IMAGE_FILE_DLL ideal-int +pkg debug/pe, const IMAGE_FILE_EXECUTABLE_IMAGE = 2 +pkg debug/pe, const IMAGE_FILE_EXECUTABLE_IMAGE ideal-int +pkg debug/pe, const IMAGE_FILE_LARGE_ADDRESS_AWARE = 32 +pkg debug/pe, const IMAGE_FILE_LARGE_ADDRESS_AWARE ideal-int +pkg debug/pe, const IMAGE_FILE_LINE_NUMS_STRIPPED = 4 +pkg debug/pe, const IMAGE_FILE_LINE_NUMS_STRIPPED ideal-int +pkg debug/pe, const IMAGE_FILE_LOCAL_SYMS_STRIPPED = 8 +pkg debug/pe, const IMAGE_FILE_LOCAL_SYMS_STRIPPED ideal-int +pkg debug/pe, const IMAGE_FILE_NET_RUN_FROM_SWAP = 2048 +pkg debug/pe, const IMAGE_FILE_NET_RUN_FROM_SWAP ideal-int +pkg debug/pe, const IMAGE_FILE_RELOCS_STRIPPED = 1 +pkg debug/pe, const IMAGE_FILE_RELOCS_STRIPPED ideal-int +pkg debug/pe, const IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP = 1024 +pkg debug/pe, const IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP ideal-int +pkg debug/pe, const IMAGE_FILE_SYSTEM = 4096 +pkg debug/pe, const IMAGE_FILE_SYSTEM ideal-int +pkg debug/pe, const IMAGE_FILE_UP_SYSTEM_ONLY = 16384 +pkg debug/pe, const IMAGE_FILE_UP_SYSTEM_ONLY ideal-int +pkg debug/pe, const IMAGE_SUBSYSTEM_EFI_APPLICATION = 10 +pkg debug/pe, const IMAGE_SUBSYSTEM_EFI_APPLICATION ideal-int +pkg debug/pe, const IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER = 11 +pkg debug/pe, const IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER ideal-int +pkg debug/pe, const IMAGE_SUBSYSTEM_EFI_ROM = 13 +pkg debug/pe, const IMAGE_SUBSYSTEM_EFI_ROM ideal-int +pkg debug/pe, const IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER = 12 +pkg debug/pe, const IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER ideal-int +pkg debug/pe, const IMAGE_SUBSYSTEM_NATIVE = 1 +pkg debug/pe, const IMAGE_SUBSYSTEM_NATIVE ideal-int +pkg debug/pe, const IMAGE_SUBSYSTEM_NATIVE_WINDOWS = 8 +pkg debug/pe, const IMAGE_SUBSYSTEM_NATIVE_WINDOWS ideal-int +pkg debug/pe, const IMAGE_SUBSYSTEM_OS2_CUI = 5 +pkg debug/pe, const IMAGE_SUBSYSTEM_OS2_CUI ideal-int +pkg debug/pe, const IMAGE_SUBSYSTEM_POSIX_CUI = 7 +pkg debug/pe, const IMAGE_SUBSYSTEM_POSIX_CUI ideal-int +pkg debug/pe, const IMAGE_SUBSYSTEM_UNKNOWN = 0 +pkg debug/pe, const IMAGE_SUBSYSTEM_UNKNOWN ideal-int +pkg debug/pe, const IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION = 16 +pkg debug/pe, const IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION ideal-int +pkg debug/pe, const IMAGE_SUBSYSTEM_WINDOWS_CE_GUI = 9 +pkg debug/pe, const IMAGE_SUBSYSTEM_WINDOWS_CE_GUI ideal-int +pkg debug/pe, const IMAGE_SUBSYSTEM_WINDOWS_CUI = 3 +pkg debug/pe, const IMAGE_SUBSYSTEM_WINDOWS_CUI ideal-int +pkg debug/pe, const IMAGE_SUBSYSTEM_WINDOWS_GUI = 2 +pkg debug/pe, const IMAGE_SUBSYSTEM_WINDOWS_GUI ideal-int +pkg debug/pe, const IMAGE_SUBSYSTEM_XBOX = 14 +pkg debug/pe, const IMAGE_SUBSYSTEM_XBOX ideal-int +pkg go/printer, const StdFormat = 16 +pkg go/printer, const StdFormat Mode +pkg go/types, type Config struct, UsesCgo bool +pkg math/big, method (*Int) FillBytes([]uint8) []uint8 +pkg net, method (*Resolver) LookupIP(context.Context, string, string) ([]IP, error) +pkg net/url, method (*URL) EscapedFragment() string +pkg net/url, method (*URL) Redacted() string +pkg net/url, type URL struct, RawFragment string +pkg os, method (*File) ReadFrom(io.Reader) (int64, error) +pkg os, var ErrDeadlineExceeded error +pkg regexp, method (*Regexp) SubexpIndex(string) int +pkg strconv, func FormatComplex(complex128, uint8, int, int) string +pkg strconv, func ParseComplex(string, int) (complex128, error) +pkg sync, method (*Map) LoadAndDelete(interface{}) (interface{}, bool) +pkg testing, method (*B) TempDir() string +pkg testing, method (*T) Deadline() (time.Time, bool) +pkg testing, method (*T) TempDir() string +pkg testing, type TB interface, TempDir() string +pkg time, method (*Ticker) Reset(Duration) diff --git a/api/next.txt b/api/next.txt index 442c29a416..e69de29bb2 100644 --- a/api/next.txt +++ b/api/next.txt @@ -1,3 +0,0 @@ -pkg testing, method (*T) Deadline() (time.Time, bool) -pkg time, method (*Ticker) Reset(Duration) -pkg sync, method (*Map) LoadAndDelete(interface{}) (interface{}, bool) From 7b872b6d955d3e749ea62dbfced68ab5c61eae91 Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Fri, 15 May 2020 12:49:04 -0700 Subject: [PATCH 26/34] crypto/tls: restore OCSP and SCTs during session resumption Restore previously sent SCTs and stapled OCSP response during session resumption for both TLS 1.2 and 1.3. This behavior is somewhat complicated for TLS 1.2 as SCTs are sent during the server hello, so they override what is saved in ClientSessionState. It is likely that if the server is sending a different set of SCTs there is probably a reason for doing so, such as a log being retired, or SCT validation requirements changing, so it makes sense to defer to the server in that case. Fixes #39075 Change-Id: I3c0fa2f69c6bf0247a447c48a1b4c733a882a233 Reviewed-on: https://go-review.googlesource.com/c/go/+/234237 Reviewed-by: Filippo Valsorda --- doc/go1.15.html | 6 ++ src/crypto/tls/common.go | 2 + src/crypto/tls/handshake_client.go | 11 +++- src/crypto/tls/handshake_client_test.go | 81 ++++++++++++++++++++++++ src/crypto/tls/handshake_client_tls13.go | 4 ++ 5 files changed, 103 insertions(+), 1 deletion(-) diff --git a/doc/go1.15.html b/doc/go1.15.html index 50f4fea5bc..ffe9d26dc7 100644 --- a/doc/go1.15.html +++ b/doc/go1.15.html @@ -478,6 +478,12 @@ Do not send CLs removing the interior tags from such phrases. ClientAuthType now implement fmt.Stringer.

+ +

+ The ConnectionState + fields OCSPResponse and SignedCertificateTimestamps + are now repopulated on client-side resumed connections. +

diff --git a/src/crypto/tls/common.go b/src/crypto/tls/common.go index fd21ae8fb1..3a5ca22613 100644 --- a/src/crypto/tls/common.go +++ b/src/crypto/tls/common.go @@ -278,6 +278,8 @@ type ClientSessionState struct { serverCertificates []*x509.Certificate // Certificate chain presented by the server verifiedChains [][]*x509.Certificate // Certificate chains we built for verification receivedAt time.Time // When the session ticket was received from the server + ocspResponse []byte // Stapled OCSP response presented by the server + scts [][]byte // SCTs presented by the server // TLS 1.3 fields. nonce []byte // Ticket nonce sent by the server, to derive PSK diff --git a/src/crypto/tls/handshake_client.go b/src/crypto/tls/handshake_client.go index 40c8e02c53..46b0a770d5 100644 --- a/src/crypto/tls/handshake_client.go +++ b/src/crypto/tls/handshake_client.go @@ -728,10 +728,17 @@ func (hs *clientHandshakeState) processServerHello() (bool, error) { return false, errors.New("tls: server resumed a session with a different cipher suite") } - // Restore masterSecret and peerCerts from previous state + // Restore masterSecret, peerCerts, and ocspResponse from previous state hs.masterSecret = hs.session.masterSecret c.peerCertificates = hs.session.serverCertificates c.verifiedChains = hs.session.verifiedChains + c.ocspResponse = hs.session.ocspResponse + // Let the ServerHello SCTs override the session SCTs from the original + // connection, if any are provided + if len(c.scts) == 0 && len(hs.session.scts) != 0 { + c.scts = hs.session.scts + } + return true, nil } @@ -788,6 +795,8 @@ func (hs *clientHandshakeState) readSessionTicket() error { serverCertificates: c.peerCertificates, verifiedChains: c.verifiedChains, receivedAt: c.config.time(), + ocspResponse: c.ocspResponse, + scts: c.scts, } return nil diff --git a/src/crypto/tls/handshake_client_test.go b/src/crypto/tls/handshake_client_test.go index 1cda90190c..12b0254123 100644 --- a/src/crypto/tls/handshake_client_test.go +++ b/src/crypto/tls/handshake_client_test.go @@ -19,6 +19,7 @@ import ( "os" "os/exec" "path/filepath" + "reflect" "strconv" "strings" "testing" @@ -2430,3 +2431,83 @@ func TestDowngradeCanary(t *testing.T) { t.Errorf("client unexpectedly reacted to a canary in TLS 1.0") } } + +func TestResumptionKeepsOCSPAndSCT(t *testing.T) { + t.Run("TLSv12", func(t *testing.T) { testResumptionKeepsOCSPAndSCT(t, VersionTLS12) }) + t.Run("TLSv13", func(t *testing.T) { testResumptionKeepsOCSPAndSCT(t, VersionTLS13) }) +} + +func testResumptionKeepsOCSPAndSCT(t *testing.T, ver uint16) { + issuer, err := x509.ParseCertificate(testRSACertificateIssuer) + if err != nil { + t.Fatalf("failed to parse test issuer") + } + roots := x509.NewCertPool() + roots.AddCert(issuer) + clientConfig := &Config{ + MaxVersion: ver, + ClientSessionCache: NewLRUClientSessionCache(32), + ServerName: "example.golang", + RootCAs: roots, + } + serverConfig := testConfig.Clone() + serverConfig.MaxVersion = ver + serverConfig.Certificates[0].OCSPStaple = []byte{1, 2, 3} + serverConfig.Certificates[0].SignedCertificateTimestamps = [][]byte{{4, 5, 6}} + + _, ccs, err := testHandshake(t, clientConfig, serverConfig) + if err != nil { + t.Fatalf("handshake failed: %s", err) + } + // after a new session we expect to see OCSPResponse and + // SignedCertificateTimestamps populated as usual + if !bytes.Equal(ccs.OCSPResponse, serverConfig.Certificates[0].OCSPStaple) { + t.Errorf("client ConnectionState contained unexpected OCSPResponse: wanted %v, got %v", + serverConfig.Certificates[0].OCSPStaple, ccs.OCSPResponse) + } + if !reflect.DeepEqual(ccs.SignedCertificateTimestamps, serverConfig.Certificates[0].SignedCertificateTimestamps) { + t.Errorf("client ConnectionState contained unexpected SignedCertificateTimestamps: wanted %v, got %v", + serverConfig.Certificates[0].SignedCertificateTimestamps, ccs.SignedCertificateTimestamps) + } + + // if the server doesn't send any SCTs, repopulate the old SCTs + oldSCTs := serverConfig.Certificates[0].SignedCertificateTimestamps + serverConfig.Certificates[0].SignedCertificateTimestamps = nil + _, ccs, err = testHandshake(t, clientConfig, serverConfig) + if err != nil { + t.Fatalf("handshake failed: %s", err) + } + if !ccs.DidResume { + t.Fatalf("expected session to be resumed") + } + // after a resumed session we also expect to see OCSPResponse + // and SignedCertificateTimestamps populated + if !bytes.Equal(ccs.OCSPResponse, serverConfig.Certificates[0].OCSPStaple) { + t.Errorf("client ConnectionState contained unexpected OCSPResponse after resumption: wanted %v, got %v", + serverConfig.Certificates[0].OCSPStaple, ccs.OCSPResponse) + } + if !reflect.DeepEqual(ccs.SignedCertificateTimestamps, oldSCTs) { + t.Errorf("client ConnectionState contained unexpected SignedCertificateTimestamps after resumption: wanted %v, got %v", + oldSCTs, ccs.SignedCertificateTimestamps) + } + + // Only test overriding the SCTs for TLS 1.2, since in 1.3 + // the server won't send the message containing them + if ver == VersionTLS13 { + return + } + + // if the server changes the SCTs it sends, they should override the saved SCTs + serverConfig.Certificates[0].SignedCertificateTimestamps = [][]byte{{7, 8, 9}} + _, ccs, err = testHandshake(t, clientConfig, serverConfig) + if err != nil { + t.Fatalf("handshake failed: %s", err) + } + if !ccs.DidResume { + t.Fatalf("expected session to be resumed") + } + if !reflect.DeepEqual(ccs.SignedCertificateTimestamps, serverConfig.Certificates[0].SignedCertificateTimestamps) { + t.Errorf("client ConnectionState contained unexpected SignedCertificateTimestamps after resumption: wanted %v, got %v", + serverConfig.Certificates[0].SignedCertificateTimestamps, ccs.SignedCertificateTimestamps) + } +} diff --git a/src/crypto/tls/handshake_client_tls13.go b/src/crypto/tls/handshake_client_tls13.go index 35a00f2f3a..9c61105cf7 100644 --- a/src/crypto/tls/handshake_client_tls13.go +++ b/src/crypto/tls/handshake_client_tls13.go @@ -334,6 +334,8 @@ func (hs *clientHandshakeStateTLS13) processServerHello() error { c.didResume = true c.peerCertificates = hs.session.serverCertificates c.verifiedChains = hs.session.verifiedChains + c.ocspResponse = hs.session.ocspResponse + c.scts = hs.session.scts return nil } @@ -666,6 +668,8 @@ func (c *Conn) handleNewSessionTicket(msg *newSessionTicketMsgTLS13) error { nonce: msg.nonce, useBy: c.config.time().Add(lifetime), ageAdd: msg.ageAdd, + ocspResponse: c.ocspResponse, + scts: c.scts, } cacheKey := clientSessionCacheKey(c.conn.RemoteAddr(), c.config) From b9332ed31aa4c2b73134a1b968761fc4c259ccac Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Fri, 5 Jun 2020 13:51:17 -0400 Subject: [PATCH 27/34] doc: document encoding/xml change in CL 203417 Change-Id: Ibc0228f166f449ec28d813f33bdb550fe7ba2b3e Reviewed-on: https://go-review.googlesource.com/c/go/+/236739 Reviewed-by: Dmitri Shuralyov --- doc/go1.15.html | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/doc/go1.15.html b/doc/go1.15.html index ffe9d26dc7..dd25b27c5f 100644 --- a/doc/go1.15.html +++ b/doc/go1.15.html @@ -478,7 +478,7 @@ Do not send CLs removing the interior tags from such phrases. ClientAuthType now implement fmt.Stringer.

- +

The ConnectionState fields OCSPResponse and SignedCertificateTimestamps @@ -569,7 +569,13 @@ Do not send CLs removing the interior tags from such phrases.

encoding/xml

- TODO: https://golang.org/cl/203417: fix reserved namespace check to be case-insensitive + The encoder has always taken care to avoid using namespace prefixes beginning with + xml, + which are reserved by the XML specification. + Now, following the specification more closely, + that check is case-insensitive, so that prefixes beginning with + XML, XmL, + and so on are also avoided.

From 2a4e71c752875f84dc0061f75fdcbfc96ae8d5f2 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Tue, 9 Jun 2020 22:00:18 -0400 Subject: [PATCH 28/34] run.bat: do not unset GOROOT_FINAL before running tests This removes the same logic from run.bat that was removed from cmd/dist in CL 236819. The duplicated logic was removed from run.bash and run.rc in CL 6531, but that part of run.bat was apparently missed (and not noticed because its effect was redundant). Also fix a path-separator bug in cmd/addr2line.TestAddr2Line that was exposed as a result. Fixes #39478 Updates #39385 Change-Id: I00054966cf92ef92a03681bf23de7f45f46fbb5e Reviewed-on: https://go-review.googlesource.com/c/go/+/237359 Run-TryBot: Bryan C. Mills Reviewed-by: Dmitri Shuralyov TryBot-Result: Gobot Gobot --- src/cmd/addr2line/addr2line_test.go | 8 +++++--- src/run.bat | 5 ----- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/cmd/addr2line/addr2line_test.go b/src/cmd/addr2line/addr2line_test.go index e12f0ae814..578d88e432 100644 --- a/src/cmd/addr2line/addr2line_test.go +++ b/src/cmd/addr2line/addr2line_test.go @@ -73,6 +73,8 @@ func testAddr2Line(t *testing.T, exepath, addr string) { if err != nil { t.Fatalf("Stat failed: %v", err) } + // Debug paths are stored slash-separated, so convert to system-native. + srcPath = filepath.FromSlash(srcPath) fi2, err := os.Stat(srcPath) if gorootFinal := os.Getenv("GOROOT_FINAL"); gorootFinal != "" && strings.HasPrefix(srcPath, gorootFinal) { if os.IsNotExist(err) || (err == nil && !os.SameFile(fi1, fi2)) { @@ -88,12 +90,12 @@ func testAddr2Line(t *testing.T, exepath, addr string) { if !os.SameFile(fi1, fi2) { t.Fatalf("addr2line_test.go and %s are not same file", srcPath) } - if srcLineNo != "97" { - t.Fatalf("line number = %v; want 97", srcLineNo) + if srcLineNo != "99" { + t.Fatalf("line number = %v; want 99", srcLineNo) } } -// This is line 96. The test depends on that. +// This is line 98. The test depends on that. func TestAddr2Line(t *testing.T) { testenv.MustHaveGoBuild(t) diff --git a/src/run.bat b/src/run.bat index 90602b68cb..c299671c13 100644 --- a/src/run.bat +++ b/src/run.bat @@ -35,11 +35,6 @@ if errorlevel 1 goto fail echo. :norebuild -:: we must unset GOROOT_FINAL before tests, because runtime/debug requires -:: correct access to source code, so if we have GOROOT_FINAL in effect, -:: at least runtime/debug test will fail. -set GOROOT_FINAL= - :: get CGO_ENABLED ..\bin\go env > env.bat if errorlevel 1 goto fail From ac743dea8e7d351d48a79bf4e7aea62ba3b4a515 Mon Sep 17 00:00:00 2001 From: Michael Munday Date: Tue, 9 Jun 2020 03:17:17 -0700 Subject: [PATCH 29/34] cmd/compile: always tighten and de-duplicate tuple selectors The scheduler assumes two special invariants that apply to tuple selectors (Select0 and Select1 ops): 1. There is only one tuple selector of each type per generator. 2. Tuple selectors and generators reside in the same block. Prior to this CL the assumption was that these invariants would only be broken by the CSE pass. The CSE pass therefore contained code to move and de-duplicate selectors to fix these invariants. However it is also possible to write relatively basic optimization rules that cause these invariants to be broken. For example: (A (Select0 (B))) -> (Select1 (B)) This rule could result in the newly added selector (Select1) being in a different block to the tuple generator (see issue #38356). It could also result in duplicate selectors if this rule matches multiple times for the same tuple generator (see issue #39472). The CSE pass will 'fix' these invariants. However it will only do so when optimizations are enabled (since disabling optimizations disables the CSE pass). This CL moves the CSE tuple selector fixup code into its own pass and makes it mandatory even when optimizations are disabled. This allows tuple selectors to be treated like normal ops for most of the compilation pipeline until after the new pass has run, at which point we need to be careful to maintain the invariant again. Fixes #39472. Change-Id: Ia3f79e09d9c65ac95f897ce37e967ee1258a080b Reviewed-on: https://go-review.googlesource.com/c/go/+/237118 Run-TryBot: Michael Munday TryBot-Result: Gobot Gobot Reviewed-by: Keith Randall --- src/cmd/compile/internal/ssa/compile.go | 3 ++ src/cmd/compile/internal/ssa/cse.go | 54 ---------------------- src/cmd/compile/internal/ssa/tuple.go | 59 +++++++++++++++++++++++++ test/fixedbugs/issue39472.go | 12 +++++ 4 files changed, 74 insertions(+), 54 deletions(-) create mode 100644 src/cmd/compile/internal/ssa/tuple.go create mode 100644 test/fixedbugs/issue39472.go diff --git a/src/cmd/compile/internal/ssa/compile.go b/src/cmd/compile/internal/ssa/compile.go index 2dbe9cf405..dbdd027716 100644 --- a/src/cmd/compile/internal/ssa/compile.go +++ b/src/cmd/compile/internal/ssa/compile.go @@ -451,6 +451,7 @@ var passes = [...]pass{ {name: "lowered deadcode for cse", fn: deadcode}, // deadcode immediately before CSE avoids CSE making dead values live again {name: "lowered cse", fn: cse}, {name: "elim unread autos", fn: elimUnreadAutos}, + {name: "tighten tuple selectors", fn: tightenTupleSelectors, required: true}, {name: "lowered deadcode", fn: deadcode, required: true}, {name: "checkLower", fn: checkLower, required: true}, {name: "late phielim", fn: phielim}, @@ -509,6 +510,8 @@ var passOrder = [...]constraint{ {"decompose builtin", "late opt"}, // decompose builtin is the last pass that may introduce new float ops, so run softfloat after it {"decompose builtin", "softfloat"}, + // tuple selectors must be tightened to generators and de-duplicated before scheduling + {"tighten tuple selectors", "schedule"}, // remove critical edges before phi tighten, so that phi args get better placement {"critical", "phi tighten"}, // don't layout blocks until critical edges have been removed diff --git a/src/cmd/compile/internal/ssa/cse.go b/src/cmd/compile/internal/ssa/cse.go index 6bfd2960c1..3b4f2be37e 100644 --- a/src/cmd/compile/internal/ssa/cse.go +++ b/src/cmd/compile/internal/ssa/cse.go @@ -223,60 +223,6 @@ func cse(f *Func) { } } - // Fixup tuple selectors. - // - // If we have rewritten a tuple generator to a new one in a different - // block, copy its selectors to the new generator's block, so tuple - // generator and selectors stay together. - // - // Note: that there must be only one selector of each type per tuple - // generator. CSE may have left us with more than one so we de-duplicate - // them using a map. See issue 16741. - selectors := make(map[struct { - id ID - op Op - }]*Value) - for _, b := range f.Blocks { - for _, selector := range b.Values { - if selector.Op != OpSelect0 && selector.Op != OpSelect1 { - continue - } - - // Get the tuple generator to use as a key for de-duplication. - tuple := selector.Args[0] - if !tuple.Type.IsTuple() { - f.Fatalf("arg of tuple selector %s is not a tuple: %s", selector.String(), tuple.LongString()) - } - - // If there is a pre-existing selector in the target block then - // use that. Do this even if the selector is already in the - // target block to avoid duplicate tuple selectors. - key := struct { - id ID - op Op - }{tuple.ID, selector.Op} - if t := selectors[key]; t != nil { - if selector != t { - selector.copyOf(t) - } - continue - } - - // If the selector is in the wrong block copy it into the target - // block. - if selector.Block != tuple.Block { - t := selector.copyInto(tuple.Block) - selector.copyOf(t) - selectors[key] = t - continue - } - - // The selector is in the target block. Add it to the map so it - // cannot be duplicated. - selectors[key] = selector - } - } - if f.pass.stats > 0 { f.LogStat("CSE REWRITES", rewrites) } diff --git a/src/cmd/compile/internal/ssa/tuple.go b/src/cmd/compile/internal/ssa/tuple.go new file mode 100644 index 0000000000..38deabf83d --- /dev/null +++ b/src/cmd/compile/internal/ssa/tuple.go @@ -0,0 +1,59 @@ +// Copyright 2020 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. + +package ssa + +// tightenTupleSelectors ensures that tuple selectors (Select0 and +// Select1 ops) are in the same block as their tuple generator. The +// function also ensures that there are no duplicate tuple selectors. +// These properties are expected by the scheduler but may not have +// been maintained by the optimization pipeline up to this point. +// +// See issues 16741 and 39472. +func tightenTupleSelectors(f *Func) { + selectors := make(map[struct { + id ID + op Op + }]*Value) + for _, b := range f.Blocks { + for _, selector := range b.Values { + if selector.Op != OpSelect0 && selector.Op != OpSelect1 { + continue + } + + // Get the tuple generator to use as a key for de-duplication. + tuple := selector.Args[0] + if !tuple.Type.IsTuple() { + f.Fatalf("arg of tuple selector %s is not a tuple: %s", selector.String(), tuple.LongString()) + } + + // If there is a pre-existing selector in the target block then + // use that. Do this even if the selector is already in the + // target block to avoid duplicate tuple selectors. + key := struct { + id ID + op Op + }{tuple.ID, selector.Op} + if t := selectors[key]; t != nil { + if selector != t { + selector.copyOf(t) + } + continue + } + + // If the selector is in the wrong block copy it into the target + // block. + if selector.Block != tuple.Block { + t := selector.copyInto(tuple.Block) + selector.copyOf(t) + selectors[key] = t + continue + } + + // The selector is in the target block. Add it to the map so it + // cannot be duplicated. + selectors[key] = selector + } + } +} diff --git a/test/fixedbugs/issue39472.go b/test/fixedbugs/issue39472.go new file mode 100644 index 0000000000..61444a28b9 --- /dev/null +++ b/test/fixedbugs/issue39472.go @@ -0,0 +1,12 @@ +// compile -N + +// Copyright 2020 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. + +package p + +func f(x float64) bool { + x += 1 + return (x != 0) == (x != 0) +} From e92be18fd8b525b642ca25bdb3e2056b35d9d73c Mon Sep 17 00:00:00 2001 From: Rodolfo Carvalho Date: Wed, 10 Jun 2020 13:30:42 +0000 Subject: [PATCH 30/34] runtime: fix typo in FuncForPC doc Change-Id: I04037e13b131e79ebc5af84896bfeda49ddc0eaa GitHub-Last-Rev: b0d0de930862e4f163e158876cba70d81ed2d52e GitHub-Pull-Request: golang/go#39500 Reviewed-on: https://go-review.googlesource.com/c/go/+/237220 Reviewed-by: Keith Randall --- src/runtime/symtab.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index ce2ec6dd1d..1e86662adc 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -563,8 +563,8 @@ func moduledataverify1(datap *moduledata) { // given program counter address, or else nil. // // If pc represents multiple functions because of inlining, it returns -// the a *Func describing the innermost function, but with an entry -// of the outermost function. +// the *Func describing the innermost function, but with an entry of +// the outermost function. func FuncForPC(pc uintptr) *Func { f := findfunc(pc) if !f.valid() { From ec177e4c83a5f318e3d65e6405ffbd0715834a98 Mon Sep 17 00:00:00 2001 From: Gawen Arab Date: Wed, 10 Jun 2020 20:31:57 +0000 Subject: [PATCH 31/34] cmd/internal/objabi: enable frame-pointer for iOS arm64 This improves stack unwinding of Go code running on iOS arm64. Change-Id: I0494f750c15dcb895f9d4a072352f050d731df17 GitHub-Last-Rev: 435a2a1690dad98975f7463f91241831cd73d3df GitHub-Pull-Request: golang/go#37403 Reviewed-on: https://go-review.googlesource.com/c/go/+/220588 Run-TryBot: Elias Naur TryBot-Result: Gobot Gobot Reviewed-by: Cherry Zhang --- src/cmd/internal/objabi/util.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/internal/objabi/util.go b/src/cmd/internal/objabi/util.go index 2f94ec6a67..f7873a42b9 100644 --- a/src/cmd/internal/objabi/util.go +++ b/src/cmd/internal/objabi/util.go @@ -134,7 +134,7 @@ func init() { } func Framepointer_enabled(goos, goarch string) bool { - return framepointer_enabled != 0 && (goarch == "amd64" || goarch == "arm64" && goos == "linux") + return framepointer_enabled != 0 && (goarch == "amd64" || goarch == "arm64" && (goos == "linux" || goos == "darwin")) } func addexp(s string) { From 6aadfcdfad663738519535abc76e819d2843375d Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Wed, 10 Jun 2020 12:47:23 -0700 Subject: [PATCH 32/34] go/types: rename UsesCgo to go115UsesCgo This API and functionality was added late in the Go 1.15 release cycle, and use within gopls has revealed some shortcomings. It's possible (but not decided) that we'll want a different API long-term, so for now this CL renames UsesCgo to a non-exported name to avoid long-term commitment under the Go 1 compat guarantee. Updates #16623. Updates #39072. Change-Id: I04bc0c161a84adebe43e926df5df406bc794c3db Reviewed-on: https://go-review.googlesource.com/c/go/+/237417 Run-TryBot: Matthew Dempsky TryBot-Result: Gobot Gobot Reviewed-by: Heschi Kreinick --- api/go1.15.txt | 1 - src/go/internal/srcimporter/srcimporter.go | 6 +++++- src/go/types/api.go | 10 +++++++--- src/go/types/check.go | 4 ++-- src/go/types/resolver.go | 4 ++-- 5 files changed, 16 insertions(+), 9 deletions(-) diff --git a/api/go1.15.txt b/api/go1.15.txt index f16faa0780..b51837cf38 100644 --- a/api/go1.15.txt +++ b/api/go1.15.txt @@ -114,7 +114,6 @@ pkg debug/pe, const IMAGE_SUBSYSTEM_XBOX = 14 pkg debug/pe, const IMAGE_SUBSYSTEM_XBOX ideal-int pkg go/printer, const StdFormat = 16 pkg go/printer, const StdFormat Mode -pkg go/types, type Config struct, UsesCgo bool pkg math/big, method (*Int) FillBytes([]uint8) []uint8 pkg net, method (*Resolver) LookupIP(context.Context, string, string) ([]IP, error) pkg net/url, method (*URL) EscapedFragment() string diff --git a/src/go/internal/srcimporter/srcimporter.go b/src/go/internal/srcimporter/srcimporter.go index daef27c8b9..90bb3a9bc1 100644 --- a/src/go/internal/srcimporter/srcimporter.go +++ b/src/go/internal/srcimporter/srcimporter.go @@ -20,6 +20,7 @@ import ( "path/filepath" "strings" "sync" + _ "unsafe" // for go:linkname ) // An Importer provides the context for importing packages from source code. @@ -133,7 +134,7 @@ func (p *Importer) ImportFrom(path, srcDir string, mode types.ImportMode) (*type // build.Context's VFS. conf.FakeImportC = true } else { - conf.UsesCgo = true + setUsesCgo(&conf) file, err := p.cgo(bp) if err != nil { return nil, err @@ -260,3 +261,6 @@ func (p *Importer) joinPath(elem ...string) string { } return filepath.Join(elem...) } + +//go:linkname setUsesCgo go/types.srcimporter_setUsesCgo +func setUsesCgo(conf *types.Config) diff --git a/src/go/types/api.go b/src/go/types/api.go index 7787b88906..1abcd9d951 100644 --- a/src/go/types/api.go +++ b/src/go/types/api.go @@ -105,14 +105,14 @@ type Config struct { // Do not use casually! FakeImportC bool - // If UsesCgo is set, the type checker expects the + // If go115UsesCgo is set, the type checker expects the // _cgo_gotypes.go file generated by running cmd/cgo to be // provided as a package source file. Qualified identifiers // referring to package C will be resolved to cgo-provided // declarations within _cgo_gotypes.go. // - // It is an error to set both FakeImportC and UsesCgo. - UsesCgo bool + // It is an error to set both FakeImportC and go115UsesCgo. + go115UsesCgo bool // If Error != nil, it is called with each error found // during type checking; err has dynamic type Error. @@ -140,6 +140,10 @@ type Config struct { DisableUnusedImportCheck bool } +func srcimporter_setUsesCgo(conf *Config) { + conf.go115UsesCgo = true +} + // Info holds result type information for a type-checked package. // Only the information for which a map is provided is collected. // If the package has type errors, the collected information may diff --git a/src/go/types/check.go b/src/go/types/check.go index a94770ffef..007babdf9d 100644 --- a/src/go/types/check.go +++ b/src/go/types/check.go @@ -248,10 +248,10 @@ func (check *Checker) handleBailout(err *error) { // Files checks the provided files as part of the checker's package. func (check *Checker) Files(files []*ast.File) error { return check.checkFiles(files) } -var errBadCgo = errors.New("cannot use FakeImportC and UsesCgo together") +var errBadCgo = errors.New("cannot use FakeImportC and go115UsesCgo together") func (check *Checker) checkFiles(files []*ast.File) (err error) { - if check.conf.FakeImportC && check.conf.UsesCgo { + if check.conf.FakeImportC && check.conf.go115UsesCgo { return errBadCgo } diff --git a/src/go/types/resolver.go b/src/go/types/resolver.go index f80b4ec784..078adc5ec7 100644 --- a/src/go/types/resolver.go +++ b/src/go/types/resolver.go @@ -141,10 +141,10 @@ func (check *Checker) importPackage(pos token.Pos, path, dir string) *Package { } // no package yet => import it - if path == "C" && (check.conf.FakeImportC || check.conf.UsesCgo) { + if path == "C" && (check.conf.FakeImportC || check.conf.go115UsesCgo) { imp = NewPackage("C", "C") imp.fake = true // package scope is not populated - imp.cgo = check.conf.UsesCgo + imp.cgo = check.conf.go115UsesCgo } else { // ordinary import var err error From 5adaa1290ec4a7507c0be56743c237d9bf311055 Mon Sep 17 00:00:00 2001 From: Vee Zhang Date: Thu, 11 Jun 2020 04:39:49 +0000 Subject: [PATCH 33/34] A+C: add Vee Zhang (individual CLA) Change-Id: Id52c5fef2e5b65056d3c87e70e176b67998cea90 GitHub-Last-Rev: b88e3afa38d96a5a51334100bb29108c5f2618f4 GitHub-Pull-Request: golang/go#39520 Reviewed-on: https://go-review.googlesource.com/c/go/+/237223 Reviewed-by: Ian Lance Taylor --- AUTHORS | 1 + CONTRIBUTORS | 1 + 2 files changed, 2 insertions(+) diff --git a/AUTHORS b/AUTHORS index 69e35a13ae..80c79feb33 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1397,6 +1397,7 @@ Upthere, Inc. Uriel Mangado Vadim Grek Vadim Vygonets +Vee Zhang Vendasta Veselkov Konstantin Victor Vrantchan diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 934834fc79..6b6ee09415 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -2195,6 +2195,7 @@ Vadim Grek Vadim Vygonets Val Polouchkine Valentin Vidic +Vee Zhang Vega Garcia Luis Alfonso Venil Noronha Veselkov Konstantin From f7ba82d68f90e20aa9e6aa973cb6f12321abec71 Mon Sep 17 00:00:00 2001 From: Baokun Lee Date: Tue, 9 Jun 2020 23:03:35 +0800 Subject: [PATCH 34/34] cmd/go/internal/web: don't follow an infinite number of redirects We replaced http.DefaultClient with securityPreservingHTTPClient, but we still need that too many redirects check. This issue introduced by CL 156838. We introduce a special path to test rediret requests in the script test framework. You can specify the number of redirects in the path. $GOPROXY/redirect//... Redirect request sequence details(count=8): request: $GOPROXY/mod/redirect/8/rsc.io/quote/@v/v1.2.0.mod redirect: $GOPROXY/mod/redirect/7/rsc.io/quote/@v/v1.2.0.mod redirect: $GOPROXY/mod/redirect/6/rsc.io/quote/@v/v1.2.0.mod redirect: $GOPROXY/mod/redirect/5/rsc.io/quote/@v/v1.2.0.mod redirect: $GOPROXY/mod/redirect/4/rsc.io/quote/@v/v1.2.0.mod redirect: $GOPROXY/mod/redirect/3/rsc.io/quote/@v/v1.2.0.mod redirect: $GOPROXY/mod/redirect/2/rsc.io/quote/@v/v1.2.0.mod redirect: $GOPROXY/mod/redirect/1/rsc.io/quote/@v/v1.2.0.mod the last: $GOPROXY/mod/rsc.io/quote/@v/v1.2.0.mod Fixes #39482 Change-Id: I149a3702b2b616069baeef787b2e4b73afc93b0e Reviewed-on: https://go-review.googlesource.com/c/go/+/237177 Run-TryBot: Baokun Lee TryBot-Result: Gobot Gobot Reviewed-by: Jay Conrod --- src/cmd/go/internal/web/http.go | 8 ++++++++ src/cmd/go/proxy_test.go | 19 +++++++++++++++++++ .../script/mod_get_too_many_redirects.txt | 10 ++++++++++ 3 files changed, 37 insertions(+) create mode 100644 src/cmd/go/testdata/script/mod_get_too_many_redirects.txt diff --git a/src/cmd/go/internal/web/http.go b/src/cmd/go/internal/web/http.go index beb80c505d..e0509808d6 100644 --- a/src/cmd/go/internal/web/http.go +++ b/src/cmd/go/internal/web/http.go @@ -13,6 +13,7 @@ package web import ( "crypto/tls" + "errors" "fmt" "mime" "net/http" @@ -47,6 +48,13 @@ var securityPreservingHTTPClient = &http.Client{ lastHop := via[len(via)-1].URL return fmt.Errorf("redirected from secure URL %s to insecure URL %s", lastHop, req.URL) } + + // Go's http.DefaultClient allows 10 redirects before returning an error. + // The securityPreservingHTTPClient also uses this default policy to avoid + // Go command hangs. + if len(via) >= 10 { + return errors.New("stopped after 10 redirects") + } return nil }, } diff --git a/src/cmd/go/proxy_test.go b/src/cmd/go/proxy_test.go index 8214488a59..2a4d2935b3 100644 --- a/src/cmd/go/proxy_test.go +++ b/src/cmd/go/proxy_test.go @@ -174,6 +174,25 @@ func proxyHandler(w http.ResponseWriter, r *http.Request) { return } + // Request for $GOPROXY/redirect//... goes to redirects. + if strings.HasPrefix(path, "redirect/") { + path = path[len("redirect/"):] + if j := strings.Index(path, "/"); j >= 0 { + count, err := strconv.Atoi(path[:j]) + if err != nil { + return + } + + // The last redirect. + if count <= 1 { + http.Redirect(w, r, fmt.Sprintf("/mod/%s", path[j+1:]), 302) + return + } + http.Redirect(w, r, fmt.Sprintf("/mod/redirect/%d/%s", count-1, path[j+1:]), 302) + return + } + } + // Request for $GOPROXY/sumdb//supported // is checking whether it's OK to access sumdb via the proxy. if path == "sumdb/"+testSumDBName+"/supported" { diff --git a/src/cmd/go/testdata/script/mod_get_too_many_redirects.txt b/src/cmd/go/testdata/script/mod_get_too_many_redirects.txt new file mode 100644 index 0000000000..9cbe0d279d --- /dev/null +++ b/src/cmd/go/testdata/script/mod_get_too_many_redirects.txt @@ -0,0 +1,10 @@ +env GO111MODULE=on +env GOPROXYBASE=$GOPROXY +env GOPROXY=$GOPROXYBASE/redirect/11 +env GOSUMDB=off + +! go get -d rsc.io/quote@v1.2.0 +stderr 'stopped after 10 redirects' + +env GOPROXY=$GOPROXYBASE/redirect/9 +go get -d rsc.io/quote@v1.2.0