Compare commits

..

99 Commits

Author SHA1 Message Date
Gopher Robot
d375ae5063 [release-branch.go1.23] go1.23.10
Change-Id: Id4ed8879352dfe662a0ab96981a8d59e2fd80767
Reviewed-on: https://go-review.googlesource.com/c/go/+/679219
Reviewed-by: Carlos Amedee <carlos@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
TryBot-Bypass: Carlos Amedee <carlos@golang.org>
2025-06-05 11:34:47 -07:00
Neal Patel
b897e97c36 [release-branch.go1.23] net/http: strip sensitive proxy headers from redirect requests
Similarly to Authentication entries, Proxy-Authentication entries should be stripped to ensure sensitive information is not leaked on redirects outside of the original domain.

https://fetch.spec.whatwg.org/#authentication-entries

Thanks to Takeshi Kaneko (GMO Cybersecurity by Ierae, Inc.) for reporting this issue.

Updates golang/go#73816
Fixes golang/go#73905
Fixes CVE-2025-4673

Change-Id: I1615f31977a2fd014fbc12aae43f82692315a6d0
Reviewed-on: https://go-review.googlesource.com/c/go/+/679255
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
2025-06-05 11:10:16 -07:00
Damien Neil
c2c89d9551 [release-branch.go1.23] os: don't follow symlinks on Windows when O_CREATE|O_EXCL
(This cherry-pick includes both CL 672396 and CL 676655.)

Match standard Unix behavior: Symlinks are not followed when
O_CREATE|O_EXCL is passed to open.

Thanks to Junyoung Park and Dong-uk Kim of KAIST Hacking Lab
for discovering this issue.

For #73702
Fixes #73719
Fixes CVE-2025-0913

Change-Id: Ieb46a6780c5e9a6090b09cd34290f04a8e3b0ca5
Reviewed-on: https://go-review.googlesource.com/c/go/+/672396
Auto-Submit: Damien Neil <dneil@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Alan Donovan <adonovan@google.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/677195
TryBot-Bypass: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
2025-05-29 10:56:13 -07:00
Cherry Mui
8eeb1340b2 [release-branch.go1.23] cmd/link: allow linkname reference to a TEXT symbol regardless of size
In CL 660696, we made the linker to choose the symbol of the
larger size in case there are multiple contentless declarations of
the same symbol. We also made it emit an error in the case that
there are a contentless declaration of a larger size and a
definition with content of a smaller size. In this case, we should
choose the definition with content, but the code accesses it
through the declaration of the larger size could fall into the
next symbol, potentially causing data corruption. So we disallowed
it.

There is one spcial case, though, that some code uses a linknamed
variable declaration to reference a function in assembly, in order
to take its address. The variable is often declared as uintptr.
The function symbol is the definition, which could sometimes be
shorter. This would trigger the error case above, causing existing
code failing to build.

This CL allows it as a special case. It is still not safe to
access the variable's content. But it is actually okay to just
take its address, which the existing code often do.

Updates #73617.
Fixes #73831.

Change-Id: I467381bc5f6baa16caee6752a0a824c7185422f6
Reviewed-on: https://go-review.googlesource.com/c/go/+/676636
Reviewed-by: David Chase <drchase@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
(cherry picked from commit 70109eb326)
Reviewed-on: https://go-review.googlesource.com/c/go/+/676958
TryBot-Bypass: Cherry Mui <cherryyz@google.com>
2025-05-29 08:12:27 -07:00
Sean Liao
4ca7c01706 [release-branch.go1.23] runtime/debug: document DefaultGODEBUG as a BuildSetting
For #66465
Fixes #73677

Change-Id: I60c017ddba29fa5b452b665d8521cd6c8e20438c
Reviewed-on: https://go-review.googlesource.com/c/go/+/597979
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Jorropo <jorropo.pgm@gmail.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>
Reviewed-by: qiu laidongfeng2 <2645477756@qq.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
(cherry picked from commit c4136a433c)
Reviewed-on: https://go-review.googlesource.com/c/go/+/671936
Reviewed-by: Sean Liao <sean@liao.dev>
TryBot-Bypass: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
TryBot-Bypass: Michael Knyszek <mknyszek@google.com>
2025-05-28 09:32:46 -07:00
Gopher Robot
f77084d15d [release-branch.go1.23] go1.23.9
Change-Id: I5ffeb84b19112888aee4ebffd88c0753b41ac833
Reviewed-on: https://go-review.googlesource.com/c/go/+/670457
Auto-Submit: Gopher Robot <gobot@golang.org>
Reviewed-by: Carlos Amedee <carlos@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
2025-05-06 11:34:22 -07:00
Keith Randall
8ff45d1aa0 [release-branch.go1.23] runtime: fix 9-arg syscall on darwin/amd64
The last 3 arguments need to be passed on the stack, not registers.

Fixes #73380

Change-Id: Ib1155ad1a805957fad3d9594c93981a558755591
Reviewed-on: https://go-review.googlesource.com/c/go/+/665435
Reviewed-by: Michael Pratt <mpratt@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Keith Randall <khr@google.com>
(cherry picked from commit 9d7de04838)
Reviewed-on: https://go-review.googlesource.com/c/go/+/666015
2025-04-28 10:29:49 -07:00
Cherry Mui
96537d5044 [release-branch.go1.23] cmd/link: choose one with larger size for duplicated BSS symbols
When two packages declare a variable with the same name (with
linkname at least on one side), the linker will choose one as the
actual definition of the symbol if one has content (i.e. a DATA
symbol) and the other does not (i.e. a BSS symbol). When both have
content, it is redefinition error. When neither has content,
currently the choice is sort of arbitrary (depending on symbol
loading order, etc. which are subject to change).

One use case for that is that one wants to reference a symbol
defined in another package, and the reference side just wants to
see some of the fields, so it may be declared with a smaller type.
In this case, we want to choose the one with the larger size as
the true definition. Otherwise the code accessing the larger
sized one may read/write out of bounds, corrupting the next
variable. This CL makes the linker do so.

Also include followup fix CL 661915.

Fixes #73091.
Updates #72032.

Change-Id: I160aa9e0234702066cb8f141c186eaa89d0fcfed
Reviewed-on: https://go-review.googlesource.com/c/go/+/660696
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Than McIntosh <thanm@golang.org>
(cherry picked from commit 8f6c083d7b)
Reviewed-on: https://go-review.googlesource.com/c/go/+/662355
Auto-Submit: Dmitri Shuralyov <dmitshur@google.com>
2025-04-10 08:35:38 -07:00
Gopher Robot
7a2cfb70b0 [release-branch.go1.23] go1.23.8
Change-Id: Ied6ade315672e373b9b861f09ee0feba4fb8030b
Reviewed-on: https://go-review.googlesource.com/c/go/+/662057
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Gopher Robot <gobot@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Carlos Amedee <carlos@golang.org>
2025-04-01 09:11:48 -07:00
Andy Pan
c72a2bad68 [release-branch.go1.23] runtime: explicitly disable async preempt for internal/runtime
Fixes #72114
For #71591
Relevant CL 560155

Change-Id: Iebc497d56b36d50c13a6dd88e7bca4578a03cf63
Reviewed-on: https://go-review.googlesource.com/c/go/+/654916
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Auto-Submit: Michael Pratt <mpratt@google.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
(cherry picked from commit 92a63bdfee)
Reviewed-on: https://go-review.googlesource.com/c/go/+/660935
Auto-Submit: Dmitri Shuralyov <dmitshur@google.com>
2025-03-26 09:35:14 -07:00
Michael Pratt
2c0a0fc6b9 [release-branch.go1.23] runtime: skip TestCgoCallbackPprof on platforms with broken profiling
CL 658035 added TestCgoCallbackPprof, which is consistently failing on
solaris. runtime/pprof maintains a list of platforms where CPU profiling
does not work properly. Since this test requires CPU profiling, skip the
this test on those platforms.

For #72870.
For #72876.
For #72871.

Change-Id: I6a6a636cbf6b16abcbba8771178fe1d001be9d9b
Reviewed-on: https://go-review.googlesource.com/c/go/+/658415
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Michael Pratt <mpratt@google.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/658435
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Auto-Submit: Dmitri Shuralyov <dmitshur@google.com>
TryBot-Bypass: Dmitri Shuralyov <dmitshur@google.com>
2025-03-25 11:51:29 -07:00
Michael Pratt
c855149768 [release-branch.go1.23] runtime: only set isExtraInC if there are no Go frames left
mp.isExtraInC is intended to indicate that this M has no Go frames at
all; it is entirely executing in C.

If there was a cgocallback to Go and then a cgocall to C, such that the
leaf frames are C, that is fine. e.g., traceback can handle this fine
with SetCgoTraceback (or by simply skipping the C frames).

However, we currently mismanage isExtraInC, unconditionally setting it
on return from cgocallback. This means that if there are two levels of
cgocallback, we end up running Go code with isExtraInC set.

1. C-created thread calls into Go function 1 (via cgocallback).
2. Go function 1 calls into C function 1 (via cgocall).
3. C function 1 calls into Go function 2 (via cgocallback).
4. Go function 2 returns back to C function 1 (returning via the remainder of cgocallback).
5. C function 1 returns back to Go function 1 (returning via the remainder of cgocall).
6. Go function 1 is now running with mp.isExtraInC == true.

The fix is simple; only set isExtraInC on return from cgocallback if
there are no more Go frames. There can't be more Go frames unless there
is an active cgocall out of the Go frames.

For #72870.
Fixes #72871.

Cq-Include-Trybots: luci.golang.try:go1.23-linux-amd64-longtest
Change-Id: I6a6a636c4e7ba75a29639d7036c5af3738033467
Reviewed-on: https://go-review.googlesource.com/c/go/+/658035
Reviewed-by: Cherry Mui <cherryyz@google.com>
Commit-Queue: Michael Pratt <mpratt@google.com>
Auto-Submit: Michael Pratt <mpratt@google.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
(cherry picked from commit 577bb3d0ce)
Reviewed-on: https://go-review.googlesource.com/c/go/+/658055
Auto-Submit: Dmitri Shuralyov <dmitshur@google.com>
2025-03-25 11:51:22 -07:00
Jordan Liggitt
ec6e84df74 [release-branch.go1.23] internal/godebugs: fix changed version for winsymlink and winreadlinkvolume to 1.23
https://go.dev/doc/godebug#go-123 documents changes to winsymlink and
winreadlinkvolume in Go 1.23.

This fixes the registered "changed" minor version to Go 1.23,
so that defaults when building a Go 1.22 module are correct.

Fixes #72937

Change-Id: I5d5bf31ca04f9e95208fb0fdaad2232f9db653ff
Reviewed-on: https://go-review.googlesource.com/c/go/+/659035
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>
(cherry picked from commit 2e749a645a)
Reviewed-on: https://go-review.googlesource.com/c/go/+/658976
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
Auto-Submit: Dmitri Shuralyov <dmitshur@google.com>
2025-03-24 15:35:29 -07:00
Damien Neil
15e01a2e43 [release-branch.go1.23] net/http: reject newlines in chunk-size lines
Unlike request headers, where we are allowed to leniently accept
a bare LF in place of a CRLF, chunked bodies must always use CRLF
line terminators. We were already enforcing this for chunk-data lines;
do so for chunk-size lines as well. Also reject bare CRs anywhere
other than as part of the CRLF terminator.

Fixes CVE-2025-22871
Fixes #72010
For #71988

Change-Id: Ib0e21af5a8ba28c2a1ca52b72af8e2265ec79e4a
Reviewed-on: https://go-review.googlesource.com/c/go/+/652998
Reviewed-by: Jonathan Amsterdam <jba@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
(cherry picked from commit d31c805535)
Reviewed-on: https://go-review.googlesource.com/c/go/+/657216
2025-03-17 14:51:53 -07:00
Junyang Shao
45aade7f1e [release-branch.go1.23] all: updates vendored x/net
This is to update module version to the fixed x/net.

For #71984

Change-Id: I8f4357f14a7d44a782c131eb856b50a103be2f2d
Reviewed-on: https://go-review.googlesource.com/c/go/+/654796
Reviewed-by: Junyang Shao <shaojunyang@google.com>
Auto-Submit: Junyang Shao <shaojunyang@google.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2025-03-04 12:31:19 -08:00
Gopher Robot
c01c4d41d6 [release-branch.go1.23] go1.23.7
Change-Id: I547945f1cb8275a000ab5d1be2608a342f57d77e
Reviewed-on: https://go-review.googlesource.com/c/go/+/654418
Reviewed-by: Michael Pratt <mpratt@google.com>
Reviewed-by: Junyang Shao <shaojunyang@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Gopher Robot <gobot@golang.org>
Auto-Submit: Junyang Shao <shaojunyang@google.com>
2025-03-04 11:14:49 -08:00
Damien Neil
25177ecde0 [release-branch.go1.23] all: updated vendored x/net with security fix
0b6d719 [internal-branch.go1.23-vendor] proxy, http/httpproxy: do not mismatch IPv6 zone ids against hosts

Fixes CVE-2025-22870
For #71985

Change-Id: Ib72c96bd0ab44d9ed2ac1428e0a9fc245464b3fc
Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/2141
Commit-Queue: Damien Neil <dneil@google.com>
Reviewed-by: Roland Shoemaker <bracewell@google.com>
Reviewed-by: Neal Patel <nealpatel@google.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/654695
Reviewed-by: Damien Neil <dneil@google.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Junyang Shao <shaojunyang@google.com>
2025-03-04 10:36:00 -08:00
Ian Lance Taylor
e4772831d3 [release-branch.go1.23] runtime/cgo: avoid errors from -Wdeclaration-after-statement
CL 652181 accidentally missed this iPhone only code.

For #71961
For #71962

Change-Id: I567f8bb38958907442e69494da330d5199d11f54
Reviewed-on: https://go-review.googlesource.com/c/go/+/653136
Reviewed-by: Michael Pratt <mpratt@google.com>
Commit-Queue: Ian Lance Taylor <iant@google.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
2025-02-26 14:41:31 -08:00
Ian Lance Taylor
9facf1f2c2 [release-branch.go1.23] runtime/cgo: avoid errors from -Wdeclaration-after-statement
It's used by the SWIG CI build, at least, and it's an easy fix.

[The change in x_cgo_sys_thread_create is gone, as that function was
already compliant in 1.23.]

Fixes #71962
For #71961

Change-Id: Id21071a5aef216b35ecf0e9cd3e05d08972d92fe
Reviewed-on: https://go-review.googlesource.com/c/go/+/652181
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Michael Pratt <mpratt@google.com>
(cherry picked from commit 76c7028253)
Reviewed-on: https://go-review.googlesource.com/c/go/+/652935
Reviewed-by: Michael Knyszek <mknyszek@google.com>
2025-02-26 11:44:28 -08:00
qiulaidongfeng
0fa31cb69f [release-branch.go1.23] reflect: let Value.Seq return the iteration value correct type
Fixes #71915
For #71905

Change-Id: I50a418f8552e071c6e5011af5b9accc7d41548d0
Reviewed-on: https://go-review.googlesource.com/c/go/+/651855
Reviewed-by: Ian Lance Taylor <iant@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
(cherry picked from commit 194696f1d1)
Reviewed-on: https://go-review.googlesource.com/c/go/+/652875
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Auto-Submit: Michael Pratt <mpratt@google.com>
2025-02-26 11:11:33 -08:00
Michael Anthony Knyszek
d89fda21d5 [release-branch.go1.23] reflect: correctly handle method values in Seq
Currently method values aren't correctly handled in Seq because we call
canRangeFunc on the reciever type, not the method value type, when we're
handling a method value. reflect.Value.Type has the logic to obtain the
method value type from the Value.

This change slightly refactors reflect.Value.Type into a separate
function so we can obtain the correct type as an abi.Type and pass it
off to canRangeFunc (and canRangeFunc2).

For #71874.
Fixes #71875.

Change-Id: Ie62dfca2a84b8f2f816bb87ff1ed1a58a7bb8122
Reviewed-on: https://go-review.googlesource.com/c/go/+/651416
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Auto-Submit: Michael Knyszek <mknyszek@google.com>
(cherry picked from commit d93f6df0cc)
Reviewed-on: https://go-review.googlesource.com/c/go/+/651498
Reviewed-by: Firuze Sayan <sayanfiruze@gmail.com>
2025-02-26 09:54:04 -08:00
Michael Pratt
acde84cf1b [release-branch.go1.23] runtime: use WCLONE when waiting on pidfd test child
As of CL 650835, the pidfd test child no longer sends SIGCHLD on exit.
Per clone(2), "If [the child termination] signal is specified as
anything other than SIGCHLD, then the parent process must specify the
__WALL or __WCLONE options when waiting for the child with wait(2)."

Align with this requirement.

For #71848.
For #71828.

Change-Id: I6a6a636c739e4a59abe1533fe429a433e8588939
Reviewed-on: https://go-review.googlesource.com/c/go/+/651415
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Auto-Submit: Michael Pratt <mpratt@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
(cherry picked from commit e1e65ae3ee)
Reviewed-on: https://go-review.googlesource.com/c/go/+/651495
2025-02-26 09:45:34 -08:00
Ian Lance Taylor
c57e2bd22c [release-branch.go1.23] syscall: don't send child signal when testing pidfd
Avoid a spurious SIGCHLD the first time we start a process.

For #71828
Fixes #71848

Change-Id: I744100d21bf6aaaaafc99bc5eec9f9f807a50682
Reviewed-on: https://go-review.googlesource.com/c/go/+/651055
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2025-02-26 09:45:28 -08:00
David Chase
2aaa388971 [release-branch.go1.23] cmd/compile, runtime: use deferreturn as target PC for recover from deferrangefunc
The existing code for recover from deferrangefunc was broken in
several ways.

1. the code following a deferrangefunc call did not check the return
value for an out-of-band value indicating "return now" (i.e., recover
was called)

2. the returned value was delivered using a bespoke ABI that happened
to match on register-ABI platforms, but not on older stack-based
ABI.

