mirror of
https://github.com/golang/go.git
synced 2026-01-30 23:52:05 +03:00
Compare commits
2 Commits
release-br
...
dev.inline
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
71aaa8bde1 | ||
|
|
3aba453b66 |
45
.github/ISSUE_TEMPLATE/00-bug.md
vendored
Normal file
45
.github/ISSUE_TEMPLATE/00-bug.md
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
---
|
||||
name: Bugs
|
||||
about: The go command, standard library, or anything else
|
||||
title: "affected/package: "
|
||||
---
|
||||
|
||||
<!--
|
||||
Please answer these questions before submitting your issue. Thanks!
|
||||
-->
|
||||
|
||||
### What version of Go are you using (`go version`)?
|
||||
|
||||
<pre>
|
||||
$ go version
|
||||
|
||||
</pre>
|
||||
|
||||
### Does this issue reproduce with the latest release?
|
||||
|
||||
|
||||
|
||||
### What operating system and processor architecture are you using (`go env`)?
|
||||
|
||||
<details><summary><code>go env</code> Output</summary><br><pre>
|
||||
$ go env
|
||||
|
||||
</pre></details>
|
||||
|
||||
### What did you do?
|
||||
|
||||
<!--
|
||||
If possible, provide a recipe for reproducing the error.
|
||||
A complete runnable program is good.
|
||||
A link on go.dev/play is best.
|
||||
-->
|
||||
|
||||
|
||||
|
||||
### What did you expect to see?
|
||||
|
||||
|
||||
|
||||
### What did you see instead?
|
||||
|
||||
|
||||
94
.github/ISSUE_TEMPLATE/00-bug.yml
vendored
94
.github/ISSUE_TEMPLATE/00-bug.yml
vendored
@@ -1,94 +0,0 @@
|
||||
# https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/configuring-issue-templates-for-your-repository#creating-issue-forms
|
||||
# https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema
|
||||
name: Bugs
|
||||
description: The go command, standard library, or anything else
|
||||
title: "import/path: issue title"
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for helping us improve! 🙏 Please answer these questions and provide as much information as possible about your problem.
|
||||
|
||||
- type: input
|
||||
id: go-version
|
||||
attributes:
|
||||
label: Go version
|
||||
description: |
|
||||
What version of Go are you using (`go version`)?
|
||||
|
||||
Note: we only [support](https://go.dev/doc/devel/release#policy) the two most recent major releases.
|
||||
placeholder: ex. go version go1.20.7 darwin/arm64
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: go-env
|
||||
attributes:
|
||||
label: "Output of `go env` in your module/workspace:"
|
||||
placeholder: |
|
||||
GO111MODULE=""
|
||||
GOARCH="arm64"
|
||||
GOBIN="/Users/gopher/go/bin"
|
||||
GOCACHE="/Users/gopher/go/cache"
|
||||
GOENV="/Users/gopher/Library/Application Support/go/env"
|
||||
GOEXE=""
|
||||
GOEXPERIMENT=""
|
||||
GOFLAGS=""
|
||||
GOHOSTARCH="arm64"
|
||||
GOHOSTOS="darwin"
|
||||
GOINSECURE=""
|
||||
GOMODCACHE="/Users/gopher/go/pkg/mod"
|
||||
GONOPROXY=""
|
||||
GONOSUMDB=""
|
||||
GOOS="darwin"
|
||||
GOPATH="/Users/gopher/go"
|
||||
GOPRIVATE=""
|
||||
GOPROXY="https://proxy.golang.org,direct"
|
||||
GOROOT="/usr/local/go"
|
||||
GOSUMDB="sum.golang.org"
|
||||
GOTMPDIR=""
|
||||
GOTOOLDIR="/usr/local/go/pkg/tool/darwin_arm64"
|
||||
GOVCS=""
|
||||
GOVERSION="go1.20.7"
|
||||
GCCGO="gccgo"
|
||||
AR="ar"
|
||||
CC="clang"
|
||||
CXX="clang++"
|
||||
CGO_ENABLED="1"
|
||||
GOMOD="/dev/null"
|
||||
GOWORK=""
|
||||
CGO_CFLAGS="-O2 -g"
|
||||
CGO_CPPFLAGS=""
|
||||
CGO_CXXFLAGS="-O2 -g"
|
||||
CGO_FFLAGS="-O2 -g"
|
||||
CGO_LDFLAGS="-O2 -g"
|
||||
PKG_CONFIG="pkg-config"
|
||||
GOGCCFLAGS="-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/44/nbbyll_10jd0z8rj_qxm43740000gn/T/go-build2331607515=/tmp/go-build -gno-record-gcc-switches -fno-common"
|
||||
render: shell
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: what-did-you-do
|
||||
attributes:
|
||||
label: "What did you do?"
|
||||
description: "If possible, provide a recipe for reproducing the error. A complete runnable program is good. A link on [go.dev/play](https://go.dev/play) is best."
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: actual-behavior
|
||||
attributes:
|
||||
label: "What did you see happen?"
|
||||
description: Command invocations and their associated output, functions with their arguments and return results, full stacktraces for panics (upload a file if it is very long), etc. Prefer copying text output over using screenshots.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: expected-behavior
|
||||
attributes:
|
||||
label: "What did you expect to see?"
|
||||
description: Why is the current output incorrect, and any additional context we may need to understand the issue.
|
||||
validations:
|
||||
required: true
|
||||
49
.github/ISSUE_TEMPLATE/01-pkgsite.md
vendored
Normal file
49
.github/ISSUE_TEMPLATE/01-pkgsite.md
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
---
|
||||
name: Pkg.go.dev bugs or feature requests
|
||||
about: Issues or feature requests for the documentation site
|
||||
title: "x/pkgsite: "
|
||||
labels: pkgsite
|
||||
---
|
||||
|
||||
<!--
|
||||
Please answer these questions before submitting your issue. Thanks!
|
||||
-->
|
||||
|
||||
### What is the URL of the page with the issue?
|
||||
|
||||
|
||||
|
||||
### What is your user agent?
|
||||
|
||||
<!--
|
||||
You can find your user agent here:
|
||||
https://www.google.com/search?q=what+is+my+user+agent
|
||||
-->
|
||||
|
||||
|
||||
|
||||
### Screenshot
|
||||
|
||||
<!--
|
||||
Please paste a screenshot of the page.
|
||||
-->
|
||||
|
||||
|
||||
|
||||
### What did you do?
|
||||
|
||||
<!--
|
||||
If possible, provide a recipe for reproducing the error.
|
||||
|
||||
Starting with a Private/Incognito tab/window may help rule out problematic browser extensions.
|
||||
-->
|
||||
|
||||
|
||||
|
||||
### What did you expect to see?
|
||||
|
||||
|
||||
|
||||
### What did you see instead?
|
||||
|
||||
|
||||
47
.github/ISSUE_TEMPLATE/01-pkgsite.yml
vendored
47
.github/ISSUE_TEMPLATE/01-pkgsite.yml
vendored
@@ -1,47 +0,0 @@
|
||||
name: Pkg.go.dev bugs or feature requests
|
||||
description: Issues or feature requests for the documentation site
|
||||
title: "x/pkgsite: issue title"
|
||||
labels: ["pkgsite"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: "Please answer these questions before submitting your issue. Thanks!"
|
||||
- type: input
|
||||
id: url
|
||||
attributes:
|
||||
label: "What is the URL of the page with the issue?"
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: user-agent
|
||||
attributes:
|
||||
label: "What is your user agent?"
|
||||
description: "You can find your user agent here: https://www.google.com/search?q=what+is+my+user+agent"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: screenshot
|
||||
attributes:
|
||||
label: "Screenshot"
|
||||
description: "Please paste a screenshot of the page."
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: what-did-you-do
|
||||
attributes:
|
||||
label: "What did you do?"
|
||||
description: "If possible, provide a recipe for reproducing the error. Starting with a Private/Incognito tab/window may help rule out problematic browser extensions."
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: actual-behavior
|
||||
attributes:
|
||||
label: "What did you see happen?"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: expected-behavior
|
||||
attributes:
|
||||
label: "What did you expect to see?"
|
||||
validations:
|
||||
required: true
|
||||
39
.github/ISSUE_TEMPLATE/02-pkgsite-removal.md
vendored
Normal file
39
.github/ISSUE_TEMPLATE/02-pkgsite-removal.md
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
---
|
||||
name: Pkg.go.dev package removal request
|
||||
about: Request a package be removed from the documentation site (pkg.go.dev)
|
||||
title: "x/pkgsite: package removal request for [type path here]"
|
||||
labels: pkgsite/package-removal
|
||||
---
|
||||
|
||||
<!--
|
||||
Please answer these questions before submitting your issue. Thanks!
|
||||
-->
|
||||
|
||||
### What is the path of the package that you would like to have removed?
|
||||
|
||||
<!---
|
||||
We can remove packages with a shared path prefix.
|
||||
For example, a request for "github.com/author" would remove all pkg.go.dev pages with that package path prefix.
|
||||
--->
|
||||
|
||||
|
||||
|
||||
### Are you the owner of this package?
|
||||
|
||||
<!---
|
||||
Only the package owners can request to have their packages removed from pkg.go.dev.
|
||||
--->
|
||||
|
||||
|
||||
|
||||
### What is the reason that you could not retract this package instead?
|
||||
|
||||
<!---
|
||||
If you would like to have your module removed from pkg.go.dev, we recommend that you retract them, so that they can be removed from the go command and proxy.golang.org as well.
|
||||
|
||||
Retracting a module version involves adding a retract directive to your go.mod file and publishing a new version. For example: https://github.com/jba/retract-demo/blob/main/go.mod#L5-L8
|
||||
|
||||
See https://pkg.go.dev/about#removing-a-package for additional tips on retractions.
|
||||
--->
|
||||
|
||||
|
||||
42
.github/ISSUE_TEMPLATE/02-pkgsite-removal.yml
vendored
42
.github/ISSUE_TEMPLATE/02-pkgsite-removal.yml
vendored
@@ -1,42 +0,0 @@
|
||||
name: Pkg.go.dev package removal request
|
||||
description: Request a package be removed from the documentation site (pkg.go.dev)
|
||||
title: "x/pkgsite: package removal request for [type path here]"
|
||||
labels: ["pkgsite/package-removal"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: "Please answer these questions before submitting your issue. Thanks!"
|
||||
- type: input
|
||||
id: package-path
|
||||
attributes:
|
||||
label: "What is the path of the package that you would like to have removed?"
|
||||
description: |
|
||||
We can remove packages with a shared path prefix.
|
||||
For example, a request for 'github.com/author' would remove all pkg.go.dev pages with that package path prefix.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: package-owner
|
||||
attributes:
|
||||
label: "Are you the owner of this package?"
|
||||
description: |
|
||||
Only the package owners can request to have their packages removed from pkg.go.dev.
|
||||
If the package path doesn't include your github username, please provide some other form of proof of ownership.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: retraction-reason
|
||||
attributes:
|
||||
label: "What is the reason that you could not retract this package instead?"
|
||||
description: |
|
||||
Requesting we remove a module here only hides the generated documentation on pkg.go.dev.
|
||||
It does not affect the behaviour of proxy.golang.org or the go command.
|
||||
Instead we recommend using the retract directive which will be processed by all 3 of the above.
|
||||
|
||||
If you have deleted your repo, please recreate it and publish a retraction.
|
||||
|
||||
Retracting a module version involves adding a retract directive to your go.mod file and publishing a new version.
|
||||
For example: https://github.com/jba/retract-demo/blob/main/go.mod#L5-L8.
|
||||
See https://pkg.go.dev/about#removing-a-package for additional tips on retractions.
|
||||
validations:
|
||||
required: true
|
||||
61
.github/ISSUE_TEMPLATE/03-gopls.md
vendored
Normal file
61
.github/ISSUE_TEMPLATE/03-gopls.md
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
---
|
||||
name: Gopls bugs or feature requests
|
||||
about: Issues or feature requests for the Go language server (gopls)
|
||||
title: "x/tools/gopls: "
|
||||
labels: gopls Tools
|
||||
---
|
||||
|
||||
<!--
|
||||
Please answer these questions before submitting your issue. Thanks!
|
||||
-->
|
||||
|
||||
### gopls version
|
||||
|
||||
<!--
|
||||
Output of `gopls -v version` on the command line
|
||||
-->
|
||||
|
||||
|
||||
|
||||
### go env
|
||||
|
||||
<!--
|
||||
Output of `go env` on the command line in your workspace directory
|
||||
-->
|
||||
|
||||
|
||||
### What did you do?
|
||||
|
||||
<!--
|
||||
If possible, provide a recipe for reproducing the error.
|
||||
A complete runnable program is good.
|
||||
A link on go.dev/play is better.
|
||||
A failing unit test is the best.
|
||||
-->
|
||||
|
||||
|
||||
|
||||
### What did you expect to see?
|
||||
|
||||
|
||||
|
||||
### What did you see instead?
|
||||
|
||||
|
||||
|
||||
### Editor and settings
|
||||
|
||||
<!--
|
||||
Your editor and any settings you have configured (for example, your VSCode settings.json file)
|
||||
-->
|
||||
|
||||
|
||||
|
||||
### Logs
|
||||
|
||||
<!--
|
||||
If possible please include gopls logs. Instructions for capturing them can be found here:
|
||||
https://github.com/golang/tools/blob/master/gopls/doc/troubleshooting.md#capture-logs
|
||||
-->
|
||||
|
||||
|
||||
56
.github/ISSUE_TEMPLATE/03-gopls.yml
vendored
56
.github/ISSUE_TEMPLATE/03-gopls.yml
vendored
@@ -1,56 +0,0 @@
|
||||
name: Gopls bugs or feature requests
|
||||
description: Issues or feature requests for the Go language server (gopls)
|
||||
title: "x/tools/gopls: issue title"
|
||||
labels: ["gopls", "Tools"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: "Please answer these questions before submitting your issue. Thanks!"
|
||||
- type: input
|
||||
id: gopls-version
|
||||
attributes:
|
||||
label: "gopls version"
|
||||
description: "Output of `gopls -v version` on the command line"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: go-env
|
||||
attributes:
|
||||
label: "go env"
|
||||
description: "Output of `go env` on the command line in your workspace directory"
|
||||
render: shell
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: what-did-you-do
|
||||
attributes:
|
||||
label: "What did you do?"
|
||||
description: "If possible, provide a recipe for reproducing the error. A complete runnable program is good. A link on [go.dev/play](https://go.dev/play) is better. A failing unit test is the best."
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: actual-behavior
|
||||
attributes:
|
||||
label: "What did you see happen?"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: expected-behavior
|
||||
attributes:
|
||||
label: "What did you expect to see?"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: editor-and-settings
|
||||
attributes:
|
||||
label: "Editor and settings"
|
||||
description: "Your editor and any settings you have configured (for example, your VSCode settings.json file)"
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: "Logs"
|
||||
description: "If possible please include gopls logs. Instructions for capturing them can be found here: https://github.com/golang/tools/blob/master/gopls/doc/troubleshooting.md#capture-logs"
|
||||
validations:
|
||||
required: false
|
||||
51
.github/ISSUE_TEMPLATE/04-vuln.md
vendored
Normal file
51
.github/ISSUE_TEMPLATE/04-vuln.md
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
---
|
||||
name: Go vulnerability management - bugs and feature requests
|
||||
about: Issues or feature requests about Go vulnerability management
|
||||
title: "x/vuln: "
|
||||
labels: "vulncheck or vulndb"
|
||||
---
|
||||
|
||||
<!--
|
||||
Please answer these questions before submitting your issue. Thanks!
|
||||
|
||||
To add a new vulnerability to the Go vulnerability database
|
||||
(https://vuln.go.dev), see https://go.dev/s/vulndb-report-new.
|
||||
|
||||
To report an issue about a report, see https://go.dev/s/vulndb-report-feedback.
|
||||
-->
|
||||
|
||||
### What version of Go are you using (`go version`)?
|
||||
|
||||
<pre>
|
||||
$ go version
|
||||
|
||||
</pre>
|
||||
|
||||
### Does this issue reproduce at the latest version of golang.org/x/vuln?
|
||||
|
||||
|
||||
|
||||
### What operating system and processor architecture are you using (`go env`)?
|
||||
|
||||
<details><summary><code>go env</code> Output</summary><br><pre>
|
||||
$ go env
|
||||
|
||||
</pre></details>
|
||||
|
||||
### What did you do?
|
||||
|
||||
<!--
|
||||
If possible, provide a recipe for reproducing the error.
|
||||
A complete runnable program is good.
|
||||
A link on go.dev/play is best.
|
||||
-->
|
||||
|
||||
|
||||
|
||||
### What did you expect to see?
|
||||
|
||||
|
||||
|
||||
### What did you see instead?
|
||||
|
||||
|
||||
52
.github/ISSUE_TEMPLATE/04-vuln.yml
vendored
52
.github/ISSUE_TEMPLATE/04-vuln.yml
vendored
@@ -1,52 +0,0 @@
|
||||
name: Go vulnerability management - bugs and feature requests
|
||||
description: Issues or feature requests about Go vulnerability management
|
||||
title: "x/vuln: issue title"
|
||||
labels: ["vulncheck or vulndb"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: "Please answer these questions before submitting your issue. Thanks! To add a new vulnerability to the Go vulnerability database (https://vuln.go.dev), see https://go.dev/s/vulndb-report-new. To report an issue about a report, see https://go.dev/s/vulndb-report-feedback."
|
||||
- type: textarea
|
||||
id: govulncheck-version
|
||||
attributes:
|
||||
label: govulncheck version
|
||||
description: What version of govulncheck are you using (`govulncheck -version`)?
|
||||
placeholder: |
|
||||
Go: devel go1.22-0262ea1ff9 Thu Oct 26 18:46:50 2023 +0000
|
||||
Scanner: govulncheck@v1.0.2-0.20231108200754-fcf7dff7b242
|
||||
DB: https://vuln.go.dev
|
||||
DB updated: 2023-11-21 15:39:17 +0000 UTC
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: reproduce-latest-version
|
||||
attributes:
|
||||
label: "Does this issue reproduce at the latest version of golang.org/x/vuln?"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: go-env
|
||||
attributes:
|
||||
label: "Output of `go env` in your module/workspace:"
|
||||
render: shell
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: what-did-you-do
|
||||
attributes:
|
||||
label: "What did you do?"
|
||||
description: "If possible, provide a recipe for reproducing the error. A complete runnable program is good. A link on [go.dev/play](https://go.dev/play) is best."
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: actual-behavior
|
||||
attributes:
|
||||
label: "What did you see happen?"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: expected-behavior
|
||||
attributes:
|
||||
label: "What did you expect to see?"
|
||||
validations:
|
||||
required: true
|
||||
13
.github/ISSUE_TEMPLATE/10-proposal.md
vendored
Normal file
13
.github/ISSUE_TEMPLATE/10-proposal.md
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
name: Proposals
|
||||
about: New external API or other notable changes
|
||||
title: "proposal: affected/package: "
|
||||
labels: Proposal
|
||||
---
|
||||
|
||||
<!--
|
||||
Our proposal process is documented here:
|
||||
https://go.dev/s/proposal-process
|
||||
-->
|
||||
|
||||
|
||||
15
.github/ISSUE_TEMPLATE/10-proposal.yml
vendored
15
.github/ISSUE_TEMPLATE/10-proposal.yml
vendored
@@ -1,15 +0,0 @@
|
||||
name: Proposals
|
||||
description: New external API or other notable changes
|
||||
title: "proposal: import/path: proposal title"
|
||||
labels: ["Proposal"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: "Our proposal process is documented here: https://go.dev/s/proposal-process"
|
||||
- type: textarea
|
||||
id: proposal-details
|
||||
attributes:
|
||||
label: "Proposal Details"
|
||||
description: "Please provide the details of your proposal here."
|
||||
validations:
|
||||
required: true
|
||||
52
.github/ISSUE_TEMPLATE/11-language-change.md
vendored
Normal file
52
.github/ISSUE_TEMPLATE/11-language-change.md
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
---
|
||||
name: Language Change Proposals
|
||||
about: Changes to the language
|
||||
title: "proposal: Go 2: "
|
||||
labels: Proposal Go2 LanguageChange
|
||||
---
|
||||
|
||||
<!--
|
||||
Our process for evaluating language changes can be found here:
|
||||
https://go.googlesource.com/proposal/+/refs/heads/master#language-changes
|
||||
-->
|
||||
|
||||
### Author background
|
||||
|
||||
- **Would you consider yourself a novice, intermediate, or experienced Go programmer?**
|
||||
- **What other languages do you have experience with?**
|
||||
|
||||
### Related proposals
|
||||
|
||||
- **Has this idea, or one like it, been proposed before?**
|
||||
- **If so, how does this proposal differ?**
|
||||
- **Does this affect error handling?**
|
||||
- **If so, how does this differ from previous error handling proposals?**
|
||||
- **Is this about generics?**
|
||||
- **If so, how does this relate to the accepted design and other generics proposals?**
|
||||
|
||||
### Proposal
|
||||
|
||||
- **What is the proposed change?**
|
||||
- **Who does this proposal help, and why?**
|
||||
- **Please describe as precisely as possible the change to the language.**
|
||||
- **What would change in the language spec?**
|
||||
- **Please also describe the change informally, as in a class teaching Go.**
|
||||
- **Is this change backward compatible?**
|
||||
- Breaking the Go 1 compatibility guarantee is a large cost and requires a large benefit.
|
||||
Show example code before and after the change.
|
||||
- **Before**
|
||||
- **After**
|
||||
- **Orthogonality: how does this change interact or overlap with existing features?**
|
||||
- **Is the goal of this change a performance improvement?**
|
||||
- **If so, what quantifiable improvement should we expect?**
|
||||
- **How would we measure it?**
|
||||
|
||||
### Costs
|
||||
|
||||
- **Would this change make Go easier or harder to learn, and why?**
|
||||
- **What is the cost of this proposal? (Every language change has a cost).**
|
||||
- **How many tools (such as vet, gopls, gofmt, goimports, etc.) would be affected?**
|
||||
- **What is the compile time cost?**
|
||||
- **What is the run time cost?**
|
||||
- **Can you describe a possible implementation?**
|
||||
- **Do you have a prototype? (This is not required.)**
|
||||
165
.github/ISSUE_TEMPLATE/11-language-change.yml
vendored
165
.github/ISSUE_TEMPLATE/11-language-change.yml
vendored
@@ -1,165 +0,0 @@
|
||||
name: Language Change Proposals
|
||||
description: Changes to the language
|
||||
labels: ["Proposal", "v2", "LanguageChange"]
|
||||
title: "proposal: Go 2: proposal title"
|
||||
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
## Our process for evaluating language changes can be found [here](https://go.googlesource.com/proposal/+/refs/heads/master#language-changes)
|
||||
|
||||
- type: dropdown
|
||||
id: author-go-experience
|
||||
attributes:
|
||||
label: "Go Programming Experience"
|
||||
description: "Would you consider yourself a novice, intermediate, or experienced Go programmer?"
|
||||
options:
|
||||
- "Novice"
|
||||
- "Intermediate"
|
||||
- "Experienced"
|
||||
default: 1
|
||||
|
||||
- type: input
|
||||
id: author-other-languages-experience
|
||||
attributes:
|
||||
label: "Other Languages Experience"
|
||||
description: "What other languages do you have experience with?"
|
||||
placeholder: "Go, Python, JS, Rust"
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: checkboxes
|
||||
id: related-idea
|
||||
attributes:
|
||||
label: "Related Idea"
|
||||
options:
|
||||
- label: "Has this idea, or one like it, been proposed before?"
|
||||
- label: "Does this affect error handling?"
|
||||
- label: "Is this about generics?"
|
||||
- label: "Is this change backward compatible? Breaking the Go 1 compatibility guarantee is a large cost and requires a large benefit"
|
||||
|
||||
- type: textarea
|
||||
id: related-proposals
|
||||
attributes:
|
||||
label: Has this idea, or one like it, been proposed before?
|
||||
description: If so, how does this proposal differ?
|
||||
placeholder: |
|
||||
Yes or No
|
||||
|
||||
If yes,
|
||||
1. Mention the related proposals
|
||||
2. then describe how this proposal differs
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: error-handling-proposal
|
||||
attributes:
|
||||
label: Does this affect error handling?
|
||||
description: If so, how does this differ from previous error handling proposals?
|
||||
placeholder: |
|
||||
Yes or No
|
||||
|
||||
If yes,
|
||||
1.how does this differ from previous error handling proposals?
|
||||
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: generics-proposal
|
||||
attributes:
|
||||
label: Is this about generics?
|
||||
description: If so, how does this relate to the accepted design and other generics proposals?
|
||||
placeholder: |
|
||||
Yes or No
|
||||
|
||||
If yes,
|
||||
1. how does this relate to the accepted design and other generics proposals?
|
||||
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: proposal
|
||||
attributes:
|
||||
label: "Proposal"
|
||||
description: "What is the proposed change? Who does this proposal help, and why? Please describe as precisely as possible the change to the language."
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: language-spec-changes
|
||||
attributes:
|
||||
label: "Language Spec Changes"
|
||||
description: "What would change in the language spec?"
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: informal-change
|
||||
attributes:
|
||||
label: "Informal Change"
|
||||
description: "Please also describe the change informally, as in a class teaching Go."
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: go-backwards-compatiblity
|
||||
attributes:
|
||||
label: Is this change backward compatible?
|
||||
description: Breaking the Go 1 compatibility guarantee is a large cost and requires a large benefit.
|
||||
placeholder: |
|
||||
Yes or No
|
||||
|
||||
If yes,
|
||||
1. Show example code before and after the change.
|
||||
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: orthogonality
|
||||
attributes:
|
||||
label: "Orthogonality: How does this change interact or overlap with existing features?"
|
||||
description: "Is the goal of this change a performance improvement? If so, what quantifiable improvement should we expect? How would we measure it?"
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: learning-curve
|
||||
attributes:
|
||||
label: "Would this change make Go easier or harder to learn, and why?"
|
||||
|
||||
- type: textarea
|
||||
id: cost-description
|
||||
attributes:
|
||||
label: "Cost Description"
|
||||
description: "What is the cost of this proposal? (Every language change has a cost)"
|
||||
|
||||
- type: input
|
||||
id: go-toolchain
|
||||
attributes:
|
||||
label: Changes to Go ToolChain
|
||||
description: "How many tools (such as vet, gopls, gofmt, goimports, etc.) would be affected? "
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: input
|
||||
id: perf-costs
|
||||
attributes:
|
||||
label: Performance Costs
|
||||
description: "What is the compile time cost? What is the run time cost? "
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: prototype
|
||||
attributes:
|
||||
label: "Prototype"
|
||||
description: "Can you describe a possible implementation?"
|
||||
validations:
|
||||
required: false
|
||||
|
||||
68
.github/ISSUE_TEMPLATE/12-telemetry.yml
vendored
68
.github/ISSUE_TEMPLATE/12-telemetry.yml
vendored
@@ -1,68 +0,0 @@
|
||||
name: Go Telemetry Proposals
|
||||
description: New telemetry counter or update on an existing one
|
||||
title: "x/telemetry/config: proposal title"
|
||||
labels: ["Telemetry-Proposal"]
|
||||
projects: ["golang/29"]
|
||||
body:
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Counter names
|
||||
description: Names of counters to add or update.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Description
|
||||
description: What do these counters measure?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Rationale
|
||||
description: |
|
||||
Why is the counter important?
|
||||
For example, what new insights will it provide, and how will that information be used?
|
||||
If this is about updating existing counters, why is the change necessary?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Do the counters carry sensitive user information?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: How?
|
||||
description: |
|
||||
How do we plan to compute the info?
|
||||
If available, include the code location or cl that uses the golang.org/x/telemetry/counter API.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Proposed Graph Config
|
||||
description: |
|
||||
Approved telemetry counters are maintained as [Go Telemetry Graph Config](https://golang.org/x/telemetry/internal/graphconfig) records.
|
||||
Please draft the record entry for your proposal here.
|
||||
If multiple records need to be included, separate them with `---` lines.
|
||||
You can check the list of the approved counters and their current configuration in [config.txt](https://go.googlesource.com/telemetry/+/master/internal/configgen/config.txt).
|
||||
render: Text
|
||||
value: |
|
||||
counter: gopls/bug
|
||||
title: Gopls bug reports
|
||||
description: Stacks of bugs encountered on the gopls server.
|
||||
type: partition, histogram, stack # choose only one.
|
||||
program: golang.org/x/tools/gopls
|
||||
counter: gopls/bug
|
||||
depth: 16 # only if type is stack.
|
||||
version: v0.13.0 # the first binary version containing this counter.
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: New or Update
|
||||
description: Is this a new counter? See [config.txt](https://go.googlesource.com/telemetry/+/master/internal/configgen/config.txt) for the list of approved counters.
|
||||
options:
|
||||
- New
|
||||
- Update
|
||||
default: 0
|
||||
2
.github/ISSUE_TEMPLATE/config.yml
vendored
2
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,4 +1,4 @@
|
||||
blank_issues_enabled: true
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Questions
|
||||
about: Please use one of the forums for questions or general discussions
|
||||
|
||||
@@ -10,4 +10,4 @@ part of that page.
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
See https://go.dev/security/policy for how to report a vulnerability.
|
||||
See https://go.dev/security for how to report a vulnerability.
|
||||
|
||||
@@ -60,9 +60,7 @@ pkg crypto/tls, method (*QUICConn) Close() error #44886
|
||||
pkg crypto/tls, method (*QUICConn) ConnectionState() ConnectionState #44886
|
||||
pkg crypto/tls, method (*QUICConn) HandleData(QUICEncryptionLevel, []uint8) error #44886
|
||||
pkg crypto/tls, method (*QUICConn) NextEvent() QUICEvent #44886
|
||||
pkg crypto/tls, method (*QUICConn) SendSessionTicket(QUICSessionTicketOptions) error #60107
|
||||
pkg crypto/tls, type QUICSessionTicketOptions struct #60107
|
||||
pkg crypto/tls, type QUICSessionTicketOptions struct, EarlyData bool #60107
|
||||
pkg crypto/tls, method (*QUICConn) SendSessionTicket(bool) error #60107
|
||||
pkg crypto/tls, method (*QUICConn) SetTransportParameters([]uint8) #44886
|
||||
pkg crypto/tls, method (*QUICConn) Start(context.Context) error #44886
|
||||
pkg crypto/tls, method (QUICEncryptionLevel) String() string #44886
|
||||
@@ -167,12 +165,7 @@ pkg errors, var ErrUnsupported error #41198
|
||||
pkg flag, func BoolFunc(string, string, func(string) error) #53747
|
||||
pkg flag, method (*FlagSet) BoolFunc(string, string, func(string) error) #53747
|
||||
pkg go/ast, func IsGenerated(*File) bool #28089
|
||||
pkg go/ast, func NewPackage //deprecated #52463
|
||||
pkg go/ast, type File struct, GoVersion string #59033
|
||||
pkg go/ast, type Importer //deprecated #52463
|
||||
pkg go/ast, type Object //deprecated #52463
|
||||
pkg go/ast, type Package //deprecated #52463
|
||||
pkg go/ast, type Scope //deprecated #52463
|
||||
pkg go/build/constraint, func GoVersion(Expr) string #59033
|
||||
pkg go/build, type Directive struct #56986
|
||||
pkg go/build, type Directive struct, Pos token.Position #56986
|
||||
@@ -226,18 +219,18 @@ pkg log/slog, func Any(string, interface{}) Attr #56345
|
||||
pkg log/slog, func AnyValue(interface{}) Value #56345
|
||||
pkg log/slog, func Bool(string, bool) Attr #56345
|
||||
pkg log/slog, func BoolValue(bool) Value #56345
|
||||
pkg log/slog, func DebugContext(context.Context, string, ...interface{}) #61200
|
||||
pkg log/slog, func DebugCtx(context.Context, string, ...interface{}) #56345
|
||||
pkg log/slog, func Debug(string, ...interface{}) #56345
|
||||
pkg log/slog, func Default() *Logger #56345
|
||||
pkg log/slog, func Duration(string, time.Duration) Attr #56345
|
||||
pkg log/slog, func DurationValue(time.Duration) Value #56345
|
||||
pkg log/slog, func ErrorContext(context.Context, string, ...interface{}) #61200
|
||||
pkg log/slog, func ErrorCtx(context.Context, string, ...interface{}) #56345
|
||||
pkg log/slog, func Error(string, ...interface{}) #56345
|
||||
pkg log/slog, func Float64(string, float64) Attr #56345
|
||||
pkg log/slog, func Float64Value(float64) Value #56345
|
||||
pkg log/slog, func Group(string, ...interface{}) Attr #59204
|
||||
pkg log/slog, func GroupValue(...Attr) Value #56345
|
||||
pkg log/slog, func InfoContext(context.Context, string, ...interface{}) #61200
|
||||
pkg log/slog, func InfoCtx(context.Context, string, ...interface{}) #56345
|
||||
pkg log/slog, func Info(string, ...interface{}) #56345
|
||||
pkg log/slog, func Int64(string, int64) Attr #56345
|
||||
pkg log/slog, func Int64Value(int64) Value #56345
|
||||
@@ -257,7 +250,7 @@ pkg log/slog, func Time(string, time.Time) Attr #56345
|
||||
pkg log/slog, func TimeValue(time.Time) Value #56345
|
||||
pkg log/slog, func Uint64(string, uint64) Attr #56345
|
||||
pkg log/slog, func Uint64Value(uint64) Value #56345
|
||||
pkg log/slog, func WarnContext(context.Context, string, ...interface{}) #61200
|
||||
pkg log/slog, func WarnCtx(context.Context, string, ...interface{}) #56345
|
||||
pkg log/slog, func Warn(string, ...interface{}) #56345
|
||||
pkg log/slog, func With(...interface{}) *Logger #56345
|
||||
pkg log/slog, method (Attr) Equal(Attr) bool #56345
|
||||
@@ -278,17 +271,17 @@ pkg log/slog, method (*LevelVar) MarshalText() ([]uint8, error) #56345
|
||||
pkg log/slog, method (*LevelVar) Set(Level) #56345
|
||||
pkg log/slog, method (*LevelVar) String() string #56345
|
||||
pkg log/slog, method (*LevelVar) UnmarshalText([]uint8) error #56345
|
||||
pkg log/slog, method (*Logger) DebugContext(context.Context, string, ...interface{}) #61200
|
||||
pkg log/slog, method (*Logger) DebugCtx(context.Context, string, ...interface{}) #56345
|
||||
pkg log/slog, method (*Logger) Debug(string, ...interface{}) #56345
|
||||
pkg log/slog, method (*Logger) Enabled(context.Context, Level) bool #56345
|
||||
pkg log/slog, method (*Logger) ErrorContext(context.Context, string, ...interface{}) #61200
|
||||
pkg log/slog, method (*Logger) ErrorCtx(context.Context, string, ...interface{}) #56345
|
||||
pkg log/slog, method (*Logger) Error(string, ...interface{}) #56345
|
||||
pkg log/slog, method (*Logger) Handler() Handler #56345
|
||||
pkg log/slog, method (*Logger) InfoContext(context.Context, string, ...interface{}) #61200
|
||||
pkg log/slog, method (*Logger) InfoCtx(context.Context, string, ...interface{}) #56345
|
||||
pkg log/slog, method (*Logger) Info(string, ...interface{}) #56345
|
||||
pkg log/slog, method (*Logger) LogAttrs(context.Context, Level, string, ...Attr) #56345
|
||||
pkg log/slog, method (*Logger) Log(context.Context, Level, string, ...interface{}) #56345
|
||||
pkg log/slog, method (*Logger) WarnContext(context.Context, string, ...interface{}) #61200
|
||||
pkg log/slog, method (*Logger) WarnCtx(context.Context, string, ...interface{}) #56345
|
||||
pkg log/slog, method (*Logger) Warn(string, ...interface{}) #56345
|
||||
pkg log/slog, method (*Logger) WithGroup(string) *Logger #56345
|
||||
pkg log/slog, method (*Logger) With(...interface{}) *Logger #56345
|
||||
@@ -351,6 +344,8 @@ pkg maps, func Copy[$0 interface{ ~map[$2]$3 }, $1 interface{ ~map[$2]$3 }, $2 c
|
||||
pkg maps, func DeleteFunc[$0 interface{ ~map[$1]$2 }, $1 comparable, $2 interface{}]($0, func($1, $2) bool) #57436
|
||||
pkg maps, func Equal[$0 interface{ ~map[$2]$3 }, $1 interface{ ~map[$2]$3 }, $2 comparable, $3 comparable]($0, $1) bool #57436
|
||||
pkg maps, func EqualFunc[$0 interface{ ~map[$2]$3 }, $1 interface{ ~map[$2]$4 }, $2 comparable, $3 interface{}, $4 interface{}]($0, $1, func($3, $4) bool) bool #57436
|
||||
pkg maps, func Keys[$0 interface{ ~map[$1]$2 }, $1 comparable, $2 interface{}]($0) []$1 #57436
|
||||
pkg maps, func Values[$0 interface{ ~map[$1]$2 }, $1 comparable, $2 interface{}]($0) []$2 #57436
|
||||
pkg math/big, method (*Int) Float64() (float64, Accuracy) #56984
|
||||
pkg net/http, method (*ProtocolError) Is(error) bool #41198
|
||||
pkg net/http, method (*ResponseController) EnableFullDuplex() error #57786
|
||||
|
||||
135
api/go1.22.txt
135
api/go1.22.txt
@@ -1,135 +0,0 @@
|
||||
pkg archive/tar, method (*Writer) AddFS(fs.FS) error #58000
|
||||
pkg archive/zip, method (*Writer) AddFS(fs.FS) error #54898
|
||||
pkg cmp, func Or[$0 comparable](...$0) $0 #60204
|
||||
pkg crypto/x509, func OIDFromInts([]uint64) (OID, error) #60665
|
||||
pkg crypto/x509, method (*CertPool) AddCertWithConstraint(*Certificate, func([]*Certificate) error) #57178
|
||||
pkg crypto/x509, method (OID) Equal(OID) bool #60665
|
||||
pkg crypto/x509, method (OID) EqualASN1OID(asn1.ObjectIdentifier) bool #60665
|
||||
pkg crypto/x509, method (OID) String() string #60665
|
||||
pkg crypto/x509, type Certificate struct, Policies []OID #60665
|
||||
pkg crypto/x509, type OID struct #60665
|
||||
pkg database/sql, method (*Null[$0]) Scan(interface{}) error #60370
|
||||
pkg database/sql, method (Null[$0]) Value() (driver.Value, error) #60370
|
||||
pkg database/sql, type Null[$0 interface{}] struct #60370
|
||||
pkg database/sql, type Null[$0 interface{}] struct, V $0 #60370
|
||||
pkg database/sql, type Null[$0 interface{}] struct, Valid bool #60370
|
||||
pkg debug/elf, const R_LARCH_64_PCREL = 109 #63725
|
||||
pkg debug/elf, const R_LARCH_64_PCREL R_LARCH #63725
|
||||
pkg debug/elf, const R_LARCH_ADD6 = 105 #63725
|
||||
pkg debug/elf, const R_LARCH_ADD6 R_LARCH #63725
|
||||
pkg debug/elf, const R_LARCH_ADD_ULEB128 = 107 #63725
|
||||
pkg debug/elf, const R_LARCH_ADD_ULEB128 R_LARCH #63725
|
||||
pkg debug/elf, const R_LARCH_ALIGN = 102 #63725
|
||||
pkg debug/elf, const R_LARCH_ALIGN R_LARCH #63725
|
||||
pkg debug/elf, const R_LARCH_CFA = 104 #63725
|
||||
pkg debug/elf, const R_LARCH_CFA R_LARCH #63725
|
||||
pkg debug/elf, const R_LARCH_DELETE = 101 #63725
|
||||
pkg debug/elf, const R_LARCH_DELETE R_LARCH #63725
|
||||
pkg debug/elf, const R_LARCH_PCREL20_S2 = 103 #63725
|
||||
pkg debug/elf, const R_LARCH_PCREL20_S2 R_LARCH #63725
|
||||
pkg debug/elf, const R_LARCH_SUB6 = 106 #63725
|
||||
pkg debug/elf, const R_LARCH_SUB6 R_LARCH #63725
|
||||
pkg debug/elf, const R_LARCH_SUB_ULEB128 = 108 #63725
|
||||
pkg debug/elf, const R_LARCH_SUB_ULEB128 R_LARCH #63725
|
||||
pkg debug/elf, const R_MIPS_PC32 = 248 #61974
|
||||
pkg debug/elf, const R_MIPS_PC32 R_MIPS #61974
|
||||
pkg encoding/base32, method (*Encoding) AppendDecode([]uint8, []uint8) ([]uint8, error) #53693
|
||||
pkg encoding/base32, method (*Encoding) AppendEncode([]uint8, []uint8) []uint8 #53693
|
||||
pkg encoding/base64, method (*Encoding) AppendDecode([]uint8, []uint8) ([]uint8, error) #53693
|
||||
pkg encoding/base64, method (*Encoding) AppendEncode([]uint8, []uint8) []uint8 #53693
|
||||
pkg encoding/hex, func AppendDecode([]uint8, []uint8) ([]uint8, error) #53693
|
||||
pkg encoding/hex, func AppendEncode([]uint8, []uint8) []uint8 #53693
|
||||
pkg go/ast, func NewPackage //deprecated #52463
|
||||
pkg go/ast, func Unparen(Expr) Expr #60061
|
||||
pkg go/ast, type Importer //deprecated #52463
|
||||
pkg go/ast, type Object //deprecated #52463
|
||||
pkg go/ast, type Package //deprecated #52463
|
||||
pkg go/ast, type Scope //deprecated #52463
|
||||
pkg go/types, func NewAlias(*TypeName, Type) *Alias #63223
|
||||
pkg go/types, func Unalias(Type) Type #63223
|
||||
pkg go/types, method (*Alias) Obj() *TypeName #63223
|
||||
pkg go/types, method (*Alias) String() string #63223
|
||||
pkg go/types, method (*Alias) Underlying() Type #63223
|
||||
pkg go/types, method (*Info) PkgNameOf(*ast.ImportSpec) *PkgName #62037
|
||||
pkg go/types, method (Checker) PkgNameOf(*ast.ImportSpec) *PkgName #62037
|
||||
pkg go/types, type Alias struct #63223
|
||||
pkg go/types, type Info struct, FileVersions map[*ast.File]string #62605
|
||||
pkg go/version, func Compare(string, string) int #62039
|
||||
pkg go/version, func IsValid(string) bool #62039
|
||||
pkg go/version, func Lang(string) string #62039
|
||||
pkg html/template, const ErrJSTemplate //deprecated #61619
|
||||
pkg io, method (*SectionReader) Outer() (ReaderAt, int64, int64) #61870
|
||||
pkg log/slog, func SetLogLoggerLevel(Level) Level #62418
|
||||
pkg math/big, method (*Rat) FloatPrec() (int, bool) #50489
|
||||
pkg math/rand/v2, func ExpFloat64() float64 #61716
|
||||
pkg math/rand/v2, func Float32() float32 #61716
|
||||
pkg math/rand/v2, func Float64() float64 #61716
|
||||
pkg math/rand/v2, func Int() int #61716
|
||||
pkg math/rand/v2, func Int32() int32 #61716
|
||||
pkg math/rand/v2, func Int32N(int32) int32 #61716
|
||||
pkg math/rand/v2, func Int64() int64 #61716
|
||||
pkg math/rand/v2, func Int64N(int64) int64 #61716
|
||||
pkg math/rand/v2, func IntN(int) int #61716
|
||||
pkg math/rand/v2, func N[$0 intType]($0) $0 #61716
|
||||
pkg math/rand/v2, func New(Source) *Rand #61716
|
||||
pkg math/rand/v2, func NewChaCha8([32]uint8) *ChaCha8 #61716
|
||||
pkg math/rand/v2, func NewPCG(uint64, uint64) *PCG #61716
|
||||
pkg math/rand/v2, func NewZipf(*Rand, float64, float64, uint64) *Zipf #61716
|
||||
pkg math/rand/v2, func NormFloat64() float64 #61716
|
||||
pkg math/rand/v2, func Perm(int) []int #61716
|
||||
pkg math/rand/v2, func Shuffle(int, func(int, int)) #61716
|
||||
pkg math/rand/v2, func Uint32() uint32 #61716
|
||||
pkg math/rand/v2, func Uint32N(uint32) uint32 #61716
|
||||
pkg math/rand/v2, func Uint64() uint64 #61716
|
||||
pkg math/rand/v2, func Uint64N(uint64) uint64 #61716
|
||||
pkg math/rand/v2, func UintN(uint) uint #61716
|
||||
pkg math/rand/v2, method (*ChaCha8) MarshalBinary() ([]uint8, error) #61716
|
||||
pkg math/rand/v2, method (*ChaCha8) Seed([32]uint8) #61716
|
||||
pkg math/rand/v2, method (*ChaCha8) Uint64() uint64 #61716
|
||||
pkg math/rand/v2, method (*ChaCha8) UnmarshalBinary([]uint8) error #61716
|
||||
pkg math/rand/v2, method (*PCG) MarshalBinary() ([]uint8, error) #61716
|
||||
pkg math/rand/v2, method (*PCG) Seed(uint64, uint64) #61716
|
||||
pkg math/rand/v2, method (*PCG) Uint64() uint64 #61716
|
||||
pkg math/rand/v2, method (*PCG) UnmarshalBinary([]uint8) error #61716
|
||||
pkg math/rand/v2, method (*Rand) ExpFloat64() float64 #61716
|
||||
pkg math/rand/v2, method (*Rand) Float32() float32 #61716
|
||||
pkg math/rand/v2, method (*Rand) Float64() float64 #61716
|
||||
pkg math/rand/v2, method (*Rand) Int() int #61716
|
||||
pkg math/rand/v2, method (*Rand) Int32() int32 #61716
|
||||
pkg math/rand/v2, method (*Rand) Int32N(int32) int32 #61716
|
||||
pkg math/rand/v2, method (*Rand) Int64() int64 #61716
|
||||
pkg math/rand/v2, method (*Rand) Int64N(int64) int64 #61716
|
||||
pkg math/rand/v2, method (*Rand) IntN(int) int #61716
|
||||
pkg math/rand/v2, method (*Rand) NormFloat64() float64 #61716
|
||||
pkg math/rand/v2, method (*Rand) Perm(int) []int #61716
|
||||
pkg math/rand/v2, method (*Rand) Shuffle(int, func(int, int)) #61716
|
||||
pkg math/rand/v2, method (*Rand) Uint32() uint32 #61716
|
||||
pkg math/rand/v2, method (*Rand) Uint32N(uint32) uint32 #61716
|
||||
pkg math/rand/v2, method (*Rand) Uint64() uint64 #61716
|
||||
pkg math/rand/v2, method (*Rand) Uint64N(uint64) uint64 #61716
|
||||
pkg math/rand/v2, method (*Rand) UintN(uint) uint #61716
|
||||
pkg math/rand/v2, method (*Zipf) Uint64() uint64 #61716
|
||||
pkg math/rand/v2, type ChaCha8 struct #61716
|
||||
pkg math/rand/v2, type PCG struct #61716
|
||||
pkg math/rand/v2, type Rand struct #61716
|
||||
pkg math/rand/v2, type Source interface { Uint64 } #61716
|
||||
pkg math/rand/v2, type Source interface, Uint64() uint64 #61716
|
||||
pkg math/rand/v2, type Zipf struct #61716
|
||||
pkg net, method (*TCPConn) WriteTo(io.Writer) (int64, error) #58808
|
||||
pkg net/http, func FileServerFS(fs.FS) Handler #51971
|
||||
pkg net/http, func NewFileTransportFS(fs.FS) RoundTripper #51971
|
||||
pkg net/http, func ServeFileFS(ResponseWriter, *Request, fs.FS, string) #51971
|
||||
pkg net/http, method (*Request) PathValue(string) string #61410
|
||||
pkg net/http, method (*Request) SetPathValue(string, string) #61410
|
||||
pkg net/netip, method (AddrPort) Compare(AddrPort) int #61642
|
||||
pkg os, method (*File) WriteTo(io.Writer) (int64, error) #58808
|
||||
pkg reflect, func PtrTo //deprecated #59599
|
||||
pkg reflect, func TypeFor[$0 interface{}]() Type #60088
|
||||
pkg slices, func Concat[$0 interface{ ~[]$1 }, $1 interface{}](...$0) $0 #56353
|
||||
pkg syscall (linux-386), type SysProcAttr struct, PidFD *int #51246
|
||||
pkg syscall (linux-386-cgo), type SysProcAttr struct, PidFD *int #51246
|
||||
pkg syscall (linux-amd64), type SysProcAttr struct, PidFD *int #51246
|
||||
pkg syscall (linux-amd64-cgo), type SysProcAttr struct, PidFD *int #51246
|
||||
pkg syscall (linux-arm), type SysProcAttr struct, PidFD *int #51246
|
||||
pkg syscall (linux-arm-cgo), type SysProcAttr struct, PidFD *int #51246
|
||||
pkg testing/slogtest, func Run(*testing.T, func(*testing.T) slog.Handler, func(*testing.T) map[string]interface{}) #61758
|
||||
@@ -1,2 +1,2 @@
|
||||
branch: release-branch.go1.22
|
||||
branch: dev.inline
|
||||
parent-branch: master
|
||||
|
||||
17
doc/asm.html
17
doc/asm.html
@@ -464,23 +464,6 @@ Function is the outermost frame of the call stack. Traceback should stop at this
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="special-instructions">Special instructions</h3>
|
||||
|
||||
<p>
|
||||
The <code>PCALIGN</code> pseudo-instruction is used to indicate that the next instruction should be aligned
|
||||
to a specified boundary by padding with no-op instructions.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
It is currently supported on arm64, amd64, ppc64, loong64 and riscv64.
|
||||
|
||||
For example, the start of the <code>MOVD</code> instruction below is aligned to 32 bytes:
|
||||
<pre>
|
||||
PCALIGN $32
|
||||
MOVD $2, R0
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
<h3 id="data-offsets">Interacting with Go types and constants</h3>
|
||||
|
||||
<p>
|
||||
|
||||
@@ -7,11 +7,8 @@
|
||||
<h2 id="Introduction">Introduction</h2>
|
||||
|
||||
<p>
|
||||
This is the reference manual for the Go programming language as it was for
|
||||
language version 1.17, in October 2021, before the introduction of generics.
|
||||
It is provided for historical interest.
|
||||
The current reference manual can be found <a href="/doc/go_spec.html">here</a>.
|
||||
For more information and other documents, see <a href="/">go.dev</a>.
|
||||
This is a reference manual for the Go programming language. For
|
||||
more information and other documents, see <a href="/">golang.org</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@@ -917,7 +914,7 @@ are required when different numeric types are mixed in an expression
|
||||
or assignment. For instance, <code>int32</code> and <code>int</code>
|
||||
are not the same type even though they may have the same size on a
|
||||
particular architecture.
|
||||
</p>
|
||||
|
||||
|
||||
<h3 id="String_types">String types</h3>
|
||||
|
||||
@@ -1454,7 +1451,6 @@ maps grow to accommodate the number of items
|
||||
stored in them, with the exception of <code>nil</code> maps.
|
||||
A <code>nil</code> map is equivalent to an empty map except that no elements
|
||||
may be added.
|
||||
</p>
|
||||
|
||||
<h3 id="Channel_types">Channel types</h3>
|
||||
|
||||
@@ -3645,8 +3641,6 @@ As the <code>++</code> and <code>--</code> operators form
|
||||
statements, not expressions, they fall
|
||||
outside the operator hierarchy.
|
||||
As a consequence, statement <code>*p++</code> is the same as <code>(*p)++</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
There are five precedence levels for binary operators.
|
||||
Multiplication operators bind strongest, followed by addition
|
||||
|
||||
1246
doc/go1.21.html
Normal file
1246
doc/go1.21.html
Normal file
File diff suppressed because it is too large
Load Diff
@@ -159,7 +159,6 @@ union of the sequenced before and synchronized before relations.
|
||||
For an ordinary (non-synchronizing) data read <i>r</i> on a memory location <i>x</i>,
|
||||
<i>W</i>(<i>r</i>) must be a write <i>w</i> that is <i>visible</i> to <i>r</i>,
|
||||
where visible means that both of the following hold:
|
||||
</p>
|
||||
|
||||
<ol>
|
||||
<li><i>w</i> happens before <i>r</i>.
|
||||
@@ -222,7 +221,7 @@ for programs that do contain races.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Any implementation can, upon detecting a data race,
|
||||
First, any implementation can, upon detecting a data race,
|
||||
report the race and halt execution of the program.
|
||||
Implementations using ThreadSanitizer
|
||||
(accessed with “<code>go</code> <code>build</code> <code>-race</code>”)
|
||||
@@ -230,18 +229,7 @@ do exactly this.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
A read of an array, struct, or complex number
|
||||
may by implemented as a read of each individual sub-value
|
||||
(array element, struct field, or real/imaginary component),
|
||||
in any order.
|
||||
Similarly, a write of an array, struct, or complex number
|
||||
may be implemented as a write of each individual sub-value,
|
||||
in any order.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
A read <i>r</i> of a memory location <i>x</i>
|
||||
holding a value
|
||||
Otherwise, a read <i>r</i> of a memory location <i>x</i>
|
||||
that is not larger than a machine word must observe
|
||||
some write <i>w</i> such that <i>r</i> does not happen before <i>w</i>
|
||||
and there is no write <i>w'</i> such that <i>w</i> happens before <i>w'</i>
|
||||
|
||||
1118
doc/go_spec.html
1118
doc/go_spec.html
File diff suppressed because it is too large
Load Diff
@@ -126,74 +126,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.22
|
||||
|
||||
Go 1.22 adds a configurable limit to control the maximum acceptable RSA key size
|
||||
that can be used in TLS handshakes, controlled by the [`tlsmaxrsasize` setting](/pkg/crypto/tls#Conn.Handshake).
|
||||
The default is tlsmaxrsasize=8192, limiting RSA to 8192-bit keys. To avoid
|
||||
denial of service attacks, this setting and default was backported to Go
|
||||
1.19.13, Go 1.20.8, and Go 1.21.1.
|
||||
|
||||
Go 1.22 made it an error for a request or response read by a net/http
|
||||
client or server to have an empty Content-Length header.
|
||||
This behavior is controlled by the `httplaxcontentlength` setting.
|
||||
|
||||
Go 1.22 changed the behavior of ServeMux to accept extended
|
||||
patterns and unescape both patterns and request paths by segment.
|
||||
This behavior can be controlled by the
|
||||
[`httpmuxgo121` setting](/pkg/net/http/#ServeMux).
|
||||
|
||||
Go 1.22 added the [Alias type](/pkg/go/types#Alias) to [go/types](/pkg/go/types)
|
||||
for the explicit representation of [type aliases](/ref/spec#Type_declarations).
|
||||
Whether the type checker produces `Alias` types or not is controlled by the
|
||||
[`gotypesalias` setting](/pkg/go/types#Alias).
|
||||
For Go 1.22 it defaults to `gotypesalias=0`.
|
||||
For Go 1.23, `gotypealias=1` will become the default.
|
||||
This setting will be removed in a future release, Go 1.24 at the earliest.
|
||||
|
||||
Go 1.22 changed the default minimum TLS version supported by both servers
|
||||
and clients to TLS 1.2. The default can be reverted to TLS 1.0 using the
|
||||
[`tls10server` setting](/pkg/crypto/tls/#Config).
|
||||
|
||||
Go 1.22 changed the default TLS cipher suites used by clients and servers when
|
||||
not explicitly configured, removing the cipher suites which used RSA based key
|
||||
exchange. The default can be revert using the [`tlsrsakex` setting](/pkg/crypto/tls/#Config).
|
||||
|
||||
Go 1.22 disabled
|
||||
[`ConnectionState.ExportKeyingMaterial`](/pkg/crypto/tls/#ConnectionState.ExportKeyingMaterial)
|
||||
when the connection supports neither TLS 1.3 nor Extended Master Secret
|
||||
(implemented in Go 1.21). It can be reenabled with the [`tlsunsafeekm`
|
||||
setting](/pkg/crypto/tls/#ConnectionState.ExportKeyingMaterial).
|
||||
|
||||
Go 1.22 changed how the runtime interacts with transparent huge pages on Linux.
|
||||
In particular, a common default Linux kernel configuration can result in
|
||||
significant memory overheads, and Go 1.22 no longer works around this default.
|
||||
To work around this issue without adjusting kernel settings, transparent huge
|
||||
pages can be disabled for Go memory with the
|
||||
[`disablethp` setting](/pkg/runtime#hdr-Environment_Variable).
|
||||
This behavior was backported to Go 1.21.1, but the setting is only available
|
||||
starting with Go 1.21.6.
|
||||
This setting may be removed in a future release, and users impacted by this issue
|
||||
should adjust their Linux configuration according to the recommendations in the
|
||||
[GC guide](/doc/gc-guide#Linux_transparent_huge_pages), or switch to a Linux
|
||||
distribution that disables transparent huge pages altogether.
|
||||
|
||||
Go 1.22 added contention on runtime-internal locks to the [`mutex`
|
||||
profile](/pkg/runtime/pprof#Profile). Contention on these locks is always
|
||||
reported at `runtime._LostContendedRuntimeLock`. Complete stack traces of
|
||||
runtime locks can be enabled with the [`runtimecontentionstacks`
|
||||
setting](/pkg/runtime#hdr-Environment_Variable). These stack traces have
|
||||
non-standard semantics, see setting documentation for details.
|
||||
|
||||
Go 1.22 added a new [`crypto/x509.Certificate`](/pkg/crypto/x509/#Certificate)
|
||||
field, [`Policies`](/pkg/crypto/x509/#Certificate.Policies), which supports
|
||||
certificate policy OIDs with components larger than 31 bits. By default this
|
||||
field is only used during parsing, when it is populated with policy OIDs, but
|
||||
not used during marshaling. It can be used to marshal these larger OIDs, instead
|
||||
of the existing PolicyIdentifiers field, by using the
|
||||
[`x509usepolicies` setting.](/pkg/crypto/x509/#CreateCertificate).
|
||||
|
||||
|
||||
### Go 1.21
|
||||
|
||||
Go 1.21 made it a run-time error to call `panic` with a nil interface value,
|
||||
@@ -210,10 +142,6 @@ forms, controlled by the
|
||||
respectively.
|
||||
This behavior was backported to Go 1.19.8+ and Go 1.20.3+.
|
||||
|
||||
Go 1.21 adds the support of Multipath TCP but it is only used if the application
|
||||
explicitly asked for it. This behavior can be controlled by the
|
||||
[`multipathtcp` setting](/pkg/net#Dialer.SetMultipathTCP).
|
||||
|
||||
There is no plan to remove any of these settings.
|
||||
|
||||
### Go 1.20
|
||||
@@ -248,17 +176,10 @@ Go 1.19 made it an error for path lookups to resolve to binaries in the current
|
||||
controlled by the [`execerrdot` setting](/pkg/os/exec#hdr-Executables_in_the_current_directory).
|
||||
There is no plan to remove this setting.
|
||||
|
||||
Go 1.19 started sending EDNS0 additional headers on DNS requests.
|
||||
This can reportedly break the DNS server provided on some routers,
|
||||
such as CenturyLink Zyxel C3000Z.
|
||||
This can be changed by the [`netedns0` setting](/pkg/net#hdr-Name_Resolution).
|
||||
This setting is available in Go 1.21.12, Go 1.22.5, Go 1.23, and later.
|
||||
There is no plan to remove this setting.
|
||||
|
||||
### Go 1.18
|
||||
|
||||
Go 1.18 removed support for SHA1 in most X.509 certificates,
|
||||
controlled by the [`x509sha1` setting](/pkg/crypto/x509#InsecureAlgorithmError).
|
||||
controlled by the [`x509sha1` setting](/crypto/x509#InsecureAlgorithmError).
|
||||
This setting will be removed in a future release, Go 1.22 at the earliest.
|
||||
|
||||
### Go 1.10
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
# in the CL match the update.bash in the CL.
|
||||
|
||||
# Versions to use.
|
||||
CODE=2023d
|
||||
DATA=2023d
|
||||
CODE=2023c
|
||||
DATA=2023c
|
||||
|
||||
set -e
|
||||
|
||||
|
||||
Binary file not shown.
@@ -3,4 +3,4 @@
|
||||
// tests and tools.
|
||||
module misc
|
||||
|
||||
go 1.22
|
||||
go 1.21
|
||||
|
||||
@@ -204,7 +204,6 @@ func runMain() (int, error) {
|
||||
`; export GOPROXY=` + os.Getenv("GOPROXY") +
|
||||
`; export GOCACHE="` + deviceRoot + `/gocache"` +
|
||||
`; export PATH="` + deviceGoroot + `/bin":$PATH` +
|
||||
`; export HOME="` + deviceRoot + `/home"` +
|
||||
`; cd "` + deviceCwd + `"` +
|
||||
"; '" + deviceBin + "' " + strings.Join(os.Args[2:], " ")
|
||||
code, err := adbRun(cmd)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build ignore
|
||||
// +build ignore
|
||||
|
||||
// detect attempts to autodetect the correct
|
||||
// values of the environment variables
|
||||
|
||||
@@ -10,19 +10,11 @@ case "$GOWASIRUNTIME" in
|
||||
"wasmer")
|
||||
exec wasmer run --dir=/ --env PWD="$PWD" --env PATH="$PATH" ${GOWASIRUNTIMEARGS:-} "$1" -- "${@:2}"
|
||||
;;
|
||||
"wazero")
|
||||
exec wazero run -mount /:/ -env-inherit -cachedir "${TMPDIR:-/tmp}"/wazero ${GOWASIRUNTIMEARGS:-} "$1" "${@:2}"
|
||||
"wasmtime")
|
||||
exec wasmtime run --dir=/ --env PWD="$PWD" --env PATH="$PATH" --max-wasm-stack 1048576 ${GOWASIRUNTIMEARGS:-} "$1" -- "${@:2}"
|
||||
;;
|
||||
"wasmtime" | "")
|
||||
# Match the major version in "wasmtime-cli 14.0.0". For versions before 14
|
||||
# we need to use the old CLI. This requires Bash v3.0 and above.
|
||||
# TODO(johanbrandhorst): Remove this condition once 1.22 is released.
|
||||
# From 1.23 onwards we'll only support the new wasmtime CLI.
|
||||
if [[ "$(wasmtime --version)" =~ wasmtime-cli[[:space:]]([0-9]+)\.[0-9]+\.[0-9]+ && "${BASH_REMATCH[1]}" -lt 14 ]]; then
|
||||
exec wasmtime run --dir=/ --env PWD="$PWD" --env PATH="$PATH" --max-wasm-stack 1048576 ${GOWASIRUNTIMEARGS:-} "$1" -- "${@:2}"
|
||||
else
|
||||
exec wasmtime run --dir=/ --env PWD="$PWD" --env PATH="$PATH" -W max-wasm-stack=1048576 ${GOWASIRUNTIMEARGS:-} "$1" "${@:2}"
|
||||
fi
|
||||
"wazero" | "")
|
||||
exec wazero run -mount /:/ -env-inherit -cachedir "${TMPDIR:-/tmp}"/wazero ${GOWASIRUNTIMEARGS:-} "$1" "${@:2}"
|
||||
;;
|
||||
*)
|
||||
echo "Unknown Go WASI runtime specified: $GOWASIRUNTIME"
|
||||
|
||||
@@ -38,7 +38,7 @@ The vendor directory may be updated with 'go mod vendor'.
|
||||
A typical sequence might be:
|
||||
|
||||
cd src
|
||||
go get golang.org/x/net@master
|
||||
go get golang.org/x/net@latest
|
||||
go mod tidy
|
||||
go mod vendor
|
||||
|
||||
|
||||
@@ -632,7 +632,7 @@ const (
|
||||
c_ISSOCK = 0140000 // Socket
|
||||
)
|
||||
|
||||
// FileInfoHeader creates a partially-populated [Header] from fi.
|
||||
// FileInfoHeader creates a partially-populated Header from fi.
|
||||
// If fi describes a symlink, FileInfoHeader records link as the link target.
|
||||
// If fi describes a directory, a slash is appended to the name.
|
||||
//
|
||||
@@ -727,3 +727,10 @@ func isHeaderOnlyType(flag byte) bool {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func min(a, b int64) int64 {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ import "strings"
|
||||
// sub-second times | no | yes | no
|
||||
// sparse files | no | yes | yes
|
||||
//
|
||||
// The table's upper portion shows the [Header] fields, where each format reports
|
||||
// The table's upper portion shows the Header fields, where each format reports
|
||||
// the maximum number of bytes allowed for each string field and
|
||||
// the integer type used to store each numeric field
|
||||
// (where timestamps are stored as the number of seconds since the Unix epoch).
|
||||
|
||||
@@ -35,7 +35,7 @@ type fileReader interface {
|
||||
WriteTo(io.Writer) (int64, error)
|
||||
}
|
||||
|
||||
// NewReader creates a new [Reader] reading from r.
|
||||
// NewReader creates a new Reader reading from r.
|
||||
func NewReader(r io.Reader) *Reader {
|
||||
return &Reader{r: r, curr: ®FileReader{r, 0}}
|
||||
}
|
||||
@@ -47,10 +47,10 @@ func NewReader(r io.Reader) *Reader {
|
||||
//
|
||||
// If Next encounters a non-local name (as defined by [filepath.IsLocal])
|
||||
// and the GODEBUG environment variable contains `tarinsecurepath=0`,
|
||||
// Next returns the header with an [ErrInsecurePath] error.
|
||||
// Next returns the header with an ErrInsecurePath error.
|
||||
// A future version of Go may introduce this behavior by default.
|
||||
// Programs that want to accept non-local names can ignore
|
||||
// the [ErrInsecurePath] error and use the returned header.
|
||||
// the ErrInsecurePath error and use the returned header.
|
||||
func (tr *Reader) Next() (*Header, error) {
|
||||
if tr.err != nil {
|
||||
return nil, tr.err
|
||||
@@ -623,14 +623,14 @@ func readGNUSparseMap0x1(paxHdrs map[string]string) (sparseDatas, error) {
|
||||
|
||||
// Read reads from the current file in the tar archive.
|
||||
// It returns (0, io.EOF) when it reaches the end of that file,
|
||||
// until [Next] is called to advance to the next file.
|
||||
// until Next is called to advance to the next file.
|
||||
//
|
||||
// If the current file is sparse, then the regions marked as a hole
|
||||
// are read back as NUL-bytes.
|
||||
//
|
||||
// Calling Read on special types like [TypeLink], [TypeSymlink], [TypeChar],
|
||||
// [TypeBlock], [TypeDir], and [TypeFifo] returns (0, [io.EOF]) regardless of what
|
||||
// the [Header.Size] claims.
|
||||
// Calling Read on special types like TypeLink, TypeSymlink, TypeChar,
|
||||
// TypeBlock, TypeDir, and TypeFifo returns (0, io.EOF) regardless of what
|
||||
// the Header.Size claims.
|
||||
func (tr *Reader) Read(b []byte) (int, error) {
|
||||
if tr.err != nil {
|
||||
return 0, tr.err
|
||||
|
||||
@@ -73,7 +73,7 @@ func (f *formatter) formatString(b []byte, s string) {
|
||||
// in the V7 path field as a directory even though the full path
|
||||
// recorded elsewhere (e.g., via PAX record) contains no trailing slash.
|
||||
if len(s) > len(b) && b[len(b)-1] == '/' {
|
||||
n := len(strings.TrimRight(s[:len(b)-1], "/"))
|
||||
n := len(strings.TrimRight(s[:len(b)], "/"))
|
||||
b[n] = 0 // Replace trailing slash with NUL terminator
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,10 +5,8 @@
|
||||
package tar
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
"path"
|
||||
"sort"
|
||||
"strings"
|
||||
@@ -16,7 +14,7 @@ import (
|
||||
)
|
||||
|
||||
// Writer provides sequential writing of a tar archive.
|
||||
// [Writer.WriteHeader] begins a new file with the provided [Header],
|
||||
// Write.WriteHeader begins a new file with the provided Header,
|
||||
// and then Writer can be treated as an io.Writer to supply that file's data.
|
||||
type Writer struct {
|
||||
w io.Writer
|
||||
@@ -46,7 +44,7 @@ type fileWriter interface {
|
||||
// Flush finishes writing the current file's block padding.
|
||||
// The current file must be fully written before Flush can be called.
|
||||
//
|
||||
// This is unnecessary as the next call to [Writer.WriteHeader] or [Writer.Close]
|
||||
// This is unnecessary as the next call to WriteHeader or Close
|
||||
// will implicitly flush out the file's padding.
|
||||
func (tw *Writer) Flush() error {
|
||||
if tw.err != nil {
|
||||
@@ -405,43 +403,6 @@ func (tw *Writer) writeRawHeader(blk *block, size int64, flag byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddFS adds the files from fs.FS to the archive.
|
||||
// It walks the directory tree starting at the root of the filesystem
|
||||
// adding each file to the tar archive while maintaining the directory structure.
|
||||
func (tw *Writer) AddFS(fsys fs.FS) error {
|
||||
return fs.WalkDir(fsys, ".", func(name string, d fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if d.IsDir() {
|
||||
return nil
|
||||
}
|
||||
info, err := d.Info()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// TODO(#49580): Handle symlinks when fs.ReadLinkFS is available.
|
||||
if !info.Mode().IsRegular() {
|
||||
return errors.New("tar: cannot add non-regular file")
|
||||
}
|
||||
h, err := FileInfoHeader(info, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
h.Name = name
|
||||
if err := tw.WriteHeader(h); err != nil {
|
||||
return err
|
||||
}
|
||||
f, err := fsys.Open(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
_, err = io.Copy(tw, f)
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
// splitUSTARPath splits a path according to USTAR prefix and suffix rules.
|
||||
// If the path is not splittable, then it will return ("", "", false).
|
||||
func splitUSTARPath(name string) (prefix, suffix string, ok bool) {
|
||||
@@ -464,12 +425,12 @@ func splitUSTARPath(name string) (prefix, suffix string, ok bool) {
|
||||
}
|
||||
|
||||
// Write writes to the current file in the tar archive.
|
||||
// Write returns the error [ErrWriteTooLong] if more than
|
||||
// Header.Size bytes are written after [Writer.WriteHeader].
|
||||
// Write returns the error ErrWriteTooLong if more than
|
||||
// Header.Size bytes are written after WriteHeader.
|
||||
//
|
||||
// Calling Write on special types like [TypeLink], [TypeSymlink], [TypeChar],
|
||||
// [TypeBlock], [TypeDir], and [TypeFifo] returns (0, [ErrWriteTooLong]) regardless
|
||||
// of what the [Header.Size] claims.
|
||||
// Calling Write on special types like TypeLink, TypeSymlink, TypeChar,
|
||||
// TypeBlock, TypeDir, and TypeFifo returns (0, ErrWriteTooLong) regardless
|
||||
// of what the Header.Size claims.
|
||||
func (tw *Writer) Write(b []byte) (int, error) {
|
||||
if tw.err != nil {
|
||||
return 0, tw.err
|
||||
@@ -503,7 +464,7 @@ func (tw *Writer) readFrom(r io.Reader) (int64, error) {
|
||||
}
|
||||
|
||||
// Close closes the tar archive by flushing the padding, and writing the footer.
|
||||
// If the current file (from a prior call to [Writer.WriteHeader]) is not fully written,
|
||||
// If the current file (from a prior call to WriteHeader) is not fully written,
|
||||
// then this returns an error.
|
||||
func (tw *Writer) Close() error {
|
||||
if tw.err == ErrWriteAfterClose {
|
||||
|
||||
@@ -9,14 +9,12 @@ import (
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"io"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
"testing/fstest"
|
||||
"testing/iotest"
|
||||
"time"
|
||||
)
|
||||
@@ -1335,67 +1333,3 @@ func TestFileWriter(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriterAddFS(t *testing.T) {
|
||||
fsys := fstest.MapFS{
|
||||
"file.go": {Data: []byte("hello")},
|
||||
"subfolder/another.go": {Data: []byte("world")},
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
tw := NewWriter(&buf)
|
||||
if err := tw.AddFS(fsys); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Test that we can get the files back from the archive
|
||||
tr := NewReader(&buf)
|
||||
|
||||
entries, err := fsys.ReadDir(".")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var curfname string
|
||||
for _, entry := range entries {
|
||||
curfname = entry.Name()
|
||||
if entry.IsDir() {
|
||||
curfname += "/"
|
||||
continue
|
||||
}
|
||||
hdr, err := tr.Next()
|
||||
if err == io.EOF {
|
||||
break // End of archive
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
data, err := io.ReadAll(tr)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
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("got file content %v, want %v",
|
||||
data, origdata)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriterAddFSNonRegularFiles(t *testing.T) {
|
||||
fsys := fstest.MapFS{
|
||||
"device": {Data: []byte("hello"), Mode: 0755 | fs.ModeDevice},
|
||||
"symlink": {Data: []byte("world"), Mode: 0755 | fs.ModeSymlink},
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
tw := NewWriter(&buf)
|
||||
if err := tw.AddFS(fsys); err == nil {
|
||||
t.Fatal("expected error, got nil")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,15 +48,15 @@ type Reader struct {
|
||||
fileList []fileListEntry
|
||||
}
|
||||
|
||||
// A ReadCloser is a [Reader] that must be closed when no longer needed.
|
||||
// A ReadCloser is a Reader that must be closed when no longer needed.
|
||||
type ReadCloser struct {
|
||||
f *os.File
|
||||
Reader
|
||||
}
|
||||
|
||||
// A File is a single file in a ZIP archive.
|
||||
// The file information is in the embedded [FileHeader].
|
||||
// The file content can be accessed by calling [File.Open].
|
||||
// The file information is in the embedded FileHeader.
|
||||
// The file content can be accessed by calling Open.
|
||||
type File struct {
|
||||
FileHeader
|
||||
zip *Reader
|
||||
@@ -93,16 +93,16 @@ func OpenReader(name string) (*ReadCloser, error) {
|
||||
return r, err
|
||||
}
|
||||
|
||||
// NewReader returns a new [Reader] reading from r, which is assumed to
|
||||
// NewReader returns a new Reader reading from r, which is assumed to
|
||||
// have the given size in bytes.
|
||||
//
|
||||
// If any file inside the archive uses a non-local name
|
||||
// (as defined by [filepath.IsLocal]) or a name containing backslashes
|
||||
// and the GODEBUG environment variable contains `zipinsecurepath=0`,
|
||||
// NewReader returns the reader with an [ErrInsecurePath] error.
|
||||
// NewReader returns the reader with an ErrInsecurePath error.
|
||||
// A future version of Go may introduce this behavior by default.
|
||||
// Programs that want to accept non-local names can ignore
|
||||
// the [ErrInsecurePath] error and use the returned reader.
|
||||
// the ErrInsecurePath error and use the returned reader.
|
||||
func NewReader(r io.ReaderAt, size int64) (*Reader, error) {
|
||||
if size < 0 {
|
||||
return nil, errors.New("zip: size cannot be negative")
|
||||
@@ -178,7 +178,7 @@ func (r *Reader) init(rdr io.ReaderAt, size int64) error {
|
||||
|
||||
// RegisterDecompressor registers or overrides a custom decompressor for a
|
||||
// specific method ID. If a decompressor for a given method is not found,
|
||||
// [Reader] will default to looking up the decompressor at the package level.
|
||||
// Reader will default to looking up the decompressor at the package level.
|
||||
func (r *Reader) RegisterDecompressor(method uint16, dcomp Decompressor) {
|
||||
if r.decompressors == nil {
|
||||
r.decompressors = make(map[uint16]Decompressor)
|
||||
@@ -202,7 +202,7 @@ func (rc *ReadCloser) Close() error {
|
||||
// DataOffset returns the offset of the file's possibly-compressed
|
||||
// data, relative to the beginning of the zip file.
|
||||
//
|
||||
// Most callers should instead use [File.Open], which transparently
|
||||
// Most callers should instead use Open, which transparently
|
||||
// decompresses data and verifies checksums.
|
||||
func (f *File) DataOffset() (offset int64, err error) {
|
||||
bodyOffset, err := f.findBodyOffset()
|
||||
@@ -212,7 +212,7 @@ func (f *File) DataOffset() (offset int64, err error) {
|
||||
return f.headerOffset + bodyOffset, nil
|
||||
}
|
||||
|
||||
// Open returns a [ReadCloser] that provides access to the [File]'s contents.
|
||||
// Open returns a ReadCloser that provides access to the File's contents.
|
||||
// Multiple files may be read concurrently.
|
||||
func (f *File) Open() (io.ReadCloser, error) {
|
||||
bodyOffset, err := f.findBodyOffset()
|
||||
@@ -255,7 +255,7 @@ func (f *File) Open() (io.ReadCloser, error) {
|
||||
return rc, nil
|
||||
}
|
||||
|
||||
// OpenRaw returns a [Reader] that provides access to the [File]'s contents without
|
||||
// OpenRaw returns a Reader that provides access to the File's contents without
|
||||
// decompression.
|
||||
func (f *File) OpenRaw() (io.Reader, error) {
|
||||
bodyOffset, err := f.findBodyOffset()
|
||||
@@ -469,8 +469,8 @@ parseExtras:
|
||||
|
||||
const ticksPerSecond = 1e7 // Windows timestamp resolution
|
||||
ts := int64(attrBuf.uint64()) // ModTime since Windows epoch
|
||||
secs := ts / ticksPerSecond
|
||||
nsecs := (1e9 / ticksPerSecond) * (ts % ticksPerSecond)
|
||||
secs := int64(ts / ticksPerSecond)
|
||||
nsecs := (1e9 / ticksPerSecond) * int64(ts%ticksPerSecond)
|
||||
epoch := time.Date(1601, time.January, 1, 0, 0, 0, 0, time.UTC)
|
||||
modified = time.Unix(epoch.Unix()+secs, nsecs)
|
||||
}
|
||||
@@ -699,13 +699,9 @@ func findSignatureInBlock(b []byte) int {
|
||||
if b[i] == 'P' && b[i+1] == 'K' && b[i+2] == 0x05 && b[i+3] == 0x06 {
|
||||
// n is length of comment
|
||||
n := int(b[i+directoryEndLen-2]) | int(b[i+directoryEndLen-1])<<8
|
||||
if n+directoryEndLen+i > len(b) {
|
||||
// Truncated comment.
|
||||
// Some parsers (such as Info-ZIP) ignore the truncated comment
|
||||
// rather than treating it as a hard error.
|
||||
return -1
|
||||
if n+directoryEndLen+i <= len(b) {
|
||||
return i
|
||||
}
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
|
||||
@@ -570,14 +570,6 @@ var tests = []ZipTest{
|
||||
},
|
||||
},
|
||||
},
|
||||
// Issue 66869: Don't skip over an EOCDR with a truncated comment.
|
||||
// The test file sneakily hides a second EOCDR before the first one;
|
||||
// previously we would extract one file ("file") from this archive,
|
||||
// while most other tools would reject the file or extract a different one ("FILE").
|
||||
{
|
||||
Name: "comment-truncated.zip",
|
||||
Error: ErrFormat,
|
||||
},
|
||||
}
|
||||
|
||||
func TestReader(t *testing.T) {
|
||||
@@ -1194,7 +1186,7 @@ func TestIssue12449(t *testing.T) {
|
||||
0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
}
|
||||
// Read in the archive.
|
||||
_, err := NewReader(bytes.NewReader(data), int64(len(data)))
|
||||
_, err := NewReader(bytes.NewReader([]byte(data)), int64(len(data)))
|
||||
if err != nil {
|
||||
t.Errorf("Error reading the archive: %v", err)
|
||||
}
|
||||
@@ -1341,7 +1333,7 @@ func TestCVE202127919(t *testing.T) {
|
||||
0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x39, 0x00,
|
||||
0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
}
|
||||
r, err := NewReader(bytes.NewReader(data), int64(len(data)))
|
||||
r, err := NewReader(bytes.NewReader([]byte(data)), int64(len(data)))
|
||||
if err != ErrInsecurePath {
|
||||
t.Fatalf("Error reading the archive: %v", err)
|
||||
}
|
||||
@@ -1567,7 +1559,7 @@ func TestCVE202141772(t *testing.T) {
|
||||
0x00, 0x04, 0x00, 0x04, 0x00, 0x31, 0x01, 0x00,
|
||||
0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
}
|
||||
r, err := NewReader(bytes.NewReader(data), int64(len(data)))
|
||||
r, err := NewReader(bytes.NewReader([]byte(data)), int64(len(data)))
|
||||
if err != ErrInsecurePath {
|
||||
t.Fatalf("Error reading the archive: %v", err)
|
||||
}
|
||||
@@ -1830,7 +1822,7 @@ func TestBaseOffsetPlusOverflow(t *testing.T) {
|
||||
}
|
||||
}()
|
||||
// Previously, this would trigger a panic as we attempt to read from
|
||||
// an io.SectionReader which would access a slice at a negative offset
|
||||
// a io.SectionReader which would access a slice at a negative offset
|
||||
// as the section reader offset & size were < 0.
|
||||
NewReader(bytes.NewReader(data), int64(len(data))+1875)
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ import (
|
||||
type Compressor func(w io.Writer) (io.WriteCloser, error)
|
||||
|
||||
// A Decompressor returns a new decompressing reader, reading from r.
|
||||
// The [io.ReadCloser]'s Close method must be used to release associated resources.
|
||||
// The ReadCloser's Close method must be used to release associated resources.
|
||||
// The Decompressor itself must be safe to invoke from multiple goroutines
|
||||
// simultaneously, but each returned reader will be used only by
|
||||
// one goroutine at a time.
|
||||
@@ -115,7 +115,7 @@ func init() {
|
||||
}
|
||||
|
||||
// RegisterDecompressor allows custom decompressors for a specified method ID.
|
||||
// The common methods [Store] and [Deflate] are built in.
|
||||
// The common methods Store and Deflate are built in.
|
||||
func RegisterDecompressor(method uint16, dcomp Decompressor) {
|
||||
if _, dup := decompressors.LoadOrStore(method, dcomp); dup {
|
||||
panic("decompressor already registered")
|
||||
@@ -123,7 +123,7 @@ func RegisterDecompressor(method uint16, dcomp Decompressor) {
|
||||
}
|
||||
|
||||
// RegisterCompressor registers custom compressors for a specified method ID.
|
||||
// The common methods [Store] and [Deflate] are built in.
|
||||
// The common methods Store and Deflate are built in.
|
||||
func RegisterCompressor(method uint16, comp Compressor) {
|
||||
if _, dup := compressors.LoadOrStore(method, comp); dup {
|
||||
panic("compressor already registered")
|
||||
|
||||
@@ -17,7 +17,7 @@ for normal archives both fields will be the same. For files requiring
|
||||
the ZIP64 format the 32 bit fields will be 0xffffffff and the 64 bit
|
||||
fields must be used instead.
|
||||
|
||||
[ZIP specification]: https://support.pkware.com/pkzip/appnote
|
||||
[ZIP specification]: https://www.pkware.com/appnote
|
||||
*/
|
||||
package zip
|
||||
|
||||
@@ -82,7 +82,7 @@ const (
|
||||
// FileHeader describes a file within a ZIP file.
|
||||
// See the [ZIP specification] for details.
|
||||
//
|
||||
// [ZIP specification]: https://support.pkware.com/pkzip/appnote
|
||||
// [ZIP specification]: https://www.pkware.com/appnote
|
||||
type FileHeader struct {
|
||||
// Name is the name of the file.
|
||||
//
|
||||
@@ -160,12 +160,12 @@ type FileHeader struct {
|
||||
ExternalAttrs uint32 // Meaning depends on CreatorVersion
|
||||
}
|
||||
|
||||
// FileInfo returns an fs.FileInfo for the [FileHeader].
|
||||
// FileInfo returns an fs.FileInfo for the FileHeader.
|
||||
func (h *FileHeader) FileInfo() fs.FileInfo {
|
||||
return headerFileInfo{h}
|
||||
}
|
||||
|
||||
// headerFileInfo implements [fs.FileInfo].
|
||||
// headerFileInfo implements fs.FileInfo.
|
||||
type headerFileInfo struct {
|
||||
fh *FileHeader
|
||||
}
|
||||
@@ -194,7 +194,7 @@ func (fi headerFileInfo) String() string {
|
||||
return fs.FormatFileInfo(fi)
|
||||
}
|
||||
|
||||
// FileInfoHeader creates a partially-populated [FileHeader] from an
|
||||
// FileInfoHeader creates a partially-populated FileHeader from an
|
||||
// fs.FileInfo.
|
||||
// Because fs.FileInfo's Name method returns only the base name of
|
||||
// the file it describes, it may be necessary to modify the Name field
|
||||
@@ -245,7 +245,7 @@ func timeZone(offset time.Duration) *time.Location {
|
||||
|
||||
// msDosTimeToTime converts an MS-DOS date and time into a time.Time.
|
||||
// The resolution is 2s.
|
||||
// See: https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-dosdatetimetofiletime
|
||||
// See: https://msdn.microsoft.com/en-us/library/ms724247(v=VS.85).aspx
|
||||
func msDosTimeToTime(dosDate, dosTime uint16) time.Time {
|
||||
return time.Date(
|
||||
// date bits 0-4: day of month; 5-8: month; 9-15: years since 1980
|
||||
@@ -265,7 +265,7 @@ func msDosTimeToTime(dosDate, dosTime uint16) time.Time {
|
||||
|
||||
// timeToMsDosTime converts a time.Time to an MS-DOS date and time.
|
||||
// The resolution is 2s.
|
||||
// See: https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-filetimetodosdatetime
|
||||
// See: https://msdn.microsoft.com/en-us/library/ms724274(v=VS.85).aspx
|
||||
func timeToMsDosTime(t time.Time) (fDate uint16, fTime uint16) {
|
||||
fDate = uint16(t.Day() + int(t.Month())<<5 + (t.Year()-1980)<<9)
|
||||
fTime = uint16(t.Second()/2 + t.Minute()<<5 + t.Hour()<<11)
|
||||
@@ -273,17 +273,17 @@ func timeToMsDosTime(t time.Time) (fDate uint16, fTime uint16) {
|
||||
}
|
||||
|
||||
// ModTime returns the modification time in UTC using the legacy
|
||||
// [ModifiedDate] and [ModifiedTime] fields.
|
||||
// ModifiedDate and ModifiedTime fields.
|
||||
//
|
||||
// Deprecated: Use [Modified] instead.
|
||||
// Deprecated: Use Modified instead.
|
||||
func (h *FileHeader) ModTime() time.Time {
|
||||
return msDosTimeToTime(h.ModifiedDate, h.ModifiedTime)
|
||||
}
|
||||
|
||||
// SetModTime sets the [Modified], [ModifiedTime], and [ModifiedDate] fields
|
||||
// SetModTime sets the Modified, ModifiedTime, and ModifiedDate fields
|
||||
// to the given time in UTC.
|
||||
//
|
||||
// Deprecated: Use [Modified] instead.
|
||||
// Deprecated: Use Modified instead.
|
||||
func (h *FileHeader) SetModTime(t time.Time) {
|
||||
t = t.UTC() // Convert to UTC for compatibility
|
||||
h.Modified = t
|
||||
@@ -309,7 +309,7 @@ const (
|
||||
msdosReadOnly = 0x01
|
||||
)
|
||||
|
||||
// Mode returns the permission and mode bits for the [FileHeader].
|
||||
// Mode returns the permission and mode bits for the FileHeader.
|
||||
func (h *FileHeader) Mode() (mode fs.FileMode) {
|
||||
switch h.CreatorVersion >> 8 {
|
||||
case creatorUnix, creatorMacOSX:
|
||||
@@ -323,7 +323,7 @@ func (h *FileHeader) Mode() (mode fs.FileMode) {
|
||||
return mode
|
||||
}
|
||||
|
||||
// SetMode changes the permission and mode bits for the [FileHeader].
|
||||
// SetMode changes the permission and mode bits for the FileHeader.
|
||||
func (h *FileHeader) SetMode(mode fs.FileMode) {
|
||||
h.CreatorVersion = h.CreatorVersion&0xff | creatorUnix<<8
|
||||
h.ExternalAttrs = fileModeToUnixMode(mode) << 16
|
||||
|
||||
BIN
src/archive/zip/testdata/comment-truncated.zip
vendored
BIN
src/archive/zip/testdata/comment-truncated.zip
vendored
Binary file not shown.
@@ -11,7 +11,6 @@ import (
|
||||
"hash"
|
||||
"hash/crc32"
|
||||
"io"
|
||||
"io/fs"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
)
|
||||
@@ -41,7 +40,7 @@ type header struct {
|
||||
raw bool
|
||||
}
|
||||
|
||||
// NewWriter returns a new [Writer] writing a zip file to w.
|
||||
// NewWriter returns a new Writer writing a zip file to w.
|
||||
func NewWriter(w io.Writer) *Writer {
|
||||
return &Writer{cw: &countWriter{w: bufio.NewWriter(w)}}
|
||||
}
|
||||
@@ -64,7 +63,7 @@ func (w *Writer) Flush() error {
|
||||
}
|
||||
|
||||
// SetComment sets the end-of-central-directory comment field.
|
||||
// It can only be called before [Writer.Close].
|
||||
// It can only be called before Close.
|
||||
func (w *Writer) SetComment(comment string) error {
|
||||
if len(comment) > uint16max {
|
||||
return errors.New("zip: Writer.Comment too long")
|
||||
@@ -208,14 +207,14 @@ func (w *Writer) Close() error {
|
||||
}
|
||||
|
||||
// Create adds a file to the zip file using the provided name.
|
||||
// It returns a [Writer] to which the file contents should be written.
|
||||
// The file contents will be compressed using the [Deflate] method.
|
||||
// It returns a Writer to which the file contents should be written.
|
||||
// The file contents will be compressed using the Deflate method.
|
||||
// The name must be a relative path: it must not start with a drive
|
||||
// letter (e.g. C:) or leading slash, and only forward slashes are
|
||||
// allowed. To create a directory instead of a file, add a trailing
|
||||
// slash to the name.
|
||||
// The file's contents must be written to the [io.Writer] before the next
|
||||
// call to [Writer.Create], [Writer.CreateHeader], or [Writer.Close].
|
||||
// The file's contents must be written to the io.Writer before the next
|
||||
// call to Create, CreateHeader, or Close.
|
||||
func (w *Writer) Create(name string) (io.Writer, error) {
|
||||
header := &FileHeader{
|
||||
Name: name,
|
||||
@@ -262,13 +261,13 @@ func (w *Writer) prepare(fh *FileHeader) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreateHeader adds a file to the zip archive using the provided [FileHeader]
|
||||
// for the file metadata. [Writer] takes ownership of fh and may mutate
|
||||
// its fields. The caller must not modify fh after calling [Writer.CreateHeader].
|
||||
// CreateHeader adds a file to the zip archive using the provided FileHeader
|
||||
// for the file metadata. Writer takes ownership of fh and may mutate
|
||||
// its fields. The caller must not modify fh after calling CreateHeader.
|
||||
//
|
||||
// This returns a [Writer] to which the file contents should be written.
|
||||
// This returns a Writer to which the file contents should be written.
|
||||
// The file's contents must be written to the io.Writer before the next
|
||||
// call to [Writer.Create], [Writer.CreateHeader], [Writer.CreateRaw], or [Writer.Close].
|
||||
// call to Create, CreateHeader, CreateRaw, or Close.
|
||||
func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error) {
|
||||
if err := w.prepare(fh); err != nil {
|
||||
return nil, err
|
||||
@@ -406,8 +405,8 @@ func writeHeader(w io.Writer, h *header) error {
|
||||
// flags.
|
||||
if h.raw && !h.hasDataDescriptor() {
|
||||
b.uint32(h.CRC32)
|
||||
b.uint32(uint32(min(h.CompressedSize64, uint32max)))
|
||||
b.uint32(uint32(min(h.UncompressedSize64, uint32max)))
|
||||
b.uint32(uint32(min64(h.CompressedSize64, uint32max)))
|
||||
b.uint32(uint32(min64(h.UncompressedSize64, uint32max)))
|
||||
} else {
|
||||
// When this package handle the compression, these values are
|
||||
// always written to the trailing data descriptor.
|
||||
@@ -427,19 +426,26 @@ func writeHeader(w io.Writer, h *header) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// CreateRaw adds a file to the zip archive using the provided [FileHeader] and
|
||||
// returns a [Writer] to which the file contents should be written. The file's
|
||||
// contents must be written to the io.Writer before the next call to [Writer.Create],
|
||||
// [Writer.CreateHeader], [Writer.CreateRaw], or [Writer.Close].
|
||||
func min64(x, y uint64) uint64 {
|
||||
if x < y {
|
||||
return x
|
||||
}
|
||||
return y
|
||||
}
|
||||
|
||||
// CreateRaw adds a file to the zip archive using the provided FileHeader and
|
||||
// returns a Writer to which the file contents should be written. The file's
|
||||
// contents must be written to the io.Writer before the next call to Create,
|
||||
// CreateHeader, CreateRaw, or Close.
|
||||
//
|
||||
// In contrast to [Writer.CreateHeader], the bytes passed to Writer are not compressed.
|
||||
// In contrast to CreateHeader, the bytes passed to Writer are not compressed.
|
||||
func (w *Writer) CreateRaw(fh *FileHeader) (io.Writer, error) {
|
||||
if err := w.prepare(fh); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fh.CompressedSize = uint32(min(fh.CompressedSize64, uint32max))
|
||||
fh.UncompressedSize = uint32(min(fh.UncompressedSize64, uint32max))
|
||||
fh.CompressedSize = uint32(min64(fh.CompressedSize64, uint32max))
|
||||
fh.UncompressedSize = uint32(min64(fh.UncompressedSize64, uint32max))
|
||||
|
||||
h := &header{
|
||||
FileHeader: fh,
|
||||
@@ -464,7 +470,7 @@ func (w *Writer) CreateRaw(fh *FileHeader) (io.Writer, error) {
|
||||
return fw, nil
|
||||
}
|
||||
|
||||
// Copy copies the file f (obtained from a [Reader]) into w. It copies the raw
|
||||
// Copy copies the file f (obtained from a Reader) into w. It copies the raw
|
||||
// form directly bypassing decompression, compression, and validation.
|
||||
func (w *Writer) Copy(f *File) error {
|
||||
r, err := f.OpenRaw()
|
||||
@@ -480,7 +486,7 @@ func (w *Writer) Copy(f *File) error {
|
||||
}
|
||||
|
||||
// RegisterCompressor registers or overrides a custom compressor for a specific
|
||||
// method ID. If a compressor for a given method is not found, [Writer] will
|
||||
// method ID. If a compressor for a given method is not found, Writer will
|
||||
// default to looking up the compressor at the package level.
|
||||
func (w *Writer) RegisterCompressor(method uint16, comp Compressor) {
|
||||
if w.compressors == nil {
|
||||
@@ -489,44 +495,6 @@ func (w *Writer) RegisterCompressor(method uint16, comp Compressor) {
|
||||
w.compressors[method] = comp
|
||||
}
|
||||
|
||||
// AddFS adds the files from fs.FS to the archive.
|
||||
// It walks the directory tree starting at the root of the filesystem
|
||||
// adding each file to the zip using deflate while maintaining the directory structure.
|
||||
func (w *Writer) AddFS(fsys fs.FS) error {
|
||||
return fs.WalkDir(fsys, ".", func(name string, d fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if d.IsDir() {
|
||||
return nil
|
||||
}
|
||||
info, err := d.Info()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !info.Mode().IsRegular() {
|
||||
return errors.New("zip: cannot add non-regular file")
|
||||
}
|
||||
h, err := FileInfoHeader(info)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
h.Name = name
|
||||
h.Method = Deflate
|
||||
fw, err := w.CreateHeader(h)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
f, err := fsys.Open(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
_, err = io.Copy(fw, f)
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
func (w *Writer) compressor(method uint16) Compressor {
|
||||
comp := w.compressors[method]
|
||||
if comp == nil {
|
||||
|
||||
@@ -16,7 +16,6 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"testing/fstest"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -603,71 +602,3 @@ func BenchmarkCompressedZipGarbage(b *testing.B) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func writeTestsToFS(tests []WriteTest) fs.FS {
|
||||
fsys := fstest.MapFS{}
|
||||
for _, wt := range tests {
|
||||
fsys[wt.Name] = &fstest.MapFile{
|
||||
Data: wt.Data,
|
||||
Mode: wt.Mode,
|
||||
}
|
||||
}
|
||||
return fsys
|
||||
}
|
||||
|
||||
func TestWriterAddFS(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
w := NewWriter(buf)
|
||||
tests := []WriteTest{
|
||||
{
|
||||
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)
|
||||
}
|
||||
|
||||
// read it back
|
||||
r, err := NewReader(bytes.NewReader(buf.Bytes()), int64(buf.Len()))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for i, wt := range tests {
|
||||
testReadFile(t, r.File[i], &wt)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIssue61875(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
w := NewWriter(buf)
|
||||
tests := []WriteTest{
|
||||
{
|
||||
Name: "symlink",
|
||||
Data: []byte("../link/target"),
|
||||
Method: Deflate,
|
||||
Mode: 0755 | fs.ModeSymlink,
|
||||
},
|
||||
{
|
||||
Name: "device",
|
||||
Data: []byte(""),
|
||||
Method: Deflate,
|
||||
Mode: 0755 | fs.ModeDevice,
|
||||
},
|
||||
}
|
||||
err := w.AddFS(writeTestsToFS(tests))
|
||||
if err == nil {
|
||||
t.Errorf("expected error, got nil")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,6 +198,13 @@ func (r *rleBuffer) Write(p []byte) (n int, err error) {
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
func min(x, y int64) int64 {
|
||||
if x < y {
|
||||
return x
|
||||
}
|
||||
return y
|
||||
}
|
||||
|
||||
func memset(a []byte, b byte) {
|
||||
if len(a) == 0 {
|
||||
return
|
||||
@@ -590,7 +597,7 @@ func testZip64(t testing.TB, size int64) *rleBuffer {
|
||||
}
|
||||
|
||||
// read back zip file and check that we get to the end of it
|
||||
r, err := NewReader(buf, buf.Size())
|
||||
r, err := NewReader(buf, int64(buf.Size()))
|
||||
if err != nil {
|
||||
t.Fatal("reader:", err)
|
||||
}
|
||||
|
||||
@@ -41,21 +41,24 @@ type Reader struct {
|
||||
const minReadBufferSize = 16
|
||||
const maxConsecutiveEmptyReads = 100
|
||||
|
||||
// NewReaderSize returns a new [Reader] whose buffer has at least the specified
|
||||
// size. If the argument io.Reader is already a [Reader] with large enough
|
||||
// size, it returns the underlying [Reader].
|
||||
// NewReaderSize returns a new Reader whose buffer has at least the specified
|
||||
// size. If the argument io.Reader is already a Reader with large enough
|
||||
// size, it returns the underlying Reader.
|
||||
func NewReaderSize(rd io.Reader, size int) *Reader {
|
||||
// Is it already a Reader?
|
||||
b, ok := rd.(*Reader)
|
||||
if ok && len(b.buf) >= size {
|
||||
return b
|
||||
}
|
||||
if size < minReadBufferSize {
|
||||
size = minReadBufferSize
|
||||
}
|
||||
r := new(Reader)
|
||||
r.reset(make([]byte, max(size, minReadBufferSize)), rd)
|
||||
r.reset(make([]byte, size), rd)
|
||||
return r
|
||||
}
|
||||
|
||||
// NewReader returns a new [Reader] whose buffer has the default size.
|
||||
// NewReader returns a new Reader whose buffer has the default size.
|
||||
func NewReader(rd io.Reader) *Reader {
|
||||
return NewReaderSize(rd, defaultBufSize)
|
||||
}
|
||||
@@ -65,9 +68,9 @@ func (b *Reader) Size() int { return len(b.buf) }
|
||||
|
||||
// Reset discards any buffered data, resets all state, and switches
|
||||
// the buffered reader to read from r.
|
||||
// Calling Reset on the zero value of [Reader] initializes the internal buffer
|
||||
// Calling Reset on the zero value of Reader initializes the internal buffer
|
||||
// to the default size.
|
||||
// Calling b.Reset(b) (that is, resetting a [Reader] to itself) does nothing.
|
||||
// Calling b.Reset(b) (that is, resetting a Reader to itself) does nothing.
|
||||
func (b *Reader) Reset(r io.Reader) {
|
||||
// If a Reader r is passed to NewReader, NewReader will return r.
|
||||
// Different layers of code may do that, and then later pass r
|
||||
@@ -132,9 +135,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 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.
|
||||
// ErrBufferFull if n is larger than b's buffer size.
|
||||
//
|
||||
// Calling Peek prevents a [Reader.UnreadByte] or [Reader.UnreadRune] call from succeeding
|
||||
// Calling Peek prevents a UnreadByte or UnreadRune call from succeeding
|
||||
// until the next read operation.
|
||||
func (b *Reader) Peek(n int) ([]byte, error) {
|
||||
if n < 0 {
|
||||
@@ -204,10 +207,10 @@ func (b *Reader) Discard(n int) (discarded int, err error) {
|
||||
|
||||
// Read reads data into p.
|
||||
// It returns the number of bytes read into p.
|
||||
// The bytes are taken from at most one Read on the underlying [Reader],
|
||||
// The bytes are taken from at most one Read on the underlying Reader,
|
||||
// hence n may be less than len(p).
|
||||
// To read exactly len(p) bytes, use io.ReadFull(b, p).
|
||||
// If the underlying [Reader] can return a non-zero count with io.EOF,
|
||||
// If the underlying Reader can return a non-zero count with io.EOF,
|
||||
// then this Read method can do so as well; see the [io.Reader] docs.
|
||||
func (b *Reader) Read(p []byte) (n int, err error) {
|
||||
n = len(p)
|
||||
@@ -277,7 +280,7 @@ func (b *Reader) ReadByte() (byte, error) {
|
||||
// UnreadByte unreads the last byte. Only the most recently read byte can be unread.
|
||||
//
|
||||
// UnreadByte returns an error if the most recent method called on the
|
||||
// [Reader] was not a read operation. Notably, [Reader.Peek], [Reader.Discard], and [Reader.WriteTo] are not
|
||||
// Reader was not a read operation. Notably, Peek, Discard, and WriteTo are not
|
||||
// considered read operations.
|
||||
func (b *Reader) UnreadByte() error {
|
||||
if b.lastByte < 0 || b.r == 0 && b.w > 0 {
|
||||
@@ -318,8 +321,8 @@ func (b *Reader) ReadRune() (r rune, size int, err error) {
|
||||
}
|
||||
|
||||
// UnreadRune unreads the last rune. If the most recent method called on
|
||||
// the [Reader] was not a [Reader.ReadRune], [Reader.UnreadRune] returns an error. (In this
|
||||
// regard it is stricter than [Reader.UnreadByte], which will unread the last byte
|
||||
// the Reader was not a ReadRune, UnreadRune returns an error. (In this
|
||||
// regard it is stricter than UnreadByte, which will unread the last byte
|
||||
// from any read operation.)
|
||||
func (b *Reader) UnreadRune() error {
|
||||
if b.lastRuneSize < 0 || b.r < b.lastRuneSize {
|
||||
@@ -339,10 +342,10 @@ func (b *Reader) Buffered() int { return b.w - b.r }
|
||||
// The bytes stop being valid at the next read.
|
||||
// If ReadSlice encounters an error before finding a delimiter,
|
||||
// it returns all the data in the buffer and the error itself (often io.EOF).
|
||||
// ReadSlice fails with error [ErrBufferFull] if the buffer fills without a delim.
|
||||
// ReadSlice fails with error ErrBufferFull if the buffer fills without a delim.
|
||||
// Because the data returned from ReadSlice will be overwritten
|
||||
// by the next I/O operation, most clients should use
|
||||
// [Reader.ReadBytes] or ReadString instead.
|
||||
// ReadBytes or ReadString instead.
|
||||
// ReadSlice returns err != nil if and only if line does not end in delim.
|
||||
func (b *Reader) ReadSlice(delim byte) (line []byte, err error) {
|
||||
s := 0 // search start index
|
||||
@@ -386,7 +389,7 @@ func (b *Reader) ReadSlice(delim byte) (line []byte, err error) {
|
||||
}
|
||||
|
||||
// ReadLine is a low-level line-reading primitive. Most callers should use
|
||||
// [Reader.ReadBytes]('\n') or [Reader.ReadString]('\n') instead or use a [Scanner].
|
||||
// ReadBytes('\n') or ReadString('\n') instead or use a Scanner.
|
||||
//
|
||||
// ReadLine tries to return a single line, not including the end-of-line bytes.
|
||||
// If the line was too long for the buffer then isPrefix is set and the
|
||||
@@ -398,7 +401,7 @@ func (b *Reader) ReadSlice(delim byte) (line []byte, err error) {
|
||||
//
|
||||
// The text returned from ReadLine does not include the line end ("\r\n" or "\n").
|
||||
// No indication or error is given if the input ends without a final line end.
|
||||
// Calling [Reader.UnreadByte] after ReadLine will always unread the last byte read
|
||||
// Calling UnreadByte after ReadLine will always unread the last byte read
|
||||
// (possibly a character belonging to the line end) even if that byte is not
|
||||
// part of the line returned by ReadLine.
|
||||
func (b *Reader) ReadLine() (line []byte, isPrefix bool, err error) {
|
||||
@@ -508,9 +511,9 @@ func (b *Reader) ReadString(delim byte) (string, error) {
|
||||
}
|
||||
|
||||
// WriteTo implements io.WriterTo.
|
||||
// This may make multiple calls to the [Reader.Read] method of the underlying [Reader].
|
||||
// If the underlying reader supports the [Reader.WriteTo] method,
|
||||
// this calls the underlying [Reader.WriteTo] without buffering.
|
||||
// This may make multiple calls to the Read method of the underlying Reader.
|
||||
// If the underlying reader supports the WriteTo method,
|
||||
// this calls the underlying WriteTo without buffering.
|
||||
func (b *Reader) WriteTo(w io.Writer) (n int64, err error) {
|
||||
b.lastByte = -1
|
||||
b.lastRuneSize = -1
|
||||
@@ -555,7 +558,7 @@ func (b *Reader) WriteTo(w io.Writer) (n int64, err error) {
|
||||
|
||||
var errNegativeWrite = errors.New("bufio: writer returned negative count from Write")
|
||||
|
||||
// writeBuf writes the [Reader]'s buffer to the writer.
|
||||
// writeBuf writes the Reader's buffer to the writer.
|
||||
func (b *Reader) writeBuf(w io.Writer) (int64, error) {
|
||||
n, err := w.Write(b.buf[b.r:b.w])
|
||||
if n < 0 {
|
||||
@@ -567,12 +570,12 @@ func (b *Reader) writeBuf(w io.Writer) (int64, error) {
|
||||
|
||||
// buffered output
|
||||
|
||||
// Writer implements buffering for an [io.Writer] object.
|
||||
// If an error occurs writing to a [Writer], no more data will be
|
||||
// accepted and all subsequent writes, and [Writer.Flush], will return the error.
|
||||
// Writer implements buffering for an io.Writer object.
|
||||
// If an error occurs writing to a Writer, no more data will be
|
||||
// accepted and all subsequent writes, and Flush, will return the error.
|
||||
// After all data has been written, the client should call the
|
||||
// [Writer.Flush] method to guarantee all data has been forwarded to
|
||||
// the underlying [io.Writer].
|
||||
// Flush method to guarantee all data has been forwarded to
|
||||
// the underlying io.Writer.
|
||||
type Writer struct {
|
||||
err error
|
||||
buf []byte
|
||||
@@ -580,9 +583,9 @@ type Writer struct {
|
||||
wr io.Writer
|
||||
}
|
||||
|
||||
// NewWriterSize returns a new [Writer] whose buffer has at least the specified
|
||||
// size. If the argument io.Writer is already a [Writer] with large enough
|
||||
// size, it returns the underlying [Writer].
|
||||
// NewWriterSize returns a new Writer whose buffer has at least the specified
|
||||
// size. If the argument io.Writer is already a Writer with large enough
|
||||
// size, it returns the underlying Writer.
|
||||
func NewWriterSize(w io.Writer, size int) *Writer {
|
||||
// Is it already a Writer?
|
||||
b, ok := w.(*Writer)
|
||||
@@ -598,9 +601,9 @@ func NewWriterSize(w io.Writer, size int) *Writer {
|
||||
}
|
||||
}
|
||||
|
||||
// NewWriter returns a new [Writer] whose buffer has the default size.
|
||||
// If the argument io.Writer is already a [Writer] with large enough buffer size,
|
||||
// it returns the underlying [Writer].
|
||||
// NewWriter returns a new Writer whose buffer has the default size.
|
||||
// If the argument io.Writer is already a Writer with large enough buffer size,
|
||||
// it returns the underlying Writer.
|
||||
func NewWriter(w io.Writer) *Writer {
|
||||
return NewWriterSize(w, defaultBufSize)
|
||||
}
|
||||
@@ -610,9 +613,9 @@ func (b *Writer) Size() int { return len(b.buf) }
|
||||
|
||||
// Reset discards any unflushed buffered data, clears any error, and
|
||||
// resets b to write its output to w.
|
||||
// Calling Reset on the zero value of [Writer] initializes the internal buffer
|
||||
// Calling Reset on the zero value of Writer initializes the internal buffer
|
||||
// to the default size.
|
||||
// Calling w.Reset(w) (that is, resetting a [Writer] to itself) does nothing.
|
||||
// Calling w.Reset(w) (that is, resetting a Writer to itself) does nothing.
|
||||
func (b *Writer) Reset(w io.Writer) {
|
||||
// If a Writer w is passed to NewWriter, NewWriter will return w.
|
||||
// Different layers of code may do that, and then later pass w
|
||||
@@ -628,7 +631,7 @@ func (b *Writer) Reset(w io.Writer) {
|
||||
b.wr = w
|
||||
}
|
||||
|
||||
// Flush writes any buffered data to the underlying [io.Writer].
|
||||
// Flush writes any buffered data to the underlying io.Writer.
|
||||
func (b *Writer) Flush() error {
|
||||
if b.err != nil {
|
||||
return b.err
|
||||
@@ -657,7 +660,7 @@ func (b *Writer) Available() int { return len(b.buf) - b.n }
|
||||
|
||||
// AvailableBuffer returns an empty buffer with b.Available() capacity.
|
||||
// This buffer is intended to be appended to and
|
||||
// passed to an immediately succeeding [Writer.Write] call.
|
||||
// passed to an immediately succeeding Write call.
|
||||
// The buffer is only valid until the next write operation on b.
|
||||
func (b *Writer) AvailableBuffer() []byte {
|
||||
return b.buf[b.n:][:0]
|
||||
@@ -774,7 +777,7 @@ func (b *Writer) WriteString(s string) (int, error) {
|
||||
return nn, nil
|
||||
}
|
||||
|
||||
// ReadFrom implements [io.ReaderFrom]. If the underlying writer
|
||||
// ReadFrom implements io.ReaderFrom. If the underlying writer
|
||||
// supports the ReadFrom method, this calls the underlying ReadFrom.
|
||||
// If there is buffered data and an underlying ReadFrom, this fills
|
||||
// the buffer and writes it before calling ReadFrom.
|
||||
@@ -826,14 +829,14 @@ func (b *Writer) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
|
||||
// buffered input and output
|
||||
|
||||
// ReadWriter stores pointers to a [Reader] and a [Writer].
|
||||
// It implements [io.ReadWriter].
|
||||
// ReadWriter stores pointers to a Reader and a Writer.
|
||||
// It implements io.ReadWriter.
|
||||
type ReadWriter struct {
|
||||
*Reader
|
||||
*Writer
|
||||
}
|
||||
|
||||
// NewReadWriter allocates a new [ReadWriter] that dispatches to r and w.
|
||||
// NewReadWriter allocates a new ReadWriter that dispatches to r and w.
|
||||
func NewReadWriter(r *Reader, w *Writer) *ReadWriter {
|
||||
return &ReadWriter{r, w}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ package bufio_test
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
@@ -138,36 +137,3 @@ func ExampleScanner_emptyFinalToken() {
|
||||
}
|
||||
// Output: "1" "2" "3" "4" ""
|
||||
}
|
||||
|
||||
// Use a Scanner with a custom split function to parse a comma-separated
|
||||
// list with an empty final value but stops at the token "STOP".
|
||||
func ExampleScanner_earlyStop() {
|
||||
onComma := func(data []byte, atEOF bool) (advance int, token []byte, err error) {
|
||||
i := bytes.IndexByte(data, ',')
|
||||
if i == -1 {
|
||||
if !atEOF {
|
||||
return 0, nil, nil
|
||||
}
|
||||
// If we have reached the end, return the last token.
|
||||
return 0, data, bufio.ErrFinalToken
|
||||
}
|
||||
// If the token is "STOP", stop the scanning and ignore the rest.
|
||||
if string(data[:i]) == "STOP" {
|
||||
return i + 1, nil, bufio.ErrFinalToken
|
||||
}
|
||||
// Otherwise, return the token before the comma.
|
||||
return i + 1, data[:i], nil
|
||||
}
|
||||
const input = "1,2,STOP,4,"
|
||||
scanner := bufio.NewScanner(strings.NewReader(input))
|
||||
scanner.Split(onComma)
|
||||
for scanner.Scan() {
|
||||
fmt.Printf("Got a token %q\n", scanner.Text())
|
||||
}
|
||||
if err := scanner.Err(); err != nil {
|
||||
fmt.Fprintln(os.Stderr, "reading input:", err)
|
||||
}
|
||||
// Output:
|
||||
// Got a token "1"
|
||||
// Got a token "2"
|
||||
}
|
||||
|
||||
@@ -13,19 +13,19 @@ import (
|
||||
|
||||
// Scanner provides a convenient interface for reading data such as
|
||||
// a file of newline-delimited lines of text. Successive calls to
|
||||
// the [Scanner.Scan] method will step through the 'tokens' of a file, skipping
|
||||
// the Scan method will step through the 'tokens' of a file, skipping
|
||||
// the bytes between the tokens. The specification of a token is
|
||||
// defined by a split function of type [SplitFunc]; the default split
|
||||
// function breaks the input into lines with line termination stripped. [Scanner.Split]
|
||||
// defined by a split function of type SplitFunc; the default split
|
||||
// function breaks the input into lines with line termination stripped. Split
|
||||
// functions are defined in this package for scanning a file into
|
||||
// lines, bytes, UTF-8-encoded runes, and space-delimited words. The
|
||||
// client may instead provide a custom split function.
|
||||
//
|
||||
// Scanning stops unrecoverably at EOF, the first I/O error, or a token too
|
||||
// large to fit in the [Scanner.Buffer]. When a scan stops, the reader may have
|
||||
// large to fit in the buffer. When a scan stops, the reader may have
|
||||
// advanced arbitrarily far past the last token. Programs that need more
|
||||
// control over error handling or large tokens, or must run sequential scans
|
||||
// on a reader, should use [bufio.Reader] instead.
|
||||
// on a reader, should use bufio.Reader instead.
|
||||
type Scanner struct {
|
||||
r io.Reader // The reader provided by the client.
|
||||
split SplitFunc // The function to split the tokens.
|
||||
@@ -42,23 +42,21 @@ type Scanner struct {
|
||||
|
||||
// SplitFunc is the signature of the split function used to tokenize the
|
||||
// input. The arguments are an initial substring of the remaining unprocessed
|
||||
// data and a flag, atEOF, that reports whether the [Reader] has no more data
|
||||
// data and a flag, atEOF, that reports whether the Reader has no more data
|
||||
// to give. The return values are the number of bytes to advance the input
|
||||
// and the next token to return to the user, if any, plus an error, if any.
|
||||
//
|
||||
// Scanning stops if the function returns an error, in which case some of
|
||||
// the input may be discarded. If that error is [ErrFinalToken], scanning
|
||||
// stops with no error. A non-nil token delivered with [ErrFinalToken]
|
||||
// will be the last token, and a nil token with [ErrFinalToken]
|
||||
// immediately stops the scanning.
|
||||
// the input may be discarded. If that error is ErrFinalToken, scanning
|
||||
// stops with no error.
|
||||
//
|
||||
// Otherwise, the [Scanner] advances the input. If the token is not nil,
|
||||
// the [Scanner] returns it to the user. If the token is nil, the
|
||||
// Otherwise, the Scanner advances the input. If the token is not nil,
|
||||
// the Scanner returns it to the user. If the token is nil, the
|
||||
// Scanner reads more data and continues scanning; if there is no more
|
||||
// data--if atEOF was true--the [Scanner] returns. If the data does not
|
||||
// data--if atEOF was true--the Scanner returns. If the data does not
|
||||
// yet hold a complete token, for instance if it has no newline while
|
||||
// scanning lines, a [SplitFunc] can return (0, nil, nil) to signal the
|
||||
// [Scanner] to read more data into the slice and try again with a
|
||||
// scanning lines, a SplitFunc can return (0, nil, nil) to signal the
|
||||
// Scanner to read more data into the slice and try again with a
|
||||
// longer slice starting at the same point in the input.
|
||||
//
|
||||
// The function is never called with an empty data slice unless atEOF
|
||||
@@ -76,7 +74,7 @@ var (
|
||||
|
||||
const (
|
||||
// MaxScanTokenSize is the maximum size used to buffer a token
|
||||
// unless the user provides an explicit buffer with [Scanner.Buffer].
|
||||
// unless the user provides an explicit buffer with Scanner.Buffer.
|
||||
// The actual maximum token size may be smaller as the buffer
|
||||
// may need to include, for instance, a newline.
|
||||
MaxScanTokenSize = 64 * 1024
|
||||
@@ -84,8 +82,8 @@ const (
|
||||
startBufSize = 4096 // Size of initial allocation for buffer.
|
||||
)
|
||||
|
||||
// NewScanner returns a new [Scanner] to read from r.
|
||||
// The split function defaults to [ScanLines].
|
||||
// NewScanner returns a new Scanner to read from r.
|
||||
// The split function defaults to ScanLines.
|
||||
func NewScanner(r io.Reader) *Scanner {
|
||||
return &Scanner{
|
||||
r: r,
|
||||
@@ -94,7 +92,7 @@ func NewScanner(r io.Reader) *Scanner {
|
||||
}
|
||||
}
|
||||
|
||||
// Err returns the first non-EOF error that was encountered by the [Scanner].
|
||||
// Err returns the first non-EOF error that was encountered by the Scanner.
|
||||
func (s *Scanner) Err() error {
|
||||
if s.err == io.EOF {
|
||||
return nil
|
||||
@@ -102,36 +100,34 @@ func (s *Scanner) Err() error {
|
||||
return s.err
|
||||
}
|
||||
|
||||
// Bytes returns the most recent token generated by a call to [Scanner.Scan].
|
||||
// Bytes returns the most recent token generated by a call to Scan.
|
||||
// The underlying array may point to data that will be overwritten
|
||||
// by a subsequent call to Scan. It does no allocation.
|
||||
func (s *Scanner) Bytes() []byte {
|
||||
return s.token
|
||||
}
|
||||
|
||||
// Text returns the most recent token generated by a call to [Scanner.Scan]
|
||||
// Text returns the most recent token generated by a call to Scan
|
||||
// as a newly allocated string holding its bytes.
|
||||
func (s *Scanner) Text() string {
|
||||
return string(s.token)
|
||||
}
|
||||
|
||||
// ErrFinalToken is a special sentinel error value. It is intended to be
|
||||
// returned by a Split function to indicate that the scanning should stop
|
||||
// with no error. If the token being delivered with this error is not nil,
|
||||
// the token is the last token.
|
||||
//
|
||||
// returned by a Split function to indicate that the token being delivered
|
||||
// with the error is the last token and scanning should stop after this one.
|
||||
// After ErrFinalToken is received by Scan, scanning stops with no error.
|
||||
// The value is useful to stop processing early or when it is necessary to
|
||||
// deliver a final empty token (which is different from a nil token).
|
||||
// One could achieve the same behavior with a custom error value but
|
||||
// providing one here is tidier.
|
||||
// deliver a final empty token. One could achieve the same behavior
|
||||
// with a custom error value but providing one here is tidier.
|
||||
// See the emptyFinalToken example for a use of this value.
|
||||
var ErrFinalToken = errors.New("final token")
|
||||
|
||||
// Scan advances the [Scanner] to the next token, which will then be
|
||||
// available through the [Scanner.Bytes] or [Scanner.Text] method. It returns false when
|
||||
// there are no more tokens, either by reaching the end of the input or an error.
|
||||
// After Scan returns false, the [Scanner.Err] method will return any error that
|
||||
// occurred during scanning, except that if it was [io.EOF], [Scanner.Err]
|
||||
// Scan advances the Scanner to the next token, which will then be
|
||||
// available through the Bytes or Text method. It returns false when the
|
||||
// scan stops, either by reaching the end of the input or an error.
|
||||
// After Scan returns false, the Err method will return any error that
|
||||
// occurred during scanning, except that if it was io.EOF, Err
|
||||
// will return nil.
|
||||
// Scan panics if the split function returns too many empty
|
||||
// tokens without advancing the input. This is a common error mode for
|
||||
@@ -152,10 +148,7 @@ func (s *Scanner) Scan() bool {
|
||||
if err == ErrFinalToken {
|
||||
s.token = token
|
||||
s.done = true
|
||||
// When token is not nil, it means the scanning stops
|
||||
// with a trailing token, and thus the return value
|
||||
// should be true to indicate the existence of the token.
|
||||
return token != nil
|
||||
return true
|
||||
}
|
||||
s.setErr(err)
|
||||
return false
|
||||
@@ -205,7 +198,9 @@ func (s *Scanner) Scan() bool {
|
||||
if newSize == 0 {
|
||||
newSize = startBufSize
|
||||
}
|
||||
newSize = min(newSize, s.maxTokenSize)
|
||||
if newSize > s.maxTokenSize {
|
||||
newSize = s.maxTokenSize
|
||||
}
|
||||
newBuf := make([]byte, newSize)
|
||||
copy(newBuf, s.buf[s.start:s.end])
|
||||
s.buf = newBuf
|
||||
@@ -260,13 +255,13 @@ func (s *Scanner) setErr(err error) {
|
||||
}
|
||||
}
|
||||
|
||||
// Buffer sets the initial buffer to use when scanning
|
||||
// and the maximum size of buffer that may be allocated during scanning.
|
||||
// The maximum token size must be less than the larger of max and cap(buf).
|
||||
// If max <= cap(buf), [Scanner.Scan] will use this buffer only and do no allocation.
|
||||
// Buffer sets the initial buffer to use when scanning and the maximum
|
||||
// size of buffer that may be allocated during scanning. The maximum
|
||||
// token size is the larger of max and cap(buf). If max <= cap(buf),
|
||||
// Scan will use this buffer only and do no allocation.
|
||||
//
|
||||
// By default, [Scanner.Scan] uses an internal buffer and sets the
|
||||
// maximum token size to [MaxScanTokenSize].
|
||||
// By default, Scan uses an internal buffer and sets the
|
||||
// maximum token size to MaxScanTokenSize.
|
||||
//
|
||||
// Buffer panics if it is called after scanning has started.
|
||||
func (s *Scanner) Buffer(buf []byte, max int) {
|
||||
@@ -277,8 +272,8 @@ func (s *Scanner) Buffer(buf []byte, max int) {
|
||||
s.maxTokenSize = max
|
||||
}
|
||||
|
||||
// Split sets the split function for the [Scanner].
|
||||
// The default split function is [ScanLines].
|
||||
// Split sets the split function for the Scanner.
|
||||
// The default split function is ScanLines.
|
||||
//
|
||||
// Split panics if it is called after scanning has started.
|
||||
func (s *Scanner) Split(split SplitFunc) {
|
||||
@@ -290,7 +285,7 @@ func (s *Scanner) Split(split SplitFunc) {
|
||||
|
||||
// Split functions
|
||||
|
||||
// ScanBytes is a split function for a [Scanner] that returns each byte as a token.
|
||||
// ScanBytes is a split function for a Scanner that returns each byte as a token.
|
||||
func ScanBytes(data []byte, atEOF bool) (advance int, token []byte, err error) {
|
||||
if atEOF && len(data) == 0 {
|
||||
return 0, nil, nil
|
||||
@@ -300,7 +295,7 @@ func ScanBytes(data []byte, atEOF bool) (advance int, token []byte, err error) {
|
||||
|
||||
var errorRune = []byte(string(utf8.RuneError))
|
||||
|
||||
// ScanRunes is a split function for a [Scanner] that returns each
|
||||
// ScanRunes is a split function for a Scanner that returns each
|
||||
// UTF-8-encoded rune as a token. The sequence of runes returned is
|
||||
// equivalent to that from a range loop over the input as a string, which
|
||||
// means that erroneous UTF-8 encodings translate to U+FFFD = "\xef\xbf\xbd".
|
||||
@@ -346,7 +341,7 @@ func dropCR(data []byte) []byte {
|
||||
return data
|
||||
}
|
||||
|
||||
// ScanLines is a split function for a [Scanner] that returns each line of
|
||||
// ScanLines is a split function for a Scanner that returns each line of
|
||||
// text, stripped of any trailing end-of-line marker. The returned line may
|
||||
// be empty. The end-of-line marker is one optional carriage return followed
|
||||
// by one mandatory newline. In regular expression notation, it is `\r?\n`.
|
||||
@@ -393,7 +388,7 @@ func isSpace(r rune) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// ScanWords is a split function for a [Scanner] that returns each
|
||||
// ScanWords is a split function for a Scanner that returns each
|
||||
// space-separated word of text, with surrounding spaces deleted. It will
|
||||
// never return an empty string. The definition of space is set by
|
||||
// unicode.IsSpace.
|
||||
|
||||
@@ -68,7 +68,7 @@ func TestScanRune(t *testing.T) {
|
||||
var i, runeCount int
|
||||
var expect rune
|
||||
// Use a string range loop to validate the sequence of runes.
|
||||
for i, expect = range test {
|
||||
for i, expect = range string(test) {
|
||||
if !s.Scan() {
|
||||
break
|
||||
}
|
||||
|
||||
@@ -6,12 +6,8 @@
|
||||
# Usage: buildall.bash [-e] [pattern]
|
||||
#
|
||||
# buildall.bash builds the standard library for all Go-supported
|
||||
# architectures.
|
||||
#
|
||||
# Originally the Go build system used it as a smoke test to quickly
|
||||
# flag portability issues in builders named "misc-compile" or "all-compile".
|
||||
# As of CL 464955, the build system uses make.bash -compile-only instead,
|
||||
# so this script no longer runs in any automated fashion.
|
||||
# architectures. It is used by the "misc-compile" trybot builders,
|
||||
# as a smoke test to quickly flag portability issues.
|
||||
#
|
||||
# Options:
|
||||
# -e: stop at first failure
|
||||
|
||||
@@ -284,10 +284,9 @@ func panic(v any)
|
||||
// by restoring normal execution and retrieves the error value passed to the
|
||||
// call of panic. If recover is called outside the deferred function it will
|
||||
// not stop a panicking sequence. In this case, or when the goroutine is not
|
||||
// panicking, recover returns nil.
|
||||
//
|
||||
// Prior to Go 1.21, recover would also return nil if panic is called with
|
||||
// a nil argument. See [panic] for details.
|
||||
// panicking, or if the argument supplied to panic was nil, recover returns
|
||||
// nil. Thus the return value from recover reports whether the goroutine is
|
||||
// panicking.
|
||||
func recover() any
|
||||
|
||||
// The print built-in function formats its arguments in an
|
||||
|
||||
@@ -98,18 +98,3 @@ func TestIndexNearPageBoundary(t *testing.T) {
|
||||
}
|
||||
q[len(q)-1] = 0
|
||||
}
|
||||
|
||||
func TestCountNearPageBoundary(t *testing.T) {
|
||||
t.Parallel()
|
||||
b := dangerousSlice(t)
|
||||
for i := range b {
|
||||
c := Count(b[i:], []byte{1})
|
||||
if c != 0 {
|
||||
t.Fatalf("Count(b[%d:], {1})=%d, want 0\n", i, c)
|
||||
}
|
||||
c = Count(b[:i], []byte{0})
|
||||
if c != i {
|
||||
t.Fatalf("Count(b[:%d], {0})=%d, want %d\n", i, c, i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
// smallBufferSize is an initial allocation minimal capacity.
|
||||
const smallBufferSize = 64
|
||||
|
||||
// A Buffer is a variable-sized buffer of bytes with [Buffer.Read] and [Buffer.Write] methods.
|
||||
// A Buffer is a variable-sized buffer of bytes with Read and Write methods.
|
||||
// The zero value for Buffer is an empty buffer ready to use.
|
||||
type Buffer struct {
|
||||
buf []byte // contents are the bytes buf[off : len(buf)]
|
||||
@@ -48,19 +48,19 @@ const maxInt = int(^uint(0) >> 1)
|
||||
|
||||
// Bytes returns a slice of length b.Len() holding the unread portion of the buffer.
|
||||
// The slice is valid for use only until the next buffer modification (that is,
|
||||
// only until the next call to a method like [Buffer.Read], [Buffer.Write], [Buffer.Reset], or [Buffer.Truncate]).
|
||||
// only until the next call to a method like Read, Write, Reset, or Truncate).
|
||||
// The slice aliases the buffer content at least until the next buffer modification,
|
||||
// so immediate changes to the slice will affect the result of future reads.
|
||||
func (b *Buffer) Bytes() []byte { return b.buf[b.off:] }
|
||||
|
||||
// AvailableBuffer returns an empty buffer with b.Available() capacity.
|
||||
// This buffer is intended to be appended to and
|
||||
// passed to an immediately succeeding [Buffer.Write] call.
|
||||
// passed to an immediately succeeding Write call.
|
||||
// The buffer is only valid until the next write operation on b.
|
||||
func (b *Buffer) AvailableBuffer() []byte { return b.buf[len(b.buf):] }
|
||||
|
||||
// String returns the contents of the unread portion of the buffer
|
||||
// as a string. If the [Buffer] is a nil pointer, it returns "<nil>".
|
||||
// as a string. If the Buffer is a nil pointer, it returns "<nil>".
|
||||
//
|
||||
// To build strings more efficiently, see the strings.Builder type.
|
||||
func (b *Buffer) String() string {
|
||||
@@ -102,7 +102,7 @@ func (b *Buffer) Truncate(n int) {
|
||||
|
||||
// Reset resets the buffer to be empty,
|
||||
// but it retains the underlying storage for use by future writes.
|
||||
// Reset is the same as [Buffer.Truncate](0).
|
||||
// Reset is the same as Truncate(0).
|
||||
func (b *Buffer) Reset() {
|
||||
b.buf = b.buf[:0]
|
||||
b.off = 0
|
||||
@@ -160,7 +160,7 @@ func (b *Buffer) grow(n int) int {
|
||||
// another n bytes. After Grow(n), at least n bytes can be written to the
|
||||
// buffer without another allocation.
|
||||
// If n is negative, Grow will panic.
|
||||
// If the buffer can't grow it will panic with [ErrTooLarge].
|
||||
// If the buffer can't grow it will panic with ErrTooLarge.
|
||||
func (b *Buffer) Grow(n int) {
|
||||
if n < 0 {
|
||||
panic("bytes.Buffer.Grow: negative count")
|
||||
@@ -171,7 +171,7 @@ func (b *Buffer) Grow(n int) {
|
||||
|
||||
// Write appends the contents of p to the buffer, growing the buffer as
|
||||
// needed. The return value n is the length of p; err is always nil. If the
|
||||
// buffer becomes too large, Write will panic with [ErrTooLarge].
|
||||
// buffer becomes too large, Write will panic with ErrTooLarge.
|
||||
func (b *Buffer) Write(p []byte) (n int, err error) {
|
||||
b.lastRead = opInvalid
|
||||
m, ok := b.tryGrowByReslice(len(p))
|
||||
@@ -183,7 +183,7 @@ func (b *Buffer) Write(p []byte) (n int, err error) {
|
||||
|
||||
// WriteString appends the contents of s to the buffer, growing the buffer as
|
||||
// needed. The return value n is the length of s; err is always nil. If the
|
||||
// buffer becomes too large, WriteString will panic with [ErrTooLarge].
|
||||
// buffer becomes too large, WriteString will panic with ErrTooLarge.
|
||||
func (b *Buffer) WriteString(s string) (n int, err error) {
|
||||
b.lastRead = opInvalid
|
||||
m, ok := b.tryGrowByReslice(len(s))
|
||||
@@ -194,7 +194,7 @@ func (b *Buffer) WriteString(s string) (n int, err error) {
|
||||
}
|
||||
|
||||
// MinRead is the minimum slice size passed to a Read call by
|
||||
// [Buffer.ReadFrom]. As long as the [Buffer] has at least MinRead bytes beyond
|
||||
// Buffer.ReadFrom. As long as the Buffer has at least MinRead bytes beyond
|
||||
// what is required to hold the contents of r, ReadFrom will not grow the
|
||||
// underlying buffer.
|
||||
const MinRead = 512
|
||||
@@ -202,7 +202,7 @@ const MinRead = 512
|
||||
// ReadFrom reads data from r until EOF and appends it to the buffer, growing
|
||||
// the buffer as needed. The return value n is the number of bytes read. Any
|
||||
// error except io.EOF encountered during the read is also returned. If the
|
||||
// buffer becomes too large, ReadFrom will panic with [ErrTooLarge].
|
||||
// buffer becomes too large, ReadFrom will panic with ErrTooLarge.
|
||||
func (b *Buffer) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
b.lastRead = opInvalid
|
||||
for {
|
||||
@@ -279,9 +279,9 @@ func (b *Buffer) WriteTo(w io.Writer) (n int64, err error) {
|
||||
}
|
||||
|
||||
// WriteByte appends the byte c to the buffer, growing the buffer as needed.
|
||||
// The returned error is always nil, but is included to match [bufio.Writer]'s
|
||||
// The returned error is always nil, but is included to match bufio.Writer's
|
||||
// WriteByte. If the buffer becomes too large, WriteByte will panic with
|
||||
// [ErrTooLarge].
|
||||
// ErrTooLarge.
|
||||
func (b *Buffer) WriteByte(c byte) error {
|
||||
b.lastRead = opInvalid
|
||||
m, ok := b.tryGrowByReslice(1)
|
||||
@@ -294,8 +294,8 @@ func (b *Buffer) WriteByte(c byte) error {
|
||||
|
||||
// WriteRune appends the UTF-8 encoding of Unicode code point r to the
|
||||
// buffer, returning its length and an error, which is always nil but is
|
||||
// included to match [bufio.Writer]'s WriteRune. The buffer is grown as needed;
|
||||
// if it becomes too large, WriteRune will panic with [ErrTooLarge].
|
||||
// included to match bufio.Writer's WriteRune. The buffer is grown as needed;
|
||||
// if it becomes too large, WriteRune will panic with ErrTooLarge.
|
||||
func (b *Buffer) WriteRune(r rune) (n int, err error) {
|
||||
// Compare as uint32 to correctly handle negative runes.
|
||||
if uint32(r) < utf8.RuneSelf {
|
||||
@@ -334,7 +334,7 @@ func (b *Buffer) Read(p []byte) (n int, err error) {
|
||||
}
|
||||
|
||||
// Next returns a slice containing the next n bytes from the buffer,
|
||||
// advancing the buffer as if the bytes had been returned by [Buffer.Read].
|
||||
// advancing the buffer as if the bytes had been returned by Read.
|
||||
// If there are fewer than n bytes in the buffer, Next returns the entire buffer.
|
||||
// The slice is only valid until the next call to a read or write method.
|
||||
func (b *Buffer) Next(n int) []byte {
|
||||
@@ -388,10 +388,10 @@ func (b *Buffer) ReadRune() (r rune, size int, err error) {
|
||||
return r, n, nil
|
||||
}
|
||||
|
||||
// UnreadRune unreads the last rune returned by [Buffer.ReadRune].
|
||||
// UnreadRune unreads the last rune returned by ReadRune.
|
||||
// If the most recent read or write operation on the buffer was
|
||||
// not a successful [Buffer.ReadRune], UnreadRune returns an error. (In this regard
|
||||
// it is stricter than [Buffer.UnreadByte], which will unread the last byte
|
||||
// not a successful ReadRune, UnreadRune returns an error. (In this regard
|
||||
// it is stricter than UnreadByte, which will unread the last byte
|
||||
// from any read operation.)
|
||||
func (b *Buffer) UnreadRune() error {
|
||||
if b.lastRead <= opInvalid {
|
||||
@@ -460,23 +460,23 @@ func (b *Buffer) ReadString(delim byte) (line string, err error) {
|
||||
return string(slice), err
|
||||
}
|
||||
|
||||
// NewBuffer creates and initializes a new [Buffer] using buf as its
|
||||
// initial contents. The new [Buffer] takes ownership of buf, and the
|
||||
// NewBuffer creates and initializes a new Buffer using buf as its
|
||||
// initial contents. The new Buffer takes ownership of buf, and the
|
||||
// caller should not use buf after this call. NewBuffer is intended to
|
||||
// prepare a [Buffer] to read existing data. It can also be used to set
|
||||
// prepare a Buffer to read existing data. It can also be used to set
|
||||
// the initial size of the internal buffer for writing. To do that,
|
||||
// buf should have the desired capacity but a length of zero.
|
||||
//
|
||||
// In most cases, new([Buffer]) (or just declaring a [Buffer] variable) is
|
||||
// sufficient to initialize a [Buffer].
|
||||
// In most cases, new(Buffer) (or just declaring a Buffer variable) is
|
||||
// sufficient to initialize a Buffer.
|
||||
func NewBuffer(buf []byte) *Buffer { return &Buffer{buf: buf} }
|
||||
|
||||
// NewBufferString creates and initializes a new [Buffer] using string s as its
|
||||
// NewBufferString creates and initializes a new Buffer using string s as its
|
||||
// initial contents. It is intended to prepare a buffer to read an existing
|
||||
// string.
|
||||
//
|
||||
// In most cases, new([Buffer]) (or just declaring a [Buffer] variable) is
|
||||
// sufficient to initialize a [Buffer].
|
||||
// In most cases, new(Buffer) (or just declaring a Buffer variable) is
|
||||
// sufficient to initialize a Buffer.
|
||||
func NewBufferString(s string) *Buffer {
|
||||
return &Buffer{buf: []byte(s)}
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ func LastIndex(s, sep []byte) int {
|
||||
case n == 0:
|
||||
return len(s)
|
||||
case n == 1:
|
||||
return bytealg.LastIndexByte(s, sep[0])
|
||||
return LastIndexByte(s, sep[0])
|
||||
case n == len(s):
|
||||
if Equal(s, sep) {
|
||||
return 0
|
||||
@@ -121,12 +121,35 @@ func LastIndex(s, sep []byte) int {
|
||||
case n > len(s):
|
||||
return -1
|
||||
}
|
||||
return bytealg.LastIndexRabinKarp(s, sep)
|
||||
// Rabin-Karp search from the end of the string
|
||||
hashss, pow := bytealg.HashStrRevBytes(sep)
|
||||
last := len(s) - n
|
||||
var h uint32
|
||||
for i := len(s) - 1; i >= last; i-- {
|
||||
h = h*bytealg.PrimeRK + uint32(s[i])
|
||||
}
|
||||
if h == hashss && Equal(s[last:], sep) {
|
||||
return last
|
||||
}
|
||||
for i := last - 1; i >= 0; i-- {
|
||||
h *= bytealg.PrimeRK
|
||||
h += uint32(s[i])
|
||||
h -= pow * uint32(s[i+n])
|
||||
if h == hashss && Equal(s[i:i+n], sep) {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
// LastIndexByte returns the index of the last instance of c in s, or -1 if c is not present in s.
|
||||
func LastIndexByte(s []byte, c byte) int {
|
||||
return bytealg.LastIndexByte(s, c)
|
||||
for i := len(s) - 1; i >= 0; i-- {
|
||||
if s[i] == c {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
// IndexRune interprets s as a sequence of UTF-8-encoded code points.
|
||||
@@ -534,12 +557,12 @@ func Join(s [][]byte, sep []byte) []byte {
|
||||
return b
|
||||
}
|
||||
|
||||
// HasPrefix reports whether the byte slice s begins with prefix.
|
||||
// HasPrefix tests whether the byte slice s begins with prefix.
|
||||
func HasPrefix(s, prefix []byte) bool {
|
||||
return len(s) >= len(prefix) && Equal(s[0:len(prefix)], prefix)
|
||||
}
|
||||
|
||||
// HasSuffix reports whether the byte slice s ends with suffix.
|
||||
// HasSuffix tests whether the byte slice s ends with suffix.
|
||||
func HasSuffix(s, suffix []byte) bool {
|
||||
return len(s) >= len(suffix) && Equal(s[len(s)-len(suffix):], suffix)
|
||||
}
|
||||
@@ -1313,7 +1336,7 @@ func Index(s, sep []byte) int {
|
||||
// we should cutover at even larger average skips,
|
||||
// because Equal becomes that much more expensive.
|
||||
// This code does not take that effect into account.
|
||||
j := bytealg.IndexRabinKarp(s[i:], sep)
|
||||
j := bytealg.IndexRabinKarpBytes(s[i:], sep)
|
||||
if j < 0 {
|
||||
return -1
|
||||
}
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
// Copyright 2024 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build js && wasm
|
||||
|
||||
package bytes_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestIssue65571(t *testing.T) {
|
||||
b := make([]byte, 1<<31+1)
|
||||
b[1<<31] = 1
|
||||
i := bytes.IndexByte(b, 1)
|
||||
if i != 1<<31 {
|
||||
t.Errorf("IndexByte(b, 1) = %d; want %d", i, 1<<31)
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ package bytes_test
|
||||
import (
|
||||
. "bytes"
|
||||
"fmt"
|
||||
"internal/testenv"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -72,7 +73,7 @@ func TestCompareBytes(t *testing.T) {
|
||||
}
|
||||
lengths = append(lengths, 256, 512, 1024, 1333, 4095, 4096, 4097)
|
||||
|
||||
if !testing.Short() {
|
||||
if !testing.Short() || testenv.Builder() != "" {
|
||||
lengths = append(lengths, 65535, 65536, 65537, 99999)
|
||||
}
|
||||
|
||||
|
||||
@@ -81,9 +81,9 @@ func ExampleBuffer_Next() {
|
||||
var b bytes.Buffer
|
||||
b.Grow(64)
|
||||
b.Write([]byte("abcde"))
|
||||
fmt.Printf("%s\n", b.Next(2))
|
||||
fmt.Printf("%s\n", b.Next(2))
|
||||
fmt.Printf("%s", b.Next(2))
|
||||
fmt.Printf("%s\n", string(b.Next(2)))
|
||||
fmt.Printf("%s\n", string(b.Next(2)))
|
||||
fmt.Printf("%s", string(b.Next(2)))
|
||||
// Output:
|
||||
// ab
|
||||
// cd
|
||||
@@ -212,17 +212,6 @@ func ExampleContainsRune() {
|
||||
// false
|
||||
}
|
||||
|
||||
func ExampleContainsFunc() {
|
||||
f := func(r rune) bool {
|
||||
return r >= 'a' && r <= 'z'
|
||||
}
|
||||
fmt.Println(bytes.ContainsFunc([]byte("HELLO"), f))
|
||||
fmt.Println(bytes.ContainsFunc([]byte("World"), f))
|
||||
// Output:
|
||||
// false
|
||||
// true
|
||||
}
|
||||
|
||||
func ExampleCount() {
|
||||
fmt.Println(bytes.Count([]byte("cheese"), []byte("e")))
|
||||
fmt.Println(bytes.Count([]byte("five"), []byte(""))) // before & after each rune
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
// A Reader implements the io.Reader, io.ReaderAt, io.WriterTo, io.Seeker,
|
||||
// io.ByteScanner, and io.RuneScanner interfaces by reading from
|
||||
// a byte slice.
|
||||
// Unlike a [Buffer], a Reader is read-only and supports seeking.
|
||||
// Unlike a Buffer, a Reader is read-only and supports seeking.
|
||||
// The zero value for Reader operates like a Reader of an empty slice.
|
||||
type Reader struct {
|
||||
s []byte
|
||||
@@ -31,11 +31,11 @@ func (r *Reader) Len() int {
|
||||
}
|
||||
|
||||
// Size returns the original length of the underlying byte slice.
|
||||
// Size is the number of bytes available for reading via [Reader.ReadAt].
|
||||
// The result is unaffected by any method calls except [Reader.Reset].
|
||||
// Size is the number of bytes available for reading via ReadAt.
|
||||
// The result is unaffected by any method calls except Reset.
|
||||
func (r *Reader) Size() int64 { return int64(len(r.s)) }
|
||||
|
||||
// Read implements the [io.Reader] interface.
|
||||
// Read implements the io.Reader interface.
|
||||
func (r *Reader) Read(b []byte) (n int, err error) {
|
||||
if r.i >= int64(len(r.s)) {
|
||||
return 0, io.EOF
|
||||
@@ -46,7 +46,7 @@ func (r *Reader) Read(b []byte) (n int, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// ReadAt implements the [io.ReaderAt] interface.
|
||||
// ReadAt implements the io.ReaderAt interface.
|
||||
func (r *Reader) ReadAt(b []byte, off int64) (n int, err error) {
|
||||
// cannot modify state - see io.ReaderAt
|
||||
if off < 0 {
|
||||
@@ -62,7 +62,7 @@ func (r *Reader) ReadAt(b []byte, off int64) (n int, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// ReadByte implements the [io.ByteReader] interface.
|
||||
// ReadByte implements the io.ByteReader interface.
|
||||
func (r *Reader) ReadByte() (byte, error) {
|
||||
r.prevRune = -1
|
||||
if r.i >= int64(len(r.s)) {
|
||||
@@ -73,7 +73,7 @@ func (r *Reader) ReadByte() (byte, error) {
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// UnreadByte complements [Reader.ReadByte] in implementing the [io.ByteScanner] interface.
|
||||
// UnreadByte complements ReadByte in implementing the io.ByteScanner interface.
|
||||
func (r *Reader) UnreadByte() error {
|
||||
if r.i <= 0 {
|
||||
return errors.New("bytes.Reader.UnreadByte: at beginning of slice")
|
||||
@@ -83,7 +83,7 @@ func (r *Reader) UnreadByte() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReadRune implements the [io.RuneReader] interface.
|
||||
// ReadRune implements the io.RuneReader interface.
|
||||
func (r *Reader) ReadRune() (ch rune, size int, err error) {
|
||||
if r.i >= int64(len(r.s)) {
|
||||
r.prevRune = -1
|
||||
@@ -99,7 +99,7 @@ func (r *Reader) ReadRune() (ch rune, size int, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// UnreadRune complements [Reader.ReadRune] in implementing the [io.RuneScanner] interface.
|
||||
// UnreadRune complements ReadRune in implementing the io.RuneScanner interface.
|
||||
func (r *Reader) UnreadRune() error {
|
||||
if r.i <= 0 {
|
||||
return errors.New("bytes.Reader.UnreadRune: at beginning of slice")
|
||||
@@ -112,7 +112,7 @@ func (r *Reader) UnreadRune() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Seek implements the [io.Seeker] interface.
|
||||
// Seek implements the io.Seeker interface.
|
||||
func (r *Reader) Seek(offset int64, whence int) (int64, error) {
|
||||
r.prevRune = -1
|
||||
var abs int64
|
||||
@@ -133,7 +133,7 @@ func (r *Reader) Seek(offset int64, whence int) (int64, error) {
|
||||
return abs, nil
|
||||
}
|
||||
|
||||
// WriteTo implements the [io.WriterTo] interface.
|
||||
// WriteTo implements the io.WriterTo interface.
|
||||
func (r *Reader) WriteTo(w io.Writer) (n int64, err error) {
|
||||
r.prevRune = -1
|
||||
if r.i >= int64(len(r.s)) {
|
||||
@@ -152,8 +152,8 @@ func (r *Reader) WriteTo(w io.Writer) (n int64, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// Reset resets the [Reader.Reader] to be reading from b.
|
||||
// Reset resets the Reader to be reading from b.
|
||||
func (r *Reader) Reset(b []byte) { *r = Reader{b, 0, -1} }
|
||||
|
||||
// NewReader returns a new [Reader.Reader] reading from b.
|
||||
// NewReader returns a new Reader reading from b.
|
||||
func NewReader(b []byte) *Reader { return &Reader{b, 0, -1} }
|
||||
|
||||
@@ -2,10 +2,9 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This package computes the exported API of a set of Go packages.
|
||||
// Package api computes the exported API of a set of Go packages.
|
||||
// It is only a test, not a command, nor a usefully importable package.
|
||||
|
||||
package main
|
||||
package api
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
@@ -106,7 +105,7 @@ func Check(t *testing.T) {
|
||||
}
|
||||
|
||||
var nextFiles []string
|
||||
if v := runtime.Version(); strings.Contains(v, "devel") || strings.Contains(v, "beta") {
|
||||
if strings.Contains(runtime.Version(), "devel") {
|
||||
next, err := filepath.Glob(filepath.Join(testenv.GOROOT(t), "api/next/*.txt"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -490,8 +489,7 @@ func (w *Walker) loadImports() {
|
||||
if w.context.Dir != "" {
|
||||
cmd.Dir = w.context.Dir
|
||||
}
|
||||
cmd.Stderr = os.Stderr
|
||||
out, err := cmd.Output()
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
log.Fatalf("loading imports: %v\n%s", err, out)
|
||||
}
|
||||
@@ -957,17 +955,17 @@ func (w *Walker) emitType(obj *types.TypeName) {
|
||||
if w.isDeprecated(obj) {
|
||||
w.emitf("type %s //deprecated", name)
|
||||
}
|
||||
typ := obj.Type()
|
||||
if obj.IsAlias() {
|
||||
w.emitf("type %s = %s", name, w.typeString(typ))
|
||||
return
|
||||
}
|
||||
if tparams := obj.Type().(*types.Named).TypeParams(); tparams != nil {
|
||||
var buf bytes.Buffer
|
||||
buf.WriteString(name)
|
||||
w.writeTypeParams(&buf, tparams, true)
|
||||
name = buf.String()
|
||||
}
|
||||
typ := obj.Type()
|
||||
if obj.IsAlias() {
|
||||
w.emitf("type %s = %s", name, w.typeString(typ))
|
||||
return
|
||||
}
|
||||
switch typ := typ.Underlying().(type) {
|
||||
case *types.Struct:
|
||||
w.emitStructType(name, typ)
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
package api
|
||||
|
||||
import (
|
||||
"flag"
|
||||
@@ -285,25 +285,6 @@ func TestIssue41358(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestIssue64958(t *testing.T) {
|
||||
defer func() {
|
||||
if x := recover(); x != nil {
|
||||
t.Errorf("expected no panic; recovered %v", x)
|
||||
}
|
||||
}()
|
||||
|
||||
testenv.MustHaveGoBuild(t)
|
||||
|
||||
for _, context := range contexts {
|
||||
w := NewWalker(context, "testdata/src/issue64958")
|
||||
pkg, err := w.importFrom("p", "", 0)
|
||||
if err != nil {
|
||||
t.Errorf("expected no error importing; got %T", err)
|
||||
}
|
||||
w.export(pkg)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheck(t *testing.T) {
|
||||
if !*flagCheck {
|
||||
t.Skip("-check not specified")
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
//go:build boringcrypto
|
||||
|
||||
package main
|
||||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
3
src/cmd/api/testdata/src/issue64958/p/p.go
vendored
3
src/cmd/api/testdata/src/issue64958/p/p.go
vendored
@@ -1,3 +0,0 @@
|
||||
package p
|
||||
|
||||
type BasicAlias = uint8
|
||||
@@ -33,8 +33,6 @@ Flags:
|
||||
Dump instructions as they are parsed.
|
||||
-dynlink
|
||||
Support references to Go symbols defined in other shared libraries.
|
||||
-e
|
||||
No limit on number of errors reported.
|
||||
-gensymabis
|
||||
Write symbol ABI information to output file. Don't assemble.
|
||||
-o file
|
||||
@@ -47,8 +45,6 @@ Flags:
|
||||
Enable spectre mitigations in list (all, ret).
|
||||
-trimpath prefix
|
||||
Remove prefix from recorded source file paths.
|
||||
-v
|
||||
Print debug output.
|
||||
|
||||
Input language:
|
||||
|
||||
|
||||
@@ -445,7 +445,7 @@ func (p *Parser) asmJump(op obj.As, cond string, a []obj.Addr) {
|
||||
// BC x,CR0EQ,...
|
||||
// BC x,CR1LT,...
|
||||
// BC x,CR1GT,...
|
||||
// The first and second cases demonstrate a symbol name which is
|
||||
// The first and second case demonstrate a symbol name which is
|
||||
// effectively discarded. In these cases, the offset determines
|
||||
// the CR bit.
|
||||
prog.Reg = a[1].Reg
|
||||
@@ -909,7 +909,7 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
|
||||
p.append(prog, cond, true)
|
||||
}
|
||||
|
||||
// symbolName returns the symbol name, or an error string if none is available.
|
||||
// symbolName returns the symbol name, or an error string if none if available.
|
||||
func symbolName(addr *obj.Addr) string {
|
||||
if addr.Sym != nil {
|
||||
return addr.Sym.Name
|
||||
|
||||
@@ -30,7 +30,7 @@ func testEndToEnd(t *testing.T, goarch, file string) {
|
||||
architecture, ctxt := setArch(goarch)
|
||||
architecture.Init(ctxt)
|
||||
lexer := lex.NewLexer(input)
|
||||
parser := NewParser(ctxt, architecture, lexer)
|
||||
parser := NewParser(ctxt, architecture, lexer, false)
|
||||
pList := new(obj.Plist)
|
||||
var ok bool
|
||||
testOut = new(strings.Builder) // The assembler writes test output to this buffer.
|
||||
@@ -68,11 +68,6 @@ Diff:
|
||||
continue
|
||||
}
|
||||
|
||||
// Ignore GLOBL.
|
||||
if strings.HasPrefix(line, "GLOBL ") {
|
||||
continue
|
||||
}
|
||||
|
||||
// The general form of a test input line is:
|
||||
// // comment
|
||||
// INST args [// printed form] [// hex encoding]
|
||||
@@ -141,17 +136,11 @@ Diff:
|
||||
// Turn relative (PC) into absolute (PC) automatically,
|
||||
// so that most branch instructions don't need comments
|
||||
// giving the absolute form.
|
||||
if len(f) > 0 && strings.Contains(printed, "(PC)") {
|
||||
index := len(f) - 1
|
||||
suf := "(PC)"
|
||||
for !strings.HasSuffix(f[index], suf) {
|
||||
index--
|
||||
suf = "(PC),"
|
||||
}
|
||||
str := f[index]
|
||||
n, err := strconv.Atoi(str[:len(str)-len(suf)])
|
||||
if len(f) > 0 && strings.HasSuffix(printed, "(PC)") {
|
||||
last := f[len(f)-1]
|
||||
n, err := strconv.Atoi(last[:len(last)-len("(PC)")])
|
||||
if err == nil {
|
||||
f[index] = fmt.Sprintf("%d%s", seq+n, suf)
|
||||
f[len(f)-1] = fmt.Sprintf("%d(PC)", seq+n)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,7 +186,7 @@ Diff:
|
||||
t.Errorf(format, args...)
|
||||
ok = false
|
||||
}
|
||||
obj.Flushplist(ctxt, pList, nil)
|
||||
obj.Flushplist(ctxt, pList, nil, "")
|
||||
|
||||
for p := top; p != nil; p = p.Link {
|
||||
if p.As == obj.ATEXT {
|
||||
@@ -283,9 +272,8 @@ var (
|
||||
func testErrors(t *testing.T, goarch, file string, flags ...string) {
|
||||
input := filepath.Join("testdata", file+".s")
|
||||
architecture, ctxt := setArch(goarch)
|
||||
architecture.Init(ctxt)
|
||||
lexer := lex.NewLexer(input)
|
||||
parser := NewParser(ctxt, architecture, lexer)
|
||||
parser := NewParser(ctxt, architecture, lexer, false)
|
||||
pList := new(obj.Plist)
|
||||
var ok bool
|
||||
ctxt.Bso = bufio.NewWriter(os.Stdout)
|
||||
@@ -311,7 +299,7 @@ func testErrors(t *testing.T, goarch, file string, flags ...string) {
|
||||
}
|
||||
}
|
||||
pList.Firstpc, ok = parser.Parse()
|
||||
obj.Flushplist(ctxt, pList, nil)
|
||||
obj.Flushplist(ctxt, pList, nil, "")
|
||||
if ok && !failed {
|
||||
t.Errorf("asm: %s had no errors", file)
|
||||
}
|
||||
@@ -378,10 +366,10 @@ func Test386EndToEnd(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestARMEndToEnd(t *testing.T) {
|
||||
defer func(old int) { buildcfg.GOARM.Version = old }(buildcfg.GOARM.Version)
|
||||
defer func(old int) { buildcfg.GOARM = old }(buildcfg.GOARM)
|
||||
for _, goarm := range []int{5, 6, 7} {
|
||||
t.Logf("GOARM=%d", goarm)
|
||||
buildcfg.GOARM.Version = goarm
|
||||
buildcfg.GOARM = goarm
|
||||
testEndToEnd(t, "arm", "arm")
|
||||
if goarm == 6 {
|
||||
testEndToEnd(t, "arm", "armv6")
|
||||
|
||||
@@ -57,7 +57,7 @@ var exprTests = []exprTest{
|
||||
}
|
||||
|
||||
func TestExpr(t *testing.T) {
|
||||
p := NewParser(nil, nil, nil) // Expression evaluation uses none of these fields of the parser.
|
||||
p := NewParser(nil, nil, nil, false) // Expression evaluation uses none of these fields of the parser.
|
||||
for i, test := range exprTests {
|
||||
p.start(lex.Tokenize(test.input))
|
||||
result := int64(p.expr())
|
||||
@@ -113,7 +113,7 @@ func TestBadExpr(t *testing.T) {
|
||||
}
|
||||
|
||||
func runBadTest(i int, test badExprTest, t *testing.T) (err error) {
|
||||
p := NewParser(nil, nil, nil) // Expression evaluation uses none of these fields of the parser.
|
||||
p := NewParser(nil, nil, nil, false) // Expression evaluation uses none of these fields of the parser.
|
||||
p.start(lex.Tokenize(test.input))
|
||||
return tryParse(t, func() {
|
||||
p.expr()
|
||||
|
||||
@@ -39,7 +39,7 @@ func testBadInstParser(t *testing.T, goarch string, tests []badInstTest) {
|
||||
for i, test := range tests {
|
||||
arch, ctxt := setArch(goarch)
|
||||
tokenizer := lex.NewTokenizer("", strings.NewReader(test.input+"\n"), nil)
|
||||
parser := NewParser(ctxt, arch, tokenizer)
|
||||
parser := NewParser(ctxt, arch, tokenizer, false)
|
||||
|
||||
err := tryParse(t, func() {
|
||||
parser.Parse()
|
||||
|
||||
@@ -23,14 +23,12 @@ func setArch(goarch string) (*arch.Arch, *obj.Link) {
|
||||
if architecture == nil {
|
||||
panic("asm: unrecognized architecture " + goarch)
|
||||
}
|
||||
ctxt := obj.Linknew(architecture.LinkArch)
|
||||
ctxt.Pkgpath = "pkg"
|
||||
return architecture, ctxt
|
||||
return architecture, obj.Linknew(architecture.LinkArch)
|
||||
}
|
||||
|
||||
func newParser(goarch string) *Parser {
|
||||
architecture, ctxt := setArch(goarch)
|
||||
return NewParser(ctxt, architecture, nil)
|
||||
return NewParser(ctxt, architecture, nil, false)
|
||||
}
|
||||
|
||||
// tryParse executes parse func in panicOnError=true context.
|
||||
@@ -78,7 +76,7 @@ func testOperandParser(t *testing.T, parser *Parser, tests []operandTest) {
|
||||
addr := obj.Addr{}
|
||||
parser.operand(&addr)
|
||||
var result string
|
||||
if parser.allowABI {
|
||||
if parser.compilingRuntime {
|
||||
result = obj.DconvWithABIDetail(&emptyProg, &addr)
|
||||
} else {
|
||||
result = obj.Dconv(&emptyProg, &addr)
|
||||
@@ -93,7 +91,7 @@ func TestAMD64OperandParser(t *testing.T) {
|
||||
parser := newParser("amd64")
|
||||
testOperandParser(t, parser, amd64OperandTests)
|
||||
testBadOperandParser(t, parser, amd64BadOperandTests)
|
||||
parser.allowABI = true
|
||||
parser.compilingRuntime = true
|
||||
testOperandParser(t, parser, amd64RuntimeOperandTests)
|
||||
testBadOperandParser(t, parser, amd64BadOperandRuntimeTests)
|
||||
}
|
||||
@@ -306,8 +304,8 @@ var amd64OperandTests = []operandTest{
|
||||
{"x·y+8(SB)", "x.y+8(SB)"},
|
||||
{"x·y+8(SP)", "x.y+8(SP)"},
|
||||
{"y+56(FP)", "y+56(FP)"},
|
||||
{"·AddUint32(SB)", "pkg.AddUint32(SB)"},
|
||||
{"·callReflect(SB)", "pkg.callReflect(SB)"},
|
||||
{"·AddUint32(SB)", "\"\".AddUint32(SB)"},
|
||||
{"·callReflect(SB)", "\"\".callReflect(SB)"},
|
||||
{"[X0-X0]", "[X0-X0]"},
|
||||
{"[ Z9 - Z12 ]", "[Z9-Z12]"},
|
||||
{"[X0-AX]", "[X0-AX]"},
|
||||
@@ -393,8 +391,8 @@ var x86OperandTests = []operandTest{
|
||||
{"sec+4(FP)", "sec+4(FP)"},
|
||||
{"shifts<>(SB)(CX*8)", "shifts<>(SB)(CX*8)"},
|
||||
{"x+4(FP)", "x+4(FP)"},
|
||||
{"·AddUint32(SB)", "pkg.AddUint32(SB)"},
|
||||
{"·reflectcall(SB)", "pkg.reflectcall(SB)"},
|
||||
{"·AddUint32(SB)", "\"\".AddUint32(SB)"},
|
||||
{"·reflectcall(SB)", "\"\".reflectcall(SB)"},
|
||||
{"[):[o-FP", ""}, // Issue 12469 - asm hung parsing the o-FP range on non ARM platforms.
|
||||
}
|
||||
|
||||
@@ -442,7 +440,7 @@ var armOperandTests = []operandTest{
|
||||
{"gosave<>(SB)", "gosave<>(SB)"},
|
||||
{"retlo+12(FP)", "retlo+12(FP)"},
|
||||
{"runtime·gogo(SB)", "runtime.gogo(SB)"},
|
||||
{"·AddUint32(SB)", "pkg.AddUint32(SB)"},
|
||||
{"·AddUint32(SB)", "\"\".AddUint32(SB)"},
|
||||
{"(R1, R3)", "(R1, R3)"},
|
||||
{"[R0,R1,g,R15", ""}, // Issue 11764 - asm hung parsing ']' missing register lists.
|
||||
{"[):[o-FP", ""}, // Issue 12469 - there was no infinite loop for ARM; these are just sanity checks.
|
||||
@@ -631,8 +629,8 @@ var ppc64OperandTests = []operandTest{
|
||||
{"g", "g"},
|
||||
{"ret+8(FP)", "ret+8(FP)"},
|
||||
{"runtime·abort(SB)", "runtime.abort(SB)"},
|
||||
{"·AddUint32(SB)", "pkg.AddUint32(SB)"},
|
||||
{"·trunc(SB)", "pkg.trunc(SB)"},
|
||||
{"·AddUint32(SB)", "\"\".AddUint32(SB)"},
|
||||
{"·trunc(SB)", "\"\".trunc(SB)"},
|
||||
{"[):[o-FP", ""}, // Issue 12469 - asm hung parsing the o-FP range on non ARM platforms.
|
||||
}
|
||||
|
||||
@@ -664,7 +662,7 @@ var arm64OperandTests = []operandTest{
|
||||
{"$(8-1)", "$7"},
|
||||
{"a+0(FP)", "a(FP)"},
|
||||
{"a1+8(FP)", "a1+8(FP)"},
|
||||
{"·AddInt32(SB)", `pkg.AddInt32(SB)`},
|
||||
{"·AddInt32(SB)", `"".AddInt32(SB)`},
|
||||
{"runtime·divWVW(SB)", "runtime.divWVW(SB)"},
|
||||
{"$argframe+0(FP)", "$argframe(FP)"},
|
||||
{"$asmcgocall<>(SB)", "$asmcgocall<>(SB)"},
|
||||
@@ -765,8 +763,8 @@ var mips64OperandTests = []operandTest{
|
||||
{"RSB", "R28"},
|
||||
{"ret+8(FP)", "ret+8(FP)"},
|
||||
{"runtime·abort(SB)", "runtime.abort(SB)"},
|
||||
{"·AddUint32(SB)", "pkg.AddUint32(SB)"},
|
||||
{"·trunc(SB)", "pkg.trunc(SB)"},
|
||||
{"·AddUint32(SB)", "\"\".AddUint32(SB)"},
|
||||
{"·trunc(SB)", "\"\".trunc(SB)"},
|
||||
{"[):[o-FP", ""}, // Issue 12469 - asm hung parsing the o-FP range on non ARM platforms.
|
||||
}
|
||||
|
||||
@@ -848,8 +846,8 @@ var mipsOperandTests = []operandTest{
|
||||
{"g", "g"},
|
||||
{"ret+8(FP)", "ret+8(FP)"},
|
||||
{"runtime·abort(SB)", "runtime.abort(SB)"},
|
||||
{"·AddUint32(SB)", "pkg.AddUint32(SB)"},
|
||||
{"·trunc(SB)", "pkg.trunc(SB)"},
|
||||
{"·AddUint32(SB)", "\"\".AddUint32(SB)"},
|
||||
{"·trunc(SB)", "\"\".trunc(SB)"},
|
||||
{"[):[o-FP", ""}, // Issue 12469 - asm hung parsing the o-FP range on non ARM platforms.
|
||||
}
|
||||
|
||||
@@ -930,8 +928,8 @@ var loong64OperandTests = []operandTest{
|
||||
{"g", "g"},
|
||||
{"ret+8(FP)", "ret+8(FP)"},
|
||||
{"runtime·abort(SB)", "runtime.abort(SB)"},
|
||||
{"·AddUint32(SB)", "pkg.AddUint32(SB)"},
|
||||
{"·trunc(SB)", "pkg.trunc(SB)"},
|
||||
{"·AddUint32(SB)", "\"\".AddUint32(SB)"},
|
||||
{"·trunc(SB)", "\"\".trunc(SB)"},
|
||||
{"[):[o-FP", ""}, // Issue 12469 - asm hung parsing the o-FP range on non ARM platforms.
|
||||
}
|
||||
|
||||
@@ -1028,7 +1026,7 @@ var s390xOperandTests = []operandTest{
|
||||
{"g", "g"},
|
||||
{"ret+8(FP)", "ret+8(FP)"},
|
||||
{"runtime·abort(SB)", "runtime.abort(SB)"},
|
||||
{"·AddUint32(SB)", "pkg.AddUint32(SB)"},
|
||||
{"·trunc(SB)", "pkg.trunc(SB)"},
|
||||
{"·AddUint32(SB)", "\"\".AddUint32(SB)"},
|
||||
{"·trunc(SB)", "\"\".trunc(SB)"},
|
||||
{"[):[o-FP", ""}, // Issue 12469 - asm hung parsing the o-FP range on non ARM platforms.
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"text/scanner"
|
||||
"unicode/utf8"
|
||||
|
||||
@@ -22,33 +21,31 @@ import (
|
||||
"cmd/internal/obj"
|
||||
"cmd/internal/obj/arm64"
|
||||
"cmd/internal/obj/x86"
|
||||
"cmd/internal/objabi"
|
||||
"cmd/internal/src"
|
||||
"cmd/internal/sys"
|
||||
)
|
||||
|
||||
type Parser struct {
|
||||
lex lex.TokenReader
|
||||
lineNum int // Line number in source file.
|
||||
errorLine int // Line number of last error.
|
||||
errorCount int // Number of errors.
|
||||
sawCode bool // saw code in this file (as opposed to comments and blank lines)
|
||||
pc int64 // virtual PC; count of Progs; doesn't advance for GLOBL or DATA.
|
||||
input []lex.Token
|
||||
inputPos int
|
||||
pendingLabels []string // Labels to attach to next instruction.
|
||||
labels map[string]*obj.Prog
|
||||
toPatch []Patch
|
||||
addr []obj.Addr
|
||||
arch *arch.Arch
|
||||
ctxt *obj.Link
|
||||
firstProg *obj.Prog
|
||||
lastProg *obj.Prog
|
||||
dataAddr map[string]int64 // Most recent address for DATA for this symbol.
|
||||
isJump bool // Instruction being assembled is a jump.
|
||||
allowABI bool // Whether ABI selectors are allowed.
|
||||
pkgPrefix string // Prefix to add to local symbols.
|
||||
errorWriter io.Writer
|
||||
lex lex.TokenReader
|
||||
lineNum int // Line number in source file.
|
||||
errorLine int // Line number of last error.
|
||||
errorCount int // Number of errors.
|
||||
sawCode bool // saw code in this file (as opposed to comments and blank lines)
|
||||
pc int64 // virtual PC; count of Progs; doesn't advance for GLOBL or DATA.
|
||||
input []lex.Token
|
||||
inputPos int
|
||||
pendingLabels []string // Labels to attach to next instruction.
|
||||
labels map[string]*obj.Prog
|
||||
toPatch []Patch
|
||||
addr []obj.Addr
|
||||
arch *arch.Arch
|
||||
ctxt *obj.Link
|
||||
firstProg *obj.Prog
|
||||
lastProg *obj.Prog
|
||||
dataAddr map[string]int64 // Most recent address for DATA for this symbol.
|
||||
isJump bool // Instruction being assembled is a jump.
|
||||
compilingRuntime bool
|
||||
errorWriter io.Writer
|
||||
}
|
||||
|
||||
type Patch struct {
|
||||
@@ -56,20 +53,15 @@ type Patch struct {
|
||||
label string
|
||||
}
|
||||
|
||||
func NewParser(ctxt *obj.Link, ar *arch.Arch, lexer lex.TokenReader) *Parser {
|
||||
pkgPrefix := obj.UnlinkablePkg
|
||||
if ctxt != nil {
|
||||
pkgPrefix = objabi.PathToPrefix(ctxt.Pkgpath)
|
||||
}
|
||||
func NewParser(ctxt *obj.Link, ar *arch.Arch, lexer lex.TokenReader, compilingRuntime bool) *Parser {
|
||||
return &Parser{
|
||||
ctxt: ctxt,
|
||||
arch: ar,
|
||||
lex: lexer,
|
||||
labels: make(map[string]*obj.Prog),
|
||||
dataAddr: make(map[string]int64),
|
||||
errorWriter: os.Stderr,
|
||||
allowABI: ctxt != nil && objabi.LookupPkgSpecial(ctxt.Pkgpath).AllowAsmABI,
|
||||
pkgPrefix: pkgPrefix,
|
||||
ctxt: ctxt,
|
||||
arch: ar,
|
||||
lex: lexer,
|
||||
labels: make(map[string]*obj.Prog),
|
||||
dataAddr: make(map[string]int64),
|
||||
errorWriter: os.Stderr,
|
||||
compilingRuntime: compilingRuntime,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -409,7 +401,7 @@ func (p *Parser) operand(a *obj.Addr) {
|
||||
fallthrough
|
||||
default:
|
||||
// We have a symbol. Parse $sym±offset(symkind)
|
||||
p.symbolReference(a, p.qualifySymbol(name), prefix)
|
||||
p.symbolReference(a, name, prefix)
|
||||
}
|
||||
// fmt.Printf("SYM %s\n", obj.Dconv(&emptyProg, 0, a))
|
||||
if p.peek() == scanner.EOF {
|
||||
@@ -777,16 +769,6 @@ func (p *Parser) registerExtension(a *obj.Addr, name string, prefix rune) {
|
||||
}
|
||||
}
|
||||
|
||||
// qualifySymbol returns name as a package-qualified symbol name. If
|
||||
// name starts with a period, qualifySymbol prepends the package
|
||||
// prefix. Otherwise it returns name unchanged.
|
||||
func (p *Parser) qualifySymbol(name string) string {
|
||||
if strings.HasPrefix(name, ".") {
|
||||
name = p.pkgPrefix + name
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
// symbolReference parses a symbol that is known not to be a register.
|
||||
func (p *Parser) symbolReference(a *obj.Addr, name string, prefix rune) {
|
||||
// Identifier is a name.
|
||||
@@ -882,7 +864,7 @@ func (p *Parser) symRefAttrs(name string, issueError bool) (bool, obj.ABI) {
|
||||
isStatic = true
|
||||
} else if tok == scanner.Ident {
|
||||
abistr := p.get(scanner.Ident).String()
|
||||
if !p.allowABI {
|
||||
if !p.compilingRuntime {
|
||||
if issueError {
|
||||
p.errorf("ABI selector only permitted when compiling runtime, reference was to %q", name)
|
||||
}
|
||||
@@ -919,7 +901,6 @@ func (p *Parser) funcAddress() (string, obj.ABI, bool) {
|
||||
if tok.ScanToken != scanner.Ident || p.atStartOfRegister(name) {
|
||||
return "", obj.ABI0, false
|
||||
}
|
||||
name = p.qualifySymbol(name)
|
||||
// Parse optional <> (indicates a static symbol) or
|
||||
// <ABIxxx> (selecting text symbol with specific ABI).
|
||||
noErrMsg := false
|
||||
@@ -947,7 +928,7 @@ func (p *Parser) funcAddress() (string, obj.ABI, bool) {
|
||||
}
|
||||
|
||||
// registerIndirect parses the general form of a register indirection.
|
||||
// It can be (R1), (R2*scale), (R1)(R2*scale), (R1)(R2.SXTX<<3) or (R1)(R2<<3)
|
||||
// It is can be (R1), (R2*scale), (R1)(R2*scale), (R1)(R2.SXTX<<3) or (R1)(R2<<3)
|
||||
// where R1 may be a simple register or register pair R:R or (R, R) or (R+R).
|
||||
// Or it might be a pseudo-indirection like (FP).
|
||||
// We are sitting on the opening parenthesis.
|
||||
@@ -1205,7 +1186,7 @@ func (p *Parser) registerListX86(a *obj.Addr) {
|
||||
a.Offset = x86.EncodeRegisterRange(lo, hi)
|
||||
}
|
||||
|
||||
// registerNumber is ARM-specific. It returns the number of the specified register.
|
||||
// register number is ARM-specific. It returns the number of the specified register.
|
||||
func (p *Parser) registerNumber(name string) uint16 {
|
||||
if p.arch.Family == sys.ARM && name == "g" {
|
||||
return 10
|
||||
|
||||
@@ -64,16 +64,16 @@ func TestErroneous(t *testing.T) {
|
||||
}
|
||||
|
||||
testcats := []struct {
|
||||
allowABI bool
|
||||
tests []errtest
|
||||
compilingRuntime bool
|
||||
tests []errtest
|
||||
}{
|
||||
{
|
||||
allowABI: false,
|
||||
tests: nonRuntimeTests,
|
||||
compilingRuntime: false,
|
||||
tests: nonRuntimeTests,
|
||||
},
|
||||
{
|
||||
allowABI: true,
|
||||
tests: runtimeTests,
|
||||
compilingRuntime: true,
|
||||
tests: runtimeTests,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ func TestErroneous(t *testing.T) {
|
||||
|
||||
for _, cat := range testcats {
|
||||
for _, test := range cat.tests {
|
||||
parser.allowABI = cat.allowABI
|
||||
parser.compilingRuntime = cat.compilingRuntime
|
||||
parser.errorCount = 0
|
||||
parser.lineNum++
|
||||
if !parser.pseudo(test.pseudo, tokenize(test.operands)) {
|
||||
|
||||
22
src/cmd/asm/internal/asm/testdata/arm.s
vendored
22
src/cmd/asm/internal/asm/testdata/arm.s
vendored
@@ -870,13 +870,10 @@ jmp_label_3:
|
||||
BIC.S R0@>R1, R2 // 7021d2e1
|
||||
|
||||
// SRL
|
||||
SRL $0, R5, R6 // 0560a0e1
|
||||
SRL $1, R5, R6 // a560a0e1
|
||||
SRL $14, R5, R6 // 2567a0e1
|
||||
SRL $15, R5, R6 // a567a0e1
|
||||
SRL $30, R5, R6 // 256fa0e1
|
||||
SRL $31, R5, R6 // a56fa0e1
|
||||
SRL $32, R5, R6 // 2560a0e1
|
||||
SRL.S $14, R5, R6 // 2567b0e1
|
||||
SRL.S $15, R5, R6 // a567b0e1
|
||||
SRL.S $30, R5, R6 // 256fb0e1
|
||||
@@ -895,13 +892,10 @@ jmp_label_3:
|
||||
SRL.S R5, R7 // 3775b0e1
|
||||
|
||||
// SRA
|
||||
SRA $0, R5, R6 // 0560a0e1
|
||||
SRA $1, R5, R6 // c560a0e1
|
||||
SRA $14, R5, R6 // 4567a0e1
|
||||
SRA $15, R5, R6 // c567a0e1
|
||||
SRA $30, R5, R6 // 456fa0e1
|
||||
SRA $31, R5, R6 // c56fa0e1
|
||||
SRA $32, R5, R6 // 4560a0e1
|
||||
SRA.S $14, R5, R6 // 4567b0e1
|
||||
SRA.S $15, R5, R6 // c567b0e1
|
||||
SRA.S $30, R5, R6 // 456fb0e1
|
||||
@@ -920,8 +914,6 @@ jmp_label_3:
|
||||
SRA.S R5, R7 // 5775b0e1
|
||||
|
||||
// SLL
|
||||
SLL $0, R5, R6 // 0560a0e1
|
||||
SLL $1, R5, R6 // 8560a0e1
|
||||
SLL $14, R5, R6 // 0567a0e1
|
||||
SLL $15, R5, R6 // 8567a0e1
|
||||
SLL $30, R5, R6 // 056fa0e1
|
||||
@@ -943,20 +935,6 @@ jmp_label_3:
|
||||
SLL R5, R7 // 1775a0e1
|
||||
SLL.S R5, R7 // 1775b0e1
|
||||
|
||||
// Ops with zero shifts should encode as left shifts
|
||||
ADD R0<<0, R1, R2 // 002081e0
|
||||
ADD R0>>0, R1, R2 // 002081e0
|
||||
ADD R0->0, R1, R2 // 002081e0
|
||||
ADD R0@>0, R1, R2 // 002081e0
|
||||
MOVW R0<<0(R1), R2 // 002091e7
|
||||
MOVW R0>>0(R1), R2 // 002091e7
|
||||
MOVW R0->0(R1), R2 // 002091e7
|
||||
MOVW R0@>0(R1), R2 // 002091e7
|
||||
MOVW R0, R1<<0(R2) // 010082e7
|
||||
MOVW R0, R1>>0(R2) // 010082e7
|
||||
MOVW R0, R1->0(R2) // 010082e7
|
||||
MOVW R0, R1@>0(R2) // 010082e7
|
||||
|
||||
// MULA / MULS
|
||||
MULAWT R1, R2, R3, R4 // c23124e1
|
||||
MULAWB R1, R2, R3, R4 // 823124e1
|
||||
|
||||
119
src/cmd/asm/internal/asm/testdata/arm64.s
vendored
119
src/cmd/asm/internal/asm/testdata/arm64.s
vendored
@@ -557,92 +557,37 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
|
||||
FMOVQ 65520(R10), F10 // 4afdff3d
|
||||
FMOVQ 64(RSP), F11 // eb13c03d
|
||||
|
||||
// medium offsets that either fit a single instruction or can use add+ldr/str
|
||||
MOVD -4095(R17), R3 // 3bfe3fd1630340f9
|
||||
MOVD -391(R17), R3 // 3b1e06d1630340f9
|
||||
MOVD -257(R17), R3 // 3b0604d1630340f9
|
||||
MOVD -256(R17), R3 // 230250f8
|
||||
MOVD 255(R17), R3 // 23f24ff8
|
||||
MOVD 256(R17), R3 // 238240f9
|
||||
MOVD 257(R17), R3 // 3b060491630340f9
|
||||
MOVD 391(R17), R3 // 3b1e0691630340f9
|
||||
MOVD 4095(R17), R3 // 3bfe3f91630340f9
|
||||
// large aligned offset, use two instructions(add+ldr/store).
|
||||
MOVB R1, 0x1001(R2) // MOVB R1, 4097(R2) // 5b04409161070039
|
||||
MOVH R1, 0x2002(R2) // MOVH R1, 8194(R2) // 5b08409161070079
|
||||
MOVW R1, 0x4004(R2) // MOVW R1, 16388(R2) // 5b104091610700b9
|
||||
MOVD R1, 0x8008(R2) // MOVD R1, 32776(R2) // 5b204091610700f9
|
||||
FMOVS F1, 0x4004(R2) // FMOVS F1, 16388(R2) // 5b104091610700bd
|
||||
FMOVD F1, 0x8008(R2) // FMOVD F1, 32776(R2) // 5b204091610700fd
|
||||
|
||||
MOVD R0, -4095(R17) // 3bfe3fd1600300f9
|
||||
MOVD R0, -391(R17) // 3b1e06d1600300f9
|
||||
MOVD R0, -257(R17) // 3b0604d1600300f9
|
||||
MOVD R0, -256(R17) // 200210f8
|
||||
MOVD R0, 255(R17) // 20f20ff8
|
||||
MOVD R0, 256(R17) // 208200f9
|
||||
MOVD R0, 257(R17) // 3b060491600300f9
|
||||
MOVD R0, 391(R17) // 3b1e0691600300f9
|
||||
MOVD R0, 4095(R17) // 3bfe3f91600300f9
|
||||
MOVD R0, 4096(R17) // 200208f9
|
||||
MOVD R3, -4095(R17) // 3bfe3fd1630300f9
|
||||
MOVD R3, -391(R17) // 3b1e06d1630300f9
|
||||
MOVD R3, -257(R17) // 3b0604d1630300f9
|
||||
MOVD R3, -256(R17) // 230210f8
|
||||
MOVD R3, 255(R17) // 23f20ff8
|
||||
MOVD R3, 256(R17) // 238200f9
|
||||
MOVD R3, 257(R17) // 3b060491630300f9
|
||||
MOVD R3, 391(R17) // 3b1e0691630300f9
|
||||
MOVD R3, 4095(R17) // 3bfe3f91630300f9
|
||||
|
||||
// large aligned offset, use two instructions(add+ldr/str).
|
||||
MOVB R1, 0x1001(R2) // MOVB R1, 4097(R2) // 5b04409161070039
|
||||
MOVB R1, 0xffffff(R2) // MOVB R1, 16777215(R2) // 5bfc7f9161ff3f39
|
||||
MOVH R1, 0x2002(R2) // MOVH R1, 8194(R2) // 5b08409161070079
|
||||
MOVH R1, 0x1000ffe(R2) // MOVH R1, 16781310(R2) // 5bfc7f9161ff3f79
|
||||
MOVW R1, 0x4004(R2) // MOVW R1, 16388(R2) // 5b104091610700b9
|
||||
MOVW R1, 0x1002ffc(R2) // MOVW R1, 16789500(R2) // 5bfc7f9161ff3fb9
|
||||
MOVD R1, 0x8008(R2) // MOVD R1, 32776(R2) // 5b204091610700f9
|
||||
MOVD R1, 0x1006ff8(R2) // MOVD R1, 16805880(R2) // 5bfc7f9161ff3ff9
|
||||
FMOVS F1, 0x4004(R2) // FMOVS F1, 16388(R2) // 5b104091610700bd
|
||||
FMOVS F1, 0x1002ffc(R2) // FMOVS F1, 16789500(R2) // 5bfc7f9161ff3fbd
|
||||
FMOVD F1, 0x8008(R2) // FMOVD F1, 32776(R2) // 5b204091610700fd
|
||||
FMOVD F1, 0x1006ff8(R2) // FMOVD F1, 16805880(R2) // 5bfc7f9161ff3ffd
|
||||
|
||||
MOVB 0x1001(R1), R2 // MOVB 4097(R1), R2 // 3b04409162078039
|
||||
MOVB 0xffffff(R1), R2 // MOVB 16777215(R1), R2 // 3bfc7f9162ffbf39
|
||||
MOVH 0x2002(R1), R2 // MOVH 8194(R1), R2 // 3b08409162078079
|
||||
MOVH 0x1000ffe(R1), R2 // MOVH 16781310(R1), R2 // 3bfc7f9162ffbf79
|
||||
MOVW 0x4004(R1), R2 // MOVW 16388(R1), R2 // 3b104091620780b9
|
||||
MOVW 0x1002ffc(R1), R2 // MOVW 16789500(R1), R2 // 3bfc7f9162ffbfb9
|
||||
MOVD 0x8008(R1), R2 // MOVD 32776(R1), R2 // 3b204091620740f9
|
||||
MOVD 0x1006ff8(R1), R2 // MOVD 16805880(R1), R2 // 3bfc7f9162ff7ff9
|
||||
FMOVS 0x4004(R1), F2 // FMOVS 16388(R1), F2 // 3b104091620740bd
|
||||
FMOVS 0x1002ffc(R1), F2 // FMOVS 16789500(R1), F2 // 3bfc7f9162ff7fbd
|
||||
FMOVD 0x8008(R1), F2 // FMOVD 32776(R1), F2 // 3b204091620740fd
|
||||
FMOVD 0x1006ff8(R1), F2 // FMOVD 16805880(R1), F2 // 3bfc7f9162ff7ffd
|
||||
MOVB 0x1001(R1), R2 // MOVB 4097(R1), R2 // 3b04409162078039
|
||||
MOVH 0x2002(R1), R2 // MOVH 8194(R1), R2 // 3b08409162078079
|
||||
MOVW 0x4004(R1), R2 // MOVW 16388(R1), R2 // 3b104091620780b9
|
||||
MOVD 0x8008(R1), R2 // MOVD 32776(R1), R2 // 3b204091620740f9
|
||||
FMOVS 0x4004(R1), F2 // FMOVS 16388(R1), F2 // 3b104091620740bd
|
||||
FMOVD 0x8008(R1), F2 // FMOVD 32776(R1), F2 // 3b204091620740fd
|
||||
|
||||
// very large or unaligned offset uses constant pool.
|
||||
// the encoding cannot be checked as the address of the constant pool is unknown.
|
||||
// here we only test that they can be assembled.
|
||||
MOVB R1, 0x1000000(R2) // MOVB R1, 16777216(R2)
|
||||
MOVB R1, 0x44332211(R2) // MOVB R1, 1144201745(R2)
|
||||
MOVH R1, 0x1001000(R2) // MOVH R1, 16781312(R2)
|
||||
MOVH R1, 0x44332211(R2) // MOVH R1, 1144201745(R2)
|
||||
MOVW R1, 0x1003000(R2) // MOVW R1, 16789504(R2)
|
||||
MOVW R1, 0x44332211(R2) // MOVW R1, 1144201745(R2)
|
||||
MOVD R1, 0x1007000(R2) // MOVD R1, 16805888(R2)
|
||||
MOVD R1, 0x44332211(R2) // MOVD R1, 1144201745(R2)
|
||||
FMOVS F1, 0x1003000(R2) // FMOVS F1, 16789504(R2)
|
||||
FMOVS F1, 0x44332211(R2) // FMOVS F1, 1144201745(R2)
|
||||
FMOVD F1, 0x1007000(R2) // FMOVD F1, 16805888(R2)
|
||||
FMOVD F1, 0x44332211(R2) // FMOVD F1, 1144201745(R2)
|
||||
MOVB R1, 0x44332211(R2) // MOVB R1, 1144201745(R2)
|
||||
MOVH R1, 0x44332211(R2) // MOVH R1, 1144201745(R2)
|
||||
MOVW R1, 0x44332211(R2) // MOVW R1, 1144201745(R2)
|
||||
MOVD R1, 0x44332211(R2) // MOVD R1, 1144201745(R2)
|
||||
FMOVS F1, 0x44332211(R2) // FMOVS F1, 1144201745(R2)
|
||||
FMOVD F1, 0x44332211(R2) // FMOVD F1, 1144201745(R2)
|
||||
|
||||
MOVB 0x1000000(R1), R2 // MOVB 16777216(R1), R2
|
||||
MOVB 0x44332211(R1), R2 // MOVB 1144201745(R1), R2
|
||||
MOVH 0x1000000(R1), R2 // MOVH 16777216(R1), R2
|
||||
MOVH 0x44332211(R1), R2 // MOVH 1144201745(R1), R2
|
||||
MOVW 0x1000000(R1), R2 // MOVW 16777216(R1), R2
|
||||
MOVW 0x44332211(R1), R2 // MOVW 1144201745(R1), R2
|
||||
MOVD 0x1000000(R1), R2 // MOVD 16777216(R1), R2
|
||||
MOVD 0x44332211(R1), R2 // MOVD 1144201745(R1), R2
|
||||
FMOVS 0x1000000(R1), F2 // FMOVS 16777216(R1), F2
|
||||
FMOVS 0x44332211(R1), F2 // FMOVS 1144201745(R1), F2
|
||||
FMOVD 0x1000000(R1), F2 // FMOVD 16777216(R1), F2
|
||||
FMOVD 0x44332211(R1), F2 // FMOVD 1144201745(R1), F2
|
||||
MOVB 0x44332211(R1), R2 // MOVB 1144201745(R1), R2
|
||||
MOVH 0x44332211(R1), R2 // MOVH 1144201745(R1), R2
|
||||
MOVW 0x44332211(R1), R2 // MOVW 1144201745(R1), R2
|
||||
MOVD 0x44332211(R1), R2 // MOVD 1144201745(R1), R2
|
||||
FMOVS 0x44332211(R1), F2 // FMOVS 1144201745(R1), F2
|
||||
FMOVD 0x44332211(R1), F2 // FMOVD 1144201745(R1), F2
|
||||
|
||||
// shifted or extended register offset.
|
||||
MOVD (R2)(R6.SXTW), R4 // 44c866f8
|
||||
@@ -650,7 +595,6 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
|
||||
MOVD (R3)(R6*1), R5 // 656866f8
|
||||
MOVD (R2)(R6), R4 // 446866f8
|
||||
MOVWU (R19)(R20<<2), R20 // 747a74b8
|
||||
MOVD (R2)(R3<<0), R1 // 416863f8
|
||||
MOVD (R2)(R6<<3), R4 // 447866f8
|
||||
MOVD (R3)(R7.SXTX<<3), R8 // 68f867f8
|
||||
MOVWU (R5)(R4.UXTW), R10 // aa4864b8
|
||||
@@ -660,7 +604,7 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
|
||||
MOVHU (R1)(R2<<1), R5 // 25786278
|
||||
MOVB (R9)(R3.UXTW), R6 // 2649a338
|
||||
MOVB (R10)(R6), R15 // 4f69a638
|
||||
MOVB (R29)(R30<<0), R14 // ae6bbe38
|
||||
MOVB (R29)(R30<<0), R14 // ae7bbe38
|
||||
MOVB (R29)(R30), R14 // ae6bbe38
|
||||
MOVH (R5)(R7.SXTX<<1), R19 // b3f8a778
|
||||
MOVH (R8)(R4<<1), R10 // 0a79a478
|
||||
@@ -981,14 +925,6 @@ again:
|
||||
ADR next, R11 // ADR R11 // 2b000010
|
||||
next:
|
||||
NOP
|
||||
ADR -2(PC), R10 // 0a000010
|
||||
ADR 2(PC), R16 // 10000010
|
||||
ADR -26(PC), R1 // 01000010
|
||||
ADR 12(PC), R2 // 02000010
|
||||
ADRP -2(PC), R10 // 0a000090
|
||||
ADRP 2(PC), R16 // 10000090
|
||||
ADRP -26(PC), R1 // 01000090
|
||||
ADRP 12(PC), R2 // 02000090
|
||||
|
||||
// LDP/STP
|
||||
LDP (R0), (R0, R1) // 000440a9
|
||||
@@ -1011,7 +947,6 @@ next:
|
||||
LDP -8(R0), (R1, R2) // 01887fa9
|
||||
LDP x(SB), (R1, R2)
|
||||
LDP x+8(SB), (R1, R2)
|
||||
LDP 8(R1), (ZR, R2) // 3f8840a9
|
||||
LDPW -5(R0), (R1, R2) // 1b1400d1610b4029
|
||||
LDPW (R0), (R1, R2) // 01084029
|
||||
LDPW 4(R0), (R1, R2) // 01884029
|
||||
@@ -1029,7 +964,6 @@ next:
|
||||
LDPW 1024(RSP), (R1, R2) // fb031091610b4029
|
||||
LDPW x(SB), (R1, R2)
|
||||
LDPW x+8(SB), (R1, R2)
|
||||
LDPW 8(R1), (ZR, R2) // 3f084129
|
||||
LDPSW (R0), (R1, R2) // 01084069
|
||||
LDPSW 4(R0), (R1, R2) // 01884069
|
||||
LDPSW -4(R0), (R1, R2) // 01887f69
|
||||
@@ -1046,7 +980,6 @@ next:
|
||||
LDPSW 1024(RSP), (R1, R2) // fb031091610b4069
|
||||
LDPSW x(SB), (R1, R2)
|
||||
LDPSW x+8(SB), (R1, R2)
|
||||
LDPSW 8(R1), (ZR, R2) // 3f084169
|
||||
STP (R3, R4), (R5) // a31000a9
|
||||
STP (R3, R4), 8(R5) // a39000a9
|
||||
STP.W (R3, R4), 8(R5) // a39080a9
|
||||
|
||||
2
src/cmd/asm/internal/asm/testdata/arm64enc.s
vendored
2
src/cmd/asm/internal/asm/testdata/arm64enc.s
vendored
@@ -186,7 +186,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
|
||||
MOVBU.P 42(R2), R12 // 4ca44238
|
||||
MOVBU.W -27(R2), R14 // 4e5c5e38
|
||||
MOVBU 2916(R24), R3 // 03936d39
|
||||
MOVBU (R19)(R14<<0), R23 // 776a6e38
|
||||
MOVBU (R19)(R14<<0), R23 // 777a6e38
|
||||
MOVBU (R2)(R8.SXTX), R19 // 53e86838
|
||||
MOVBU (R27)(R23), R14 // 6e6b7738
|
||||
MOVHU.P 107(R14), R13 // cdb54678
|
||||
|
||||
177
src/cmd/asm/internal/asm/testdata/arm64error.s
vendored
177
src/cmd/asm/internal/asm/testdata/arm64error.s
vendored
@@ -66,6 +66,7 @@ TEXT errors(SB),$0
|
||||
LDP.W 8(R3), (R2, R3) // ERROR "constrained unpredictable behavior"
|
||||
LDP (R1), (R2, R2) // ERROR "constrained unpredictable behavior"
|
||||
LDP (R0), (F0, F1) // ERROR "invalid register pair"
|
||||
LDP (R0), (R3, ZR) // ERROR "invalid register pair"
|
||||
LDXPW (RSP), (R2, R2) // ERROR "constrained unpredictable behavior"
|
||||
LDAXPW (R5), (R2, R2) // ERROR "constrained unpredictable behavior"
|
||||
MOVD.P 300(R2), R3 // ERROR "offset out of range [-256,255]"
|
||||
@@ -165,94 +166,94 @@ TEXT errors(SB),$0
|
||||
FSTPD (R1, R2), (R0) // ERROR "invalid register pair"
|
||||
FMOVS (F2), F0 // ERROR "illegal combination"
|
||||
FMOVD F0, (F1) // ERROR "illegal combination"
|
||||
LDADDAD R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDADDAW R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDADDAH R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDADDAB R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDADDALD R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDADDALW R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDADDALH R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDADDALB R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDADDD R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDADDW R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDADDH R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDADDB R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDADDLD R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDADDLW R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDADDLH R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDADDLB R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDCLRAD R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDCLRAW R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDCLRAH R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDCLRAB R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDCLRALD R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDCLRALW R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDCLRALH R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDCLRALB R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDCLRD R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDCLRW R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDCLRH R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDCLRB R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDCLRLD R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDCLRLW R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDCLRLH R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDCLRLB R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDEORAD R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDEORAW R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDEORAH R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDEORAB R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDEORALD R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDEORALW R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDEORALH R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDEORALB R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDEORD R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDEORW R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDEORH R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDEORB R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDEORLD R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDEORLW R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDEORLH R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDEORLB R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDORAD R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDORAW R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDORAH R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDORAB R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDORALD R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDORALW R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDORALH R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDORALB R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDORD R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDORW R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDORH R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDORB R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDORLD R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDORLW R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDORLH R5, (R6), RSP // ERROR "illegal combination"
|
||||
LDORLB R5, (R6), RSP // ERROR "illegal combination"
|
||||
SWPAD R5, (R6), RSP // ERROR "illegal combination"
|
||||
SWPAW R5, (R6), RSP // ERROR "illegal combination"
|
||||
SWPAH R5, (R6), RSP // ERROR "illegal combination"
|
||||
SWPAB R5, (R6), RSP // ERROR "illegal combination"
|
||||
SWPALD R5, (R6), RSP // ERROR "illegal combination"
|
||||
SWPALW R5, (R6), RSP // ERROR "illegal combination"
|
||||
SWPALH R5, (R6), RSP // ERROR "illegal combination"
|
||||
SWPALB R5, (R6), RSP // ERROR "illegal combination"
|
||||
SWPD R5, (R6), RSP // ERROR "illegal combination"
|
||||
SWPW R5, (R6), RSP // ERROR "illegal combination"
|
||||
SWPH R5, (R6), RSP // ERROR "illegal combination"
|
||||
SWPB R5, (R6), RSP // ERROR "illegal combination"
|
||||
SWPLD R5, (R6), RSP // ERROR "illegal combination"
|
||||
SWPLW R5, (R6), RSP // ERROR "illegal combination"
|
||||
SWPLH R5, (R6), RSP // ERROR "illegal combination"
|
||||
SWPLB R5, (R6), RSP // ERROR "illegal combination"
|
||||
STXR R5, (R6), RSP // ERROR "illegal combination"
|
||||
STXRW R5, (R6), RSP // ERROR "illegal combination"
|
||||
STLXR R5, (R6), RSP // ERROR "illegal combination"
|
||||
STLXRW R5, (R6), RSP // ERROR "illegal combination"
|
||||
STXP (R5, R7), (R6), RSP // ERROR "illegal combination"
|
||||
STXPW (R5, R7), (R6), RSP // ERROR "illegal combination"
|
||||
STLXP (R5, R7), (R6), RSP // ERROR "illegal combination"
|
||||
STLXP (R5, R7), (R6), RSP // ERROR "illegal combination"
|
||||
LDADDAD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDADDAW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDADDAH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDADDAB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDADDALD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDADDALW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDADDALH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDADDALB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDADDD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDADDW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDADDH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDADDB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDADDLD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDADDLW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDADDLH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDADDLB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDCLRAD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDCLRAW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDCLRAH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDCLRAB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDCLRALD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDCLRALW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDCLRALH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDCLRALB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDCLRD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDCLRW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDCLRH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDCLRB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDCLRLD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDCLRLW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDCLRLH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDCLRLB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDEORAD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDEORAW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDEORAH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDEORAB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDEORALD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDEORALW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDEORALH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDEORALB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDEORD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDEORW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDEORH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDEORB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDEORLD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDEORLW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDEORLH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDEORLB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDORAD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDORAW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDORAH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDORAB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDORALD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDORALW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDORALH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDORALB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDORD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDORW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDORH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDORB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDORLD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDORLW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDORLH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDORLB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
SWPAD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
SWPAW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
SWPAH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
SWPAB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
SWPALD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
SWPALW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
SWPALH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
SWPALB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
SWPD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
SWPW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
SWPH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
SWPB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
SWPLD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
SWPLW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
SWPLH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
SWPLB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
STXR R5, (R6), RSP // ERROR "illegal destination register"
|
||||
STXRW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
STLXR R5, (R6), RSP // ERROR "illegal destination register"
|
||||
STLXRW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
STXP (R5, R7), (R6), RSP // ERROR "illegal destination register"
|
||||
STXPW (R5, R7), (R6), RSP // ERROR "illegal destination register"
|
||||
STLXP (R5, R7), (R6), RSP // ERROR "illegal destination register"
|
||||
STLXP (R5, R7), (R6), RSP // ERROR "illegal destination register"
|
||||
MSR OSLAR_EL1, R5 // ERROR "illegal combination"
|
||||
MRS R11, AIDR_EL1 // ERROR "illegal combination"
|
||||
MSR R6, AIDR_EL1 // ERROR "system register is not writable"
|
||||
|
||||
5
src/cmd/asm/internal/asm/testdata/mips.s
vendored
5
src/cmd/asm/internal/asm/testdata/mips.s
vendored
@@ -429,11 +429,6 @@ label4:
|
||||
CLZ R1, R2 // 70221020
|
||||
CLO R1, R2 // 70221021
|
||||
|
||||
WSBH R1, R2 // 7c0110a0
|
||||
|
||||
SEB R1, R2 // 7c011420
|
||||
SEH R1, R2 // 7c011620
|
||||
|
||||
// to (Hi, Lo)
|
||||
MADD R2, R1 // 70220000
|
||||
MSUB R2, R1 // 70220004
|
||||
|
||||
9
src/cmd/asm/internal/asm/testdata/mips64.s
vendored
9
src/cmd/asm/internal/asm/testdata/mips64.s
vendored
@@ -587,17 +587,8 @@ label4:
|
||||
CALL foo(SB)
|
||||
RET foo(SB)
|
||||
|
||||
// unary operation
|
||||
NEGW R1, R2 // 00011023
|
||||
NEGV R1, R2 // 0001102f
|
||||
|
||||
WSBH R1, R2 // 7c0110a0
|
||||
DSBH R1, R2 // 7c0110a4
|
||||
DSHD R1, R2 // 7c011164
|
||||
|
||||
SEB R1, R2 // 7c011420
|
||||
SEH R1, R2 // 7c011620
|
||||
|
||||
RET
|
||||
|
||||
// MSA VMOVI
|
||||
|
||||
59
src/cmd/asm/internal/asm/testdata/ppc64.s
vendored
59
src/cmd/asm/internal/asm/testdata/ppc64.s
vendored
@@ -17,14 +17,14 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
|
||||
MOVD $1, R3 // 38600001
|
||||
MOVD $-1, R4 // 3880ffff
|
||||
MOVD $65535, R5 // 6005ffff
|
||||
MOVD $65536, R6 // 3cc00001
|
||||
MOVD $65536, R6 // 64060001
|
||||
MOVD $-32767, R5 // 38a08001
|
||||
MOVD $-32768, R6 // 38c08000
|
||||
MOVD $1234567, R5 // 6405001260a5d687 or 0600001238a0d687
|
||||
MOVW $1, R3 // 38600001
|
||||
MOVW $-1, R4 // 3880ffff
|
||||
MOVW $65535, R5 // 6005ffff
|
||||
MOVW $65536, R6 // 3cc00001
|
||||
MOVW $65536, R6 // 64060001
|
||||
MOVW $-32767, R5 // 38a08001
|
||||
MOVW $-32768, R6 // 38c08000
|
||||
MOVW $1234567, R5 // 6405001260a5d687 or 0600001238a0d687
|
||||
@@ -32,29 +32,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
|
||||
MOVW $2147483649, R5 // 6405800060a50001 or 0600800038a00001
|
||||
MOVD $2147483649, R5 // 6405800060a50001 or 0600800038a00001
|
||||
// Hex constant 0xFFFFFFFF80000001
|
||||
MOVD $-2147483647, R5 // 3ca0800060a50001 or 0603800038a00001
|
||||
// Hex constant 0xFFFFFFFE00000002 (load of constant on < power10, pli on >= power10
|
||||
MOVD $-8589934590, R5 // 3ca00000e8a50000 or 0602000038a00002
|
||||
|
||||
// For backwards compatibility, MOVW $const,Rx and MOVWZ $const,Rx assemble identically
|
||||
// and accept the same constants.
|
||||
MOVW $2147483648, R5 // 64058000
|
||||
MOVWZ $-2147483648, R5 // 3ca08000
|
||||
|
||||
// TODO: These are preprocessed by the assembler into MOVD $const>>shift, R5; SLD $shift, R5.
|
||||
// This only captures the MOVD. Should the SLD be appended to the encoding by the test?
|
||||
// Hex constant 0x20004000000
|
||||
MOVD $2199090364416, R5 // 60058001
|
||||
// Hex constant 0xFFFFFE0004000000
|
||||
MOVD $-2198956146688, R5 // 38a08001
|
||||
// TODO: On GOPPC64={power8,power9}, this is preprocessed into MOVD $-1, R5; RLDC R5, $33, $63, R5.
|
||||
// This only captures the MOVD. Should the RLDC be appended to the encoding by the test?
|
||||
// Hex constant 0xFFFFFFFE00000001
|
||||
MOVD $-8589934591, R5 // 38a0ffff or 0602000038a00001
|
||||
|
||||
// For #66955. Verify this opcode turns into a load and assembles.
|
||||
MOVD $-6795364578871345152, R5 // 3ca00000e8a50000 or 04100000e4a00000
|
||||
|
||||
MOVD $-2147483647, R5 // 3ca0800060a50001 or 0603800038a00001
|
||||
MOVD 8(R3), R4 // e8830008
|
||||
MOVD (R3)(R4), R5 // 7ca4182a
|
||||
MOVD (R3)(R0), R5 // 7ca0182a
|
||||
@@ -93,7 +71,6 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
|
||||
MOVHBR (R3)(R4), R5 // 7ca41e2c
|
||||
MOVHBR (R3)(R0), R5 // 7ca01e2c
|
||||
MOVHBR (R3), R5 // 7ca01e2c
|
||||
OR $0, R0, R0
|
||||
MOVD $foo+4009806848(FP), R5 // 3ca1ef0138a5cc40 or 0600ef0038a1cc40
|
||||
MOVD $foo(SB), R5 // 3ca0000038a50000 or 0610000038a00000
|
||||
|
||||
@@ -187,10 +164,6 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
|
||||
ADD $-32767, R5, R4 // 38858001
|
||||
ADD $-32768, R6 // 38c68000
|
||||
ADD $-32768, R6, R5 // 38a68000
|
||||
// Hex constant 0xFFFFFFFE00000000
|
||||
ADD $-8589934592, R5 // 3fe0fffe600000007bff83e4600000007cbf2a14 or 0602000038a50000
|
||||
// Hex constant 0xFFFFFFFE00010001
|
||||
ADD $-8589869055, R5 // 3fe0fffe63ff00017bff83e463ff00017cbf2a14 or 0602000138a50001
|
||||
|
||||
//TODO: this compiles to add r5,r6,r0. It should be addi r5,r6,0.
|
||||
// this is OK since r0 == $0, but the latter is preferred.
|
||||
@@ -201,7 +174,6 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
|
||||
ADDEX R3, R5, $3, R6 // 7cc32f54
|
||||
ADDEX R3, $3, R5, R6 // 7cc32f54
|
||||
ADDIS $8, R3 // 3c630008
|
||||
ADD $524288, R3 // 3c630008
|
||||
ADDIS $1000, R3, R4 // 3c8303e8
|
||||
|
||||
ANDCC $1, R3 // 70630001
|
||||
@@ -220,7 +192,6 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
|
||||
ANDCC $1234567, R5, R6 // 641f001263ffd6877fe62839
|
||||
ANDISCC $1, R3 // 74630001
|
||||
ANDISCC $1000, R3, R4 // 746403e8
|
||||
ANDCC $65536000, R3, R4 // 746403e8
|
||||
|
||||
OR $1, R3 // 60630001
|
||||
OR $1, R3, R4 // 60640001
|
||||
@@ -236,10 +207,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
|
||||
OR $-32768, R6, R7 // 3be080007fe73378
|
||||
OR $1234567, R5 // 641f001263ffd6877fe52b78
|
||||
OR $1234567, R5, R3 // 641f001263ffd6877fe32b78
|
||||
OR $2147483648, R5, R3 // 64a38000
|
||||
OR $2147483649, R5, R3 // 641f800063ff00017fe32b78
|
||||
ORIS $255, R3, R4 // 646400ff
|
||||
OR $16711680, R3, R4 // 646400ff
|
||||
ORIS $255, R3, R4
|
||||
|
||||
XOR $1, R3 // 68630001
|
||||
XOR $1, R3, R4 // 68640001
|
||||
@@ -255,8 +223,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
|
||||
XOR $-32768, R6, R7 // 3be080007fe73278
|
||||
XOR $1234567, R5 // 641f001263ffd6877fe52a78
|
||||
XOR $1234567, R5, R3 // 641f001263ffd6877fe32a78
|
||||
XORIS $15, R3, R4 // 6c64000f
|
||||
XOR $983040, R3, R4 // 6c64000f
|
||||
XORIS $15, R3, R4
|
||||
|
||||
// TODO: the order of CR operands don't match
|
||||
CMP R3, R4 // 7c232000
|
||||
@@ -266,6 +233,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
|
||||
CMPB R3,R4,R4 // 7c6423f8
|
||||
CMPEQB R3,R4,CR6 // 7f0321c0
|
||||
|
||||
// TODO: constants for ADDC?
|
||||
ADD R3, R4 // 7c841a14
|
||||
ADD R3, R4, R5 // 7ca41a14
|
||||
ADDC R3, R4 // 7c841814
|
||||
@@ -278,8 +246,6 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
|
||||
ADDV R3, R4 // 7c841e14
|
||||
ADDVCC R3, R4 // 7c841e15
|
||||
ADDCCC R3, R4, R5 // 7ca41815
|
||||
ADDCCC $65536, R4, R5 // 641f0001600000007cbf2015
|
||||
ADDCCC $65537, R4, R5 // 641f000163ff00017cbf2015
|
||||
ADDME R3, R4 // 7c8301d4
|
||||
ADDMECC R3, R4 // 7c8301d5
|
||||
ADDMEV R3, R4 // 7c8305d4
|
||||
@@ -333,8 +299,6 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
|
||||
SUBECC R3, R4, R5 // 7ca32111
|
||||
SUBEV R3, R4, R5 // 7ca32510
|
||||
SUBEVCC R3, R4, R5 // 7ca32511
|
||||
SUBC R3, $65536, R4 // 3fe00001600000007c83f810
|
||||
SUBC R3, $65537, R4 // 3fe0000163ff00017c83f810
|
||||
|
||||
MULLW R3, R4 // 7c8419d6
|
||||
MULLW R3, R4, R5 // 7ca419d6
|
||||
@@ -429,19 +393,12 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
|
||||
EXTSHCC R3, R4 // 7c640735
|
||||
EXTSW R3, R4 // 7c6407b4
|
||||
EXTSWCC R3, R4 // 7c6407b5
|
||||
RLWMI $7, R3, $4026531855, R6 // 50663f06
|
||||
RLWMI $7, R3, $1, R6 // 50663ffe
|
||||
RLWMI $7, R3, $2147483648, R6 // 50663800
|
||||
RLWMI $7, R3, $65535, R6 // 50663c3e
|
||||
RLWMI $7, R3, $16, $31, R6 // 50663c3e
|
||||
RLWMICC $7, R3, $65535, R6 // 50663c3f
|
||||
RLWMICC $7, R3, $16, $31, R6 // 50663c3f
|
||||
RLWNM $3, R4, $7, R6 // 54861f7e
|
||||
RLWNM $0, R4, $7, R6 // 5486077e
|
||||
RLWNM R0, R4, $7, R6 // 5c86077e
|
||||
RLWNM $3, R4, $29, $31, R6 // 54861f7e
|
||||
RLWNM $0, R4, $29, $31, R6 // 5486077e
|
||||
RLWNM R0, R4, $29, $31, R6 // 5c86077e
|
||||
RLWNM R3, R4, $7, R6 // 5c861f7e
|
||||
RLWNM R3, R4, $29, $31, R6 // 5c861f7e
|
||||
RLWNMCC $3, R4, $7, R6 // 54861f7f
|
||||
@@ -453,10 +410,6 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
|
||||
RLDIMI $0, R4, $7, R6 // 788601cc
|
||||
RLDIMICC $0, R4, $7, R6 // 788601cd
|
||||
RLDC $0, R4, $15, R6 // 78860728
|
||||
RLDC R3, $32, $12, R4 // 7864030a
|
||||
RLDC R3, $8, $32, R4 // 78644028
|
||||
RLDCCC R3, $32, $12, R4 // 7864030b
|
||||
RLDCCC R3, $8, $32, R4 // 78644029
|
||||
RLDCCC $0, R4, $15, R6 // 78860729
|
||||
RLDCL $0, R4, $7, R6 // 78860770
|
||||
RLDCLCC $0, R4, $15, R6 // 78860721
|
||||
|
||||
57
src/cmd/asm/internal/asm/testdata/riscv64.s
vendored
57
src/cmd/asm/internal/asm/testdata/riscv64.s
vendored
@@ -94,10 +94,6 @@ start:
|
||||
|
||||
SUB X6, X5, X7 // b3836240
|
||||
SUB X5, X6 // 33035340
|
||||
SUB $-2047, X5, X6 // 1383f27f
|
||||
SUB $2048, X5, X6 // 13830280
|
||||
SUB $-2047, X5 // 9382f27f
|
||||
SUB $2048, X5 // 93820280
|
||||
|
||||
SRA X6, X5, X7 // b3d36240
|
||||
SRA X5, X6 // 33535340
|
||||
@@ -161,7 +157,6 @@ start:
|
||||
ADDW $1, X6 // 1b031300
|
||||
SLLW $1, X6 // 1b131300
|
||||
SRLW $1, X6 // 1b531300
|
||||
SUBW $1, X6 // 1b03f3ff
|
||||
SRAW $1, X6 // 1b531340
|
||||
|
||||
// 5.3: Load and Store Instructions (RV64I)
|
||||
@@ -188,28 +183,28 @@ start:
|
||||
// 8.2: Load-Reserved/Store-Conditional
|
||||
LRW (X5), X6 // 2fa30214
|
||||
LRD (X5), X6 // 2fb30214
|
||||
SCW X5, (X6), X7 // af23531a
|
||||
SCD X5, (X6), X7 // af33531a
|
||||
SCW X5, (X6), X7 // af23531c
|
||||
SCD X5, (X6), X7 // af33531c
|
||||
|
||||
// 8.3: Atomic Memory Operations
|
||||
AMOSWAPW X5, (X6), X7 // af23530e
|
||||
AMOSWAPD X5, (X6), X7 // af33530e
|
||||
AMOADDW X5, (X6), X7 // af235306
|
||||
AMOADDD X5, (X6), X7 // af335306
|
||||
AMOANDW X5, (X6), X7 // af235366
|
||||
AMOANDD X5, (X6), X7 // af335366
|
||||
AMOORW X5, (X6), X7 // af235346
|
||||
AMOORD X5, (X6), X7 // af335346
|
||||
AMOXORW X5, (X6), X7 // af235326
|
||||
AMOXORD X5, (X6), X7 // af335326
|
||||
AMOMAXW X5, (X6), X7 // af2353a6
|
||||
AMOMAXD X5, (X6), X7 // af3353a6
|
||||
AMOMAXUW X5, (X6), X7 // af2353e6
|
||||
AMOMAXUD X5, (X6), X7 // af3353e6
|
||||
AMOMINW X5, (X6), X7 // af235386
|
||||
AMOMIND X5, (X6), X7 // af335386
|
||||
AMOMINUW X5, (X6), X7 // af2353c6
|
||||
AMOMINUD X5, (X6), X7 // af3353c6
|
||||
AMOSWAPW X5, (X6), X7 // af23530c
|
||||
AMOSWAPD X5, (X6), X7 // af33530c
|
||||
AMOADDW X5, (X6), X7 // af235304
|
||||
AMOADDD X5, (X6), X7 // af335304
|
||||
AMOANDW X5, (X6), X7 // af235364
|
||||
AMOANDD X5, (X6), X7 // af335364
|
||||
AMOORW X5, (X6), X7 // af235344
|
||||
AMOORD X5, (X6), X7 // af335344
|
||||
AMOXORW X5, (X6), X7 // af235324
|
||||
AMOXORD X5, (X6), X7 // af335324
|
||||
AMOMAXW X5, (X6), X7 // af2353a4
|
||||
AMOMAXD X5, (X6), X7 // af3353a4
|
||||
AMOMAXUW X5, (X6), X7 // af2353e4
|
||||
AMOMAXUD X5, (X6), X7 // af3353e4
|
||||
AMOMINW X5, (X6), X7 // af235384
|
||||
AMOMIND X5, (X6), X7 // af335384
|
||||
AMOMINUW X5, (X6), X7 // af2353c4
|
||||
AMOMINUD X5, (X6), X7 // af3353c4
|
||||
|
||||
// 10.1: Base Counters and Timers
|
||||
RDCYCLE X5 // f32200c0
|
||||
@@ -359,14 +354,6 @@ start:
|
||||
MOVD F0, 4(X5) // 27b20200
|
||||
MOVD F0, F1 // d3000022
|
||||
|
||||
// TLS load with local-exec (LUI + ADDIW + ADD of TP + load)
|
||||
MOV tls(SB), X5 // b70f00009b8f0f00b38f4f0083b20f00
|
||||
MOVB tls(SB), X5 // b70f00009b8f0f00b38f4f0083820f00
|
||||
|
||||
// TLS store with local-exec (LUI + ADDIW + ADD of TP + store)
|
||||
MOV X5, tls(SB) // b70f00009b8f0f00b38f4f0023b05f00
|
||||
MOVB X5, tls(SB) // b70f00009b8f0f00b38f4f0023805f00
|
||||
|
||||
// NOT pseudo-instruction
|
||||
NOT X5 // 93c2f2ff
|
||||
NOT X5, X6 // 13c3f2ff
|
||||
@@ -386,7 +373,7 @@ start:
|
||||
JMP 4(X5) // 67804200
|
||||
|
||||
// CALL and JMP to symbol are encoded as JAL (using LR or ZERO
|
||||
// respectively), with a R_RISCV_JAL relocation. The linker resolves
|
||||
// respectively), with a R_RISCV_CALL relocation. The linker resolves
|
||||
// the real address and updates the immediate, using a trampoline in
|
||||
// the case where the address is not directly reachable.
|
||||
CALL asmtest(SB) // ef000000
|
||||
@@ -420,5 +407,3 @@ start:
|
||||
FLTD F0, F1, X5 // d39200a2
|
||||
FLED F0, F1, X5 // d38200a2
|
||||
FEQD F0, F1, X5 // d3a200a2
|
||||
|
||||
GLOBL tls(SB), TLSBSS, $8
|
||||
|
||||
@@ -38,8 +38,5 @@ TEXT errors(SB),$0
|
||||
SLLIW $-1, X5, X6 // ERROR "shift amount out of range 0 to 31"
|
||||
SRLIW $-1, X5, X6 // ERROR "shift amount out of range 0 to 31"
|
||||
SRAIW $-1, X5, X6 // ERROR "shift amount out of range 0 to 31"
|
||||
SD X5, 4294967296(X6) // ERROR "constant 4294967296 too large"
|
||||
SRLI $1, X5, F1 // ERROR "expected integer register in rd position but got non-integer register F1"
|
||||
SRLI $1, F1, X5 // ERROR "expected integer register in rs1 position but got non-integer register F1"
|
||||
FNES F1, (X5) // ERROR "needs an integer register output"
|
||||
|
||||
RET
|
||||
|
||||
8
src/cmd/asm/internal/asm/testdata/s390x.s
vendored
8
src/cmd/asm/internal/asm/testdata/s390x.s
vendored
@@ -415,14 +415,6 @@ TEXT main·foo(SB),DUPOK|NOSPLIT,$16-0 // TEXT main.foo(SB), DUPOK|NOSPLIT, $16-
|
||||
|
||||
SYNC // 07e0
|
||||
|
||||
KM R2, R4 // b92e0024
|
||||
KMC R2, R6 // b92f0026
|
||||
KLMD R2, R8 // b93f0028
|
||||
KIMD R0, R4 // b93e0004
|
||||
KDSA R0, R8 // b93a0008
|
||||
KMA R2, R6, R4 // b9296024
|
||||
KMCTR R2, R6, R4 // b92d6024
|
||||
|
||||
// vector add and sub instructions
|
||||
VAB V3, V4, V4 // e743400000f3
|
||||
VAH V3, V4, V4 // e743400010f3
|
||||
|
||||
@@ -16,16 +16,17 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
Debug = flag.Bool("debug", false, "dump instructions as they are parsed")
|
||||
OutputFile = flag.String("o", "", "output file; default foo.o for /a/b/c/foo.s as first argument")
|
||||
TrimPath = flag.String("trimpath", "", "remove prefix from recorded source file paths")
|
||||
Shared = flag.Bool("shared", false, "generate code that can be linked into a shared library")
|
||||
Dynlink = flag.Bool("dynlink", false, "support references to Go symbols defined in other shared libraries")
|
||||
Linkshared = flag.Bool("linkshared", false, "generate code that will be linked against Go shared libraries")
|
||||
AllErrors = flag.Bool("e", false, "no limit on number of errors reported")
|
||||
SymABIs = flag.Bool("gensymabis", false, "write symbol ABI information to output file, don't assemble")
|
||||
Importpath = flag.String("p", obj.UnlinkablePkg, "set expected package import to path")
|
||||
Spectre = flag.String("spectre", "", "enable spectre mitigations in `list` (all, ret)")
|
||||
Debug = flag.Bool("debug", false, "dump instructions as they are parsed")
|
||||
OutputFile = flag.String("o", "", "output file; default foo.o for /a/b/c/foo.s as first argument")
|
||||
TrimPath = flag.String("trimpath", "", "remove prefix from recorded source file paths")
|
||||
Shared = flag.Bool("shared", false, "generate code that can be linked into a shared library")
|
||||
Dynlink = flag.Bool("dynlink", false, "support references to Go symbols defined in other shared libraries")
|
||||
Linkshared = flag.Bool("linkshared", false, "generate code that will be linked against Go shared libraries")
|
||||
AllErrors = flag.Bool("e", false, "no limit on number of errors reported")
|
||||
SymABIs = flag.Bool("gensymabis", false, "write symbol ABI information to output file, don't assemble")
|
||||
Importpath = flag.String("p", obj.UnlinkablePkg, "set expected package import to path")
|
||||
Spectre = flag.String("spectre", "", "enable spectre mitigations in `list` (all, ret)")
|
||||
CompilingRuntime = flag.Bool("compiling-runtime", false, "source to be compiled is part of the Go runtime")
|
||||
)
|
||||
|
||||
var DebugFlags struct {
|
||||
|
||||
@@ -6,6 +6,7 @@ package lex
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"internal/buildcfg"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
@@ -45,6 +46,21 @@ func NewInput(name string) *Input {
|
||||
// predefine installs the macros set by the -D flag on the command line.
|
||||
func predefine(defines flags.MultiFlag) map[string]*Macro {
|
||||
macros := make(map[string]*Macro)
|
||||
|
||||
// Set macros for GOEXPERIMENTs so we can easily switch
|
||||
// runtime assembly code based on them.
|
||||
if *flags.CompilingRuntime {
|
||||
for _, exp := range buildcfg.Experiment.Enabled() {
|
||||
// Define macro.
|
||||
name := "GOEXPERIMENT_" + exp
|
||||
macros[name] = &Macro{
|
||||
name: name,
|
||||
args: nil,
|
||||
tokens: Tokenize("1"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, name := range defines {
|
||||
value := "1"
|
||||
i := strings.IndexRune(name, '=')
|
||||
|
||||
@@ -105,9 +105,13 @@ type Token struct {
|
||||
|
||||
// Make returns a Token with the given rune (ScanToken) and text representation.
|
||||
func Make(token ScanToken, text string) Token {
|
||||
// If the symbol starts with center dot, as in ·x, rewrite it as ""·x
|
||||
if token == scanner.Ident && strings.HasPrefix(text, "\u00B7") {
|
||||
text = `""` + text
|
||||
}
|
||||
// Substitute the substitutes for . and /.
|
||||
text = strings.ReplaceAll(text, "\u00B7", ".")
|
||||
text = strings.ReplaceAll(text, "\u2215", "/")
|
||||
text = strings.Replace(text, "\u00B7", ".", -1)
|
||||
text = strings.Replace(text, "\u2215", "/", -1)
|
||||
return Token{ScanToken: token, text: text}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ func main() {
|
||||
if architecture == nil {
|
||||
log.Fatalf("unrecognized architecture %s", GOARCH)
|
||||
}
|
||||
|
||||
ctxt := obj.Linknew(architecture.LinkArch)
|
||||
ctxt.Debugasm = flags.PrintOut
|
||||
ctxt.Debugvlog = flags.DebugV
|
||||
@@ -75,19 +76,12 @@ func main() {
|
||||
fmt.Fprintf(buf, "!\n")
|
||||
}
|
||||
|
||||
// Set macros for GOEXPERIMENTs so we can easily switch
|
||||
// runtime assembly code based on them.
|
||||
if objabi.LookupPkgSpecial(ctxt.Pkgpath).AllowAsmABI {
|
||||
for _, exp := range buildcfg.Experiment.Enabled() {
|
||||
flags.D = append(flags.D, "GOEXPERIMENT_"+exp)
|
||||
}
|
||||
}
|
||||
|
||||
var ok, diag bool
|
||||
var failedFile string
|
||||
for _, f := range flag.Args() {
|
||||
lexer := lex.NewLexer(f)
|
||||
parser := asm.NewParser(ctxt, architecture, lexer)
|
||||
parser := asm.NewParser(ctxt, architecture, lexer,
|
||||
*flags.CompilingRuntime)
|
||||
ctxt.DiagFunc = func(format string, args ...interface{}) {
|
||||
diag = true
|
||||
log.Printf(format, args...)
|
||||
@@ -99,7 +93,7 @@ func main() {
|
||||
pList.Firstpc, ok = parser.Parse()
|
||||
// reports errors to parser.Errorf
|
||||
if ok {
|
||||
obj.Flushplist(ctxt, pList, nil)
|
||||
obj.Flushplist(ctxt, pList, nil, *flags.Importpath)
|
||||
}
|
||||
}
|
||||
if !ok {
|
||||
|
||||
@@ -686,7 +686,7 @@ files:
|
||||
_cgo_export.c # for gcc
|
||||
_cgo_export.h # for gcc
|
||||
_cgo_main.c # for gcc
|
||||
_cgo_flags # for build tool (if -gccgo)
|
||||
_cgo_flags # for alternative build tools
|
||||
|
||||
The file x.cgo1.go is a copy of x.go with the import "C" removed and
|
||||
references to C.xxx replaced with names like _Cfunc_xxx or _Ctype_xxx.
|
||||
|
||||
@@ -73,41 +73,27 @@ func cname(s string) string {
|
||||
return s
|
||||
}
|
||||
|
||||
// ProcessCgoDirectives processes the import C preamble:
|
||||
// 1. discards all #cgo CFLAGS, LDFLAGS, nocallback and noescape directives,
|
||||
// so they don't make their way into _cgo_export.h.
|
||||
// 2. parse the nocallback and noescape directives.
|
||||
func (f *File) ProcessCgoDirectives() {
|
||||
// DiscardCgoDirectives processes the import C preamble, and discards
|
||||
// all #cgo CFLAGS and LDFLAGS directives, so they don't make their
|
||||
// way into _cgo_export.h.
|
||||
func (f *File) DiscardCgoDirectives() {
|
||||
linesIn := strings.Split(f.Preamble, "\n")
|
||||
linesOut := make([]string, 0, len(linesIn))
|
||||
f.NoCallbacks = make(map[string]bool)
|
||||
f.NoEscapes = make(map[string]bool)
|
||||
for _, line := range linesIn {
|
||||
l := strings.TrimSpace(line)
|
||||
if len(l) < 5 || l[:4] != "#cgo" || !unicode.IsSpace(rune(l[4])) {
|
||||
linesOut = append(linesOut, line)
|
||||
} else {
|
||||
linesOut = append(linesOut, "")
|
||||
|
||||
// #cgo (nocallback|noescape) <function name>
|
||||
if fields := strings.Fields(l); len(fields) == 3 {
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
f.Preamble = strings.Join(linesOut, "\n")
|
||||
}
|
||||
|
||||
// addToFlag appends args to flag.
|
||||
// addToFlag appends args to flag. All flags are later written out onto the
|
||||
// _cgo_flags file for the build system to use.
|
||||
func (p *Package) addToFlag(flag string, args []string) {
|
||||
p.CgoFlags[flag] = append(p.CgoFlags[flag], args...)
|
||||
if flag == "CFLAGS" {
|
||||
// We'll also need these when preprocessing for dwarf information.
|
||||
// However, discard any -g options: we need to be able
|
||||
@@ -118,9 +104,6 @@ func (p *Package) addToFlag(flag string, args []string) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if flag == "LDFLAGS" {
|
||||
p.LdFlags = append(p.LdFlags, args...)
|
||||
}
|
||||
}
|
||||
|
||||
// splitQuoted splits the string s around each instance of one or more consecutive
|
||||
@@ -598,7 +581,7 @@ func (p *Package) loadDWARF(f *File, conv *typeConv, names []*Name) {
|
||||
// As of https://reviews.llvm.org/D123534, clang
|
||||
// now emits DW_TAG_variable DIEs that have
|
||||
// no name (so as to be able to describe the
|
||||
// type and source locations of constant strings)
|
||||
// type and source locations of constant strings
|
||||
// like the second arg in the call below:
|
||||
//
|
||||
// myfunction(42, "foo")
|
||||
@@ -2579,11 +2562,6 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Typ
|
||||
if dt.BitSize > 0 {
|
||||
fatalf("%s: unexpected: %d-bit int type - %s", lineno(pos), dt.BitSize, dtype)
|
||||
}
|
||||
|
||||
if t.Align = t.Size; t.Align >= c.ptrSize {
|
||||
t.Align = c.ptrSize
|
||||
}
|
||||
|
||||
switch t.Size {
|
||||
default:
|
||||
fatalf("%s: unexpected: %d-byte int type - %s", lineno(pos), t.Size, dtype)
|
||||
@@ -2600,8 +2578,9 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Typ
|
||||
Len: c.intExpr(t.Size),
|
||||
Elt: c.uint8,
|
||||
}
|
||||
// t.Align is the alignment of the Go type.
|
||||
t.Align = 1
|
||||
}
|
||||
if t.Align = t.Size; t.Align >= c.ptrSize {
|
||||
t.Align = c.ptrSize
|
||||
}
|
||||
|
||||
case *dwarf.PtrType:
|
||||
@@ -2830,11 +2809,6 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Typ
|
||||
if dt.BitSize > 0 {
|
||||
fatalf("%s: unexpected: %d-bit uint type - %s", lineno(pos), dt.BitSize, dtype)
|
||||
}
|
||||
|
||||
if t.Align = t.Size; t.Align >= c.ptrSize {
|
||||
t.Align = c.ptrSize
|
||||
}
|
||||
|
||||
switch t.Size {
|
||||
default:
|
||||
fatalf("%s: unexpected: %d-byte uint type - %s", lineno(pos), t.Size, dtype)
|
||||
@@ -2851,8 +2825,9 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Typ
|
||||
Len: c.intExpr(t.Size),
|
||||
Elt: c.uint8,
|
||||
}
|
||||
// t.Align is the alignment of the Go type.
|
||||
t.Align = 1
|
||||
}
|
||||
if t.Align = t.Size; t.Align >= c.ptrSize {
|
||||
t.Align = c.ptrSize
|
||||
}
|
||||
|
||||
case *dwarf.VoidType:
|
||||
@@ -3118,11 +3093,10 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct
|
||||
}
|
||||
|
||||
// Round off up to talign, assumed to be a power of 2.
|
||||
origOff := off
|
||||
off = (off + talign - 1) &^ (talign - 1)
|
||||
|
||||
if f.ByteOffset > off {
|
||||
fld, sizes = c.pad(fld, sizes, f.ByteOffset-origOff)
|
||||
fld, sizes = c.pad(fld, sizes, f.ByteOffset-off)
|
||||
off = f.ByteOffset
|
||||
}
|
||||
if f.ByteOffset < off {
|
||||
|
||||
@@ -44,18 +44,11 @@ func run(t *testing.T, dir string, lto bool, args ...string) {
|
||||
cmd := exec.Command("go", runArgs...)
|
||||
cmd.Dir = dir
|
||||
if lto {
|
||||
// On the builders we're using the default /usr/bin/ld, but
|
||||
// that has problems when asking for LTO in particular. Force
|
||||
// use of lld, which ships with our clang installation.
|
||||
extraLDFlags := ""
|
||||
if strings.Contains(testenv.Builder(), "clang") {
|
||||
extraLDFlags += " -fuse-ld=lld"
|
||||
}
|
||||
const cflags = "-flto -Wno-lto-type-mismatch -Wno-unknown-warning-option"
|
||||
cmd.Env = append(cmd.Environ(),
|
||||
"CGO_CFLAGS="+cflags,
|
||||
"CGO_CXXFLAGS="+cflags,
|
||||
"CGO_LDFLAGS="+cflags+extraLDFlags)
|
||||
"CGO_LDFLAGS="+cflags)
|
||||
}
|
||||
out, err := cmd.CombinedOutput()
|
||||
if string(out) != "OK\n" {
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
// Copyright 2023 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 cgotest
|
||||
|
||||
/*
|
||||
#include <windows.h>
|
||||
USHORT backtrace(ULONG FramesToCapture, PVOID *BackTrace) {
|
||||
#ifdef _AMD64_
|
||||
CONTEXT context;
|
||||
RtlCaptureContext(&context);
|
||||
ULONG64 ControlPc;
|
||||
ControlPc = context.Rip;
|
||||
int i;
|
||||
for (i = 0; i < FramesToCapture; i++) {
|
||||
PRUNTIME_FUNCTION FunctionEntry;
|
||||
ULONG64 ImageBase;
|
||||
VOID *HandlerData;
|
||||
ULONG64 EstablisherFrame;
|
||||
|
||||
FunctionEntry = RtlLookupFunctionEntry(ControlPc, &ImageBase, NULL);
|
||||
|
||||
if (!FunctionEntry) {
|
||||
// For simplicity, don't unwind leaf entries, which are not used in this test.
|
||||
break;
|
||||
} else {
|
||||
RtlVirtualUnwind(0, ImageBase, ControlPc, FunctionEntry, &context, &HandlerData, &EstablisherFrame, NULL);
|
||||
}
|
||||
|
||||
ControlPc = context.Rip;
|
||||
// Check if we left the user range.
|
||||
if (ControlPc < 0x10000) {
|
||||
break;
|
||||
}
|
||||
|
||||
BackTrace[i] = (PVOID)(ControlPc);
|
||||
}
|
||||
return i;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"internal/testenv"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Test that the stack can be unwound through a call out and call back
|
||||
// into Go.
|
||||
func testCallbackCallersSEH(t *testing.T) {
|
||||
testenv.SkipIfOptimizationOff(t) // This test requires inlining.
|
||||
if runtime.Compiler != "gc" {
|
||||
// The exact function names are not going to be the same.
|
||||
t.Skip("skipping for non-gc toolchain")
|
||||
}
|
||||
if runtime.GOARCH != "amd64" {
|
||||
// TODO: support SEH on other architectures.
|
||||
t.Skip("skipping on non-amd64")
|
||||
}
|
||||
// Only frames in the test package are checked.
|
||||
want := []string{
|
||||
"test._Cfunc_backtrace",
|
||||
"test.testCallbackCallersSEH.func1.1",
|
||||
"test.testCallbackCallersSEH.func1",
|
||||
"test.goCallback",
|
||||
"test._Cfunc_callback",
|
||||
"test.nestedCall.func1",
|
||||
"test.nestedCall",
|
||||
"test.testCallbackCallersSEH",
|
||||
"test.TestCallbackCallersSEH",
|
||||
}
|
||||
pc := make([]uintptr, 100)
|
||||
n := 0
|
||||
nestedCall(func() {
|
||||
n = int(C.backtrace(C.DWORD(len(pc)), (*C.PVOID)(unsafe.Pointer(&pc[0]))))
|
||||
})
|
||||
got := make([]string, 0, n)
|
||||
for i := 0; i < n; i++ {
|
||||
f := runtime.FuncForPC(pc[i] - 1)
|
||||
if f == nil {
|
||||
continue
|
||||
}
|
||||
fname := f.Name()
|
||||
switch fname {
|
||||
case "goCallback":
|
||||
// TODO(qmuntal): investigate why this function doesn't appear
|
||||
// when using the external linker.
|
||||
continue
|
||||
}
|
||||
// In module mode, this package has a fully-qualified import path.
|
||||
// Remove it if present.
|
||||
fname = strings.TrimPrefix(fname, "cmd/cgo/internal/")
|
||||
if !strings.HasPrefix(fname, "test.") {
|
||||
continue
|
||||
}
|
||||
got = append(got, fname)
|
||||
}
|
||||
if !reflect.DeepEqual(want, got) {
|
||||
t.Errorf("incorrect backtrace:\nwant:\t%v\ngot:\t%v", want, got)
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
// Copyright 2023 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 cgotest
|
||||
|
||||
// extern int notoc_func(void);
|
||||
// int TestPPC64Stubs(void) {
|
||||
// return notoc_func();
|
||||
// }
|
||||
import "C"
|
||||
import "testing"
|
||||
|
||||
func testPPC64CallStubs(t *testing.T) {
|
||||
// Verify the trampolines run on the testing machine. If they
|
||||
// do not, or are missing, a crash is expected.
|
||||
if C.TestPPC64Stubs() != 0 {
|
||||
t.Skipf("This test requires binutils 2.35 or newer.")
|
||||
}
|
||||
}
|
||||
@@ -70,7 +70,6 @@ func Test31891(t *testing.T) { test31891(t) }
|
||||
func Test42018(t *testing.T) { test42018(t) }
|
||||
func Test45451(t *testing.T) { test45451(t) }
|
||||
func Test49633(t *testing.T) { test49633(t) }
|
||||
func Test69086(t *testing.T) { test69086(t) }
|
||||
func TestAlign(t *testing.T) { testAlign(t) }
|
||||
func TestAtol(t *testing.T) { testAtol(t) }
|
||||
func TestBlocking(t *testing.T) { testBlocking(t) }
|
||||
|
||||
@@ -8,7 +8,6 @@ package cgotest
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"internal/testenv"
|
||||
"os"
|
||||
"runtime"
|
||||
"sort"
|
||||
@@ -146,13 +145,6 @@ func test1435(t *testing.T) {
|
||||
if syscall.Getuid() != 0 {
|
||||
t.Skip("skipping root only test")
|
||||
}
|
||||
if testing.Short() && testenv.Builder() != "" && os.Getenv("USER") == "swarming" {
|
||||
// The Go build system's swarming user is known not to be root.
|
||||
// Unfortunately, it sometimes appears as root due the current
|
||||
// implementation of a no-network check using 'unshare -n -r'.
|
||||
// Since this test does need root to work, we need to skip it.
|
||||
t.Skip("skipping root only test on a non-root builder")
|
||||
}
|
||||
if runtime.GOOS == "linux" {
|
||||
if _, err := os.Stat("/etc/alpine-release"); err == nil {
|
||||
t.Skip("skipping failing test on alpine - go.dev/issue/19938")
|
||||
|
||||
@@ -72,7 +72,7 @@ func test18146(t *testing.T) {
|
||||
}()
|
||||
}
|
||||
runtime.GOMAXPROCS(threads)
|
||||
argv := append(os.Args, "-test.run=^$")
|
||||
argv := append(os.Args, "-test.run=NoSuchTestExists")
|
||||
if err := syscall.Exec(os.Args[0], argv, os.Environ()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -85,7 +85,7 @@ func test18146(t *testing.T) {
|
||||
}
|
||||
}()
|
||||
|
||||
args := append(append([]string(nil), os.Args[1:]...), "-test.run=^Test18146$")
|
||||
args := append(append([]string(nil), os.Args[1:]...), "-test.run=Test18146")
|
||||
for n := attempts; n > 0; n-- {
|
||||
cmd := exec.Command(os.Args[0], args...)
|
||||
cmd.Env = append(os.Environ(), "test18146=exec")
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !windows && !static && !(darwin && internal)
|
||||
//go:build !windows && !static && (!darwin || (!internal_pie && !arm64))
|
||||
|
||||
#include <stdint.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
@@ -2,10 +2,11 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !windows && !static && !(darwin && internal)
|
||||
//go:build !windows && !static && (!darwin || (!internal_pie && !arm64))
|
||||
|
||||
// Excluded in darwin internal linking PIE (which is the default) mode,
|
||||
// as dynamic export is not supported.
|
||||
// Excluded in darwin internal linking PIE mode, as dynamic export is not
|
||||
// supported.
|
||||
// Excluded in internal linking mode on darwin/arm64, as it is always PIE.
|
||||
|
||||
package cgotest
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build windows || static || (darwin && internal)
|
||||
//go:build windows || static || (darwin && internal_pie) || (darwin && arm64)
|
||||
|
||||
package cgotest
|
||||
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#include <stdio.h>
|
||||
#include "issue4339.h"
|
||||
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
typedef struct Issue4339 Issue4339;
|
||||
|
||||
struct Issue4339 {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user