From 2bbb2ace346a26e0b1f7e32f1cdc645db8170d1c Mon Sep 17 00:00:00 2001 From: jjpinto Date: Mon, 5 Jan 2026 23:08:44 +0000 Subject: runtime/trace: fix documentation comment Correct documentation comment for mul function Change-Id: I8b90f02bf0aaba9bb5813833d1b9dd1ebb7d71f4 GitHub-Last-Rev: e91af64af9bad9cd2574dc3dd7ed88123a288be8 GitHub-Pull-Request: golang/go#77082 Reviewed-on: https://go-review.googlesource.com/c/go/+/734100 Reviewed-by: Michael Knyszek LUCI-TryBot-Result: Go LUCI Reviewed-by: Michael Pratt --- src/runtime/trace/recorder.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/trace/recorder.go b/src/runtime/trace/recorder.go index a18d764141..8617231aaa 100644 --- a/src/runtime/trace/recorder.go +++ b/src/runtime/trace/recorder.go @@ -112,7 +112,7 @@ func runtime_traceClockNow() uint64 // frequency is nanoseconds per timestamp unit. type frequency float64 -// mul multiplies an unprocessed to produce a time in nanoseconds. +// mul multiplies an unprocessed timestamp to produce a time in nanoseconds. func (f frequency) mul(t timestamp) eventTime { return eventTime(float64(t) * float64(f)) } -- cgit v1.3 From 108b333d510c1f60877ac917375d7931791acfe6 Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Thu, 8 Jan 2026 12:45:34 -0500 Subject: cmd/go: only use check cache action's dependencies to build vet config We manipulate the dependencies of the build action when adding the non-test variant of the package being tested as a dependency for the test, so the set of deps of the build package doesn't correctly represent the dependencies of the package that have been built. Restrict the set of dependencies we use to populate the vet data to the actual build dependencies depended on by the check cache action so we don't check an action that we don't actually depend on (and which may not have completed yet!) Fixes #75380 Change-Id: I029080d00b3b10a837abcfb7039e00206a6a6964 Reviewed-on: https://go-review.googlesource.com/c/go/+/734961 Reviewed-by: Michael Matloob Reviewed-by: Michael Pratt LUCI-TryBot-Result: Go LUCI --- src/cmd/go/internal/work/exec.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go index f2d1b1040b..0afdce2356 100644 --- a/src/cmd/go/internal/work/exec.go +++ b/src/cmd/go/internal/work/exec.go @@ -627,7 +627,7 @@ func (b *Builder) checkCacheForBuild(a, buildAction *Action, covMetaFileName str // If we are going to do a full build anyway, // we're going to regenerate the files in the build action anyway. if need == needVet { - if err := b.loadCachedVet(buildAction); err == nil { + if err := b.loadCachedVet(buildAction, a.Deps); err == nil { need &^= needVet } } @@ -841,7 +841,7 @@ func (b *Builder) build(ctx context.Context, a *Action) (err error) { // Prepare Go vet config if needed. if need&needVet != 0 { - buildVetConfig(a, srcfiles) + buildVetConfig(a, srcfiles, a.Deps) need &^= needVet } if need&needCompiledGoFiles != 0 { @@ -1121,7 +1121,7 @@ func (b *Builder) cacheSrcFiles(a *Action, srcfiles []string) { cache.PutBytes(c, cache.Subkey(a.actionID, "srcfiles"), buf.Bytes()) } -func (b *Builder) loadCachedVet(a *Action) error { +func (b *Builder) loadCachedVet(a *Action, vetDeps []*Action) error { c := cache.Default() list, _, err := cache.GetBytes(c, cache.Subkey(a.actionID, "srcfiles")) if err != nil { @@ -1141,7 +1141,7 @@ func (b *Builder) loadCachedVet(a *Action) error { } srcfiles = append(srcfiles, a.Objdir+name) } - buildVetConfig(a, srcfiles) + buildVetConfig(a, srcfiles, vetDeps) return nil } @@ -1197,7 +1197,7 @@ type vetConfig struct { SucceedOnTypecheckFailure bool // awful hack; see #18395 and below } -func buildVetConfig(a *Action, srcfiles []string) { +func buildVetConfig(a *Action, srcfiles []string, vetDeps []*Action) { // Classify files based on .go extension. // srcfiles does not include raw cgo files. var gofiles, nongofiles []string @@ -1253,7 +1253,7 @@ func buildVetConfig(a *Action, srcfiles []string) { vcfgMapped[p] = true } - for _, a1 := range a.Deps { + for _, a1 := range vetDeps { p1 := a1.Package if p1 == nil || p1.ImportPath == "" || p1 == a.Package { continue -- cgit v1.3 From 088ba94439775e025b90790f1c8db49ee2e7017f Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Thu, 8 Jan 2026 02:23:02 +0100 Subject: crypto/rsa: log key on test failure For #74326 Change-Id: If1e61db22c9e7192e5dd56cd36141e5b6a6a6964 Reviewed-on: https://go-review.googlesource.com/c/go/+/734640 LUCI-TryBot-Result: Go LUCI Auto-Submit: Filippo Valsorda Reviewed-by: Daniel McCarney Reviewed-by: Roland Shoemaker Reviewed-by: Junyang Shao --- src/crypto/rsa/rsa_test.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/crypto/rsa/rsa_test.go b/src/crypto/rsa/rsa_test.go index 5ae4c1dd20..124fba1e8a 100644 --- a/src/crypto/rsa/rsa_test.go +++ b/src/crypto/rsa/rsa_test.go @@ -145,6 +145,12 @@ d8Y7 } func testKeyBasics(t *testing.T, priv *PrivateKey) { + defer func() { + if t.Failed() { + t.Logf("failed key: %#v", priv) + } + }() + if err := priv.Validate(); err != nil { t.Errorf("Validate() failed: %s", err) } -- cgit v1.3 From 55ab5bba17a5221a51df244c8a3aeb1898cbdf1a Mon Sep 17 00:00:00 2001 From: Alan Donovan Date: Fri, 9 Jan 2026 11:01:00 -0500 Subject: path/filepath: Match: improve doc comment Change-Id: Ic7a6e11ddeb79af67ece345405cdca6cf5199173 Reviewed-on: https://go-review.googlesource.com/c/go/+/735180 Reviewed-by: Damien Neil Auto-Submit: Alan Donovan LUCI-TryBot-Result: Go LUCI --- src/path/filepath/match.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/path/filepath/match.go b/src/path/filepath/match.go index 7ccf71ee0c..3c1c22bb8a 100644 --- a/src/path/filepath/match.go +++ b/src/path/filepath/match.go @@ -28,13 +28,15 @@ var ErrBadPattern = errors.New("syntax error in pattern") // '[' [ '^' ] { character-range } ']' // character class (must be non-empty) // c matches character c (c != '*', '?', '\\', '[') -// '\\' c matches character c +// '\\' c matches character c (except on Windows) // // character-range: // c matches character c (c != '\\', '-', ']') -// '\\' c matches character c +// '\\' c matches character c (except on Windows) // lo '-' hi matches character c for lo <= c <= hi // +// Path segments in the pattern must be separated by [Separator]. +// // Match requires pattern to match all of name, not just a substring. // The only possible returned error is [ErrBadPattern], when pattern // is malformed. -- cgit v1.3 From fed3b0a298464457c58d1150bdb3942f22bd6220 Mon Sep 17 00:00:00 2001 From: jjpinto Date: Mon, 5 Jan 2026 22:59:29 +0000 Subject: cmd/dist: fix goroot typo in panic message Change-Id: I636a029eedaab0967b774648670710d1303a1f7c GitHub-Last-Rev: 519faedc5b8327696efeeb431ef66e9fd29f0db7 GitHub-Pull-Request: golang/go#77081 Reviewed-on: https://go-review.googlesource.com/c/go/+/734080 Reviewed-by: Ian Lance Taylor LUCI-TryBot-Result: Go LUCI Reviewed-by: Junyang Shao Reviewed-by: Cherry Mui --- src/cmd/dist/imports.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/dist/imports.go b/src/cmd/dist/imports.go index 0ec2b06c4f..c00369a6ba 100644 --- a/src/cmd/dist/imports.go +++ b/src/cmd/dist/imports.go @@ -259,6 +259,6 @@ func resolveVendor(imp, srcDir string) string { } else if strings.HasPrefix(srcDir, filepath.Join(goroot, "src")) { return path.Join("vendor", imp) } else { - panic(fmt.Sprintf("srcDir %q not in GOOROT/src", srcDir)) + panic(fmt.Sprintf("srcDir %q not in GOROOT/src", srcDir)) } } -- cgit v1.3 From cc1d7afb247677fd9a1f75d11587af00d65e231d Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 6 Jan 2026 17:43:56 -0800 Subject: spec: slightly re-arrange composite literal section for readability - introduce subtitles to make various sub-sections easier to find - split rules for struct literals into two groups (literals without and with keys) - move section on syntax ambiguity up as it pertains to the syntax introduced at the start - move prose specific to map literals into its own section No language changes. Change-Id: If8895b869138693179ca6e4d8b1c6ebdc705eccf Reviewed-on: https://go-review.googlesource.com/c/go/+/734322 Reviewed-by: Alan Donovan Auto-Submit: Robert Griesemer LUCI-TryBot-Result: Go LUCI Reviewed-by: Robert Griesemer --- doc/go_spec.html | 87 +++++++++++++++++++++++++++++++++----------------------- 1 file changed, 51 insertions(+), 36 deletions(-) diff --git a/doc/go_spec.html b/doc/go_spec.html index f47f5a6e3e..478aefd4a6 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -1,6 +1,6 @@ @@ -3143,7 +3143,8 @@ math.Sin // denotes the Sin function in package math

Composite literals construct new values for structs, arrays, slices, and maps each time they are evaluated. -They consist of the type of the literal followed by a brace-bound list of elements. +They consist of the type of the literal followed by a (possibly empty) +brace-bound list of elements. Each element may optionally be preceded by a corresponding key.

@@ -3168,35 +3169,53 @@ as a TypeName). If the LiteralType is a type parameter, all types in its type set must have the same underlying type which must be a valid composite literal type. +

+ +

The types of the elements and keys must be assignable -to the respective field, element, and key types of type T; +to the respective field, element, and key types of the LiteralType; there is no additional conversion. The key is interpreted as a field name for struct literals, an index for array and slice literals, and a key for map literals. -For map literals, all elements must have a key. It is an error -to specify multiple elements with the same field name or -constant key value. For non-constant map keys, see the section on -evaluation order. +It is an error to specify multiple elements with the same field name +or constant key value. +A literal may omit the element list; such a literal evaluates +to the zero value for its type.

-For struct literals the following rules apply: +A parsing ambiguity arises when a composite literal using the +TypeName form of the LiteralType appears as an operand between the +keyword and the opening brace of the block +of an "if", "for", or "switch" statement, and the composite literal +is not enclosed in parentheses, square brackets, or curly braces. +In this rare case, the opening brace of the literal is erroneously parsed +as the one introducing the block of statements. To resolve the ambiguity, +the composite literal must appear within parentheses. +

+ +
+if x == (T{a,b,c}[i]) { … }
+if (x == T{a,b,c}[i]) { … }
+
+ +

Struct literals

+ +

+For struct literals without keys, the element list must contain an element +for each struct field in the order in which the fields are declared. +

+ +