3. the returned value was the wrong width (1 word versus 2) and
type/value(integer 1, not a pointer to anything) for deferrangefunc's
any-typed return value (in practice, the OOB value check could catch
this, but still, it's sketchy).

This -- using the deferreturn lookup method already in place for
open-coded defers -- turned out to be a much-less-ugly way of
obtaining the desired transfer of control for recover().

TODO: we also could do this for regular defer, and delete some code.

Fixes #71839

Change-Id: If7d7ea789ad4320821aab3b443759a7d71647ff0
Reviewed-on: https://go-review.googlesource.com/c/go/+/650476
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/651496
2025-02-21 18:58:07 -08:00
Paul Murphy
22fdd35c24 [release-branch.go1.23] runtime: fix usleep on s390x/linux
The timespec argument takes the remainder in nanoseconds, not
microseconds. Convert the remaining time to nsec.

Fixes #71727

Change-Id: I36cbbe3a088830c5e3afcc9516ef42e96ee21268
Reviewed-on: https://go-review.googlesource.com/c/go/+/648915
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Mauri de Souza Meneguzzo <mauri870@gmail.com>
Reviewed-by: Axel Busch <axel.busch@ibm.com>
Run-TryBot: Paul Murphy <murp@ibm.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Vishwanatha HD <vishwanatha.hd@ibm.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/649395
Auto-Submit: Ian Lance Taylor <iant@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
2025-02-19 09:14:50 -08:00
Gopher Robot
a991f9c34d [release-branch.go1.23] go1.23.6
Change-Id: Iec54508cfd791299630ae4b784667cd2643c4c15
Reviewed-on: https://go-review.googlesource.com/c/go/+/646221
Reviewed-by: Carlos Amedee <carlos@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Auto-Submit: Gopher Robot <gobot@golang.org>
TryBot-Bypass: Cherry Mui <cherryyz@google.com>
2025-02-04 08:39:47 -08:00
Roland Shoemaker
6644ed63b1 [release-branch.go1.23] crypto/internal/fips140/nistec: make p256NegCond constant time on ppc64le
Remove the branching instruction from p256NegCond which made it variable
time. The technique used matches that used in p256MovCond.

Fixes #71383
Fixes #71423
Fixes CVE-2025-22866

Change-Id: Ibc2a46814d856cbbdaf6cc0c5a415ed5d42ca793
Reviewed-on: https://go-review.googlesource.com/c/go/+/643735
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
Reviewed-by: Paul Murphy <murp@ibm.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
(cherry picked from commit 6fc23a3cff)
Reviewed-on: https://go-review.googlesource.com/c/go/+/645515
Reviewed-by: Carlos Amedee <carlos@golang.org>
2025-01-31 09:38:23 -08:00
Russ Cox
ab44565bcd [release-branch.go1.23] cmd/go/internal/modfetch: do not trust server to send all tags in shallow fetch
Newer git versions (at least git 2.47.1) do not send all the matching tags
for a shallow fetch of a specific hash anymore. The go command assumes
that git servers do this. Since that assumption is broken, use the local
copy of the remote refs list to augment the tags sent by the server.
This makes the cmd/go/internal/modfetch tests pass again with newer git.

For #71261
Fixes #71263

Change-Id: I9fd4f3fd7beeb68a522938599f8f3acd887d0b26
Reviewed-on: https://go-review.googlesource.com/c/go/+/642437
Reviewed-by: Michael Matloob <matloob@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Russ Cox <rsc@golang.org>
(cherry picked from commit bd80d8956f)
Reviewed-on: https://go-review.googlesource.com/c/go/+/642696
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Russ Cox <rsc@golang.org>
2025-01-17 08:30:53 -08:00
Keith Randall
9cbbf5e0f4 [release-branch.go1.23] cmd/compile: fix write barrier coalescing
We can't coalesce a non-WB store with a subsequent Move, as the
result of the store might be the source of the move.

There's a simple codegen test. Not sure how we might do a real test,
as all the repro's I've come up with are very expensive and unreliable.

Fixes #71230

Change-Id: If18bf181a266b9b90964e2591cd2e61a7168371c
Reviewed-on: https://go-review.googlesource.com/c/go/+/642197
Reviewed-by: Keith Randall <khr@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/642498
2025-01-17 07:41:09 -08:00
Gopher Robot
d04e3cbc92 [release-branch.go1.23] go1.23.5
Change-Id: I849328cf93adf24c223f103f5b834635970ea652
Reviewed-on: https://go-review.googlesource.com/c/go/+/643137
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
Auto-Submit: Gopher Robot <gobot@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2025-01-16 12:07:56 -08:00
Damien Neil
bb8230f805 [release-branch.go1.23] net/http: persist header stripping across repeated redirects
When an HTTP redirect changes the host of a request, we drop
sensitive headers such as Authorization from the redirected request.
Fix a bug where a chain of redirects could result in sensitive
headers being sent to the wrong host:

  1. request to a.tld with Authorization header
  2. a.tld redirects to b.tld
  3. request to b.tld with no Authorization header
  4. b.tld redirects to b.tld
  3. request to b.tld with Authorization header restored

Thanks to Kyle Seely for reporting this issue.

For #70530
Fixes ##71211
Fixes CVE-2024-45336

Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/1641
Reviewed-by: Roland Shoemaker <bracewell@google.com>
Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
Commit-Queue: Roland Shoemaker <bracewell@google.com>
Change-Id: I326544358de71ff892d9e9fe338252a5dd04001f
Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/1764
Reviewed-on: https://go-review.googlesource.com/c/go/+/643104
Auto-Submit: Michael Knyszek <mknyszek@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
2025-01-16 11:00:39 -08:00
Roland Shoemaker
fdb8413fe5 [release-branch.go1.23] crypto/x509: properly check for IPv6 hosts in URIs
When checking URI constraints, use netip.ParseAddr, which understands
zones, unlike net.ParseIP which chokes on them. This prevents zone IDs
from mistakenly satisfying URI constraints.

Thanks to Juho Forsén of Mattermost for reporting this issue.

For #71156
Fixes #71208
Fixes CVE-2024-45341

Change-Id: Iecac2529f3605382d257996e0fb6d6983547e400
Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/1700
Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
Reviewed-by: Damien Neil <dneil@google.com>
(cherry picked from commit 22ca55d396ba801e6ae9b2bd67a059fcb30562fd)
Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/1762
Reviewed-by: Roland Shoemaker <bracewell@google.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/643103
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
2025-01-16 11:00:37 -08:00
Michael Anthony Knyszek
1dde0b4844 [release-branch.go1.23] runtime: hold traceAcquire across casgstatus in injectglist
Currently injectglist emits all the trace events before actually calling
casgstatus on each goroutine. This is a problem, since tracing can
observe an inconsistent state (gstatus does not match tracer's 'emitted
an event' state).

This change fixes the problem by having injectglist do what every other
scheduler function does, and that's wrap each call to casgstatus in
traceAcquire/traceRelease.

For #70883.
Fixes #71147.

Change-Id: I857e96cec01688013597e8efc0c4c3d0b72d3a70
Reviewed-on: https://go-review.googlesource.com/c/go/+/638558
Reviewed-by: Michael Pratt <mpratt@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
(cherry picked from commit f025d19e7b)
Reviewed-on: https://go-review.googlesource.com/c/go/+/641378
Auto-Submit: Michael Pratt <mpratt@google.com>
2025-01-08 10:02:57 -08:00
Filippo Valsorda
3417000c69 [release-branch.go1.23] crypto/tls: fix Config.Time in tests using expired certificates
Updates #71077
Fixes #71104

Change-Id: I6a6a465685f3bd50a5bb35a160f87b59b74fa6af
Reviewed-on: https://go-review.googlesource.com/c/go/+/639655
Auto-Submit: Ian Lance Taylor <iant@google.com>
Reviewed-by: Damien Neil <dneil@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Filippo Valsorda <filippo@golang.org>
Auto-Submit: Damien Neil <dneil@google.com>
Reviewed-by: Joel Sing <joel@sing.id.au>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/640315
Reviewed-by: Filippo Valsorda <filippo@golang.org>
2025-01-08 09:33:16 -08:00
Ian Lance Taylor
1576793c51 [release-branch.go1.23] net: don't use sendfile for irregular files; handle EOPNOTSUPP/ENOTSUP
This is not a cherry pick, because the code has changed on tip.

For #70763
Fixes #70789

Change-Id: If9fcfee17e86a746cf8c72293dc34f80b430f6e6
Reviewed-on: https://go-review.googlesource.com/c/go/+/635397
Auto-Submit: Ian Lance Taylor <iant@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Damien Neil <dneil@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2024-12-18 09:42:15 -08:00
Cherry Mui
59b7d40774 [release-branch.go1.23] runtime: update and restore g0 stack bounds at cgocallback
Currently, at a cgo callback where there is already a Go frame on
the stack (i.e. C->Go->C->Go), we require that at the inner Go
callback the SP is within the g0's stack bounds set by a previous
callback. This is to prevent that the C code switches stack while
having a Go frame on the stack, which we don't really support. But
this could also happen when we cannot get accurate stack bounds,
e.g. when pthread_getattr_np is not available. Since the stack
bounds are just estimates based on the current SP, if there are
multiple C->Go callbacks with various stack depth, it is possible
that the SP of a later callback falls out of a previous call's
estimate. This leads to runtime throw in a seemingly reasonable
program.

This CL changes it to save the old g0 stack bounds at cgocallback,
update the bounds, and restore the old bounds at return. So each
callback will get its own stack bounds based on the current SP,
and when it returns, the outer callback has the its old stack
bounds restored.

Also, at a cgo callback when there is no Go frame on the stack,
we currently always get new stack bounds. We do this because if
we can only get estimated bounds based on the SP, and the stack
depth varies a lot between two C->Go calls, the previous
estimates may be off and we fall out or nearly fall out of the
previous bounds. But this causes a performance problem: the
pthread API to get accurate stack bounds (pthread_getattr_np) is
very slow when called on the main thread. Getting the stack bounds
every time significantly slows down repeated C->Go calls on the
main thread.

This CL fixes it by "caching" the stack bounds if they are
accurate. I.e. at the second time Go calls into C, if the previous
stack bounds are accurate, and the current SP is in bounds, we can
be sure it is the same stack and we don't need to update the bounds.
This avoids the repeated calls to pthread_getattr_np. If we cannot
get the accurate bounds, we continue to update the stack bounds
based on the SP, and that operation is very cheap.

On a Linux/AMD64 machine with glibc:

name                     old time/op  new time/op  delta
CgoCallbackMainThread-8  96.4µs ± 3%   0.1µs ± 2%  -99.92%  (p=0.000 n=10+9)

Updates #68285.
Updates #68587.
Fixes #69988.

Change-Id: I3422badd5ad8ff63e1a733152d05fb7a44d5d435
Reviewed-on: https://go-review.googlesource.com/c/go/+/600296
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
(cherry picked from commit 76a8409eb8)
Reviewed-on: https://go-review.googlesource.com/c/go/+/635775
2024-12-13 11:18:11 -08:00
Tim King
69c8cfe29b [release-branch.go1.23] cmd/compile/internal/importer: enable aliases
Flips the pkgReader.enableAlias flag to true when reading unified IR.
This was disabled while resolving #66873. This resolves the TODO to
flip it back to true.

Fixes #70394
Fixes #70517
Updates #66873

Change-Id: Ifd52b0f9510d6bcf151de1c9a18d71ab548c14e4
Reviewed-on: https://go-review.googlesource.com/c/go/+/604099
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: David Chase <drchase@google.com>
(cherry picked from commit 209ed1a9c7)
Reviewed-on: https://go-review.googlesource.com/c/go/+/631855
Commit-Queue: Tim King <taking@google.com>
Reviewed-by: Robert Griesemer <gri@google.com>
2024-12-11 11:17:27 -08:00
Gopher Robot
194de8fbfa [release-branch.go1.23] go1.23.4
Change-Id: I8d26e5231e868476949390ec900f0273c816d807
Reviewed-on: https://go-review.googlesource.com/c/go/+/633217
Reviewed-by: Veronica Silina <veronicasilina@google.com>
Auto-Submit: Gopher Robot <gobot@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
2024-12-03 18:27:46 +00:00
Felix Geisendörfer
5164a865e3 [release-branch.go1.23] cmd/trace: also show end stack traces
Fix a regression that appeared in 1.23 when it comes to the stack traces
shown in the trace viewer. In 1.22 and earlier, the viewer was always
showing end stack traces. In 1.23 and later the viewer started to
exclusively show start stack traces.

Showing only the start stack traces made it impossible to see the last
stack trace produced by a goroutine. It also made it hard to understand
why a goroutine went off-cpu, as one had to hunt down the next running
slice of the same goroutine.

Emit end stack traces in addition to start stack traces to fix the
issue.

Fixes #70592

Change-Id: Ib22ea61388c1d94cdbc99fae2d207c4dce011a59
Reviewed-on: https://go-review.googlesource.com/c/go/+/631895
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
Auto-Submit: Felix Geisendörfer <felix.geisendoerfer@datadoghq.com>
Reviewed-by: Nick Ripley <nick.ripley@datadoghq.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
(cherry picked from commit 6405e60ca6)
Reviewed-on: https://go-review.googlesource.com/c/go/+/632075
Reviewed-by: Veronica Silina <veronicasilina@google.com>
Auto-Submit: Veronica Silina <veronicasilina@google.com>
2024-11-27 20:24:20 +00:00
Russ Cox
25f042daec [release-branch.go1.23] runtime: reserve 4kB for system stack on windows-386
The failures in #70288 are consistent with and strongly imply
stack corruption during fault handling, and debug prints show
that the Go code run during fault handling is running about
300 bytes above the bottom of the goroutine stack.
That should be okay, but that implies the DLL code that called
Go's handler was running near the bottom of the stack too,
and maybe it called other deeper things before or after the
Go handler and smashed the stack that way.

stackSystem is already 4096 bytes on amd64;
making it match that on 386 makes the flaky failures go away.
It's a little unsatisfying not to be able to say exactly what is
overflowing the stack, but the circumstantial evidence is
very strong that it's Windows.

For #70288.
Fixes #70475.

Change-Id: Ife89385873d5e5062a71629dbfee40825edefa49
Reviewed-on: https://go-review.googlesource.com/c/go/+/627375
Reviewed-by: Ian Lance Taylor <iant@google.com>
Auto-Submit: Russ Cox <rsc@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
(cherry picked from commit 7eeb0a188e)
Reviewed-on: https://go-review.googlesource.com/c/go/+/632196
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Auto-Submit: Veronica Silina <veronicasilina@google.com>
2024-11-27 19:14:27 +00:00
Michael Anthony Knyszek
be062b7f61 [release-branch.go1.23] runtime: explicitly keep handle alive during getOrAddWeakHandle
getOrAddWeakHandle is very careful about keeping its input alive across
the operation, but not very careful about keeping the heap-allocated
handle it creates alive. In fact, there's a window in this function
where it is *only* visible via the special. Specifically, the window of
time between when the handle is stored in the special and when the
special actually becomes visible to the GC.

(If we fail to add the special because it already exists, that case is
fine. We don't even use the same handle value, but the one we obtain
from the attached GC-visible special, *and* we return that value, so it
remains live.)

For #70455.
Fixes #70469.

Change-Id: Iadaff0cfb93bcaf61ba2b05be7fa0519c481de82
Reviewed-on: https://go-review.googlesource.com/c/go/+/630316
Auto-Submit: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2024-11-20 19:59:34 +00:00
Michael Anthony Knyszek
d8adc6c4c7 [release-branch.go1.23] runtime: prevent weak->strong conversions during mark termination
Currently it's possible for weak->strong conversions to create more GC
work during mark termination. When a weak->strong conversion happens
during the mark phase, we need to mark the newly-strong pointer, since
it may now be the only pointer to that object. In other words, the
object could be white.

But queueing new white objects creates GC work, and if this happens
during mark termination, we could end up violating mark termination
invariants. In the parlance of the mark termination algorithm, the
weak->strong conversion is a non-monotonic source of GC work, unlike the
write barriers (which will eventually only see black objects).

This change fixes the problem by forcing weak->strong conversions to
block during mark termination. We can do this efficiently by setting a
global flag before the ragged barrier that is checked at each
weak->strong conversion. If the flag is set, then the conversions block.
The ragged barrier ensures that all Ps have observed the flag and that
any weak->strong conversions which completed before the ragged barrier
have their newly-minted strong pointers visible in GC work queues if
necessary. We later unset the flag and wake all the blocked goroutines
during the mark termination STW.

There are a few subtleties that we need to account for. For one, it's
possible that a goroutine which blocked in a weak->strong conversion
wakes up only to find it's mark termination time again, so we need to
recheck the global flag on wake. We should also stay non-preemptible
while performing the check, so that if the check *does* appear as true,
it cannot switch back to false while we're actively trying to block. If
it switches to false while we try to block, then we'll be stuck in the
queue until the following GC.

All-in-all, this CL is more complicated than I would have liked, but
it's the only idea so far that is clearly correct to me at a high level.

This change adds a test which is somewhat invasive as it manipulates
mark termination, but hopefully that infrastructure will be useful for
debugging, fixing, and regression testing mark termination whenever we
do fix it.

For #69803.
Fixes #70323.

Change-Id: Ie314e6fd357c9e2a07a9be21f217f75f7aba8c4a
Reviewed-on: https://go-review.googlesource.com/c/go/+/623615
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
(cherry picked from commit 80d306da50)
Reviewed-on: https://go-review.googlesource.com/c/go/+/627615
TryBot-Bypass: Dmitri Shuralyov <dmitshur@google.com>
Auto-Submit: Dmitri Shuralyov <dmitshur@google.com>
2024-11-20 19:08:32 +00:00
qmuntal
847cb6f9ca [release-branch.go1.23] syscall: mark SyscallN as noescape
syscall.SyscallN is implemented by runtime.syscall_syscalln, which makes
sure that the variadic argument doesn't escape.

There is no need to worry about the lifetime of the elements of the
variadic argument, as the compiler will keep them live until the
function returns.

For #70197
Fixes #70202

Change-Id: I12991f0be12062eea68f2b103fa0a794c1b527eb
Reviewed-on: https://go-review.googlesource.com/c/go/+/625297
Reviewed-by: Ian Lance Taylor <iant@google.com>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
Reviewed-by: David Chase <drchase@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
(cherry picked from commit 7fff741016)
Reviewed-on: https://go-review.googlesource.com/c/go/+/630196
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>
Reviewed-by: Quim Muntal <quimmuntal@gmail.com>
2024-11-20 18:07:04 +00:00
Dmitri Shuralyov
777f43ab27 [release-branch.go1.23]time: accept "+01" in TestLoadFixed on OpenBSD
This stops the test from failing with a known failure mode, and
creates time to look into what the next steps should be, if any.

For #69840
Fixes #70239

Change-Id: I060903d256ed65c5dfcd70ae76eb361cab63186f
Reviewed-on: https://go-review.googlesource.com/c/go/+/625197
Auto-Submit: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Reviewed-by: Eric Grosse <grosse@gmail.com>
(cherry picked from commit bea9b91f0f)
Reviewed-on: https://go-review.googlesource.com/c/go/+/627575
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
TryBot-Bypass: Dmitri Shuralyov <dmitshur@google.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>
2024-11-19 18:04:02 +00:00
David Chase
3726f07c46 [release-branch.go1.23] cmd/compile: use a non-fragile test for "does f contain closure c?"
The old test relied on naming conventions.  The new test
uses an explicit parent pointer chain initialized when the
closures are created (in the same place that the names
used in the older fragile test were assigned).

Fixes #70198.

Change-Id: Ie834103c7096e4505faaff3bed1fc6e918a21211
Reviewed-on: https://go-review.googlesource.com/c/go/+/622656
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/625535
Auto-Submit: Dmitri Shuralyov <dmitshur@google.com>
2024-11-19 17:52:28 +00:00
Gopher Robot
c390a1c22e [release-branch.go1.23] go1.23.3
Change-Id: I065005a4a18f801d09ad3ebc886e90a6dd1df69a
Reviewed-on: https://go-review.googlesource.com/c/go/+/626137
Reviewed-by: Carlos Amedee <carlos@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Gopher Robot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
2024-11-06 22:48:16 +00:00
qmuntal
1207de4f6c [release-branch.go1.23] runtime: reduce syscall.SyscallX stack usage
syscall.SyscallX consumes a lot of stack space, which is a problem
because they are nosplit functions. They used to use less stack space,
but CL 563315, that landed in Go 1.23, increased the stack usage by a
lot.

This CL reduces the stack usage back to the previous level.

Fixes #69848
Updates #69813

Change-Id: Iddedd28b693c66a258da687389768055c493fc2e
Reviewed-on: https://go-review.googlesource.com/c/go/+/618497
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
(cherry picked from commit fa7343aca3)
Reviewed-on: https://go-review.googlesource.com/c/go/+/623516
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
2024-10-30 17:06:14 +00:00
Felix Geisendörfer
a0d15cb9c8 [release-branch.go1.23] runtime: fix MutexProfile missing root frames
Fix a regression introduced in CL 598515 causing runtime.MutexProfile
stack traces to omit their root frames.

In most cases this was merely causing the `runtime.goexit` frame to go
missing. But in the case of runtime._LostContendedRuntimeLock, an empty
stack trace was being produced.

Add a test that catches this regression by checking for a stack trace
with the `runtime.goexit` frame.

Also fix a separate problem in expandFrame that could cause
out-of-bounds panics when profstackdepth is set to a value below 32.
There is no test for this fix because profstackdepth can't be changed at
runtime right now.

Fixes #69865

Change-Id: I1600fe62548ea84981df0916d25072c3ddf1ea1a
Reviewed-on: https://go-review.googlesource.com/c/go/+/611615
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Nick Ripley <nick.ripley@datadoghq.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
(cherry picked from commit c64ca8c6ef)
Reviewed-on: https://go-review.googlesource.com/c/go/+/621276
Reviewed-by: Cherry Mui <cherryyz@google.com>
2024-10-30 17:05:06 +00:00
Andy Pan
958f3a0309 [release-branch.go1.23] internal/poll: handle the special case of sendfile(2) sending the full chunk
CL 622235 would fix #70000 while resulting in one extra sendfile(2) system
call when sendfile(2) returns (>0, EAGAIN).
That's also why I left sendfile_bsd.go behind, and didn't make it line up
with other two implementations: sendfile_linux.go and sendfile_solaris.go.

Unlike sendfile(2)'s on Linux and Solaris that always return (0, EAGAIN),
sendfile(2)'s on *BSD and macOS may return (>0, EAGAIN) when using a socket
marked for non-blocking I/O. In that case, the current code will try to re-call
sendfile(2) immediately, which will most likely get us a (0, EAGAIN).
After that, it goes to `dstFD.pd.waitWrite(dstFD.isFile)` below,
which should have been done in the first place.

Thus, the real problem that leads to #70000 is that the old code doesn't handle
the special case of sendfile(2) sending the exact number of bytes the caller requested.

Fixes #70000
Fixes #70020

Change-Id: I6073d6b9feb58b3d7e114ec21e4e80d9727bca66
Reviewed-on: https://go-review.googlesource.com/c/go/+/622255
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Damien Neil <dneil@google.com>
Run-TryBot: Andy Pan <panjf2000@gmail.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/622697
2024-10-30 17:04:03 +00:00
Damien Neil
6ba3a8a6ba [release-branch.go1.23] internal/poll: keep copying after successful Sendfile return on BSD
The BSD implementation of poll.SendFile incorrectly halted
copying after succesfully writing one full chunk of data.
Adjust the copy loop to match the Linux and Solaris
implementations.

In testing, empirically macOS appears to sometimes return
EAGAIN from sendfile after successfully copying a full
chunk. Add a check to all implementations to return nil
after successfully copying all data if the last sendfile
call returns EAGAIN.

For #70000
For #70020

Change-Id: I57ba649491fc078c7330310b23e1cfd85135c8ff
Reviewed-on: https://go-review.googlesource.com/c/go/+/622235
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
(cherry picked from commit bd388c0216)
Reviewed-on: https://go-review.googlesource.com/c/go/+/622696
2024-10-30 17:03:55 +00:00
Cherry Mui
5472853843 [release-branch.go1.23] cmd/link: generate Mach-O UUID when -B flag is specified
Currently, on Mach-O, the Go linker doesn't generate LC_UUID in
internal linking mode. This causes some macOS system tools unable
to track the binary, as well as in some cases the binary unable
to access local network on macOS 15.

This CL makes the linker start generate LC_UUID. Currently, the
UUID is generated if the -B flag is specified. And we'll make it
generate UUID by default in a later CL. The -B flag is currently
for generating GNU build ID on ELF, which is a similar concept to
Mach-O's UUID. Instead of introducing another flag, we just use
the same flag and the same setting. Specifically, "-B gobuildid"
will generate a UUID based on the Go build ID.

Updates #68678.
Fixes #69992.

Cq-Include-Trybots: luci.golang.try:go1.23-darwin-amd64_14,go1.23-darwin-arm64_13
Change-Id: I90089a78ba144110bf06c1c6836daf2d737ff10a
Reviewed-on: https://go-review.googlesource.com/c/go/+/618595
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Ingo Oeser <nightlyone@googlemail.com>
Reviewed-by: Than McIntosh <thanm@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
(cherry picked from commit 20ed603118)
Reviewed-on: https://go-review.googlesource.com/c/go/+/622595
Reviewed-by: Michael Pratt <mpratt@google.com>
2024-10-30 17:03:35 +00:00
Michael Anthony Knyszek
cfe0ae0b70 [release-branch.go1.23] runtime: uphold goroutine profile invariants in coroswitch
Goroutine profiles require checking in with the profiler before any
goroutine starts running. coroswitch is a place where a goroutine may
start running, but where we do not check in with the profiler, which
leads to crashes. Fix this by checking in with the profiler the same way
execute does.

For #69998.
Fixes #70001.

Change-Id: Idef6dd31b70a73dd1c967b56c307c7a46a26ba73
Reviewed-on: https://go-review.googlesource.com/c/go/+/622016
Reviewed-by: David Chase <drchase@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
(cherry picked from commit 2a98a1849f)
Reviewed-on: https://go-review.googlesource.com/c/go/+/622375
Reviewed-by: Michael Pratt <mpratt@google.com>
2024-10-30 16:49:25 +00:00
Michael Anthony Knyszek
58babf6e0b [release-branch.go1.23] runtime,time: use atomic.Int32 for isSending
This change switches isSending to be an atomic.Int32 instead of an
atomic.Uint8. The Int32 version is managed as a counter, which is
something that we couldn't do with Uint8 without adding a new intrinsic
which may not be available on all architectures.

That is, instead of only being able to support 8 concurrent timer
firings on the same timer because we only have 8 independent bits to set
for each concurrent timer firing, we can now have 2^31-1 concurrent
timer firings before running into any issues. Like the fact that each
bit-set was matched with a clear, here we match increments with
decrements to indicate that we're in the "sending on a channel" critical
section in the timer code, so we can report the correct result back on
Stop or Reset.

We choose an Int32 instead of a Uint32 because it's easier to check for
obviously bad values (negative values are always bad) and 2^31-1
concurrent timer firings should be enough for anyone.

Previously, we avoided anything bigger than a Uint8 because we could
pack it into some padding in the runtime.timer struct. But it turns out
that the type that actually matters, runtime.timeTimer, is exactly 96
bytes in size. This means its in the next size class up in the 112 byte
size class because of an allocation header. We thus have some free space
to work with. This change increases the size of this struct from 96
bytes to 104 bytes.

(I'm not sure if runtime.timer is often allocated directly, but if it
is, we get lucky in the same way too. It's exactly 80 bytes in size,
which means its in the 96-byte size class, leaving us with some space to
work with.)

Fixes #69978
For #69969.
Related to #69880 and #69312 and #69882.

Change-Id: I9fd59cb6a69365c62971d1f225490a65c58f3e77
Cq-Include-Trybots: luci.golang.try:go1.23-linux-amd64-longtest
Reviewed-on: https://go-review.googlesource.com/c/go/+/621616
Reviewed-by: Ian Lance Taylor <iant@google.com>
Auto-Submit: Michael Knyszek <mknyszek@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
(cherry picked from commit 6a49f81edc)
Reviewed-on: https://go-review.googlesource.com/c/go/+/621856
Auto-Submit: Ian Lance Taylor <iant@google.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
2024-10-25 20:34:25 +00:00
Ian Lance Taylor
8d79bf799b [release-branch.go1.23] runtime: don't frob isSending for tickers
The Ticker Stop and Reset methods don't report a value,
so we don't need to track whether they are interrupting a send.

This includes a test that used to fail about 2% of the time on
my laptop when run under x/tools/cmd/stress.

For #69880
Fixes #69882

Change-Id: Ic6d14b344594149dd3c24b37bbe4e42e83f9a9ad
Reviewed-on: https://go-review.googlesource.com/c/go/+/620136
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Auto-Submit: Michael Knyszek <mknyszek@google.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
(cherry picked from commit 48849e0866)
Reviewed-on: https://go-review.googlesource.com/c/go/+/620137
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
2024-10-23 22:07:00 +00:00
Felix Geisendörfer
35c010ad6d [release-branch.go1.23] runtime: fix GoroutineProfile stacks not getting null terminated
Fix a regression introduced in CL 572396 causing goroutine stacks not
getting null terminated.

This bug impacts callers that reuse the []StackRecord slice for multiple
calls to GoroutineProfile. See https://github.com/felixge/fgprof/issues/33
for an example of the problem.

Add a test case to prevent similar regressions in the future. Use null
padding instead of null termination to be consistent with other profile
types and because it's less code to implement. Also fix the
ThreadCreateProfile code path.

Fixes #69258

Change-Id: I0b9414f6c694c304bc03a5682586f619e9bf0588
Reviewed-on: https://go-review.googlesource.com/c/go/+/609815
Reviewed-by: Tim King <taking@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
(cherry picked from commit 49e542aa85)
Reviewed-on: https://go-review.googlesource.com/c/go/+/621277
Reviewed-by: Cherry Mui <cherryyz@google.com>
2024-10-21 18:37:43 +00:00
Michael Pratt
6495ce0495 [release-branch.go1.23] syscall: use SYS_EXIT_GROUP in CLONE_PIDFD feature check child
Inside Google we have seen issues with QEMU user mode failing to wake a
parent waitid when this child exits with SYS_EXIT. This bug appears to
not affect SYS_EXIT_GROUP.

It is currently unclear if this is a general QEMU or specific to
Google's configuration, but SYS_EXIT and SYS_EXIT_GROUP are semantically
equivalent here, so we can use the latter here in case this is a general
QEMU bug.

For #68976.
For #69259.

Change-Id: I34e51088c9a6b7493a060e2a719a3cc4a3d54aa0
Reviewed-on: https://go-review.googlesource.com/c/go/+/617417
Reviewed-by: Ian Lance Taylor <iant@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
(cherry picked from commit 47a9935920)
Reviewed-on: https://go-review.googlesource.com/c/go/+/617716
2024-10-11 17:02:01 +00:00
Michael Pratt
7fc8312673 [release-branch.go1.23] os: add clone(CLONE_PIDFD) check to pidfd feature check
clone(CLONE_PIDFD) was added in Linux 5.2 and pidfd_open was added in
Linux 5.3. Thus our feature check for pidfd_open should be sufficient to
ensure that clone(CLONE_PIDFD) works.

Unfortuantely, some alternative Linux implementations may not follow
this strict ordering. For example, QEMU 7.2 (Dec 2022) added pidfd_open,
but clone(CLONE_PIDFD) was only added in QEMU 8.0 (Apr 2023).

Debian bookworm provides QEMU 7.2 by default.

For #68976.
Fixes #69259.

Change-Id: Ie3f3dc51f0cd76944871bf98690abf59f68fd7bf
Reviewed-on: https://go-review.googlesource.com/c/go/+/592078
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
(cherry picked from commit 7a5fc9b34d)
Reviewed-on: https://go-review.googlesource.com/c/go/+/612218
2024-10-11 17:01:46 +00:00
Ian Lance Taylor
cc16cdf48f [release-branch.go1.23] runtime: clear isSending bit earlier
I've done some more testing of the new isSending field.
I'm not able to get more than 2 bits set. That said,
with this change it's significantly less likely to have even
2 bits set. The idea here is to clear the bit before possibly
locking the channel we are sending the value on, thus avoiding
some delay and some serialization.

For #69312
For #69333

Change-Id: I8b5f167f162bbcbcbf7ea47305967f349b62b0f4
Reviewed-on: https://go-review.googlesource.com/c/go/+/617596
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Commit-Queue: Ian Lance Taylor <iant@google.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>
2024-10-08 22:28:41 +00:00
cions
9563300f6e [release-branch.go1.23] os: ignore SIGSYS in checkPidfd
In Android version 11 and earlier, pidfd-related system calls
are not allowed by the seccomp policy, which causes crashes due
to SIGSYS signals.

For #69065
Fixes #69640

Change-Id: Ib29631639a5cf221ac11b4d82390cb79436b8657
GitHub-Last-Rev: aad6b3b32c
GitHub-Pull-Request: golang/go#69543
Reviewed-on: https://go-review.googlesource.com/c/go/+/614277
Auto-Submit: Ian Lance Taylor <iant@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
(cherry picked from commit a3a05ed04c)
Reviewed-on: https://go-review.googlesource.com/c/go/+/616077
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Kirill Kolyshkin <kolyshkin@gmail.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Mauri de Souza Meneguzzo <mauri870@gmail.com>
Auto-Submit: Michael Knyszek <mknyszek@google.com>
2024-10-02 16:52:24 +00:00
Shulhan
f8080edefd [release-branch.go1.23] runtime: fix TestGdbAutotmpTypes on gdb version 15
On Arch Linux with gdb version 15.1, the test for TestGdbAutotmpTypes print
the following output,

----
~/src/go/src/runtime
$ go test -run=TestGdbAutotmpTypes -v
=== RUN   TestGdbAutotmpTypes
=== PAUSE TestGdbAutotmpTypes
=== CONT  TestGdbAutotmpTypes
    runtime-gdb_test.go:78: gdb version 15.1
    runtime-gdb_test.go:570: gdb output:
        Loading Go Runtime support.
        Target 'exec' cannot support this command.
        Breakpoint 1 at 0x46e416: file /tmp/TestGdbAutotmpTypes750485513/001/main.go, line 8.

        This GDB supports auto-downloading debuginfo from the following URLs:
          <https://debuginfod.archlinux.org>
        Enable debuginfod for this session? (y or [n]) [answered N; input not from terminal]
        Debuginfod has been disabled.
        To make this setting permanent, add 'set debuginfod enabled off' to .gdbinit.
        [New LWP 355373]
        [New LWP 355374]
        [New LWP 355375]
        [New LWP 355376]

        Thread 1 "a.exe" hit Breakpoint 1, main.main () at /tmp/TestGdbAutotmpTypes750485513/001/main.go:8
        8       func main() {
        9               var iface interface{} = map[string]astruct{}
        All types matching regular expression "astruct":

        File runtime:
                []main.astruct
                bucket<string,main.astruct>
                hash<string,main.astruct>
                main.astruct
                typedef hash<string,main.astruct> * map[string]main.astruct;
                typedef noalg.[8]main.astruct noalg.[8]main.astruct;
                noalg.map.bucket[string]main.astruct
    runtime-gdb_test.go:587: could not find []main.astruct; in 'info typrs astruct' output
!!! FAIL
exit status 1
FAIL    runtime 0.273s
$
----

In the back trace for "File runtime", each output lines does not end with
";" anymore, while in test we check the string with it.

While at it, print the expected string with "%q" instead of "%s" for
better error message.

For #67089
Fixes #69746

Change-Id: If6019ee68c0d8e495c920f98568741462c7d0fd0
Reviewed-on: https://go-review.googlesource.com/c/go/+/598135
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Meng Zhuo <mengzhuo1203@gmail.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
(cherry picked from commit ff695ca2e3)
Reviewed-on: https://go-review.googlesource.com/c/go/+/617455
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Auto-Submit: Michael Knyszek <mknyszek@google.com>
2024-10-02 16:23:59 +00:00
Gopher Robot
ed07b321ae [release-branch.go1.23] go1.23.2
Change-Id: I904d2e951796dd4142d6e9de4a55af07852bca51
Reviewed-on: https://go-review.googlesource.com/c/go/+/617019
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Auto-Submit: Gopher Robot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
2024-10-01 17:24:29 +00:00
Ian Lance Taylor
3b2e846e11 [release-branch.go1.23] runtime: if stop/reset races with running timer, return correct result
The timer code is careful to ensure that if stop/reset is called
while a timer is being run, we cancel the run. However, the code
failed to ensure that in that case stop/reset returned true,
meaning that the timer had been stopped. In the racing case
stop/reset could see that t.when had been set to zero,
and return false, even though the timer had not and never would fire.

Fix this by tracking whether a timer run is in progress,
and using that to reliably detect that the run was cancelled,
meaning that stop/reset should return true.

For #69312
Fixes #69333

Change-Id: I78e870063eb96650638f12c056e32c931417c84a
Reviewed-on: https://go-review.googlesource.com/c/go/+/611496
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Ian Lance Taylor <iant@golang.org>
(cherry picked from commit 2ebaff4890)
Reviewed-on: https://go-review.googlesource.com/c/go/+/616096
Reviewed-by: Ian Lance Taylor <iant@google.com>
Commit-Queue: Ian Lance Taylor <iant@google.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>
2024-09-27 18:23:47 +00:00
Cuong Manh Le
fbddfae62f [release-branch.go1.23] cmd/compile: fix wrong esacpe analysis for rangefunc
CL 584596 "-range<N>" suffix to the name of closure generated for a
rangefunc loop body. However, this breaks the condition that escape
analysis uses for checking whether a closure contains within function,
which is "F.funcN" for outer function "F" and closure "funcN".

Fixing this by adding new "-rangeN" to the condition.

Updates #69434
Fixes #69511

Change-Id: I411de8f63b69a6514a9e9504d49d62e00ce4115d
Reviewed-on: https://go-review.googlesource.com/c/go/+/614096
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/614195
2024-09-25 16:22:40 +00:00
Ian Lance Taylor
c8c6f9abfb [release-branch.go1.23] syscall: on exec failure, close pidfd
For #69284
Fixes #69402

Change-Id: I6350209302778ba5e44fa03d0b9e680d2b4ec192
Reviewed-on: https://go-review.googlesource.com/c/go/+/611495
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: roger peppe <rogpeppe@gmail.com>
Reviewed-by: Tim King <taking@google.com>
Auto-Submit: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
(cherry picked from commit 8926ca9c5e)
Reviewed-on: https://go-review.googlesource.com/c/go/+/613616
Reviewed-by: Ian Lance Taylor <iant@google.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>
Reviewed-by: Tobias Klauser <tobias.klauser@gmail.com>
2024-09-18 19:41:05 +00:00
Michael Anthony Knyszek
a74951c5af [release-branch.go1.23] unique: don't retain uncloned input as key
Currently the unique package tries to clone strings that get stored in
its internal map to avoid retaining large strings.

However, this falls over entirely due to the fact that the original
string is *still* stored in the map as a key. Whoops. Fix this by
storing the cloned value in the map instead.

This change also adds a test which fails without this change.

For #69370.
Fixes #69383.

Change-Id: I1a6bb68ed79b869ea12ab6be061a5ae4b4377ddb
Reviewed-on: https://go-review.googlesource.com/c/go/+/610738
Reviewed-by: Michael Pratt <mpratt@google.com>
Auto-Submit: Michael Knyszek <mknyszek@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
(cherry picked from commit 21ac23a96f)
Reviewed-on: https://go-review.googlesource.com/c/go/+/612295
Auto-Submit: Tim King <taking@google.com>
2024-09-11 18:11:20 +00:00
Wei Fu
e6598e7baa [release-branch.go1.23] os: dup pidfd if caller sets PidFD manually
For #68984.
Fixes #69119.

Change-Id: I16d25777cb38a337cd4204a8147eaf866c3df9e1
Reviewed-on: https://go-review.googlesource.com/c/go/+/607695
Reviewed-by: Kirill Kolyshkin <kolyshkin@gmail.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Commit-Queue: Ian Lance Taylor <iant@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Auto-Submit: Ian Lance Taylor <iant@golang.org>
(cherry picked from commit 239666cd73)
Reviewed-on: https://go-review.googlesource.com/c/go/+/611415
Auto-Submit: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
TryBot-Bypass: Dmitri Shuralyov <dmitshur@golang.org>
2024-09-06 16:06:09 +00:00
Michael Anthony Knyszek
82575f76b8 [release-branch.go1.23] internal/weak: shade pointer in weak-to-strong conversion
There's a bug in the weak-to-strong conversion in that creating the
*only* strong pointer to some weakly-held object during the mark phase
may result in that object not being properly marked.

The exact mechanism for this is that the new strong pointer will always
point to a white object (because it was only weakly referenced up until
this point) and it can then be stored in a blackened stack, hiding it
from the garbage collector.

This "hide a white pointer in the stack" problem is pretty much exactly
what the Yuasa part of the hybrid write barrier is trying to catch, so
we need to do the same thing the write barrier would do: shade the
pointer.

Added a test and confirmed that it fails with high probability if the
pointer shading is missing.

For #69210.
Fixes #69240.

Change-Id: Iaae64ae95ea7e975c2f2c3d4d1960e74e1bd1c3f
Reviewed-on: https://go-review.googlesource.com/c/go/+/610396
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
Auto-Submit: Michael Knyszek <mknyszek@google.com>
(cherry picked from commit 79fd633632)
Reviewed-on: https://go-review.googlesource.com/c/go/+/610696
Auto-Submit: Dmitri Shuralyov <dmitshur@google.com>
2024-09-06 14:34:16 +00:00
Keith Randall
a886959aa2 [release-branch.go1.23] runtime: size maps.Clone destination bucket array safely
In rare situations, like during same-sized grows, the source map for
maps.Clone may be overloaded (has more than 6.5 entries per
bucket). This causes the runtime to allocate a larger bucket array for
the destination map than for the source map. The maps.Clone code
walks off the end of the source array if it is smaller than the
destination array.

This is a pretty simple fix, ensuring that the destination bucket
array is never longer than the source bucket array. Maybe a better fix
is to make the Clone code handle shorter source arrays correctly, but
this fix is deliberately simple to reduce the risk of backporting this
fix.

Fixes #69156

Change-Id: I824c93d1db690999f25a3c43b2816fc28ace7509
Reviewed-on: https://go-review.googlesource.com/c/go/+/610377
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Keith Randall <khr@google.com>
2024-09-06 14:32:57 +00:00
Ian Lance Taylor
80ff7cd35a [release-branch.go1.23] cmd/cgo: correct padding required by alignment
If the aligned offset isn't sufficient for the field offset,
we were padding based on the aligned offset. We need to pad
based on the original offset instead.

Also set the Go alignment correctly for int128. We were defaulting
to the maximum alignment, but since we translate int128 into an
array of uint8 the correct Go alignment is 1.

For #69086
Fixes #69219

Change-Id: I23ce583335c81beac2ac51f7f9336ac97ccebf09
Reviewed-on: https://go-review.googlesource.com/c/go/+/608815
Reviewed-by: Damien Neil <dneil@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Auto-Submit: Ian Lance Taylor <iant@golang.org>
(cherry picked from commit c209892905)
Reviewed-on: https://go-review.googlesource.com/c/go/+/611296
Reviewed-by: Ian Lance Taylor <iant@google.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>
Commit-Queue: Ian Lance Taylor <iant@google.com>
2024-09-05 21:57:44 +00:00
Gopher Robot
69234ded30 [release-branch.go1.23] go1.23.1
Change-Id: I1f2dab5560d3214c8934074a53f7750d8d431936
Reviewed-on: https://go-review.googlesource.com/c/go/+/611196
Reviewed-by: Michael Pratt <mpratt@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Commit-Queue: Gopher Robot <gobot@golang.org>
TryBot-Bypass: Dmitri Shuralyov <dmitshur@google.com>
Auto-Submit: Gopher Robot <gobot@golang.org>
2024-09-05 15:20:23 +00:00
Roland Shoemaker
032ac075c2 [release-branch.go1.23] go/build/constraint: add parsing limits
Limit the size of build constraints that we will parse. This prevents a
number of stack exhaustions that can be hit when parsing overly complex
constraints. The imposed limits are unlikely to ever be hit in real
world usage.

Updates #69141
Fixes #69149
Fixes CVE-2024-34158

Change-Id: I38b614bf04caa36eefc6a4350d848588c4cef3c4
Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/1540
Reviewed-by: Damien Neil <dneil@google.com>
Reviewed-by: Russ Cox <rsc@google.com>
(cherry picked from commit 0c74dc9e0da0cf1e12494b514d822b5bebbc9f04)
Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/1562
Commit-Queue: Roland Shoemaker <bracewell@google.com>
Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/611177
Reviewed-by: Michael Pratt <mpratt@google.com>
TryBot-Bypass: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Auto-Submit: Dmitri Shuralyov <dmitshur@google.com>
2024-09-05 14:55:17 +00:00
Roland Shoemaker
fa8ff1a46d [release-branch.go1.23] encoding/gob: cover missed cases when checking ignore depth
This change makes sure that we are properly checking the ignored field
recursion depth in decIgnoreOpFor consistently. This prevents stack
exhaustion when attempting to decode a message that contains an
extremely deeply nested struct which is ignored.

Thanks to Md Sakib Anwar of The Ohio State University (anwar.40@osu.edu)
for reporting this issue.

Updates #69139
Fixes #69145
Fixes CVE-2024-34156

Change-Id: Iacce06be95a5892b3064f1c40fcba2e2567862d6
Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/1440
Reviewed-by: Russ Cox <rsc@google.com>
Reviewed-by: Damien Neil <dneil@google.com>
(cherry picked from commit 9f2ea73c5f2a7056b7da5d579a485a7216f4b20a)
Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/1581
Commit-Queue: Roland Shoemaker <bracewell@google.com>
Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/611176
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Auto-Submit: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
TryBot-Bypass: Dmitri Shuralyov <dmitshur@google.com>
2024-09-05 14:55:14 +00:00
Roland Shoemaker
53487e5477 [release-branch.go1.23] go/parser: track depth in nested element lists
Prevents stack exhaustion with extremely deeply nested literal values,
i.e. field values in structs.

Updates #69138
Fixes #69143
Fixes CVE-2024-34155

Change-Id: I2e8e33b44105cc169d7ed1ae83fb56df0c10f1ee
Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/1520
Reviewed-by: Robert Griesemer <gri@google.com>
Reviewed-by: Damien Neil <dneil@google.com>
Reviewed-by: Russ Cox <rsc@google.com>
(cherry picked from commit eb1b038c0d01761694e7a735ef87ac9164c6568e)
Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/1560
Commit-Queue: Roland Shoemaker <bracewell@google.com>
Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/611175
Auto-Submit: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
TryBot-Bypass: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
2024-09-05 14:55:11 +00:00
Michael Pratt
3d1f1f27cf [release-branch.go1.23] cmd: vendor golang.org/x/telemetry@internal-branch.go1.23-vendor
Update x/telemetry to fix #68976 and #68946.

Commands run:
  go get golang.org/x/telemetry@internal-branch.go1.23-vendor
  go mod tidy
  go mod vendor

Fixes #68994.
Fixes #68995.

Change-Id: I63b892ad4c313aa92f21fbd4f519a0b19d725849
Reviewed-on: https://go-review.googlesource.com/c/go/+/609355
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Michael Pratt <mpratt@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
2024-08-29 00:09:27 +00:00
Nic Klaassen
6de5a7180c [release-branch.go1.23] database/sql: fix panic with concurrent Conn and Close
The current implementation has a panic when the database is closed
concurrently with a new connection attempt.

connRequestSet.CloseAndRemoveAll sets connRequestSet.s to a nil slice.
If this happens between calls to connRequestSet.Add and
connRequestSet.Delete, there is a panic when trying to write to the nil
slice. This is sequence is likely to occur in DB.conn, where the mutex
is released between calls to db.connRequests.Add and
db.connRequests.Delete

This change updates connRequestSet.CloseAndRemoveAll to set the curIdx
to -1 for all pending requests before setting its internal slice to nil.
CloseAndRemoveAll already iterates the full slice to close all the request
channels. It seems appropriate to set curIdx to -1 before deleting the
slice for 3 reasons:
1. connRequestSet.deleteIndex also sets curIdx to -1
2. curIdx will not be relevant to anything after the slice is set to nil
3. connRequestSet.Delete already checks for negative indices

For #68949
Fixes #69041

Change-Id: I6b7ebc5a71b67322908271d13865fa12f2469b87
GitHub-Last-Rev: 7d2669155b
GitHub-Pull-Request: golang/go#68953
Reviewed-on: https://go-review.googlesource.com/c/go/+/607238
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Ian Lance Taylor <iant@golang.org>
Commit-Queue: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
(cherry picked from commit 08707d66c3)
Reviewed-on: https://go-review.googlesource.com/c/go/+/609255
2024-08-28 18:37:00 +00:00
Tim King
9625a7faae [release-branch.go1.23] go/types, types2: unalias tilde terms in underIs
Unalias the ~T terms during underIs. Before, if T was an alias
of U, it may pass T to the iteration function. The iterator
function expects an underlying type, under(U), to be passed.
This caused several bugs where underIs is used without
eventually taking the underlying type.

Fixes #68905

Change-Id: Ie8691d8dddaea00e1dcba94d17c0f1b021fc49a2
Reviewed-on: https://go-review.googlesource.com/c/go/+/606075
Reviewed-by: Robert Griesemer <gri@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Robert Findley <rfindley@google.com>
(cherry picked from commit 1a90dcdaaf)
Reviewed-on: https://go-review.googlesource.com/c/go/+/607635
2024-08-28 18:10:23 +00:00
Michael Anthony Knyszek
9c939a1e60 [release-branch.go1.23] runtime: store bp on cgocallback as unsafe.Pointer
As of CL 580255, the runtime tracks the frame pointer (or base pointer,
bp) when entering syscalls, so that we can use fpTracebackPCs on
goroutines that are sitting in syscalls. That CL mostly got things
right, but missed one very subtle detail.

When calling from Go->C->Go, the goroutine stack performing the calls
when returning to Go is free to move around in memory due to growth,
shrinking, etc. But upon returning back to C, it needs to restore
gp.syscall*, including gp.syscallsp and gp.syscallbp. The way syscallsp
currently gets updated is automagically: it's stored as an
unsafe.Pointer on the stack so that it shows up in a stack map. If the
stack ever moves, it'll get updated correctly. But gp.syscallbp isn't
saved to the stack as an unsafe.Pointer, but rather as a uintptr, so it
never gets updated! As a result, in rare circumstances, fpTracebackPCs
can correctly try to use gp.syscallbp as the starting point for the
traceback, but the value is stale.

This change fixes the problem by just storing gp.syscallbp to the stack
on cgocallback as an unsafe.Pointer, like gp.syscallsp. It also adds a
comment documenting this subtlety; the lack of explanation for the
unsafe.Pointer type on syscallsp meant this detail was missed -- let's
not miss it again in the future.

Now, we have a fix, what about a test? Unfortunately, testing this is
going to be incredibly annoying because the circumstances under which
gp.syscallbp are actually used for traceback are non-deterministic and
hard to arrange, especially from within testprogcgo where we don't have
export_test.go and can't reach into the runtime.

So, instead, add a gp.syscallbp check to reentersyscall and
entersyscallblock that mirrors the gp.syscallbp consistency check. This
probably causes some miniscule slowdown to the syscall path, but it'll
catch the issue without having to actually perform a traceback.

For #69085.
Fixes #69087.

Change-Id: Iaf771758f1666024b854f5fbe2b2c63cbe35b201
Reviewed-on: https://go-review.googlesource.com/c/go/+/608775
Reviewed-by: Nick Ripley <nick.ripley@datadoghq.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
(cherry picked from commit 54fe0fd43f)
Reviewed-on: https://go-review.googlesource.com/c/go/+/608835
2024-08-28 17:42:20 +00:00
Michael Matloob
7afe17bbdb [release-branch.go1.23] go/types, types2: use max(fileVersion, go1.21) if fileVersion present
Change the rules for how //go:build "file versions" are applied: instead
of considering whether a file version is an upgrade or downgrade from
the -lang version, always use max(fileVersion, go1.21). This prevents
file versions from downgrading the version below go1.21.  Before Go 1.21
the //go:build version did not have the meaning of setting the file's
langage version.

This fixes an issue that was appearing in GOPATH builds: Go 1.23.0
started providing -lang versions to the compiler in GOPATH mode (among
other places) which it wasn't doing before, and it set -lang to the
toolchain version (1.23). Because the -lang version was greater than
go1.21, language version used to compile the file would be set to the
//go:build file version. //go:build file versions below 1.21 could cause
files that could previously build to stop building.

For example, take a Go file with a //go:build line specifying go1.10.
If that file used a 1.18 feature, that use would compile fine with a Go
1.22 toolchain. But it would produce an error when compiling with the
1.23.0 toolchain because it set the language version to 1.10 and
disallowed the 1.18 feature. This breaks backwards compatibility: when
the build tag was added, it did not have the meaning of restricting the
language version.

For #68658
Fixes #69094

Change-Id: I6cedda81a55bcccffaa3501eef9e2be6541b6ece
Reviewed-on: https://go-review.googlesource.com/c/go/+/607955
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Robert Griesemer <gri@google.com>
(cherry picked from commit aeac0b6cbf)
Reviewed-on: https://go-review.googlesource.com/c/go/+/608935
2024-08-28 15:43:17 +00:00
Paul E. Murphy
8002845759 [release-branch.go1.23] runtime: on AIX, fix call to _cgo_sys_thread_create in _rt0_ppc64_aix_lib
The AIX ABI requires allocating parameter save space when calling
a function, even if the arguments are passed via registers.

gcc sometimes uses this space. In the case of the cgo c-archive
tests, it clobbered the storage space of argc/argv which prevented
the test program from running the expected test.

Fixes #68973

Change-Id: I8a267b463b1abb2b37ac85231f6c328f406b7515
Reviewed-on: https://go-review.googlesource.com/c/go/+/606895
Reviewed-by: Ian Lance Taylor <iant@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Run-TryBot: Paul Murphy <murp@ibm.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-on: https://go-review.googlesource.com/c/go/+/607195
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
2024-08-21 20:26:47 +00:00
Robert Griesemer
9166d2feec [release-branch.go1.23] go/types, types2: Named.cleanup must also handle *Alias types
Named.cleanup is called at the end of type-checking to ensure that
a named type is fully set up; specifically that it's underlying
field is not (still) a Named type. Now it can also be an *Alias
type. Add this case to the respective type switch.

Fixes #68894.

Change-Id: I29bc0024ac9d8b0152a3d97c82dd28d09d5dbd66
Reviewed-on: https://go-review.googlesource.com/c/go/+/605977
Auto-Submit: Robert Griesemer <gri@google.com>
Reviewed-by: Robert Griesemer <gri@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/606656
2024-08-21 17:42:47 +00:00
Michael Anthony Knyszek
76346b3543 [release-branch.go1.23] unique: use TypeFor instead of TypeOf to get type in Make
Currently the first thing Make does it get the abi.Type of its argument,
and uses abi.TypeOf to do it. However, this has a problem for interface
types, since the type of the value stored in the interface value will
bleed through. This is a classic reflection mistake.

Fix this by implementing and using a generic TypeFor which matches
reflect.TypeFor. This gets the type of the type parameter, which is far
less ambiguous and error-prone.

For #68990.
Fixes #68992.

Change-Id: Idd8d9a1095ef017e9cd7c7779314f7d4034f01a7
Reviewed-on: https://go-review.googlesource.com/c/go/+/607355
Reviewed-by: David Chase <drchase@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
(cherry picked from commit 755c18ecdf)
Reviewed-on: https://go-review.googlesource.com/c/go/+/607435
Reviewed-by: Ian Lance Taylor <iant@google.com>
2024-08-21 17:42:03 +00:00
Andy Pan
3c9340557c [release-branch.go1.23] os: use O_EXCL instead of O_TRUNC in CopyFS to disallow rewriting existing files does not exist
On Linux, a call to creat() is equivalent to calling open() with flags
equal to O_CREAT|O_WRONLY|O_TRUNC, which applies to other platforms
as well in a similar manner. Thus, to force CopyFS's behavior to
comply with the function comment, we need to replace O_TRUNC with O_EXCL.

Fixes #68907

Change-Id: I3e2ab153609d3c8cf20ce5969d6f3ef593833cd1
Reviewed-on: https://go-review.googlesource.com/c/go/+/606095
Auto-Submit: Ian Lance Taylor <iant@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Damien Neil <dneil@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
(cherry picked from commit aa5d672a00)
Reviewed-on: https://go-review.googlesource.com/c/go/+/606415
2024-08-21 17:05:16 +00:00
Kir Kolyshkin
dbecb416d1 [release-branch.go1.23] os: fix Chtimes test flakes
It appears that some builders (notably, linux-arm) have some additional
security software installed, which apparently reads the files created by
tests. As a result, test file atime is changed, making the test fail
like these:

=== RUN   TestChtimesOmit
    ...
    os_test.go:1475: atime mismatch, got: "2024-07-30 18:42:03.450932494 +0000 UTC", want: "2024-07-30 18:42:02.450932494 +0000 UTC"

=== RUN   TestChtimes
    ...
    os_test.go:1539: AccessTime didn't go backwards; was=2024-07-31 20:45:53.390326147 +0000 UTC, after=2024-07-31 20:45:53.394326118 +0000 UTC

According to inode(7), atime is changed when more than 0 bytes are read
from the file. So, one possible solution to these flakes is to make the
test files empty, so no one can read more than 0 bytes from them.

For #68687
For #68663
Fixes #68812

Change-Id: Ib9234567883ef7b16ff8811e3360cd26c2d6bdab
Reviewed-on: https://go-review.googlesource.com/c/go/+/604315
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Kirill Kolyshkin <kolyshkin@gmail.com>
Reviewed-by: Robert Griesemer <gri@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Commit-Queue: Ian Lance Taylor <iant@google.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>
(cherry picked from commit 84266e1469)
Reviewed-on: https://go-review.googlesource.com/c/go/+/604196
2024-08-14 17:44:07 +00:00
Gopher Robot
6885bad7dd [release-branch.go1.23] go1.23.0
Change-Id: I2b0514157b85ca61f9f6b8931df6ac874598a045
Reviewed-on: https://go-review.googlesource.com/c/go/+/605215
Reviewed-by: Carlos Amedee <carlos@golang.org>
Auto-Submit: Gopher Robot <gobot@golang.org>
Auto-Submit: Carlos Amedee <carlos@golang.org>
Reviewed-by: David Chase <drchase@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2024-08-13 16:16:34 +00:00
Carlos Amedee
ec7d6094e6 [release-branch.go1.23] revert "go/types, types2: only use fileVersion if 1.21 or greater"
This reverts commit CL 604935.

Reason for revert: The team has decided that this change will be added to a point release.

Change-Id: I1c1032b881c3a98312a4753b9767cb7c8eed9e09
Reviewed-on: https://go-review.googlesource.com/c/go/+/605096
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Michael Matloob <matloob@golang.org>
2024-08-13 14:45:01 +00:00
Michael Matloob
63b0f805cd [release-branch.go1.23] go/types, types2: only use fileVersion if 1.21 or greater
Only honor //go:build language version downgrades if the version
specified is 1.21 or greater. Before 1.21 the version in //go:build
lines didn't have the meaning of setting the file's language version.

This fixes an issue that was appearing in GOPATH builds: Go 1.23 started
providing -lang versions to the compiler in GOPATH mode (among other
places) which it wasn't doing before.

For example, take a go file with a //go:build line specifying go1.10.
If that file used a 1.18 feature, that use would compile fine with a Go
1.22 toolchain. But, before this change, it would produce an error when
compiling with the 1.23 toolchain because it set the language version to
1.10 and disallowed the 1.18 feature. This breaks backwards
compatibility: when the build tag was added, it did not have the meaning
of restricting the language version.

Fixes #68658

Change-Id: I4ac2b45a981cd019183d52ba324ba8f0fed93a8e
Reviewed-on: https://go-review.googlesource.com/c/go/+/603895
Reviewed-by: Robert Griesemer <gri@google.com>
Commit-Queue: Michael Matloob <matloob@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Michael Matloob <matloob@golang.org>
Reviewed-on: https://go-review.googlesource.com/c/go/+/604935
2024-08-12 20:21:53 +00:00
Filippo Valsorda
7adb012205 [release-branch.go1.23] crypto/tls: fix testHandshake close flakes
The flakes were introduced by me in CL 586655. It's unclear why only
FreeBSD seems affected, maybe other TCP stacks handle sending on a
half-closed connection differently, or aren't as quick to propagate the
RST over localhost.

Updates #68155

Change-Id: I32a1b474a7d6531dbab93910c23568b867629e8c
Reviewed-on: https://go-review.googlesource.com/c/go/+/602635
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Auto-Submit: Filippo Valsorda <filippo@golang.org>
Reviewed-by: Roland Shoemaker <roland@golang.org>
2024-08-02 19:55:18 +00:00
Cuong Manh Le
c9940fe2a9 [release-branch.go1.23] types2, go/types: fix instantiation of named type with generic alias
The typechecker is assuming that alias instances cannot be reached from
a named type. However, when type parameters on aliases are permited, it
can happen.

This CL changes the typechecker to propagate the correct named instance
is being expanded.

Updates #46477
Fixes #68580

Change-Id: Id0879021f4640c0fefe277701d5096c649413811
Reviewed-on: https://go-review.googlesource.com/c/go/+/601115
Auto-Submit: Robert Griesemer <gri@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Robert Griesemer <gri@google.com>
Auto-Submit: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/601116
2024-07-26 16:35:29 +00:00
Robert Griesemer
3509415eca [release-branch.go1.23] cmd/compile: more informative panic when importing generic type alias
When GOEXPERIMENT=aliastypeparams is set, type aliases may have type
parameters. The compiler export data doesn't export that type parameter
information yet, which leads to an index-out-of-bounds panic when a
client package imports a package with a general type alias and then
refers to one of the missing type parameters.

This CL detects this specific case and panics with a more informative
panic message explaining the shortcoming. The change is only in effect
if the respective GOEXPERIMENT is enabled.

Manually tested. No test addded since this is just a temporary fix
(Go 1.24 will have a complete implementation), and because the existing
testing framework doesn't easily support testing that a compilation
panics.

Together with @taking and input from @rfindley.

For #68526.

Change-Id: I24737b153a7e2f9b705cd29a5b70b2b9e808dffc
Reviewed-on: https://go-review.googlesource.com/c/go/+/601035
Reviewed-by: Tim King <taking@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Robert Griesemer <gri@google.com>
2024-07-26 03:55:54 +00:00
Damien Neil
559c77592f [release-branch.go1.23] os: document CopyFS behavior for symlinks in destination
Also clarify the permissions of created files,
and note that CopyFS will not overwrite files.

Update a few places in documentation to use 0oXXX for octal consts.

For #62484

Change-Id: I208ed2bde250304bc7fac2b93963ba57037e791e
Reviewed-on: https://go-review.googlesource.com/c/go/+/600775
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
(cherry picked from commit 910e6b5fae)
Reviewed-on: https://go-review.googlesource.com/c/go/+/600815
Reviewed-by: Ian Lance Taylor <iant@google.com>
2024-07-24 18:55:12 +00:00
Dmitri Shuralyov
f5e4e45ef7 [release-branch.go1.23] all: merge master (5e8a731) into release-branch.go1.23
Merge List:

+ 2024-07-22 5e8a731665 README: fix CC BY license name
+ 2024-07-22 a799fa5189 slices: explicitly document nil and empty slice equality
+ 2024-07-22 f0de94ff12 cmd/compile: don't inline runtime functions in -d=checkptr build
+ 2024-07-19 3959d54c0b runtime: mark lockWithRankMayAcquire as nosplit
+ 2024-07-17 70491a8111 maps: document handling of non-reflexive keys
+ 2024-07-17 7321aa91c6 cmd: vendor golang.org/x/telemetry@0b706e1
+ 2024-07-17 420037b16d os: don't try to signal PID -1 on Unix
+ 2024-07-17 87abb4afb6 runtime: avoid multiple records with identical stacks from MutexProfile
+ 2024-07-17 8c88f0c736 cmd/cgo/internal/testcarchive: remove 1-minute timeout
+ 2024-07-17 fc51e5023e math/big: fix comment typo in natdiv.go
+ 2024-07-17 90c6558b6a internal/bytealg: extend memchr result correctly on wasm
+ 2024-07-16 355711821e cmd/internal/cov: close counter data files eagerly
+ 2024-07-16 f2bcab5fb3 regexp: more cross-references in docstrings
+ 2024-07-16 9915b87059 bytes: more cross-references in docstrings
+ 2024-07-16 97ccc224f1 math/big: use lists in docstrings
+ 2024-07-16 66e940b6f8 math/big: more cross-references in docstrings
+ 2024-07-16 0dae393a26 encoding/binary: use list format in docstrings
+ 2024-07-16 451a284d80 strings,bytes,regexp: use lists in Split* docstrings
+ 2024-07-16 b4a92f56ff crypto/tls: add exclude tls flags to bogo_shim_test
+ 2024-07-16 3bfbfa821f encoding/json: document compact json output in Encoder.Encode
+ 2024-07-16 d5479e197d net: document ParseIP always returns IPv6 addresses
+ 2024-07-16 5c7f541386 archive/zip: document handling of duplicate names in Writer.Create
+ 2024-07-16 6b97448132 sort: add example for Find
+ 2024-07-16 8b48290895 cmd/compile: fix recursive generic interface instantiation
+ 2024-07-15 959b3fd426 flag: add FlagSet example

Change-Id: I0e7cac2f1cef42ccf3d392c57dad793ca3b08b11
2024-07-22 14:12:36 -04:00
Gopher Robot
30b6fd60a6 [release-branch.go1.23] go1.23rc2
Change-Id: I73a3f2e680a84aa698c6f64b1e924bb1b9a85a89
Reviewed-on: https://go-review.googlesource.com/c/go/+/598555
TryBot-Bypass: Carlos Amedee <carlos@golang.org>
Reviewed-by: Carlos Amedee <carlos@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Auto-Submit: Carlos Amedee <carlos@golang.org>
Auto-Submit: Gopher Robot <gobot@golang.org>
2024-07-16 15:33:13 +00:00
Cherry Mui
7e4d6c2bcb [release-branch.go1.23] all: merge master (6948b4d) into release-branch.go1.23
Merge List:

+ 2024-07-15 6948b4df8c Revert "runtime: avoid multiple records with identical stacks from MutexProfile"

Change-Id: I94d1f445b0304eb4355ef6e91bf9f8585abfe0f8
2024-07-15 16:40:36 -04:00
Cherry Mui
8bd4ed6cbb [release-branch.go1.23] all: merge master (8f1ec59) into release-branch.go1.23
Merge List:

+ 2024-07-15 8f1ec59bdb strings: re-introduce noescape wrapper
+ 2024-07-15 5d36bc18d5 net/http: document io.Seeker requirement for fs.FS arguments
+ 2024-07-12 071b8d51c1 cmd: vendor golang.org/x/telemetry@268b4a8ec2d7
+ 2024-07-12 4e77872d16 go/types: fix assertion failure when range over int is not permitted
+ 2024-07-12 8bc32ab6b1 os: clean up after TestIssue60181
+ 2024-07-11 b31e9a63a4 unsafe: say "functions like syscall.Syscall", not only Syscall
+ 2024-07-11 a71bb570d0 all: make struct comments match struct names
+ 2024-07-11 611f18c4e9 strings: more cross-references in docstrings
+ 2024-07-11 08a6e080ca database/sql/driver: fix name in comment
+ 2024-07-11 dfaaa91f05 os: clarify that IsNotExist, IsExist, IsPermission and IsTimeout work with nil errors
+ 2024-07-10 5881d857c5 crypto/tls: add support for -expect-no-hrr to bogo_shim_test
+ 2024-07-10 b3040679ad math: remove riscv64 assembly implementations of rounding
+ 2024-07-10 70e453b436 context: handle nil values for valueCtx.String()
+ 2024-07-09 183a40db6d runtime: avoid multiple records with identical stacks from MutexProfile
+ 2024-07-09 e89e880eac crypto/tls: add support for -reject-alpn and -decline-alpn flags to bogo_shim_test
+ 2024-07-09 73186ba002 crypto/internal/cryptotest: add common tests for the hash.Hash interface
+ 2024-07-08 87ec2c959c testing: remove call to os.Exit in documentation for TestMain
+ 2024-07-08 6d89b38ed8 unsafe: clarify when String bytes can be modified
+ 2024-07-07 5565462a86 cmd/dist: remove iter,slices,maps test on GOEXPERIMENT=rangefunc
+ 2024-07-07 b43d6c57de io: add test for Pipe constructor allocations
+ 2024-07-07 d0146bd85b os/exec: only use cachedLookExtensions if Cmd.Path is unmodified
+ 2024-07-05 ad77cefeb2 cmd/compile: correct RewriteMultiValueCall fatal message
+ 2024-07-05 be152920b9 cmd/compile: fix ICE when compiling global a, b = f()
+ 2024-07-03 82c14346d8 cmd/link: don't disable memory profiling when pprof.WriteHeapProfile is used
+ 2024-07-03 7d19d508a9 cmd/cgo: read CGO_LDFLAGS environment variable
+ 2024-07-03 5f50b1e3bf cmd/compile: fix mis-compilation when switching over channels
+ 2024-07-03 71f9dbb1e4 cmd/compile: emit error message on mismatch import path
+ 2024-07-03 148755a27b cmd/link: document -checklinkname option
+ 2024-07-02 f12ac5be70 time: fix time zone parsing when format includes time zone seconds
+ 2024-07-02 09aeb6e33a os: add TODO about removing test exception
+ 2024-07-01 94982a0782 cmd/go/internal/workcmd: remove a potentially confusing statement
+ 2024-07-01 f71c00b616 cmd/link: align .reloc block starts by 32 bits for PE target
+ 2024-07-01 d3c93f2f00 cmd/go: update go clean help message
+ 2024-07-01 cdbf5f2f7e sync: refer to Locker interface methods in RWMutex.RLocker doc
+ 2024-07-01 c33144c47c runtime: fix nil pointer in TestGoroutineParallelism2 when offline
+ 2024-06-28 82c371a307 cmd/compile: drop internal range-over-func vars from DWARF output
+ 2024-06-28 773767def0 net/http: avoid appending an existing trailing slash to path again
+ 2024-06-28 7f90b960a9 cmd/compile: don't elide zero extension on top of signed values
+ 2024-06-27 ea537cca31 cmd/go/internal/help: add documentation for language version downgrading
+ 2024-06-27 b0927fdd49 slices: update docs for All, Backward, Values
+ 2024-06-26 5a18e79687 cmd/link: don't skip code sign even if dsymutil didn't generate a file
+ 2024-06-26 5f319b7507 cmd/link: don't let dsymutil delete our temp directory
+ 2024-06-26 a2e90be996 os: rewrite TestChtimesWithZeroTimes
+ 2024-06-25 90bcc552c0 crypto/tls: apply QUIC session event flag to QUICResumeSession events
+ 2024-06-25 b1fd047508 cmd/internal/obj/arm64: fix return with register
+ 2024-06-25 b3b4556c24 cmd/compile: update README to reflect dead code elimination changes
+ 2024-06-24 68315bc8ce cmd: run go mod tidy after CL 593684
+ 2024-06-24 f214a76075 cmd/vendor: vendor x/telemetry@38a4430
+ 2024-06-24 29b1a6765f net/http: document that Request.Clone does not deep copy Body
+ 2024-06-24 cf54a3d114 crypto/tls: replay test recordings without network
+ 2024-06-24 b98803e8e5 os: TestChtimes: separate hasNoatime
+ 2024-06-24 0def9d5c02 cmd/internal/obj/arm64: Enable arm64 assembler tests for cross-compiler builds
+ 2024-06-24 085cf0fcdc net/netip: add test that Compare and reflect.DeepEqual match
+ 2024-06-24 740043f516 net/netip: unexport fields of addrDetail
+ 2024-06-23 e8ee1dc4f9 cmd/link/internal/ld: handle "\r" in MinGW "--print-prog-name" output
+ 2024-06-22 44f1870666 cmd/link: handle dynamic import variables on Darwin in plugin mode
+ 2024-06-21 0af2148fdc cmd: vendor golang.org/x/telemetry@a740542
+ 2024-06-21 cb3b34349b doc/next: delete
+ 2024-06-21 d79c350916 cmd/internal: separate counter package from telemetry package
+ 2024-06-21 52ce25b44e cmd/vendor: pull in golang.org/x/telemetry@b4de734
+ 2024-06-21 fed2c11d67 iter: minor doc comment updates
+ 2024-06-21 d73a8a206a cmd/cgo: fail on v, err := C.fn when fn is a builtin function
+ 2024-06-21 1b4f1dc95d os: improve newFile, rm newDir
+ 2024-06-21 72e2220b50 encoding/json: clarify the map's key type for Unmarshal
+ 2024-06-21 e9a306e004 types2, go/types: correct NewTypeParam documentation
+ 2024-06-21 6fea409424 text/template/parse: fix handling of assignment/declaration in PipeNode.String
+ 2024-06-21 d67839f58a crypto/tls: add support for -expect-version to bogo_shim_test
+ 2024-06-21 201129414f sync/atomic: correct result names for Or methods
+ 2024-06-21 20b79fd577 time: provide non-default metric for asynctimerchan
+ 2024-06-20 9d33956503 internal/godebugs: fix old value for httpservecontentkeepheaders
+ 2024-06-20 477ad7dd51 cmd/compile: support generic alias type
+ 2024-06-18 4f77a83589 internal/syscall/unix: fix UTIME_OMIT for dragonfly

Change-Id: I3864b03b8c377e8fe82014eee96dc7b77aea64e2
2024-07-15 13:23:34 -04:00
Gopher Robot
7dff7439dc [release-branch.go1.23] go1.23rc1
Change-Id: Ied4bb63f49d13bd7d421cf9cb269220974641b89
Reviewed-on: https://go-review.googlesource.com/c/go/+/593897
Auto-Submit: David Chase <drchase@google.com>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Gopher Robot <gobot@golang.org>
2024-06-21 16:32:19 +00:00
Damien Neil
62c3a6350b [release-branch.go1.23] internal/godebugs: fix old value for httpservecontentkeepheaders
The pre-Go 1.23 behavior is httpservecontentkeepheaders=1.

For #66343

Change-Id: If6f92853b38522f19a8908ff11ac49b12f3dc3e0
Reviewed-on: https://go-review.googlesource.com/c/go/+/593775
Reviewed-by: David Chase <drchase@google.com>
Auto-Submit: Damien Neil <dneil@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/593795
Reviewed-by: Damien Neil <dneil@google.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
2024-06-20 19:14:07 +00:00
Cuong Manh Le
eba9e08766 [release-branch.go1.23] cmd/compile: support generic alias type
Type parameters on aliases are now allowed after #46477 accepted.

Updates #46477
Fixes #68054

Change-Id: Ic2e3b6f960a898163f47666e3a6bfe43b8cc22e2
Reviewed-on: https://go-review.googlesource.com/c/go/+/593715
Reviewed-by: Robert Griesemer <gri@google.com>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Robert Griesemer <gri@google.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/593797
Reviewed-by: Michael Pratt <mpratt@google.com>
2024-06-20 19:13:52 +00:00
Kir Kolyshkin
f3bdcda88a [release-branch.go1.23] internal/syscall/unix: fix UTIME_OMIT for dragonfly
CL 219638 added UTIME_OMIT values for various systems. The value for
DragonFly BSD appears to be incorrect.

The correct value is -2 (see references below), while -1 is used for
UTIME_NOW. As a result, timestamp is changed to the current time instead
of not touching. This should have been caught by the accompanying test
case, TestChtimesWithZeroTimes, but its failures are essentially skipped
on dragonfly (this is being fixed separately in a followup CL 591535).

Improve formatting while at it.

References:
 - https://github.com/DragonFlyBSD/DragonFlyBSD/blob/965b380e9609/sys/sys/stat.h#L284
 - https://go.googlesource.com/sys/+/refs/tags/v0.20.0/unix/zerrors_dragonfly_amd64.go#1421

Change-Id: I432360ca982c84b7cd70d0cf01d860af9ff985fa
Reviewed-on: https://go-review.googlesource.com/c/go/+/589496
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Auto-Submit: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Commit-Queue: Ian Lance Taylor <iant@golang.org>
Reviewed-on: https://go-review.googlesource.com/c/go/+/593796
Reviewed-by: Michael Pratt <mpratt@google.com>
2024-06-20 19:13:34 +00:00
David Chase
362f22d2d2 [release-branch.go1.23] update codereview.cfg for release-branch.go1.23
Change-Id: Ib335bc903e2b8d5b7be6a158a6debe5db48e79a4
Reviewed-on: https://go-review.googlesource.com/c/go/+/593535
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: David Chase <drchase@google.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
2024-06-18 21:25:28 +00:00
3098 changed files with 60120 additions and 232093 deletions

View File

@@ -1,7 +1,7 @@
name: Language Change Proposals
description: Changes to the language
labels: ["Proposal", "LanguageChange", "LanguageChangeReview"]
title: "proposal: spec: proposal title"
labels: ["Proposal", "v2", "LanguageChange"]
title: "proposal: Go 2: proposal title"
body:

2
.gitignore vendored
View File

@@ -37,7 +37,7 @@ _testmain.go
/src/go/build/zcgo.go
/src/go/doc/headscan
/src/internal/buildcfg/zbootstrap.go
/src/internal/runtime/sys/zversion.go
/src/runtime/internal/sys/zversion.go
/src/unicode/maketables
/src/time/tzdata/zzipdata.go
/test.out

View File

@@ -1,4 +1,4 @@
Copyright 2009 The Go Authors.
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
@@ -10,7 +10,7 @@ notice, this list of conditions and the following disclaimer.
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google LLC nor the names of its
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

2
VERSION Normal file
View File

@@ -0,0 +1,2 @@
go1.23.10
time 2025-05-29T19:37:36Z

View File

@@ -1,230 +0,0 @@
pkg bytes, func FieldsFuncSeq([]uint8, func(int32) bool) iter.Seq[[]uint8] #61901
pkg bytes, func FieldsSeq([]uint8) iter.Seq[[]uint8] #61901
pkg bytes, func Lines([]uint8) iter.Seq[[]uint8] #61901
pkg bytes, func SplitAfterSeq([]uint8, []uint8) iter.Seq[[]uint8] #61901
pkg bytes, func SplitSeq([]uint8, []uint8) iter.Seq[[]uint8] #61901
pkg crypto/cipher, func NewCFBDecrypter //deprecated #69445
pkg crypto/cipher, func NewCFBEncrypter //deprecated #69445
pkg crypto/cipher, func NewGCMWithRandomNonce(Block) (AEAD, error) #69981
pkg crypto/cipher, func NewOFB //deprecated #69445
pkg crypto/fips140, func Enabled() bool #70123
pkg crypto/hkdf, func Expand[$0 hash.Hash](func() $0, []uint8, string, int) ([]uint8, error) #61477
pkg crypto/hkdf, func Extract[$0 hash.Hash](func() $0, []uint8, []uint8) ([]uint8, error) #61477
pkg crypto/hkdf, func Key[$0 hash.Hash](func() $0, []uint8, []uint8, string, int) ([]uint8, error) #61477
pkg crypto/mlkem, const CiphertextSize1024 = 1568 #70122
pkg crypto/mlkem, const CiphertextSize1024 ideal-int #70122
pkg crypto/mlkem, const CiphertextSize768 = 1088 #70122
pkg crypto/mlkem, const CiphertextSize768 ideal-int #70122
pkg crypto/mlkem, const EncapsulationKeySize1024 = 1568 #70122
pkg crypto/mlkem, const EncapsulationKeySize1024 ideal-int #70122
pkg crypto/mlkem, const EncapsulationKeySize768 = 1184 #70122
pkg crypto/mlkem, const EncapsulationKeySize768 ideal-int #70122
pkg crypto/mlkem, const SeedSize = 64 #70122
pkg crypto/mlkem, const SeedSize ideal-int #70122
pkg crypto/mlkem, const SharedKeySize = 32 #70122
pkg crypto/mlkem, const SharedKeySize ideal-int #70122
pkg crypto/mlkem, func GenerateKey1024() (*DecapsulationKey1024, error) #70122
pkg crypto/mlkem, func GenerateKey768() (*DecapsulationKey768, error) #70122
pkg crypto/mlkem, func NewDecapsulationKey1024([]uint8) (*DecapsulationKey1024, error) #70122
pkg crypto/mlkem, func NewDecapsulationKey768([]uint8) (*DecapsulationKey768, error) #70122
pkg crypto/mlkem, func NewEncapsulationKey1024([]uint8) (*EncapsulationKey1024, error) #70122
pkg crypto/mlkem, func NewEncapsulationKey768([]uint8) (*EncapsulationKey768, error) #70122
pkg crypto/mlkem, method (*DecapsulationKey1024) Bytes() []uint8 #70122
pkg crypto/mlkem, method (*DecapsulationKey1024) Decapsulate([]uint8) ([]uint8, error) #70122
pkg crypto/mlkem, method (*DecapsulationKey1024) EncapsulationKey() *EncapsulationKey1024 #70122
pkg crypto/mlkem, method (*DecapsulationKey768) Bytes() []uint8 #70122
pkg crypto/mlkem, method (*DecapsulationKey768) Decapsulate([]uint8) ([]uint8, error) #70122
pkg crypto/mlkem, method (*DecapsulationKey768) EncapsulationKey() *EncapsulationKey768 #70122
pkg crypto/mlkem, method (*EncapsulationKey1024) Bytes() []uint8 #70122
pkg crypto/mlkem, method (*EncapsulationKey1024) Encapsulate() ([]uint8, []uint8) #70122
pkg crypto/mlkem, method (*EncapsulationKey768) Bytes() []uint8 #70122
pkg crypto/mlkem, method (*EncapsulationKey768) Encapsulate() ([]uint8, []uint8) #70122
pkg crypto/mlkem, type DecapsulationKey1024 struct #70122
pkg crypto/mlkem, type DecapsulationKey768 struct #70122
pkg crypto/mlkem, type EncapsulationKey1024 struct #70122
pkg crypto/mlkem, type EncapsulationKey768 struct #70122
pkg crypto/pbkdf2, func Key[$0 hash.Hash](func() $0, string, []uint8, int, int) ([]uint8, error) #69488
pkg crypto/rand, func Text() string #67057
pkg crypto/sha3, func New224() *SHA3 #69982
pkg crypto/sha3, func New256() *SHA3 #69982
pkg crypto/sha3, func New384() *SHA3 #69982
pkg crypto/sha3, func New512() *SHA3 #69982
pkg crypto/sha3, func NewCSHAKE128([]uint8, []uint8) *SHAKE #69982
pkg crypto/sha3, func NewCSHAKE256([]uint8, []uint8) *SHAKE #69982
pkg crypto/sha3, func NewSHAKE128() *SHAKE #69982
pkg crypto/sha3, func NewSHAKE256() *SHAKE #69982
pkg crypto/sha3, func Sum224([]uint8) [28]uint8 #69982
pkg crypto/sha3, func Sum256([]uint8) [32]uint8 #69982
pkg crypto/sha3, func Sum384([]uint8) [48]uint8 #69982
pkg crypto/sha3, func Sum512([]uint8) [64]uint8 #69982
pkg crypto/sha3, func SumSHAKE128([]uint8, int) []uint8 #69982
pkg crypto/sha3, func SumSHAKE256([]uint8, int) []uint8 #69982
pkg crypto/sha3, method (*SHA3) AppendBinary([]uint8) ([]uint8, error) #69982
pkg crypto/sha3, method (*SHA3) BlockSize() int #69982
pkg crypto/sha3, method (*SHA3) MarshalBinary() ([]uint8, error) #69982
pkg crypto/sha3, method (*SHA3) Reset() #69982
pkg crypto/sha3, method (*SHA3) Size() int #69982
pkg crypto/sha3, method (*SHA3) Sum([]uint8) []uint8 #69982
pkg crypto/sha3, method (*SHA3) UnmarshalBinary([]uint8) error #69982
pkg crypto/sha3, method (*SHA3) Write([]uint8) (int, error) #69982
pkg crypto/sha3, method (*SHAKE) AppendBinary([]uint8) ([]uint8, error) #69982
pkg crypto/sha3, method (*SHAKE) BlockSize() int #69982
pkg crypto/sha3, method (*SHAKE) MarshalBinary() ([]uint8, error) #69982
pkg crypto/sha3, method (*SHAKE) Read([]uint8) (int, error) #69982
pkg crypto/sha3, method (*SHAKE) Reset() #69982
pkg crypto/sha3, method (*SHAKE) UnmarshalBinary([]uint8) error #69982
pkg crypto/sha3, method (*SHAKE) Write([]uint8) (int, error) #69982
pkg crypto/sha3, type SHA3 struct #69982
pkg crypto/sha3, type SHAKE struct #69982
pkg crypto/subtle, func WithDataIndependentTiming(func()) #66450
pkg crypto/tls, const X25519MLKEM768 = 4588 #69985
pkg crypto/tls, const X25519MLKEM768 CurveID #69985
pkg crypto/tls, type ClientHelloInfo struct, Extensions []uint16 #32936
pkg crypto/tls, type Config struct, EncryptedClientHelloKeys []EncryptedClientHelloKey #68500
pkg crypto/tls, type EncryptedClientHelloKey struct #68500
pkg crypto/tls, type EncryptedClientHelloKey struct, Config []uint8 #68500
pkg crypto/tls, type EncryptedClientHelloKey struct, PrivateKey []uint8 #68500
pkg crypto/tls, type EncryptedClientHelloKey struct, SendAsRetry bool #68500
pkg crypto/x509, const NoValidChains = 10 #68484
pkg crypto/x509, const NoValidChains InvalidReason #68484
pkg crypto/x509, method (OID) AppendBinary([]uint8) ([]uint8, error) #62384
pkg crypto/x509, method (OID) AppendText([]uint8) ([]uint8, error) #62384
pkg crypto/x509, type Certificate struct, InhibitAnyPolicy int #68484
pkg crypto/x509, type Certificate struct, InhibitAnyPolicyZero bool #68484
pkg crypto/x509, type Certificate struct, InhibitPolicyMapping int #68484
pkg crypto/x509, type Certificate struct, InhibitPolicyMappingZero bool #68484
pkg crypto/x509, type Certificate struct, PolicyMappings []PolicyMapping #68484
pkg crypto/x509, type Certificate struct, RequireExplicitPolicy int #68484
pkg crypto/x509, type Certificate struct, RequireExplicitPolicyZero bool #68484
pkg crypto/x509, type PolicyMapping struct #68484
pkg crypto/x509, type PolicyMapping struct, IssuerDomainPolicy OID #68484
pkg crypto/x509, type PolicyMapping struct, SubjectDomainPolicy OID #68484
pkg crypto/x509, type VerifyOptions struct, CertificatePolicies []OID #68484
pkg debug/elf, const VER_FLG_BASE = 1 #63952
pkg debug/elf, const VER_FLG_BASE DynamicVersionFlag #63952
pkg debug/elf, const VER_FLG_INFO = 4 #63952
pkg debug/elf, const VER_FLG_INFO DynamicVersionFlag #63952
pkg debug/elf, const VER_FLG_WEAK = 2 #63952
pkg debug/elf, const VER_FLG_WEAK DynamicVersionFlag #63952
pkg debug/elf, const VerFlagGlobal = 2 #63952
pkg debug/elf, const VerFlagGlobal SymbolVersionFlag #63952
pkg debug/elf, const VerFlagHidden = 4 #63952
pkg debug/elf, const VerFlagHidden SymbolVersionFlag #63952
pkg debug/elf, const VerFlagLocal = 1 #63952
pkg debug/elf, const VerFlagLocal SymbolVersionFlag #63952
pkg debug/elf, const VerFlagNone = 0 #63952
pkg debug/elf, const VerFlagNone SymbolVersionFlag #63952
pkg debug/elf, method (*File) DynamicVersionNeeds() ([]DynamicVersionNeed, error) #63952
pkg debug/elf, method (*File) DynamicVersions() ([]DynamicVersion, error) #63952
pkg debug/elf, type DynamicVersion struct #63952
pkg debug/elf, type DynamicVersion struct, Deps []string #63952
pkg debug/elf, type DynamicVersion struct, Flags DynamicVersionFlag #63952
pkg debug/elf, type DynamicVersion struct, Index uint16 #63952
pkg debug/elf, type DynamicVersion struct, Version uint16 #63952
pkg debug/elf, type DynamicVersionDep struct #63952
pkg debug/elf, type DynamicVersionDep struct, Dep string #63952
pkg debug/elf, type DynamicVersionDep struct, Flags DynamicVersionFlag #63952
pkg debug/elf, type DynamicVersionDep struct, Other uint16 #63952
pkg debug/elf, type DynamicVersionFlag uint16 #63952
pkg debug/elf, type DynamicVersionNeed struct #63952
pkg debug/elf, type DynamicVersionNeed struct, Name string #63952
pkg debug/elf, type DynamicVersionNeed struct, Needs []DynamicVersionDep #63952
pkg debug/elf, type DynamicVersionNeed struct, Version uint16 #63952
pkg debug/elf, type Symbol struct, VersionFlags SymbolVersionFlag #63952
pkg debug/elf, type Symbol struct, VersionIndex int16 #63952
pkg debug/elf, type SymbolVersionFlag uint8 #63952
pkg encoding, type BinaryAppender interface { AppendBinary } #62384
pkg encoding, type BinaryAppender interface, AppendBinary([]uint8) ([]uint8, error) #62384
pkg encoding, type TextAppender interface { AppendText } #62384
pkg encoding, type TextAppender interface, AppendText([]uint8) ([]uint8, error) #62384
pkg go/types, method (*Interface) EmbeddedTypes() iter.Seq[Type] #66626
pkg go/types, method (*Interface) ExplicitMethods() iter.Seq[*Func] #66626
pkg go/types, method (*Interface) Methods() iter.Seq[*Func] #66626
pkg go/types, method (*MethodSet) Methods() iter.Seq[*Selection] #66626
pkg go/types, method (*Named) Methods() iter.Seq[*Func] #66626
pkg go/types, method (*Scope) Children() iter.Seq[*Scope] #66626
pkg go/types, method (*Struct) Fields() iter.Seq[*Var] #66626
pkg go/types, method (*Tuple) Variables() iter.Seq[*Var] #66626
pkg go/types, method (*TypeList) Types() iter.Seq[Type] #66626
pkg go/types, method (*TypeParamList) TypeParams() iter.Seq[*TypeParam] #66626
pkg go/types, method (*Union) Terms() iter.Seq[*Term] #66626
pkg hash/maphash, func Comparable[$0 comparable](Seed, $0) uint64 #54670
pkg hash/maphash, func WriteComparable[$0 comparable](*Hash, $0) #54670
pkg log/slog, method (*LevelVar) AppendText([]uint8) ([]uint8, error) #62384
pkg log/slog, method (Level) AppendText([]uint8) ([]uint8, error) #62384
pkg log/slog, var DiscardHandler Handler #62005
pkg math/big, method (*Float) AppendText([]uint8) ([]uint8, error) #62384
pkg math/big, method (*Int) AppendText([]uint8) ([]uint8, error) #62384
pkg math/big, method (*Rat) AppendText([]uint8) ([]uint8, error) #62384
pkg math/rand/v2, method (*ChaCha8) AppendBinary([]uint8) ([]uint8, error) #62384
pkg math/rand/v2, method (*PCG) AppendBinary([]uint8) ([]uint8, error) #62384
pkg net, method (IP) AppendText([]uint8) ([]uint8, error) #62384
pkg net/http, method (*Protocols) SetHTTP1(bool) #67814
pkg net/http, method (*Protocols) SetHTTP2(bool) #67814
pkg net/http, method (*Protocols) SetUnencryptedHTTP2(bool) #67816
pkg net/http, method (Protocols) HTTP1() bool #67814
pkg net/http, method (Protocols) HTTP2() bool #67814
pkg net/http, method (Protocols) String() string #67814
pkg net/http, method (Protocols) UnencryptedHTTP2() bool #67816
pkg net/http, type HTTP2Config struct #67813
pkg net/http, type HTTP2Config struct, CountError func(string) #67813
pkg net/http, type HTTP2Config struct, MaxConcurrentStreams int #67813
pkg net/http, type HTTP2Config struct, MaxDecoderHeaderTableSize int #67813
pkg net/http, type HTTP2Config struct, MaxEncoderHeaderTableSize int #67813
pkg net/http, type HTTP2Config struct, MaxReadFrameSize int #67813
pkg net/http, type HTTP2Config struct, MaxReceiveBufferPerConnection int #67813
pkg net/http, type HTTP2Config struct, MaxReceiveBufferPerStream int #67813
pkg net/http, type HTTP2Config struct, PermitProhibitedCipherSuites bool #67813
pkg net/http, type HTTP2Config struct, PingTimeout time.Duration #67813
pkg net/http, type HTTP2Config struct, SendPingTimeout time.Duration #67813
pkg net/http, type HTTP2Config struct, WriteByteTimeout time.Duration #67813
pkg net/http, type Protocols struct #67814
pkg net/http, type Server struct, HTTP2 *HTTP2Config #67813
pkg net/http, type Server struct, Protocols *Protocols #67814
pkg net/http, type Transport struct, HTTP2 *HTTP2Config #67813
pkg net/http, type Transport struct, Protocols *Protocols #67814
pkg net/netip, method (Addr) AppendBinary([]uint8) ([]uint8, error) #62384
pkg net/netip, method (Addr) AppendText([]uint8) ([]uint8, error) #62384
pkg net/netip, method (AddrPort) AppendBinary([]uint8) ([]uint8, error) #62384
pkg net/netip, method (AddrPort) AppendText([]uint8) ([]uint8, error) #62384
pkg net/netip, method (Prefix) AppendBinary([]uint8) ([]uint8, error) #62384
pkg net/netip, method (Prefix) AppendText([]uint8) ([]uint8, error) #62384
pkg net/url, method (*URL) AppendBinary([]uint8) ([]uint8, error) #62384
pkg os, func OpenInRoot(string, string) (*File, error) #67002
pkg os, func OpenRoot(string) (*Root, error) #67002
pkg os, method (*Root) Close() error #67002
pkg os, method (*Root) Create(string) (*File, error) #67002
pkg os, method (*Root) FS() fs.FS #67002
pkg os, method (*Root) Lstat(string) (fs.FileInfo, error) #67002
pkg os, method (*Root) Mkdir(string, fs.FileMode) error #67002
pkg os, method (*Root) Name() string #67002
pkg os, method (*Root) Open(string) (*File, error) #67002
pkg os, method (*Root) OpenFile(string, int, fs.FileMode) (*File, error) #67002
pkg os, method (*Root) OpenRoot(string) (*Root, error) #67002
pkg os, method (*Root) Remove(string) error #67002
pkg os, method (*Root) Stat(string) (fs.FileInfo, error) #67002
pkg os, type Root struct #67002
pkg regexp, method (*Regexp) AppendText([]uint8) ([]uint8, error) #62384
pkg runtime, func AddCleanup[$0 interface{}, $1 interface{}](*$0, func($1), $1) Cleanup #67535
pkg runtime, func GOROOT //deprecated #51473
pkg runtime, method (Cleanup) Stop() #67535
pkg runtime, type Cleanup struct #67535
pkg strings, func FieldsFuncSeq(string, func(int32) bool) iter.Seq[string] #61901
pkg strings, func FieldsSeq(string) iter.Seq[string] #61901
pkg strings, func Lines(string) iter.Seq[string] #61901
pkg strings, func SplitAfterSeq(string, string) iter.Seq[string] #61901
pkg strings, func SplitSeq(string, string) iter.Seq[string] #61901
pkg testing, method (*B) Chdir(string) #62516
pkg testing, method (*B) Context() context.Context #36532
pkg testing, method (*B) Loop() bool #61515
pkg testing, method (*F) Chdir(string) #62516
pkg testing, method (*F) Context() context.Context #36532
pkg testing, method (*T) Chdir(string) #62516
pkg testing, method (*T) Context() context.Context #36532
pkg testing, type TB interface, Chdir(string) #62516
pkg testing, type TB interface, Context() context.Context #36532
pkg time, method (Time) AppendBinary([]uint8) ([]uint8, error) #62384
pkg time, method (Time) AppendText([]uint8) ([]uint8, error) #62384
pkg weak, func Make[$0 interface{}](*$0) Pointer[$0] #67552
pkg weak, method (Pointer[$0]) Value() *$0 #67552
pkg weak, type Pointer[$0 interface{}] struct #67552

View File

@@ -1 +1,2 @@
branch: master
branch: release-branch.go1.23
parent-branch: master

View File

@@ -70,6 +70,6 @@ To begin the next release development cycle, populate the contents of `next`
with those of `initial`. From the repo root:
> cd doc
> cp -R initial/ next
> cp -r initial/* next
Then edit `next/1-intro.md` to refer to the next version.

View File

@@ -1,6 +1,6 @@
<!--{
"Title": "The Go Programming Language Specification",
"Subtitle": "Language version go1.17 (Oct 15, 2021)",
"Subtitle": "Version of Oct 15, 2021",
"Path": "/ref/spec"
}-->

View File

@@ -82,7 +82,7 @@ while still insisting that races are errors and that tools can diagnose and repo
<p>
The following formal definition of Go's memory model closely follows
the approach presented by Hans-J. Boehm and Sarita V. Adve in
<a href="https://dl.acm.org/doi/10.1145/1375581.1375591">Foundations of the C++ Concurrency Memory Model</a>”,
<a href="https://www.hpl.hp.com/techreports/2008/HPL-2008-56.pdf">Foundations of the C++ Concurrency Memory Model</a>”,
published in PLDI 2008.
The definition of data-race-free programs and the guarantee of sequential consistency
for race-free programs are equivalent to the ones in that work.

View File

@@ -1,6 +1,6 @@
<!--{
"Title": "The Go Programming Language Specification",
"Subtitle": "Language version go1.24 (Nov 20, 2024)",
"Subtitle": "Language version go1.23 (June 13, 2024)",
"Path": "/ref/spec"
}-->
@@ -1086,7 +1086,7 @@ A field declared with a type but no explicit field name is called an <i>embedded
An embedded field must be specified as
a type name <code>T</code> or as a pointer to a non-interface type name <code>*T</code>,
and <code>T</code> itself may not be
a pointer type or type parameter. The unqualified type name acts as the field name.
a pointer type. The unqualified type name acts as the field name.
</p>
<pre>
@@ -1127,7 +1127,7 @@ of a struct except that they cannot be used as field names in
</p>
<p>
Given a struct type <code>S</code> and a type name
Given a struct type <code>S</code> and a <a href="#Types">named type</a>
<code>T</code>, promoted methods are included in the method set of the struct as follows:
</p>
<ul>
@@ -1927,8 +1927,8 @@ components have identical types. In detail:
<li>Two slice types are identical if they have identical element types.</li>
<li>Two struct types are identical if they have the same sequence of fields,
and if corresponding pairs of fields have the same names, identical types,
and identical tags, and are either both embedded or both not embedded.
and if corresponding fields have the same names, and identical types,
and identical tags.
<a href="#Exported_identifiers">Non-exported</a> field names from different
packages are always different.</li>
@@ -2511,12 +2511,12 @@ An alias declaration binds an identifier to the given type
</p>
<pre class="ebnf">
AliasDecl = identifier [ TypeParameters ] "=" Type .
AliasDecl = identifier "=" Type .
</pre>
<p>
Within the <a href="#Declarations_and_scope">scope</a> of
the identifier, it serves as an <i>alias</i> for the given type.
the identifier, it serves as an <i>alias</i> for the type.
</p>
<pre>
@@ -2526,24 +2526,6 @@ type (
)
</pre>
<p>
If the alias declaration specifies <a href="#Type_parameter_declarations">type parameters</a>
[<a href="#Go_1.24">Go 1.24</a>], the type name denotes a <i>generic alias</i>.
Generic aliases must be <a href="#Instantiations">instantiated</a> when they
are used.
</p>
<pre>
type set[P comparable] = map[P]bool
</pre>
<p>
In an alias declaration the given type cannot be a type parameter.
</p>
<pre>
type A[P any] = P // illegal: P is a type parameter
</pre>
<h4 id="Type_definitions">Type definitions</h4>
@@ -3093,7 +3075,7 @@ to the base type <code>Point</code>.
</p>
<p>
If the receiver base type is a <a href="#Type_definitions">generic type</a>, the
If the receiver base type is a <a href="#Type_declarations">generic type</a>, the
receiver specification must declare corresponding type parameters for the method
to use. This makes the receiver type parameters available to the method.
Syntactically, this type parameter declaration looks like an
@@ -3117,22 +3099,6 @@ func (p Pair[A, B]) Swap() Pair[B, A] { … } // receiver declares A, B
func (p Pair[First, _]) First() First { … } // receiver declares First, corresponds to A in Pair
</pre>
<p>
If the receiver type is denoted by (a pointer to) an <a href="#Alias_declarations">alias</a>,
the alias must not be generic and it must not denote an instantiated generic type, neither
directly nor indirectly via another alias, and irrespective of pointer indirections.
</p>
<pre>
type GPoint[P any] = Point
type HPoint = *GPoint[int]
type IPair = Pair[int, int]
func (*GPoint[P]) Draw(P) { … } // illegal: alias must not be generic
func (HPoint) Draw(P) { … } // illegal: alias must not denote instantiated type GPoint[int]
func (*IPair) Second() int { … } // illegal: alias must not denote instantiated type Pair[int, int]
</pre>
<h2 id="Expressions">Expressions</h2>
<p>
@@ -8721,15 +8687,6 @@ integer values from zero to an upper limit.
function as range expression.
</li>
</ul>
<h4 id="Go_1.24">Go 1.24</h4>
<ul>
<li>
An <a href="#Alias_declarations">alias declaration</a> may declare
<a href="#Type_parameter_declarations">type parameters</a>.
</li>
</ul>
<h3 id="Type_unification_rules">Type unification rules</h3>
<p>

View File

@@ -34,7 +34,6 @@ For example, if a Go program is running in an environment that contains
then that Go program will disable the use of HTTP/2 by default in both
the HTTP client and the HTTP server.
Unrecognized settings in the `GODEBUG` environment variable are ignored.
It is also possible to set the default `GODEBUG` for a given program
(discussed below).
@@ -151,68 +150,6 @@ for example,
see the [runtime documentation](/pkg/runtime#hdr-Environment_Variables)
and the [go command documentation](/cmd/go#hdr-Build_and_test_caching).
### Go 1.24
Go 1.24 changed the global [`math/rand.Seed`](/pkg/math/rand/#Seed) to be a
no-op. This behavior is controlled by the `randseednop` setting.
For Go 1.24 it defaults to `randseednop=1`.
Using `randseednop=0` reverts to the pre-Go 1.24 behavior.
Go 1.24 added new values for the `multipathtcp` setting.
The possible values for `multipathtcp` are now:
- "0": disable MPTCP on dialers and listeners by default
- "1": enable MPTCP on dialers and listeners by default
- "2": enable MPTCP on listeners only by default
- "3": enable MPTCP on dialers only by default
For Go 1.24, it now defaults to multipathtcp="2", thus
enabled by default on listeners. Using multipathtcp="0" reverts to the
pre-Go 1.24 behavior.
Go 1.24 changed the behavior of `go test -json` to emit build errors as JSON
instead of text.
These new JSON events are distinguished by new `Action` values,
but can still cause problems with CI systems that aren't robust to these events.
This behavior can be controlled with the `gotestjsonbuildtext` setting.
Using `gotestjsonbuildtext=1` restores the 1.23 behavior.
This setting will be removed in a future release, Go 1.28 at the earliest.
Go 1.24 changed [`crypto/rsa`](/pkg/crypto/rsa) to require RSA keys to be at
least 1024 bits. This behavior can be controlled with the `rsa1024min` setting.
Using `rsa1024min=0` restores the Go 1.23 behavior.
Go 1.24 introduced a mechanism for enabling platform specific Data Independent
Timing (DIT) modes in the [`crypto/subtle`](/pkg/crypto/subtle) package. This
mode can be enabled for an entire program with the `dataindependenttiming` setting.
For Go 1.24 it defaults to `dataindependenttiming=0`. There is no change in default
behavior from Go 1.23 when `dataindependenttiming` is unset.
Using `dataindependenttiming=1` enables the DIT mode for the entire Go program.
When enabled, DIT will be enabled when calling into C from Go. When enabled,
calling into Go code from C will enable DIT, and disable it before returning to
C if it was not enabled when Go code was entered.
This currently only affects arm64 programs. For all other platforms it is a no-op.
Go 1.24 removed the `x509sha1` setting. `crypto/x509` no longer supports verifying
signatures on certificates that use SHA-1 based signature algorithms.
Go 1.24 changes the default value of the [`x509usepolicies`
setting.](/pkg/crypto/x509/#CreateCertificate) from `0` to `1`. When marshalling
certificates, policies are now taken from the
[`Certificate.Policies`](/pkg/crypto/x509/#Certificate.Policies) field rather
than the
[`Certificate.PolicyIdentifiers`](/pkg/crypto/x509/#Certificate.PolicyIdentifiers)
field by default.
Go 1.24 enabled the post-quantum key exchange mechanism
X25519MLKEM768 by default. The default can be reverted using the
[`tlsmlkem` setting](/pkg/crypto/tls/#Config.CurvePreferences).
Go 1.24 also removed X25519Kyber768Draft00 and the Go 1.23 `tlskyber` setting.
Go 1.24 made [`ParsePKCS1PrivateKey`](/pkg/crypto/x509/#ParsePKCS1PrivateKey)
use and validate the CRT parameters in the encoded private key. This behavior
can be controlled with the `x509rsacrt` setting. Using `x509rsacrt=0` restores
the Go 1.23 behavior.
### Go 1.23
Go 1.23 changed the channels created by package time to be unbuffered
@@ -405,7 +342,7 @@ There is no plan to remove this setting.
Go 1.18 removed support for SHA1 in most X.509 certificates,
controlled by the [`x509sha1` setting](/pkg/crypto/x509#InsecureAlgorithmError).
This setting was removed in Go 1.24.
This setting will be removed in a future release, Go 1.22 at the earliest.
### Go 1.10

View File

@@ -1,46 +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.
# Rules for building and testing new FIPS snapshots.
# For example:
#
# make v1.2.3.zip
# make v1.2.3.test
#
# and then if changes are needed, check them into master
# and run 'make v1.2.3.rm' and repeat.
#
# Note that once published a snapshot zip file should never
# be modified. We record the sha256 hashes of the zip files
# in fips140.sum, and the cmd/go/internal/fips140 test checks
# that the zips match.
#
# When the zip file is finalized, run 'make updatesum' to update
# fips140.sum.
default:
@echo nothing to make
# make v1.2.3.zip builds a v1.2.3.zip file
# from the current origin/master.
# copy and edit the 'go run' command by hand to use a different branch.
v%.zip:
git fetch origin master
go run ../../src/cmd/go/internal/fips140/mkzip.go -b master v$*
# normally mkzip refuses to overwrite an existing zip file.
# make v1.2.3.rm removes the zip file and and unpacked
# copy from the module cache.
v%.rm:
rm -f v$*.zip
chmod -R u+w $$(go env GOMODCACHE)/golang.org/fips140@v$* 2>/dev/null || true
rm -rf $$(go env GOMODCACHE)/golang.org/fips140@v$*
# make v1.2.3.test runs the crypto tests using that snapshot.
v%.test:
GOFIPS140=v$* go test -short crypto...
# make updatesum updates the fips140.sum file.
updatesum:
go test cmd/go/internal/fips140 -update

View File

@@ -1,9 +0,0 @@
This directory holds snapshots of the crypto/internal/fips140 tree
that are being validated and certified for FIPS-140 use.
The file x.txt (for example, inprocess.txt, certified.txt)
defines the meaning of the FIPS version alias x, listing
the exact version to use.
The zip files are created by cmd/go/internal/fips140/mkzip.go.
The fips140.sum file lists checksums for the zip files.
See the Makefile for recipes.

View File

@@ -1,11 +0,0 @@
# SHA256 checksums of snapshot zip files in this directory.
# These checksums are included in the FIPS security policy
# (validation instructions sent to the lab) and MUST NOT CHANGE.
# That is, the zip files themselves must not change.
#
# It is okay to add new zip files to the list, and it is okay to
# remove zip files from the list when they are removed from
# this directory. To update this file:
#
# go test cmd/go/internal/fips140 -update
#

View File

@@ -24,8 +24,8 @@
# in the CL match the update.bash in the CL.
# Versions to use.
CODE=2024b
DATA=2024b
CODE=2024a
DATA=2024a
set -e

Binary file not shown.

View File

@@ -17,7 +17,7 @@ license that can be found in the LICENSE file.
<script src="https://cdn.jsdelivr.net/npm/text-encoding@0.7.0/lib/encoding.min.js"></script>
(see https://caniuse.com/#feat=textencoder)
-->
<script src="../../lib/wasm/wasm_exec.js"></script>
<script src="wasm_exec.js"></script>
<script>
if (!WebAssembly.instantiateStreaming) { // polyfill
WebAssembly.instantiateStreaming = async (resp, importObject) => {

View File

@@ -14,7 +14,7 @@
if (!globalThis.fs) {
let outputBuf = "";
globalThis.fs = {
constants: { O_WRONLY: -1, O_RDWR: -1, O_CREAT: -1, O_TRUNC: -1, O_APPEND: -1, O_EXCL: -1, O_DIRECTORY: -1 }, // unused
constants: { O_WRONLY: -1, O_RDWR: -1, O_CREAT: -1, O_TRUNC: -1, O_APPEND: -1, O_EXCL: -1 }, // unused
writeSync(fd, buf) {
outputBuf += decoder.decode(buf);
const nl = outputBuf.lastIndexOf("\n");
@@ -73,14 +73,6 @@
}
}
if (!globalThis.path) {
globalThis.path = {
resolve(...pathSegments) {
return pathSegments.join("/");
}
}
}
if (!globalThis.crypto) {
throw new Error("globalThis.crypto is not available, polyfill required (crypto.getRandomValues only)");
}
@@ -216,16 +208,10 @@
return decoder.decode(new DataView(this._inst.exports.mem.buffer, saddr, len));
}
const testCallExport = (a, b) => {
this._inst.exports.testExport0();
return this._inst.exports.testExport(a, b);
}
const timeOrigin = Date.now() - performance.now();
this.importObject = {
_gotest: {
add: (a, b) => a + b,
callExport: testCallExport,
},
gojs: {
// Go's SP does not change as long as no Go code is running. Some operations (e.g. calls, getters and setters)

View File

@@ -11,7 +11,6 @@ if (process.argv.length < 3) {
globalThis.require = require;
globalThis.fs = require("fs");
globalThis.path = require("path");
globalThis.TextEncoder = require("util").TextEncoder;
globalThis.TextDecoder = require("util").TextDecoder;

View File

@@ -33,10 +33,6 @@ Before updating vendor directories, ensure that module mode is enabled.
Make sure that GO111MODULE is not set in the environment, or that it is
set to 'on' or 'auto', and if you use a go.work file, set GOWORK=off.
Also, ensure that 'go env GOROOT' shows the root of this Go source
tree. Otherwise, the results are undefined. It's recommended to build
Go from source and use that 'go' binary to update its source tree.
Requirements may be added, updated, and removed with 'go get'.
The vendor directory may be updated with 'go mod vendor'.
A typical sequence might be:

View File

@@ -15,7 +15,6 @@ import (
"fmt"
"internal/godebug"
"io/fs"
"maps"
"math"
"path"
"reflect"
@@ -697,14 +696,24 @@ func FileInfoHeader(fi fs.FileInfo, link string) (*Header, error) {
h.Gname = sys.Gname
h.AccessTime = sys.AccessTime
h.ChangeTime = sys.ChangeTime
h.Xattrs = maps.Clone(sys.Xattrs)
if sys.Xattrs != nil {
h.Xattrs = make(map[string]string)
for k, v := range sys.Xattrs {
h.Xattrs[k] = v
}
}
if sys.Typeflag == TypeLink {
// hard link
h.Typeflag = TypeLink
h.Size = 0
h.Linkname = sys.Linkname
}
h.PAXRecords = maps.Clone(sys.PAXRecords)
if sys.PAXRecords != nil {
h.PAXRecords = make(map[string]string)
for k, v := range sys.PAXRecords {
h.PAXRecords[k] = v
}
}
}
var doNameLookups = true
if iface, ok := fi.(FileInfoNames); ok {

View File

@@ -7,16 +7,14 @@ package tar
import (
"bytes"
"compress/bzip2"
"crypto/md5"
"errors"
"fmt"
"hash/crc32"
"io"
"maps"
"math"
"os"
"path"
"reflect"
"slices"
"strconv"
"strings"
"testing"
@@ -27,7 +25,7 @@ func TestReader(t *testing.T) {
vectors := []struct {
file string // Test input file
headers []*Header // Expected output headers
chksums []string // CRC32 checksum of files, leave as nil if not checked
chksums []string // MD5 checksum of files, leave as nil if not checked
err error // Expected error to occur
}{{
file: "testdata/gnu.tar",
@@ -55,8 +53,8 @@ func TestReader(t *testing.T) {
Format: FormatGNU,
}},
chksums: []string{
"6cbd88fc",
"ddac04b3",
"e38b27eaccb4391bdec553a7f3ae6b2f",
"c65bd2e50a56a2138bf1716f2fd56fe9",
},
}, {
file: "testdata/sparse-formats.tar",
@@ -149,11 +147,11 @@ func TestReader(t *testing.T) {
Format: FormatGNU,
}},
chksums: []string{
"5375e1d2",
"5375e1d2",
"5375e1d2",
"5375e1d2",
"8eb179ba",
"6f53234398c2449fe67c1812d993012f",
"6f53234398c2449fe67c1812d993012f",
"6f53234398c2449fe67c1812d993012f",
"6f53234398c2449fe67c1812d993012f",
"b0061974914468de549a2af8ced10316",
},
}, {
file: "testdata/star.tar",
@@ -270,7 +268,7 @@ func TestReader(t *testing.T) {
Format: FormatPAX,
}},
chksums: []string{
"5fd7e86a",
"0afb597b283fe61b5d4879669a350556",
},
}, {
file: "testdata/pax-records.tar",
@@ -657,7 +655,7 @@ func TestReader(t *testing.T) {
if v.chksums == nil {
continue
}
h := crc32.NewIEEE()
h := md5.New()
_, err = io.CopyBuffer(h, tr, rdbuf) // Effectively an incremental read
if err != nil {
break
@@ -1019,7 +1017,7 @@ func TestParsePAX(t *testing.T) {
for i, v := range vectors {
r := strings.NewReader(v.in)
got, err := parsePAX(r)
if !maps.Equal(got, v.want) && !(len(got) == 0 && len(v.want) == 0) {
if !reflect.DeepEqual(got, v.want) && !(len(got) == 0 && len(v.want) == 0) {
t.Errorf("test %d, parsePAX():\ngot %v\nwant %v", i, got, v.want)
}
if ok := err == nil; ok != v.ok {
@@ -1136,7 +1134,7 @@ func TestReadOldGNUSparseMap(t *testing.T) {
v.input = v.input[copy(blk[:], v.input):]
tr := Reader{r: bytes.NewReader(v.input)}
got, err := tr.readOldGNUSparseMap(&hdr, &blk)
if !slices.Equal(got, v.wantMap) {
if !equalSparseEntries(got, v.wantMap) {
t.Errorf("test %d, readOldGNUSparseMap(): got %v, want %v", i, got, v.wantMap)
}
if err != v.wantErr {
@@ -1327,7 +1325,7 @@ func TestReadGNUSparsePAXHeaders(t *testing.T) {
r := strings.NewReader(v.inputData + "#") // Add canary byte
tr := Reader{curr: &regFileReader{r, int64(r.Len())}}
got, err := tr.readGNUSparsePAXHeaders(&hdr)
if !slices.Equal(got, v.wantMap) {
if !equalSparseEntries(got, v.wantMap) {
t.Errorf("test %d, readGNUSparsePAXHeaders(): got %v, want %v", i, got, v.wantMap)
}
if err != v.wantErr {

View File

@@ -11,13 +11,11 @@ import (
"internal/testenv"
"io"
"io/fs"
"maps"
"math"
"os"
"path"
"path/filepath"
"reflect"
"slices"
"strings"
"testing"
"time"
@@ -100,6 +98,10 @@ func (f *testFile) Seek(pos int64, whence int) (int64, error) {
return f.pos, nil
}
func equalSparseEntries(x, y []sparseEntry) bool {
return (len(x) == 0 && len(y) == 0) || reflect.DeepEqual(x, y)
}
func TestSparseEntries(t *testing.T) {
vectors := []struct {
in []sparseEntry
@@ -196,11 +198,11 @@ func TestSparseEntries(t *testing.T) {
continue
}
gotAligned := alignSparseEntries(append([]sparseEntry{}, v.in...), v.size)
if !slices.Equal(gotAligned, v.wantAligned) {
if !equalSparseEntries(gotAligned, v.wantAligned) {
t.Errorf("test %d, alignSparseEntries():\ngot %v\nwant %v", i, gotAligned, v.wantAligned)
}
gotInverted := invertSparseEntries(append([]sparseEntry{}, v.in...), v.size)
if !slices.Equal(gotInverted, v.wantInverted) {
if !equalSparseEntries(gotInverted, v.wantInverted) {
t.Errorf("test %d, inverseSparseEntries():\ngot %v\nwant %v", i, gotInverted, v.wantInverted)
}
}
@@ -742,7 +744,7 @@ func TestHeaderAllowedFormats(t *testing.T) {
if formats != v.formats {
t.Errorf("test %d, allowedFormats(): got %v, want %v", i, formats, v.formats)
}
if formats&FormatPAX > 0 && !maps.Equal(paxHdrs, v.paxHdrs) && !(len(paxHdrs) == 0 && len(v.paxHdrs) == 0) {
if formats&FormatPAX > 0 && !reflect.DeepEqual(paxHdrs, v.paxHdrs) && !(len(paxHdrs) == 0 && len(v.paxHdrs) == 0) {
t.Errorf("test %d, allowedFormats():\ngot %v\nwant %s", i, paxHdrs, v.paxHdrs)
}
if (formats != FormatUnknown) && (err != nil) {

View File

@@ -9,7 +9,6 @@ import (
"fmt"
"io"
"io/fs"
"maps"
"path"
"slices"
"strings"
@@ -170,10 +169,16 @@ func (tw *Writer) writePAXHeader(hdr *Header, paxHdrs map[string]string) error {
// Write PAX records to the output.
isGlobal := hdr.Typeflag == TypeXGlobalHeader
if len(paxHdrs) > 0 || isGlobal {
// Sort keys for deterministic ordering.
var keys []string
for k := range paxHdrs {
keys = append(keys, k)
}
slices.Sort(keys)
// Write each record to a buffer.
var buf strings.Builder
// Sort keys for deterministic ordering.
for _, k := range slices.Sorted(maps.Keys(paxHdrs)) {
for _, k := range keys {
rec, err := formatPAXRecord(k, paxHdrs[k])
if err != nil {
return err
@@ -408,7 +413,7 @@ func (tw *Writer) AddFS(fsys fs.FS) error {
if err != nil {
return err
}
if name == "." {
if d.IsDir() {
return nil
}
info, err := d.Info()
@@ -416,7 +421,7 @@ func (tw *Writer) AddFS(fsys fs.FS) error {
return err
}
// TODO(#49580): Handle symlinks when fs.ReadLinkFS is available.
if !d.IsDir() && !info.Mode().IsRegular() {
if !info.Mode().IsRegular() {
return errors.New("tar: cannot add non-regular file")
}
h, err := FileInfoHeader(info, "")
@@ -427,9 +432,6 @@ func (tw *Writer) AddFS(fsys fs.FS) error {
if err := tw.WriteHeader(h); err != nil {
return err
}
if d.IsDir() {
return nil
}
f, err := fsys.Open(name)
if err != nil {
return err
@@ -666,7 +668,6 @@ func (sw *sparseFileWriter) ReadFrom(r io.Reader) (n int64, err error) {
func (sw sparseFileWriter) logicalRemaining() int64 {
return sw.sp[len(sw.sp)-1].endOffset() - sw.pos
}
func (sw sparseFileWriter) physicalRemaining() int64 {
return sw.fw.physicalRemaining()
}

View File

@@ -10,11 +10,10 @@ import (
"errors"
"io"
"io/fs"
"maps"
"os"
"path"
"reflect"
"slices"
"sort"
"strings"
"testing"
"testing/fstest"
@@ -703,7 +702,7 @@ func TestPaxXattrs(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if !maps.Equal(hdr.Xattrs, xattrs) {
if !reflect.DeepEqual(hdr.Xattrs, xattrs) {
t.Fatalf("xattrs did not survive round trip: got %+v, want %+v",
hdr.Xattrs, xattrs)
}
@@ -1339,40 +1338,29 @@ func TestFileWriter(t *testing.T) {
func TestWriterAddFS(t *testing.T) {
fsys := fstest.MapFS{
"emptyfolder": {Mode: 0o755 | os.ModeDir},
"file.go": {Data: []byte("hello")},
"subfolder/another.go": {Data: []byte("world")},
// Notably missing here is the "subfolder" directory. This makes sure even
// if we don't have a subfolder directory listed.
}
var buf bytes.Buffer
tw := NewWriter(&buf)
if err := tw.AddFS(fsys); err != nil {
t.Fatal(err)
}
if err := tw.Close(); err != nil {
t.Fatal(err)
}
// Add subfolder into fsys to match what we'll read from the tar.
fsys["subfolder"] = &fstest.MapFile{Mode: 0o555 | os.ModeDir}
// Test that we can get the files back from the archive
tr := NewReader(&buf)
names := make([]string, 0, len(fsys))
for name := range fsys {
names = append(names, name)
entries, err := fsys.ReadDir(".")
if err != nil {
t.Fatal(err)
}
sort.Strings(names)
entriesLeft := len(fsys)
for _, name := range names {
entriesLeft--
entryInfo, err := fsys.Stat(name)
if err != nil {
t.Fatalf("getting entry info error: %v", err)
var curfname string
for _, entry := range entries {
curfname = entry.Name()
if entry.IsDir() {
curfname += "/"
continue
}
hdr, err := tr.Next()
if err == io.EOF {
@@ -1382,33 +1370,22 @@ func TestWriterAddFS(t *testing.T) {
t.Fatal(err)
}
if hdr.Name != name {
t.Errorf("test fs has filename %v; archive header has %v",
name, hdr.Name)
}
if entryInfo.Mode() != hdr.FileInfo().Mode() {
t.Errorf("%s: test fs has mode %v; archive header has %v",
name, entryInfo.Mode(), hdr.FileInfo().Mode())
}
if entryInfo.IsDir() {
continue
}
data, err := io.ReadAll(tr)
if err != nil {
t.Fatal(err)
}
origdata := fsys[name].Data
if hdr.Name != curfname {
t.Fatalf("got filename %v, want %v",
curfname, hdr.Name)
}
origdata := fsys[curfname].Data
if string(data) != string(origdata) {
t.Fatalf("test fs has file content %v; archive header has %v",
t.Fatalf("got file content %v, want %v",
data, origdata)
}
}
if entriesLeft > 0 {
t.Fatalf("not all entries are in the archive")
}
}
func TestWriterAddFSNonRegularFiles(t *testing.T) {

View File

@@ -902,8 +902,14 @@ func (r *Reader) Open(name string) (fs.File, error) {
}
func split(name string) (dir, elem string, isDir bool) {
name, isDir = strings.CutSuffix(name, "/")
i := strings.LastIndexByte(name, '/')
if len(name) > 0 && name[len(name)-1] == '/' {
isDir = true
name = name[:len(name)-1]
}
i := len(name) - 1
for i >= 0 && name[i] != '/' {
i--
}
if i < 0 {
return ".", name, isDir
}

View File

@@ -13,8 +13,8 @@ import (
"io/fs"
"os"
"path/filepath"
"reflect"
"regexp"
"slices"
"strings"
"testing"
"testing/fstest"
@@ -1274,7 +1274,7 @@ func TestFSWalk(t *testing.T) {
} else if !test.wantErr && sawErr {
t.Error("unexpected error")
}
if test.want != nil && !slices.Equal(files, test.want) {
if test.want != nil && !reflect.DeepEqual(files, test.want) {
t.Errorf("got %v want %v", files, test.want)
}
})
@@ -1580,7 +1580,7 @@ func TestCVE202141772(t *testing.T) {
t.Errorf("Opening %q with fs.FS API succeeded", f.Name)
}
}
if !slices.Equal(names, entryNames) {
if !reflect.DeepEqual(names, entryNames) {
t.Errorf("Unexpected file entries: %q", names)
}
if _, err := r.Open(""); err == nil {
@@ -1693,7 +1693,7 @@ func TestInsecurePaths(t *testing.T) {
for _, f := range zr.File {
gotPaths = append(gotPaths, f.Name)
}
if !slices.Equal(gotPaths, []string{path}) {
if !reflect.DeepEqual(gotPaths, []string{path}) {
t.Errorf("NewReader for archive with file %q: got files %q", path, gotPaths)
continue
}
@@ -1718,7 +1718,7 @@ func TestDisableInsecurePathCheck(t *testing.T) {
for _, f := range zr.File {
gotPaths = append(gotPaths, f.Name)
}
if want := []string{name}; !slices.Equal(gotPaths, want) {
if want := []string{name}; !reflect.DeepEqual(gotPaths, want) {
t.Errorf("NewReader with zipinsecurepath=1: got files %q, want %q", gotPaths, want)
}
}

View File

@@ -505,14 +505,14 @@ func (w *Writer) AddFS(fsys fs.FS) error {
if err != nil {
return err
}
if name == "." {
if d.IsDir() {
return nil
}
info, err := d.Info()
if err != nil {
return err
}
if !d.IsDir() && !info.Mode().IsRegular() {
if !info.Mode().IsRegular() {
return errors.New("zip: cannot add non-regular file")
}
h, err := FileInfoHeader(info)
@@ -525,9 +525,6 @@ func (w *Writer) AddFS(fsys fs.FS) error {
if err != nil {
return err
}
if d.IsDir() {
return nil
}
f, err := fsys.Open(name)
if err != nil {
return err

View File

@@ -108,7 +108,7 @@ func TestWriter(t *testing.T) {
// TestWriterComment is test for EOCD comment read/write.
func TestWriterComment(t *testing.T) {
tests := []struct {
var tests = []struct {
comment string
ok bool
}{
@@ -158,7 +158,7 @@ func TestWriterComment(t *testing.T) {
}
func TestWriterUTF8(t *testing.T) {
utf8Tests := []struct {
var utf8Tests = []struct {
name string
comment string
nonUTF8 bool
@@ -619,23 +619,26 @@ func TestWriterAddFS(t *testing.T) {
buf := new(bytes.Buffer)
w := NewWriter(buf)
tests := []WriteTest{
{Name: "emptyfolder", Mode: 0o755 | os.ModeDir},
{Name: "file.go", Data: []byte("hello"), Mode: 0644},
{Name: "subfolder/another.go", Data: []byte("world"), Mode: 0644},
// Notably missing here is the "subfolder" directory. This makes sure even
// if we don't have a subfolder directory listed.
{
Name: "file.go",
Data: []byte("hello"),
Mode: 0644,
},
{
Name: "subfolder/another.go",
Data: []byte("world"),
Mode: 0644,
},
}
err := w.AddFS(writeTestsToFS(tests))
if err != nil {
t.Fatal(err)
}
if err := w.Close(); err != nil {
t.Fatal(err)
}
// Add subfolder into fsys to match what we'll read from the tar.
tests = append(tests[:2:2], WriteTest{Name: "subfolder", Mode: 0o555 | os.ModeDir}, tests[2])
// read it back
r, err := NewReader(bytes.NewReader(buf.Bytes()), int64(buf.Len()))
if err != nil {

View File

@@ -29,9 +29,6 @@ var (
// Buffered input.
// Reader implements buffering for an io.Reader object.
// A new Reader is created by calling [NewReader] or [NewReaderSize];
// alternatively the zero value of a Reader may be used after calling [Reset]
// on it.
type Reader struct {
buf []byte
rd io.Reader // reader provided by the client
@@ -133,10 +130,9 @@ func (b *Reader) readErr() error {
}
// Peek returns the next n bytes without advancing the reader. The bytes stop
// being valid at the next read call. If necessary, Peek will read more bytes
// into the buffer in order to make n bytes available. If Peek returns fewer
// than n bytes, it also returns an error explaining why the read is short.
// The error is [ErrBufferFull] if n is larger than b's buffer size.
// being valid at the next read call. If Peek returns fewer than n bytes, it
// also returns an error explaining why the read is short. The error is
// [ErrBufferFull] if n is larger than b's buffer size.
//
// Calling Peek prevents a [Reader.UnreadByte] or [Reader.UnreadRune] call from succeeding
// until the next read operation.

View File

@@ -9,7 +9,6 @@ import (
"bytes"
"errors"
"fmt"
"internal/asan"
"io"
"math/rand"
"strconv"
@@ -586,9 +585,6 @@ func TestWriteInvalidRune(t *testing.T) {
}
func TestReadStringAllocs(t *testing.T) {
if asan.Enabled {
t.Skip("test allocates more with -asan; see #70079")
}
r := strings.NewReader(" foo foo 42 42 42 42 42 42 42 42 4.2 4.2 4.2 4.2\n")
buf := NewReader(r)
allocs := testing.AllocsPerRun(100, func() {
@@ -640,7 +636,7 @@ func TestWriter(t *testing.T) {
for l := 0; l < len(written); l++ {
if written[l] != data[l] {
t.Errorf("wrong bytes written")
t.Errorf("want=%q", data[:len(written)])
t.Errorf("want=%q", data[0:len(written)])
t.Errorf("have=%q", written)
}
}
@@ -939,6 +935,7 @@ func (t *testReader) Read(buf []byte) (n int, err error) {
}
func testReadLine(t *testing.T, input []byte) {
//for stride := 1; stride < len(input); stride++ {
for stride := 1; stride < 2; stride++ {
done := 0
reader := testReader{input, stride}

View File

@@ -33,33 +33,6 @@ func ExampleWriter_AvailableBuffer() {
// Output: 1 2 3 4
}
// ExampleWriter_ReadFrom demonstrates how to use the ReadFrom method of Writer.
func ExampleWriter_ReadFrom() {
var buf bytes.Buffer
writer := bufio.NewWriter(&buf)
data := "Hello, world!\nThis is a ReadFrom example."
reader := strings.NewReader(data)
n, err := writer.ReadFrom(reader)
if err != nil {
fmt.Println("ReadFrom Error:", err)
return
}
if err = writer.Flush(); err != nil {
fmt.Println("Flush Error:", err)
return
}
fmt.Println("Bytes written:", n)
fmt.Println("Buffer contents:", buf.String())
// Output:
// Bytes written: 41
// Buffer contents: Hello, world!
// This is a ReadFrom example.
}
// The simplest use of a Scanner, to read standard input as a set of lines.
func ExampleScanner_lines() {
scanner := bufio.NewScanner(os.Stdin)

View File

@@ -247,8 +247,8 @@ func growSlice(b []byte, n int) []byte {
c = 2 * cap(b)
}
b2 := append([]byte(nil), make([]byte, c)...)
i := copy(b2, b)
return b2[:i]
copy(b2, b)
return b2[:len(b)]
}
// WriteTo writes data to w until the buffer is drained or an error occurs.

View File

@@ -213,7 +213,7 @@ func TestLargeByteWrites(t *testing.T) {
func TestLargeStringReads(t *testing.T) {
var buf Buffer
for i := 3; i < 30; i += 3 {
s := fillString(t, "TestLargeReads (1)", &buf, "", 5, testString[:len(testString)/i])
s := fillString(t, "TestLargeReads (1)", &buf, "", 5, testString[0:len(testString)/i])
empty(t, "TestLargeReads (2)", &buf, s, make([]byte, len(testString)))
}
check(t, "TestLargeStringReads (3)", &buf, "")
@@ -222,7 +222,7 @@ func TestLargeStringReads(t *testing.T) {
func TestLargeByteReads(t *testing.T) {
var buf Buffer
for i := 3; i < 30; i += 3 {
s := fillBytes(t, "TestLargeReads (1)", &buf, "", 5, testBytes[:len(testBytes)/i])
s := fillBytes(t, "TestLargeReads (1)", &buf, "", 5, testBytes[0:len(testBytes)/i])
empty(t, "TestLargeReads (2)", &buf, s, make([]byte, len(testString)))
}
check(t, "TestLargeByteReads (3)", &buf, "")
@@ -274,7 +274,7 @@ func TestNil(t *testing.T) {
func TestReadFrom(t *testing.T) {
var buf Buffer
for i := 3; i < 30; i += 3 {
s := fillBytes(t, "TestReadFrom (1)", &buf, "", 5, testBytes[:len(testBytes)/i])
s := fillBytes(t, "TestReadFrom (1)", &buf, "", 5, testBytes[0:len(testBytes)/i])
var b Buffer
b.ReadFrom(&buf)
empty(t, "TestReadFrom (2)", &b, s, make([]byte, len(testString)))
@@ -337,7 +337,7 @@ func TestReadFromNegativeReader(t *testing.T) {
func TestWriteTo(t *testing.T) {
var buf Buffer
for i := 3; i < 30; i += 3 {
s := fillBytes(t, "TestWriteTo (1)", &buf, "", 5, testBytes[:len(testBytes)/i])
s := fillBytes(t, "TestWriteTo (1)", &buf, "", 5, testBytes[0:len(testBytes)/i])
var b Buffer
buf.WriteTo(&b)
empty(t, "TestWriteTo (2)", &b, s, make([]byte, len(testString)))

View File

@@ -8,7 +8,6 @@ package bytes
import (
"internal/bytealg"
"math/bits"
"unicode"
"unicode/utf8"
_ "unsafe" // for linkname
@@ -137,7 +136,6 @@ func LastIndexByte(s []byte, c byte) int {
// If r is [utf8.RuneError], it returns the first instance of any
// invalid UTF-8 byte sequence.
func IndexRune(s []byte, r rune) int {
const haveFastIndex = bytealg.MaxBruteForce > 0
switch {
case 0 <= r && r < utf8.RuneSelf:
return IndexByte(s, byte(r))
@@ -153,64 +151,9 @@ func IndexRune(s []byte, r rune) int {
case !utf8.ValidRune(r):
return -1
default:
// Search for rune r using the last byte of its UTF-8 encoded form.
// The distribution of the last byte is more uniform compared to the
// first byte which has a 78% chance of being [240, 243, 244].
var b [utf8.UTFMax]byte
n := utf8.EncodeRune(b[:], r)
last := n - 1
i := last
fails := 0
for i < len(s) {
if s[i] != b[last] {
o := IndexByte(s[i+1:], b[last])
if o < 0 {
return -1
}
i += o + 1
}
// Step backwards comparing bytes.
for j := 1; j < n; j++ {
if s[i-j] != b[last-j] {
goto next
}
}
return i - last
next:
fails++
i++
if (haveFastIndex && fails > bytealg.Cutover(i)) && i < len(s) ||
(!haveFastIndex && fails >= 4+i>>4 && i < len(s)) {
goto fallback
}
}
return -1
fallback:
// Switch to bytealg.Index, if available, or a brute force search when
// IndexByte returns too many false positives.
if haveFastIndex {
if j := bytealg.Index(s[i-last:], b[:n]); j >= 0 {
return i + j - last
}
} else {
// If bytealg.Index is not available a brute force search is
// ~1.5-3x faster than Rabin-Karp since n is small.
c0 := b[last]
c1 := b[last-1] // There are at least 2 chars to match
loop:
for ; i < len(s); i++ {
if s[i] == c0 && s[i-1] == c1 {
for k := 2; k < n; k++ {
if s[i-k] != b[last-k] {
continue loop
}
}
return i - last
}
}
}
return -1
return Index(s, b[:n])
}
}
@@ -592,7 +535,7 @@ func Join(s [][]byte, sep []byte) []byte {
// HasPrefix reports whether the byte slice s begins with prefix.
func HasPrefix(s, prefix []byte) bool {
return len(s) >= len(prefix) && Equal(s[:len(prefix)], prefix)
return len(s) >= len(prefix) && Equal(s[0:len(prefix)], prefix)
}
// HasSuffix reports whether the byte slice s ends with suffix.
@@ -651,11 +594,10 @@ func Repeat(b []byte, count int) []byte {
if count < 0 {
panic("bytes: negative Repeat count")
}
hi, lo := bits.Mul(uint(len(b)), uint(count))
if hi > 0 || lo > uint(maxInt) {
if len(b) > maxInt/count {
panic("bytes: Repeat output length overflow")
}
n := int(lo) // lo = len(b) * count
n := len(b) * count
if len(b) == 0 {
return []byte{}
@@ -682,7 +624,10 @@ func Repeat(b []byte, count int) []byte {
nb := bytealg.MakeNoZero(n)[:n:n]
bp := copy(nb, b)
for bp < n {
chunk := min(bp, chunkMax)
chunk := bp
if chunk > chunkMax {
chunk = chunkMax
}
bp += copy(nb[bp:], nb[:chunk])
}
return nb

View File

@@ -8,10 +8,9 @@ import (
. "bytes"
"fmt"
"internal/testenv"
"iter"
"math"
"math/rand"
"slices"
"reflect"
"strings"
"testing"
"unicode"
@@ -19,6 +18,18 @@ import (
"unsafe"
)
func eq(a, b []string) bool {
if len(a) != len(b) {
return false
}
for i := 0; i < len(a); i++ {
if a[i] != b[i] {
return false
}
}
return true
}
func sliceOfString(s [][]byte) []string {
result := make([]string, len(s))
for i, v := range s {
@@ -27,37 +38,6 @@ func sliceOfString(s [][]byte) []string {
return result
}
func collect(t *testing.T, seq iter.Seq[[]byte]) [][]byte {
out := slices.Collect(seq)
out1 := slices.Collect(seq)
if !slices.Equal(sliceOfString(out), sliceOfString(out1)) {
t.Fatalf("inconsistent seq:\n%s\n%s", out, out1)
}
return out
}
type LinesTest struct {
a string
b []string
}
var linesTests = []LinesTest{
{a: "abc\nabc\n", b: []string{"abc\n", "abc\n"}},
{a: "abc\r\nabc", b: []string{"abc\r\n", "abc"}},
{a: "abc\r\n", b: []string{"abc\r\n"}},
{a: "\nabc", b: []string{"\n", "abc"}},
{a: "\nabc\n\n", b: []string{"\n", "abc\n", "\n"}},
}
func TestLines(t *testing.T) {
for _, s := range linesTests {
result := sliceOfString(slices.Collect(Lines([]byte(s.a))))
if !slices.Equal(result, s.b) {
t.Errorf(`slices.Collect(Lines(%q)) = %q; want %q`, s.a, result, s.b)
}
}
}
// For ease of reading, the test cases use strings that are converted to byte
// slices before invoking the functions.
@@ -197,11 +177,6 @@ var indexTests = []BinOpTest{
{"oxoxoxoxoxoxoxoxoxoxoxox", "oy", -1},
// test fallback to Rabin-Karp.
{"000000000000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000000001", 5},
// test fallback to IndexRune
{"oxoxoxoxoxoxoxoxoxoxox☺", "☺", 22},
// invalid UTF-8 byte sequence (must be longer than bytealg.MaxBruteForce to
// test that we don't use IndexRune)
{"xx0123456789012345678901234567890123456789012345678901234567890120123456789012345678901234567890123456xxx\xed\x9f\xc0", "\xed\x9f\xc0", 105},
}
var lastIndexTests = []BinOpTest{
@@ -450,31 +425,6 @@ func TestIndexRune(t *testing.T) {
{"some_text=some_value", '=', 9},
{"☺a", 'a', 3},
{"a☻☺b", '☺', 4},
{"𠀳𠀗𠀾𠁄𠀧𠁆𠁂𠀫𠀖𠀪𠀲𠀴𠁀𠀨𠀿", '𠀿', 56},
// 2 bytes
{"ӆ", 'ӆ', 0},
{"a", 'ӆ', -1},
{" ӆ", 'ӆ', 2},
{" a", 'ӆ', -1},
{strings.Repeat("ц", 64) + "ӆ", 'ӆ', 128}, // test cutover
{strings.Repeat("ц", 64), 'ӆ', -1},
// 3 bytes
{"Ꚁ", 'Ꚁ', 0},
{"a", 'Ꚁ', -1},
{" Ꚁ", 'Ꚁ', 2},
{" a", 'Ꚁ', -1},
{strings.Repeat("Ꙁ", 64) + "Ꚁ", 'Ꚁ', 192}, // test cutover
{strings.Repeat("Ꙁ", 64) + "Ꚁ", '䚀', -1}, // 'Ꚁ' and '䚀' share the same last two bytes
// 4 bytes
{"𡌀", '𡌀', 0},
{"a", '𡌀', -1},
{" 𡌀", '𡌀', 2},
{" a", '𡌀', -1},
{strings.Repeat("𡋀", 64) + "𡌀", '𡌀', 256}, // test cutover
{strings.Repeat("𡋀", 64) + "𡌀", '𣌀', -1}, // '𡌀' and '𣌀' share the same last two bytes
// RuneError should match any invalid UTF-8 byte sequence.
{"<22>", '<27>', 0},
@@ -488,13 +438,6 @@ func TestIndexRune(t *testing.T) {
{"a☺b☻c☹d\xe2\x98<39>\xff<66>\xed\xa0\x80", -1, -1},
{"a☺b☻c☹d\xe2\x98<39>\xff<66>\xed\xa0\x80", 0xD800, -1}, // Surrogate pair
{"a☺b☻c☹d\xe2\x98<39>\xff<66>\xed\xa0\x80", utf8.MaxRune + 1, -1},
// Test the cutover to bytealg.Index when it is triggered in
// the middle of rune that contains consecutive runs of equal bytes.
{"aaaaa\U000bc104", '\U000bc104', 17}, // cutover: (n + 16) / 8
{"aaaaa鄄", '鄄', 17},
{"aaa\U000bc104", '\U000bc104', 18}, // cutover: 4 + n>>4
{"aaa鄄", '鄄', 18},
}
for _, tt := range tests {
if got := IndexRune([]byte(tt.in), tt.rune); got != tt.want {
@@ -642,21 +585,6 @@ func BenchmarkIndexRuneASCII(b *testing.B) {
benchBytes(b, indexSizes, bmIndexRuneASCII(IndexRune))
}
func BenchmarkIndexRuneUnicode(b *testing.B) {
b.Run("Latin", func(b *testing.B) {
// Latin is mostly 1, 2, 3 byte runes.
benchBytes(b, indexSizes, bmIndexRuneUnicode(unicode.Latin, 'é'))
})
b.Run("Cyrillic", func(b *testing.B) {
// Cyrillic is mostly 2 and 3 byte runes.
benchBytes(b, indexSizes, bmIndexRuneUnicode(unicode.Cyrillic, 'Ꙁ'))
})
b.Run("Han", func(b *testing.B) {
// Han consists only of 3 and 4 byte runes.
benchBytes(b, indexSizes, bmIndexRuneUnicode(unicode.Han, '𠀿'))
})
}
func bmIndexRuneASCII(index func([]byte, rune) int) func(b *testing.B, n int) {
return func(b *testing.B, n int) {
buf := bmbuf[0:n]
@@ -687,61 +615,6 @@ func bmIndexRune(index func([]byte, rune) int) func(b *testing.B, n int) {
}
}
func bmIndexRuneUnicode(rt *unicode.RangeTable, needle rune) func(b *testing.B, n int) {
var rs []rune
for _, r16 := range rt.R16 {
for r := rune(r16.Lo); r <= rune(r16.Hi); r += rune(r16.Stride) {
if r != needle {
rs = append(rs, rune(r))
}
}
}
for _, r32 := range rt.R32 {
for r := rune(r32.Lo); r <= rune(r32.Hi); r += rune(r32.Stride) {
if r != needle {
rs = append(rs, rune(r))
}
}
}
// Shuffle the runes so that they are not in descending order.
// The sort is deterministic since this is used for benchmarks,
// which need to be repeatable.
rr := rand.New(rand.NewSource(1))
rr.Shuffle(len(rs), func(i, j int) {
rs[i], rs[j] = rs[j], rs[i]
})
uchars := string(rs)
return func(b *testing.B, n int) {
buf := bmbuf[0:n]
o := copy(buf, uchars)
for o < len(buf) {
o += copy(buf[o:], uchars)
}
// Make space for the needle rune at the end of buf.
m := utf8.RuneLen(needle)
for o := m; o > 0; {
_, sz := utf8.DecodeLastRune(buf)
copy(buf[len(buf)-sz:], "\x00\x00\x00\x00")
buf = buf[:len(buf)-sz]
o -= sz
}
buf = utf8.AppendRune(buf[:n-m], needle)
n -= m // adjust for rune len
for i := 0; i < b.N; i++ {
j := IndexRune(buf, needle)
if j != n {
b.Fatal("bad index", j)
}
}
for i := range buf {
buf[i] = '\x00'
}
}
}
func BenchmarkEqual(b *testing.B) {
b.Run("0", func(b *testing.B) {
var buf [4]byte
@@ -935,18 +808,10 @@ func TestSplit(t *testing.T) {
}
result := sliceOfString(a)
if !slices.Equal(result, tt.a) {
if !eq(result, tt.a) {
t.Errorf(`Split(%q, %q, %d) = %v; want %v`, tt.s, tt.sep, tt.n, result, tt.a)
continue
}
if tt.n < 0 {
b := sliceOfString(slices.Collect(SplitSeq([]byte(tt.s), []byte(tt.sep))))
if !slices.Equal(b, tt.a) {
t.Errorf(`collect(SplitSeq(%q, %q)) = %v; want %v`, tt.s, tt.sep, b, tt.a)
}
}
if tt.n == 0 || len(a) == 0 {
continue
}
@@ -960,8 +825,8 @@ func TestSplit(t *testing.T) {
t.Errorf(`Join(Split(%q, %q, %d), %q) = %q`, tt.s, tt.sep, tt.n, tt.sep, s)
}
if tt.n < 0 {
b := sliceOfString(Split([]byte(tt.s), []byte(tt.sep)))
if !slices.Equal(result, b) {
b := Split([]byte(tt.s), []byte(tt.sep))
if !reflect.DeepEqual(a, b) {
t.Errorf("Split disagrees withSplitN(%q, %q, %d) = %v; want %v", tt.s, tt.sep, tt.n, b, a)
}
}
@@ -1001,18 +866,11 @@ func TestSplitAfter(t *testing.T) {
}
result := sliceOfString(a)
if !slices.Equal(result, tt.a) {
if !eq(result, tt.a) {
t.Errorf(`Split(%q, %q, %d) = %v; want %v`, tt.s, tt.sep, tt.n, result, tt.a)
continue
}
if tt.n < 0 {
b := sliceOfString(slices.Collect(SplitAfterSeq([]byte(tt.s), []byte(tt.sep))))
if !slices.Equal(b, tt.a) {
t.Errorf(`collect(SplitAfterSeq(%q, %q)) = %v; want %v`, tt.s, tt.sep, b, tt.a)
}
}
if want := tt.a[len(tt.a)-1] + "z"; string(x) != want {
t.Errorf("last appended result was %s; want %s", x, want)
}
@@ -1022,8 +880,8 @@ func TestSplitAfter(t *testing.T) {
t.Errorf(`Join(Split(%q, %q, %d), %q) = %q`, tt.s, tt.sep, tt.n, tt.sep, s)
}
if tt.n < 0 {
b := sliceOfString(SplitAfter([]byte(tt.s), []byte(tt.sep)))
if !slices.Equal(result, b) {
b := SplitAfter([]byte(tt.s), []byte(tt.sep))
if !reflect.DeepEqual(a, b) {
t.Errorf("SplitAfter disagrees withSplitAfterN(%q, %q, %d) = %v; want %v", tt.s, tt.sep, tt.n, b, a)
}
}
@@ -1061,16 +919,11 @@ func TestFields(t *testing.T) {
}
result := sliceOfString(a)
if !slices.Equal(result, tt.a) {
if !eq(result, tt.a) {
t.Errorf("Fields(%q) = %v; want %v", tt.s, a, tt.a)
continue
}
result2 := sliceOfString(collect(t, FieldsSeq([]byte(tt.s))))
if !slices.Equal(result2, tt.a) {
t.Errorf(`collect(FieldsSeq(%q)) = %v; want %v`, tt.s, result2, tt.a)
}
if string(b) != tt.s {
t.Errorf("slice changed to %s; want %s", string(b), tt.s)
}
@@ -1086,7 +939,7 @@ func TestFieldsFunc(t *testing.T) {
for _, tt := range fieldstests {
a := FieldsFunc([]byte(tt.s), unicode.IsSpace)
result := sliceOfString(a)
if !slices.Equal(result, tt.a) {
if !eq(result, tt.a) {
t.Errorf("FieldsFunc(%q, unicode.IsSpace) = %v; want %v", tt.s, a, tt.a)
continue
}
@@ -1109,15 +962,10 @@ func TestFieldsFunc(t *testing.T) {
}
result := sliceOfString(a)
if !slices.Equal(result, tt.a) {
if !eq(result, tt.a) {
t.Errorf("FieldsFunc(%q) = %v, want %v", tt.s, a, tt.a)
}
result2 := sliceOfString(collect(t, FieldsFuncSeq([]byte(tt.s), pred)))
if !slices.Equal(result2, tt.a) {
t.Errorf(`collect(FieldsFuncSeq(%q)) = %v; want %v`, tt.s, result2, tt.a)
}
if string(b) != tt.s {
t.Errorf("slice changed to %s; want %s", b, tt.s)
}
@@ -1438,6 +1286,18 @@ func TestRepeatCatchesOverflow(t *testing.T) {
})
}
func runesEqual(a, b []rune) bool {
if len(a) != len(b) {
return false
}
for i, r := range a {
if r != b[i] {
return false
}
}
return true
}
type RunesTest struct {
in string
out []rune
@@ -1458,7 +1318,7 @@ func TestRunes(t *testing.T) {
for _, tt := range RunesTests {
tin := []byte(tt.in)
a := Runes(tin)
if !slices.Equal(a, tt.out) {
if !runesEqual(a, tt.out) {
t.Errorf("Runes(%q) = %v; want %v", tin, a, tt.out)
continue
}
@@ -2184,11 +2044,6 @@ func makeBenchInputHard() []byte {
var benchInputHard = makeBenchInputHard()
func benchmarkIndexHard(b *testing.B, sep []byte) {
n := Index(benchInputHard, sep)
if n < 0 {
n = len(benchInputHard)
}
b.SetBytes(int64(n))
for i := 0; i < b.N; i++ {
Index(benchInputHard, sep)
}

View File

@@ -502,10 +502,10 @@ func ExampleTitle() {
func ExampleToTitle() {
fmt.Printf("%s\n", bytes.ToTitle([]byte("loud noises")))
fmt.Printf("%s\n", bytes.ToTitle([]byte("брат")))
fmt.Printf("%s\n", bytes.ToTitle([]byte("хлеб")))
// Output:
// LOUD NOISES
// БРАТ
// ХЛЕБ
}
func ExampleToTitleSpecial() {

View File

@@ -1,148 +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.
package bytes
import (
"iter"
"unicode"
"unicode/utf8"
)
// Lines returns an iterator over the newline-terminated lines in the byte slice s.
// The lines yielded by the iterator include their terminating newlines.
// If s is empty, the iterator yields no lines at all.
// If s does not end in a newline, the final yielded line will not end in a newline.
// It returns a single-use iterator.
func Lines(s []byte) iter.Seq[[]byte] {
return func(yield func([]byte) bool) {
for len(s) > 0 {
var line []byte
if i := IndexByte(s, '\n'); i >= 0 {
line, s = s[:i+1], s[i+1:]
} else {
line, s = s, nil
}
if !yield(line[:len(line):len(line)]) {
return
}
}
return
}
}
// explodeSeq returns an iterator over the runes in s.
func explodeSeq(s []byte) iter.Seq[[]byte] {
return func(yield func([]byte) bool) {
for len(s) > 0 {
_, size := utf8.DecodeRune(s)
if !yield(s[:size:size]) {
return
}
s = s[size:]
}
}
}
// splitSeq is SplitSeq or SplitAfterSeq, configured by how many
// bytes of sep to include in the results (none or all).
func splitSeq(s, sep []byte, sepSave int) iter.Seq[[]byte] {
if len(sep) == 0 {
return explodeSeq(s)
}
return func(yield func([]byte) bool) {
for {
i := Index(s, sep)
if i < 0 {
break
}
frag := s[:i+sepSave]
if !yield(frag[:len(frag):len(frag)]) {
return
}
s = s[i+len(sep):]
}
yield(s[:len(s):len(s)])
}
}
// SplitSeq returns an iterator over all substrings of s separated by sep.
// The iterator yields the same strings that would be returned by Split(s, sep),
// but without constructing the slice.
// It returns a single-use iterator.
func SplitSeq(s, sep []byte) iter.Seq[[]byte] {
return splitSeq(s, sep, 0)
}
// SplitAfterSeq returns an iterator over substrings of s split after each instance of sep.
// The iterator yields the same strings that would be returned by SplitAfter(s, sep),
// but without constructing the slice.
// It returns a single-use iterator.
func SplitAfterSeq(s, sep []byte) iter.Seq[[]byte] {
return splitSeq(s, sep, len(sep))
}
// FieldsSeq returns an iterator over substrings of s split around runs of
// whitespace characters, as defined by unicode.IsSpace.
// The iterator yields the same strings that would be returned by Fields(s),
// but without constructing the slice.
func FieldsSeq(s []byte) iter.Seq[[]byte] {
return func(yield func([]byte) bool) {
start := -1
for i := 0; i < len(s); {
size := 1
r := rune(s[i])
isSpace := asciiSpace[s[i]] != 0
if r >= utf8.RuneSelf {
r, size = utf8.DecodeRune(s[i:])
isSpace = unicode.IsSpace(r)
}
if isSpace {
if start >= 0 {
if !yield(s[start:i:i]) {
return
}
start = -1
}
} else if start < 0 {
start = i
}
i += size
}
if start >= 0 {
yield(s[start:len(s):len(s)])
}
}
}
// FieldsFuncSeq returns an iterator over substrings of s split around runs of
// Unicode code points satisfying f(c).
// The iterator yields the same strings that would be returned by FieldsFunc(s),
// but without constructing the slice.
func FieldsFuncSeq(s []byte, f func(rune) bool) iter.Seq[[]byte] {
return func(yield func([]byte) bool) {
start := -1
for i := 0; i < len(s); {
size := 1
r := rune(s[i])
if r >= utf8.RuneSelf {
r, size = utf8.DecodeRune(s[i:])
}
if f(r) {
if start >= 0 {
if !yield(s[start:i:i]) {
return
}
start = -1
}
} else if start < 0 {
start = i
}
i += size
}
if start >= 0 {
yield(s[start:len(s):len(s)])
}
}
}

View File

@@ -12,6 +12,7 @@ import (
"path/filepath"
"runtime"
"strings"
"sync"
"testing"
)
@@ -27,6 +28,26 @@ func TestMain(m *testing.M) {
os.Exit(m.Run())
}
// addr2linePath returns the path to the "addr2line" binary to run.
func addr2linePath(t testing.TB) string {
t.Helper()
testenv.MustHaveExec(t)
addr2linePathOnce.Do(func() {
addr2lineExePath, addr2linePathErr = os.Executable()
})
if addr2linePathErr != nil {
t.Fatal(addr2linePathErr)
}
return addr2lineExePath
}
var (
addr2linePathOnce sync.Once
addr2lineExePath string
addr2linePathErr error
)
func loadSyms(t *testing.T, dbgExePath string) map[string]string {
cmd := testenv.Command(t, testenv.GoToolPath(t), "tool", "nm", dbgExePath)
out, err := cmd.CombinedOutput()
@@ -49,7 +70,7 @@ func loadSyms(t *testing.T, dbgExePath string) map[string]string {
}
func runAddr2Line(t *testing.T, dbgExePath, addr string) (funcname, path, lineno string) {
cmd := testenv.Command(t, testenv.Executable(t), dbgExePath)
cmd := testenv.Command(t, addr2linePath(t), dbgExePath)
cmd.Stdin = strings.NewReader(addr)
out, err := cmd.CombinedOutput()
if err != nil {
@@ -87,22 +108,27 @@ func testAddr2Line(t *testing.T, dbgExePath, addr string) {
// Debug paths are stored slash-separated, so convert to system-native.
srcPath = filepath.FromSlash(srcPath)
fi2, err := os.Stat(srcPath)
if err != nil {
t.Fatalf("Stat failed: %v", err)
}
if !os.SameFile(fi1, fi2) {
t.Fatalf("addr2line_test.go and %s are not same file", srcPath)
}
if want := "102"; srcLineNo != want {
if want := "124"; srcLineNo != want {
t.Fatalf("line number = %v; want %s", srcLineNo, want)
}
}
// This is line 101. The test depends on that.
// This is line 123. The test depends on that.
func TestAddr2Line(t *testing.T) {
testenv.MustHaveGoBuild(t)
tmpDir := t.TempDir()
tmpDir, err := os.MkdirTemp("", "TestAddr2Line")
if err != nil {
t.Fatal("TempDir failed: ", err)
}
defer os.RemoveAll(tmpDir)
// Build copy of test binary with debug symbols,
// since the one running now may not have them.

View File

@@ -11,7 +11,7 @@ import (
"internal/testenv"
"os"
"path/filepath"
"slices"
"sort"
"strings"
"sync"
"testing"
@@ -77,7 +77,7 @@ func TestGolden(t *testing.T) {
t.Fatalf("opening golden.txt for package %q: %v", fi.Name(), err)
}
wanted := strings.Split(string(bs), "\n")
slices.Sort(wanted)
sort.Strings(wanted)
for _, feature := range wanted {
if feature == "" {
continue

View File

@@ -25,7 +25,7 @@ import (
"path/filepath"
"regexp"
"runtime"
"slices"
"sort"
"strconv"
"strings"
"sync"
@@ -232,8 +232,8 @@ func compareAPI(w io.Writer, features, required, exception []string) (ok bool) {
featureSet := set(features)
exceptionSet := set(exception)
slices.Sort(features)
slices.Sort(required)
sort.Strings(features)
sort.Strings(required)
take := func(sl *[]string) string {
s := (*sl)[0]
@@ -378,7 +378,7 @@ func (w *Walker) Features() (fs []string) {
for f := range w.features {
fs = append(fs, f)
}
slices.Sort(fs)
sort.Strings(fs)
return
}
@@ -431,7 +431,7 @@ func tagKey(dir string, context *build.Context, tags []string) string {
// an indirect imported package. See https://github.com/golang/go/issues/21181
// for more detail.
tags = append(tags, context.GOOS, context.GOARCH)
slices.Sort(tags)
sort.Strings(tags)
for _, tag := range tags {
if ctags[tag] {
@@ -535,7 +535,7 @@ func (w *Walker) loadImports() {
}
}
slices.Sort(stdPackages)
sort.Strings(stdPackages)
imports = listImports{
stdPackages: stdPackages,
importMap: importMap,
@@ -717,7 +717,7 @@ func sortedMethodNames(typ *types.Interface) []string {
for i := range list {
list[i] = typ.Method(i).Name()
}
slices.Sort(list)
sort.Strings(list)
return list
}
@@ -747,7 +747,7 @@ func (w *Walker) sortedEmbeddeds(typ *types.Interface) []string {
list = append(list, buf.String())
}
}
slices.Sort(list)
sort.Strings(list)
return list
}
@@ -1019,7 +1019,7 @@ func (w *Walker) emitType(obj *types.TypeName) {
func (w *Walker) emitStructType(name string, typ *types.Struct) {
typeStruct := fmt.Sprintf("type %s struct", name)
w.emitf("%s", typeStruct)
w.emitf(typeStruct)
defer w.pushScope(typeStruct)()
for i := 0; i < typ.NumFields(); i++ {
@@ -1083,7 +1083,7 @@ func (w *Walker) emitIfaceType(name string, typ *types.Interface) {
return
}
slices.Sort(methodNames)
sort.Strings(methodNames)
w.emitf("type %s interface { %s }", name, strings.Join(methodNames, ", "))
}

View File

@@ -520,27 +520,15 @@ func archLoong64(linkArch *obj.LinkArch) *Arch {
for i := loong64.REG_R0; i <= loong64.REG_R31; i++ {
register[obj.Rconv(i)] = int16(i)
}
for i := loong64.REG_F0; i <= loong64.REG_F31; i++ {
register[obj.Rconv(i)] = int16(i)
}
for i := loong64.REG_FCSR0; i <= loong64.REG_FCSR31; i++ {
register[obj.Rconv(i)] = int16(i)
}
for i := loong64.REG_FCC0; i <= loong64.REG_FCC31; i++ {
register[obj.Rconv(i)] = int16(i)
}
for i := loong64.REG_V0; i <= loong64.REG_V31; i++ {
register[obj.Rconv(i)] = int16(i)
}
for i := loong64.REG_X0; i <= loong64.REG_X31; i++ {
register[obj.Rconv(i)] = int16(i)
}
// Pseudo-registers.
register["SB"] = RSB
register["FP"] = RFP
@@ -553,8 +541,6 @@ func archLoong64(linkArch *obj.LinkArch) *Arch {
"FCSR": true,
"FCC": true,
"R": true,
"V": true,
"X": true,
}
instructions := make(map[string]obj.As)
@@ -600,10 +586,6 @@ func archRISCV64(shared bool) *Arch {
name := fmt.Sprintf("F%d", i-riscv.REG_F0)
register[name] = int16(i)
}
for i := riscv.REG_V0; i <= riscv.REG_V31; i++ {
name := fmt.Sprintf("V%d", i-riscv.REG_V0)
register[name] = int16(i)
}
// General registers with ABI names.
register["ZERO"] = riscv.REG_ZERO

View File

@@ -101,7 +101,7 @@ func IsARMCMP(op obj.As) bool {
// one of the STREX-like instructions that require special handling.
func IsARMSTREX(op obj.As) bool {
switch op {
case arm.ASTREX, arm.ASTREXD, arm.ASTREXB, arm.ASWPW, arm.ASWPBU:
case arm.ASTREX, arm.ASTREXD, arm.ASWPW, arm.ASWPBU:
return true
}
return false

View File

@@ -11,8 +11,6 @@ package arch
import (
"cmd/internal/obj"
"cmd/internal/obj/loong64"
"errors"
"fmt"
)
func jumpLoong64(word string) bool {
@@ -23,6 +21,17 @@ func jumpLoong64(word string) bool {
return false
}
// IsLoong64CMP reports whether the op (as defined by an loong64.A* constant) is
// one of the CMP instructions that require special handling.
func IsLoong64CMP(op obj.As) bool {
switch op {
case loong64.ACMPEQF, loong64.ACMPEQD, loong64.ACMPGEF, loong64.ACMPGED,
loong64.ACMPGTF, loong64.ACMPGTD:
return true
}
return false
}
// IsLoong64MUL reports whether the op (as defined by an loong64.A* constant) is
// one of the MUL/DIV/REM instructions that require special handling.
func IsLoong64MUL(op obj.As) bool {
@@ -50,82 +59,6 @@ func IsLoong64AMO(op obj.As) bool {
return loong64.IsAtomicInst(op)
}
var loong64ElemExtMap = map[string]int16{
"B": loong64.ARNG_B,
"H": loong64.ARNG_H,
"W": loong64.ARNG_W,
"V": loong64.ARNG_V,
"BU": loong64.ARNG_BU,
"HU": loong64.ARNG_HU,
"WU": loong64.ARNG_WU,
"VU": loong64.ARNG_VU,
}
var loong64LsxArngExtMap = map[string]int16{
"B16": loong64.ARNG_16B,
"H8": loong64.ARNG_8H,
"W4": loong64.ARNG_4W,
"V2": loong64.ARNG_2V,
}
var loong64LasxArngExtMap = map[string]int16{
"B32": loong64.ARNG_32B,
"H16": loong64.ARNG_16H,
"W8": loong64.ARNG_8W,
"V4": loong64.ARNG_4V,
"Q2": loong64.ARNG_2Q,
}
// Loong64RegisterExtension constructs an Loong64 register with extension or arrangement.
func Loong64RegisterExtension(a *obj.Addr, ext string, reg, num int16, isAmount, isIndex bool) error {
var ok bool
var arng_type int16
var simd_type int16
switch {
case reg >= loong64.REG_V0 && reg <= loong64.REG_V31:
simd_type = loong64.LSX
case reg >= loong64.REG_X0 && reg <= loong64.REG_X31:
simd_type = loong64.LASX
default:
return errors.New("Loong64 extension: invalid LSX/LASX register: " + fmt.Sprintf("%d", reg))
}
if isIndex {
arng_type, ok = loong64ElemExtMap[ext]
if !ok {
return errors.New("Loong64 extension: invalid LSX/LASX arrangement type: " + ext)
}
a.Reg = loong64.REG_ELEM
a.Reg += ((reg & loong64.EXT_REG_MASK) << loong64.EXT_REG_SHIFT)
a.Reg += ((arng_type & loong64.EXT_TYPE_MASK) << loong64.EXT_TYPE_SHIFT)
a.Reg += ((simd_type & loong64.EXT_SIMDTYPE_MASK) << loong64.EXT_SIMDTYPE_SHIFT)
a.Index = num
} else {
switch simd_type {
case loong64.LSX:
arng_type, ok = loong64LsxArngExtMap[ext]
if !ok {
return errors.New("Loong64 extension: invalid LSX arrangement type: " + ext)
}
case loong64.LASX:
arng_type, ok = loong64LasxArngExtMap[ext]
if !ok {
return errors.New("Loong64 extension: invalid LASX arrangement type: " + ext)
}
}
a.Reg = loong64.REG_ARNG
a.Reg += ((reg & loong64.EXT_REG_MASK) << loong64.EXT_REG_SHIFT)
a.Reg += ((arng_type & loong64.EXT_TYPE_MASK) << loong64.EXT_TYPE_SHIFT)
a.Reg += ((simd_type & loong64.EXT_SIMDTYPE_MASK) << loong64.EXT_SIMDTYPE_SHIFT)
}
return nil
}
func loong64RegisterNumber(name string, n int16) (int16, bool) {
switch name {
case "F":
@@ -144,14 +77,6 @@ func loong64RegisterNumber(name string, n int16) (int16, bool) {
if 0 <= n && n <= 31 {
return loong64.REG_R0 + n, true
}
case "V":
if 0 <= n && n <= 31 {
return loong64.REG_V0 + n, true
}
case "X":
if 0 <= n && n <= 31 {
return loong64.REG_X0 + n, true
}
}
return 0, false
}

View File

@@ -25,7 +25,7 @@ func jumpPPC64(word string) bool {
// one of the CMP instructions that require special handling.
func IsPPC64CMP(op obj.As) bool {
switch op {
case ppc64.ACMP, ppc64.ACMPU, ppc64.ACMPW, ppc64.ACMPWU, ppc64.AFCMPO, ppc64.AFCMPU, ppc64.ADCMPO, ppc64.ADCMPU, ppc64.ADCMPOQ, ppc64.ADCMPUQ:
case ppc64.ACMP, ppc64.ACMPU, ppc64.ACMPW, ppc64.ACMPWU, ppc64.AFCMPO, ppc64.AFCMPU:
return true
}
return false

View File

@@ -353,7 +353,6 @@ func (p *Parser) asmPCAlign(operands [][]lex.Token) {
prog := &obj.Prog{
Ctxt: p.ctxt,
As: obj.APCALIGN,
Pos: p.pos(),
From: key,
}
p.append(prog, "", true)
@@ -643,6 +642,12 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
break
}
} else if p.arch.Family == sys.Loong64 {
if arch.IsLoong64CMP(op) {
prog.From = a[0]
prog.Reg = p.getRegister(prog, op, &a[1])
break
}
if arch.IsLoong64RDTIME(op) {
// The Loong64 RDTIME family of instructions is a bit special,
// in that both its register operands are outputs
@@ -823,13 +828,6 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
prog.To = a[3]
break
}
if p.arch.Family == sys.Loong64 {
prog.From = a[0]
prog.Reg = p.getRegister(prog, op, &a[1])
prog.AddRestSource(a[2])
prog.To = a[3]
break
}
if p.arch.Family == sys.PPC64 {
prog.From = a[0]
prog.To = a[3]

View File

@@ -217,8 +217,8 @@ next:
for {
tok = p.nextToken()
if len(operands) == 0 && len(items) == 0 {
if p.arch.InFamily(sys.ARM, sys.ARM64, sys.AMD64, sys.I386, sys.Loong64, sys.RISCV64) && tok == '.' {
// Suffixes: ARM conditionals, Loong64 vector instructions, RISCV rounding mode or x86 modifiers.
if p.arch.InFamily(sys.ARM, sys.ARM64, sys.AMD64, sys.I386, sys.RISCV64) && tok == '.' {
// Suffixes: ARM conditionals, RISCV rounding mode or x86 modifiers.
tok = p.nextToken()
str := p.lex.Text()
if tok != scanner.Ident {
@@ -570,13 +570,12 @@ func (p *Parser) atRegisterShift() bool {
// atRegisterExtension reports whether we are at the start of an ARM64 extended register.
// We have consumed the register or R prefix.
func (p *Parser) atRegisterExtension() bool {
switch p.arch.Family {
case sys.ARM64, sys.Loong64:
// R1.xxx
return p.peek() == '.'
default:
// ARM64 only.
if p.arch.Family != sys.ARM64 {
return false
}
// R1.xxx
return p.peek() == '.'
}
// registerReference parses a register given either the name, R10, or a parenthesized form, SPR(10).
@@ -709,7 +708,7 @@ func (p *Parser) registerShift(name string, prefix rune) int64 {
if p.arch.Family == sys.ARM64 {
off, err := arch.ARM64RegisterShift(r1, op, count)
if err != nil {
p.errorf("%v", err)
p.errorf(err.Error())
}
return off
} else {
@@ -771,12 +770,7 @@ func (p *Parser) registerExtension(a *obj.Addr, name string, prefix rune) {
case sys.ARM64:
err := arch.ARM64RegisterExtension(a, ext, reg, num, isAmount, isIndex)
if err != nil {
p.errorf("%v", err)
}
case sys.Loong64:
err := arch.Loong64RegisterExtension(a, ext, reg, num, isAmount, isIndex)
if err != nil {
p.errorf("%v", err)
p.errorf(err.Error())
}
default:
p.errorf("register extension not supported on this architecture")
@@ -1123,7 +1117,7 @@ ListLoop:
ext := tok.String()
curArrangement, err := arch.ARM64RegisterArrangement(reg, name, ext)
if err != nil {
p.errorf("%v", err)
p.errorf(err.Error())
}
if firstReg == -1 {
// only record the first register and arrangement
@@ -1170,7 +1164,7 @@ ListLoop:
case sys.ARM64:
offset, err := arch.ARM64RegisterListOffset(firstReg, regCnt, arrangement)
if err != nil {
p.errorf("%v", err)
p.errorf(err.Error())
}
a.Offset = offset
default:

View File

@@ -1777,7 +1777,6 @@ next:
MSR R17, ZCR_EL1 // 111218d5
SYS $32768, R1 // 018008d5
SYS $32768 // 1f8008d5
MSR $1, DIT // 5f4103d5
// TLBI instruction
TLBI VMALLE1IS // 1f8308d5

View File

@@ -260,7 +260,5 @@ TEXT errors(SB),$0
STREXD R0, (R2), R1 // ERROR "cannot use same register as both source and destination"
STREXD R0, (R2), R2 // ERROR "cannot use same register as both source and destination"
STREXD R1, (R4), R7 // ERROR "must be even"
STREXB R0, (R2), R0 // ERROR "cannot use same register as both source and destination"
STREXB R0, (R2), R2 // ERROR "cannot use same register as both source and destination"
END

View File

@@ -52,10 +52,8 @@ TEXT foo(SB), DUPOK|NOSPLIT, $0
MOVDF F4, F5 // c45bb7ee
LDREX (R8), R9 // 9f9f98e1
LDREXB (R11), R12 // 9fcfdbe1
LDREXD (R11), R12 // 9fcfbbe1
STREX R3, (R4), R5 // STREX (R4), R3, R5 // 935f84e1
STREXB R8, (R9), g // STREXB (R9), R8, g // 98afc9e1
STREXD R8, (R9), g // STREXD (R9), R8, g // 98afa9e1
CMPF F8, F9 // c89ab4ee10faf1ee

View File

@@ -21,11 +21,8 @@ lable2:
MOVW $65536, R4 // 04020014
MOVW $4096, R4 // 24000014
MOVV $65536, R4 // 04020014
MOVB R4, R5 // 855c0000
MOVH R4, R5 // 85580000
MOVV $4096, R4 // 24000014
MOVW R4, R5 // 85001700
MOVWU R4, R5 // 8500df00
MOVV R4, R5 // 85001500
MOVBU R4, R5 // 85fc4303
SUB R4, R5, R6 // a6101100
@@ -52,29 +49,11 @@ lable2:
SLLV R4, R5, R6 // a6901800
ROTRV R4, R5 // a5901b00
ROTRV R4, R5, R6 // a6901b00
CLOW R4, R5 // 85100000
CLZW R4, R5 // 85140000
CTOW R4, R5 // 85180000
CTZW R4, R5 // 851c0000
CLOV R4, R5 // 85200000
CLZV R4, R5 // 85240000
CTOV R4, R5 // 85280000
CTZV R4, R5 // 852c0000
REVB2H R4, R5 // 85300000
REVB4H R4, R5 // 85340000
REVB2W R4, R5 // 85380000
REVBV R4, R5 // 853c0000
REVH2W R4, R5 // 85400000
REVHV R4, R5 // 85440000
BITREV4B R4, R5 // 85480000
BITREVW R4, R5 // 85500000
BITREV8B R4, R5 // 854c0000
BITREVV R4, R5 // 85540000
EXTWB R4, R5 // 855c0000
EXTWH R4, R5 // 85580000
CPUCFG R4, R5 // 856c0000
CLO R4, R5 // 85100000
CLZ R4, R5 // 85140000
ADDF F4, F5 // a5900001
ADDF F4, F5, F6 // a6900001
ADDF F4, R5, F6 // a6900001
CMPEQF F4, R5 // a010120c
ABSF F4, F5 // 85041401
MOVVF F4, F5 // 85181d01
MOVF F4, F5 // 85941401
@@ -84,11 +63,15 @@ lable2:
MOVV R4, result+16(FP) // 6460c029
MOVB R4, result+16(FP) // 64600029
MOVBU R4, result+16(FP) // 64600029
MOVWL R4, result+16(FP) // 6460002f
MOVVL R4, result+16(FP) // 6460802f
MOVW R4, 1(R5) // a4048029
MOVWU R4, 1(R5) // a4048029
MOVV R4, 1(R5) // a404c029
MOVB R4, 1(R5) // a4040029
MOVBU R4, 1(R5) // a4040029
MOVWL R4, 1(R5) // a404002f
MOVVL R4, 1(R5) // a404802f
SC R4, 1(R5) // a4040021
SCV R4, 1(R5) // a4040023
MOVW y+8(FP), R4 // 64408028
@@ -96,11 +79,15 @@ lable2:
MOVV y+8(FP), R4 // 6440c028
MOVB y+8(FP), R4 // 64400028
MOVBU y+8(FP), R4 // 6440002a
MOVWL y+8(FP), R4 // 6440002e
MOVVL y+8(FP), R4 // 6440802e
MOVW 1(R5), R4 // a4048028
MOVWU 1(R5), R4 // a404802a
MOVV 1(R5), R4 // a404c028
MOVB 1(R5), R4 // a4040028
MOVBU 1(R5), R4 // a404002a
MOVWL 1(R5), R4 // a404002e
MOVVL 1(R5), R4 // a404802e
LL 1(R5), R4 // a4040020
LLV 1(R5), R4 // a4040022
MOVW $4(R4), R5 // 8510c002
@@ -137,12 +124,16 @@ lable2:
BNE R4, R0, 1(PC) // 80040044
BNE R0, R4, 1(PC) // 80040044
BLTU R4, 1(PC) // 80040068
MOVW y+8(FP), F4 // 6440002b
MOVF y+8(FP), F4 // 6440002b
MOVD y+8(FP), F4 // 6440802b
MOVW 1(F5), F4 // a404002b
MOVF 1(F5), F4 // a404002b
MOVD 1(F5), F4 // a404802b
MOVW F4, result+16(FP) // 6460402b
MOVF F4, result+16(FP) // 6460402b
MOVD F4, result+16(FP) // 6460c02b
MOVW F4, 1(F5) // a404402b
MOVF F4, 1(F5) // a404402b
MOVD F4, 1(F5) // a404c02b
MOVW R4, F5 // 85a41401
@@ -153,11 +144,6 @@ lable2:
BREAK // 00002a00
UNDEF // 00002a00
ANDN R4, R5, R6 // a6901600
ANDN R4, R5 // a5901600
ORN R4, R5, R6 // a6101600
ORN R4, R5 // a5101600
// mul
MUL R4, R5 // a5101c00
MUL R4, R5, R6 // a6101c00
@@ -211,16 +197,6 @@ lable2:
MASKEQZ R4, R5, R6 // a6101300
MASKNEZ R4, R5, R6 // a6901300
// CRC32
CRCWBW R4, R5, R6 // a6102400
CRCWHW R4, R5, R6 // a6902400
CRCWWW R4, R5, R6 // a6102500
CRCWVW R4, R5, R6 // a6902500
CRCCWBW R4, R5, R6 // a6102600
CRCCWHW R4, R5, R6 // a6902600
CRCCWWW R4, R5, R6 // a6102700
CRCCWVW R4, R5, R6 // a6902700
MOVFD F4, F5 // 85241901
MOVDF F4, F5 // 85181901
MOVWF F4, F5 // 85101d01
@@ -238,21 +214,21 @@ lable2:
DBAR // 00007238
NOOP // 00004003
CMPEQF F4, F5, FCC0 // a010120c
CMPGTF F4, F5, FCC1 // a190110c
CMPGTD F4, F5, FCC2 // a290210c
CMPGEF F4, F5, FCC3 // a390130c
CMPGED F4, F5, FCC4 // a490230c
CMPEQD F4, F5, FCC5 // a510220c
MOVWR R4, result+16(FP) // 6460402f
MOVWR R4, 1(R5) // a404402f
MOVWR y+8(FP), R4 // 6440402e
MOVWR 1(R5), R4 // a404402e
CMPGTF F4, R5 // a090110c
CMPGTD F4, R5 // a090210c
CMPGEF F4, R5 // a090130c
CMPGED F4, R5 // a090230c
CMPEQD F4, R5 // a010220c
RDTIMELW R4, R0 // 80600000
RDTIMEHW R4, R0 // 80640000
RDTIMED R4, R5 // 85680000
MOVV R4, FCSR3 // 83c01401
MOVV FCSR3, R4 // 64c81401
MOVV F4, FCC0 // 80d01401
MOVV FCC0, F4 // 04d41401
MOVV FCC0, R4 // 04dc1401
MOVV R4, FCC0 // 80d81401
@@ -305,214 +281,3 @@ lable2:
AMMAXDBVU R14, (R13), R12 // acb97038
AMMINDBWU R14, (R13), R12 // ac397138
AMMINDBVU R14, (R13), R12 // acb97138
FMADDF F2, F14, F9, F16 // 30391108
FMADDD F11, F20, F23, F12 // ecd22508
FMSUBF F3, F11, F31, F22 // f6af5108
FMSUBD F13, F30, F9, F15 // 2ff96608
FNMADDF F27, F11, F5, F21 // b5ac9d08
FNMADDD F29, F14, F27, F6 // 66bbae08
FNMSUBF F17, F8, F12, F8 // 88a1d808
FNMSUBD F29, F21, F3, F17 // 71d4ee08
FMADDF F2, F14, F9 // 29391108
FMADDD F11, F20, F23 // f7d22508
FMSUBF F3, F11, F31 // ffaf5108
FMSUBD F13, F30, F9 // 29f96608
FNMADDF F27, F11, F5 // a5ac9d08
FNMADDD F29, F14, F27 // 7bbbae08
FNMSUBF F17, F8, F12 // 8ca1d808
FNMSUBD F29, F21, F3 // 63d4ee08
FMINF F4, F5, F6 // a6900a01
FMINF F4, F5 // a5900a01
FMIND F4, F5, F6 // a6100b01
FMIND F4, F5 // a5100b01
FMAXF F4, F5, F6 // a6900801
FMAXF F4, F5 // a5900801
FMAXD F4, F5, F6 // a6100901
FMAXD F4, F5 // a5100901
FCOPYSGF F4, F5, F6 // a6901201
FCOPYSGD F4, F5, F6 // a6101301
FCLASSF F4, F5 // 85341401
FCLASSD F4, F5 // 85381401
FFINTFW F0, F1 // 01101d01
FFINTFV F0, F1 // 01181d01
FFINTDW F0, F1 // 01201d01
FFINTDV F0, F1 // 01281d01
FTINTWF F0, F1 // 01041b01
FTINTWD F0, F1 // 01081b01
FTINTVF F0, F1 // 01241b01
FTINTVD F0, F1 // 01281b01
FTINTRMWF F0, F2 // 02041a01
FTINTRMWD F0, F2 // 02081a01
FTINTRMVF F0, F2 // 02241a01
FTINTRMVD F0, F2 // 02281a01
FTINTRPWF F0, F2 // 02441a01
FTINTRPWD F0, F2 // 02481a01
FTINTRPVF F0, F2 // 02641a01
FTINTRPVD F0, F2 // 02681a01
FTINTRZWF F0, F2 // 02841a01
FTINTRZWD F0, F2 // 02881a01
FTINTRZVF F0, F2 // 02a41a01
FTINTRZVD F0, F2 // 02a81a01
FTINTRNEWF F0, F2 // 02c41a01
FTINTRNEWD F0, F2 // 02c81a01
FTINTRNEVF F0, F2 // 02e41a01
FTINTRNEVD F0, F2 // 02e81a01
// LDX.{B,BU,H,HU,W,WU,D} instructions
MOVB (R14)(R13), R12 // cc350038
MOVBU (R14)(R13), R12 // cc352038
MOVH (R14)(R13), R12 // cc350438
MOVHU (R14)(R13), R12 // cc352438
MOVW (R14)(R13), R12 // cc350838
MOVWU (R14)(R13), R12 // cc352838
MOVV (R14)(R13), R12 // cc350c38
// STX.{B,H,W,D} instructions
MOVB R12, (R14)(R13) // cc351038
MOVH R12, (R14)(R13) // cc351438
MOVW R12, (R14)(R13) // cc351838
MOVV R12, (R14)(R13) // cc351c38
// FLDX.{S,D} instructions
MOVF (R14)(R13), F2 // c2353038
MOVD (R14)(R13), F2 // c2353438
// FSTX.{S,D} instructions
MOVF F2, (R14)(R13) // c2353838
MOVD F2, (R14)(R13) // c2353c38
BSTRINSW $0, R4, $0, R5 // 85006000
BSTRINSW $31, R4, $0, R5 // 85007f00
BSTRINSW $15, R4, $6, R5 // 85186f00
BSTRINSV $0, R4, $0, R5 // 85008000
BSTRINSV $63, R4, $0, R5 // 8500bf00
BSTRINSV $15, R4, $6, R5 // 85188f00
BSTRPICKW $0, R4, $0, R5 // 85806000
BSTRPICKW $31, R4, $0, R5 // 85807f00
BSTRPICKW $15, R4, $6, R5 // 85986f00
BSTRPICKV $0, R4, $0, R5 // 8500c000
BSTRPICKV $63, R4, $0, R5 // 8500ff00
BSTRPICKV $15, R4, $6, R5 // 8518cf00
FSCALEBF F4, F5, F6 // a6901001
FSCALEBD F4, F5, F6 // a6101101
FLOGBF F4, F5 // 85241401
FLOGBD F4, F5 // 85281401
// VSTX/VLDX/XVSTX/XVLDX instructions
VMOVQ V2, (R5)(R5) // a2144438
VMOVQ (R4)(R5), V2 // 82144038
XVMOVQ X2, (R4)(R5) // 82144c38
XVMOVQ (R4)(R5), X2 // 82144838
// VST/VLD/XVST/XVLD instructions
VMOVQ V2, (R4) // 8200402c
VMOVQ V2, 3(R4) // 820c402c
VMOVQ V2, 2040(R4) // 82e05f2c
VMOVQ V2, -2040(R4) // 8220602c
VMOVQ V2, y+16(FP) // 0260402c
VMOVQ V2, x+2030(FP) // 02d85f2c
VMOVQ (R4), V2 // 8200002c
VMOVQ 3(R4), V2 // 820c002c
VMOVQ 2044(R4), V2 // 82f01f2c
VMOVQ -2044(R4), V2 // 8210202c
VMOVQ y+16(FP), V2 // 0260002c
VMOVQ x+2030(FP), V2 // 02d81f2c
XVMOVQ X2, (R4) // 8200c02c
XVMOVQ X3, 3(R4) // 830cc02c
XVMOVQ X4, 2040(R4) // 84e0df2c
XVMOVQ X5, -2040(R4) // 8520e02c
XVMOVQ X6, y+16(FP) // 0660c02c
XVMOVQ X7, x+2030(FP) // 07d8df2c
XVMOVQ (R4), X2 // 8200802c
XVMOVQ 3(R4), X3 // 830c802c
XVMOVQ 2044(R4), X4 // 84f09f2c
XVMOVQ -2044(R4), X5 // 8510a02c
XVMOVQ y+16(FP), X6 // 0660802c
XVMOVQ x+2030(FP), X7 // 07d89f2c
// Move vector element to general-purpose register: VMOVQ <Vn>.<T>[index], Rd
VMOVQ V0.B[0], R4 // 0480ef72
VMOVQ V3.B[3], R5 // 658cef72
VMOVQ V4.H[2], R6 // 86c8ef72
VMOVQ V5.W[2], R7 // a7e8ef72
VMOVQ V6.V[1], R8 // c8f4ef72
VMOVQ V7.BU[0], R4 // e480f372
VMOVQ V7.BU[1], R4 // e484f372
VMOVQ V9.BU[3], R5 // 258df372
VMOVQ V10.HU[2], R6 // 46c9f372
VMOVQ V11.WU[2], R7 // 67e9f372
VMOVQ V31.VU[1], R8 // e8f7f372
XVMOVQ X1.W[2], R7 // 27c8ef76
XVMOVQ X6.V[2], R8 // c8e8ef76
XVMOVQ X8.WU[2], R7 // 07c9f376
XVMOVQ X31.VU[2], R8 // e8ebf376
// Move general-purpose register to a vector element: VMOVQ Rn, <Vd>.<T>[index]
VMOVQ R4, V2.B[0] // 8280eb72
VMOVQ R4, V3.B[1] // 8384eb72
VMOVQ R5, V4.B[3] // a48ceb72
VMOVQ R6, V5.H[2] // c5c8eb72
VMOVQ R7, V6.W[2] // e6e8eb72
VMOVQ R8, V7.V[1] // 07f5eb72
XVMOVQ R7, X9.W[2] // e9c8eb76
XVMOVQ R8, X10.V[2] // 0ae9eb76
// Duplicate general-purpose register to vector
VMOVQ R4, V2.B16 // 82009f72
VMOVQ R5, V3.H8 // a3049f72
VMOVQ R6, V4.W4 // c4089f72
VMOVQ R7, V5.V2 // e50c9f72
XVMOVQ R16, X31.B32 // 1f029f76
XVMOVQ R17, X28.H16 // 3c069f76
XVMOVQ R18, X10.W8 // 4a0a9f76
XVMOVQ R19, X9.V4 // 690e9f76
// Move vector
XVMOVQ X0, X31.B32 // 1f000777
XVMOVQ X1, X30.H16 // 3e800777
XVMOVQ X2, X29.W8 // 5dc00777
XVMOVQ X3, X28.V4 // 7ce00777
XVMOVQ X3, X27.Q2 // 7bf00777
// Move vector element to scalar.
XVMOVQ X0, X31.W[7] // 1fdcff76
XVMOVQ X1, X29.W[0] // 3dc0ff76
XVMOVQ X3, X28.V[3] // 7cecff76
XVMOVQ X4, X27.V[0] // 9be0ff76
XVMOVQ X31.W[7], X0 // e0df0377
XVMOVQ X29.W[0], X1 // a1c30377
XVMOVQ X28.V[3], X8 // 88ef0377
XVMOVQ X27.V[0], X9 // 69e30377
//Move vector element to vector.
VMOVQ V1.B[3], V9.B16 // 298cf772
VMOVQ V2.H[2], V8.H8 // 48c8f772
VMOVQ V3.W[1], V7.W4 // 67e4f772
VMOVQ V4.V[0], V6.V2 // 86f0f772
// VSEQ{B,H,W,V}, XVSEQ{B,H,W,V} instruction
VSEQB V1, V2, V3 // 43040070
VSEQH V1, V2, V3 // 43840070
VSEQW V1, V2, V3 // 43040170
VSEQV V1, V2, V3 // 43840170
XVSEQB X3, X2, X4 // 440c0074
XVSEQH X3, X2, X4 // 448c0074
XVSEQW X3, X2, X4 // 440c0174
XVSEQV X3, X2, X4 // 448c0174
// VPCNT{B,H,W,V}, XVPCNT{B,H,W,V} instruction
VPCNTB V1, V2 // 22209c72
VPCNTH V1, V2 // 22249c72
VPCNTW V1, V2 // 22289c72
VPCNTV V1, V2 // 222c9c72
XVPCNTB X3, X2 // 62209c76
XVPCNTH X3, X2 // 62249c76
XVPCNTW X3, X2 // 62289c76
XVPCNTV X3, X2 // 622c9c76

View File

@@ -5,6 +5,8 @@
#include "../../../../../runtime/textflag.h"
TEXT asmtest(SB),DUPOK|NOSPLIT,$0
MOVB R4, R5 // 85e04000a5e04800
MOVWU R4, R5 // 85804100a5804500
MOVW $74565, R4 // 4402001484148d03
MOVW $4097, R4 // 2400001484048003
MOVV $74565, R4 // 4402001484148d03
@@ -57,6 +59,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
XOR $4096, R4 // 3e00001484f81500
XOR $-1, R4, R5 // 1efcbf0285f81500
XOR $-1, R4 // 1efcbf0284f81500
MOVH R4, R5 // 85c04000a5c04800
// relocation instructions
MOVW R4, name(SB) // 1e00001ac4038029

View File

@@ -64,20 +64,28 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
MOVV 4096(R5), R4 // 3e000014de971000c403c028
MOVB 4096(R5), R4 // 3e000014de971000c4030028
MOVBU 4096(R5), R4 // 3e000014de971000c403002a
MOVW y+65540(FP), F4 // 1e020014de8f1000c433002b
MOVF y+65540(FP), F4 // 1e020014de8f1000c433002b
MOVD y+65540(FP), F4 // 1e020014de8f1000c433802b
MOVW y+4097(FP), F4 // 3e000014de8f1000c427002b
MOVF y+4097(FP), F4 // 3e000014de8f1000c427002b
MOVD y+4097(FP), F4 // 3e000014de8f1000c427802b
MOVW 65536(R5), F4 // 1e020014de971000c403002b
MOVF 65536(R5), F4 // 1e020014de971000c403002b
MOVD 65536(R5), F4 // 1e020014de971000c403802b
MOVW 4096(R5), F4 // 3e000014de971000c403002b
MOVF 4096(R5), F4 // 3e000014de971000c403002b
MOVD 4096(R5), F4 // 3e000014de971000c403802b
MOVW F4, result+65540(FP) // 1e020014de8f1000c433402b
MOVF F4, result+65540(FP) // 1e020014de8f1000c433402b
MOVD F4, result+65540(FP) // 1e020014de8f1000c433c02b
MOVW F4, result+4097(FP) // 3e000014de8f1000c427402b
MOVF F4, result+4097(FP) // 3e000014de8f1000c427402b
MOVD F4, result+4097(FP) // 3e000014de8f1000c427c02b
MOVW F4, 65536(R5) // 1e020014de971000c403402b
MOVF F4, 65536(R5) // 1e020014de971000c403402b
MOVD F4, 65536(R5) // 1e020014de971000c403c02b
MOVW F4, 4096(R5) // 3e000014de971000c403402b
MOVF F4, 4096(R5) // 3e000014de971000c403402b
MOVD F4, 4096(R5) // 3e000014de971000c403c02b

View File

@@ -508,26 +508,17 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
BEQ 0(PC) // 41820000
BEQ CR1,0(PC) // 41860000
BEQ CR0, LR // 4d820020
BEQ CR7, LR // 4d9e0020
BGE 0(PC) // 40800000
BGE CR2,0(PC) // 40880000
BGE CR6,LR // 4c980020
BGT 4(PC) // 41810010
BGT CR3,4(PC) // 418d0010
BGT CR6, LR // 4d990020
BLE 0(PC) // 40810000
BLE CR4,0(PC) // 40910000
BLE CR6, LR // 4c990020
BLT 0(PC) // 41800000
BLT CR5,0(PC) // 41940000
BNE 0(PC) // 40820000
BNE CR6, LR // 4c9a0020
BLT CR6,0(PC) // 41980000
BLT CR6, LR // 4d980020
BVC 0(PC) // 40830000
BVC CR6, LR // 4c9b0020
BVS CR6, LR // 4d9b0020
BVS 0(PC) // 41830000
JMP 8(PC) // 48000010
@@ -690,17 +681,9 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
FMOVDCC F1, F2 // fc400891
FADDS F1, F2 // ec42082a
FADDS F1, F2, F3 // ec62082a
DADD F1, F2 // ec420804
DADD F1, F2, F3 // ec620804
DADDQ F2, F4 // fc841004
DADDQ F2, F4, F6 // fcc41004
FADDSCC F1, F2, F3 // ec62082b
FSUB F1, F2 // fc420828
FSUB F1, F2, F3 // fc620828
DSUB F1, F2 // ec420c04
DSUB F1, F2, F3 // ec620c04
DSUBQ F2, F4 // fc841404
DSUBQ F2, F4, F6 // fcc41404
FSUBCC F1, F2, F3 // fc620829
FSUBS F1, F2 // ec420828
FSUBS F1, F2, F3 // ec620828
@@ -708,20 +691,12 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
FSUBSCC F1, F2, F3 // ec620829
FMUL F1, F2 // fc420072
FMUL F1, F2, F3 // fc620072
DMUL F1, F2 // ec420044
DMUL F1, F2, F3 // ec620044
DMULQ F2, F4 // fc8400c4
DMULQ F2, F4, F6 // fcc400c4
FMULCC F1, F2, F3 // fc620073
FMULS F1, F2 // ec420072
FMULS F1, F2, F3 // ec620072
FMULSCC F1, F2, F3 // ec620073
FDIV F1, F2 // fc420824
FDIV F1, F2, F3 // fc620824
DDIV F1, F2 // ec420c44
DDIV F1, F2, F3 // ec620c44
DDIVQ F2, F4 // fc841444
DDIVQ F2, F4, F6 // fcc41444
FDIVCC F1, F2, F3 // fc620825
FDIVS F1, F2 // ec420824
FDIVS F1, F2, F3 // ec620824
@@ -788,17 +763,9 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
FCPSGN F1, F2 // fc420810
FCPSGNCC F1, F2 // fc420811
FCMPO F1, F2 // fc011040
FCMPO F1, F2, CR0 // FCMPO F1,CR0,F2 // fc011040
FCMPO F1, F2, CR0 // FCMPO F1,CR0,F2 // fc011040
FCMPU F1, F2 // fc011000
FCMPU F1, F2, CR0 // FCMPU F1,CR0,F2 // fc011000
DCMPO F1, F2 // ec011104
DCMPO F1, F2, CR0 // DCMPO F1,CR0,F2 // ec011104
DCMPOQ F2, F4 // fc022104
DCMPOQ F2,F4, CR0 // DCMPOQ F2,CR0,F4 // fc022104
DCMPU F1, F2 // ec011504
DCMPU F1, F2, CR0 // DCMPU F1,CR0,F2 // ec011504
DCMPUQ F2, F4 // fc022504
DCMPUQ F2,F4, CR0 // DCMPUQ F2,CR0,F4 // fc022504
FCMPU F1, F2, CR0 // FCMPU F1,CR0,F2 // fc011000
LVX (R3)(R4), V1 // 7c2418ce
LVX (R3)(R0), V1 // 7c2018ce
LVX (R3), V1 // 7c2018ce
@@ -1189,8 +1156,6 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
MOVD 4(R1), SPR(3) // ebe100047fe303a6
MOVD 4(R1), XER // ebe100047fe103a6
OR $0, R0, R0 // 60000000
PCALIGN $16
PNOP // 0700000000000000
SETB CR1,R3 // 7c640100

View File

@@ -6,9 +6,7 @@
TEXT asmtest(SB),DUPOK|NOSPLIT,$0
start:
//
// Unprivileged ISA
//
// 2.4: Integer Computational Instructions
@@ -141,7 +139,7 @@ start:
// 2.7: Memory Ordering Instructions
FENCE // 0f00f00f
// 4.2: Integer Computational Instructions (RV64I)
// 5.2: Integer Computational Instructions (RV64I)
ADDIW $1, X5, X6 // 1b831200
SLLIW $1, X5, X6 // 1b931200
SRLIW $1, X5, X6 // 1bd31200
@@ -166,25 +164,18 @@ start:
SUBW $1, X6 // 1b03f3ff
SRAW $1, X6 // 1b531340
// 4.3: Load and Store Instructions (RV64I)
// 5.3: Load and Store Instructions (RV64I)
LD (X5), X6 // 03b30200
LD 4(X5), X6 // 03b34200
SD X5, (X6) // 23305300
SD X5, 4(X6) // 23325300
// 8.1: Base Counters and Timers (Zicntr)
RDCYCLE X5 // f32200c0
RDTIME X5 // f32210c0
RDINSTRET X5 // f32220c0
// 13.1: Multiplication Operations
// 7.1: Multiplication Operations
MUL X5, X6, X7 // b3035302
MULH X5, X6, X7 // b3135302
MULHU X5, X6, X7 // b3335302
MULHSU X5, X6, X7 // b3235302
MULW X5, X6, X7 // bb035302
// 13.2: Division Operations
DIV X5, X6, X7 // b3435302
DIVU X5, X6, X7 // b3535302
REM X5, X6, X7 // b3635302
@@ -194,13 +185,13 @@ start:
REMW X5, X6, X7 // bb635302
REMUW X5, X6, X7 // bb735302
// 14.2: Load-Reserved/Store-Conditional (Zalrsc)
// 8.2: Load-Reserved/Store-Conditional
LRW (X5), X6 // 2fa30214
LRD (X5), X6 // 2fb30214
SCW X5, (X6), X7 // af23531a
SCD X5, (X6), X7 // af33531a
// 14.4: Atomic Memory Operations (Zaamo)
// 8.3: Atomic Memory Operations
AMOSWAPW X5, (X6), X7 // af23530e
AMOSWAPD X5, (X6), X7 // af33530e
AMOADDW X5, (X6), X7 // af235306
@@ -220,13 +211,18 @@ start:
AMOMINUW X5, (X6), X7 // af2353c6
AMOMINUD X5, (X6), X7 // af3353c6
// 20.5: Single-Precision Load and Store Instructions
// 10.1: Base Counters and Timers
RDCYCLE X5 // f32200c0
RDTIME X5 // f32210c0
RDINSTRET X5 // f32220c0
// 11.5: Single-Precision Load and Store Instructions
FLW (X5), F0 // 07a00200
FLW 4(X5), F0 // 07a04200
FSW F0, (X5) // 27a00200
FSW F0, 4(X5) // 27a20200
// 20.6: Single-Precision Floating-Point Computational Instructions
// 11.6: Single-Precision Floating-Point Computational Instructions
FADDS F1, F0, F2 // 53011000
FSUBS F1, F0, F2 // 53011008
FMULS F1, F0, F2 // 53011010
@@ -235,7 +231,7 @@ start:
FMAXS F1, F0, F2 // 53111028
FSQRTS F0, F1 // d3000058
// 20.7: Single-Precision Floating-Point Conversion and Move Instructions
// 11.7: Single-Precision Floating-Point Conversion and Move Instructions
FCVTWS F0, X5 // d31200c0
FCVTWS.RNE F0, X5 // d30200c0
FCVTWS.RTZ F0, X5 // d31200c0
@@ -276,21 +272,21 @@ start:
FNMSUBS F1, F2, F3, F4 // 4b822018
FNMADDS F1, F2, F3, F4 // 4f822018
// 20.8: Single-Precision Floating-Point Compare Instructions
// 11.8: Single-Precision Floating-Point Compare Instructions
FEQS F0, F1, X7 // d3a300a0
FLTS F0, F1, X7 // d39300a0
FLES F0, F1, X7 // d38300a0
// 20.9: Single-Precision Floating-Point Classify Instruction
// 11.9: Single-Precision Floating-Point Classify Instruction
FCLASSS F0, X5 // d31200e0
// 21.3: Double-Precision Load and Store Instructions
// 12.3: Double-Precision Load and Store Instructions
FLD (X5), F0 // 07b00200
FLD 4(X5), F0 // 07b04200
FSD F0, (X5) // 27b00200
FSD F0, 4(X5) // 27b20200
// 21.4: Double-Precision Floating-Point Computational Instructions
// 12.4: Double-Precision Floating-Point Computational Instructions
FADDD F1, F0, F2 // 53011002
FSUBD F1, F0, F2 // 5301100a
FMULD F1, F0, F2 // 53011012
@@ -299,7 +295,7 @@ start:
FMAXD F1, F0, F2 // 5311102a
FSQRTD F0, F1 // d300005a
// 21.5: Double-Precision Floating-Point Conversion and Move Instructions
// 12.5: Double-Precision Floating-Point Conversion and Move Instructions
FCVTWD F0, X5 // d31200c2
FCVTWD.RNE F0, X5 // d30200c2
FCVTWD.RTZ F0, X5 // d31200c2
@@ -340,10 +336,11 @@ start:
FNMSUBD F1, F2, F3, F4 // 4b82201a
FNMADDD F1, F2, F3, F4 // 4f82201a
// 21.7: Double-Precision Floating-Point Classify Instruction
// 12.6: Double-Precision Floating-Point Classify Instruction
FCLASSD F0, X5 // d31200e2
// 28.4.1: Address Generation Instructions (Zba)
// RISC-V Bit-Manipulation ISA-extensions (1.0)
// 1.1: Address Generation Instructions (Zba)
ADDUW X10, X11, X12 // 3b86a508
ADDUW X10, X11 // bb85a508
SH1ADD X11, X12, X13 // b326b620
@@ -363,9 +360,9 @@ start:
SLLIUW $63, X17, X18 // 1b99f80b
SLLIUW $1, X18, X19 // 9b191908
// 28.4.2: Basic Bit Manipulation (Zbb)
ANDN X19, X20, X21 // b37a3a41 or 93caf9ffb37a5a01
ANDN X19, X20 // 337a3a41 or 93cff9ff337afa01
// 1.2: Basic Bit Manipulation (Zbb)
ANDN X19, X20, X21 // b37a3a41
ANDN X19, X20 // 337a3a41
CLZ X20, X21 // 931a0a60
CLZW X21, X22 // 1b9b0a60
CPOP X22, X23 // 931b2b60
@@ -380,15 +377,15 @@ start:
MIN X29, X30 // 334fdf0b
MINU X30, X5, X6 // 33d3e20b
MINU X30, X5 // b3d2e20b
ORN X6, X7, X8 // 33e46340 or 1344f3ff33e48300
ORN X6, X7 // b3e36340 or 934ff3ffb3e3f301
ORN X6, X7, X8 // 33e46340
ORN X6, X7 // b3e36340
SEXTB X16, X17 // 93184860
SEXTH X17, X18 // 13995860
XNOR X18, X19, X20 // 33ca2941 or 33ca2901134afaff
XNOR X18, X19 // b3c92941 or b3c9290193c9f9ff
XNOR X18, X19, X20 // 33ca2941
XNOR X18, X19 // b3c92941
ZEXTH X19, X20 // 3bca0908
// 28.4.2: Bitwise Rotation (Zbb)
// 1.3: Bitwise Rotation (Zbb)
ROL X8, X9, X10 // 33958460 or b30f8040b3dff4013395840033e5af00
ROL X8, X9 // b3948460 or b30f8040b3dff401b3948400b3e49f00
ROLW X9, X10, X11 // bb159560 or b30f9040bb5ff501bb159500b3e5bf00
@@ -406,7 +403,7 @@ start:
ORCB X5, X6 // 13d37228
REV8 X7, X8 // 13d4836b
// 28.4.4: Single-bit Instructions (Zbs)
// 1.5: Single-bit Instructions (Zbs)
BCLR X23, X24, X25 // b31c7c49
BCLR $63, X24 // 131cfc4b
BCLRI $1, X25, X26 // 139d1c48
@@ -420,11 +417,9 @@ start:
BSET $63, X9 // 9394f42b
BSETI $1, X10, X11 // 93151528
//
// Privileged ISA
//
// 3.3.1: Environment Call and Breakpoint
// 3.2.1: Environment Call and Breakpoint
ECALL // 73000000
SCALL // 73000000
EBREAK // 73001000

View File

@@ -520,20 +520,7 @@ TEXT main·foo(SB),DUPOK|NOSPLIT,$16-0 // TEXT main.foo(SB), DUPOK|NOSPLIT, $16-
VSUMQF V4, V5, V6 // e76450002067
VSUMQG V19, V20, V21 // e75340003e67
VSUMB V7, V8, V9 // e79780000064
VSUMH V22, V23, V24 // e78670001e64
VSTRC V18, V20, V22, V24 // e78240006f8a
VSTRCB V18, V20, V22, V24 // e78240006f8a
VSTRCH V18, V20, V22, V24 // e78241006f8a
VSTRCF V18, V20, V22, V24 // e78242006f8a
VSTRCBS V18, V20, V22, V24 // e78240106f8a
VSTRCHS V18, V20, V22, V24 // e78241106f8a
VSTRCFS V18, V20, V22, V24 // e78242106f8a
VSTRCZB V18, V20, V22, V24 // e78240206f8a
VSTRCZH V18, V20, V22, V24 // e78241206f8a
VSTRCZF V18, V20, V22, V24 // e78242206f8a
VSTRCZBS V18, V20, V22, V24 // e78240306f8a
VSTRCZHS V18, V20, V22, V24 // e78241306f8a
VSTRCZFS V18, V20, V22, V24 // e78242306f8a
VSUMH V22, V23, V24 // e78670001e64
RET
RET foo(SB)

View File

@@ -8,7 +8,6 @@ import (
"fmt"
"os"
"path/filepath"
"slices"
"strconv"
"strings"
"text/scanner"
@@ -253,7 +252,7 @@ func (in *Input) macroDefinition(name string) ([]string, []Token) {
in.Error("bad syntax in definition for macro:", name)
}
arg := in.Stack.Text()
if slices.Contains(args, arg) {
if i := lookup(args, arg); i >= 0 {
in.Error("duplicate argument", arg, "in definition for macro:", name)
}
args = append(args, arg)
@@ -281,6 +280,15 @@ func (in *Input) macroDefinition(name string) ([]string, []Token) {
return args, tokens
}
func lookup(args []string, arg string) int {
for i, a := range args {
if a == arg {
return i
}
}
return -1
}
// invokeMacro pushes onto the input Stack a Slice that holds the macro definition with the actual
// parameters substituted for the formals.
// Invoking a macro does not touch the PC/line history.

View File

@@ -181,7 +181,7 @@ func (f *File) ParseGo(abspath string, src []byte) {
// Like ast.CommentGroup's Text method but preserves
// leading blank lines, so that line numbers line up.
func commentText(g *ast.CommentGroup) string {
pieces := make([]string, 0, len(g.List))
var pieces []string
for _, com := range g.List {
c := com.Text
// Remove comment markers.

View File

@@ -163,14 +163,10 @@ type in Go are instead represented by a uintptr. See the Special
cases section below.
To access a struct, union, or enum type directly, prefix it with
struct_, union_, or enum_, as in C.struct_stat. The size of any C type
T is available as C.sizeof_T, as in C.sizeof_struct_stat. These
special prefixes means that there is no way to directly reference a C
identifier that starts with "struct_", "union_", "enum_", or
"sizeof_", such as a function named "struct_function".
A workaround is to use a "#define" in the preamble, as in
"#define c_struct_function struct_function" and then in the
Go code refer to "C.c_struct_function".
struct_, union_, or enum_, as in C.struct_stat.
The size of any C type T is available as C.sizeof_T, as in
C.sizeof_struct_stat.
A C function may be declared in the Go file with a parameter type of
the special name _GoString_. This function may be called with an
@@ -209,17 +205,6 @@ function returns void). For example:
_, err := C.voidFunc()
var n, err = C.sqrt(1)
Note that the C errno value may be non-zero, and thus the err result may be
non-nil, even if the function call is successful. Unlike normal Go conventions,
you should first check whether the call succeeded before checking the error
result. For example:
n, err := C.setenv(key, value, 1)
if n != 0 {
// we know the call failed, so it is now valid to use err
return err
}
Calling C function pointers is currently not supported, however you can
declare Go variables which hold C function pointers and pass them
back and forth between Go and C. C code may call function pointers
@@ -358,12 +343,12 @@ determined by how the memory was allocated; it has nothing to do with
the type of the pointer.
Note that values of some Go types, other than the type's zero value,
always include Go pointers. This is true of interface, channel, map,
and function types. A pointer type may hold a Go pointer or a C pointer.
Array, slice, string, and struct types may or may not include Go pointers,
depending on their type and how they are constructed. All the discussion
below about Go pointers applies not just to pointer types,
but also to other types that include Go pointers.
always include Go pointers. This is true of string, slice, interface,
channel, map, and function types. A pointer type may hold a Go pointer
or a C pointer. Array and struct types may or may not include Go
pointers, depending on the element types. All the discussion below
about Go pointers applies not just to pointer types, but also to other
types that include Go pointers.
All Go pointers passed to C must point to pinned Go memory. Go pointers
passed as function arguments to C functions have the memory they point to
@@ -436,30 +421,6 @@ passing uninitialized C memory to Go code if the Go code is going to
store pointer values in it. Zero out the memory in C before passing it
to Go.
# Optimizing calls of C code
When passing a Go pointer to a C function the compiler normally ensures
that the Go object lives on the heap. If the C function does not keep
a copy of the Go pointer, and never passes the Go pointer back to Go code,
then this is unnecessary. The #cgo noescape directive may be used to tell
the compiler that no Go pointers escape via the named C function.
If the noescape directive is used and the C function does not handle the
pointer safely, the program may crash or see memory corruption.
For example:
// #cgo noescape cFunctionName
When a Go function calls a C function, it prepares for the C function to
call back to a Go function. The #cgo nocallback directive may be used to
tell the compiler that these preparations are not necessary.
If the nocallback directive is used and the C function does call back into
Go code, the program will panic.
For example:
// #cgo nocallback cFunctionName
# Special cases
A few special C types which would normally be represented by a pointer
@@ -545,6 +506,15 @@ The following options are available when running cgo directly:
If there are any exported functions, write the
generated export declarations to file.
C code can #include this to see the declarations.
-importpath string
The import path for the Go package. Optional; used for
nicer comments in the generated files.
-import_runtime_cgo
If set (which it is by default) import runtime/cgo in
generated output.
-import_syscall
If set (which it is by default) import syscall in
generated output.
-gccgo
Generate output for the gccgo compiler rather than the
gc compiler.
@@ -559,25 +529,12 @@ The following options are available when running cgo directly:
Write out input file in Go syntax replacing C package
names with real values. Used to generate files in the
syscall package when bootstrapping a new target.
-importpath string
The import path for the Go package. Optional; used for
nicer comments in the generated files.
-import_runtime_cgo
If set (which it is by default) import runtime/cgo in
generated output.
-import_syscall
If set (which it is by default) import syscall in
generated output.
-ldflags flags
Flags to pass to the C linker. The cmd/go tool uses
this to pass in the flags in the CGO_LDFLAGS variable.
-objdir directory
Put all generated files in directory.
-srcdir directory
Find the Go input files, listed on the command line,
in directory.
-trimpath rewrites
Apply trims and rewrites to source file paths.
*/
package main

View File

@@ -24,7 +24,6 @@ import (
"math"
"os"
"os/exec"
"slices"
"strconv"
"strings"
"unicode"
@@ -59,17 +58,17 @@ func cname(s string) string {
return t
}
if t, ok := strings.CutPrefix(s, "struct_"); ok {
return "struct " + t
if strings.HasPrefix(s, "struct_") {
return "struct " + s[len("struct_"):]
}
if t, ok := strings.CutPrefix(s, "union_"); ok {
return "union " + t
if strings.HasPrefix(s, "union_") {
return "union " + s[len("union_"):]
}
if t, ok := strings.CutPrefix(s, "enum_"); ok {
return "enum " + t
if strings.HasPrefix(s, "enum_") {
return "enum " + s[len("enum_"):]
}
if t, ok := strings.CutPrefix(s, "sizeof_"); ok {
return "sizeof(" + cname(t) + ")"
if strings.HasPrefix(s, "sizeof_") {
return "sizeof(" + cname(s[len("sizeof_"):]) + ")"
}
return s
}
@@ -95,8 +94,10 @@ func (f *File) ProcessCgoDirectives() {
directive := fields[1]
funcName := fields[2]
if directive == "nocallback" {
fatalf("#cgo nocallback disabled until Go 1.23")
f.NoCallbacks[funcName] = true
} else if directive == "noescape" {
fatalf("#cgo noescape disabled until Go 1.23")
f.NoEscapes[funcName] = true
}
}
@@ -194,6 +195,7 @@ func (p *Package) Translate(f *File) {
var conv typeConv
conv.Init(p.PtrSize, p.IntSize)
p.loadDefines(f)
p.typedefs = map[string]bool{}
p.typedefList = nil
numTypedefs := -1
@@ -233,14 +235,12 @@ func (p *Package) Translate(f *File) {
// loadDefines coerces gcc into spitting out the #defines in use
// in the file f and saves relevant renamings in f.Name[name].Define.
// Returns true if env:CC is Clang
func (f *File) loadDefines(gccOptions []string) bool {
func (p *Package) loadDefines(f *File) {
var b bytes.Buffer
b.WriteString(builtinProlog)
b.WriteString(f.Preamble)
stdout := gccDefines(b.Bytes(), gccOptions)
stdout := p.gccDefines(b.Bytes())
var gccIsClang bool
for _, line := range strings.Split(stdout, "\n") {
if len(line) < 9 || line[0:7] != "#define" {
continue
@@ -263,7 +263,7 @@ func (f *File) loadDefines(gccOptions []string) bool {
}
if key == "__clang__" {
gccIsClang = true
p.GccIsClang = true
}
if n := f.Name[key]; n != nil {
@@ -273,7 +273,6 @@ func (f *File) loadDefines(gccOptions []string) bool {
n.Define = val
}
}
return gccIsClang
}
// guessKinds tricks gcc into revealing the kind of each
@@ -490,7 +489,7 @@ func (p *Package) guessKinds(f *File) []*Name {
// Don't report an error, and skip adding n to the needType array.
continue
}
error_(f.NamePos[n], "could not determine what C.%s refers to", fixGo(n.Go))
error_(f.NamePos[n], "could not determine kind of name for C.%s", fixGo(n.Go))
case notStrLiteral | notType:
n.Kind = "iconst"
case notIntConst | notStrLiteral | notType:
@@ -782,13 +781,16 @@ func (p *Package) mangleName(n *Name) {
}
func (f *File) isMangledName(s string) bool {
t, ok := strings.CutPrefix(s, "_C")
if !ok {
return false
prefix := "_C"
if strings.HasPrefix(s, prefix) {
t := s[len(prefix):]
for _, k := range nameKinds {
if strings.HasPrefix(t, k+"_") {
return true
}
}
}
return slices.ContainsFunc(nameKinds, func(k string) bool {
return strings.HasPrefix(t, k+"_")
})
return false
}
// rewriteCalls rewrites all calls that pass pointers to check that
@@ -1048,9 +1050,12 @@ func (p *Package) hasPointer(f *File, t ast.Expr, top bool) bool {
}
return p.hasPointer(f, t.Elt, top)
case *ast.StructType:
return slices.ContainsFunc(t.Fields.List, func(field *ast.Field) bool {
return p.hasPointer(f, field.Type, top)
})
for _, field := range t.Fields.List {
if p.hasPointer(f, field.Type, top) {
return true
}
}
return false
case *ast.StarExpr: // Pointer type.
if !top {
return true
@@ -1719,7 +1724,7 @@ func checkGCCBaseCmd() ([]string, error) {
}
// gccMachine returns the gcc -m flag to use, either "-m32", "-m64" or "-marm".
func gccMachine() []string {
func (p *Package) gccMachine() []string {
switch goarch {
case "amd64":
if goos == "darwin" {
@@ -1792,7 +1797,7 @@ func (p *Package) gccCmd() []string {
}
c = append(c, p.GccOptions...)
c = append(c, gccMachine()...)
c = append(c, p.gccMachine()...)
if goos == "aix" {
c = append(c, "-maix64")
c = append(c, "-mcmodel=large")
@@ -1833,8 +1838,8 @@ func (p *Package) gccDebug(stdin []byte, nnames int) (d *dwarf.Data, ints []int6
if strings.HasPrefix(s, "___") {
s = s[1:]
}
if t, ok := strings.CutPrefix(s, "__cgodebug_strlen__"); ok {
if n, err := strconv.Atoi(t); err == nil {
if strings.HasPrefix(s, "__cgodebug_strlen__") {
if n, err := strconv.Atoi(s[len("__cgodebug_strlen__"):]); err == nil {
return n
}
}
@@ -2184,10 +2189,10 @@ func (p *Package) gccDebug(stdin []byte, nnames int) (d *dwarf.Data, ints []int6
// and returns the corresponding standard output, which is the
// #defines that gcc encountered while processing the input
// and its included files.
func gccDefines(stdin []byte, gccOptions []string) string {
func (p *Package) gccDefines(stdin []byte) string {
base := append(gccBaseCmd, "-E", "-dM", "-xc")
base = append(base, gccMachine()...)
stdout, _ := runGcc(stdin, append(append(base, gccOptions...), "-"))
base = append(base, p.gccMachine()...)
stdout, _ := runGcc(stdin, append(append(base, p.GccOptions...), "-"))
return stdout
}
@@ -3197,9 +3202,12 @@ func (c *typeConv) dwarfHasPointer(dt dwarf.Type, pos token.Pos) bool {
return c.dwarfHasPointer(dt.Type, pos)
case *dwarf.StructType:
return slices.ContainsFunc(dt.Field, func(f *dwarf.StructField) bool {
return c.dwarfHasPointer(f.Type, pos)
})
for _, f := range dt.Field {
if c.dwarfHasPointer(f.Type, pos) {
return true
}
}
return false
case *dwarf.TypedefType:
if dt.Name == "_GoString_" || dt.Name == "_GoBytes_" {

View File

@@ -69,11 +69,11 @@ func testCallbackCallersSEH(t *testing.T) {
want := []string{
"test._Cfunc_backtrace",
"test.testCallbackCallersSEH.func1.1",
// "test.testCallbackCallersSEH.func1", // hidden by inlining
"test.testCallbackCallersSEH.func1",
"test.goCallback",
"test._Cfunc_callback",
"test.nestedCall.func1",
// "test.nestedCall", // hidden by inlining
"test.nestedCall",
"test.testCallbackCallersSEH",
"test.TestCallbackCallersSEH",
}
@@ -84,7 +84,6 @@ func testCallbackCallersSEH(t *testing.T) {
})
got := make([]string, 0, n)
for i := 0; i < n; i++ {
// This test is brittle in the face of inliner changes
f := runtime.FuncForPC(pc[i] - 1)
if f == nil {
continue

View File

@@ -117,8 +117,8 @@ int add(int x, int y) {
// escape vs noescape
#cgo noescape handleGoStringPointerNoescape
#cgo nocallback handleGoStringPointerNoescape
// TODO(#56378): enable in Go 1.23:
// #cgo noescape handleGoStringPointerNoescape
void handleGoStringPointerNoescape(void *s) {}
void handleGoStringPointerEscape(void *s) {}
@@ -959,7 +959,6 @@ import "C"
import (
"context"
"fmt"
"internal/asan"
"math"
"math/rand"
"os"
@@ -1774,9 +1773,6 @@ func issue8331a() C.issue8331 {
// issue 10303
func test10303(t *testing.T, n int) {
if asan.Enabled {
t.Skip("variable z is heap-allocated due to extra allocations with -asan; see #70079")
}
if runtime.Compiler == "gccgo" {
t.Skip("gccgo permits C pointers on the stack")
}

View File

@@ -41,16 +41,16 @@ func (v *Visitor) Visit(node ast.Node) ast.Visitor {
var errorMessage strings.Builder
for caseIndex, expectedPos := range expectedPositions {
actualPosition := v.fset.PositionFor(ident.Pos(), true)
errorOccurred := false
errorOccured := false
if expectedPos.Line != actualPosition.Line {
fmt.Fprintf(&errorMessage, "wrong line number for ident %s: expected: %d got: %d\n", ident.Name, expectedPos.Line, actualPosition.Line)
errorOccurred = true
errorOccured = true
}
if expectedPos.Column != actualPosition.Column {
fmt.Fprintf(&errorMessage, "wrong column number for ident %s: expected: %d got: %d\n", ident.Name, expectedPos.Column, actualPosition.Column)
errorOccurred = true
errorOccured = true
}
if errorOccurred {
if errorOccured {
continue
}
gotMatch = true
@@ -58,7 +58,7 @@ func (v *Visitor) Visit(node ast.Node) ast.Visitor {
}
if !gotMatch {
v.t.Error(errorMessage.String())
v.t.Errorf(errorMessage.String())
}
}
}

View File

@@ -60,23 +60,19 @@ func check(t *testing.T, file string) {
if len(errors) == 0 {
t.Fatalf("cannot find ERROR HERE")
}
expect(t, errors, file)
expect(t, file, errors)
})
}
func expect(t *testing.T, errors []*regexp.Regexp, files ...string) {
func expect(t *testing.T, file string, errors []*regexp.Regexp) {
dir, err := os.MkdirTemp("", filepath.Base(t.Name()))
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(dir)
dst := filepath.Join(dir, strings.TrimSuffix(files[0], ".go"))
args := []string{"build", "-gcflags=-L -e", "-o=" + dst} // TODO(gri) no need for -gcflags=-L if go tool is adjusted
for _, file := range files {
args = append(args, path(file))
}
cmd := exec.Command("go", args...)
dst := filepath.Join(dir, strings.TrimSuffix(file, ".go"))
cmd := exec.Command("go", "build", "-gcflags=-L -e", "-o="+dst, path(file)) // TODO(gri) no need for -gcflags=-L if go tool is adjusted
out, err := cmd.CombinedOutput()
if err == nil {
t.Errorf("expected cgo to fail but it succeeded")
@@ -132,7 +128,6 @@ func TestReportsTypeErrors(t *testing.T) {
"issue50710.go",
"issue67517.go",
"issue67707.go",
"issue69176.go",
} {
check(t, file)
}
@@ -185,13 +180,3 @@ func TestNotMatchedCFunction(t *testing.T) {
file := "notmatchedcfunction.go"
check(t, file)
}
func TestIncompatibleDeclarations(t *testing.T) {
testenv.MustHaveCGO(t)
testenv.MustHaveGoRun(t)
t.Parallel()
expect(t, []*regexp.Regexp{
regexp.MustCompile("inconsistent definitions for C[.]f"),
regexp.MustCompile("inconsistent definitions for C[.]g"),
}, "issue67699a.go", "issue67699b.go")
}

View File

@@ -472,23 +472,6 @@ var ptrTests = []ptrTest{
body: `s := struct { a [4]byte; p *int }{p: new(int)}; C.f43(unsafe.Pointer(unsafe.SliceData(s.a[:])))`,
fail: false,
},
{
// Passing the address of an element of a pointer-to-array.
name: "arraypointer",
c: `void f44(void* p) {}`,
imports: []string{"unsafe"},
body: `a := new([10]byte); C.f44(unsafe.Pointer(&a[0]))`,
fail: false,
},
{
// Passing the address of an element of a pointer-to-array
// that contains a Go pointer.
name: "arraypointer2",
c: `void f45(void** p) {}`,
imports: []string{"unsafe"},
body: `i := 0; a := &[2]unsafe.Pointer{nil, unsafe.Pointer(&i)}; C.f45(&a[0])`,
fail: true,
},
}
func TestPointerChecks(t *testing.T) {
@@ -624,7 +607,7 @@ func buildPtrTests(t *testing.T, gopath string, cgocheck2 bool) (exe string) {
goexperiment = append(goexperiment, "cgocheck2")
changed = true
} else if !cgocheck2 && i >= 0 {
goexperiment = slices.Delete(goexperiment, i, i+1)
goexperiment = append(goexperiment[:i], goexperiment[i+1:]...)
changed = true
}
if changed {

View File

@@ -1,12 +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.
package p
import "C"
type T = T // ERROR HERE
//export F
func F(p *T) {}

View File

@@ -5,7 +5,8 @@
package main
/*
// ERROR MESSAGE: #cgo noescape noMatchedCFunction: no matched C function
// TODO(#56378): change back to "#cgo noescape noMatchedCFunction: no matched C function" in Go 1.23
// ERROR MESSAGE: #cgo noescape disabled until Go 1.23
#cgo noescape noMatchedCFunction
*/
import "C"

View File

@@ -7,19 +7,42 @@
package sanitizers_test
import (
"bytes"
"fmt"
"internal/platform"
"internal/testenv"
"os/exec"
"strings"
"testing"
)
func TestASAN(t *testing.T) {
config := mustHaveASAN(t)
testenv.MustHaveGoBuild(t)
testenv.MustHaveCGO(t)
goos, err := goEnv("GOOS")
if err != nil {
t.Fatal(err)
}
goarch, err := goEnv("GOARCH")
if err != nil {
t.Fatal(err)
}
// The asan tests require support for the -asan option.
if !platform.ASanSupported(goos, goarch) {
t.Skipf("skipping on %s/%s; -asan option is not supported.", goos, goarch)
}
// The current implementation is only compatible with the ASan library from version
// v7 to v9 (See the description in src/runtime/asan/asan.go). Therefore, using the
// -asan option must use a compatible version of ASan library, which requires that
// the gcc version is not less than 7 and the clang version is not less than 9,
// otherwise a segmentation fault will occur.
if !compilerRequiredAsanVersion(goos, goarch) {
t.Skipf("skipping on %s/%s: too old version of compiler", goos, goarch)
}
t.Parallel()
requireOvercommit(t)
config := configure("address")
config.skipIfCSanitizerBroken(t)
mustRun(t, config.goCmd("build", "std"))
cases := []struct {
@@ -83,10 +106,29 @@ func TestASAN(t *testing.T) {
}
func TestASANLinkerX(t *testing.T) {
testenv.MustHaveGoBuild(t)
testenv.MustHaveCGO(t)
// Test ASAN with linker's -X flag (see issue 56175).
config := mustHaveASAN(t)
goos, err := goEnv("GOOS")
if err != nil {
t.Fatal(err)
}
goarch, err := goEnv("GOARCH")
if err != nil {
t.Fatal(err)
}
// The asan tests require support for the -asan option.
if !platform.ASanSupported(goos, goarch) {
t.Skipf("skipping on %s/%s; -asan option is not supported.", goos, goarch)
}
if !compilerRequiredAsanVersion(goos, goarch) {
t.Skipf("skipping on %s/%s: too old version of compiler", goos, goarch)
}
t.Parallel()
requireOvercommit(t)
config := configure("address")
config.skipIfCSanitizerBroken(t)
dir := newTempDir(t)
defer dir.RemoveAll(t)
@@ -105,66 +147,3 @@ func TestASANLinkerX(t *testing.T) {
// run the binary
mustRun(t, hangProneCmd(outPath))
}
// Issue 66966.
func TestASANFuzz(t *testing.T) {
config := mustHaveASAN(t)
t.Parallel()
dir := newTempDir(t)
defer dir.RemoveAll(t)
exe := dir.Join("asan_fuzz_test.exe")
cmd := config.goCmd("test", "-c", "-o", exe, srcPath("asan_fuzz_test.go"))
t.Logf("%v", cmd)
out, err := cmd.CombinedOutput()
t.Logf("%s", out)
if err != nil {
t.Fatal(err)
}
cmd = exec.Command(exe, "-test.fuzz=Fuzz", "-test.fuzzcachedir="+dir.Base())
cmd.Dir = dir.Base()
t.Logf("%v", cmd)
out, err = cmd.CombinedOutput()
t.Logf("%s", out)
if err == nil {
t.Error("expected fuzzing failure")
}
if bytes.Contains(out, []byte("AddressSanitizer")) {
t.Error(`output contains "AddressSanitizer", but should not`)
}
}
func mustHaveASAN(t *testing.T) *config {
testenv.MustHaveGoBuild(t)
testenv.MustHaveCGO(t)
goos, err := goEnv("GOOS")
if err != nil {
t.Fatal(err)
}
goarch, err := goEnv("GOARCH")
if err != nil {
t.Fatal(err)
}
if !platform.ASanSupported(goos, goarch) {
t.Skipf("skipping on %s/%s; -asan option is not supported.", goos, goarch)
}
// The current implementation is only compatible with the ASan library from version
// v7 to v9 (See the description in src/runtime/asan/asan.go). Therefore, using the
// -asan option must use a compatible version of ASan library, which requires that
// the gcc version is not less than 7 and the clang version is not less than 9,
// otherwise a segmentation fault will occur.
if !compilerRequiredAsanVersion(goos, goarch) {
t.Skipf("skipping on %s/%s: too old version of compiler", goos, goarch)
}
requireOvercommit(t)
config := configure("address")
config.skipIfCSanitizerBroken(t)
return config
}

View File

@@ -563,7 +563,12 @@ func (d *tempDir) Join(name string) string {
}
func newTempDir(t *testing.T) *tempDir {
return &tempDir{base: t.TempDir()}
t.Helper()
dir, err := os.MkdirTemp("", filepath.Dir(t.Name()))
if err != nil {
t.Fatalf("Failed to create temp dir: %v", err)
}
return &tempDir{base: dir}
}
// hangProneCmd returns an exec.Cmd for a command that is likely to hang.

View File

@@ -11,7 +11,6 @@ import (
"internal/platform"
"internal/testenv"
"os"
"os/exec"
"strings"
"testing"
)
@@ -91,23 +90,7 @@ func TestShared(t *testing.T) {
cmd.Args = append(cmd.Args, "-o", dstBin, cSrc, lib)
mustRun(t, cmd)
cmdArgs := []string{dstBin}
if tc.sanitizer == "thread" && GOOS == "linux" {
// Disable ASLR for TSAN. See https://go.dev/issue/59418.
out, err := exec.Command("uname", "-m").Output()
if err != nil {
t.Fatalf("failed to run `uname -m`: %v", err)
}
arch := strings.TrimSpace(string(out))
if _, err := exec.Command("setarch", arch, "-R", "true").Output(); err != nil {
// Some systems don't have permission to run `setarch`.
// See https://go.dev/issue/70463.
t.Logf("failed to run `setarch %s -R true`: %v", arch, err)
} else {
cmdArgs = []string{"setarch", arch, "-R", dstBin}
}
}
cmd = hangProneCmd(cmdArgs[0], cmdArgs[1:]...)
cmd = hangProneCmd(dstBin)
replaceEnv(cmd, "LD_LIBRARY_PATH", ".")
mustRun(t, cmd)
})

View File

@@ -1,30 +0,0 @@
package main
import (
"slices"
"testing"
)
func Reverse(s string) string {
runes := []rune(s)
slices.Reverse(runes)
return string(runes)
}
// This fuzz test should quickly fail, because Reverse doesn't
// work for strings that are not valid UTF-8.
// What we are testing for is whether we see a failure from ASAN;
// we should see a fuzzing failure, not an ASAN failure.
func FuzzReverse(f *testing.F) {
f.Add("Go")
f.Add("Gopher")
f.Add("Hello, 世界")
f.Fuzz(func(t *testing.T, s string) {
r1 := Reverse(s)
r2 := Reverse(r1)
if s != r2 {
t.Errorf("got %q want %q", r2, s)
}
})
}

View File

@@ -26,22 +26,12 @@ void msanGoTraceback(void* parg) {
arg->buf[0] = 0;
}
// Don't warn if the compiler doesn't support the maybe_undef attribute.
#pragma GCC diagnostic ignored "-Wattributes"
// msanGoWait will be called with all registers undefined as far as
// msan is concerned. It just waits for a signal.
// Because the registers are msan-undefined, the signal handler will
// be invoked with all registers msan-undefined.
// The maybe_undef attribute tells clang to not complain about
// passing uninitialized values.
__attribute__((noinline))
void msanGoWait(unsigned long a1 __attribute__((maybe_undef)),
unsigned long a2 __attribute__((maybe_undef)),
unsigned long a3 __attribute__((maybe_undef)),
unsigned long a4 __attribute__((maybe_undef)),
unsigned long a5 __attribute__((maybe_undef)),
unsigned long a6 __attribute__((maybe_undef))) {
void msanGoWait(unsigned long a1, unsigned long a2, unsigned long a3, unsigned long a4, unsigned long a5, unsigned long a6) {
sigset_t mask;
sigemptyset(&mask);

View File

@@ -8,7 +8,6 @@ package sanitizers_test
import (
"internal/testenv"
"os/exec"
"strings"
"testing"
)
@@ -25,7 +24,7 @@ func TestTSAN(t *testing.T) {
if err != nil {
t.Fatal(err)
}
// The tsan tests require support for the -tsan option.
// The msan tests require support for the -msan option.
if !compilerRequiredTsanVersion(goos, goarch) {
t.Skipf("skipping on %s/%s; compiler version for -tsan option is too old.", goos, goarch)
}
@@ -69,23 +68,7 @@ func TestTSAN(t *testing.T) {
outPath := dir.Join(name)
mustRun(t, config.goCmd("build", "-o", outPath, srcPath(tc.src)))
cmdArgs := []string{outPath}
if goos == "linux" {
// Disable ASLR for TSAN. See https://go.dev/issue/59418.
out, err := exec.Command("uname", "-m").Output()
if err != nil {
t.Fatalf("failed to run `uname -m`: %v", err)
}
arch := strings.TrimSpace(string(out))
if _, err := exec.Command("setarch", arch, "-R", "true").Output(); err != nil {
// Some systems don't have permission to run `setarch`.
// See https://go.dev/issue/70463.
t.Logf("failed to run `setarch %s -R true`: %v", arch, err)
} else {
cmdArgs = []string{"setarch", arch, "-R", outPath}
}
}
cmd := hangProneCmd(cmdArgs[0], cmdArgs[1:]...)
cmd := hangProneCmd(outPath)
if tc.needsRuntime {
config.skipIfRuntimeIncompatible(t)
}

View File

@@ -18,17 +18,15 @@ import (
"go/token"
"internal/buildcfg"
"io"
"maps"
"os"
"path/filepath"
"reflect"
"runtime"
"sort"
"strings"
"sync"
"cmd/internal/edit"
"cmd/internal/hash"
"cmd/internal/notsha256"
"cmd/internal/objabi"
"cmd/internal/telemetry/counter"
)
@@ -83,7 +81,7 @@ func (f *File) offset(p token.Pos) int {
}
func nameKeys(m map[string]*Name) []string {
ks := make([]string, 0, len(m))
var ks []string
for k := range m {
ks = append(ks, k)
}
@@ -161,13 +159,6 @@ type Type struct {
BadPointer bool // this pointer type should be represented as a uintptr (deprecated)
}
func (t *Type) fuzzyMatch(t2 *Type) bool {
if t == nil || t2 == nil {
return false
}
return t.Size == t2.Size && t.Align == t2.Align
}
// A FuncType collects information about a function type in both the C and Go worlds.
type FuncType struct {
Params []*Type
@@ -175,24 +166,6 @@ type FuncType struct {
Go *ast.FuncType
}
func (t *FuncType) fuzzyMatch(t2 *FuncType) bool {
if t == nil || t2 == nil {
return false
}
if !t.Result.fuzzyMatch(t2.Result) {
return false
}
if len(t.Params) != len(t2.Params) {
return false
}
for i := range t.Params {
if !t.Params[i].fuzzyMatch(t2.Params[i]) {
return false
}
}
return true
}
func usage() {
fmt.Fprint(os.Stderr, "usage: cgo -- [compiler options] file.go ...\n")
flag.PrintDefaults()
@@ -389,11 +362,9 @@ func main() {
// we use to coordinate between gcc and ourselves.
// We already put _cgo_ at the beginning, so the main
// concern is other cgo wrappers for the same functions.
// Use the beginning of the 16 bytes hash of the input to disambiguate.
h := hash.New16()
// Use the beginning of the notsha256 of the input to disambiguate.
h := notsha256.New()
io.WriteString(h, *importPath)
var once sync.Once
var wg sync.WaitGroup
fs := make([]*File, len(goFiles))
for i, input := range goFiles {
if *srcDir != "" {
@@ -415,34 +386,23 @@ func main() {
fatalf("%s", err)
}
wg.Add(1)
go func() {
defer wg.Done()
// Apply trimpath to the file path. The path won't be read from after this point.
input, _ = objabi.ApplyRewrites(input, *trimpath)
if strings.ContainsAny(input, "\r\n") {
// ParseGo, (*Package).writeOutput, and printer.Fprint in SourcePos mode
// all emit line directives, which don't permit newlines in the file path.
// Bail early if we see anything newline-like in the trimmed path.
fatalf("input path contains newline character: %q", input)
}
goFiles[i] = input
// Apply trimpath to the file path. The path won't be read from after this point.
input, _ = objabi.ApplyRewrites(input, *trimpath)
if strings.ContainsAny(input, "\r\n") {
// ParseGo, (*Package).writeOutput, and printer.Fprint in SourcePos mode
// all emit line directives, which don't permit newlines in the file path.
// Bail early if we see anything newline-like in the trimmed path.
fatalf("input path contains newline character: %q", input)
}
goFiles[i] = input
f := new(File)
f.Edit = edit.NewBuffer(b)
f.ParseGo(input, b)
f.ProcessCgoDirectives()
gccIsClang := f.loadDefines(p.GccOptions)
once.Do(func() {
p.GccIsClang = gccIsClang
})
fs[i] = f
}()
f := new(File)
f.Edit = edit.NewBuffer(b)
f.ParseGo(input, b)
f.ProcessCgoDirectives()
fs[i] = f
}
wg.Wait()
cPrefix = fmt.Sprintf("_%x", h.Sum(nil)[0:6])
if *objDir == "" {
@@ -555,52 +515,30 @@ func (p *Package) Record(f *File) {
if p.Name == nil {
p.Name = f.Name
} else {
// Merge the new file's names in with the existing names.
for k, v := range f.Name {
if p.Name[k] == nil {
// Never seen before, just save it.
p.Name[k] = v
} else if p.incompleteTypedef(p.Name[k].Type) && p.Name[k].FuncType == nil {
// Old one is incomplete, just use new one.
} else if p.incompleteTypedef(p.Name[k].Type) {
p.Name[k] = v
} else if p.incompleteTypedef(v.Type) && v.FuncType == nil {
// New one is incomplete, just use old one.
} else if p.incompleteTypedef(v.Type) {
// Nothing to do.
} else if _, ok := nameToC[k]; ok {
// Names we predefine may appear inconsistent
// if some files typedef them and some don't.
// Issue 26743.
} else if !reflect.DeepEqual(p.Name[k], v) {
// We don't require strict func type equality, because some functions
// can have things like typedef'd arguments that are equivalent to
// the standard arguments. e.g.
// int usleep(unsigned);
// int usleep(useconds_t);
// So we just check size/alignment of arguments. At least that
// avoids problems like those in #67670 and #67699.
ok := false
ft1 := p.Name[k].FuncType
ft2 := v.FuncType
if ft1.fuzzyMatch(ft2) {
// Retry DeepEqual with the FuncType field cleared.
x1 := *p.Name[k]
x2 := *v
x1.FuncType = nil
x2.FuncType = nil
if reflect.DeepEqual(&x1, &x2) {
ok = true
}
}
if !ok {
error_(token.NoPos, "inconsistent definitions for C.%s", fixGo(k))
}
error_(token.NoPos, "inconsistent definitions for C.%s", fixGo(k))
}
}
}
// merge nocallback & noescape
maps.Copy(p.noCallbacks, f.NoCallbacks)
maps.Copy(p.noEscapes, f.NoEscapes)
for k, v := range f.NoCallbacks {
p.noCallbacks[k] = v
}
for k, v := range f.NoEscapes {
p.noEscapes[k] = v
}
if f.ExpFunc != nil {
p.ExpFunc = append(p.ExpFunc, f.ExpFunc...)

View File

@@ -104,9 +104,6 @@ func (p *Package) writeDefs() {
fmt.Fprintf(fgo2, "var _Cgo_always_false bool\n")
fmt.Fprintf(fgo2, "//go:linkname _Cgo_use runtime.cgoUse\n")
fmt.Fprintf(fgo2, "func _Cgo_use(interface{})\n")
fmt.Fprintf(fgo2, "//go:linkname _Cgo_keepalive runtime.cgoKeepAlive\n")
fmt.Fprintf(fgo2, "//go:noescape\n")
fmt.Fprintf(fgo2, "func _Cgo_keepalive(interface{})\n")
}
fmt.Fprintf(fgo2, "//go:linkname _Cgo_no_callback runtime.cgoNoCallback\n")
fmt.Fprintf(fgo2, "func _Cgo_no_callback(bool)\n")
@@ -381,7 +378,9 @@ func dynimport(obj string) {
defer f.Close()
sym, _ := f.ImportedSymbols()
for _, s := range sym {
s = strings.TrimPrefix(s, "_")
if len(s) > 0 && s[0] == '_' {
s = s[1:]
}
checkImportSymName(s)
fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", s, s, "")
}
@@ -447,7 +446,7 @@ func checkImportSymName(s string) {
}
}
if strings.Contains(s, "//") || strings.Contains(s, "/*") {
fatalf("dynamic symbol %q contains Go comment", s)
fatalf("dynamic symbol %q contains Go comment")
}
}
@@ -642,20 +641,17 @@ func (p *Package) writeDefsFunc(fgo2 io.Writer, n *Name, callsMalloc *bool) {
fmt.Fprintf(fgo2, "\t_Cgo_no_callback(false)\n")
}
// Use _Cgo_keepalive instead of _Cgo_use when noescape & nocallback exist,
// skip _Cgo_use when noescape exist,
// so that the compiler won't force to escape them to heap.
// Instead, make the compiler keep them alive by using _Cgo_keepalive.
touchFunc := "_Cgo_use"
if p.noEscapes[n.C] && p.noCallbacks[n.C] {
touchFunc = "_Cgo_keepalive"
}
fmt.Fprintf(fgo2, "\tif _Cgo_always_false {\n")
if d.Type.Params != nil {
for _, name := range paramnames {
fmt.Fprintf(fgo2, "\t\t%s(%s)\n", touchFunc, name)
if !p.noEscapes[n.C] {
fmt.Fprintf(fgo2, "\tif _Cgo_always_false {\n")
if d.Type.Params != nil {
for i := range d.Type.Params.List {
fmt.Fprintf(fgo2, "\t\t_Cgo_use(p%d)\n", i)
}
}
fmt.Fprintf(fgo2, "\t}\n")
}
fmt.Fprintf(fgo2, "\t}\n")
fmt.Fprintf(fgo2, "\treturn\n")
fmt.Fprintf(fgo2, "}\n")
}
@@ -1418,18 +1414,9 @@ var goTypes = map[string]*Type{
// Map an ast type to a Type.
func (p *Package) cgoType(e ast.Expr) *Type {
return p.doCgoType(e, make(map[ast.Expr]bool))
}
// Map an ast type to a Type, avoiding cycles.
func (p *Package) doCgoType(e ast.Expr, m map[ast.Expr]bool) *Type {
if m[e] {
fatalf("%s: invalid recursive type", fset.Position(e.Pos()))
}
m[e] = true
switch t := e.(type) {
case *ast.StarExpr:
x := p.doCgoType(t.X, m)
x := p.cgoType(t.X)
return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("%s*", x.C)}
case *ast.ArrayType:
if t.Len == nil {
@@ -1474,12 +1461,7 @@ func (p *Package) doCgoType(e ast.Expr, m map[ast.Expr]bool) *Type {
continue
}
if ts.Name.Name == t.Name {
// Give a better error than the one
// above if we detect a recursive type.
if m[ts.Type] {
fatalf("%s: invalid recursive type: %s refers to itself", fset.Position(e.Pos()), t.Name)
}
return p.doCgoType(ts.Type, m)
return p.cgoType(ts.Type)
}
}
}

View File

@@ -10,14 +10,13 @@ import (
"go/token"
"os"
"os/exec"
"slices"
)
// run runs the command argv, feeding in stdin on standard input.
// It returns the output to standard output and standard error.
// ok indicates whether the command exited successfully.
func run(stdin []byte, argv []string) (stdout, stderr []byte, ok bool) {
if i := slices.Index(argv, "-xc"); i >= 0 && argv[len(argv)-1] == "-" {
if i := find(argv, "-xc"); i >= 0 && argv[len(argv)-1] == "-" {
// Some compilers have trouble with standard input.
// Others have trouble with -xc.
// Avoid both problems by writing a file with a .c extension.
@@ -70,6 +69,15 @@ func run(stdin []byte, argv []string) (stdout, stderr []byte, ok bool) {
return
}
func find(argv []string, target string) int {
for i, arg := range argv {
if arg == target {
return i
}
}
return -1
}
func lineno(pos token.Pos) string {
return fset.Position(pos).String()
}

Binary file not shown.

View File

@@ -309,33 +309,13 @@ The types of parameters and return values to the Go function are translated to
Wasm according to the following table:
Go types Wasm types
bool i32
int32, uint32 i32
int64, uint64 i64
float32 f32
float64 f64
unsafe.Pointer i32
pointer i32 (more restrictions below)
string (i32, i32) (only permitted as a parameters, not a result)
For a pointer type, its element type must be a bool, int8, uint8, int16, uint16,
int32, uint32, int64, uint64, float32, float64, an array whose element type is
a permitted pointer element type, or a struct, which, if non-empty, embeds
structs.HostLayout, and contains only fields whose types are permitted pointer
element types.
Any other parameter types are disallowed by the compiler.
//go:wasmexport exportname
The //go:wasmexport directive is wasm-only and must be followed by a
function definition.
It specifies that the function is exported to the wasm host as ``exportname``.
//go:wasmexport f
func g()
The types of parameters and return values to the Go function are permitted and
translated to Wasm in the same way as //go:wasmimport functions.
*/
package main

View File

@@ -819,6 +819,13 @@ func (t *node32) leftToRoot() *node32 {
return left
}
func max(a, b int8) int8 {
if a > b {
return a
}
return b
}
func (t *node32) copy() *node32 {
u := *t
return &u

View File

@@ -256,39 +256,9 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
ssa.OpAMD64POR, ssa.OpAMD64PXOR,
ssa.OpAMD64BTSL, ssa.OpAMD64BTSQ,
ssa.OpAMD64BTCL, ssa.OpAMD64BTCQ,
ssa.OpAMD64BTRL, ssa.OpAMD64BTRQ,
ssa.OpAMD64PCMPEQB, ssa.OpAMD64PSIGNB,
ssa.OpAMD64PUNPCKLBW:
ssa.OpAMD64BTRL, ssa.OpAMD64BTRQ:
opregreg(s, v.Op.Asm(), v.Reg(), v.Args[1].Reg())
case ssa.OpAMD64PSHUFLW:
p := s.Prog(v.Op.Asm())
imm := v.AuxInt
if imm < 0 || imm > 255 {
v.Fatalf("Invalid source selection immediate")
}
p.From.Offset = imm
p.From.Type = obj.TYPE_CONST
p.AddRestSourceReg(v.Args[0].Reg())
p.To.Type = obj.TYPE_REG
p.To.Reg = v.Reg()
case ssa.OpAMD64PSHUFBbroadcast:
// PSHUFB with a control mask of zero copies byte 0 to all
// bytes in the register.
//
// X15 is always zero with ABIInternal.
if s.ABI != obj.ABIInternal {
// zero X15 manually
opregreg(s, x86.AXORPS, x86.REG_X15, x86.REG_X15)
}
p := s.Prog(v.Op.Asm())
p.From.Type = obj.TYPE_REG
p.To.Type = obj.TYPE_REG
p.To.Reg = v.Reg()
p.From.Reg = x86.REG_X15
case ssa.OpAMD64SHRDQ, ssa.OpAMD64SHLDQ:
p := s.Prog(v.Op.Asm())
lo, hi, bits := v.Args[0].Reg(), v.Args[1].Reg(), v.Args[2].Reg()
@@ -945,7 +915,7 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
ssagen.AddAux2(&p.To, v, sc.Off64())
case ssa.OpAMD64MOVLQSX, ssa.OpAMD64MOVWQSX, ssa.OpAMD64MOVBQSX, ssa.OpAMD64MOVLQZX, ssa.OpAMD64MOVWQZX, ssa.OpAMD64MOVBQZX,
ssa.OpAMD64CVTTSS2SL, ssa.OpAMD64CVTTSD2SL, ssa.OpAMD64CVTTSS2SQ, ssa.OpAMD64CVTTSD2SQ,
ssa.OpAMD64CVTSS2SD, ssa.OpAMD64CVTSD2SS, ssa.OpAMD64VPBROADCASTB, ssa.OpAMD64PMOVMSKB:
ssa.OpAMD64CVTSS2SD, ssa.OpAMD64CVTSD2SS:
opregreg(s, v.Op.Asm(), v.Reg(), v.Args[0].Reg())
case ssa.OpAMD64CVTSL2SD, ssa.OpAMD64CVTSQ2SD, ssa.OpAMD64CVTSQ2SS, ssa.OpAMD64CVTSL2SS:
r := v.Reg()
@@ -1316,8 +1286,7 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
p = s.Prog(x86.ASETEQ)
p.To.Type = obj.TYPE_REG
p.To.Reg = v.Reg0()
case ssa.OpAMD64ANDBlock, ssa.OpAMD64ANDLlock, ssa.OpAMD64ANDQlock, ssa.OpAMD64ORBlock, ssa.OpAMD64ORLlock, ssa.OpAMD64ORQlock:
// Atomic memory operations that don't need to return the old value.
case ssa.OpAMD64ANDBlock, ssa.OpAMD64ANDLlock, ssa.OpAMD64ORBlock, ssa.OpAMD64ORLlock:
s.Prog(x86.ALOCK)
p := s.Prog(v.Op.Asm())
p.From.Type = obj.TYPE_REG
@@ -1325,60 +1294,6 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
p.To.Type = obj.TYPE_MEM
p.To.Reg = v.Args[0].Reg()
ssagen.AddAux(&p.To, v)
case ssa.OpAMD64LoweredAtomicAnd64, ssa.OpAMD64LoweredAtomicOr64, ssa.OpAMD64LoweredAtomicAnd32, ssa.OpAMD64LoweredAtomicOr32:
// Atomic memory operations that need to return the old value.
// We need to do these with compare-and-exchange to get access to the old value.
// loop:
// MOVQ mask, tmp
// MOVQ (addr), AX
// ANDQ AX, tmp
// LOCK CMPXCHGQ tmp, (addr) : note that AX is implicit old value to compare against
// JNE loop
// : result in AX
mov := x86.AMOVQ
op := x86.AANDQ
cmpxchg := x86.ACMPXCHGQ
switch v.Op {
case ssa.OpAMD64LoweredAtomicOr64:
op = x86.AORQ
case ssa.OpAMD64LoweredAtomicAnd32:
mov = x86.AMOVL
op = x86.AANDL
cmpxchg = x86.ACMPXCHGL
case ssa.OpAMD64LoweredAtomicOr32:
mov = x86.AMOVL
op = x86.AORL
cmpxchg = x86.ACMPXCHGL
}
addr := v.Args[0].Reg()
mask := v.Args[1].Reg()
tmp := v.RegTmp()
p1 := s.Prog(mov)
p1.From.Type = obj.TYPE_REG
p1.From.Reg = mask
p1.To.Type = obj.TYPE_REG
p1.To.Reg = tmp
p2 := s.Prog(mov)
p2.From.Type = obj.TYPE_MEM
p2.From.Reg = addr
ssagen.AddAux(&p2.From, v)
p2.To.Type = obj.TYPE_REG
p2.To.Reg = x86.REG_AX
p3 := s.Prog(op)
p3.From.Type = obj.TYPE_REG
p3.From.Reg = x86.REG_AX
p3.To.Type = obj.TYPE_REG
p3.To.Reg = tmp
s.Prog(x86.ALOCK)
p5 := s.Prog(cmpxchg)
p5.From.Type = obj.TYPE_REG
p5.From.Reg = tmp
p5.To.Type = obj.TYPE_MEM
p5.To.Reg = addr
ssagen.AddAux(&p5.To, v)
p6 := s.Prog(x86.AJNE)
p6.To.Type = obj.TYPE_BRANCH
p6.To.SetTarget(p1)
case ssa.OpAMD64PrefetchT0, ssa.OpAMD64PrefetchNTA:
p := s.Prog(v.Op.Asm())
p.From.Type = obj.TYPE_MEM

View File

@@ -78,7 +78,7 @@ func TestGoAMD64v1(t *testing.T) {
cmd.Env = append(cmd.Env, fmt.Sprintf("GODEBUG=%s", strings.Join(features, ",")))
out, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("couldn't execute test: %s\n%s", err, out)
t.Fatalf("couldn't execute test: %s", err)
}
// Expect to see output of the form "PASS\n", unless the test binary
// was compiled for coverage (in which case there will be an extra line).

View File

@@ -78,48 +78,6 @@ func storeByType(t *types.Type) obj.As {
panic("bad store type")
}
// loadByType2 returns an opcode that can load consecutive memory locations into 2 registers with type t.
// returns obj.AXXX if no such opcode exists.
func loadByType2(t *types.Type) obj.As {
if t.IsFloat() {
switch t.Size() {
case 4:
return arm64.AFLDPS
case 8:
return arm64.AFLDPD
}
} else {
switch t.Size() {
case 4:
return arm64.ALDPW
case 8:
return arm64.ALDP
}
}
return obj.AXXX
}
// storeByType2 returns an opcode that can store registers with type t into 2 consecutive memory locations.
// returns obj.AXXX if no such opcode exists.
func storeByType2(t *types.Type) obj.As {
if t.IsFloat() {
switch t.Size() {
case 4:
return arm64.AFSTPS
case 8:
return arm64.AFSTPD
}
} else {
switch t.Size() {
case 4:
return arm64.ASTPW
case 8:
return arm64.ASTP
}
}
return obj.AXXX
}
// makeshift encodes a register shifted by a constant, used as an Offset in Prog.
func makeshift(v *ssa.Value, reg int16, typ int64, s int64) int64 {
if s < 0 || s >= 64 {
@@ -209,38 +167,17 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
p.From.Reg = v.Args[0].Reg()
ssagen.AddrAuto(&p.To, v)
case ssa.OpArgIntReg, ssa.OpArgFloatReg:
ssagen.CheckArgReg(v)
// The assembler needs to wrap the entry safepoint/stack growth code with spill/unspill
// The loop only runs once.
args := v.Block.Func.RegArgs
if len(args) == 0 {
break
}
v.Block.Func.RegArgs = nil // prevent from running again
for i := 0; i < len(args); i++ {
a := args[i]
// Offset by size of the saved LR slot.
for _, a := range v.Block.Func.RegArgs {
// Pass the spill/unspill information along to the assembler, offset by size of
// the saved LR slot.
addr := ssagen.SpillSlotAddr(a, arm64.REGSP, base.Ctxt.Arch.FixedFrameSize)
// Look for double-register operations if we can.
if i < len(args)-1 {
b := args[i+1]
if a.Type.Size() == b.Type.Size() &&
a.Type.IsFloat() == b.Type.IsFloat() &&
b.Offset == a.Offset+a.Type.Size() {
ld := loadByType2(a.Type)
st := storeByType2(a.Type)
if ld != obj.AXXX && st != obj.AXXX {
s.FuncInfo().AddSpill(obj.RegSpill{Reg: a.Reg, Reg2: b.Reg, Addr: addr, Unspill: ld, Spill: st})
i++ // b is done also, skip it.
continue
}
}
}
// Pass the spill/unspill information along to the assembler.
s.FuncInfo().AddSpill(obj.RegSpill{Reg: a.Reg, Addr: addr, Unspill: loadByType(a.Type), Spill: storeByType(a.Type)})
s.FuncInfo().AddSpill(
obj.RegSpill{Reg: a.Reg, Addr: addr, Unspill: loadByType(a.Type), Spill: storeByType(a.Type)})
}
v.Block.Func.RegArgs = nil
ssagen.CheckArgReg(v)
case ssa.OpARM64ADD,
ssa.OpARM64SUB,
ssa.OpARM64AND,
@@ -641,22 +578,15 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
p.To.Type = obj.TYPE_REG
p.To.Reg = v.Reg()
case ssa.OpARM64LoweredAtomicExchange64,
ssa.OpARM64LoweredAtomicExchange32,
ssa.OpARM64LoweredAtomicExchange8:
ssa.OpARM64LoweredAtomicExchange32:
// LDAXR (Rarg0), Rout
// STLXR Rarg1, (Rarg0), Rtmp
// CBNZ Rtmp, -2(PC)
var ld, st obj.As
switch v.Op {
case ssa.OpARM64LoweredAtomicExchange8:
ld = arm64.ALDAXRB
st = arm64.ASTLXRB
case ssa.OpARM64LoweredAtomicExchange32:
ld := arm64.ALDAXR
st := arm64.ASTLXR
if v.Op == ssa.OpARM64LoweredAtomicExchange32 {
ld = arm64.ALDAXRW
st = arm64.ASTLXRW
case ssa.OpARM64LoweredAtomicExchange64:
ld = arm64.ALDAXR
st = arm64.ASTLXR
}
r0 := v.Args[0].Reg()
r1 := v.Args[1].Reg()
@@ -678,16 +608,10 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
p2.To.Type = obj.TYPE_BRANCH
p2.To.SetTarget(p)
case ssa.OpARM64LoweredAtomicExchange64Variant,
ssa.OpARM64LoweredAtomicExchange32Variant,
ssa.OpARM64LoweredAtomicExchange8Variant:
var swap obj.As
switch v.Op {
case ssa.OpARM64LoweredAtomicExchange8Variant:
swap = arm64.ASWPALB
case ssa.OpARM64LoweredAtomicExchange32Variant:
ssa.OpARM64LoweredAtomicExchange32Variant:
swap := arm64.ASWPALD
if v.Op == ssa.OpARM64LoweredAtomicExchange32Variant {
swap = arm64.ASWPALW
case ssa.OpARM64LoweredAtomicExchange64Variant:
swap = arm64.ASWPALD
}
r0 := v.Args[0].Reg()
r1 := v.Args[1].Reg()

View File

@@ -30,7 +30,6 @@ type DebugFlags struct {
DwarfInl int `help:"print information about DWARF inlined function creation"`
EscapeMutationsCalls int `help:"print extra escape analysis diagnostics about mutations and calls" concurrent:"ok"`
Export int `help:"print export data"`
FIPSHash string `help:"hash value for FIPS debugging" concurrent:"ok"`
Fmahash string `help:"hash value for use in debugging platform-dependent multiply-add use" concurrent:"ok"`
GCAdjust int `help:"log adjustments to GOGC" concurrent:"ok"`
GCCheck int `help:"check heap/gc use by compiler" concurrent:"ok"`
@@ -49,7 +48,6 @@ type DebugFlags struct {
MergeLocalsTrace int `help:"trace debug output for locals merging"`
MergeLocalsHTrace int `help:"hash-selected trace debug output for locals merging"`
Nil int `help:"print information about nil checks"`
NoDeadLocals int `help:"disable deadlocals pass" concurrent:"ok"`
NoOpenDefer int `help:"disable open-coded defers" concurrent:"ok"`
NoRefName int `help:"do not include referenced symbol names in object file" concurrent:"ok"`
PCTab string `help:"print named pc-value table\nOne of: pctospadj, pctofile, pctoline, pctoinline, pctopcdata"`
@@ -60,7 +58,6 @@ type DebugFlags struct {
SoftFloat int `help:"force compiler to emit soft-float code" concurrent:"ok"`
StaticCopy int `help:"print information about missed static copies" concurrent:"ok"`
SyncFrames int `help:"how many writer stack frames to include at sync points in unified export data"`
TailCall int `help:"print information about tail calls"`
TypeAssert int `help:"print information about type assertion inlining"`
WB int `help:"print information about write barriers"`
ABIWrap int `help:"print information about ABI wrapper generation"`

View File

@@ -206,7 +206,6 @@ func ParseFlags() {
if Debug.Gossahash != "" {
hashDebug = NewHashDebug("gossahash", Debug.Gossahash, nil)
}
obj.SetFIPSDebugHash(Debug.FIPSHash)
// Compute whether we're compiling the runtime from the package path. Test
// code can also use the flag to set this explicitly.

View File

@@ -8,7 +8,6 @@ import (
"math/bits"
"cmd/compile/internal/base"
"cmd/internal/src"
)
const (
@@ -34,11 +33,11 @@ type Bulk struct {
nword int32
}
func NewBulk(nbit int32, count int32, pos src.XPos) Bulk {
func NewBulk(nbit int32, count int32) Bulk {
nword := (nbit + wordBits - 1) / wordBits
size := int64(nword) * int64(count)
if int64(int32(size*4)) != size*4 {
base.FatalfAt(pos, "NewBulk too big: nbit=%d count=%d nword=%d size=%d", nbit, count, nword, size)
base.Fatalf("NewBulk too big: nbit=%d count=%d nword=%d size=%d", nbit, count, nword, size)
}
return Bulk{
words: make([]uint32, size),

View File

@@ -1,194 +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.
// The deadlocals pass removes assignments to unused local variables.
package deadlocals
import (
"cmd/compile/internal/base"
"cmd/compile/internal/ir"
"cmd/compile/internal/types"
"cmd/internal/src"
"fmt"
"go/constant"
)
// Funcs applies the deadlocals pass to fns.
func Funcs(fns []*ir.Func) {
if base.Flag.N != 0 || base.Debug.NoDeadLocals != 0 {
return
}
zero := ir.NewBasicLit(base.AutogeneratedPos, types.Types[types.TINT], constant.MakeInt64(0))
for _, fn := range fns {
if fn.IsClosure() {
continue
}
v := newVisitor(fn)
v.nodes(fn.Body)
for _, k := range v.defsKeys {
assigns := v.defs[k]
for _, as := range assigns {
// Kludge for "missing func info" linker panic.
// See also closureInitLSym in inline/inl.go.
if clo, ok := (*as.rhs).(*ir.ClosureExpr); ok && clo.Op() == ir.OCLOSURE {
if clo.Func.IsClosure() {
ir.InitLSym(clo.Func, true)
}
}
*as.lhs = ir.BlankNode
*as.rhs = zero
}
}
}
}
type visitor struct {
curfn *ir.Func
// defs[name] contains assignments that can be discarded if name can be discarded.
// if defs[name] is defined nil, then name is actually used.
defs map[*ir.Name][]assign
defsKeys []*ir.Name // insertion order of keys, for reproducible iteration (and builds)
doNode func(ir.Node) bool
}
type assign struct {
pos src.XPos
lhs, rhs *ir.Node
}
func newVisitor(fn *ir.Func) *visitor {
v := &visitor{
curfn: fn,
defs: make(map[*ir.Name][]assign),
}
v.doNode = func(n ir.Node) bool {
v.node(n)
return false
}
return v
}
func (v *visitor) node(n ir.Node) {
if n == nil {
return
}
switch n.Op() {
default:
ir.DoChildrenWithHidden(n, v.doNode)
case ir.OCLOSURE:
n := n.(*ir.ClosureExpr)
v.nodes(n.Init())
for _, cv := range n.Func.ClosureVars {
v.node(cv)
}
v.nodes(n.Func.Body)
case ir.ODCL:
// ignore
case ir.ONAME:
n := n.(*ir.Name)
n = n.Canonical()
if isLocal(n, false) {
// Force any lazy definitions.
s, ok := v.defs[n]
if !ok {
v.defsKeys = append(v.defsKeys, n)
}
v.defs[n] = nil
for _, as := range s {
// do the visit that was skipped in v.assign when as was appended to v.defs[n]
v.node(*as.rhs)
}
}
case ir.OAS:
n := n.(*ir.AssignStmt)
v.assign(n.Pos(), &n.X, &n.Y, false)
case ir.OAS2:
n := n.(*ir.AssignListStmt)
// If all LHS vars are blank, treat them as intentional
// uses of corresponding RHS vars. If any are non-blank
// then any blanks are discards.
hasNonBlank := false
for i := range n.Lhs {
if !ir.IsBlank(n.Lhs[i]) {
hasNonBlank = true
break
}
}
for i := range n.Lhs {
v.assign(n.Pos(), &n.Lhs[i], &n.Rhs[i], hasNonBlank)
}
}
}
func (v *visitor) nodes(list ir.Nodes) {
for _, n := range list {
v.node(n)
}
}
func hasEffects(n ir.Node) bool {
if n == nil {
return false
}
if len(n.Init()) != 0 {
return true
}
switch n.Op() {
// TODO(mdempsky): More.
case ir.ONAME, ir.OLITERAL, ir.ONIL, ir.OCLOSURE:
return false
}
return true
}
func (v *visitor) assign(pos src.XPos, lhs, rhs *ir.Node, blankIsNotUse bool) {
name, ok := (*lhs).(*ir.Name)
if !ok {
v.node(*lhs) // XXX: Interpret as variable, not value.
v.node(*rhs)
return
}
name = name.Canonical()
if isLocal(name, blankIsNotUse) && !hasEffects(*rhs) {
if s, ok := v.defs[name]; !ok || s != nil {
// !ok || s != nil is FALSE if previously "v.defs[name] = nil" -- that marks a use.
if !ok {
v.defsKeys = append(v.defsKeys, name)
}
v.defs[name] = append(s, assign{pos, lhs, rhs})
return // don't visit rhs unless that node ends up live, later.
}
}
v.node(*rhs)
}
func isLocal(n *ir.Name, blankIsNotUse bool) bool {
if ir.IsBlank(n) {
// Treat single assignments as intentional use (false), anything else is a discard (true).
return blankIsNotUse
}
switch n.Class {
case ir.PAUTO, ir.PPARAM:
return true
case ir.PPARAMOUT:
return false
case ir.PEXTERN, ir.PFUNC:
return false
}
panic(fmt.Sprintf("unexpected Class: %+v", n))
}

View File

@@ -63,7 +63,7 @@ func StaticCall(call *ir.CallExpr) {
// dictionary parameter. We could devirtualize this call if we
// could derive an appropriate dictionary argument.
//
// TODO(mdempsky): If typ has a promoted non-generic method,
// TODO(mdempsky): If typ has has a promoted non-generic method,
// then that method won't require a dictionary argument. We could
// still devirtualize those calls.
//

View File

@@ -241,9 +241,8 @@ func maybeDevirtualizeFunctionCall(p *pgoir.Profile, fn *ir.Func, call *ir.CallE
return nil, nil, 0
}
// runtime.memhash_varlen does not look like a closure, but it uses
// internal/runtime/sys.GetClosurePtr to access data encoded by
// callers, which are generated by
// cmd/compile/internal/reflectdata.genhash.
// runtime.getclosureptr to access data encoded by callers, which are
// are generated by cmd/compile/internal/reflectdata.genhash.
if callee.Sym().Pkg.Path == "runtime" && callee.Sym().Name == "memhash_varlen" {
if base.Debug.PGODebug >= 3 {
fmt.Printf("callee %s is a closure (runtime.memhash_varlen), skipping\n", ir.FuncName(callee))

View File

@@ -9,9 +9,7 @@ import (
"flag"
"fmt"
"internal/buildcfg"
"slices"
"sort"
"strings"
"cmd/compile/internal/base"
"cmd/compile/internal/ir"
@@ -26,7 +24,7 @@ import (
"cmd/internal/src"
)
func Info(ctxt *obj.Link, fnsym *obj.LSym, infosym *obj.LSym, curfn obj.Func) (scopes []dwarf.Scope, inlcalls dwarf.InlCalls) {
func Info(fnsym *obj.LSym, infosym *obj.LSym, curfn obj.Func) (scopes []dwarf.Scope, inlcalls dwarf.InlCalls) {
fn := curfn.(*ir.Func)
if fn.Nname != nil {
@@ -132,11 +130,11 @@ func Info(ctxt *obj.Link, fnsym *obj.LSym, infosym *obj.LSym, curfn obj.Func) (s
for t := range fnsym.Func().Autot {
typesyms = append(typesyms, t)
}
slices.SortFunc(typesyms, func(a, b *obj.LSym) int {
return strings.Compare(a.Name, b.Name)
})
sort.Sort(obj.BySymName(typesyms))
for _, sym := range typesyms {
infosym.AddRel(ctxt, obj.Reloc{Type: objabi.R_USETYPE, Sym: sym})
r := obj.Addrel(infosym)
r.Sym = sym
r.Type = objabi.R_USETYPE
}
fnsym.Func().Autot = nil

View File

@@ -5,7 +5,6 @@
package dwarfgen
import (
"cmp"
"debug/dwarf"
"fmt"
"internal/platform"
@@ -13,7 +12,7 @@ import (
"os"
"path/filepath"
"runtime"
"slices"
"sort"
"strconv"
"strings"
"testing"
@@ -401,8 +400,8 @@ func readScope(ctxt *scopexplainContext, scope *lexblock, entry *dwarf.Entry) {
}
switch e.Tag {
case 0:
slices.SortFunc(scope.vars, func(a, b variable) int {
return cmp.Compare(a.expr, b.expr)
sort.Slice(scope.vars, func(i, j int) bool {
return scope.vars[i].expr < scope.vars[j].expr
})
return
case dwarf.TagFormalParameter:

View File

@@ -10,7 +10,6 @@ import (
"cmd/compile/internal/typecheck"
"cmd/compile/internal/types"
"cmd/internal/src"
"strings"
)
// call evaluates a call expressions, including builtin calls. ks
@@ -83,29 +82,6 @@ func (e *escape) call(ks []hole, call ir.Node) {
argument(e.tagHole(ks, fn, param), arg)
}
// hash/maphash.escapeForHash forces its argument to be on
// the heap, if it contains a non-string pointer. We cannot
// hash pointers to local variables, as the address of the
// local variable might change on stack growth.
// Strings are okay as the hash depends on only the content,
// not the pointer.
// The actual call we match is
// hash/maphash.escapeForHash[go.shape.T](dict, go.shape.T)
if fn != nil && fn.Sym().Pkg.Path == "hash/maphash" && strings.HasPrefix(fn.Sym().Name, "escapeForHash[") {
ps := fntype.Params()
if len(ps) == 2 && ps[1].Type.IsShape() {
if !hasNonStringPointers(ps[1].Type) {
argumentParam = func(param *types.Field, arg ir.Node) {
argument(e.discardHole(), arg)
}
} else {
argumentParam = func(param *types.Field, arg ir.Node) {
argument(e.heapHole(), arg)
}
}
}
}
args := call.Args
if recvParam := fntype.Recv(); recvParam != nil {
if recvArg == nil {
@@ -383,23 +359,3 @@ func (e *escape) tagHole(ks []hole, fn *ir.Name, param *types.Field) hole {
return e.teeHole(tagKs...)
}
func hasNonStringPointers(t *types.Type) bool {
if !t.HasPointers() {
return false
}
switch t.Kind() {
case types.TSTRING:
return false
case types.TSTRUCT:
for _, f := range t.Fields() {
if hasNonStringPointers(f.Type) {
return true
}
}
return false
case types.TARRAY:
return hasNonStringPointers(t.Elem())
}
return true
}

View File

@@ -139,13 +139,13 @@ func Batch(fns []*ir.Func, recursive bool) {
b.initFunc(fn)
}
for _, fn := range fns {
if !fn.IsClosure() {
if !fn.IsHiddenClosure() {
b.walkFunc(fn)
}
}
// We've walked the function bodies, so we've seen everywhere a
// variable might be reassigned or have its address taken. Now we
// variable might be reassigned or have it's address taken. Now we
// can decide whether closures should capture their free variables
// by value or reference.
for _, closure := range b.closures {

View File

@@ -38,7 +38,7 @@ func (e *escape) exprSkipInit(k hole, n ir.Node) {
default:
base.Fatalf("unexpected expr: %s %v", n.Op().String(), n)
case ir.OLITERAL, ir.ONIL, ir.OGETG, ir.OGETCALLERSP, ir.OTYPE, ir.OMETHEXPR, ir.OLINKSYMOFFSET:
case ir.OLITERAL, ir.ONIL, ir.OGETG, ir.OGETCALLERPC, ir.OGETCALLERSP, ir.OTYPE, ir.OMETHEXPR, ir.OLINKSYMOFFSET:
// nop
case ir.ONAME:
@@ -230,7 +230,7 @@ func (e *escape) exprSkipInit(k hole, n ir.Node) {
k = e.spill(k, n)
e.closures = append(e.closures, closure{k, n})
if fn := n.Func; fn.IsClosure() {
if fn := n.Func; fn.IsHiddenClosure() {
for _, cv := range fn.ClosureVars {
if loc := e.oldLoc(cv); !loc.captured {
loc.captured = true

View File

@@ -5,10 +5,9 @@
package gc
import (
"cmp"
"internal/race"
"math/rand"
"slices"
"sort"
"sync"
"cmd/compile/internal/base"
@@ -40,7 +39,12 @@ func enqueueFunc(fn *ir.Func) {
return
}
if fn.IsClosure() {
// Don't try compiling dead hidden closure.
if fn.IsDeadcodeClosure() {
return
}
if clo := fn.OClosure; clo != nil && !ir.IsTrivialClosure(clo) {
return // we'll get this as part of its enclosing function
}
@@ -106,11 +110,6 @@ func prepareFunc(fn *ir.Func) {
// Calculate parameter offsets.
types.CalcSize(fn.Type())
// Generate wrappers between Go ABI and Wasm ABI, for a wasmexport
// function.
// Must be done after InitLSym and CalcSize.
ssagen.GenWasmExportWrapper(fn)
ir.CurFunc = fn
walk.Walk(fn)
ir.CurFunc = nil // enforce no further uses of CurFunc
@@ -132,8 +131,8 @@ func compileFunctions(profile *pgoir.Profile) {
// Compile the longest functions first,
// since they're most likely to be the slowest.
// This helps avoid stragglers.
slices.SortFunc(compilequeue, func(a, b *ir.Func) int {
return cmp.Compare(len(b.Body), len(a.Body))
sort.Slice(compilequeue, func(i, j int) bool {
return len(compilequeue[i].Body) > len(compilequeue[j].Body)
})
}

View File

@@ -9,7 +9,6 @@ import (
"bytes"
"cmd/compile/internal/base"
"cmd/compile/internal/coverage"
"cmd/compile/internal/deadlocals"
"cmd/compile/internal/dwarfgen"
"cmd/compile/internal/escape"
"cmd/compile/internal/inline"
@@ -104,13 +103,6 @@ func Main(archInit func(*ssagen.ArchInfo)) {
ir.Pkgs.Runtime = types.NewPkg("go.runtime", "runtime")
ir.Pkgs.Runtime.Prefix = "runtime"
if buildcfg.Experiment.SwissMap {
// Pseudo-package that contains the compiler's builtin
// declarations for maps.
ir.Pkgs.InternalMaps = types.NewPkg("go.internal/runtime/maps", "internal/runtime/maps")
ir.Pkgs.InternalMaps.Prefix = "internal/runtime/maps"
}
// pseudo-packages used in symbol tables
ir.Pkgs.Itab = types.NewPkg("go.itab", "go.itab")
ir.Pkgs.Itab.Prefix = "go:itab"
@@ -140,7 +132,7 @@ func Main(archInit func(*ssagen.ArchInfo)) {
}
if base.Flag.SmallFrames {
ir.MaxStackVarSize = 64 * 1024
ir.MaxStackVarSize = 128 * 1024
ir.MaxImplicitStackVarSize = 16 * 1024
}
@@ -255,8 +247,6 @@ func Main(archInit func(*ssagen.ArchInfo)) {
// and doesn't benefit from dead-coding or inlining.
symABIs.GenABIWrappers()
deadlocals.Funcs(typecheck.Target.Funcs)
// Escape analysis.
// Required for moving heap allocations onto stack,
// which in turn is required by the closure implementation,

View File

@@ -0,0 +1,95 @@
// Copyright 2011 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.
// This file implements FindExportData.
package importer
import (
"bufio"
"fmt"
"io"
"strconv"
"strings"
)
func readGopackHeader(r *bufio.Reader) (name string, size int, err error) {
// See $GOROOT/include/ar.h.
hdr := make([]byte, 16+12+6+6+8+10+2)
_, err = io.ReadFull(r, hdr)
if err != nil {
return
}
// leave for debugging
if false {
fmt.Printf("header: %s", hdr)
}
s := strings.TrimSpace(string(hdr[16+12+6+6+8:][:10]))
size, err = strconv.Atoi(s)
if err != nil || hdr[len(hdr)-2] != '`' || hdr[len(hdr)-1] != '\n' {
err = fmt.Errorf("invalid archive header")
return
}
name = strings.TrimSpace(string(hdr[:16]))
return
}
// FindExportData positions the reader r at the beginning of the
// export data section of an underlying GC-created object/archive
// file by reading from it. The reader must be positioned at the
// start of the file before calling this function. The hdr result
// is the string before the export data, either "$$" or "$$B".
//
// If size is non-negative, it's the number of bytes of export data
// still available to read from r.
func FindExportData(r *bufio.Reader) (hdr string, size int, err error) {
// Read first line to make sure this is an object file.
line, err := r.ReadSlice('\n')
if err != nil {
err = fmt.Errorf("can't find export data (%v)", err)
return
}
if string(line) == "!<arch>\n" {
// Archive file. Scan to __.PKGDEF.
var name string
if name, size, err = readGopackHeader(r); err != nil {
return
}
// First entry should be __.PKGDEF.
if name != "__.PKGDEF" {
err = fmt.Errorf("go archive is missing __.PKGDEF")
return
}
// Read first line of __.PKGDEF data, so that line
// is once again the first line of the input.
if line, err = r.ReadSlice('\n'); err != nil {
err = fmt.Errorf("can't find export data (%v)", err)
return
}
}
// Now at __.PKGDEF in archive or still at beginning of file.
// Either way, line should begin with "go object ".
if !strings.HasPrefix(string(line), "go object ") {
err = fmt.Errorf("not a Go object file")
return
}
size -= len(line)
// Skip over object header to export data.
// Begins after first line starting with $$.
for line[0] != '$' {
if line, err = r.ReadSlice('\n'); err != nil {
err = fmt.Errorf("can't find export data (%v)", err)
return
}
size -= len(line)
}
hdr = string(line)
return
}

View File

@@ -2,26 +2,151 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This file implements the Import function for tests to use gc-generated object files.
// package importer implements Import for gc-generated object files.
package importer
import (
"bufio"
"bytes"
"errors"
"fmt"
"internal/exportdata"
"go/build"
"internal/pkgbits"
"io"
"os"
"os/exec"
"path/filepath"
"strings"
"sync"
"cmd/compile/internal/types2"
)
var exportMap sync.Map // package dir → func() (string, error)
// lookupGorootExport returns the location of the export data
// (normally found in the build cache, but located in GOROOT/pkg
// in prior Go releases) for the package located in pkgDir.
//
// (We use the package's directory instead of its import path
// mainly to simplify handling of the packages in src/vendor
// and cmd/vendor.)
func lookupGorootExport(pkgDir string) (string, error) {
f, ok := exportMap.Load(pkgDir)
if !ok {
var (
listOnce sync.Once
exportPath string
err error
)
f, _ = exportMap.LoadOrStore(pkgDir, func() (string, error) {
listOnce.Do(func() {
cmd := exec.Command(filepath.Join(build.Default.GOROOT, "bin", "go"), "list", "-export", "-f", "{{.Export}}", pkgDir)
cmd.Dir = build.Default.GOROOT
cmd.Env = append(os.Environ(), "PWD="+cmd.Dir, "GOROOT="+build.Default.GOROOT)
var output []byte
output, err = cmd.Output()
if err != nil {
if ee, ok := err.(*exec.ExitError); ok && len(ee.Stderr) > 0 {
err = errors.New(string(ee.Stderr))
}
return
}
exports := strings.Split(string(bytes.TrimSpace(output)), "\n")
if len(exports) != 1 {
err = fmt.Errorf("go list reported %d exports; expected 1", len(exports))
return
}
exportPath = exports[0]
})
return exportPath, err
})
}
return f.(func() (string, error))()
}
var pkgExts = [...]string{".a", ".o"} // a file from the build cache will have no extension
// FindPkg returns the filename and unique package id for an import
// path based on package information provided by build.Import (using
// the build.Default build.Context). A relative srcDir is interpreted
// relative to the current working directory.
func FindPkg(path, srcDir string) (filename, id string, err error) {
if path == "" {
return "", "", errors.New("path is empty")
}
var noext string
switch {
default:
// "x" -> "$GOPATH/pkg/$GOOS_$GOARCH/x.ext", "x"
// Don't require the source files to be present.
if abs, err := filepath.Abs(srcDir); err == nil { // see issue 14282
srcDir = abs
}
var bp *build.Package
bp, err = build.Import(path, srcDir, build.FindOnly|build.AllowBinary)
if bp.PkgObj == "" {
if bp.Goroot && bp.Dir != "" {
filename, err = lookupGorootExport(bp.Dir)
if err == nil {
_, err = os.Stat(filename)
}
if err == nil {
return filename, bp.ImportPath, nil
}
}
goto notfound
} else {
noext = strings.TrimSuffix(bp.PkgObj, ".a")
}
id = bp.ImportPath
case build.IsLocalImport(path):
// "./x" -> "/this/directory/x.ext", "/this/directory/x"
noext = filepath.Join(srcDir, path)
id = noext
case filepath.IsAbs(path):
// for completeness only - go/build.Import
// does not support absolute imports
// "/x" -> "/x.ext", "/x"
noext = path
id = path
}
if false { // for debugging
if path != id {
fmt.Printf("%s -> %s\n", path, id)
}
}
// try extensions
for _, ext := range pkgExts {
filename = noext + ext
f, statErr := os.Stat(filename)
if statErr == nil && !f.IsDir() {
return filename, id, nil
}
if err == nil {
err = statErr
}
}
notfound:
if err == nil {
return "", path, fmt.Errorf("can't find import: %q", path)
}
return "", path, fmt.Errorf("can't find import: %q: %w", path, err)
}
// Import imports a gc-generated package given its import path and srcDir, adds
// the corresponding package object to the packages map, and returns the object.
// The packages map must contain all packages already imported.
//
// This function should only be used in tests.
func Import(packages map[string]*types2.Package, path, srcDir string, lookup func(path string) (io.ReadCloser, error)) (pkg *types2.Package, err error) {
var rc io.ReadCloser
var id string
@@ -44,7 +169,7 @@ func Import(packages map[string]*types2.Package, path, srcDir string, lookup fun
rc = f
} else {
var filename string
filename, id, err = exportdata.FindPkg(path, srcDir)
filename, id, err = FindPkg(path, srcDir)
if filename == "" {
if path == "unsafe" {
return types2.Unsafe, nil
@@ -73,15 +198,56 @@ func Import(packages map[string]*types2.Package, path, srcDir string, lookup fun
defer rc.Close()
buf := bufio.NewReader(rc)
data, err := exportdata.ReadUnified(buf)
hdr, size, err := FindExportData(buf)
if err != nil {
err = fmt.Errorf("import %q: %v", path, err)
return
}
s := string(data)
input := pkgbits.NewPkgDecoder(id, s)
pkg = ReadPackage(nil, packages, input)
switch hdr {
case "$$\n":
err = fmt.Errorf("import %q: old textual export format no longer supported (recompile library)", path)
case "$$B\n":
var data []byte
var r io.Reader = buf
if size >= 0 {
r = io.LimitReader(r, int64(size))
}
data, err = io.ReadAll(r)
if err != nil {
break
}
if len(data) == 0 {
err = fmt.Errorf("import %q: missing export data", path)
break
}
exportFormat := data[0]
s := string(data[1:])
// The indexed export format starts with an 'i'; the older
// binary export format starts with a 'c', 'd', or 'v'
// (from "version"). Select appropriate importer.
switch exportFormat {
case 'u':
s = s[:strings.Index(s, "\n$$\n")]
input := pkgbits.NewPkgDecoder(id, s)
pkg = ReadPackage(nil, packages, input)
case 'i':
pkg, err = ImportData(packages, s, id)
default:
err = fmt.Errorf("import %q: old binary export format no longer supported (recompile library)", path)
}
default:
err = fmt.Errorf("import %q: unknown export data header: %q", path, hdr)
}
return
}
type byPath []*types2.Package
func (a byPath) Len() int { return len(a) }
func (a byPath) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a byPath) Less(i, j int) bool { return a[i].Path() < a[j].Path() }

View File

@@ -6,11 +6,9 @@ package importer
import (
"bytes"
"cmd/compile/internal/syntax"
"cmd/compile/internal/types2"
"fmt"
"go/build"
"internal/exportdata"
"internal/testenv"
"os"
"os/exec"
@@ -18,7 +16,6 @@ import (
"path/filepath"
"runtime"
"strings"
"sync"
"testing"
"time"
)
@@ -93,16 +90,22 @@ func TestImportTestdata(t *testing.T) {
testenv.MustHaveGoBuild(t)
testfiles := map[string][]string{
"exports.go": {"go/ast"},
"exports.go": {"go/ast", "go/token"},
"generics.go": nil,
}
if true /* was goexperiment.Unified */ {
// TODO(mdempsky): Fix test below to flatten the transitive
// Package.Imports graph. Unified IR is more precise about
// recreating the package import graph.
testfiles["exports.go"] = []string{"go/ast"}
}
for testfile, wantImports := range testfiles {
tmpdir := mktmpdir(t)
importMap := map[string]string{}
for _, pkg := range wantImports {
export, _, err := exportdata.FindPkg(pkg, "testdata")
export, _, err := FindPkg(pkg, "testdata")
if export == "" {
t.Fatalf("no export data found for %s: %v", pkg, err)
}
@@ -163,29 +166,17 @@ func TestVersionHandling(t *testing.T) {
// test that export data can be imported
_, err := Import(make(map[string]*types2.Package), pkgpath, dir, nil)
if err != nil {
// ok to fail if it fails with a 'not the start of an archive file' error for select files
// ok to fail if it fails with a no longer supported error for select files
if strings.Contains(err.Error(), "no longer supported") {
switch name {
case "test_go1.8_4.a",
"test_go1.8_5.a":
case "test_go1.7_0.a", "test_go1.7_1.a",
"test_go1.8_4.a", "test_go1.8_5.a",
"test_go1.11_6b.a", "test_go1.11_999b.a":
continue
}
// fall through
}
// ok to fail if it fails with a 'no longer supported' error for select files
if strings.Contains(err.Error(), "no longer supported") {
switch name {
case "test_go1.7_0.a",
"test_go1.7_1.a",
"test_go1.8_4.a",
"test_go1.8_5.a",
"test_go1.11_6b.a",
"test_go1.11_999b.a":
continue
}
// fall through
}
// ok to fail if it fails with a 'newer version' error for select files
// ok to fail if it fails with a newer version error for select files
if strings.Contains(err.Error(), "newer version") {
switch name {
case "test_go1.11_999i.a":
@@ -205,8 +196,6 @@ func TestVersionHandling(t *testing.T) {
}
// 2) find export data
i := bytes.Index(data, []byte("\n$$B\n")) + 5
// Export data can contain "\n$$\n" in string constants, however,
// searching for the next end of section marker "\n$$\n" is good enough for testzs.
j := bytes.Index(data[i:], []byte("\n$$\n")) + i
if i < 0 || j < 0 || i > j {
t.Fatalf("export data section not found (i = %d, j = %d)", i, j)
@@ -279,7 +268,7 @@ var importedObjectTests = []struct {
{"math.Pi", "const Pi untyped float"},
{"math.Sin", "func Sin(x float64) float64"},
{"go/ast.NotNilFilter", "func NotNilFilter(_ string, v reflect.Value) bool"},
{"internal/exportdata.FindPkg", "func FindPkg(path string, srcDir string) (filename string, id string, err error)"},
{"go/internal/gcimporter.FindPkg", "func FindPkg(path string, srcDir string) (filename string, id string, err error)"},
// interfaces
{"context.Context", "type Context interface{Deadline() (deadline time.Time, ok bool); Done() <-chan struct{}; Err() error; Value(key any) any}"},
@@ -347,7 +336,14 @@ func verifyInterfaceMethodRecvs(t *testing.T, named *types2.Named, level int) {
// The unified IR importer always sets interface method receiver
// parameters to point to the Interface type, rather than the Named.
// See #49906.
var want types2.Type = iface
//
// TODO(mdempsky): This is only true for the types2 importer. For
// the go/types importer, we duplicate the Interface and rewrite its
// receiver methods to match historical behavior.
var want types2.Type = named
if true /* was goexperiment.Unified */ {
want = iface
}
// check explicitly declared methods
for i := 0; i < iface.NumExplicitMethods(); i++ {
@@ -441,7 +437,7 @@ func TestIssue13566(t *testing.T) {
t.Fatal(err)
}
jsonExport, _, err := exportdata.FindPkg("encoding/json", "testdata")
jsonExport, _, err := FindPkg("encoding/json", "testdata")
if jsonExport == "" {
t.Fatalf("no export data found for encoding/json: %v", err)
}
@@ -586,6 +582,23 @@ func TestIssue25596(t *testing.T) {
compileAndImportPkg(t, "issue25596")
}
func TestIssue70394(t *testing.T) {
testenv.MustHaveGoBuild(t)
// This package only handles gc export data.
if runtime.Compiler != "gc" {
t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
}
pkg := compileAndImportPkg(t, "alias")
obj := lookupObj(t, pkg.Scope(), "A")
typ := obj.Type()
if _, ok := typ.(*types2.Alias); !ok {
t.Fatalf("type of %s is %s, wanted an alias", obj, typ)
}
}
func importPkg(t *testing.T, path, srcDir string) *types2.Package {
pkg, err := Import(make(map[string]*types2.Package), path, srcDir, nil)
if err != nil {
@@ -610,66 +623,3 @@ func lookupObj(t *testing.T, scope *types2.Scope, name string) types2.Object {
t.Fatalf("%s not found", name)
return nil
}
// importMap implements the types2.Importer interface.
type importMap map[string]*types2.Package
func (m importMap) Import(path string) (*types2.Package, error) { return m[path], nil }
func TestIssue69912(t *testing.T) {
testenv.MustHaveGoBuild(t)
// This package only handles gc export data.
if runtime.Compiler != "gc" {
t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
}
tmpdir := t.TempDir()
testoutdir := filepath.Join(tmpdir, "testdata")
if err := os.Mkdir(testoutdir, 0700); err != nil {
t.Fatalf("making output dir: %v", err)
}
compile(t, "testdata", "issue69912.go", testoutdir, nil)
issue69912, err := Import(make(map[string]*types2.Package), "./testdata/issue69912", tmpdir, nil)
if err != nil {
t.Fatal(err)
}
check := func(pkgname, src string, imports importMap) (*types2.Package, error) {
f, err := syntax.Parse(syntax.NewFileBase(pkgname), strings.NewReader(src), nil, nil, 0)
if err != nil {
return nil, err
}
config := &types2.Config{
Importer: imports,
}
return config.Check(pkgname, []*syntax.File{f}, nil)
}
// Use the resulting package concurrently, via dot-imports, to exercise the
// race of issue #69912.
const pSrc = `package p
import . "issue69912"
type S struct {
f T
}
`
importer := importMap{
"issue69912": issue69912,
}
var wg sync.WaitGroup
for range 10 {
wg.Add(1)
go func() {
defer wg.Done()
if _, err := check("p", pSrc, importer); err != nil {
t.Errorf("Check failed: %v", err)
}
}()
}
wg.Wait()
}

Some files were not shown because too many files have changed in this diff Show More