+For struct literals with keys the following rules apply:

    -
  • A key must be a field name declared in the struct type. -
  • -
  • An element list that does not contain any keys must - list an element for each struct field in the - order in which the fields are declared. +
  • Every element must have a key.
  • -
  • If any element has a key, every element must have a key. +
  • Each key must be a field name declared in the struct type.
  • -
  • An element list that contains keys does not need to - have an element for each struct field. Omitted fields - get the zero value for that field. -
  • -
  • A literal may omit the element list; such a literal evaluates - to the zero value for its type. +
  • The element list does not need to have an element for each struct field. + Omitted fields get the zero value for that field.
  • It is an error to specify an element for a non-exported field of a struct belonging to a different package. @@ -3220,6 +3239,8 @@ origin := Point3D{} // zero value for Point3D line := Line{origin, Point3D{y: -4, z: 12.3}} // zero value for line.q.x +

    Array and slice literals

    +

    For array and slice literals the following rules apply:

    @@ -3295,6 +3316,16 @@ tmp := [n]T{x1, x2, … xn} tmp[0 : n] +

    Map literals

    + +

    +For map literals, each element must have a key. +For non-constant map keys, see the section on +evaluation order. +

    + +

    Elision of element types

    +

    Within a composite literal of array, slice, or map type T, elements or map keys that are themselves composite literals may elide the respective @@ -3315,22 +3346,6 @@ type PPoint *Point [2]PPoint{{1.5, -3.5}, {}} // same as [2]PPoint{PPoint(&Point{1.5, -3.5}), PPoint(&Point{})} -

    -A parsing ambiguity arises when a composite literal using the -TypeName form of the LiteralType appears as an operand between the -keyword and the opening brace of the block -of an "if", "for", or "switch" statement, and the composite literal -is not enclosed in parentheses, square brackets, or curly braces. -In this rare case, the opening brace of the literal is erroneously parsed -as the one introducing the block of statements. To resolve the ambiguity, -the composite literal must appear within parentheses. -

    - -
    -if x == (T{a,b,c}[i]) { … }
    -if (x == T{a,b,c}[i]) { … }
    -
    -

    Examples of valid array, slice, and map literals:

    -- cgit v1.3 From df6c351aa4bbc8805406bfef979e62f59fc76da9 Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Fri, 9 Jan 2026 19:01:50 +0100 Subject: crypto: use testenv.Executable(t) instead of os.Args[0] in tests Change-Id: Ib0ec1f05e51a4295a9369d6e8c6b61976a6a6964 Reviewed-on: https://go-review.googlesource.com/c/go/+/735260 LUCI-TryBot-Result: Go LUCI Reviewed-by: Junyang Shao Reviewed-by: Daniel McCarney Auto-Submit: Filippo Valsorda Reviewed-by: Michael Pratt --- src/crypto/internal/fips140test/acvp_test.go | 4 ++-- src/crypto/internal/fips140test/check_test.go | 2 +- src/crypto/tls/bogo_shim_test.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/crypto/internal/fips140test/acvp_test.go b/src/crypto/internal/fips140test/acvp_test.go index e94bab74fd..6a0b46af2b 100644 --- a/src/crypto/internal/fips140test/acvp_test.go +++ b/src/crypto/internal/fips140test/acvp_test.go @@ -2146,7 +2146,7 @@ func TestACVP(t *testing.T) { } configPath := filepath.Join(cwd, testConfigFile) t.Logf("running check_expected.go\ncwd: %q\ndata_dir: %q\nconfig: %q\ntool: %q\nmodule-wrapper: %q\n", - cwd, dataDir, configPath, toolPath, os.Args[0]) + cwd, dataDir, configPath, toolPath, testenv.Executable(t)) // Run the check_expected test driver using the acvptool we built, and this test binary as the // module wrapper. The file paths in the config file are specified relative to the dataDir root @@ -2157,7 +2157,7 @@ func TestACVP(t *testing.T) { "-tool", toolPath, // Note: module prefix must match Wrapper value in testConfigFile. - "-module-wrappers", "go:" + os.Args[0], + "-module-wrappers", "go:" + testenv.Executable(t), "-tests", configPath, } cmd = testenv.Command(t, testenv.GoToolPath(t), args...) diff --git a/src/crypto/internal/fips140test/check_test.go b/src/crypto/internal/fips140test/check_test.go index 8aef1f9b9b..d70ffbb77f 100644 --- a/src/crypto/internal/fips140test/check_test.go +++ b/src/crypto/internal/fips140test/check_test.go @@ -46,7 +46,7 @@ func TestIntegrityCheckFailure(t *testing.T) { moduleStatus(t) cryptotest.MustSupportFIPS140(t) - bin, err := os.ReadFile(os.Args[0]) + bin, err := os.ReadFile(testenv.Executable(t)) if err != nil { t.Fatal(err) } diff --git a/src/crypto/tls/bogo_shim_test.go b/src/crypto/tls/bogo_shim_test.go index 1b5fc49c4f..ccac47c271 100644 --- a/src/crypto/tls/bogo_shim_test.go +++ b/src/crypto/tls/bogo_shim_test.go @@ -577,7 +577,7 @@ func TestBogoSuite(t *testing.T) { "test", ".", fmt.Sprintf("-shim-config=%s", filepath.Join(cwd, "bogo_config.json")), - fmt.Sprintf("-shim-path=%s", os.Args[0]), + fmt.Sprintf("-shim-path=%s", testenv.Executable(t)), "-shim-extra-flags=-bogo-mode", "-allow-unimplemented", "-loose-errors", // TODO(roland): this should be removed eventually -- cgit v1.3 From 5741608de26f06488e771fd7b3b35ca2ca4c93a6 Mon Sep 17 00:00:00 2001 From: qmuntal Date: Thu, 8 Jan 2026 10:25:44 +0100 Subject: net: don't ignore errors in TestUnixUnlink TestUnixUnlink calls some functions and methods that can fail, but it ignores the returned errors. This test is flaky on Windows, and those errors should be checked to help diagnose the problem. Updates #75282 Updates #76582 Updates #77038 Change-Id: Ia868762a4c0b94a7255d57add63777568caa6cd2 Reviewed-on: https://go-review.googlesource.com/c/go/+/734720 Reviewed-by: Florian Lehner LUCI-TryBot-Result: Go LUCI Reviewed-by: Damien Neil Reviewed-by: Dmitri Shuralyov --- src/net/unixsock_test.go | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/net/unixsock_test.go b/src/net/unixsock_test.go index f6c5679f42..3e4a14b255 100644 --- a/src/net/unixsock_test.go +++ b/src/net/unixsock_test.go @@ -375,6 +375,17 @@ func TestUnixUnlink(t *testing.T) { } return l.(*UnixListener) } + fileListener := func(t *testing.T, l *UnixListener) (*os.File, Listener) { + f, err := l.File() + if err != nil { + t.Fatal(err) + } + ln, err := FileListener(f) + if err != nil { + t.Fatal(err) + } + return f, ln + } checkExists := func(t *testing.T, desc string) { if _, err := os.Stat(name); err != nil { t.Fatalf("unix socket does not exist %s: %v", desc, err) @@ -397,8 +408,7 @@ func TestUnixUnlink(t *testing.T) { // FileListener should not. t.Run("FileListener", func(t *testing.T) { l := listen(t) - f, _ := l.File() - l1, _ := FileListener(f) + f, l1 := fileListener(t, l) checkExists(t, "after FileListener") f.Close() checkExists(t, "after File close") @@ -444,8 +454,7 @@ func TestUnixUnlink(t *testing.T) { t.Run("FileListener/SetUnlinkOnClose(true)", func(t *testing.T) { l := listen(t) - f, _ := l.File() - l1, _ := FileListener(f) + f, l1 := fileListener(t, l) checkExists(t, "after FileListener") l1.(*UnixListener).SetUnlinkOnClose(true) f.Close() @@ -457,8 +466,7 @@ func TestUnixUnlink(t *testing.T) { t.Run("FileListener/SetUnlinkOnClose(false)", func(t *testing.T) { l := listen(t) - f, _ := l.File() - l1, _ := FileListener(f) + f, l1 := fileListener(t, l) checkExists(t, "after FileListener") l1.(*UnixListener).SetUnlinkOnClose(false) f.Close() -- cgit v1.3 From 30d0b4026410da3486ba841bb7f13c1d9074e91d Mon Sep 17 00:00:00 2001 From: qmuntal Date: Thu, 8 Jan 2026 15:44:51 +0100 Subject: net: don't ignore getsockname errors in newFileFD newFileFD is called when creating a net FD from an existing socket handle. That socket might not be bound yet, in which case getsockname returns a useful error that is currently ignored and replaced with a potentially misleading EPROTONOSUPPORT error later on. Updates #73696 Updates #74976 Updates #75282 Updates #75279 Updates #76537 Updates #76582 Updates #77038 Change-Id: I2a8b30ffbb037035669f65a95a923edc8b288145 Reviewed-on: https://go-review.googlesource.com/c/go/+/734820 LUCI-TryBot-Result: Go LUCI Reviewed-by: Dmitri Shuralyov Reviewed-by: Damien Neil --- src/net/file_posix.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/net/file_posix.go b/src/net/file_posix.go index 132d03e9e3..b28ff5845d 100644 --- a/src/net/file_posix.go +++ b/src/net/file_posix.go @@ -23,7 +23,11 @@ func newFileFD(f *os.File) (*netFD, error) { poll.CloseFunc(s) return nil, os.NewSyscallError("getsockopt", err) } - lsa, _ := syscall.Getsockname(s) + lsa, err := syscall.Getsockname(s) + if err != nil { + poll.CloseFunc(s) + return nil, os.NewSyscallError("getsockname", err) + } rsa, _ := syscall.Getpeername(s) switch lsa.(type) { case *syscall.SockaddrInet4: -- cgit v1.3 From cbe153806e67a16e362a1cdbbf1741d4ce82e98a Mon Sep 17 00:00:00 2001 From: qmuntal Date: Thu, 8 Jan 2026 15:50:15 +0100 Subject: net: fix socket duplication error handling on Windows Calls to dupSocket may fail, but the error is not properly handled because the surrounding code incorrectly checks for nil error instead of non-nil error. I'm not aware of any code paths that would trigger this error, and I haven't been able to create a test case that does so, but this change fixes the error handling to correctly propagate any errors from dupSocket. Change-Id: I5ffd3cbe8ed58a83634f3b97c0878a7c73e0505e Reviewed-on: https://go-review.googlesource.com/c/go/+/734821 Reviewed-by: Dmitri Shuralyov LUCI-TryBot-Result: Go LUCI Reviewed-by: Damien Neil --- src/net/fd_windows.go | 2 +- src/net/file_windows.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/net/fd_windows.go b/src/net/fd_windows.go index 52985be8e6..c28ce045c4 100644 --- a/src/net/fd_windows.go +++ b/src/net/fd_windows.go @@ -248,7 +248,7 @@ func (fd *netFD) dup() (*os.File, error) { err := fd.pfd.RawControl(func(fd uintptr) { h, syserr = dupSocket(syscall.Handle(fd)) }) - if err != nil { + if err == nil { err = syserr } if err != nil { diff --git a/src/net/file_windows.go b/src/net/file_windows.go index b4eb00e564..6a6305035a 100644 --- a/src/net/file_windows.go +++ b/src/net/file_windows.go @@ -39,7 +39,7 @@ func dupFileSocket(f *os.File) (syscall.Handle, error) { err = sc.Control(func(fd uintptr) { h, syserr = dupSocket(syscall.Handle(fd)) }) - if err != nil { + if err == nil { err = syserr } if err != nil { -- cgit v1.3 From b7e6d8b923ad06538c800d635d3ede90d3d0b782 Mon Sep 17 00:00:00 2001 From: Ori Bernstein Date: Sat, 27 Dec 2025 19:08:26 -0500 Subject: os/exec_test: fix test on Plan 9 Error strings vary across OSes when trying to execute a file that does not exist. Since matching them is not the point of the test, ignore them. Fixes #76965 Change-Id: I6d220bc2d0289070f3441adb48983c13b2a3e597 Reviewed-on: https://go-review.googlesource.com/c/go/+/732940 LUCI-TryBot-Result: Go LUCI Reviewed-by: Richard Miller Reviewed-by: Alan Donovan Auto-Submit: Alan Donovan Reviewed-by: Michael Pratt --- src/os/exec/exec_test.go | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/src/os/exec/exec_test.go b/src/os/exec/exec_test.go index bf2f3da535..2746ad8783 100644 --- a/src/os/exec/exec_test.go +++ b/src/os/exec/exec_test.go @@ -1845,23 +1845,13 @@ func TestStart_twice(t *testing.T) { testenv.MustHaveExec(t) cmd := exec.Command("/bin/nonesuch") - for i, want := range []string{ - cond(runtime.GOOS == "windows", - `exec: "/bin/nonesuch": executable file not found in %PATH%`, - "fork/exec /bin/nonesuch: no such file or directory"), - "exec: already started", - } { - err := cmd.Start() - if got := fmt.Sprint(err); got != want { - t.Errorf("Start call #%d return err %q, want %q", i+1, got, want) - } + if err := cmd.Start(); err == nil { + t.Fatalf("running invalid command succeeded") } -} - -func cond[T any](cond bool, t, f T) T { - if cond { - return t - } else { - return f + err := cmd.Start() + got := fmt.Sprint(err) + want := "exec: already started" + if got != want { + t.Fatalf("Start call returned err %q, want %q", got, want) } } -- cgit v1.3 From c16402d15b42cf494774796e606aba66c90d3d6b Mon Sep 17 00:00:00 2001 From: Damien Neil Date: Tue, 6 Jan 2026 15:57:00 -0800 Subject: os/exec: move platform-specific LookPath docs to a common comment We have four different LookPath variations (unix, windows, plan9, wasm), each with slightly different doc comments. Unify the documentation and move it to a single, common LookPath. Change-Id: I56bae57e80887a73ef0f6933258ee0a48dbccdcf Reviewed-on: https://go-review.googlesource.com/c/go/+/734320 Reviewed-by: Roland Shoemaker Reviewed-by: Brad Fitzpatrick LUCI-TryBot-Result: Go LUCI --- src/os/exec/lookpath.go | 30 ++++++++++++++++++++++++++++++ src/os/exec/lp_plan9.go | 11 +---------- src/os/exec/lp_unix.go | 10 +--------- src/os/exec/lp_wasm.go | 2 +- src/os/exec/lp_windows.go | 26 ++++++++------------------ 5 files changed, 41 insertions(+), 38 deletions(-) create mode 100644 src/os/exec/lookpath.go diff --git a/src/os/exec/lookpath.go b/src/os/exec/lookpath.go new file mode 100644 index 0000000000..71f86b994f --- /dev/null +++ b/src/os/exec/lookpath.go @@ -0,0 +1,30 @@ +// Copyright 2026 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 exec + +// LookPath searches for an executable named file in the current path, +// following the conventions of the host operating system. +// If file contains a slash, it is tried directly and the default path is not consulted. +// Otherwise, on success the result is an absolute path. +// +// LookPath returns an error satisfying [errors.Is](err, [ErrDot]) +// if the resolved path is relative to the current directory. +// See the package documentation for more details. +// +// LookPath looks for an executable named file in the +// directories named by the PATH environment variable, +// except as described below. +// +// - On Windows, the file must have an extension named by +// the PATHEXT environment variable. +// When PATHEXT is unset, the file must have +// a ".com", ".exe", ".bat", or ".cmd" extension. +// - On Plan 9, LookPath consults the path environment variable. +// If file begins with "/", "#", "./", or "../", it is tried +// directly and the path is not consulted. +// - On Wasm, LookPath always returns an error. +func LookPath(file string) (string, error) { + return lookPath(file) +} diff --git a/src/os/exec/lp_plan9.go b/src/os/exec/lp_plan9.go index f713a6905c..711aad11bd 100644 --- a/src/os/exec/lp_plan9.go +++ b/src/os/exec/lp_plan9.go @@ -26,16 +26,7 @@ func findExecutable(file string) error { return fs.ErrPermission } -// LookPath searches for an executable named file in the -// directories named by the path environment variable. -// If file begins with "/", "#", "./", or "../", it is tried -// directly and the path is not consulted. -// On success, the result is an absolute path. -// -// In older versions of Go, LookPath could return a path relative to the current directory. -// As of Go 1.19, LookPath will instead return that path along with an error satisfying -// [errors.Is](err, [ErrDot]). See the package documentation for more details. -func LookPath(file string) (string, error) { +func lookPath(file string) (string, error) { if err := validateLookPath(filepath.Clean(file)); err != nil { return "", &Error{file, err} } diff --git a/src/os/exec/lp_unix.go b/src/os/exec/lp_unix.go index e5fddbafe2..d3b10cc43d 100644 --- a/src/os/exec/lp_unix.go +++ b/src/os/exec/lp_unix.go @@ -41,15 +41,7 @@ func findExecutable(file string) error { return fs.ErrPermission } -// LookPath searches for an executable named file in the -// directories named by the PATH environment variable. -// If file contains a slash, it is tried directly and the PATH is not consulted. -// Otherwise, on success, the result is an absolute path. -// -// In older versions of Go, LookPath could return a path relative to the current directory. -// As of Go 1.19, LookPath will instead return that path along with an error satisfying -// [errors.Is](err, [ErrDot]). See the package documentation for more details. -func LookPath(file string) (string, error) { +func lookPath(file string) (string, error) { // NOTE(rsc): I wish we could use the Plan 9 behavior here // (only bypass the path if file begins with / or ./ or ../) // but that would not match all the Unix shells. diff --git a/src/os/exec/lp_wasm.go b/src/os/exec/lp_wasm.go index 3c819049ba..1de9076e53 100644 --- a/src/os/exec/lp_wasm.go +++ b/src/os/exec/lp_wasm.go @@ -17,7 +17,7 @@ var ErrNotFound = errors.New("executable file not found in $PATH") // directories named by the PATH environment variable. // If file contains a slash, it is tried directly and the PATH is not consulted. // The result may be an absolute path or a path relative to the current directory. -func LookPath(file string) (string, error) { +func lookPath(file string) (string, error) { // Wasm can not execute processes, so act as if there are no executables at all. return "", &Error{file, ErrNotFound} } diff --git a/src/os/exec/lp_windows.go b/src/os/exec/lp_windows.go index 74537dec68..f58aabc19f 100644 --- a/src/os/exec/lp_windows.go +++ b/src/os/exec/lp_windows.go @@ -56,22 +56,12 @@ func findExecutable(file string, exts []string) (string, error) { return "", ErrNotFound } -// LookPath searches for an executable named file in the -// directories named by the PATH environment variable. -// LookPath also uses PATHEXT environment variable to match -// a suitable candidate. -// If file contains a slash, it is tried directly and the PATH is not consulted. -// Otherwise, on success, the result is an absolute path. -// -// In older versions of Go, LookPath could return a path relative to the current directory. -// As of Go 1.19, LookPath will instead return that path along with an error satisfying -// [errors.Is](err, [ErrDot]). See the package documentation for more details. -func LookPath(file string) (string, error) { +func lookPath(file string) (string, error) { if err := validateLookPath(file); err != nil { return "", &Error{file, err} } - return lookPath(file, pathExt()) + return lookPathExts(file, pathExt()) } // lookExtensions finds windows executable by its dir and path. @@ -101,17 +91,17 @@ func lookExtensions(path, dir string) (string, error) { } } if dir == "" { - return lookPath(path, exts) + return lookPathExts(path, exts) } if filepath.VolumeName(path) != "" { - return lookPath(path, exts) + return lookPathExts(path, exts) } if len(path) > 1 && os.IsPathSeparator(path[0]) { - return lookPath(path, exts) + return lookPathExts(path, exts) } dirandpath := filepath.Join(dir, path) // We assume that LookPath will only add file extension. - lp, err := lookPath(dirandpath, exts) + lp, err := lookPathExts(dirandpath, exts) if err != nil { return "", err } @@ -138,8 +128,8 @@ func pathExt() []string { return exts } -// lookPath implements LookPath for the given PATHEXT list. -func lookPath(file string, exts []string) (string, error) { +// lookPathExts implements LookPath for the given PATHEXT list. +func lookPathExts(file string, exts []string) (string, error) { if strings.ContainsAny(file, `:\/`) { f, err := findExecutable(file, exts) if err == nil { -- cgit v1.3 From 7f6418bb4e44b1b11d428d402dd6935a2a1ea335 Mon Sep 17 00:00:00 2001 From: cuishuang Date: Wed, 7 Jan 2026 13:46:43 +0800 Subject: all: fix misspellings in comments Change-Id: I121847e7f68c602dd8e9ecddfc41b547f8a86f10 Reviewed-on: https://go-review.googlesource.com/c/go/+/734361 LUCI-TryBot-Result: Go LUCI Reviewed-by: Robert Griesemer Reviewed-by: Junyang Shao --- src/cmd/compile/internal/ssagen/ssa.go | 2 +- src/simd/archsimd/_gen/simdgen/gen_simdMachineOps.go | 2 +- src/simd/archsimd/_gen/simdgen/gen_simdssa.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index 33fcf979c5..dd5baa0ed5 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -7795,7 +7795,7 @@ func AddrAuto(a *obj.Addr, v *ssa.Value) { // Call returns a new CALL instruction for the SSA value v. // It uses PrepareCall to prepare the call. func (s *State) Call(v *ssa.Value) *obj.Prog { - pPosIsStmt := s.pp.Pos.IsStmt() // The statement-ness fo the call comes from ssaGenState + pPosIsStmt := s.pp.Pos.IsStmt() // The statement-ness of the call comes from ssaGenState s.PrepareCall(v) p := s.Prog(obj.ACALL) diff --git a/src/simd/archsimd/_gen/simdgen/gen_simdMachineOps.go b/src/simd/archsimd/_gen/simdgen/gen_simdMachineOps.go index 3d99dd2a81..94b122ac39 100644 --- a/src/simd/archsimd/_gen/simdgen/gen_simdMachineOps.go +++ b/src/simd/archsimd/_gen/simdgen/gen_simdMachineOps.go @@ -181,7 +181,7 @@ func writeSIMDMachineOps(ops []Operation) *bytes.Buffer { } hasMerging = gOp.hasMaskedMerging(maskType, shapeOut) if hasMerging && !resultInArg0 { - // We have to copy the slice here becasue the sort will be visible from other + // We have to copy the slice here because the sort will be visible from other // aliases when no reslicing is happening. newIn := make([]Operand, len(op.In), len(op.In)+1) copy(newIn, op.In) diff --git a/src/simd/archsimd/_gen/simdgen/gen_simdssa.go b/src/simd/archsimd/_gen/simdgen/gen_simdssa.go index 876ffabe3d..96d096688f 100644 --- a/src/simd/archsimd/_gen/simdgen/gen_simdssa.go +++ b/src/simd/archsimd/_gen/simdgen/gen_simdssa.go @@ -133,7 +133,7 @@ func writeSIMDSSA(ops []Operation) *bytes.Buffer { if mem == NoMem && op.hasMaskedMerging(maskType, shapeOut) { regShapeMerging := regShape if shapeOut != OneVregOutAtIn { - // We have to copy the slice here becasue the sort will be visible from other + // We have to copy the slice here because the sort will be visible from other // aliases when no reslicing is happening. newIn := make([]Operand, len(op.In), len(op.In)+1) copy(newIn, op.In) -- cgit v1.3 From e2fef50def98b87107ab963f657d43d7869b8463 Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Mon, 12 Jan 2026 14:37:39 -0500 Subject: runtime: rename mallocTiny* to mallocgcTinySize* This makes it easier to identify which functions are used for memory allocation by looking for functions that start with mallocgc. The Size suffix is added so that the isSpecializedMalloc function in cmd/compile/internal/ssa can distinguish between the generated functions and the mallocgcTiny function called by mallocgc, similar to the SC suffixes for the mallocgcSmallNoScanSC* and mallocgcSmallScanNoHeaderSC* functons. Change-Id: I6ad7f15617bf6f18ae5d1bfa2a0b94e86a6a6964 Reviewed-on: https://go-review.googlesource.com/c/go/+/735780 Reviewed-by: Michael Matloob Reviewed-by: Michael Knyszek LUCI-TryBot-Result: Go LUCI --- src/cmd/compile/internal/ssa/rewrite.go | 2 +- src/cmd/compile/internal/ssagen/ssa.go | 2 +- src/runtime/_mkmalloc/mkmalloc.go | 2 +- src/runtime/malloc_generated.go | 30 +++++++++++++++--------------- src/runtime/malloc_tables_generated.go | 30 +++++++++++++++--------------- test/codegen/strings.go | 2 +- test/live.go | 4 ++-- test/live_regabi.go | 4 ++-- 8 files changed, 38 insertions(+), 38 deletions(-) diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go index af2568ae89..032915f701 100644 --- a/src/cmd/compile/internal/ssa/rewrite.go +++ b/src/cmd/compile/internal/ssa/rewrite.go @@ -480,7 +480,7 @@ func isSpecializedMalloc(aux Aux) bool { name := fn.String() return strings.HasPrefix(name, "runtime.mallocgcSmallNoScanSC") || strings.HasPrefix(name, "runtime.mallocgcSmallScanNoHeaderSC") || - strings.HasPrefix(name, "runtime.mallocTiny") + strings.HasPrefix(name, "runtime.mallocgcTinySize") } // canLoadUnaligned reports if the architecture supports unaligned load operations. diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index dd5baa0ed5..17feb90df7 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -140,7 +140,7 @@ func InitConfig() { ir.Syms.MallocGCSmallScanNoHeader[i] = typecheck.LookupRuntimeFunc(fmt.Sprintf("mallocgcSmallScanNoHeaderSC%d", i)) } for i := 1; i < len(ir.Syms.MallocGCTiny); i++ { - ir.Syms.MallocGCTiny[i] = typecheck.LookupRuntimeFunc(fmt.Sprintf("mallocTiny%d", i)) + ir.Syms.MallocGCTiny[i] = typecheck.LookupRuntimeFunc(fmt.Sprintf("mallocgcTinySize%d", i)) } ir.Syms.MallocGC = typecheck.LookupRuntimeFunc("mallocgc") ir.Syms.Memmove = typecheck.LookupRuntimeFunc("memmove") diff --git a/src/runtime/_mkmalloc/mkmalloc.go b/src/runtime/_mkmalloc/mkmalloc.go index 434eaad767..450608a7a4 100644 --- a/src/runtime/_mkmalloc/mkmalloc.go +++ b/src/runtime/_mkmalloc/mkmalloc.go @@ -130,7 +130,7 @@ func tinyFuncName(size uintptr) string { if size == 0 || size > smallScanNoHeaderMax { return "mallocPanic" } - return fmt.Sprintf("mallocTiny%d", size) + return fmt.Sprintf("mallocgcTinySize%d", size) } func smallNoScanSCFuncName(sc, scMax uint8) string { diff --git a/src/runtime/malloc_generated.go b/src/runtime/malloc_generated.go index 2be6a5b6f5..8d7112646f 100644 --- a/src/runtime/malloc_generated.go +++ b/src/runtime/malloc_generated.go @@ -4300,7 +4300,7 @@ func mallocgcSmallScanNoHeaderSC26(size uintptr, typ *_type, needzero bool) unsa return x } -func mallocTiny1(size uintptr, typ *_type, needzero bool) unsafe.Pointer { +func mallocgcTinySize1(size uintptr, typ *_type, needzero bool) unsafe.Pointer { gp := getg() if goexperiment.RuntimeSecret && gp.secret > 0 { @@ -4456,7 +4456,7 @@ func mallocTiny1(size uintptr, typ *_type, needzero bool) unsafe.Pointer { return x } -func mallocTiny2(size uintptr, typ *_type, needzero bool) unsafe.Pointer { +func mallocgcTinySize2(size uintptr, typ *_type, needzero bool) unsafe.Pointer { gp := getg() if goexperiment.RuntimeSecret && gp.secret > 0 { @@ -4612,7 +4612,7 @@ func mallocTiny2(size uintptr, typ *_type, needzero bool) unsafe.Pointer { return x } -func mallocTiny3(size uintptr, typ *_type, needzero bool) unsafe.Pointer { +func mallocgcTinySize3(size uintptr, typ *_type, needzero bool) unsafe.Pointer { gp := getg() if goexperiment.RuntimeSecret && gp.secret > 0 { @@ -4768,7 +4768,7 @@ func mallocTiny3(size uintptr, typ *_type, needzero bool) unsafe.Pointer { return x } -func mallocTiny4(size uintptr, typ *_type, needzero bool) unsafe.Pointer { +func mallocgcTinySize4(size uintptr, typ *_type, needzero bool) unsafe.Pointer { gp := getg() if goexperiment.RuntimeSecret && gp.secret > 0 { @@ -4924,7 +4924,7 @@ func mallocTiny4(size uintptr, typ *_type, needzero bool) unsafe.Pointer { return x } -func mallocTiny5(size uintptr, typ *_type, needzero bool) unsafe.Pointer { +func mallocgcTinySize5(size uintptr, typ *_type, needzero bool) unsafe.Pointer { gp := getg() if goexperiment.RuntimeSecret && gp.secret > 0 { @@ -5080,7 +5080,7 @@ func mallocTiny5(size uintptr, typ *_type, needzero bool) unsafe.Pointer { return x } -func mallocTiny6(size uintptr, typ *_type, needzero bool) unsafe.Pointer { +func mallocgcTinySize6(size uintptr, typ *_type, needzero bool) unsafe.Pointer { gp := getg() if goexperiment.RuntimeSecret && gp.secret > 0 { @@ -5236,7 +5236,7 @@ func mallocTiny6(size uintptr, typ *_type, needzero bool) unsafe.Pointer { return x } -func mallocTiny7(size uintptr, typ *_type, needzero bool) unsafe.Pointer { +func mallocgcTinySize7(size uintptr, typ *_type, needzero bool) unsafe.Pointer { gp := getg() if goexperiment.RuntimeSecret && gp.secret > 0 { @@ -5392,7 +5392,7 @@ func mallocTiny7(size uintptr, typ *_type, needzero bool) unsafe.Pointer { return x } -func mallocTiny8(size uintptr, typ *_type, needzero bool) unsafe.Pointer { +func mallocgcTinySize8(size uintptr, typ *_type, needzero bool) unsafe.Pointer { gp := getg() if goexperiment.RuntimeSecret && gp.secret > 0 { @@ -5548,7 +5548,7 @@ func mallocTiny8(size uintptr, typ *_type, needzero bool) unsafe.Pointer { return x } -func mallocTiny9(size uintptr, typ *_type, needzero bool) unsafe.Pointer { +func mallocgcTinySize9(size uintptr, typ *_type, needzero bool) unsafe.Pointer { gp := getg() if goexperiment.RuntimeSecret && gp.secret > 0 { @@ -5704,7 +5704,7 @@ func mallocTiny9(size uintptr, typ *_type, needzero bool) unsafe.Pointer { return x } -func mallocTiny10(size uintptr, typ *_type, needzero bool) unsafe.Pointer { +func mallocgcTinySize10(size uintptr, typ *_type, needzero bool) unsafe.Pointer { gp := getg() if goexperiment.RuntimeSecret && gp.secret > 0 { @@ -5860,7 +5860,7 @@ func mallocTiny10(size uintptr, typ *_type, needzero bool) unsafe.Pointer { return x } -func mallocTiny11(size uintptr, typ *_type, needzero bool) unsafe.Pointer { +func mallocgcTinySize11(size uintptr, typ *_type, needzero bool) unsafe.Pointer { gp := getg() if goexperiment.RuntimeSecret && gp.secret > 0 { @@ -6016,7 +6016,7 @@ func mallocTiny11(size uintptr, typ *_type, needzero bool) unsafe.Pointer { return x } -func mallocTiny12(size uintptr, typ *_type, needzero bool) unsafe.Pointer { +func mallocgcTinySize12(size uintptr, typ *_type, needzero bool) unsafe.Pointer { gp := getg() if goexperiment.RuntimeSecret && gp.secret > 0 { @@ -6172,7 +6172,7 @@ func mallocTiny12(size uintptr, typ *_type, needzero bool) unsafe.Pointer { return x } -func mallocTiny13(size uintptr, typ *_type, needzero bool) unsafe.Pointer { +func mallocgcTinySize13(size uintptr, typ *_type, needzero bool) unsafe.Pointer { gp := getg() if goexperiment.RuntimeSecret && gp.secret > 0 { @@ -6328,7 +6328,7 @@ func mallocTiny13(size uintptr, typ *_type, needzero bool) unsafe.Pointer { return x } -func mallocTiny14(size uintptr, typ *_type, needzero bool) unsafe.Pointer { +func mallocgcTinySize14(size uintptr, typ *_type, needzero bool) unsafe.Pointer { gp := getg() if goexperiment.RuntimeSecret && gp.secret > 0 { @@ -6484,7 +6484,7 @@ func mallocTiny14(size uintptr, typ *_type, needzero bool) unsafe.Pointer { return x } -func mallocTiny15(size uintptr, typ *_type, needzero bool) unsafe.Pointer { +func mallocgcTinySize15(size uintptr, typ *_type, needzero bool) unsafe.Pointer { gp := getg() if goexperiment.RuntimeSecret && gp.secret > 0 { diff --git a/src/runtime/malloc_tables_generated.go b/src/runtime/malloc_tables_generated.go index 36650881fe..b1ddde2aad 100644 --- a/src/runtime/malloc_tables_generated.go +++ b/src/runtime/malloc_tables_generated.go @@ -523,21 +523,21 @@ var mallocScanTable = [513]func(size uintptr, typ *_type, needzero bool) unsafe. var mallocNoScanTable = [513]func(size uintptr, typ *_type, needzero bool) unsafe.Pointer{ mallocPanic, - mallocTiny1, - mallocTiny2, - mallocTiny3, - mallocTiny4, - mallocTiny5, - mallocTiny6, - mallocTiny7, - mallocTiny8, - mallocTiny9, - mallocTiny10, - mallocTiny11, - mallocTiny12, - mallocTiny13, - mallocTiny14, - mallocTiny15, + mallocgcTinySize1, + mallocgcTinySize2, + mallocgcTinySize3, + mallocgcTinySize4, + mallocgcTinySize5, + mallocgcTinySize6, + mallocgcTinySize7, + mallocgcTinySize8, + mallocgcTinySize9, + mallocgcTinySize10, + mallocgcTinySize11, + mallocgcTinySize12, + mallocgcTinySize13, + mallocgcTinySize14, + mallocgcTinySize15, mallocgcSmallNoScanSC2, mallocgcSmallNoScanSC3, mallocgcSmallNoScanSC3, diff --git a/test/codegen/strings.go b/test/codegen/strings.go index 0c5ee2f8f5..1c14021150 100644 --- a/test/codegen/strings.go +++ b/test/codegen/strings.go @@ -23,7 +23,7 @@ func CountBytes(s []byte) int { func ToByteSlice() []byte { // Issue #24698 // amd64:`LEAQ type:\[3\]uint8` - // amd64:`CALL runtime\.(newobject|mallocTiny3)` + // amd64:`CALL runtime\.(newobject|mallocgcTinySize3)` // amd64:-`.*runtime.stringtoslicebyte` return []byte("foo") } diff --git a/test/live.go b/test/live.go index f8ad8df1ca..6561b20925 100644 --- a/test/live.go +++ b/test/live.go @@ -665,14 +665,14 @@ func f39a() (x []int) { func f39b() (x [10]*int) { x = [10]*int{} - x[0] = new(int) // ERROR "live at call to (newobject|mallocTiny[48]): x$" + x[0] = new(int) // ERROR "live at call to (newobject|mallocgcTinySize[48]): x$" printnl() // ERROR "live at call to printnl: x$" return x } func f39c() (x [10]*int) { x = [10]*int{} - x[0] = new(int) // ERROR "live at call to (newobject|mallocTiny[48]): x$" + x[0] = new(int) // ERROR "live at call to (newobject|mallocgcTinySize[48]): x$" printnl() // ERROR "live at call to printnl: x$" return } diff --git a/test/live_regabi.go b/test/live_regabi.go index 9809353f1b..75b842d732 100644 --- a/test/live_regabi.go +++ b/test/live_regabi.go @@ -663,14 +663,14 @@ func f39a() (x []int) { func f39b() (x [10]*int) { x = [10]*int{} - x[0] = new(int) // ERROR "live at call to (newobject|mallocTiny[48]): x$" + x[0] = new(int) // ERROR "live at call to (newobject|mallocgcTinySize[48]): x$" printnl() // ERROR "live at call to printnl: x$" return x } func f39c() (x [10]*int) { x = [10]*int{} - x[0] = new(int) // ERROR "live at call to (newobject|mallocTiny[48]): x$" + x[0] = new(int) // ERROR "live at call to (newobject|mallocgcTinySize[48]): x$" printnl() // ERROR "live at call to printnl: x$" return } -- cgit v1.3 From 9ef1692c93bf96328bcaf7a5c8a46094748da7f3 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Tue, 13 Jan 2026 09:34:53 -0500 Subject: simd/archsimd/_gen/simdgen: feature implications This simplifies our handling of XED features, adds a table of which features imply which other features, and adds this information to the documentation of the CPU features APIs. As part of this we fix an issue around the "AVXAES" feature. AVXAES is defined as the combination of the AVX and AES CPUID flags. Several other features also work like this, but have hand-written logic in internal/cpu to compute logical feature flags from the underlying CPUID bits. For these, we expose a single feature check function from the SIMD API. AVXAES currently doesn't work like this: it requires the user to check both features. However, this forces the SIMD API to expose an "AES" feature check, which really has nothing to do with SIMD. To make this consistent, we introduce an AVXAES feature check function and use it in feature requirement docs. Unlike the others combo features, this is implemented in the simd package, but the difference is invisible to the user. Change-Id: I2985ebd361f0ecd45fd428903efe4c981a5ec65d Reviewed-on: https://go-review.googlesource.com/c/go/+/736100 LUCI-TryBot-Result: Go LUCI Reviewed-by: Cherry Mui Reviewed-by: Junyang Shao Reviewed-on: https://go-review.googlesource.com/c/go/+/736200 Reviewed-by: Austin Clements --- src/simd/archsimd/_gen/simdgen/gen_simdTypes.go | 97 ++++++++++++++++++- src/simd/archsimd/_gen/simdgen/xed.go | 121 +++++++++++++++--------- src/simd/archsimd/cpu.go | 38 ++++++-- src/simd/archsimd/ops_amd64.go | 12 +-- 4 files changed, 205 insertions(+), 63 deletions(-) diff --git a/src/simd/archsimd/_gen/simdgen/gen_simdTypes.go b/src/simd/archsimd/_gen/simdgen/gen_simdTypes.go index dd3a75eb44..4f1c70e211 100644 --- a/src/simd/archsimd/_gen/simdgen/gen_simdTypes.go +++ b/src/simd/archsimd/_gen/simdgen/gen_simdTypes.go @@ -189,6 +189,7 @@ type X86Features struct {} var X86 X86Features {{range .}} +{{$f := .}} {{- if eq .Feature "AVX512"}} // {{.Feature}} returns whether the CPU supports the AVX512F+CD+BW+DQ+VL features. // @@ -199,11 +200,19 @@ var X86 X86Features {{- else -}} // {{.Feature}} returns whether the CPU supports the {{.Feature}} feature. {{- end}} +{{- if ne .ImpliesAll ""}} +// +// If it returns true, then the CPU also supports {{.ImpliesAll}}. +{{- end}} // // {{.Feature}} is defined on all GOARCHes, but will only return true on // GOARCH {{.GoArch}}. -func (X86Features) {{.Feature}}() bool { - return cpu.X86.Has{{.Feature}} +func ({{.FeatureVar}}Features) {{.Feature}}() bool { +{{- if .Virtual}} + return {{range $i, $dep := .Implies}}{{if $i}} && {{end}}cpu.{{$f.FeatureVar}}.Has{{$dep}}{{end}} +{{- else}} + return cpu.{{.FeatureVar}}.Has{{.Feature}} +{{- end}} } {{end}} ` @@ -591,6 +600,65 @@ func writeSIMDTypes(typeMap simdTypeMap) *bytes.Buffer { return buffer } +type goarchFeatures struct { + // featureVar is the name of the exported feature-check variable for this + // architecture. + featureVar string + + // features records per-feature information. + features map[string]featureInfo +} + +type featureInfo struct { + // Implies is a list of other CPU features that are required for this + // feature. These are allowed to chain. + // + // For example, if the Frob feature lists "Baz", then if X.Frob() returns + // true, it must also be true that the CPU has feature Baz. + Implies []string + + // Virtual means this feature is not represented directly in internal/cpu, + // but is instead the logical AND of the features in Implies. + Virtual bool +} + +// goarchFeatureInfo maps from GOARCH to CPU feature to additional information +// about that feature. Not all features need to be in this map. +var goarchFeatureInfo = make(map[string]goarchFeatures) + +func registerFeatureInfo(goArch string, features goarchFeatures) { + goarchFeatureInfo[goArch] = features +} + +func featureImplies(goarch string, base string) string { + // Compute the transitive closure of base. + var list []string + var visit func(f string) + visit = func(f string) { + list = append(list, f) + for _, dep := range goarchFeatureInfo[goarch].features[f].Implies { + visit(dep) + } + } + visit(base) + // Drop base + list = list[1:] + // Put in "nice" order + slices.Reverse(list) + // Combine into a comment-ready form + switch len(list) { + case 0: + return "" + case 1: + return list[0] + case 2: + return list[0] + " and " + list[1] + default: + list[len(list)-1] = "and " + list[len(list)-1] + return strings.Join(list, ", ") + } +} + func writeSIMDFeatures(ops []Operation) *bytes.Buffer { // Gather all features type featureKey struct { @@ -606,13 +674,36 @@ func writeSIMDFeatures(ops []Operation) *bytes.Buffer { featureSet[featureKey{op.GoArch, feature}] = struct{}{} } } - features := slices.SortedFunc(maps.Keys(featureSet), func(a, b featureKey) int { + featureKeys := slices.SortedFunc(maps.Keys(featureSet), func(a, b featureKey) int { if c := cmp.Compare(a.GoArch, b.GoArch); c != 0 { return c } return compareNatural(a.Feature, b.Feature) }) + // TODO: internal/cpu doesn't enforce these at all. You can even do + // GODEBUG=cpu.avx=off and it will happily turn off AVX without turning off + // AVX2. We need to push these dependencies into it somehow. + type feature struct { + featureKey + FeatureVar string + Virtual bool + Implies []string + ImpliesAll string + } + var features []feature + for _, k := range featureKeys { + featureVar := goarchFeatureInfo[k.GoArch].featureVar + fi := goarchFeatureInfo[k.GoArch].features[k.Feature] + features = append(features, feature{ + featureKey: k, + FeatureVar: featureVar, + Virtual: fi.Virtual, + Implies: fi.Implies, + ImpliesAll: featureImplies(k.GoArch, k.Feature), + }) + } + // If we ever have the same feature name on more than one GOARCH, we'll have // to be more careful about this. t := templateOf(simdFeaturesTemplate, "features") diff --git a/src/simd/archsimd/_gen/simdgen/xed.go b/src/simd/archsimd/_gen/simdgen/xed.go index 4ba6738e7e..49bedc9b28 100644 --- a/src/simd/archsimd/_gen/simdgen/xed.go +++ b/src/simd/archsimd/_gen/simdgen/xed.go @@ -5,7 +5,6 @@ package main import ( - "cmp" "fmt" "log" "maps" @@ -210,16 +209,9 @@ func loadXED(xedPath string) []*unify.Value { } log.Printf("%d unhandled CPU features for %d instructions (use -v for details)", len(unknownFeatures), nInst) } else { - keys := slices.SortedFunc(maps.Keys(unknownFeatures), func(a, b cpuFeatureKey) int { - return cmp.Or(cmp.Compare(a.Extension, b.Extension), - cmp.Compare(a.ISASet, b.ISASet)) - }) + keys := slices.Sorted(maps.Keys(unknownFeatures)) for _, key := range keys { - if key.ISASet == "" || key.ISASet == key.Extension { - log.Printf("unhandled Extension %s", key.Extension) - } else { - log.Printf("unhandled Extension %s and ISASet %s", key.Extension, key.ISASet) - } + log.Printf("unhandled ISASet %s", key) log.Printf(" opcodes: %s", slices.Sorted(maps.Keys(unknownFeatures[key]))) } } @@ -763,16 +755,24 @@ func instToUVal1(inst *xeddata.Inst, ops []operand, feature string, variant inst // decodeCPUFeature returns the CPU feature name required by inst. These match // the names of the "Has*" feature checks in the simd package. func decodeCPUFeature(inst *xeddata.Inst) (string, bool) { - key := cpuFeatureKey{ - Extension: inst.Extension, - ISASet: isaSetStrip.ReplaceAllLiteralString(inst.ISASet, ""), + isaSet := inst.ISASet + if isaSet == "" { + // Older instructions don't have an ISA set. Use their "extension" + // instead. + isaSet = inst.Extension + } + // We require AVX512VL to use AVX512 at all, so strip off the vector length + // suffixes. + if strings.HasPrefix(isaSet, "AVX512") { + isaSet = isaSetVL.ReplaceAllLiteralString(isaSet, "") } - feat, ok := cpuFeatureMap[key] + + feat, ok := cpuFeatureMap[isaSet] if !ok { - imap := unknownFeatures[key] + imap := unknownFeatures[isaSet] if imap == nil { imap = make(map[string]struct{}) - unknownFeatures[key] = imap + unknownFeatures[isaSet] = imap } imap[inst.Opcode()] = struct{}{} return "", false @@ -783,45 +783,74 @@ func decodeCPUFeature(inst *xeddata.Inst) (string, bool) { return feat, true } -var isaSetStrip = regexp.MustCompile("_(128N?|256N?|512)$") - -type cpuFeatureKey struct { - Extension, ISASet string -} - -// cpuFeatureMap maps from XED's "EXTENSION" and "ISA_SET" to a CPU feature name -// that can be used in the SIMD API. -var cpuFeatureMap = map[cpuFeatureKey]string{ - {"SHA", "SHA"}: "SHA", +var isaSetVL = regexp.MustCompile("_(128N?|256N?|512)$") - {"AVX", ""}: "AVX", - {"AVX_VNNI", "AVX_VNNI"}: "AVXVNNI", - {"AVX2", ""}: "AVX2", - {"AVXAES", ""}: "AVX, AES", +// cpuFeatureMap maps from XED's "ISA_SET" (or "EXTENSION") to a CPU feature +// name to expose in the SIMD feature check API. +// +// See XED's datafiles/*/cpuid.xed.txt for how ISA set names map to CPUID flags. +var cpuFeatureMap = map[string]string{ + "AVX": "AVX", + "AVX_VNNI": "AVXVNNI", + "AVX2": "AVX2", + "AVXAES": "AVXAES", + "SHA": "SHA", // AVX-512 foundational features. We combine all of these into one "AVX512" feature. - {"AVX512EVEX", "AVX512F"}: "AVX512", - {"AVX512EVEX", "AVX512CD"}: "AVX512", - {"AVX512EVEX", "AVX512BW"}: "AVX512", - {"AVX512EVEX", "AVX512DQ"}: "AVX512", - // AVX512VL doesn't appear explicitly in the ISASet. I guess it's implied by - // the vector length suffix. + "AVX512F": "AVX512", + "AVX512BW": "AVX512", + "AVX512CD": "AVX512", + "AVX512DQ": "AVX512", + // AVX512VL doesn't appear as its own ISASet; instead, the CPUID flag is + // required by the *_128 and *_256 ISASets. We fold it into "AVX512" anyway. // AVX-512 extension features - {"AVX512EVEX", "AVX512_BITALG"}: "AVX512BITALG", - {"AVX512EVEX", "AVX512_GFNI"}: "AVX512GFNI", - {"AVX512EVEX", "AVX512_VBMI2"}: "AVX512VBMI2", - {"AVX512EVEX", "AVX512_VBMI"}: "AVX512VBMI", - {"AVX512EVEX", "AVX512_VNNI"}: "AVX512VNNI", - {"AVX512EVEX", "AVX512_VPOPCNTDQ"}: "AVX512VPOPCNTDQ", - {"AVX512EVEX", "AVX512_VAES"}: "AVX512VAES", - {"AVX512EVEX", "AVX512_VPCLMULQDQ"}: "AVX512VPCLMULQDQ", + "AVX512_BITALG": "AVX512BITALG", + "AVX512_GFNI": "AVX512GFNI", + "AVX512_VBMI": "AVX512VBMI", + "AVX512_VBMI2": "AVX512VBMI2", + "AVX512_VNNI": "AVX512VNNI", + "AVX512_VPOPCNTDQ": "AVX512VPOPCNTDQ", + "AVX512_VAES": "AVX512VAES", + "AVX512_VPCLMULQDQ": "AVX512VPCLMULQDQ", // AVX 10.2 (not yet supported) - {"AVX512EVEX", "AVX10_2_RC"}: "ignore", + "AVX10_2_RC": "ignore", +} + +func init() { + // TODO: In general, Intel doesn't make any guarantees about what flags are + // set, so this means our feature checks need to ensure these, just to be + // sure. + var features = map[string]featureInfo{ + "AVX2": {Implies: []string{"AVX"}}, + "AVX512": {Implies: []string{"AVX2"}}, + + "AVXAES": {Virtual: true, Implies: []string{"AVX", "AES"}}, + + // AVX-512 subfeatures. + "AVX512BITALG": {Implies: []string{"AVX512"}}, + "AVX512GFNI": {Implies: []string{"AVX512"}}, + "AVX512VBMI": {Implies: []string{"AVX512"}}, + "AVX512VBMI2": {Implies: []string{"AVX512"}}, + "AVX512VNNI": {Implies: []string{"AVX512"}}, + "AVX512VPOPCNTDQ": {Implies: []string{"AVX512"}}, + "AVX512VAES": {Implies: []string{"AVX512"}}, + + // AVX-VNNI and AVX-IFMA are "backports" of the AVX512-VNNI/IFMA + // instructions to VEX encoding, limited to 256 bit vectors. They're + // intended for lower end CPUs that want to support VNNI/IFMA without + // supporting AVX-512. As such, they're built on AVX2's VEX encoding. + "AVXVNNI": {Implies: []string{"AVX2"}}, + "AVXIFMA": {Implies: []string{"AVX2"}}, + } + registerFeatureInfo("amd64", goarchFeatures{ + featureVar: "X86", + features: features, + }) } -var unknownFeatures = map[cpuFeatureKey]map[string]struct{}{} +var unknownFeatures = map[string]map[string]struct{}{} // hasOptionalMask returns whether there is an optional mask operand in ops. func hasOptionalMask(ops []operand) bool { diff --git a/src/simd/archsimd/cpu.go b/src/simd/archsimd/cpu.go index d0c0ff5426..1cd765268f 100644 --- a/src/simd/archsimd/cpu.go +++ b/src/simd/archsimd/cpu.go @@ -10,14 +10,6 @@ type X86Features struct{} var X86 X86Features -// AES returns whether the CPU supports the AES feature. -// -// AES is defined on all GOARCHes, but will only return true on -// GOARCH amd64. -func (X86Features) AES() bool { - return cpu.X86.HasAES -} - // AVX returns whether the CPU supports the AVX feature. // // AVX is defined on all GOARCHes, but will only return true on @@ -28,6 +20,8 @@ func (X86Features) AVX() bool { // AVX2 returns whether the CPU supports the AVX2 feature. // +// If it returns true, then the CPU also supports AVX. +// // AVX2 is defined on all GOARCHes, but will only return true on // GOARCH amd64. func (X86Features) AVX2() bool { @@ -41,6 +35,8 @@ func (X86Features) AVX2() bool { // Nearly every CPU that has shipped with any support for AVX-512 has // supported all five of these features. // +// If it returns true, then the CPU also supports AVX and AVX2. +// // AVX512 is defined on all GOARCHes, but will only return true on // GOARCH amd64. func (X86Features) AVX512() bool { @@ -49,6 +45,8 @@ func (X86Features) AVX512() bool { // AVX512BITALG returns whether the CPU supports the AVX512BITALG feature. // +// If it returns true, then the CPU also supports AVX, AVX2, and AVX512. +// // AVX512BITALG is defined on all GOARCHes, but will only return true on // GOARCH amd64. func (X86Features) AVX512BITALG() bool { @@ -57,6 +55,8 @@ func (X86Features) AVX512BITALG() bool { // AVX512GFNI returns whether the CPU supports the AVX512GFNI feature. // +// If it returns true, then the CPU also supports AVX, AVX2, and AVX512. +// // AVX512GFNI is defined on all GOARCHes, but will only return true on // GOARCH amd64. func (X86Features) AVX512GFNI() bool { @@ -65,6 +65,8 @@ func (X86Features) AVX512GFNI() bool { // AVX512VAES returns whether the CPU supports the AVX512VAES feature. // +// If it returns true, then the CPU also supports AVX, AVX2, and AVX512. +// // AVX512VAES is defined on all GOARCHes, but will only return true on // GOARCH amd64. func (X86Features) AVX512VAES() bool { @@ -73,6 +75,8 @@ func (X86Features) AVX512VAES() bool { // AVX512VBMI returns whether the CPU supports the AVX512VBMI feature. // +// If it returns true, then the CPU also supports AVX, AVX2, and AVX512. +// // AVX512VBMI is defined on all GOARCHes, but will only return true on // GOARCH amd64. func (X86Features) AVX512VBMI() bool { @@ -81,6 +85,8 @@ func (X86Features) AVX512VBMI() bool { // AVX512VBMI2 returns whether the CPU supports the AVX512VBMI2 feature. // +// If it returns true, then the CPU also supports AVX, AVX2, and AVX512. +// // AVX512VBMI2 is defined on all GOARCHes, but will only return true on // GOARCH amd64. func (X86Features) AVX512VBMI2() bool { @@ -89,6 +95,8 @@ func (X86Features) AVX512VBMI2() bool { // AVX512VNNI returns whether the CPU supports the AVX512VNNI feature. // +// If it returns true, then the CPU also supports AVX, AVX2, and AVX512. +// // AVX512VNNI is defined on all GOARCHes, but will only return true on // GOARCH amd64. func (X86Features) AVX512VNNI() bool { @@ -105,14 +113,28 @@ func (X86Features) AVX512VPCLMULQDQ() bool { // AVX512VPOPCNTDQ returns whether the CPU supports the AVX512VPOPCNTDQ feature. // +// If it returns true, then the CPU also supports AVX, AVX2, and AVX512. +// // AVX512VPOPCNTDQ is defined on all GOARCHes, but will only return true on // GOARCH amd64. func (X86Features) AVX512VPOPCNTDQ() bool { return cpu.X86.HasAVX512VPOPCNTDQ } +// AVXAES returns whether the CPU supports the AVXAES feature. +// +// If it returns true, then the CPU also supports AES and AVX. +// +// AVXAES is defined on all GOARCHes, but will only return true on +// GOARCH amd64. +func (X86Features) AVXAES() bool { + return cpu.X86.HasAVX && cpu.X86.HasAES +} + // AVXVNNI returns whether the CPU supports the AVXVNNI feature. // +// If it returns true, then the CPU also supports AVX and AVX2. +// // AVXVNNI is defined on all GOARCHes, but will only return true on // GOARCH amd64. func (X86Features) AVXVNNI() bool { diff --git a/src/simd/archsimd/ops_amd64.go b/src/simd/archsimd/ops_amd64.go index bb162c4ff9..d65c7dde0c 100644 --- a/src/simd/archsimd/ops_amd64.go +++ b/src/simd/archsimd/ops_amd64.go @@ -11,7 +11,7 @@ package archsimd // y is the chunk of dw array in use. // result = AddRoundKey(InvShiftRows(InvSubBytes(x)), y) // -// Asm: VAESDECLAST, CPU Feature: AVX, AES +// Asm: VAESDECLAST, CPU Feature: AVXAES func (x Uint8x16) AESDecryptLastRound(y Uint32x4) Uint8x16 // AESDecryptLastRound performs a series of operations in AES cipher algorithm defined in FIPS 197. @@ -37,7 +37,7 @@ func (x Uint8x64) AESDecryptLastRound(y Uint32x16) Uint8x64 // y is the chunk of dw array in use. // result = AddRoundKey(InvMixColumns(InvShiftRows(InvSubBytes(x))), y) // -// Asm: VAESDEC, CPU Feature: AVX, AES +// Asm: VAESDEC, CPU Feature: AVXAES func (x Uint8x16) AESDecryptOneRound(y Uint32x4) Uint8x16 // AESDecryptOneRound performs a series of operations in AES cipher algorithm defined in FIPS 197. @@ -63,7 +63,7 @@ func (x Uint8x64) AESDecryptOneRound(y Uint32x16) Uint8x64 // y is the chunk of w array in use. // result = AddRoundKey((ShiftRows(SubBytes(x))), y) // -// Asm: VAESENCLAST, CPU Feature: AVX, AES +// Asm: VAESENCLAST, CPU Feature: AVXAES func (x Uint8x16) AESEncryptLastRound(y Uint32x4) Uint8x16 // AESEncryptLastRound performs a series of operations in AES cipher algorithm defined in FIPS 197. @@ -89,7 +89,7 @@ func (x Uint8x64) AESEncryptLastRound(y Uint32x16) Uint8x64 // y is the chunk of w array in use. // result = AddRoundKey(MixColumns(ShiftRows(SubBytes(x))), y) // -// Asm: VAESENC, CPU Feature: AVX, AES +// Asm: VAESENC, CPU Feature: AVXAES func (x Uint8x16) AESEncryptOneRound(y Uint32x4) Uint8x16 // AESEncryptOneRound performs a series of operations in AES cipher algorithm defined in FIPS 197. @@ -114,7 +114,7 @@ func (x Uint8x64) AESEncryptOneRound(y Uint32x16) Uint8x64 // x is the chunk of w array in use. // result = InvMixColumns(x) // -// Asm: VAESIMC, CPU Feature: AVX, AES +// Asm: VAESIMC, CPU Feature: AVXAES func (x Uint32x4) AESInvMixColumns() Uint32x4 /* AESRoundKeyGenAssist */ @@ -129,7 +129,7 @@ func (x Uint32x4) AESInvMixColumns() Uint32x4 // // rconVal results in better performance when it's a constant, a non-constant value will be translated into a jump table. // -// Asm: VAESKEYGENASSIST, CPU Feature: AVX, AES +// Asm: VAESKEYGENASSIST, CPU Feature: AVXAES func (x Uint32x4) AESRoundKeyGenAssist(rconVal uint8) Uint32x4 /* Abs */ -- cgit v1.3 From e2429619605951b137e25f6a51fbc39d9f0f1e9b Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Tue, 13 Jan 2026 14:18:14 -0500 Subject: simd/archsimd: 128- and 256-bit FMA operations do not require AVX-512 Currently, all FMA operations are marked as requiring AVX512, even on smaller vector widths. This is happening because the narrower FMA operations are marked as extension "FMA" in the XED. Since this extension doesn't start with "AVX", we filter them out very early in the XED process. However, this is just a quirk of naming: the FMA feature depends on the AVX feature, so it is part of AVX, even if it doesn't say so on the tin. Fix this by accepting the FMA extension and adding FMA to the table of CPU features. We also tweak internal/cpu slightly do it correctly enforces that the logical FMA feature depends on both the FMA and AVX CPUID flags. This actually *deletes* a lot of generated code because we no longer need the AVX-512 encoding of these 128- and 256-bit operations. Change-Id: I744a18d0be888f536ac034fe88b110347622be7e Reviewed-on: https://go-review.googlesource.com/c/go/+/736160 Auto-Submit: Austin Clements Reviewed-by: Junyang Shao LUCI-TryBot-Result: Go LUCI Reviewed-on: https://go-review.googlesource.com/c/go/+/736201 Reviewed-by: Austin Clements --- src/cmd/compile/internal/amd64/simdssa.go | 12 - src/cmd/compile/internal/ssa/_gen/simdAMD64.rules | 12 - src/cmd/compile/internal/ssa/_gen/simdAMD64ops.go | 36 +-- src/cmd/compile/internal/ssa/opGen.go | 324 +++---------------- src/cmd/compile/internal/ssa/rewriteAMD64.go | 372 ---------------------- src/internal/cpu/cpu_x86.go | 14 +- src/simd/archsimd/_gen/simdgen/xed.go | 4 +- src/simd/archsimd/cpu.go | 10 + src/simd/archsimd/ops_amd64.go | 24 +- 9 files changed, 93 insertions(+), 715 deletions(-) diff --git a/src/cmd/compile/internal/amd64/simdssa.go b/src/cmd/compile/internal/amd64/simdssa.go index a028cbe86d..ea33808a1c 100644 --- a/src/cmd/compile/internal/amd64/simdssa.go +++ b/src/cmd/compile/internal/amd64/simdssa.go @@ -1959,23 +1959,11 @@ func ssaGenSIMDValue(s *ssagen.State, v *ssa.Value) bool { ssa.OpAMD64VPERMI2Q256load, ssa.OpAMD64VPERMI2PD512load, ssa.OpAMD64VPERMI2Q512load, - ssa.OpAMD64VFMADD213PS128load, - ssa.OpAMD64VFMADD213PS256load, ssa.OpAMD64VFMADD213PS512load, - ssa.OpAMD64VFMADD213PD128load, - ssa.OpAMD64VFMADD213PD256load, ssa.OpAMD64VFMADD213PD512load, - ssa.OpAMD64VFMADDSUB213PS128load, - ssa.OpAMD64VFMADDSUB213PS256load, ssa.OpAMD64VFMADDSUB213PS512load, - ssa.OpAMD64VFMADDSUB213PD128load, - ssa.OpAMD64VFMADDSUB213PD256load, ssa.OpAMD64VFMADDSUB213PD512load, - ssa.OpAMD64VFMSUBADD213PS128load, - ssa.OpAMD64VFMSUBADD213PS256load, ssa.OpAMD64VFMSUBADD213PS512load, - ssa.OpAMD64VFMSUBADD213PD128load, - ssa.OpAMD64VFMSUBADD213PD256load, ssa.OpAMD64VFMSUBADD213PD512load, ssa.OpAMD64VPSHLDVD128load, ssa.OpAMD64VPSHLDVD256load, diff --git a/src/cmd/compile/internal/ssa/_gen/simdAMD64.rules b/src/cmd/compile/internal/ssa/_gen/simdAMD64.rules index 799461610d..63b37f99cb 100644 --- a/src/cmd/compile/internal/ssa/_gen/simdAMD64.rules +++ b/src/cmd/compile/internal/ssa/_gen/simdAMD64.rules @@ -2771,11 +2771,7 @@ (VPMULLQ128 x l:(VMOVDQUload128 {sym} [off] ptr mem)) && canMergeLoad(v, l) && clobber(l) => (VPMULLQ128load {sym} [off] x ptr mem) (VPMULLQ256 x l:(VMOVDQUload256 {sym} [off] ptr mem)) && canMergeLoad(v, l) && clobber(l) => (VPMULLQ256load {sym} [off] x ptr mem) (VPMULLQ512 x l:(VMOVDQUload512 {sym} [off] ptr mem)) && canMergeLoad(v, l) && clobber(l) => (VPMULLQ512load {sym} [off] x ptr mem) -(VFMADD213PS128 x y l:(VMOVDQUload128 {sym} [off] ptr mem)) && canMergeLoad(v, l) && clobber(l) => (VFMADD213PS128load {sym} [off] x y ptr mem) -(VFMADD213PS256 x y l:(VMOVDQUload256 {sym} [off] ptr mem)) && canMergeLoad(v, l) && clobber(l) => (VFMADD213PS256load {sym} [off] x y ptr mem) (VFMADD213PS512 x y l:(VMOVDQUload512 {sym} [off] ptr mem)) && canMergeLoad(v, l) && clobber(l) => (VFMADD213PS512load {sym} [off] x y ptr mem) -(VFMADD213PD128 x y l:(VMOVDQUload128 {sym} [off] ptr mem)) && canMergeLoad(v, l) && clobber(l) => (VFMADD213PD128load {sym} [off] x y ptr mem) -(VFMADD213PD256 x y l:(VMOVDQUload256 {sym} [off] ptr mem)) && canMergeLoad(v, l) && clobber(l) => (VFMADD213PD256load {sym} [off] x y ptr mem) (VFMADD213PD512 x y l:(VMOVDQUload512 {sym} [off] ptr mem)) && canMergeLoad(v, l) && clobber(l) => (VFMADD213PD512load {sym} [off] x y ptr mem) (VFMADD213PSMasked128 x y l:(VMOVDQUload128 {sym} [off] ptr mem) mask) && canMergeLoad(v, l) && clobber(l) => (VFMADD213PSMasked128load {sym} [off] x y ptr mask mem) (VFMADD213PSMasked256 x y l:(VMOVDQUload256 {sym} [off] ptr mem) mask) && canMergeLoad(v, l) && clobber(l) => (VFMADD213PSMasked256load {sym} [off] x y ptr mask mem) @@ -2783,11 +2779,7 @@ (VFMADD213PDMasked128 x y l:(VMOVDQUload128 {sym} [off] ptr mem) mask) && canMergeLoad(v, l) && clobber(l) => (VFMADD213PDMasked128load {sym} [off] x y ptr mask mem) (VFMADD213PDMasked256 x y l:(VMOVDQUload256 {sym} [off] ptr mem) mask) && canMergeLoad(v, l) && clobber(l) => (VFMADD213PDMasked256load {sym} [off] x y ptr mask mem) (VFMADD213PDMasked512 x y l:(VMOVDQUload512 {sym} [off] ptr mem) mask) && canMergeLoad(v, l) && clobber(l) => (VFMADD213PDMasked512load {sym} [off] x y ptr mask mem) -(VFMADDSUB213PS128 x y l:(VMOVDQUload128 {sym} [off] ptr mem)) && canMergeLoad(v, l) && clobber(l) => (VFMADDSUB213PS128load {sym} [off] x y ptr mem) -(VFMADDSUB213PS256 x y l:(VMOVDQUload256 {sym} [off] ptr mem)) && canMergeLoad(v, l) && clobber(l) => (VFMADDSUB213PS256load {sym} [off] x y ptr mem) (VFMADDSUB213PS512 x y l:(VMOVDQUload512 {sym} [off] ptr mem)) && canMergeLoad(v, l) && clobber(l) => (VFMADDSUB213PS512load {sym} [off] x y ptr mem) -(VFMADDSUB213PD128 x y l:(VMOVDQUload128 {sym} [off] ptr mem)) && canMergeLoad(v, l) && clobber(l) => (VFMADDSUB213PD128load {sym} [off] x y ptr mem) -(VFMADDSUB213PD256 x y l:(VMOVDQUload256 {sym} [off] ptr mem)) && canMergeLoad(v, l) && clobber(l) => (VFMADDSUB213PD256load {sym} [off] x y ptr mem) (VFMADDSUB213PD512 x y l:(VMOVDQUload512 {sym} [off] ptr mem)) && canMergeLoad(v, l) && clobber(l) => (VFMADDSUB213PD512load {sym} [off] x y ptr mem) (VFMADDSUB213PSMasked128 x y l:(VMOVDQUload128 {sym} [off] ptr mem) mask) && canMergeLoad(v, l) && clobber(l) => (VFMADDSUB213PSMasked128load {sym} [off] x y ptr mask mem) (VFMADDSUB213PSMasked256 x y l:(VMOVDQUload256 {sym} [off] ptr mem) mask) && canMergeLoad(v, l) && clobber(l) => (VFMADDSUB213PSMasked256load {sym} [off] x y ptr mask mem) @@ -2807,11 +2799,7 @@ (VPMULLQMasked128 x l:(VMOVDQUload128 {sym} [off] ptr mem) mask) && canMergeLoad(v, l) && clobber(l) => (VPMULLQMasked128load {sym} [off] x ptr mask mem) (VPMULLQMasked256 x l:(VMOVDQUload256 {sym} [off] ptr mem) mask) && canMergeLoad(v, l) && clobber(l) => (VPMULLQMasked256load {sym} [off] x ptr mask mem) (VPMULLQMasked512 x l:(VMOVDQUload512 {sym} [off] ptr mem) mask) && canMergeLoad(v, l) && clobber(l) => (VPMULLQMasked512load {sym} [off] x ptr mask mem) -(VFMSUBADD213PS128 x y l:(VMOVDQUload128 {sym} [off] ptr mem)) && canMergeLoad(v, l) && clobber(l) => (VFMSUBADD213PS128load {sym} [off] x y ptr mem) -(VFMSUBADD213PS256 x y l:(VMOVDQUload256 {sym} [off] ptr mem)) && canMergeLoad(v, l) && clobber(l) => (VFMSUBADD213PS256load {sym} [off] x y ptr mem) (VFMSUBADD213PS512 x y l:(VMOVDQUload512 {sym} [off] ptr mem)) && canMergeLoad(v, l) && clobber(l) => (VFMSUBADD213PS512load {sym} [off] x y ptr mem) -(VFMSUBADD213PD128 x y l:(VMOVDQUload128 {sym} [off] ptr mem)) && canMergeLoad(v, l) && clobber(l) => (VFMSUBADD213PD128load {sym} [off] x y ptr mem) -(VFMSUBADD213PD256 x y l:(VMOVDQUload256 {sym} [off] ptr mem)) && canMergeLoad(v, l) && clobber(l) => (VFMSUBADD213PD256load {sym} [off] x y ptr mem) (VFMSUBADD213PD512 x y l:(VMOVDQUload512 {sym} [off] ptr mem)) && canMergeLoad(v, l) && clobber(l) => (VFMSUBADD213PD512load {sym} [off] x y ptr mem) (VFMSUBADD213PSMasked128 x y l:(VMOVDQUload128 {sym} [off] ptr mem) mask) && canMergeLoad(v, l) && clobber(l) => (VFMSUBADD213PSMasked128load {sym} [off] x y ptr mask mem) (VFMSUBADD213PSMasked256 x y l:(VMOVDQUload256 {sym} [off] ptr mem) mask) && canMergeLoad(v, l) && clobber(l) => (VFMSUBADD213PSMasked256load {sym} [off] x y ptr mask mem) diff --git a/src/cmd/compile/internal/ssa/_gen/simdAMD64ops.go b/src/cmd/compile/internal/ssa/_gen/simdAMD64ops.go index 648e372fb4..339ec7fce3 100644 --- a/src/cmd/compile/internal/ssa/_gen/simdAMD64ops.go +++ b/src/cmd/compile/internal/ssa/_gen/simdAMD64ops.go @@ -172,38 +172,38 @@ func simdAMD64Ops(v11, v21, v2k, vkv, v2kv, v2kk, v31, v3kv, vgpv, vgp, vfpv, vf {name: "VEXPANDPSMasked128", argLength: 2, reg: wkw, asm: "VEXPANDPS", commutative: false, typ: "Vec128", resultInArg0: false}, {name: "VEXPANDPSMasked256", argLength: 2, reg: wkw, asm: "VEXPANDPS", commutative: false, typ: "Vec256", resultInArg0: false}, {name: "VEXPANDPSMasked512", argLength: 2, reg: wkw, asm: "VEXPANDPS", commutative: false, typ: "Vec512", resultInArg0: false}, - {name: "VFMADD213PD128", argLength: 3, reg: w31, asm: "VFMADD213PD", commutative: false, typ: "Vec128", resultInArg0: true}, - {name: "VFMADD213PD256", argLength: 3, reg: w31, asm: "VFMADD213PD", commutative: false, typ: "Vec256", resultInArg0: true}, + {name: "VFMADD213PD128", argLength: 3, reg: v31, asm: "VFMADD213PD", commutative: false, typ: "Vec128", resultInArg0: true}, + {name: "VFMADD213PD256", argLength: 3, reg: v31, asm: "VFMADD213PD", commutative: false, typ: "Vec256", resultInArg0: true}, {name: "VFMADD213PD512", argLength: 3, reg: w31, asm: "VFMADD213PD", commutative: false, typ: "Vec512", resultInArg0: true}, {name: "VFMADD213PDMasked128", argLength: 4, reg: w3kw, asm: "VFMADD213PD", commutative: false, typ: "Vec128", resultInArg0: true}, {name: "VFMADD213PDMasked256", argLength: 4, reg: w3kw, asm: "VFMADD213PD", commutative: false, typ: "Vec256", resultInArg0: true}, {name: "VFMADD213PDMasked512", argLength: 4, reg: w3kw, asm: "VFMADD213PD", commutative: false, typ: "Vec512", resultInArg0: true}, - {name: "VFMADD213PS128", argLength: 3, reg: w31, asm: "VFMADD213PS", commutative: false, typ: "Vec128", resultInArg0: true}, - {name: "VFMADD213PS256", argLength: 3, reg: w31, asm: "VFMADD213PS", commutative: false, typ: "Vec256", resultInArg0: true}, + {name: "VFMADD213PS128", argLength: 3, reg: v31, asm: "VFMADD213PS", commutative: false, typ: "Vec128", resultInArg0: true}, + {name: "VFMADD213PS256", argLength: 3, reg: v31, asm: "VFMADD213PS", commutative: false, typ: "Vec256", resultInArg0: true}, {name: "VFMADD213PS512", argLength: 3, reg: w31, asm: "VFMADD213PS", commutative: false, typ: "Vec512", resultInArg0: true}, {name: "VFMADD213PSMasked128", argLength: 4, reg: w3kw, asm: "VFMADD213PS", commutative: false, typ: "Vec128", resultInArg0: true}, {name: "VFMADD213PSMasked256", argLength: 4, reg: w3kw, asm: "VFMADD213PS", commutative: false, typ: "Vec256", resultInArg0: true}, {name: "VFMADD213PSMasked512", argLength: 4, reg: w3kw, asm: "VFMADD213PS", commutative: false, typ: "Vec512", resultInArg0: true}, - {name: "VFMADDSUB213PD128", argLength: 3, reg: w31, asm: "VFMADDSUB213PD", commutative: false, typ: "Vec128", resultInArg0: true}, - {name: "VFMADDSUB213PD256", argLength: 3, reg: w31, asm: "VFMADDSUB213PD", commutative: false, typ: "Vec256", resultInArg0: true}, + {name: "VFMADDSUB213PD128", argLength: 3, reg: v31, asm: "VFMADDSUB213PD", commutative: false, typ: "Vec128", resultInArg0: true}, + {name: "VFMADDSUB213PD256", argLength: 3, reg: v31, asm: "VFMADDSUB213PD", commutative: false, typ: "Vec256", resultInArg0: true}, {name: "VFMADDSUB213PD512", argLength: 3, reg: w31, asm: "VFMADDSUB213PD", commutative: false, typ: "Vec512", resultInArg0: true}, {name: "VFMADDSUB213PDMasked128", argLength: 4, reg: w3kw, asm: "VFMADDSUB213PD", commutative: false, typ: "Vec128", resultInArg0: true}, {name: "VFMADDSUB213PDMasked256", argLength: 4, reg: w3kw, asm: "VFMADDSUB213PD", commutative: false, typ: "Vec256", resultInArg0: true}, {name: "VFMADDSUB213PDMasked512", argLength: 4, reg: w3kw, asm: "VFMADDSUB213PD", commutative: false, typ: "Vec512", resultInArg0: true}, - {name: "VFMADDSUB213PS128", argLength: 3, reg: w31, asm: "VFMADDSUB213PS", commutative: false, typ: "Vec128", resultInArg0: true}, - {name: "VFMADDSUB213PS256", argLength: 3, reg: w31, asm: "VFMADDSUB213PS", commutative: false, typ: "Vec256", resultInArg0: true}, + {name: "VFMADDSUB213PS128", argLength: 3, reg: v31, asm: "VFMADDSUB213PS", commutative: false, typ: "Vec128", resultInArg0: true}, + {name: "VFMADDSUB213PS256", argLength: 3, reg: v31, asm: "VFMADDSUB213PS", commutative: false, typ: "Vec256", resultInArg0: true}, {name: "VFMADDSUB213PS512", argLength: 3, reg: w31, asm: "VFMADDSUB213PS", commutative: false, typ: "Vec512", resultInArg0: true}, {name: "VFMADDSUB213PSMasked128", argLength: 4, reg: w3kw, asm: "VFMADDSUB213PS", commutative: false, typ: "Vec128", resultInArg0: true}, {name: "VFMADDSUB213PSMasked256", argLength: 4, reg: w3kw, asm: "VFMADDSUB213PS", commutative: false, typ: "Vec256", resultInArg0: true}, {name: "VFMADDSUB213PSMasked512", argLength: 4, reg: w3kw, asm: "VFMADDSUB213PS", commutative: false, typ: "Vec512", resultInArg0: true}, - {name: "VFMSUBADD213PD128", argLength: 3, reg: w31, asm: "VFMSUBADD213PD", commutative: false, typ: "Vec128", resultInArg0: true}, - {name: "VFMSUBADD213PD256", argLength: 3, reg: w31, asm: "VFMSUBADD213PD", commutative: false, typ: "Vec256", resultInArg0: true}, + {name: "VFMSUBADD213PD128", argLength: 3, reg: v31, asm: "VFMSUBADD213PD", commutative: false, typ: "Vec128", resultInArg0: true}, + {name: "VFMSUBADD213PD256", argLength: 3, reg: v31, asm: "VFMSUBADD213PD", commutative: false, typ: "Vec256", resultInArg0: true}, {name: "VFMSUBADD213PD512", argLength: 3, reg: w31, asm: "VFMSUBADD213PD", commutative: false, typ: "Vec512", resultInArg0: true}, {name: "VFMSUBADD213PDMasked128", argLength: 4, reg: w3kw, asm: "VFMSUBADD213PD", commutative: false, typ: "Vec128", resultInArg0: true}, {name: "VFMSUBADD213PDMasked256", argLength: 4, reg: w3kw, asm: "VFMSUBADD213PD", commutative: false, typ: "Vec256", resultInArg0: true}, {name: "VFMSUBADD213PDMasked512", argLength: 4, reg: w3kw, asm: "VFMSUBADD213PD", commutative: false, typ: "Vec512", resultInArg0: true}, - {name: "VFMSUBADD213PS128", argLength: 3, reg: w31, asm: "VFMSUBADD213PS", commutative: false, typ: "Vec128", resultInArg0: true}, - {name: "VFMSUBADD213PS256", argLength: 3, reg: w31, asm: "VFMSUBADD213PS", commutative: false, typ: "Vec256", resultInArg0: true}, + {name: "VFMSUBADD213PS128", argLength: 3, reg: v31, asm: "VFMSUBADD213PS", commutative: false, typ: "Vec128", resultInArg0: true}, + {name: "VFMSUBADD213PS256", argLength: 3, reg: v31, asm: "VFMSUBADD213PS", commutative: false, typ: "Vec256", resultInArg0: true}, {name: "VFMSUBADD213PS512", argLength: 3, reg: w31, asm: "VFMSUBADD213PS", commutative: false, typ: "Vec512", resultInArg0: true}, {name: "VFMSUBADD213PSMasked128", argLength: 4, reg: w3kw, asm: "VFMSUBADD213PS", commutative: false, typ: "Vec128", resultInArg0: true}, {name: "VFMSUBADD213PSMasked256", argLength: 4, reg: w3kw, asm: "VFMSUBADD213PS", commutative: false, typ: "Vec256", resultInArg0: true}, @@ -1594,38 +1594,26 @@ func simdAMD64Ops(v11, v21, v2k, vkv, v2kv, v2kk, v31, v3kv, vgpv, vgp, vfpv, vf {name: "VDIVPSMasked128load", argLength: 4, reg: w2kwload, asm: "VDIVPS", commutative: false, typ: "Vec128", aux: "SymOff", symEffect: "Read", resultInArg0: false}, {name: "VDIVPSMasked256load", argLength: 4, reg: w2kwload, asm: "VDIVPS", commutative: false, typ: "Vec256", aux: "SymOff", symEffect: "Read", resultInArg0: false}, {name: "VDIVPSMasked512load", argLength: 4, reg: w2kwload, asm: "VDIVPS", commutative: false, typ: "Vec512", aux: "SymOff", symEffect: "Read", resultInArg0: false}, - {name: "VFMADD213PD128load", argLength: 4, reg: w31load, asm: "VFMADD213PD", commutative: false, typ: "Vec128", aux: "SymOff", symEffect: "Read", resultInArg0: true}, - {name: "VFMADD213PD256load", argLength: 4, reg: w31load, asm: "VFMADD213PD", commutative: false, typ: "Vec256", aux: "SymOff", symEffect: "Read", resultInArg0: true}, {name: "VFMADD213PD512load", argLength: 4, reg: w31load, asm: "VFMADD213PD", commutative: false, typ: "Vec512", aux: "SymOff", symEffect: "Read", resultInArg0: true}, {name: "VFMADD213PDMasked128load", argLength: 5, reg: w3kwload, asm: "VFMADD213PD", commutative: false, typ: "Vec128", aux: "SymOff", symEffect: "Read", resultInArg0: true}, {name: "VFMADD213PDMasked256load", argLength: 5, reg: w3kwload, asm: "VFMADD213PD", commutative: false, typ: "Vec256", aux: "SymOff", symEffect: "Read", resultInArg0: true}, {name: "VFMADD213PDMasked512load", argLength: 5, reg: w3kwload, asm: "VFMADD213PD", commutative: false, typ: "Vec512", aux: "SymOff", symEffect: "Read", resultInArg0: true}, - {name: "VFMADD213PS128load", argLength: 4, reg: w31load, asm: "VFMADD213PS", commutative: false, typ: "Vec128", aux: "SymOff", symEffect: "Read", resultInArg0: true}, - {name: "VFMADD213PS256load", argLength: 4, reg: w31load, asm: "VFMADD213PS", commutative: false, typ: "Vec256", aux: "SymOff", symEffect: "Read", resultInArg0: true}, {name: "VFMADD213PS512load", argLength: 4, reg: w31load, asm: "VFMADD213PS", commutative: false, typ: "Vec512", aux: "SymOff", symEffect: "Read", resultInArg0: true}, {name: "VFMADD213PSMasked128load", argLength: 5, reg: w3kwload, asm: "VFMADD213PS", commutative: false, typ: "Vec128", aux: "SymOff", symEffect: "Read", resultInArg0: true}, {name: "VFMADD213PSMasked256load", argLength: 5, reg: w3kwload, asm: "VFMADD213PS", commutative: false, typ: "Vec256", aux: "SymOff", symEffect: "Read", resultInArg0: true}, {name: "VFMADD213PSMasked512load", argLength: 5, reg: w3kwload, asm: "VFMADD213PS", commutative: false, typ: "Vec512", aux: "SymOff", symEffect: "Read", resultInArg0: true}, - {name: "VFMADDSUB213PD128load", argLength: 4, reg: w31load, asm: "VFMADDSUB213PD", commutative: false, typ: "Vec128", aux: "SymOff", symEffect: "Read", resultInArg0: true}, - {name: "VFMADDSUB213PD256load", argLength: 4, reg: w31load, asm: "VFMADDSUB213PD", commutative: false, typ: "Vec256", aux: "SymOff", symEffect: "Read", resultInArg0: true}, {name: "VFMADDSUB213PD512load", argLength: 4, reg: w31load, asm: "VFMADDSUB213PD", commutative: false, typ: "Vec512", aux: "SymOff", symEffect: "Read", resultInArg0: true}, {name: "VFMADDSUB213PDMasked128load", argLength: 5, reg: w3kwload, asm: "VFMADDSUB213PD", commutative: false, typ: "Vec128", aux: "SymOff", symEffect: "Read", resultInArg0: true}, {name: "VFMADDSUB213PDMasked256load", argLength: 5, reg: w3kwload, asm: "VFMADDSUB213PD", commutative: false, typ: "Vec256", aux: "SymOff", symEffect: "Read", resultInArg0: true}, {name: "VFMADDSUB213PDMasked512load", argLength: 5, reg: w3kwload, asm: "VFMADDSUB213PD", commutative: false, typ: "Vec512", aux: "SymOff", symEffect: "Read", resultInArg0: true}, - {name: "VFMADDSUB213PS128load", argLength: 4, reg: w31load, asm: "VFMADDSUB213PS", commutative: false, typ: "Vec128", aux: "SymOff", symEffect: "Read", resultInArg0: true}, - {name: "VFMADDSUB213PS256load", argLength: 4, reg: w31load, asm: "VFMADDSUB213PS", commutative: false, typ: "Vec256", aux: "SymOff", symEffect: "Read", resultInArg0: true}, {name: "VFMADDSUB213PS512load", argLength: 4, reg: w31load, asm: "VFMADDSUB213PS", commutative: false, typ: "Vec512", aux: "SymOff", symEffect: "Read", resultInArg0: true}, {name: "VFMADDSUB213PSMasked128load", argLength: 5, reg: w3kwload, asm: "VFMADDSUB213PS", commutative: false, typ: "Vec128", aux: "SymOff", symEffect: "Read", resultInArg0: true}, {name: "VFMADDSUB213PSMasked256load", argLength: 5, reg: w3kwload, asm: "VFMADDSUB213PS", commutative: false, typ: "Vec256", aux: "SymOff", symEffect: "Read", resultInArg0: true}, {name: "VFMADDSUB213PSMasked512load", argLength: 5, reg: w3kwload, asm: "VFMADDSUB213PS", commutative: false, typ: "Vec512", aux: "SymOff", symEffect: "Read", resultInArg0: true}, - {name: "VFMSUBADD213PD128load", argLength: 4, reg: w31load, asm: "VFMSUBADD213PD", commutative: false, typ: "Vec128", aux: "SymOff", symEffect: "Read", resultInArg0: true}, - {name: "VFMSUBADD213PD256load", argLength: 4, reg: w31load, asm: "VFMSUBADD213PD", commutative: false, typ: "Vec256", aux: "SymOff", symEffect: "Read", resultInArg0: true}, {name: "VFMSUBADD213PD512load", argLength: 4, reg: w31load, asm: "VFMSUBADD213PD", commutative: false, typ: "Vec512", aux: "SymOff", symEffect: "Read", resultInArg0: true}, {name: "VFMSUBADD213PDMasked128load", argLength: 5, reg: w3kwload, asm: "VFMSUBADD213PD", commutative: false, typ: "Vec128", aux: "SymOff", symEffect: "Read", resultInArg0: true}, {name: "VFMSUBADD213PDMasked256load", argLength: 5, reg: w3kwload, asm: "VFMSUBADD213PD", commutative: false, typ: "Vec256", aux: "SymOff", symEffect: "Read", resultInArg0: true}, {name: "VFMSUBADD213PDMasked512load", argLength: 5, reg: w3kwload, asm: "VFMSUBADD213PD", commutative: false, typ: "Vec512", aux: "SymOff", symEffect: "Read", resultInArg0: true}, - {name: "VFMSUBADD213PS128load", argLength: 4, reg: w31load, asm: "VFMSUBADD213PS", commutative: false, typ: "Vec128", aux: "SymOff", symEffect: "Read", resultInArg0: true}, - {name: "VFMSUBADD213PS256load", argLength: 4, reg: w31load, asm: "VFMSUBADD213PS", commutative: false, typ: "Vec256", aux: "SymOff", symEffect: "Read", resultInArg0: true}, {name: "VFMSUBADD213PS512load", argLength: 4, reg: w31load, asm: "VFMSUBADD213PS", commutative: false, typ: "Vec512", aux: "SymOff", symEffect: "Read", resultInArg0: true}, {name: "VFMSUBADD213PSMasked128load", argLength: 5, reg: w3kwload, asm: "VFMSUBADD213PS", commutative: false, typ: "Vec128", aux: "SymOff", symEffect: "Read", resultInArg0: true}, {name: "VFMSUBADD213PSMasked256load", argLength: 5, reg: w3kwload, asm: "VFMSUBADD213PS", commutative: false, typ: "Vec256", aux: "SymOff", symEffect: "Read", resultInArg0: true}, diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 9e5fdb1fc1..a84fc161e9 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -2841,38 +2841,26 @@ const ( OpAMD64VDIVPSMasked128load OpAMD64VDIVPSMasked256load OpAMD64VDIVPSMasked512load - OpAMD64VFMADD213PD128load - OpAMD64VFMADD213PD256load OpAMD64VFMADD213PD512load OpAMD64VFMADD213PDMasked128load OpAMD64VFMADD213PDMasked256load OpAMD64VFMADD213PDMasked512load - OpAMD64VFMADD213PS128load - OpAMD64VFMADD213PS256load OpAMD64VFMADD213PS512load OpAMD64VFMADD213PSMasked128load OpAMD64VFMADD213PSMasked256load OpAMD64VFMADD213PSMasked512load - OpAMD64VFMADDSUB213PD128load - OpAMD64VFMADDSUB213PD256load OpAMD64VFMADDSUB213PD512load OpAMD64VFMADDSUB213PDMasked128load OpAMD64VFMADDSUB213PDMasked256load OpAMD64VFMADDSUB213PDMasked512load - OpAMD64VFMADDSUB213PS128load - OpAMD64VFMADDSUB213PS256load OpAMD64VFMADDSUB213PS512load OpAMD64VFMADDSUB213PSMasked128load OpAMD64VFMADDSUB213PSMasked256load OpAMD64VFMADDSUB213PSMasked512load - OpAMD64VFMSUBADD213PD128load - OpAMD64VFMSUBADD213PD256load OpAMD64VFMSUBADD213PD512load OpAMD64VFMSUBADD213PDMasked128load OpAMD64VFMSUBADD213PDMasked256load OpAMD64VFMSUBADD213PDMasked512load - OpAMD64VFMSUBADD213PS128load - OpAMD64VFMSUBADD213PS256load OpAMD64VFMSUBADD213PS512load OpAMD64VFMSUBADD213PSMasked128load OpAMD64VFMSUBADD213PSMasked256load @@ -23179,12 +23167,12 @@ var opcodeTable = [...]opInfo{ asm: x86.AVFMADD213PD, reg: regInfo{ inputs: []inputInfo{ - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - {1, 281474976645120}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - {2, 281474976645120}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 + {0, 2147418112}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 + {1, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 + {2, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 }, outputs: []outputInfo{ - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 + {0, 2147418112}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 }, }, }, @@ -23195,12 +23183,12 @@ var opcodeTable = [...]opInfo{ asm: x86.AVFMADD213PD, reg: regInfo{ inputs: []inputInfo{ - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - {1, 281474976645120}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - {2, 281474976645120}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 + {0, 2147418112}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 + {1, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 + {2, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 }, outputs: []outputInfo{ - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 + {0, 2147418112}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 }, }, }, @@ -23278,12 +23266,12 @@ var opcodeTable = [...]opInfo{ asm: x86.AVFMADD213PS, reg: regInfo{ inputs: []inputInfo{ - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - {1, 281474976645120}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - {2, 281474976645120}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 + {0, 2147418112}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 + {1, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 + {2, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 }, outputs: []outputInfo{ - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 + {0, 2147418112}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 }, }, }, @@ -23294,12 +23282,12 @@ var opcodeTable = [...]opInfo{ asm: x86.AVFMADD213PS, reg: regInfo{ inputs: []inputInfo{ - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - {1, 281474976645120}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - {2, 281474976645120}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 + {0, 2147418112}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 + {1, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 + {2, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 }, outputs: []outputInfo{ - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 + {0, 2147418112}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 }, }, }, @@ -23377,12 +23365,12 @@ var opcodeTable = [...]opInfo{ asm: x86.AVFMADDSUB213PD, reg: regInfo{ inputs: []inputInfo{ - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - {1, 281474976645120}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - {2, 281474976645120}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 + {0, 2147418112}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 + {1, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 + {2, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 }, outputs: []outputInfo{ - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 + {0, 2147418112}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 }, }, }, @@ -23393,12 +23381,12 @@ var opcodeTable = [...]opInfo{ asm: x86.AVFMADDSUB213PD, reg: regInfo{ inputs: []inputInfo{ - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - {1, 281474976645120}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - {2, 281474976645120}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 + {0, 2147418112}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 + {1, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 + {2, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 }, outputs: []outputInfo{ - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 + {0, 2147418112}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 }, }, }, @@ -23476,12 +23464,12 @@ var opcodeTable = [...]opInfo{ asm: x86.AVFMADDSUB213PS, reg: regInfo{ inputs: []inputInfo{ - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - {1, 281474976645120}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - {2, 281474976645120}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 + {0, 2147418112}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 + {1, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 + {2, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 }, outputs: []outputInfo{ - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 + {0, 2147418112}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 }, }, }, @@ -23492,12 +23480,12 @@ var opcodeTable = [...]opInfo{ asm: x86.AVFMADDSUB213PS, reg: regInfo{ inputs: []inputInfo{ - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - {1, 281474976645120}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - {2, 281474976645120}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 + {0, 2147418112}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 + {1, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 + {2, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 }, outputs: []outputInfo{ - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 + {0, 2147418112}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 }, }, }, @@ -23575,12 +23563,12 @@ var opcodeTable = [...]opInfo{ asm: x86.AVFMSUBADD213PD, reg: regInfo{ inputs: []inputInfo{ - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - {1, 281474976645120}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - {2, 281474976645120}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 + {0, 2147418112}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 + {1, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 + {2, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 }, outputs: []outputInfo{ - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 + {0, 2147418112}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 }, }, }, @@ -23591,12 +23579,12 @@ var opcodeTable = [...]opInfo{ asm: x86.AVFMSUBADD213PD, reg: regInfo{ inputs: []inputInfo{ - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - {1, 281474976645120}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - {2, 281474976645120}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 + {0, 2147418112}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 + {1, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 + {2, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 }, outputs: []outputInfo{ - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 + {0, 2147418112}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 }, }, }, @@ -23674,12 +23662,12 @@ var opcodeTable = [...]opInfo{ asm: x86.AVFMSUBADD213PS, reg: regInfo{ inputs: []inputInfo{ - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - {1, 281474976645120}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - {2, 281474976645120}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 + {0, 2147418112}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 + {1, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 + {2, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 }, outputs: []outputInfo{ - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 + {0, 2147418112}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 }, }, }, @@ -23690,12 +23678,12 @@ var opcodeTable = [...]opInfo{ asm: x86.AVFMSUBADD213PS, reg: regInfo{ inputs: []inputInfo{ - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - {1, 281474976645120}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - {2, 281474976645120}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 + {0, 2147418112}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 + {1, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 + {2, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 }, outputs: []outputInfo{ - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 + {0, 2147418112}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 }, }, }, @@ -44193,42 +44181,6 @@ var opcodeTable = [...]opInfo{ }, }, }, - { - name: "VFMADD213PD128load", - auxType: auxSymOff, - argLen: 4, - resultInArg0: true, - symEffect: SymRead, - asm: x86.AVFMADD213PD, - reg: regInfo{ - inputs: []inputInfo{ - {2, 72057594037977087}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R15 SB - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - {1, 281474976645120}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - }, - outputs: []outputInfo{ - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - }, - }, - }, - { - name: "VFMADD213PD256load", - auxType: auxSymOff, - argLen: 4, - resultInArg0: true, - symEffect: SymRead, - asm: x86.AVFMADD213PD, - reg: regInfo{ - inputs: []inputInfo{ - {2, 72057594037977087}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R15 SB - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - {1, 281474976645120}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - }, - outputs: []outputInfo{ - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - }, - }, - }, { name: "VFMADD213PD512load", auxType: auxSymOff, @@ -44304,42 +44256,6 @@ var opcodeTable = [...]opInfo{ }, }, }, - { - name: "VFMADD213PS128load", - auxType: auxSymOff, - argLen: 4, - resultInArg0: true, - symEffect: SymRead, - asm: x86.AVFMADD213PS, - reg: regInfo{ - inputs: []inputInfo{ - {2, 72057594037977087}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R15 SB - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - {1, 281474976645120}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - }, - outputs: []outputInfo{ - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - }, - }, - }, - { - name: "VFMADD213PS256load", - auxType: auxSymOff, - argLen: 4, - resultInArg0: true, - symEffect: SymRead, - asm: x86.AVFMADD213PS, - reg: regInfo{ - inputs: []inputInfo{ - {2, 72057594037977087}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R15 SB - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - {1, 281474976645120}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - }, - outputs: []outputInfo{ - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - }, - }, - }, { name: "VFMADD213PS512load", auxType: auxSymOff, @@ -44415,42 +44331,6 @@ var opcodeTable = [...]opInfo{ }, }, }, - { - name: "VFMADDSUB213PD128load", - auxType: auxSymOff, - argLen: 4, - resultInArg0: true, - symEffect: SymRead, - asm: x86.AVFMADDSUB213PD, - reg: regInfo{ - inputs: []inputInfo{ - {2, 72057594037977087}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R15 SB - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - {1, 281474976645120}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - }, - outputs: []outputInfo{ - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - }, - }, - }, - { - name: "VFMADDSUB213PD256load", - auxType: auxSymOff, - argLen: 4, - resultInArg0: true, - symEffect: SymRead, - asm: x86.AVFMADDSUB213PD, - reg: regInfo{ - inputs: []inputInfo{ - {2, 72057594037977087}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R15 SB - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - {1, 281474976645120}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - }, - outputs: []outputInfo{ - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - }, - }, - }, { name: "VFMADDSUB213PD512load", auxType: auxSymOff, @@ -44526,42 +44406,6 @@ var opcodeTable = [...]opInfo{ }, }, }, - { - name: "VFMADDSUB213PS128load", - auxType: auxSymOff, - argLen: 4, - resultInArg0: true, - symEffect: SymRead, - asm: x86.AVFMADDSUB213PS, - reg: regInfo{ - inputs: []inputInfo{ - {2, 72057594037977087}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R15 SB - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - {1, 281474976645120}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - }, - outputs: []outputInfo{ - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - }, - }, - }, - { - name: "VFMADDSUB213PS256load", - auxType: auxSymOff, - argLen: 4, - resultInArg0: true, - symEffect: SymRead, - asm: x86.AVFMADDSUB213PS, - reg: regInfo{ - inputs: []inputInfo{ - {2, 72057594037977087}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R15 SB - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - {1, 281474976645120}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - }, - outputs: []outputInfo{ - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - }, - }, - }, { name: "VFMADDSUB213PS512load", auxType: auxSymOff, @@ -44637,42 +44481,6 @@ var opcodeTable = [...]opInfo{ }, }, }, - { - name: "VFMSUBADD213PD128load", - auxType: auxSymOff, - argLen: 4, - resultInArg0: true, - symEffect: SymRead, - asm: x86.AVFMSUBADD213PD, - reg: regInfo{ - inputs: []inputInfo{ - {2, 72057594037977087}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R15 SB - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - {1, 281474976645120}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - }, - outputs: []outputInfo{ - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - }, - }, - }, - { - name: "VFMSUBADD213PD256load", - auxType: auxSymOff, - argLen: 4, - resultInArg0: true, - symEffect: SymRead, - asm: x86.AVFMSUBADD213PD, - reg: regInfo{ - inputs: []inputInfo{ - {2, 72057594037977087}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R15 SB - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - {1, 281474976645120}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - }, - outputs: []outputInfo{ - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - }, - }, - }, { name: "VFMSUBADD213PD512load", auxType: auxSymOff, @@ -44748,42 +44556,6 @@ var opcodeTable = [...]opInfo{ }, }, }, - { - name: "VFMSUBADD213PS128load", - auxType: auxSymOff, - argLen: 4, - resultInArg0: true, - symEffect: SymRead, - asm: x86.AVFMSUBADD213PS, - reg: regInfo{ - inputs: []inputInfo{ - {2, 72057594037977087}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R15 SB - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - {1, 281474976645120}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - }, - outputs: []outputInfo{ - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - }, - }, - }, - { - name: "VFMSUBADD213PS256load", - auxType: auxSymOff, - argLen: 4, - resultInArg0: true, - symEffect: SymRead, - asm: x86.AVFMSUBADD213PS, - reg: regInfo{ - inputs: []inputInfo{ - {2, 72057594037977087}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R15 SB - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - {1, 281474976645120}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - }, - outputs: []outputInfo{ - {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 - }, - }, - }, { name: "VFMSUBADD213PS512load", auxType: auxSymOff, diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index fe0005bb05..b1b1c84046 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -782,10 +782,6 @@ func rewriteValueAMD64(v *Value) bool { return rewriteValueAMD64_OpAMD64VDIVPSMasked256(v) case OpAMD64VDIVPSMasked512: return rewriteValueAMD64_OpAMD64VDIVPSMasked512(v) - case OpAMD64VFMADD213PD128: - return rewriteValueAMD64_OpAMD64VFMADD213PD128(v) - case OpAMD64VFMADD213PD256: - return rewriteValueAMD64_OpAMD64VFMADD213PD256(v) case OpAMD64VFMADD213PD512: return rewriteValueAMD64_OpAMD64VFMADD213PD512(v) case OpAMD64VFMADD213PDMasked128: @@ -794,10 +790,6 @@ func rewriteValueAMD64(v *Value) bool { return rewriteValueAMD64_OpAMD64VFMADD213PDMasked256(v) case OpAMD64VFMADD213PDMasked512: return rewriteValueAMD64_OpAMD64VFMADD213PDMasked512(v) - case OpAMD64VFMADD213PS128: - return rewriteValueAMD64_OpAMD64VFMADD213PS128(v) - case OpAMD64VFMADD213PS256: - return rewriteValueAMD64_OpAMD64VFMADD213PS256(v) case OpAMD64VFMADD213PS512: return rewriteValueAMD64_OpAMD64VFMADD213PS512(v) case OpAMD64VFMADD213PSMasked128: @@ -806,10 +798,6 @@ func rewriteValueAMD64(v *Value) bool { return rewriteValueAMD64_OpAMD64VFMADD213PSMasked256(v) case OpAMD64VFMADD213PSMasked512: return rewriteValueAMD64_OpAMD64VFMADD213PSMasked512(v) - case OpAMD64VFMADDSUB213PD128: - return rewriteValueAMD64_OpAMD64VFMADDSUB213PD128(v) - case OpAMD64VFMADDSUB213PD256: - return rewriteValueAMD64_OpAMD64VFMADDSUB213PD256(v) case OpAMD64VFMADDSUB213PD512: return rewriteValueAMD64_OpAMD64VFMADDSUB213PD512(v) case OpAMD64VFMADDSUB213PDMasked128: @@ -818,10 +806,6 @@ func rewriteValueAMD64(v *Value) bool { return rewriteValueAMD64_OpAMD64VFMADDSUB213PDMasked256(v) case OpAMD64VFMADDSUB213PDMasked512: return rewriteValueAMD64_OpAMD64VFMADDSUB213PDMasked512(v) - case OpAMD64VFMADDSUB213PS128: - return rewriteValueAMD64_OpAMD64VFMADDSUB213PS128(v) - case OpAMD64VFMADDSUB213PS256: - return rewriteValueAMD64_OpAMD64VFMADDSUB213PS256(v) case OpAMD64VFMADDSUB213PS512: return rewriteValueAMD64_OpAMD64VFMADDSUB213PS512(v) case OpAMD64VFMADDSUB213PSMasked128: @@ -830,10 +814,6 @@ func rewriteValueAMD64(v *Value) bool { return rewriteValueAMD64_OpAMD64VFMADDSUB213PSMasked256(v) case OpAMD64VFMADDSUB213PSMasked512: return rewriteValueAMD64_OpAMD64VFMADDSUB213PSMasked512(v) - case OpAMD64VFMSUBADD213PD128: - return rewriteValueAMD64_OpAMD64VFMSUBADD213PD128(v) - case OpAMD64VFMSUBADD213PD256: - return rewriteValueAMD64_OpAMD64VFMSUBADD213PD256(v) case OpAMD64VFMSUBADD213PD512: return rewriteValueAMD64_OpAMD64VFMSUBADD213PD512(v) case OpAMD64VFMSUBADD213PDMasked128: @@ -842,10 +822,6 @@ func rewriteValueAMD64(v *Value) bool { return rewriteValueAMD64_OpAMD64VFMSUBADD213PDMasked256(v) case OpAMD64VFMSUBADD213PDMasked512: return rewriteValueAMD64_OpAMD64VFMSUBADD213PDMasked512(v) - case OpAMD64VFMSUBADD213PS128: - return rewriteValueAMD64_OpAMD64VFMSUBADD213PS128(v) - case OpAMD64VFMSUBADD213PS256: - return rewriteValueAMD64_OpAMD64VFMSUBADD213PS256(v) case OpAMD64VFMSUBADD213PS512: return rewriteValueAMD64_OpAMD64VFMSUBADD213PS512(v) case OpAMD64VFMSUBADD213PSMasked128: @@ -31492,64 +31468,6 @@ func rewriteValueAMD64_OpAMD64VDIVPSMasked512(v *Value) bool { } return false } -func rewriteValueAMD64_OpAMD64VFMADD213PD128(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (VFMADD213PD128 x y l:(VMOVDQUload128 {sym} [off] ptr mem)) - // cond: canMergeLoad(v, l) && clobber(l) - // result: (VFMADD213PD128load {sym} [off] x y ptr mem) - for { - x := v_0 - y := v_1 - l := v_2 - if l.Op != OpAMD64VMOVDQUload128 { - break - } - off := auxIntToInt32(l.AuxInt) - sym := auxToSym(l.Aux) - mem := l.Args[1] - ptr := l.Args[0] - if !(canMergeLoad(v, l) && clobber(l)) { - break - } - v.reset(OpAMD64VFMADD213PD128load) - v.AuxInt = int32ToAuxInt(off) - v.Aux = symToAux(sym) - v.AddArg4(x, y, ptr, mem) - return true - } - return false -} -func rewriteValueAMD64_OpAMD64VFMADD213PD256(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (VFMADD213PD256 x y l:(VMOVDQUload256 {sym} [off] ptr mem)) - // cond: canMergeLoad(v, l) && clobber(l) - // result: (VFMADD213PD256load {sym} [off] x y ptr mem) - for { - x := v_0 - y := v_1 - l := v_2 - if l.Op != OpAMD64VMOVDQUload256 { - break - } - off := auxIntToInt32(l.AuxInt) - sym := auxToSym(l.Aux) - mem := l.Args[1] - ptr := l.Args[0] - if !(canMergeLoad(v, l) && clobber(l)) { - break - } - v.reset(OpAMD64VFMADD213PD256load) - v.AuxInt = int32ToAuxInt(off) - v.Aux = symToAux(sym) - v.AddArg4(x, y, ptr, mem) - return true - } - return false -} func rewriteValueAMD64_OpAMD64VFMADD213PD512(v *Value) bool { v_2 := v.Args[2] v_1 := v.Args[1] @@ -31672,64 +31590,6 @@ func rewriteValueAMD64_OpAMD64VFMADD213PDMasked512(v *Value) bool { } return false } -func rewriteValueAMD64_OpAMD64VFMADD213PS128(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (VFMADD213PS128 x y l:(VMOVDQUload128 {sym} [off] ptr mem)) - // cond: canMergeLoad(v, l) && clobber(l) - // result: (VFMADD213PS128load {sym} [off] x y ptr mem) - for { - x := v_0 - y := v_1 - l := v_2 - if l.Op != OpAMD64VMOVDQUload128 { - break - } - off := auxIntToInt32(l.AuxInt) - sym := auxToSym(l.Aux) - mem := l.Args[1] - ptr := l.Args[0] - if !(canMergeLoad(v, l) && clobber(l)) { - break - } - v.reset(OpAMD64VFMADD213PS128load) - v.AuxInt = int32ToAuxInt(off) - v.Aux = symToAux(sym) - v.AddArg4(x, y, ptr, mem) - return true - } - return false -} -func rewriteValueAMD64_OpAMD64VFMADD213PS256(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (VFMADD213PS256 x y l:(VMOVDQUload256 {sym} [off] ptr mem)) - // cond: canMergeLoad(v, l) && clobber(l) - // result: (VFMADD213PS256load {sym} [off] x y ptr mem) - for { - x := v_0 - y := v_1 - l := v_2 - if l.Op != OpAMD64VMOVDQUload256 { - break - } - off := auxIntToInt32(l.AuxInt) - sym := auxToSym(l.Aux) - mem := l.Args[1] - ptr := l.Args[0] - if !(canMergeLoad(v, l) && clobber(l)) { - break - } - v.reset(OpAMD64VFMADD213PS256load) - v.AuxInt = int32ToAuxInt(off) - v.Aux = symToAux(sym) - v.AddArg4(x, y, ptr, mem) - return true - } - return false -} func rewriteValueAMD64_OpAMD64VFMADD213PS512(v *Value) bool { v_2 := v.Args[2] v_1 := v.Args[1] @@ -31852,64 +31712,6 @@ func rewriteValueAMD64_OpAMD64VFMADD213PSMasked512(v *Value) bool { } return false } -func rewriteValueAMD64_OpAMD64VFMADDSUB213PD128(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (VFMADDSUB213PD128 x y l:(VMOVDQUload128 {sym} [off] ptr mem)) - // cond: canMergeLoad(v, l) && clobber(l) - // result: (VFMADDSUB213PD128load {sym} [off] x y ptr mem) - for { - x := v_0 - y := v_1 - l := v_2 - if l.Op != OpAMD64VMOVDQUload128 { - break - } - off := auxIntToInt32(l.AuxInt) - sym := auxToSym(l.Aux) - mem := l.Args[1] - ptr := l.Args[0] - if !(canMergeLoad(v, l) && clobber(l)) { - break - } - v.reset(OpAMD64VFMADDSUB213PD128load) - v.AuxInt = int32ToAuxInt(off) - v.Aux = symToAux(sym) - v.AddArg4(x, y, ptr, mem) - return true - } - return false -} -func rewriteValueAMD64_OpAMD64VFMADDSUB213PD256(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (VFMADDSUB213PD256 x y l:(VMOVDQUload256 {sym} [off] ptr mem)) - // cond: canMergeLoad(v, l) && clobber(l) - // result: (VFMADDSUB213PD256load {sym} [off] x y ptr mem) - for { - x := v_0 - y := v_1 - l := v_2 - if l.Op != OpAMD64VMOVDQUload256 { - break - } - off := auxIntToInt32(l.AuxInt) - sym := auxToSym(l.Aux) - mem := l.Args[1] - ptr := l.Args[0] - if !(canMergeLoad(v, l) && clobber(l)) { - break - } - v.reset(OpAMD64VFMADDSUB213PD256load) - v.AuxInt = int32ToAuxInt(off) - v.Aux = symToAux(sym) - v.AddArg4(x, y, ptr, mem) - return true - } - return false -} func rewriteValueAMD64_OpAMD64VFMADDSUB213PD512(v *Value) bool { v_2 := v.Args[2] v_1 := v.Args[1] @@ -32032,64 +31834,6 @@ func rewriteValueAMD64_OpAMD64VFMADDSUB213PDMasked512(v *Value) bool { } return false } -func rewriteValueAMD64_OpAMD64VFMADDSUB213PS128(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (VFMADDSUB213PS128 x y l:(VMOVDQUload128 {sym} [off] ptr mem)) - // cond: canMergeLoad(v, l) && clobber(l) - // result: (VFMADDSUB213PS128load {sym} [off] x y ptr mem) - for { - x := v_0 - y := v_1 - l := v_2 - if l.Op != OpAMD64VMOVDQUload128 { - break - } - off := auxIntToInt32(l.AuxInt) - sym := auxToSym(l.Aux) - mem := l.Args[1] - ptr := l.Args[0] - if !(canMergeLoad(v, l) && clobber(l)) { - break - } - v.reset(OpAMD64VFMADDSUB213PS128load) - v.AuxInt = int32ToAuxInt(off) - v.Aux = symToAux(sym) - v.AddArg4(x, y, ptr, mem) - return true - } - return false -} -func rewriteValueAMD64_OpAMD64VFMADDSUB213PS256(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (VFMADDSUB213PS256 x y l:(VMOVDQUload256 {sym} [off] ptr mem)) - // cond: canMergeLoad(v, l) && clobber(l) - // result: (VFMADDSUB213PS256load {sym} [off] x y ptr mem) - for { - x := v_0 - y := v_1 - l := v_2 - if l.Op != OpAMD64VMOVDQUload256 { - break - } - off := auxIntToInt32(l.AuxInt) - sym := auxToSym(l.Aux) - mem := l.Args[1] - ptr := l.Args[0] - if !(canMergeLoad(v, l) && clobber(l)) { - break - } - v.reset(OpAMD64VFMADDSUB213PS256load) - v.AuxInt = int32ToAuxInt(off) - v.Aux = symToAux(sym) - v.AddArg4(x, y, ptr, mem) - return true - } - return false -} func rewriteValueAMD64_OpAMD64VFMADDSUB213PS512(v *Value) bool { v_2 := v.Args[2] v_1 := v.Args[1] @@ -32212,64 +31956,6 @@ func rewriteValueAMD64_OpAMD64VFMADDSUB213PSMasked512(v *Value) bool { } return false } -func rewriteValueAMD64_OpAMD64VFMSUBADD213PD128(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (VFMSUBADD213PD128 x y l:(VMOVDQUload128 {sym} [off] ptr mem)) - // cond: canMergeLoad(v, l) && clobber(l) - // result: (VFMSUBADD213PD128load {sym} [off] x y ptr mem) - for { - x := v_0 - y := v_1 - l := v_2 - if l.Op != OpAMD64VMOVDQUload128 { - break - } - off := auxIntToInt32(l.AuxInt) - sym := auxToSym(l.Aux) - mem := l.Args[1] - ptr := l.Args[0] - if !(canMergeLoad(v, l) && clobber(l)) { - break - } - v.reset(OpAMD64VFMSUBADD213PD128load) - v.AuxInt = int32ToAuxInt(off) - v.Aux = symToAux(sym) - v.AddArg4(x, y, ptr, mem) - return true - } - return false -} -func rewriteValueAMD64_OpAMD64VFMSUBADD213PD256(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (VFMSUBADD213PD256 x y l:(VMOVDQUload256 {sym} [off] ptr mem)) - // cond: canMergeLoad(v, l) && clobber(l) - // result: (VFMSUBADD213PD256load {sym} [off] x y ptr mem) - for { - x := v_0 - y := v_1 - l := v_2 - if l.Op != OpAMD64VMOVDQUload256 { - break - } - off := auxIntToInt32(l.AuxInt) - sym := auxToSym(l.Aux) - mem := l.Args[1] - ptr := l.Args[0] - if !(canMergeLoad(v, l) && clobber(l)) { - break - } - v.reset(OpAMD64VFMSUBADD213PD256load) - v.AuxInt = int32ToAuxInt(off) - v.Aux = symToAux(sym) - v.AddArg4(x, y, ptr, mem) - return true - } - return false -} func rewriteValueAMD64_OpAMD64VFMSUBADD213PD512(v *Value) bool { v_2 := v.Args[2] v_1 := v.Args[1] @@ -32392,64 +32078,6 @@ func rewriteValueAMD64_OpAMD64VFMSUBADD213PDMasked512(v *Value) bool { } return false } -func rewriteValueAMD64_OpAMD64VFMSUBADD213PS128(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (VFMSUBADD213PS128 x y l:(VMOVDQUload128 {sym} [off] ptr mem)) - // cond: canMergeLoad(v, l) && clobber(l) - // result: (VFMSUBADD213PS128load {sym} [off] x y ptr mem) - for { - x := v_0 - y := v_1 - l := v_2 - if l.Op != OpAMD64VMOVDQUload128 { - break - } - off := auxIntToInt32(l.AuxInt) - sym := auxToSym(l.Aux) - mem := l.Args[1] - ptr := l.Args[0] - if !(canMergeLoad(v, l) && clobber(l)) { - break - } - v.reset(OpAMD64VFMSUBADD213PS128load) - v.AuxInt = int32ToAuxInt(off) - v.Aux = symToAux(sym) - v.AddArg4(x, y, ptr, mem) - return true - } - return false -} -func rewriteValueAMD64_OpAMD64VFMSUBADD213PS256(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (VFMSUBADD213PS256 x y l:(VMOVDQUload256 {sym} [off] ptr mem)) - // cond: canMergeLoad(v, l) && clobber(l) - // result: (VFMSUBADD213PS256load {sym} [off] x y ptr mem) - for { - x := v_0 - y := v_1 - l := v_2 - if l.Op != OpAMD64VMOVDQUload256 { - break - } - off := auxIntToInt32(l.AuxInt) - sym := auxToSym(l.Aux) - mem := l.Args[1] - ptr := l.Args[0] - if !(canMergeLoad(v, l) && clobber(l)) { - break - } - v.reset(OpAMD64VFMSUBADD213PS256load) - v.AuxInt = int32ToAuxInt(off) - v.Aux = symToAux(sym) - v.AddArg4(x, y, ptr, mem) - return true - } - return false -} func rewriteValueAMD64_OpAMD64VFMSUBADD213PS512(v *Value) bool { v_2 := v.Args[2] v_1 := v.Args[1] diff --git a/src/internal/cpu/cpu_x86.go b/src/internal/cpu/cpu_x86.go index 711fb045c3..0e97651e3d 100644 --- a/src/internal/cpu/cpu_x86.go +++ b/src/internal/cpu/cpu_x86.go @@ -136,12 +136,6 @@ func doinit() { // e.g. setting the xsavedisable boot option on Windows 10. X86.HasOSXSAVE = isSet(ecx1, cpuid_OSXSAVE) - // The FMA instruction set extension only has VEX prefixed instructions. - // VEX prefixed instructions require OSXSAVE to be enabled. - // See Intel 64 and IA-32 Architecture Software Developer’s Manual Volume 2 - // Section 2.4 "AVX and SSE Instruction Exception Specification" - X86.HasFMA = isSet(ecx1, cpuid_FMA) && X86.HasOSXSAVE - osSupportsAVX := false osSupportsAVX512 := false // For XGETBV, OSXSAVE bit is required and sufficient. @@ -159,6 +153,14 @@ func doinit() { X86.HasAVX = isSet(ecx1, cpuid_AVX) && osSupportsAVX + // The FMA instruction set extension requires both the FMA and AVX flags. + // + // Furthermore, the FMA instructions are all VEX prefixed instructions. + // VEX prefixed instructions require OSXSAVE to be enabled. + // See Intel 64 and IA-32 Architecture Software Developer’s Manual Volume 2 + // Section 2.4 "AVX and SSE Instruction Exception Specification" + X86.HasFMA = isSet(ecx1, cpuid_FMA) && X86.HasAVX && X86.HasOSXSAVE + if maxID < 7 { osInit() return diff --git a/src/simd/archsimd/_gen/simdgen/xed.go b/src/simd/archsimd/_gen/simdgen/xed.go index 49bedc9b28..5d6fac64d0 100644 --- a/src/simd/archsimd/_gen/simdgen/xed.go +++ b/src/simd/archsimd/_gen/simdgen/xed.go @@ -77,7 +77,7 @@ func loadXED(xedPath string) []*unify.Value { switch { case inst.RealOpcode == "N": return // Skip unstable instructions - case !(strings.HasPrefix(inst.Extension, "AVX") || strings.HasPrefix(inst.Extension, "SHA")): + case !(strings.HasPrefix(inst.Extension, "AVX") || strings.HasPrefix(inst.Extension, "SHA") || inst.Extension == "FMA"): // We're only interested in AVX and SHA instructions. return } @@ -795,6 +795,7 @@ var cpuFeatureMap = map[string]string{ "AVX2": "AVX2", "AVXAES": "AVXAES", "SHA": "SHA", + "FMA": "FMA", // AVX-512 foundational features. We combine all of these into one "AVX512" feature. "AVX512F": "AVX512", @@ -827,6 +828,7 @@ func init() { "AVX512": {Implies: []string{"AVX2"}}, "AVXAES": {Virtual: true, Implies: []string{"AVX", "AES"}}, + "FMA": {Implies: []string{"AVX"}}, // AVX-512 subfeatures. "AVX512BITALG": {Implies: []string{"AVX512"}}, diff --git a/src/simd/archsimd/cpu.go b/src/simd/archsimd/cpu.go index 1cd765268f..8069ee7f26 100644 --- a/src/simd/archsimd/cpu.go +++ b/src/simd/archsimd/cpu.go @@ -141,6 +141,16 @@ func (X86Features) AVXVNNI() bool { return cpu.X86.HasAVXVNNI } +// FMA returns whether the CPU supports the FMA feature. +// +// If it returns true, then the CPU also supports AVX. +// +// FMA is defined on all GOARCHes, but will only return true on +// GOARCH amd64. +func (X86Features) FMA() bool { + return cpu.X86.HasFMA +} + // SHA returns whether the CPU supports the SHA feature. // // SHA is defined on all GOARCHes, but will only return true on diff --git a/src/simd/archsimd/ops_amd64.go b/src/simd/archsimd/ops_amd64.go index d65c7dde0c..ec50cc72c5 100644 --- a/src/simd/archsimd/ops_amd64.go +++ b/src/simd/archsimd/ops_amd64.go @@ -4088,12 +4088,12 @@ func (x Uint64x8) Mul(y Uint64x8) Uint64x8 // MulAdd performs a fused (x * y) + z. // -// Asm: VFMADD213PS, CPU Feature: AVX512 +// Asm: VFMADD213PS, CPU Feature: FMA func (x Float32x4) MulAdd(y Float32x4, z Float32x4) Float32x4 // MulAdd performs a fused (x * y) + z. // -// Asm: VFMADD213PS, CPU Feature: AVX512 +// Asm: VFMADD213PS, CPU Feature: FMA func (x Float32x8) MulAdd(y Float32x8, z Float32x8) Float32x8 // MulAdd performs a fused (x * y) + z. @@ -4103,12 +4103,12 @@ func (x Float32x16) MulAdd(y Float32x16, z Float32x16) Float32x16 // MulAdd performs a fused (x * y) + z. // -// Asm: VFMADD213PD, CPU Feature: AVX512 +// Asm: VFMADD213PD, CPU Feature: FMA func (x Float64x2) MulAdd(y Float64x2, z Float64x2) Float64x2 // MulAdd performs a fused (x * y) + z. // -// Asm: VFMADD213PD, CPU Feature: AVX512 +// Asm: VFMADD213PD, CPU Feature: FMA func (x Float64x4) MulAdd(y Float64x4, z Float64x4) Float64x4 // MulAdd performs a fused (x * y) + z. @@ -4120,12 +4120,12 @@ func (x Float64x8) MulAdd(y Float64x8, z Float64x8) Float64x8 // MulAddSub performs a fused (x * y) - z for odd-indexed elements, and (x * y) + z for even-indexed elements. // -// Asm: VFMADDSUB213PS, CPU Feature: AVX512 +// Asm: VFMADDSUB213PS, CPU Feature: FMA func (x Float32x4) MulAddSub(y Float32x4, z Float32x4) Float32x4 // MulAddSub performs a fused (x * y) - z for odd-indexed elements, and (x * y) + z for even-indexed elements. // -// Asm: VFMADDSUB213PS, CPU Feature: AVX512 +// Asm: VFMADDSUB213PS, CPU Feature: FMA func (x Float32x8) MulAddSub(y Float32x8, z Float32x8) Float32x8 // MulAddSub performs a fused (x * y) - z for odd-indexed elements, and (x * y) + z for even-indexed elements. @@ -4135,12 +4135,12 @@ func (x Float32x16) MulAddSub(y Float32x16, z Float32x16) Float32x16 // MulAddSub performs a fused (x * y) - z for odd-indexed elements, and (x * y) + z for even-indexed elements. // -// Asm: VFMADDSUB213PD, CPU Feature: AVX512 +// Asm: VFMADDSUB213PD, CPU Feature: FMA func (x Float64x2) MulAddSub(y Float64x2, z Float64x2) Float64x2 // MulAddSub performs a fused (x * y) - z for odd-indexed elements, and (x * y) + z for even-indexed elements. // -// Asm: VFMADDSUB213PD, CPU Feature: AVX512 +// Asm: VFMADDSUB213PD, CPU Feature: FMA func (x Float64x4) MulAddSub(y Float64x4, z Float64x4) Float64x4 // MulAddSub performs a fused (x * y) - z for odd-indexed elements, and (x * y) + z for even-indexed elements. @@ -4210,12 +4210,12 @@ func (x Uint16x32) MulHigh(y Uint16x32) Uint16x32 // MulSubAdd performs a fused (x * y) + z for odd-indexed elements, and (x * y) - z for even-indexed elements. // -// Asm: VFMSUBADD213PS, CPU Feature: AVX512 +// Asm: VFMSUBADD213PS, CPU Feature: FMA func (x Float32x4) MulSubAdd(y Float32x4, z Float32x4) Float32x4 // MulSubAdd performs a fused (x * y) + z for odd-indexed elements, and (x * y) - z for even-indexed elements. // -// Asm: VFMSUBADD213PS, CPU Feature: AVX512 +// Asm: VFMSUBADD213PS, CPU Feature: FMA func (x Float32x8) MulSubAdd(y Float32x8, z Float32x8) Float32x8 // MulSubAdd performs a fused (x * y) + z for odd-indexed elements, and (x * y) - z for even-indexed elements. @@ -4225,12 +4225,12 @@ func (x Float32x16) MulSubAdd(y Float32x16, z Float32x16) Float32x16 // MulSubAdd performs a fused (x * y) + z for odd-indexed elements, and (x * y) - z for even-indexed elements. // -// Asm: VFMSUBADD213PD, CPU Feature: AVX512 +// Asm: VFMSUBADD213PD, CPU Feature: FMA func (x Float64x2) MulSubAdd(y Float64x2, z Float64x2) Float64x2 // MulSubAdd performs a fused (x * y) + z for odd-indexed elements, and (x * y) - z for even-indexed elements. // -// Asm: VFMSUBADD213PD, CPU Feature: AVX512 +// Asm: VFMSUBADD213PD, CPU Feature: FMA func (x Float64x4) MulSubAdd(y Float64x4, z Float64x4) Float64x4 // MulSubAdd performs a fused (x * y) + z for odd-indexed elements, and (x * y) - z for even-indexed elements. -- cgit v1.3 From 2bc4315d92a70d9a5e895d60defba4f799798806 Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Fri, 19 Dec 2025 23:14:05 +0100 Subject: crypto/internal/fips140test: add ML-DSA to FIPS 140-3 functional tests Change-Id: I568d28d27d2bc55bbadcc678a2fcf9d36a6a6964 Reviewed-on: https://go-review.googlesource.com/c/go/+/731540 Reviewed-by: Roland Shoemaker Reviewed-by: Junyang Shao Auto-Submit: Filippo Valsorda LUCI-TryBot-Result: Go LUCI --- .../internal/fips140test/cast_fips140v1.0_test.go | 9 ------ .../internal/fips140test/cast_fips140v1.26_test.go | 16 ----------- .../internal/fips140test/fips140v1.0_test.go | 13 +++++++++ .../internal/fips140test/fips140v1.26_test.go | 33 ++++++++++++++++++++++ src/crypto/internal/fips140test/fips_test.go | 2 ++ 5 files changed, 48 insertions(+), 25 deletions(-) delete mode 100644 src/crypto/internal/fips140test/cast_fips140v1.0_test.go delete mode 100644 src/crypto/internal/fips140test/cast_fips140v1.26_test.go create mode 100644 src/crypto/internal/fips140test/fips140v1.0_test.go create mode 100644 src/crypto/internal/fips140test/fips140v1.26_test.go diff --git a/src/crypto/internal/fips140test/cast_fips140v1.0_test.go b/src/crypto/internal/fips140test/cast_fips140v1.0_test.go deleted file mode 100644 index b9ddfe4d8b..0000000000 --- a/src/crypto/internal/fips140test/cast_fips140v1.0_test.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2024 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. - -//go:build fips140v1.0 - -package fipstest - -func fips140v126Conditionals() {} diff --git a/src/crypto/internal/fips140test/cast_fips140v1.26_test.go b/src/crypto/internal/fips140test/cast_fips140v1.26_test.go deleted file mode 100644 index ef79068c38..0000000000 --- a/src/crypto/internal/fips140test/cast_fips140v1.26_test.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2024 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. - -//go:build !fips140v1.0 - -package fipstest - -import "crypto/internal/fips140/mldsa" - -func fips140v126Conditionals() { - // ML-DSA sign and verify PCT - kMLDSA := mldsa.GenerateKey44() - // ML-DSA-44 - mldsa.SignDeterministic(kMLDSA, make([]byte, 32), "") -} diff --git a/src/crypto/internal/fips140test/fips140v1.0_test.go b/src/crypto/internal/fips140test/fips140v1.0_test.go new file mode 100644 index 0000000000..262ef61d5c --- /dev/null +++ b/src/crypto/internal/fips140test/fips140v1.0_test.go @@ -0,0 +1,13 @@ +// Copyright 2024 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. + +//go:build fips140v1.0 + +package fipstest + +import "testing" + +func fips140v126Conditionals() {} + +func testFIPS140v126(t *testing.T, plaintext []byte) {} diff --git a/src/crypto/internal/fips140test/fips140v1.26_test.go b/src/crypto/internal/fips140test/fips140v1.26_test.go new file mode 100644 index 0000000000..6cd9f4fe40 --- /dev/null +++ b/src/crypto/internal/fips140test/fips140v1.26_test.go @@ -0,0 +1,33 @@ +// Copyright 2024 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. + +//go:build !fips140v1.0 + +package fipstest + +import ( + "crypto/internal/fips140/mldsa" + "testing" +) + +func fips140v126Conditionals() { + // ML-DSA sign and verify PCT + kMLDSA := mldsa.GenerateKey44() + // ML-DSA-44 + mldsa.SignDeterministic(kMLDSA, make([]byte, 32), "") +} + +func testFIPS140v126(t *testing.T, plaintext []byte) { + t.Run("ML-DSA KeyGen, SigGen, SigVer", func(t *testing.T) { + ensureServiceIndicator(t) + k := mldsa.GenerateKey44() + + sig, err := mldsa.SignDeterministic(k, plaintext, "") + fatalIfErr(t, err) + t.Logf("ML-DSA signature: %x", sig) + + err = mldsa.Verify(k.PublicKey(), plaintext, sig, "") + fatalIfErr(t, err) + }) +} diff --git a/src/crypto/internal/fips140test/fips_test.go b/src/crypto/internal/fips140test/fips_test.go index 52fc9d3488..7f2824ca9a 100644 --- a/src/crypto/internal/fips140test/fips_test.go +++ b/src/crypto/internal/fips140test/fips_test.go @@ -101,6 +101,8 @@ func TestFIPS140(t *testing.T) { aesBlock, err := aes.New(aesKey) fatalIfErr(t, err) + testFIPS140v126(t, plaintext) + t.Run("AES-CTR", func(t *testing.T) { ensureServiceIndicator(t) ctr := aes.NewCTR(aesBlock, aesIV) -- cgit v1.3 From 9ef26e96e3ae1e3a3d5e01a9b7fd1fa4dc5d6dd5 Mon Sep 17 00:00:00 2001 From: Prateik Lohani <91936249+Prateik-Lohani-07@users.noreply.github.com> Date: Thu, 15 Jan 2026 08:05:23 +0000 Subject: sort: improve comment readability for Stable function Change-Id: I3bc9f906f85e2b5f3d4ba6484e3c125065e36b57 GitHub-Last-Rev: 5d637c132533691d5a56fd00845bdb1d349642a3 GitHub-Pull-Request: golang/go#77190 Reviewed-on: https://go-review.googlesource.com/c/go/+/736501 Reviewed-by: Robert Griesemer Auto-Submit: Keith Randall Auto-Submit: Robert Griesemer Reviewed-by: Keith Randall LUCI-TryBot-Result: Go LUCI Reviewed-by: Keith Randall --- src/sort/sort.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sort/sort.go b/src/sort/sort.go index fd3cd6dabf..087e7d033d 100644 --- a/src/sort/sort.go +++ b/src/sort/sort.go @@ -197,7 +197,7 @@ func Float64sAreSorted(x []float64) bool { return slices.IsSorted(x) } func StringsAreSorted(x []string) bool { return slices.IsSorted(x) } // Notes on stable sorting: -// The used algorithms are simple and provable correct on all input and use +// The used algorithms are simple and provably correct on all input and use // only logarithmic additional stack space. They perform well if compared // experimentally to other stable in-place sorting algorithms. // -- cgit v1.3 From bba24719a4cad5cc8d771fc9cfff5a38019d554a Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Tue, 6 Jan 2026 14:36:01 -0800 Subject: crypto/tls: don't copy auto-rotated session ticket keys in Config.Clone Once a tls.Config is used, it is not safe to mutate. We provide the Clone method in order to allow users to copy and modify a Config that is in use. If Config.SessionTicketKey is not populated, and if Config.SetSessionTicketKeys has not been called, we automatically populate and rotate session ticket keys. Clone was previously copying these keys into the new Config, meaning that two Configs could share the same auto-rotated session ticket keys. This could allow sessions to be resumed across different Configs, which may have completely different configurations. This change updates Clone to not copy the auto-rotated session ticket keys. Additionally, when resuming a session, check that not just that the leaf certificate is unexpired, but that the entire certificate chain is still unexpired. Fixes #77113 Fixes CVE-2025-68121 Change-Id: I011df7329de83068d11b3f0c793763692d018a98 Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/3300 Reviewed-by: Damien Neil Reviewed-by: Nicholas Husin Reviewed-on: https://go-review.googlesource.com/c/go/+/736709 Auto-Submit: Michael Pratt Reviewed-by: Junyang Shao LUCI-TryBot-Result: Go LUCI --- src/crypto/tls/common.go | 7 ++- src/crypto/tls/handshake_server.go | 9 ++- src/crypto/tls/handshake_server_test.go | 101 +++++++++++++++++++++++++++++++ src/crypto/tls/handshake_server_tls13.go | 10 ++- src/crypto/tls/tls_test.go | 11 +++- 5 files changed, 132 insertions(+), 6 deletions(-) diff --git a/src/crypto/tls/common.go b/src/crypto/tls/common.go index 099a11ca63..093869ac8b 100644 --- a/src/crypto/tls/common.go +++ b/src/crypto/tls/common.go @@ -980,6 +980,10 @@ const maxSessionTicketLifetime = 7 * 24 * time.Hour // Clone returns a shallow clone of c or nil if c is nil. It is safe to clone a [Config] that is // being used concurrently by a TLS client or server. +// +// If Config.SessionTicketKey is unpopulated, and Config.SetSessionTicketKeys has not been +// called, the clone will not share the same auto-rotated session ticket keys as the original +// Config in order to prevent sessions from being resumed across Configs. func (c *Config) Clone() *Config { if c == nil { return nil @@ -1020,7 +1024,8 @@ func (c *Config) Clone() *Config { EncryptedClientHelloRejectionVerify: c.EncryptedClientHelloRejectionVerify, EncryptedClientHelloKeys: c.EncryptedClientHelloKeys, sessionTicketKeys: c.sessionTicketKeys, - autoSessionTicketKeys: c.autoSessionTicketKeys, + // We explicitly do not copy autoSessionTicketKeys, so that Configs do + // not share the same auto-rotated keys. } } diff --git a/src/crypto/tls/handshake_server.go b/src/crypto/tls/handshake_server.go index efdaeae6f7..06675a8ce9 100644 --- a/src/crypto/tls/handshake_server.go +++ b/src/crypto/tls/handshake_server.go @@ -520,8 +520,13 @@ func (hs *serverHandshakeState) checkForResumption() error { if sessionHasClientCerts && c.config.ClientAuth == NoClientCert { return nil } - if sessionHasClientCerts && c.config.time().After(sessionState.peerCertificates[0].NotAfter) { - return nil + if sessionHasClientCerts { + now := c.config.time() + for _, c := range sessionState.peerCertificates { + if now.After(c.NotAfter) { + return nil + } + } } if sessionHasClientCerts && c.config.ClientAuth >= VerifyClientCertIfGiven && len(sessionState.verifiedChains) == 0 { diff --git a/src/crypto/tls/handshake_server_test.go b/src/crypto/tls/handshake_server_test.go index 7e35c25259..41ae87050e 100644 --- a/src/crypto/tls/handshake_server_test.go +++ b/src/crypto/tls/handshake_server_test.go @@ -13,6 +13,7 @@ import ( "crypto/rand" "crypto/tls/internal/fips140tls" "crypto/x509" + "crypto/x509/pkix" "encoding/pem" "errors" "fmt" @@ -2153,3 +2154,103 @@ func TestHandshakeContextHierarchy(t *testing.T) { t.Errorf("Unexpected client error: %v", err) } } + +func TestHandshakeChainExpiryResumptionTLS12(t *testing.T) { + t.Run("TLS1.2", func(t *testing.T) { + testHandshakeChainExpiryResumption(t, VersionTLS12) + }) + t.Run("TLS1.3", func(t *testing.T) { + testHandshakeChainExpiryResumption(t, VersionTLS13) + }) +} + +func testHandshakeChainExpiryResumption(t *testing.T, version uint16) { + now := time.Now() + createChain := func(leafNotAfter, rootNotAfter time.Time) (certDER []byte, root *x509.Certificate) { + tmpl := &x509.Certificate{ + Subject: pkix.Name{CommonName: "root"}, + NotBefore: rootNotAfter.Add(-time.Hour * 24), + NotAfter: rootNotAfter, + IsCA: true, + BasicConstraintsValid: true, + } + rootDER, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &testECDSAPrivateKey.PublicKey, testECDSAPrivateKey) + if err != nil { + t.Fatalf("CreateCertificate: %v", err) + } + root, err = x509.ParseCertificate(rootDER) + if err != nil { + t.Fatalf("ParseCertificate: %v", err) + } + + tmpl = &x509.Certificate{ + Subject: pkix.Name{}, + DNSNames: []string{"expired-resume.example.com"}, + NotBefore: leafNotAfter.Add(-time.Hour * 24), + NotAfter: leafNotAfter, + KeyUsage: x509.KeyUsageDigitalSignature, + } + certDER, err = x509.CreateCertificate(rand.Reader, tmpl, root, &testECDSAPrivateKey.PublicKey, testECDSAPrivateKey) + if err != nil { + t.Fatalf("CreateCertificate: %v", err) + } + + return certDER, root + } + + initialLeafDER, initialRoot := createChain(now.Add(time.Hour), now.Add(2*time.Hour)) + + serverConfig := testConfig.Clone() + serverConfig.MaxVersion = version + serverConfig.Certificates = []Certificate{{ + Certificate: [][]byte{initialLeafDER}, + PrivateKey: testECDSAPrivateKey, + }} + serverConfig.ClientCAs = x509.NewCertPool() + serverConfig.ClientCAs.AddCert(initialRoot) + serverConfig.ClientAuth = RequireAndVerifyClientCert + serverConfig.Time = func() time.Time { + return now + } + + clientConfig := testConfig.Clone() + clientConfig.MaxVersion = version + clientConfig.Certificates = []Certificate{{ + Certificate: [][]byte{initialLeafDER}, + PrivateKey: testECDSAPrivateKey, + }} + clientConfig.RootCAs = x509.NewCertPool() + clientConfig.RootCAs.AddCert(initialRoot) + clientConfig.ServerName = "expired-resume.example.com" + clientConfig.ClientSessionCache = NewLRUClientSessionCache(32) + + testResume := func(t *testing.T, sc, cc *Config, expectResume bool) { + t.Helper() + ss, cs, err := testHandshake(t, cc, sc) + if err != nil { + t.Fatalf("handshake: %v", err) + } + if cs.DidResume != expectResume { + t.Fatalf("DidResume = %v; want %v", cs.DidResume, expectResume) + } + if ss.DidResume != expectResume { + t.Fatalf("DidResume = %v; want %v", cs.DidResume, expectResume) + } + } + + testResume(t, serverConfig, clientConfig, false) + testResume(t, serverConfig, clientConfig, true) + + freshLeafDER, freshRoot := createChain(now.Add(2*time.Hour), now.Add(3*time.Hour)) + clientConfig.Certificates = []Certificate{{ + Certificate: [][]byte{freshLeafDER}, + PrivateKey: testECDSAPrivateKey, + }} + serverConfig.Time = func() time.Time { + return now.Add(1*time.Hour + 30*time.Minute) + } + serverConfig.ClientCAs = x509.NewCertPool() + serverConfig.ClientCAs.AddCert(freshRoot) + + testResume(t, serverConfig, clientConfig, false) +} diff --git a/src/crypto/tls/handshake_server_tls13.go b/src/crypto/tls/handshake_server_tls13.go index b066924e29..0033164f65 100644 --- a/src/crypto/tls/handshake_server_tls13.go +++ b/src/crypto/tls/handshake_server_tls13.go @@ -314,6 +314,7 @@ func (hs *serverHandshakeStateTLS13) checkForResumption() error { return nil } +pskIdentityLoop: for i, identity := range hs.clientHello.pskIdentities { if i >= maxClientPSKIdentities { break @@ -366,8 +367,13 @@ func (hs *serverHandshakeStateTLS13) checkForResumption() error { if sessionHasClientCerts && c.config.ClientAuth == NoClientCert { continue } - if sessionHasClientCerts && c.config.time().After(sessionState.peerCertificates[0].NotAfter) { - continue + if sessionHasClientCerts { + now := c.config.time() + for _, c := range sessionState.peerCertificates { + if now.After(c.NotAfter) { + continue pskIdentityLoop + } + } } if sessionHasClientCerts && c.config.ClientAuth >= VerifyClientCertIfGiven && len(sessionState.verifiedChains) == 0 { diff --git a/src/crypto/tls/tls_test.go b/src/crypto/tls/tls_test.go index 39ebb9d2f1..48428e4cc9 100644 --- a/src/crypto/tls/tls_test.go +++ b/src/crypto/tls/tls_test.go @@ -935,8 +935,8 @@ func TestCloneNonFuncFields(t *testing.T) { } } // Set the unexported fields related to session ticket keys, which are copied with Clone(). - c1.autoSessionTicketKeys = []ticketKey{c1.ticketKeyFromBytes(c1.SessionTicketKey)} c1.sessionTicketKeys = []ticketKey{c1.ticketKeyFromBytes(c1.SessionTicketKey)} + // We explicitly don't copy autoSessionTicketKeys in Clone, so don't set it. c2 := c1.Clone() if !reflect.DeepEqual(&c1, c2) { @@ -2461,3 +2461,12 @@ func (s messageOnlySigner) SignMessage(rand io.Reader, msg []byte, opts crypto.S digest := h.Sum(nil) return s.Signer.Sign(rand, digest, opts) } + +func TestConfigCloneAutoSessionTicketKeys(t *testing.T) { + orig := &Config{} + orig.ticketKeys(nil) + clone := orig.Clone() + if slices.Equal(orig.autoSessionTicketKeys, clone.autoSessionTicketKeys) { + t.Fatal("autoSessionTicketKeys slice copied in Clone") + } +} -- cgit v1.3 From 94a1296a457387d1fd6eca1a9bcd44e89bdd9d55 Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Wed, 10 Dec 2025 08:13:07 -0500 Subject: cmd/go: update VCS commands to use safer flag/argument syntax In various situations, the toolchain invokes VCS commands. Some of these commands take arbitrary input, either provided by users or fetched from external sources. To prevent potential command injection vulnerabilities or misinterpretation of arguments as flags, this change updates the VCS commands to use various techniques to separate flags from positional arguments, and to directly associate flags with their values. Additionally, we update the environment variable for Mercurial to use `HGPLAIN=+strictflags`, which is the more explicit way to disable user configurations (intended or otherwise) that might interfere with command execution. We also now disallow version strings from being prefixed with '-' or '/', as doing so opens us up to making the same mistake again in the future. As far as we know there are currently ~0 public modules affected by this. While I was working on cmd/go/internal/vcs, I also noticed that a significant portion of the commands being implemented were dead code. In order to reduce the maintenance burden and surface area for potential issues, I removed the dead code for unused commands. We should probably follow up with a more structured change to make it harder to accidentally re-introduce these issues in the future, but for now this addresses the issue at hand. Thanks to splitline (@splitline) from DEVCORE Research Team for reporting this issue. Fixes CVE-2025-68119 Fixes #77099 Change-Id: I9d9f4ee05b95be49fe14edf71a1b8e6c0784378e Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/3260 Reviewed-by: Damien Neil Reviewed-by: Nicholas Husin Reviewed-on: https://go-review.googlesource.com/c/go/+/736710 Auto-Submit: Michael Pratt Reviewed-by: Junyang Shao LUCI-TryBot-Result: Go LUCI --- src/cmd/go/internal/modcmd/edit.go | 10 +- src/cmd/go/internal/modfetch/codehost/git.go | 20 +- src/cmd/go/internal/modfetch/codehost/vcs.go | 26 +- src/cmd/go/internal/modget/query.go | 5 +- src/cmd/go/internal/modload/build.go | 12 +- src/cmd/go/internal/modload/list.go | 30 ++- src/cmd/go/internal/toolchain/select.go | 7 +- src/cmd/go/internal/vcs/vcs.go | 353 +++------------------------ src/cmd/go/internal/vcs/vcs_test.go | 36 +++ src/cmd/go/internal/workcmd/edit.go | 5 +- 10 files changed, 157 insertions(+), 347 deletions(-) diff --git a/src/cmd/go/internal/modcmd/edit.go b/src/cmd/go/internal/modcmd/edit.go index 69ebb14813..cd15b822ad 100644 --- a/src/cmd/go/internal/modcmd/edit.go +++ b/src/cmd/go/internal/modcmd/edit.go @@ -328,7 +328,10 @@ func runEdit(ctx context.Context, cmd *base.Command, args []string) { // parsePathVersion parses -flag=arg expecting arg to be path@version. func parsePathVersion(flag, arg string) (path, version string) { - before, after, found := strings.Cut(arg, "@") + before, after, found, err := modload.ParsePathVersion(arg) + if err != nil { + base.Fatalf("go: -%s=%s: %v", flag, arg, err) + } if !found { base.Fatalf("go: -%s=%s: need path@version", flag, arg) } @@ -362,7 +365,10 @@ func parsePathVersionOptional(adj, arg string, allowDirPath bool) (path, version if allowDirPath && modfile.IsDirectoryPath(arg) { return arg, "", nil } - before, after, found := strings.Cut(arg, "@") + before, after, found, err := modload.ParsePathVersion(arg) + if err != nil { + return "", "", err + } if !found { path = arg } else { diff --git a/src/cmd/go/internal/modfetch/codehost/git.go b/src/cmd/go/internal/modfetch/codehost/git.go index 3d50dca3c4..6eb61772db 100644 --- a/src/cmd/go/internal/modfetch/codehost/git.go +++ b/src/cmd/go/internal/modfetch/codehost/git.go @@ -261,7 +261,7 @@ func (r *gitRepo) loadRefs(ctx context.Context) (map[string]string, error) { r.refsErr = err return } - out, gitErr := r.runGit(ctx, "git", "ls-remote", "-q", r.remote) + out, gitErr := r.runGit(ctx, "git", "ls-remote", "-q", "--end-of-options", r.remote) release() if gitErr != nil { @@ -530,7 +530,7 @@ func (r *gitRepo) stat(ctx context.Context, rev string) (info *RevInfo, err erro if fromTag && !slices.Contains(info.Tags, tag) { // The local repo includes the commit hash we want, but it is missing // the corresponding tag. Add that tag and try again. - _, err := r.runGit(ctx, "git", "tag", tag, hash) + _, err := r.runGit(ctx, "git", "tag", "--end-of-options", tag, hash) if err != nil { return nil, err } @@ -579,7 +579,7 @@ func (r *gitRepo) stat(ctx context.Context, rev string) (info *RevInfo, err erro // an apparent Git bug introduced in Git 2.21 (commit 61c771), // which causes the handler for protocol version 1 to sometimes miss // tags that point to the requested commit (see https://go.dev/issue/56881). - _, err = r.runGit(ctx, "git", "-c", "protocol.version=2", "fetch", "-f", "--depth=1", r.remote, refspec) + _, err = r.runGit(ctx, "git", "-c", "protocol.version=2", "fetch", "-f", "--depth=1", "--end-of-options", r.remote, refspec) release() if err == nil { @@ -625,12 +625,12 @@ func (r *gitRepo) fetchRefsLocked(ctx context.Context) error { } defer release() - if _, err := r.runGit(ctx, "git", "fetch", "-f", r.remote, "refs/heads/*:refs/heads/*", "refs/tags/*:refs/tags/*"); err != nil { + if _, err := r.runGit(ctx, "git", "fetch", "-f", "--end-of-options", r.remote, "refs/heads/*:refs/heads/*", "refs/tags/*:refs/tags/*"); err != nil { return err } if _, err := os.Stat(filepath.Join(r.dir, "shallow")); err == nil { - if _, err := r.runGit(ctx, "git", "fetch", "--unshallow", "-f", r.remote); err != nil { + if _, err := r.runGit(ctx, "git", "fetch", "--unshallow", "-f", "--end-of-options", r.remote); err != nil { return err } } @@ -643,7 +643,7 @@ func (r *gitRepo) fetchRefsLocked(ctx context.Context) error { // statLocal returns a new RevInfo describing rev in the local git repository. // It uses version as info.Version. func (r *gitRepo) statLocal(ctx context.Context, version, rev string) (*RevInfo, error) { - out, err := r.runGit(ctx, "git", "-c", "log.showsignature=false", "log", "--no-decorate", "-n1", "--format=format:%H %ct %D", rev, "--") + out, err := r.runGit(ctx, "git", "-c", "log.showsignature=false", "log", "--no-decorate", "-n1", "--format=format:%H %ct %D", "--end-of-options", rev, "--") if err != nil { // Return info with Origin.RepoSum if possible to allow caching of negative lookup. var info *RevInfo @@ -733,7 +733,7 @@ func (r *gitRepo) ReadFile(ctx context.Context, rev, file string, maxSize int64) if err != nil { return nil, err } - out, err := r.runGit(ctx, "git", "cat-file", "blob", info.Name+":"+file) + out, err := r.runGit(ctx, "git", "cat-file", "--end-of-options", "blob", info.Name+":"+file) if err != nil { return nil, fs.ErrNotExist } @@ -751,7 +751,7 @@ func (r *gitRepo) RecentTag(ctx context.Context, rev, prefix string, allowed fun // result is definitive. describe := func() (definitive bool) { var out []byte - out, err = r.runGit(ctx, "git", "for-each-ref", "--format", "%(refname)", "refs/tags", "--merged", rev) + out, err = r.runGit(ctx, "git", "for-each-ref", "--format=%(refname)", "--merged="+rev) if err != nil { return true } @@ -903,7 +903,7 @@ func (r *gitRepo) ReadZip(ctx context.Context, rev, subdir string, maxSize int64 // TODO: Use maxSize or drop it. args := []string{} if subdir != "" { - args = append(args, "--", subdir) + args = append(args, subdir) } info, err := r.Stat(ctx, rev) // download rev into local git repo if err != nil { @@ -925,7 +925,7 @@ func (r *gitRepo) ReadZip(ctx context.Context, rev, subdir string, maxSize int64 // text file line endings. Setting -c core.autocrlf=input means only // translate files on the way into the repo, not on the way out (archive). // The -c core.eol=lf should be unnecessary but set it anyway. - archive, err := r.runGit(ctx, "git", "-c", "core.autocrlf=input", "-c", "core.eol=lf", "archive", "--format=zip", "--prefix=prefix/", info.Name, args) + archive, err := r.runGit(ctx, "git", "-c", "core.autocrlf=input", "-c", "core.eol=lf", "archive", "--format=zip", "--prefix=prefix/", "--end-of-options", info.Name, args) if err != nil { if bytes.Contains(err.(*RunError).Stderr, []byte("did not match any files")) { return nil, fs.ErrNotExist diff --git a/src/cmd/go/internal/modfetch/codehost/vcs.go b/src/cmd/go/internal/modfetch/codehost/vcs.go index aae1a60bfa..59264a3b90 100644 --- a/src/cmd/go/internal/modfetch/codehost/vcs.go +++ b/src/cmd/go/internal/modfetch/codehost/vcs.go @@ -188,6 +188,7 @@ var vcsCmds = map[string]*vcsCmd{ "hg", "--config=extensions.goreposum=" + filepath.Join(cfg.GOROOT, "lib/hg/goreposum.py"), "goreposum", + "--", remote, } }, @@ -196,6 +197,7 @@ var vcsCmds = map[string]*vcsCmd{ "hg", "--config=extensions.goreposum=" + filepath.Join(cfg.GOROOT, "lib/hg/goreposum.py"), "golookup", + "--", remote, ref, } @@ -216,26 +218,26 @@ var vcsCmds = map[string]*vcsCmd{ branchRE: re(`(?m)^[^\n]+$`), badLocalRevRE: re(`(?m)^(tip)$`), statLocal: func(rev, remote string) []string { - return []string{"hg", "log", "-l1", "-r", rev, "--template", "{node} {date|hgdate} {tags}"} + return []string{"hg", "log", "-l1", fmt.Sprintf("--rev=%s", rev), "--template", "{node} {date|hgdate} {tags}"} }, parseStat: hgParseStat, fetch: []string{"hg", "pull", "-f"}, latest: "tip", descendsFrom: func(rev, tag string) []string { - return []string{"hg", "log", "-r", "ancestors(" + rev + ") and " + tag} + return []string{"hg", "log", "--rev=ancestors(" + rev + ") and " + tag} }, recentTags: func(rev string) []string { - return []string{"hg", "log", "-r", "ancestors(" + rev + ") and tag()", "--template", "{tags}\n"} + return []string{"hg", "log", "--rev=ancestors(" + rev + ") and tag()", "--template", "{tags}\n"} }, readFile: func(rev, file, remote string) []string { - return []string{"hg", "cat", "-r", rev, file} + return []string{"hg", "cat", fmt.Sprintf("--rev=%s", rev), "--", file} }, readZip: func(rev, subdir, remote, target string) []string { pattern := []string{} if subdir != "" { - pattern = []string{"-I", subdir + "/**"} + pattern = []string{fmt.Sprintf("--include=%s", subdir+"/**")} } - return str.StringList("hg", "archive", "-t", "zip", "--no-decode", "-r", rev, "--prefix=prefix/", pattern, "--", target) + return str.StringList("hg", "archive", "-t", "zip", "--no-decode", fmt.Sprintf("--rev=%s", rev), "--prefix=prefix/", pattern, "--", target) }, }, @@ -275,19 +277,19 @@ var vcsCmds = map[string]*vcsCmd{ tagRE: re(`(?m)^\S+`), badLocalRevRE: re(`^revno:-`), statLocal: func(rev, remote string) []string { - return []string{"bzr", "log", "-l1", "--long", "--show-ids", "-r", rev} + return []string{"bzr", "log", "-l1", "--long", "--show-ids", fmt.Sprintf("--revision=%s", rev)} }, parseStat: bzrParseStat, latest: "revno:-1", readFile: func(rev, file, remote string) []string { - return []string{"bzr", "cat", "-r", rev, file} + return []string{"bzr", "cat", fmt.Sprintf("--revision=%s", rev), "--", file} }, readZip: func(rev, subdir, remote, target string) []string { extra := []string{} if subdir != "" { extra = []string{"./" + subdir} } - return str.StringList("bzr", "export", "--format=zip", "-r", rev, "--root=prefix/", "--", target, extra) + return str.StringList("bzr", "export", "--format=zip", fmt.Sprintf("--revision=%s", rev), "--root=prefix/", "--", target, extra) }, }, @@ -302,17 +304,17 @@ var vcsCmds = map[string]*vcsCmd{ }, tagRE: re(`XXXTODO`), statLocal: func(rev, remote string) []string { - return []string{"fossil", "info", "-R", ".fossil", rev} + return []string{"fossil", "info", "-R", ".fossil", "--", rev} }, parseStat: fossilParseStat, latest: "trunk", readFile: func(rev, file, remote string) []string { - return []string{"fossil", "cat", "-R", ".fossil", "-r", rev, file} + return []string{"fossil", "cat", "-R", ".fossil", fmt.Sprintf("-r=%s", rev), "--", file} }, readZip: func(rev, subdir, remote, target string) []string { extra := []string{} if subdir != "" && !strings.ContainsAny(subdir, "*?[],") { - extra = []string{"--include", subdir} + extra = []string{fmt.Sprintf("--include=%s", subdir)} } // Note that vcsRepo.ReadZip below rewrites this command // to run in a different directory, to work around a fossil bug. diff --git a/src/cmd/go/internal/modget/query.go b/src/cmd/go/internal/modget/query.go index 3086dbc1ad..e9807edda5 100644 --- a/src/cmd/go/internal/modget/query.go +++ b/src/cmd/go/internal/modget/query.go @@ -140,7 +140,10 @@ func errSet(err error) pathSet { return pathSet{err: err} } // newQuery returns a new query parsed from the raw argument, // which must be either path or path@version. func newQuery(loaderstate *modload.State, raw string) (*query, error) { - pattern, rawVers, found := strings.Cut(raw, "@") + pattern, rawVers, found, err := modload.ParsePathVersion(raw) + if err != nil { + return nil, err + } if found && (strings.Contains(rawVers, "@") || rawVers == "") { return nil, fmt.Errorf("invalid module version syntax %q", raw) } diff --git a/src/cmd/go/internal/modload/build.go b/src/cmd/go/internal/modload/build.go index b560dd6a61..cb4371357c 100644 --- a/src/cmd/go/internal/modload/build.go +++ b/src/cmd/go/internal/modload/build.go @@ -12,7 +12,6 @@ import ( "io/fs" "os" "path/filepath" - "strings" "cmd/go/internal/base" "cmd/go/internal/cfg" @@ -88,7 +87,16 @@ func ModuleInfo(loaderstate *State, ctx context.Context, path string) *modinfo.M return nil } - if path, vers, found := strings.Cut(path, "@"); found { + path, vers, found, err := ParsePathVersion(path) + if err != nil { + return &modinfo.ModulePublic{ + Path: path, + Error: &modinfo.ModuleError{ + Err: err.Error(), + }, + } + } + if found { m := module.Version{Path: path, Version: vers} return moduleInfo(loaderstate, ctx, nil, m, 0, nil) } diff --git a/src/cmd/go/internal/modload/list.go b/src/cmd/go/internal/modload/list.go index 316fda4003..32f8c5fe3d 100644 --- a/src/cmd/go/internal/modload/list.go +++ b/src/cmd/go/internal/modload/list.go @@ -150,7 +150,11 @@ func listModules(loaderstate *State, ctx context.Context, rs *Requirements, args } continue } - if path, vers, found := strings.Cut(arg, "@"); found { + path, vers, found, err := ParsePathVersion(arg) + if err != nil { + base.Fatalf("go: %v", err) + } + if found { if vers == "upgrade" || vers == "patch" { if _, ok := rs.rootSelected(loaderstate, path); !ok || rs.pruning == unpruned { needFullGraph = true @@ -176,7 +180,11 @@ func listModules(loaderstate *State, ctx context.Context, rs *Requirements, args matchedModule := map[module.Version]bool{} for _, arg := range args { - if path, vers, found := strings.Cut(arg, "@"); found { + path, vers, found, err := ParsePathVersion(arg) + if err != nil { + base.Fatalf("go: %v", err) + } + if found { var current string if mg == nil { current, _ = rs.rootSelected(loaderstate, path) @@ -317,3 +325,21 @@ func modinfoError(path, vers string, err error) *modinfo.ModuleError { return &modinfo.ModuleError{Err: err.Error()} } + +// ParsePathVersion parses arg expecting arg to be path@version. If there is no +// '@' in arg, found is false, vers is "", and path is arg. This mirrors the +// typical usage of strings.Cut. ParsePathVersion is meant to be a general +// replacement for strings.Cut in module version parsing. If the version is +// invalid, an error is returned. The version is considered invalid if it is +// prefixed with '-' or '/', which can cause security problems when constructing +// commands to execute that use the version. +func ParsePathVersion(arg string) (path, vers string, found bool, err error) { + path, vers, found = strings.Cut(arg, "@") + if !found { + return arg, "", false, nil + } + if len(vers) > 0 && (vers[0] == '-' || vers[0] == '/') { + return "", "", false, fmt.Errorf("invalid module version %q", vers) + } + return path, vers, true, nil +} diff --git a/src/cmd/go/internal/toolchain/select.go b/src/cmd/go/internal/toolchain/select.go index 192fb62fc2..0cb93f67e1 100644 --- a/src/cmd/go/internal/toolchain/select.go +++ b/src/cmd/go/internal/toolchain/select.go @@ -667,7 +667,10 @@ func maybeSwitchForGoInstallVersion(loaderstate *modload.State, minVers string) if !strings.Contains(pkgArg, "@") || build.IsLocalImport(pkgArg) || filepath.IsAbs(pkgArg) { return } - path, version, _ := strings.Cut(pkgArg, "@") + path, version, _, err := modload.ParsePathVersion(pkgArg) + if err != nil { + base.Fatalf("go: %v", err) + } if path == "" || version == "" || gover.IsToolchain(path) { return } @@ -702,7 +705,7 @@ func maybeSwitchForGoInstallVersion(loaderstate *modload.State, minVers string) allowed = nil } noneSelected := func(path string) (version string) { return "none" } - _, err := modload.QueryPackages(loaderstate, ctx, path, version, noneSelected, allowed) + _, err = modload.QueryPackages(loaderstate, ctx, path, version, noneSelected, allowed) if errors.Is(err, gover.ErrTooNew) { // Run early switch, same one go install or go run would eventually do, // if it understood all the command-line flags. diff --git a/src/cmd/go/internal/vcs/vcs.go b/src/cmd/go/internal/vcs/vcs.go index 7c198c5f2b..9e8efaf206 100644 --- a/src/cmd/go/internal/vcs/vcs.go +++ b/src/cmd/go/internal/vcs/vcs.go @@ -17,7 +17,6 @@ import ( "os" "os/exec" "path/filepath" - "regexp" "strconv" "strings" "sync" @@ -41,20 +40,10 @@ type Cmd struct { Env []string // any environment values to set/override RootNames []rootName // filename and mode indicating the root of a checkout directory - CreateCmd []string // commands to download a fresh copy of a repository - DownloadCmd []string // commands to download updates into an existing repository - - TagCmd []tagCmd // commands to list tags - TagLookupCmd []tagCmd // commands to lookup tags before running tagSyncCmd - TagSyncCmd []string // commands to sync to specific tag - TagSyncDefault []string // commands to sync to default tag - Scheme []string PingCmd string - RemoteRepo func(v *Cmd, rootDir string) (remoteRepo string, err error) - ResolveRepo func(v *Cmd, rootDir, remoteRepo string) (realRepo string, err error) - Status func(v *Cmd, rootDir string) (Status, error) + Status func(v *Cmd, rootDir string) (Status, error) } // Status is the current state of a local repository. @@ -157,40 +146,16 @@ var vcsHg = &Cmd{ Name: "Mercurial", Cmd: "hg", - // HGPLAIN=1 turns off additional output that a user may have enabled via - // config options or certain extensions. - Env: []string{"HGPLAIN=1"}, + // HGPLAIN=+strictflags turns off additional output that a user may have + // enabled via config options or certain extensions. + Env: []string{"HGPLAIN=+strictflags"}, RootNames: []rootName{ {filename: ".hg", isDir: true}, }, - CreateCmd: []string{"clone -U -- {repo} {dir}"}, - DownloadCmd: []string{"pull"}, - - // We allow both tag and branch names as 'tags' - // for selecting a version. This lets people have - // a go.release.r60 branch and a go1 branch - // and make changes in both, without constantly - // editing .hgtags. - TagCmd: []tagCmd{ - {"tags", `^(\S+)`}, - {"branches", `^(\S+)`}, - }, - TagSyncCmd: []string{"update -r {tag}"}, - TagSyncDefault: []string{"update default"}, - - Scheme: []string{"https", "http", "ssh"}, - PingCmd: "identify -- {scheme}://{repo}", - RemoteRepo: hgRemoteRepo, - Status: hgStatus, -} - -func hgRemoteRepo(vcsHg *Cmd, rootDir string) (remoteRepo string, err error) { - out, err := vcsHg.runOutput(rootDir, "paths default") - if err != nil { - return "", err - } - return strings.TrimSpace(string(out)), nil + Scheme: []string{"https", "http", "ssh"}, + PingCmd: "identify -- {scheme}://{repo}", + Status: hgStatus, } func hgStatus(vcsHg *Cmd, rootDir string) (Status, error) { @@ -253,25 +218,6 @@ var vcsGit = &Cmd{ {filename: ".git", isDir: true}, }, - CreateCmd: []string{"clone -- {repo} {dir}", "-go-internal-cd {dir} submodule update --init --recursive"}, - DownloadCmd: []string{"pull --ff-only", "submodule update --init --recursive"}, - - TagCmd: []tagCmd{ - // tags/xxx matches a git tag named xxx - // origin/xxx matches a git branch named xxx on the default remote repository - {"show-ref", `(?:tags|origin)/(\S+)$`}, - }, - TagLookupCmd: []tagCmd{ - {"show-ref tags/{tag} origin/{tag}", `((?:tags|origin)/\S+)$`}, - }, - TagSyncCmd: []string{"checkout {tag}", "submodule update --init --recursive"}, - // both createCmd and downloadCmd update the working dir. - // No need to do more here. We used to 'checkout master' - // but that doesn't work if the default branch is not named master. - // DO NOT add 'checkout master' here. - // See golang.org/issue/9032. - TagSyncDefault: []string{"submodule update --init --recursive"}, - Scheme: []string{"git", "https", "http", "git+ssh", "ssh"}, // Leave out the '--' separator in the ls-remote command: git 2.7.4 does not @@ -280,54 +226,7 @@ var vcsGit = &Cmd{ // See golang.org/issue/33836. PingCmd: "ls-remote {scheme}://{repo}", - RemoteRepo: gitRemoteRepo, - Status: gitStatus, -} - -// scpSyntaxRe matches the SCP-like addresses used by Git to access -// repositories by SSH. -var scpSyntaxRe = lazyregexp.New(`^(\w+)@([\w.-]+):(.*)$`) - -func gitRemoteRepo(vcsGit *Cmd, rootDir string) (remoteRepo string, err error) { - const cmd = "config remote.origin.url" - outb, err := vcsGit.run1(rootDir, cmd, nil, false) - if err != nil { - // if it doesn't output any message, it means the config argument is correct, - // but the config value itself doesn't exist - if outb != nil && len(outb) == 0 { - return "", errors.New("remote origin not found") - } - return "", err - } - out := strings.TrimSpace(string(outb)) - - var repoURL *urlpkg.URL - if m := scpSyntaxRe.FindStringSubmatch(out); m != nil { - // Match SCP-like syntax and convert it to a URL. - // Eg, "git@github.com:user/repo" becomes - // "ssh://git@github.com/user/repo". - repoURL = &urlpkg.URL{ - Scheme: "ssh", - User: urlpkg.User(m[1]), - Host: m[2], - Path: m[3], - } - } else { - repoURL, err = urlpkg.Parse(out) - if err != nil { - return "", err - } - } - - // Iterate over insecure schemes too, because this function simply - // reports the state of the repo. If we can't see insecure schemes then - // we can't report the actual repo URL. - for _, s := range vcsGit.Scheme { - if repoURL.Scheme == s { - return repoURL.String(), nil - } - } - return "", errors.New("unable to parse output of git " + cmd) + Status: gitStatus, } func gitStatus(vcsGit *Cmd, rootDir string) (Status, error) { @@ -367,62 +266,9 @@ var vcsBzr = &Cmd{ {filename: ".bzr", isDir: true}, }, - CreateCmd: []string{"branch -- {repo} {dir}"}, - - // Without --overwrite bzr will not pull tags that changed. - // Replace by --overwrite-tags after http://pad.lv/681792 goes in. - DownloadCmd: []string{"pull --overwrite"}, - - TagCmd: []tagCmd{{"tags", `^(\S+)`}}, - TagSyncCmd: []string{"update -r {tag}"}, - TagSyncDefault: []string{"update -r revno:-1"}, - - Scheme: []string{"https", "http", "bzr", "bzr+ssh"}, - PingCmd: "info -- {scheme}://{repo}", - RemoteRepo: bzrRemoteRepo, - ResolveRepo: bzrResolveRepo, - Status: bzrStatus, -} - -func bzrRemoteRepo(vcsBzr *Cmd, rootDir string) (remoteRepo string, err error) { - outb, err := vcsBzr.runOutput(rootDir, "config parent_location") - if err != nil { - return "", err - } - return strings.TrimSpace(string(outb)), nil -} - -func bzrResolveRepo(vcsBzr *Cmd, rootDir, remoteRepo string) (realRepo string, err error) { - outb, err := vcsBzr.runOutput(rootDir, "info "+remoteRepo) - if err != nil { - return "", err - } - out := string(outb) - - // Expect: - // ... - // (branch root|repository branch): - // ... - - found := false - for _, prefix := range []string{"\n branch root: ", "\n repository branch: "} { - i := strings.Index(out, prefix) - if i >= 0 { - out = out[i+len(prefix):] - found = true - break - } - } - if !found { - return "", fmt.Errorf("unable to parse output of bzr info") - } - - i := strings.Index(out, "\n") - if i < 0 { - return "", fmt.Errorf("unable to parse output of bzr info") - } - out = out[:i] - return strings.TrimSpace(out), nil + Scheme: []string{"https", "http", "bzr", "bzr+ssh"}, + PingCmd: "info -- {scheme}://{repo}", + Status: bzrStatus, } func bzrStatus(vcsBzr *Cmd, rootDir string) (Status, error) { @@ -490,46 +336,12 @@ var vcsSvn = &Cmd{ {filename: ".svn", isDir: true}, }, - CreateCmd: []string{"checkout -- {repo} {dir}"}, - DownloadCmd: []string{"update"}, - // There is no tag command in subversion. // The branch information is all in the path names. - Scheme: []string{"https", "http", "svn", "svn+ssh"}, - PingCmd: "info -- {scheme}://{repo}", - RemoteRepo: svnRemoteRepo, - Status: svnStatus, -} - -func svnRemoteRepo(vcsSvn *Cmd, rootDir string) (remoteRepo string, err error) { - outb, err := vcsSvn.runOutput(rootDir, "info") - if err != nil { - return "", err - } - out := string(outb) - - // Expect: - // - // ... - // URL: - // ... - // - // Note that we're not using the Repository Root line, - // because svn allows checking out subtrees. - // The URL will be the URL of the subtree (what we used with 'svn co') - // while the Repository Root may be a much higher parent. - i := strings.Index(out, "\nURL: ") - if i < 0 { - return "", fmt.Errorf("unable to parse output of svn info") - } - out = out[i+len("\nURL: "):] - i = strings.Index(out, "\n") - if i < 0 { - return "", fmt.Errorf("unable to parse output of svn info") - } - out = out[:i] - return strings.TrimSpace(out), nil + Scheme: []string{"https", "http", "svn", "svn+ssh"}, + PingCmd: "info -- {scheme}://{repo}", + Status: svnStatus, } func svnStatus(vcsSvn *Cmd, rootDir string) (Status, error) { @@ -574,24 +386,8 @@ var vcsFossil = &Cmd{ {filename: "_FOSSIL_", isDir: false}, }, - CreateCmd: []string{"-go-internal-mkdir {dir} clone -- {repo} " + filepath.Join("{dir}", fossilRepoName), "-go-internal-cd {dir} open .fossil"}, - DownloadCmd: []string{"up"}, - - TagCmd: []tagCmd{{"tag ls", `(.*)`}}, - TagSyncCmd: []string{"up tag:{tag}"}, - TagSyncDefault: []string{"up trunk"}, - - Scheme: []string{"https", "http"}, - RemoteRepo: fossilRemoteRepo, - Status: fossilStatus, -} - -func fossilRemoteRepo(vcsFossil *Cmd, rootDir string) (remoteRepo string, err error) { - out, err := vcsFossil.runOutput(rootDir, "remote-url") - if err != nil { - return "", err - } - return strings.TrimSpace(string(out)), nil + Scheme: []string{"https", "http"}, + Status: fossilStatus, } var errFossilInfo = errors.New("unable to parse output of fossil info") @@ -692,7 +488,7 @@ func (v *Cmd) run1(dir string, cmdline string, keyval []string, verbose bool) ([ args[i] = expand(m, arg) } - if len(args) >= 2 && args[0] == "-go-internal-mkdir" { + if len(args) >= 2 && args[0] == "--go-internal-mkdir" { var err error if filepath.IsAbs(args[1]) { err = os.Mkdir(args[1], fs.ModePerm) @@ -705,7 +501,7 @@ func (v *Cmd) run1(dir string, cmdline string, keyval []string, verbose bool) ([ args = args[2:] } - if len(args) >= 2 && args[0] == "-go-internal-cd" { + if len(args) >= 2 && args[0] == "--go-internal-cd" { if filepath.IsAbs(args[1]) { dir = args[1] } else { @@ -766,99 +562,6 @@ func (v *Cmd) Ping(scheme, repo string) error { return v.runVerboseOnly(dir, v.PingCmd, "scheme", scheme, "repo", repo) } -// Create creates a new copy of repo in dir. -// The parent of dir must exist; dir must not. -func (v *Cmd) Create(dir, repo string) error { - release, err := base.AcquireNet() - if err != nil { - return err - } - defer release() - - for _, cmd := range v.CreateCmd { - if err := v.run(filepath.Dir(dir), cmd, "dir", dir, "repo", repo); err != nil { - return err - } - } - return nil -} - -// Download downloads any new changes for the repo in dir. -func (v *Cmd) Download(dir string) error { - release, err := base.AcquireNet() - if err != nil { - return err - } - defer release() - - for _, cmd := range v.DownloadCmd { - if err := v.run(dir, cmd); err != nil { - return err - } - } - return nil -} - -// Tags returns the list of available tags for the repo in dir. -func (v *Cmd) Tags(dir string) ([]string, error) { - var tags []string - for _, tc := range v.TagCmd { - out, err := v.runOutput(dir, tc.cmd) - if err != nil { - return nil, err - } - re := regexp.MustCompile(`(?m-s)` + tc.pattern) - for _, m := range re.FindAllStringSubmatch(string(out), -1) { - tags = append(tags, m[1]) - } - } - return tags, nil -} - -// TagSync syncs the repo in dir to the named tag, -// which either is a tag returned by tags or is v.tagDefault. -func (v *Cmd) TagSync(dir, tag string) error { - if v.TagSyncCmd == nil { - return nil - } - if tag != "" { - for _, tc := range v.TagLookupCmd { - out, err := v.runOutput(dir, tc.cmd, "tag", tag) - if err != nil { - return err - } - re := regexp.MustCompile(`(?m-s)` + tc.pattern) - m := re.FindStringSubmatch(string(out)) - if len(m) > 1 { - tag = m[1] - break - } - } - } - - release, err := base.AcquireNet() - if err != nil { - return err - } - defer release() - - if tag == "" && v.TagSyncDefault != nil { - for _, cmd := range v.TagSyncDefault { - if err := v.run(dir, cmd); err != nil { - return err - } - } - return nil - } - - for _, cmd := range v.TagSyncCmd { - if err := v.run(dir, cmd, "tag", tag); err != nil { - return err - } - } - return nil -} - // A vcsPath describes how to convert an import path into a // version control system and repository name. type vcsPath struct { @@ -1385,6 +1088,10 @@ func repoRootForImportDynamic(importPath string, mod ModuleMode, security web.Se } } + if err := validateRepoSubDir(mmi.SubDir); err != nil { + return nil, fmt.Errorf("%s: invalid subdirectory %q: %v", resp.URL, mmi.SubDir, err) + } + if err := validateRepoRoot(mmi.RepoRoot); err != nil { return nil, fmt.Errorf("%s: invalid repo root %q: %v", resp.URL, mmi.RepoRoot, err) } @@ -1416,6 +1123,22 @@ func repoRootForImportDynamic(importPath string, mod ModuleMode, security web.Se return rr, nil } +// validateRepoSubDir returns an error if subdir is not a valid subdirectory path. +// We consider a subdirectory path to be valid as long as it doesn't have a leading +// slash (/) or hyphen (-). +func validateRepoSubDir(subdir string) error { + if subdir == "" { + return nil + } + if subdir[0] == '/' { + return errors.New("leading slash") + } + if subdir[0] == '-' { + return errors.New("leading hyphen") + } + return nil +} + // validateRepoRoot returns an error if repoRoot does not seem to be // a valid URL with scheme. func validateRepoRoot(repoRoot string) error { diff --git a/src/cmd/go/internal/vcs/vcs_test.go b/src/cmd/go/internal/vcs/vcs_test.go index 361d85bcfb..ab70e517e2 100644 --- a/src/cmd/go/internal/vcs/vcs_test.go +++ b/src/cmd/go/internal/vcs/vcs_test.go @@ -507,6 +507,42 @@ func TestValidateRepoRoot(t *testing.T) { } } +func TestValidateRepoSubDir(t *testing.T) { + tests := []struct { + subdir string + ok bool + }{ + { + subdir: "", + ok: true, + }, + { + subdir: "sub/dir", + ok: true, + }, + { + subdir: "/leading/slash", + ok: false, + }, + { + subdir: "-leading/hyphen", + ok: false, + }, + } + + for _, test := range tests { + err := validateRepoSubDir(test.subdir) + ok := err == nil + if ok != test.ok { + want := "error" + if test.ok { + want = "nil" + } + t.Errorf("validateRepoSubDir(%q) = %q, want %s", test.subdir, err, want) + } + } +} + var govcsTests = []struct { govcs string path string diff --git a/src/cmd/go/internal/workcmd/edit.go b/src/cmd/go/internal/workcmd/edit.go index b18098ba5d..9b62dbb15f 100644 --- a/src/cmd/go/internal/workcmd/edit.go +++ b/src/cmd/go/internal/workcmd/edit.go @@ -279,7 +279,10 @@ func allowedVersionArg(arg string) bool { // parsePathVersionOptional parses path[@version], using adj to // describe any errors. func parsePathVersionOptional(adj, arg string, allowDirPath bool) (path, version string, err error) { - before, after, found := strings.Cut(arg, "@") + before, after, found, err := modload.ParsePathVersion(arg) + if err != nil { + return "", "", err + } if !found { path = arg } else { -- cgit v1.3 From 5e1ad12db93611b13d2be176fdc276330dc52b98 Mon Sep 17 00:00:00 2001 From: Neal Patel Date: Thu, 4 Dec 2025 12:30:39 -0500 Subject: cmd/go/internal/work: sanitize flags before invoking 'pkg-config' The addition of CgoPkgConfig allowed execution with flags not matching the safelist. In order to prevent potential arbitrary code execution at build time, ensure that flags are validated prior to invoking the 'pkg-config' binary. Thank you to RyotaK (https://ryotak.net) of GMO Flatt Security Inc. for reporting this issue. Fixes CVE-2025-61731 Fixes #77100 Change-Id: Ic51b41f1f7e697ab98c9c32c6fae35f217f7f364 Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/3240 Reviewed-by: Nicholas Husin Reviewed-by: Damien Neil Reviewed-on: https://go-review.googlesource.com/c/go/+/736711 Reviewed-by: Junyang Shao Auto-Submit: Michael Pratt LUCI-TryBot-Result: Go LUCI --- src/cmd/go/internal/work/exec.go | 8 ++++++++ src/cmd/go/internal/work/security.go | 1 + 2 files changed, 9 insertions(+) diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go index 0afdce2356..c497135612 100644 --- a/src/cmd/go/internal/work/exec.go +++ b/src/cmd/go/internal/work/exec.go @@ -1788,6 +1788,14 @@ func (b *Builder) getPkgConfigFlags(a *Action, p *load.Package) (cflags, ldflags return nil, nil, fmt.Errorf("invalid pkg-config package name: %s", pkg) } } + + // Running 'pkg-config' can cause execution of + // arbitrary code using flags that are not in + // the safelist. + if err := checkCompilerFlags("CFLAGS", "pkg-config --cflags", pcflags); err != nil { + return nil, nil, err + } + var out []byte out, err = sh.runOut(p.Dir, nil, b.PkgconfigCmd(), "--cflags", pcflags, "--", pkgs) if err != nil { diff --git a/src/cmd/go/internal/work/security.go b/src/cmd/go/internal/work/security.go index ffa83e0591..80b3f8797c 100644 --- a/src/cmd/go/internal/work/security.go +++ b/src/cmd/go/internal/work/security.go @@ -129,6 +129,7 @@ var validCompilerFlags = []*lazyregexp.Regexp{ re(`-pedantic(-errors)?`), re(`-pipe`), re(`-pthread`), + re(`--static`), re(`-?-std=([^@\-].*)`), re(`-?-stdlib=([^@\-].*)`), re(`--sysroot=([^@\-].*)`), -- cgit v1.3 From 2dcaaa751295597e1f603b7488c4624db6a84d2b Mon Sep 17 00:00:00 2001 From: Damien Neil Date: Mon, 3 Nov 2025 14:28:47 -0800 Subject: net/url: add urlmaxqueryparams GODEBUG to limit the number of query parameters net/url does not currently limit the number of query parameters parsed by url.ParseQuery or URL.Query. When parsing a application/x-www-form-urlencoded form, net/http.Request.ParseForm will parse up to 10 MB of query parameters. An input consisting of a large number of small, unique parameters can cause excessive memory consumption. We now limit the number of query parameters parsed to 10000 by default. The limit can be adjusted by setting GODEBUG=urlmaxqueryparams=. Setting urlmaxqueryparams to 0 disables the limit. Thanks to jub0bs for reporting this issue. Fixes #77101 Fixes CVE-2025-61726 Change-Id: Iee3374c7ee2d8586dbf158536d3ade424203ff66 Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/3020 Reviewed-by: Nicholas Husin Reviewed-by: Neal Patel Reviewed-on: https://go-review.googlesource.com/c/go/+/736712 Auto-Submit: Michael Pratt Reviewed-by: Junyang Shao LUCI-TryBot-Result: Go LUCI --- doc/godebug.md | 7 ++++++ src/internal/godebugs/table.go | 1 + src/net/url/url.go | 23 ++++++++++++++++++++ src/net/url/url_test.go | 48 ++++++++++++++++++++++++++++++++++++++++++ src/runtime/metrics/doc.go | 5 +++++ 5 files changed, 84 insertions(+) diff --git a/doc/godebug.md b/doc/godebug.md index 28a2dc506e..184e161c40 100644 --- a/doc/godebug.md +++ b/doc/godebug.md @@ -163,6 +163,13 @@ will fail early. The default value is `httpcookiemaxnum=3000`. Setting number of cookies. To avoid denial of service attacks, this setting and default was backported to Go 1.25.2 and Go 1.24.8. +Go 1.26 added a new `urlmaxqueryparams` setting that controls the maximum number +of query parameters that net/url will accept when parsing a URL-encoded query string. +If the number of parameters exceeds the number set in `urlmaxqueryparams`, +parsing will fail early. The default value is `urlmaxqueryparams=10000`. +Setting `urlmaxqueryparams=0`bles the limit. To avoid denial of service attacks, +this setting and default was backported to Go 1.25.4 and Go 1.24.10. + Go 1.26 added a new `urlstrictcolons` setting that controls whether `net/url.Parse` allows malformed hostnames containing colons outside of a bracketed IPv6 address. The default `urlstrictcolons=1` rejects URLs such as `http://localhost:1:2` or `http://::1/`. diff --git a/src/internal/godebugs/table.go b/src/internal/godebugs/table.go index 8f6d8bbdda..87b499385a 100644 --- a/src/internal/godebugs/table.go +++ b/src/internal/godebugs/table.go @@ -69,6 +69,7 @@ var All = []Info{ {Name: "tlssha1", Package: "crypto/tls", Changed: 25, Old: "1"}, {Name: "tlsunsafeekm", Package: "crypto/tls", Changed: 22, Old: "1"}, {Name: "updatemaxprocs", Package: "runtime", Changed: 25, Old: "0"}, + {Name: "urlmaxqueryparams", Package: "net/url", Changed: 24, Old: "0"}, {Name: "urlstrictcolons", Package: "net/url", Changed: 26, Old: "0"}, {Name: "winreadlinkvolume", Package: "os", Changed: 23, Old: "0"}, {Name: "winsymlink", Package: "os", Changed: 23, Old: "0"}, diff --git a/src/net/url/url.go b/src/net/url/url.go index 3acd202c24..202957a3a2 100644 --- a/src/net/url/url.go +++ b/src/net/url/url.go @@ -929,7 +929,30 @@ func ParseQuery(query string) (Values, error) { return m, err } +var urlmaxqueryparams = godebug.New("urlmaxqueryparams") + +const defaultMaxParams = 10000 + +func urlParamsWithinMax(params int) bool { + withinDefaultMax := params <= defaultMaxParams + if urlmaxqueryparams.Value() == "" { + return withinDefaultMax + } + customMax, err := strconv.Atoi(urlmaxqueryparams.Value()) + if err != nil { + return withinDefaultMax + } + withinCustomMax := customMax == 0 || params < customMax + if withinDefaultMax != withinCustomMax { + urlmaxqueryparams.IncNonDefault() + } + return withinCustomMax +} + func parseQuery(m Values, query string) (err error) { + if !urlParamsWithinMax(strings.Count(query, "&") + 1) { + return errors.New("number of URL query parameters exceeded limit") + } for query != "" { var key string key, query, _ = strings.Cut(query, "&") diff --git a/src/net/url/url_test.go b/src/net/url/url_test.go index bb48bb6bee..d099353eb2 100644 --- a/src/net/url/url_test.go +++ b/src/net/url/url_test.go @@ -1521,6 +1521,54 @@ func TestParseQuery(t *testing.T) { } } +func TestParseQueryLimits(t *testing.T) { + for _, test := range []struct { + params int + godebug string + wantErr bool + }{{ + params: 10, + wantErr: false, + }, { + params: defaultMaxParams, + wantErr: false, + }, { + params: defaultMaxParams + 1, + wantErr: true, + }, { + params: 10, + godebug: "urlmaxqueryparams=9", + wantErr: true, + }, { + params: defaultMaxParams + 1, + godebug: "urlmaxqueryparams=0", + wantErr: false, + }} { + t.Setenv("GODEBUG", test.godebug) + want := Values{} + var b strings.Builder + for i := range test.params { + if i > 0 { + b.WriteString("&") + } + p := fmt.Sprintf("p%v", i) + b.WriteString(p) + want[p] = []string{""} + } + query := b.String() + got, err := ParseQuery(query) + if gotErr, wantErr := err != nil, test.wantErr; gotErr != wantErr { + t.Errorf("GODEBUG=%v ParseQuery(%v params) = %v, want error: %v", test.godebug, test.params, err, wantErr) + } + if err != nil { + continue + } + if got, want := len(got), test.params; got != want { + t.Errorf("GODEBUG=%v ParseQuery(%v params): got %v params, want %v", test.godebug, test.params, got, want) + } + } +} + type RequestURITest struct { url *URL out string diff --git a/src/runtime/metrics/doc.go b/src/runtime/metrics/doc.go index ca032f51b1..6b774c36f3 100644 --- a/src/runtime/metrics/doc.go +++ b/src/runtime/metrics/doc.go @@ -404,6 +404,11 @@ Below is the full list of supported metrics, ordered lexicographically. The number of non-default behaviors executed by the runtime package due to a non-default GODEBUG=updatemaxprocs=... setting. + /godebug/non-default-behavior/urlmaxqueryparams:events + The number of non-default behaviors executed by the net/url + package due to a non-default GODEBUG=urlmaxqueryparams=... + setting. + /godebug/non-default-behavior/urlstrictcolons:events The number of non-default behaviors executed by the net/url package due to a non-default GODEBUG=urlstrictcolons=... -- cgit v1.3 From bb7c0c717c8b3517210dce8f38cb2c91694af4e2 Mon Sep 17 00:00:00 2001 From: Damien Neil Date: Tue, 4 Nov 2025 17:00:33 -0800 Subject: archive/zip: reduce CPU usage in index construction MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Constructing the zip index (which is done once when first opening a file in an archive) can consume large amounts of CPU when processing deeply-nested directory paths. Switch to a less inefficient algorithm. Thanks to Jakub Ciolek for reporting this issue. goos: darwin goarch: arm64 pkg: archive/zip cpu: Apple M4 Pro │ /tmp/bench.0 │ /tmp/bench.1 │ │ sec/op │ sec/op vs base │ ReaderOneDeepDir-14 25983.62m ± 2% 46.01m ± 2% -99.82% (p=0.000 n=8) ReaderManyDeepDirs-14 16.221 ± 1% 2.763 ± 6% -82.96% (p=0.000 n=8) ReaderManyShallowFiles-14 130.3m ± 1% 128.8m ± 2% -1.20% (p=0.003 n=8) geomean 3.801 253.9m -93.32% Fixes #77102 Fixes CVE-2025-61728 Change-Id: I2c9c864be01b2a2769eb67fbab1b250aeb8f6c42 Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/3060 Reviewed-by: Nicholas Husin Reviewed-by: Neal Patel Reviewed-on: https://go-review.googlesource.com/c/go/+/736713 Auto-Submit: Michael Pratt LUCI-TryBot-Result: Go LUCI Reviewed-by: Junyang Shao --- src/archive/zip/reader.go | 11 +++++- src/archive/zip/reader_test.go | 81 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+), 1 deletion(-) diff --git a/src/archive/zip/reader.go b/src/archive/zip/reader.go index 6b57f767fc..b2a4ed6042 100644 --- a/src/archive/zip/reader.go +++ b/src/archive/zip/reader.go @@ -834,7 +834,16 @@ func (r *Reader) initFileList() { continue } - for dir := path.Dir(name); dir != "."; dir = path.Dir(dir) { + dir := name + for { + if idx := strings.LastIndex(dir, "/"); idx < 0 { + break + } else { + dir = dir[:idx] + } + if dirs[dir] { + break + } dirs[dir] = true } diff --git a/src/archive/zip/reader_test.go b/src/archive/zip/reader_test.go index cb8a0c2871..5ce994e4dd 100644 --- a/src/archive/zip/reader_test.go +++ b/src/archive/zip/reader_test.go @@ -9,6 +9,7 @@ import ( "encoding/binary" "encoding/hex" "errors" + "fmt" "internal/obscuretestdata" "io" "io/fs" @@ -1874,3 +1875,83 @@ func TestBaseOffsetPlusOverflow(t *testing.T) { // as the section reader offset & size were < 0. NewReader(bytes.NewReader(data), int64(len(data))+1875) } + +func BenchmarkReaderOneDeepDir(b *testing.B) { + var buf bytes.Buffer + zw := NewWriter(&buf) + + for i := range 4000 { + name := strings.Repeat("a/", i) + "data" + zw.CreateHeader(&FileHeader{ + Name: name, + Method: Store, + }) + } + + if err := zw.Close(); err != nil { + b.Fatal(err) + } + data := buf.Bytes() + + for b.Loop() { + zr, err := NewReader(bytes.NewReader(data), int64(len(data))) + if err != nil { + b.Fatal(err) + } + zr.Open("does-not-exist") + } +} + +func BenchmarkReaderManyDeepDirs(b *testing.B) { + var buf bytes.Buffer + zw := NewWriter(&buf) + + for i := range 2850 { + name := fmt.Sprintf("%x", i) + name = strings.Repeat("/"+name, i+1)[1:] + + zw.CreateHeader(&FileHeader{ + Name: name, + Method: Store, + }) + } + + if err := zw.Close(); err != nil { + b.Fatal(err) + } + data := buf.Bytes() + + for b.Loop() { + zr, err := NewReader(bytes.NewReader(data), int64(len(data))) + if err != nil { + b.Fatal(err) + } + zr.Open("does-not-exist") + } +} + +func BenchmarkReaderManyShallowFiles(b *testing.B) { + var buf bytes.Buffer + zw := NewWriter(&buf) + + for i := range 310000 { + name := fmt.Sprintf("%v", i) + zw.CreateHeader(&FileHeader{ + Name: name, + Method: Store, + }) + } + + if err := zw.Close(); err != nil { + b.Fatal(err) + } + data := buf.Bytes() + + for b.Loop() { + zr, err := NewReader(bytes.NewReader(data), int64(len(data))) + if err != nil { + b.Fatal(err) + } + zr.Open("does-not-exist") + } +} -- cgit v1.3 From 532e3203492ebcac67b2f3aa2a52115f49d51997 Mon Sep 17 00:00:00 2001 From: Alan Donovan Date: Thu, 18 Dec 2025 12:27:11 -0500 Subject: go/types,cmd/compile/internal/types2: better diagnostic for type shadowing This change causes the "x is not a type" diagnostic to describe x's actual kind, helping to reveal when shadowing is at work. (The kind description could improve other errors too.) Fixes #76877 Change-Id: Ia3484998bb384ff570c20b6792cf8461c60aa38c Reviewed-on: https://go-review.googlesource.com/c/go/+/731180 Reviewed-by: Robert Griesemer Auto-Submit: Alan Donovan LUCI-TryBot-Result: Go LUCI Auto-Submit: Robert Griesemer --- src/cmd/compile/internal/types2/object.go | 49 ++++++++++++++++++++++ src/cmd/compile/internal/types2/typexpr.go | 3 +- src/go/types/object.go | 49 ++++++++++++++++++++++ src/go/types/typexpr.go | 3 +- src/internal/types/testdata/check/cycles5.go | 2 +- src/internal/types/testdata/check/cycles5a.go | 2 +- src/internal/types/testdata/check/decls1.go | 9 +++- src/internal/types/testdata/check/issues0.go | 2 +- src/internal/types/testdata/check/issues1.go | 2 +- .../types/testdata/fixedbugs/issue39634.go | 2 +- .../types/testdata/fixedbugs/issue65344.go | 4 +- test/fixedbugs/issue4610.go | 1 - 12 files changed, 117 insertions(+), 11 deletions(-) diff --git a/src/cmd/compile/internal/types2/object.go b/src/cmd/compile/internal/types2/object.go index dd2d415790..5d284ee61b 100644 --- a/src/cmd/compile/internal/types2/object.go +++ b/src/cmd/compile/internal/types2/object.go @@ -671,3 +671,52 @@ func writeFuncName(buf *bytes.Buffer, f *Func, qf Qualifier) { } buf.WriteString(f.name) } + +// objectKind returns a description of the object's kind. +func objectKind(obj Object) string { + switch obj := obj.(type) { + case *PkgName: + return "package name" + case *Const: + return "constant" + case *TypeName: + if obj.IsAlias() { + return "type alias" + } else if _, ok := obj.Type().(*TypeParam); ok { + return "type parameter" + } else { + return "defined type" + } + case *Var: + switch obj.Kind() { + case PackageVar: + return "package-level variable" + case LocalVar: + return "local variable" + case RecvVar: + return "receiver" + case ParamVar: + return "parameter" + case ResultVar: + return "result variable" + case FieldVar: + return "struct field" + } + case *Func: + if obj.Signature().Recv() != nil { + return "method" + } else { + return "function" + } + case *Label: + return "label" + case *Builtin: + return "built-in function" + case *Nil: + return "untyped nil" + } + if debug { + panic(fmt.Sprintf("unknown symbol (%T)", obj)) + } + return "unknown symbol" +} diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index a79b54eacc..7d5932eec1 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -50,7 +50,8 @@ func (check *Checker) ident(x *operand, e *syntax.Name, wantType bool) { // (see go.dev/issue/65344). _, gotType := obj.(*TypeName) if !gotType && wantType { - check.errorf(e, NotAType, "%s is not a type", obj.Name()) + check.errorf(e, NotAType, "%s (%s) is not a type", obj.Name(), objectKind(obj)) + // avoid "declared but not used" errors // (don't use Checker.use - we don't want to evaluate too much) if v, _ := obj.(*Var); v != nil && v.pkg == check.pkg /* see Checker.use1 */ { diff --git a/src/go/types/object.go b/src/go/types/object.go index 57158c1595..e12bf7285a 100644 --- a/src/go/types/object.go +++ b/src/go/types/object.go @@ -674,3 +674,52 @@ func writeFuncName(buf *bytes.Buffer, f *Func, qf Qualifier) { } buf.WriteString(f.name) } + +// objectKind returns a description of the object's kind. +func objectKind(obj Object) string { + switch obj := obj.(type) { + case *PkgName: + return "package name" + case *Const: + return "constant" + case *TypeName: + if obj.IsAlias() { + return "type alias" + } else if _, ok := obj.Type().(*TypeParam); ok { + return "type parameter" + } else { + return "defined type" + } + case *Var: + switch obj.Kind() { + case PackageVar: + return "package-level variable" + case LocalVar: + return "local variable" + case RecvVar: + return "receiver" + case ParamVar: + return "parameter" + case ResultVar: + return "result variable" + case FieldVar: + return "struct field" + } + case *Func: + if obj.Signature().Recv() != nil { + return "method" + } else { + return "function" + } + case *Label: + return "label" + case *Builtin: + return "built-in function" + case *Nil: + return "untyped nil" + } + if debug { + panic(fmt.Sprintf("unknown symbol (%T)", obj)) + } + return "unknown symbol" +} diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index 346ff18e9a..549c307487 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -49,7 +49,8 @@ func (check *Checker) ident(x *operand, e *ast.Ident, wantType bool) { // (see go.dev/issue/65344). _, gotType := obj.(*TypeName) if !gotType && wantType { - check.errorf(e, NotAType, "%s is not a type", obj.Name()) + check.errorf(e, NotAType, "%s (%s) is not a type", obj.Name(), objectKind(obj)) + // avoid "declared but not used" errors // (don't use Checker.use - we don't want to evaluate too much) if v, _ := obj.(*Var); v != nil && v.pkg == check.pkg /* see Checker.use1 */ { diff --git a/src/internal/types/testdata/check/cycles5.go b/src/internal/types/testdata/check/cycles5.go index de85c03d8a..9605f8ded4 100644 --- a/src/internal/types/testdata/check/cycles5.go +++ b/src/internal/types/testdata/check/cycles5.go @@ -162,7 +162,7 @@ func makeArray() (res T12) { return } // issue #20770 var r = newReader() -func newReader() r // ERROR "r is not a type" +func newReader() r // ERROR "r (package-level variable) is not a type" // variations of the theme of #8699 and #20770 var arr /* ERROR "cycle" */ = f() diff --git a/src/internal/types/testdata/check/cycles5a.go b/src/internal/types/testdata/check/cycles5a.go index e10f554e5c..a8cad50243 100644 --- a/src/internal/types/testdata/check/cycles5a.go +++ b/src/internal/types/testdata/check/cycles5a.go @@ -162,7 +162,7 @@ func makeArray() (res T12) { return } // issue #20770 var r = newReader() -func newReader() r // ERROR "r is not a type" +func newReader() r // ERROR "r (package-level variable) is not a type" // variations of the theme of #8699 and #20770 var arr /* ERROR "cycle" */ = f() diff --git a/src/internal/types/testdata/check/decls1.go b/src/internal/types/testdata/check/decls1.go index 6cdbf27f4c..5e4ba86cb0 100644 --- a/src/internal/types/testdata/check/decls1.go +++ b/src/internal/types/testdata/check/decls1.go @@ -63,7 +63,7 @@ var ( t12 complex64 = -(u + *t11) / *&v t13 int = a /* ERROR "shifted operand" */ << d t14 int = i << j - t15 math /* ERROR "math is not a type" */ + t15 math /* ERROR "math (package name) is not a type" */ t16 math.xxx /* ERROR "undefined" */ t17 math /* ERROR "not a type" */ .Pi t18 float64 = math.Pi * 10.0 @@ -144,3 +144,10 @@ func init /* ERROR "no arguments and no return values" */ (int) {} func init /* ERROR "no arguments and no return values" */ () int { return 0 } func init /* ERROR "no arguments and no return values" */ (int) int { return 0 } func (T) init(int) int { return 0 } + +func _() { + var error error + var _ error /* ERROR "error (local variable) is not a type" */ + _ = error +} + diff --git a/src/internal/types/testdata/check/issues0.go b/src/internal/types/testdata/check/issues0.go index 6117f7a8b9..fb4e1282f9 100644 --- a/src/internal/types/testdata/check/issues0.go +++ b/src/internal/types/testdata/check/issues0.go @@ -104,7 +104,7 @@ func issue10979() { // issue11347 // These should not crash. -var a1, b1, c1 /* ERROR "cycle" */ b1 /* ERROR "b1 is not a type" */ = 0 > 0<<""[""[c1]]>c1 +var a1, b1, c1 /* ERROR "cycle" */ b1 /* ERROR "b1 (package-level variable) is not a type" */ = 0 > 0<<""[""[c1]]>c1 var a2, b2 /* ERROR "cycle" */ = 0 /* ERROR "assignment mismatch" */ /* ERROR "assignment mismatch" */ > 0<<""[b2] var a3, b3 /* ERROR "cycle" */ = int /* ERROR "assignment mismatch" */ /* ERROR "assignment mismatch" */ (1<<""[b3]) diff --git a/src/internal/types/testdata/check/issues1.go b/src/internal/types/testdata/check/issues1.go index 72c6cf7757..482bdb08e1 100644 --- a/src/internal/types/testdata/check/issues1.go +++ b/src/internal/types/testdata/check/issues1.go @@ -246,5 +246,5 @@ var _ = append[context.CancelFunc, []context.CancelFunc, context.CancelFunc](can func g[T any](T) T { panic(0) } var _ = g[int] -var _ = g[nil /* ERROR "is not a type" */ ] +var _ = g[nil /* ERROR "nil (untyped nil) is not a type" */ ] var _ = g(0) diff --git a/src/internal/types/testdata/fixedbugs/issue39634.go b/src/internal/types/testdata/fixedbugs/issue39634.go index 58fc43eea6..5392f903c2 100644 --- a/src/internal/types/testdata/fixedbugs/issue39634.go +++ b/src/internal/types/testdata/fixedbugs/issue39634.go @@ -43,7 +43,7 @@ type foo9[A any] interface { foo9 /* ERROR "invalid recursive type" */ [A] } func _() { var _ = new(foo9[int]) } // crash 12 -var u, i [func /* ERROR "used as value" */ /* ERROR "used as value" */ (u /* ERROR "u is not a type" */ /* ERROR "u is not a type" */ , c /* ERROR "undefined" */ /* ERROR "undefined" */ ) {}(0, len /* ERROR "must be called" */ /* ERROR "must be called" */ )]c /* ERROR "undefined" */ /* ERROR "undefined" */ +var u, i [func /* ERROR "used as value" */ /* ERROR "used as value" */ (u /* ERROR "u (package-level variable) is not a type" */ /* ERROR "u (package-level variable) is not a type" */ , c /* ERROR "undefined" */ /* ERROR "undefined" */ ) {}(0, len /* ERROR "must be called" */ /* ERROR "must be called" */ )]c /* ERROR "undefined" */ /* ERROR "undefined" */ // crash 15 func y15() { var a /* ERROR "declared and not used" */ interface{ p() } = G15[string]{} } diff --git a/src/internal/types/testdata/fixedbugs/issue65344.go b/src/internal/types/testdata/fixedbugs/issue65344.go index 9f8337cf2b..4db97c04ff 100644 --- a/src/internal/types/testdata/fixedbugs/issue65344.go +++ b/src/internal/types/testdata/fixedbugs/issue65344.go @@ -4,12 +4,12 @@ package p -type T1 C /* ERROR "C is not a type" */ +type T1 C /* ERROR "C (constant) is not a type" */ // TODO(gri) try to avoid this follow-on error const C = T1(0 /* ERROR "cannot convert 0 (untyped int constant) to type T1" */) -type T2 V /* ERROR "V is not a type" */ +type T2 V /* ERROR "V (package-level variable) is not a type" */ var V T2 diff --git a/test/fixedbugs/issue4610.go b/test/fixedbugs/issue4610.go index d56c6d3e8c..8993f9882b 100644 --- a/test/fixedbugs/issue4610.go +++ b/test/fixedbugs/issue4610.go @@ -14,4 +14,3 @@ func main() { var foo bar _ = &foo{} // ERROR "is not a type|expected .;." } // GCCGO_ERROR "expected declaration" - -- cgit v1.3 From 7251c9e0f00a6d7d37bb441f3e823c160131e9b5 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Fri, 16 Jan 2026 12:20:39 -0500 Subject: doc: fix urlmaxqueryparams typos Updates #77101. Change-Id: I6a6a636cd58e1bd01943066368cb1424db6c6a92 Reviewed-on: https://go-review.googlesource.com/c/go/+/737040 Reviewed-by: Damien Neil Auto-Submit: Michael Pratt LUCI-TryBot-Result: Go LUCI --- doc/godebug.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/godebug.md b/doc/godebug.md index 184e161c40..90ed63a01a 100644 --- a/doc/godebug.md +++ b/doc/godebug.md @@ -167,8 +167,8 @@ Go 1.26 added a new `urlmaxqueryparams` setting that controls the maximum number of query parameters that net/url will accept when parsing a URL-encoded query string. If the number of parameters exceeds the number set in `urlmaxqueryparams`, parsing will fail early. The default value is `urlmaxqueryparams=10000`. -Setting `urlmaxqueryparams=0`bles the limit. To avoid denial of service attacks, -this setting and default was backported to Go 1.25.4 and Go 1.24.10. +Setting `urlmaxqueryparams=0` disables the limit. To avoid denial of service +attacks, this setting and default was backported to Go 1.25.6 and Go 1.24.12. Go 1.26 added a new `urlstrictcolons` setting that controls whether `net/url.Parse` allows malformed hostnames containing colons outside of a bracketed IPv6 address. -- cgit v1.3 From 4edaaf2b529219ff219798914f730ca5a0ab018b Mon Sep 17 00:00:00 2001 From: Daniel Müllner Date: Mon, 19 Jan 2026 09:18:05 +0100 Subject: strconv: don't call internal Atoi twice in Atoi Change-Id: I89a41bbc83fdf473399527a933d57794ce83f68a Reviewed-on: https://go-review.googlesource.com/c/go/+/737261 Reviewed-by: Russ Cox LUCI-TryBot-Result: Go LUCI Reviewed-by: Ian Lance Taylor Reviewed-by: Florian Lehner --- src/strconv/number.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/strconv/number.go b/src/strconv/number.go index 3fa625c35f..acaed1c96e 100644 --- a/src/strconv/number.go +++ b/src/strconv/number.go @@ -148,7 +148,7 @@ func Atoi(s string) (int, error) { if err != nil { return x, toError("Atoi", s, 0, 0, err) } - return strconv.Atoi(s) + return x, nil } // FormatComplex converts the complex number c to a string of the -- cgit v1.3 From a8291eb61402d4549b69803fc8f834ded45b1f6c Mon Sep 17 00:00:00 2001 From: Alan Donovan Date: Tue, 20 Jan 2026 16:18:59 -0500 Subject: cmd/compile/internal/staticinit: fix bug in global new(expr) The StaticInit pass asserts that the operand of &v is a global, but this is not so for the &autotemp desugaring of new(expr). (The variable has by that point escaped to the heap, so the object code calls runtime.newobject. A future optimization would be to statically allocate the variable when it is safe and advantageous to do so.) Thanks to khr for suggesting the fix. + static test Fixes #77237 Change-Id: I71b34a1353fe0f3e297beab9851f8f87d765d8f1 Reviewed-on: https://go-review.googlesource.com/c/go/+/737680 Reviewed-by: Keith Randall Reviewed-by: Keith Randall LUCI-TryBot-Result: Go LUCI --- src/cmd/compile/internal/staticinit/sched.go | 3 +++ test/newexpr.go | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/src/cmd/compile/internal/staticinit/sched.go b/src/cmd/compile/internal/staticinit/sched.go index 5e39bb512f..c79715be46 100644 --- a/src/cmd/compile/internal/staticinit/sched.go +++ b/src/cmd/compile/internal/staticinit/sched.go @@ -228,6 +228,9 @@ func (s *Schedule) staticcopy(l *ir.Name, loff int64, rn *ir.Name, typ *types.Ty case ir.OADDR: r := r.(*ir.AddrExpr) if a, ok := r.X.(*ir.Name); ok && a.Op() == ir.ONAME { + if a.Class != ir.PEXTERN { + return false // e.g. local from new(expr) + } staticdata.InitAddr(l, loff, staticdata.GlobalLinksym(a)) return true } diff --git a/test/newexpr.go b/test/newexpr.go index c9a8804d4e..00d753c572 100644 --- a/test/newexpr.go +++ b/test/newexpr.go @@ -37,3 +37,10 @@ func main() { } } } + +// Regression test for ICE in staticdata.GlobalLinksym from +// use of autotemp outside a function (go.dev/issue/77237). +var ( + x = new(0) + y = x +) -- cgit v1.3 From 2baa1d17628bb2f09757617382b1e61f1f9f0ddd Mon Sep 17 00:00:00 2001 From: Youlin Feng Date: Sat, 17 Jan 2026 14:20:22 +0800 Subject: runtime: remove the unused scanIdx from mspan After CL 700496, mspan.scanIdx is never used, this CL just remove it. Change-Id: I41ce9902957c0cfa6fbf26b66a2a7787b179376a Reviewed-on: https://go-review.googlesource.com/c/go/+/737220 LUCI-TryBot-Result: Go LUCI Reviewed-by: Carlos Amedee Auto-Submit: Carlos Amedee Reviewed-by: Michael Knyszek --- src/runtime/mheap.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/runtime/mheap.go b/src/runtime/mheap.go index 68dfca4668..9b62ee4273 100644 --- a/src/runtime/mheap.go +++ b/src/runtime/mheap.go @@ -457,12 +457,6 @@ type mspan struct { // mallocgc, and issue 54596). freeIndexForScan uint16 - // Temporary storage for the object index that caused this span to - // be queued for scanning. - // - // Used only with goexperiment.GreenTeaGC. - scanIdx uint16 - // Cache of the allocBits at freeindex. allocCache is shifted // such that the lowest bit corresponds to the bit freeindex. // allocCache holds the complement of allocBits, thus allowing -- cgit v1.3