mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[dev.boringcrypto] all: merge master into dev.boringcrypto
Change-Id: Ia8ddd4e52dcfe87f9daef2edd37c8155fcae7f5a
This commit is contained in:
commit
4d1aa482b8
1291 changed files with 63258 additions and 17546 deletions
257
CONTRIBUTORS
257
CONTRIBUTORS
File diff suppressed because it is too large
Load diff
|
|
@ -362,17 +362,21 @@ pkg syscall (openbsd-386-cgo), const SYS_KILL = 37
|
||||||
pkg syscall (openbsd-amd64), const SYS_KILL = 37
|
pkg syscall (openbsd-amd64), const SYS_KILL = 37
|
||||||
pkg syscall (openbsd-amd64-cgo), const SYS_KILL = 37
|
pkg syscall (openbsd-amd64-cgo), const SYS_KILL = 37
|
||||||
pkg unicode, const Version = "9.0.0"
|
pkg unicode, const Version = "9.0.0"
|
||||||
|
pkg syscall (windows-386), const TOKEN_ALL_ACCESS = 983295
|
||||||
|
pkg syscall (windows-386), type AddrinfoW struct, Addr uintptr
|
||||||
pkg syscall (windows-386), type CertChainPolicyPara struct, ExtraPolicyPara uintptr
|
pkg syscall (windows-386), type CertChainPolicyPara struct, ExtraPolicyPara uintptr
|
||||||
pkg syscall (windows-386), type CertChainPolicyStatus struct, ExtraPolicyStatus uintptr
|
pkg syscall (windows-386), type CertChainPolicyStatus struct, ExtraPolicyStatus uintptr
|
||||||
pkg syscall (windows-386), type CertContext struct, CertInfo uintptr
|
pkg syscall (windows-386), type CertContext struct, CertInfo uintptr
|
||||||
pkg syscall (windows-386), type CertRevocationInfo struct, CrlInfo uintptr
|
pkg syscall (windows-386), type CertRevocationInfo struct, CrlInfo uintptr
|
||||||
pkg syscall (windows-386), type CertRevocationInfo struct, OidSpecificInfo uintptr
|
pkg syscall (windows-386), type CertRevocationInfo struct, OidSpecificInfo uintptr
|
||||||
pkg syscall (windows-386), type CertSimpleChain struct, TrustListInfo uintptr
|
pkg syscall (windows-386), type CertSimpleChain struct, TrustListInfo uintptr
|
||||||
pkg syscall (windows-386), const TOKEN_ALL_ACCESS = 983295
|
pkg syscall (windows-386), type RawSockaddrAny struct, Pad [96]int8
|
||||||
|
pkg syscall (windows-amd64), const TOKEN_ALL_ACCESS = 983295
|
||||||
|
pkg syscall (windows-amd64), type AddrinfoW struct, Addr uintptr
|
||||||
pkg syscall (windows-amd64), type CertChainPolicyPara struct, ExtraPolicyPara uintptr
|
pkg syscall (windows-amd64), type CertChainPolicyPara struct, ExtraPolicyPara uintptr
|
||||||
pkg syscall (windows-amd64), type CertChainPolicyStatus struct, ExtraPolicyStatus uintptr
|
pkg syscall (windows-amd64), type CertChainPolicyStatus struct, ExtraPolicyStatus uintptr
|
||||||
pkg syscall (windows-amd64), type CertContext struct, CertInfo uintptr
|
pkg syscall (windows-amd64), type CertContext struct, CertInfo uintptr
|
||||||
pkg syscall (windows-amd64), type CertRevocationInfo struct, CrlInfo uintptr
|
pkg syscall (windows-amd64), type CertRevocationInfo struct, CrlInfo uintptr
|
||||||
pkg syscall (windows-amd64), type CertRevocationInfo struct, OidSpecificInfo uintptr
|
pkg syscall (windows-amd64), type CertRevocationInfo struct, OidSpecificInfo uintptr
|
||||||
pkg syscall (windows-amd64), type CertSimpleChain struct, TrustListInfo uintptr
|
pkg syscall (windows-amd64), type CertSimpleChain struct, TrustListInfo uintptr
|
||||||
pkg syscall (windows-amd64), const TOKEN_ALL_ACCESS = 983295
|
pkg syscall (windows-amd64), type RawSockaddrAny struct, Pad [96]int8
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
pkg crypto/cipher, func NewGCMWithTagSize(Block, int) (AEAD, error)
|
pkg crypto/cipher, func NewGCMWithTagSize(Block, int) (AEAD, error)
|
||||||
pkg crypto/rsa, method (*PrivateKey) Size() int
|
pkg crypto/rsa, method (*PrivateKey) Size() int
|
||||||
pkg crypto/rsa, method (*PublicKey) Size() int
|
pkg crypto/rsa, method (*PublicKey) Size() int
|
||||||
pkg crypto/tls, type ConnectionState struct, ExportKeyingMaterial func(string, []uint8, int) ([]uint8, bool)
|
pkg crypto/tls, method (*ConnectionState) ExportKeyingMaterial(string, []uint8, int) ([]uint8, error)
|
||||||
pkg database/sql, method (IsolationLevel) String() string
|
pkg database/sql, method (IsolationLevel) String() string
|
||||||
pkg database/sql, type DBStats struct, Idle int
|
pkg database/sql, type DBStats struct, Idle int
|
||||||
pkg database/sql, type DBStats struct, InUse int
|
pkg database/sql, type DBStats struct, InUse int
|
||||||
|
|
@ -445,9 +445,20 @@ pkg net, method (*ListenConfig) ListenPacket(context.Context, string, string) (P
|
||||||
pkg net, type Dialer struct, Control func(string, string, syscall.RawConn) error
|
pkg net, type Dialer struct, Control func(string, string, syscall.RawConn) error
|
||||||
pkg net, type ListenConfig struct
|
pkg net, type ListenConfig struct
|
||||||
pkg net, type ListenConfig struct, Control func(string, string, syscall.RawConn) error
|
pkg net, type ListenConfig struct, Control func(string, string, syscall.RawConn) error
|
||||||
|
pkg net/http, const SameSiteDefaultMode = 1
|
||||||
|
pkg net/http, const SameSiteDefaultMode SameSite
|
||||||
|
pkg net/http, const SameSiteLaxMode = 2
|
||||||
|
pkg net/http, const SameSiteLaxMode SameSite
|
||||||
|
pkg net/http, const SameSiteStrictMode = 3
|
||||||
|
pkg net/http, const SameSiteStrictMode SameSite
|
||||||
pkg net/http, const StatusMisdirectedRequest = 421
|
pkg net/http, const StatusMisdirectedRequest = 421
|
||||||
pkg net/http, const StatusMisdirectedRequest ideal-int
|
pkg net/http, const StatusMisdirectedRequest ideal-int
|
||||||
|
pkg net/http, type Cookie struct, SameSite SameSite
|
||||||
|
pkg net/http, type SameSite int
|
||||||
|
pkg net/http, type Transport struct, MaxConnsPerHost int
|
||||||
pkg net/http/httptrace, type ClientTrace struct, Got1xxResponse func(int, textproto.MIMEHeader) error
|
pkg net/http/httptrace, type ClientTrace struct, Got1xxResponse func(int, textproto.MIMEHeader) error
|
||||||
|
pkg net/http/httptrace, type ClientTrace struct, WroteHeaderField func(string, []string)
|
||||||
|
pkg net/http/httputil, type ReverseProxy struct, ErrorHandler func(http.ResponseWriter, *http.Request, error)
|
||||||
pkg os, const ModeIrregular = 524288
|
pkg os, const ModeIrregular = 524288
|
||||||
pkg os, const ModeIrregular FileMode
|
pkg os, const ModeIrregular FileMode
|
||||||
pkg os, const ModeType = 2399666176
|
pkg os, const ModeType = 2399666176
|
||||||
|
|
@ -519,6 +530,7 @@ pkg syscall (openbsd-amd64-cgo), func Pipe2([]int, int) error
|
||||||
pkg syscall (windows-386), const TOKEN_ADJUST_SESSIONID = 256
|
pkg syscall (windows-386), const TOKEN_ADJUST_SESSIONID = 256
|
||||||
pkg syscall (windows-386), const TOKEN_ADJUST_SESSIONID ideal-int
|
pkg syscall (windows-386), const TOKEN_ADJUST_SESSIONID ideal-int
|
||||||
pkg syscall (windows-386), const TOKEN_ALL_ACCESS = 983551
|
pkg syscall (windows-386), const TOKEN_ALL_ACCESS = 983551
|
||||||
|
pkg syscall (windows-386), type AddrinfoW struct, Addr Pointer
|
||||||
pkg syscall (windows-386), type CertChainPolicyPara struct, ExtraPolicyPara Pointer
|
pkg syscall (windows-386), type CertChainPolicyPara struct, ExtraPolicyPara Pointer
|
||||||
pkg syscall (windows-386), type CertChainPolicyStatus struct, ExtraPolicyStatus Pointer
|
pkg syscall (windows-386), type CertChainPolicyStatus struct, ExtraPolicyStatus Pointer
|
||||||
pkg syscall (windows-386), type CertContext struct, CertInfo *CertInfo
|
pkg syscall (windows-386), type CertContext struct, CertInfo *CertInfo
|
||||||
|
|
@ -532,6 +544,7 @@ pkg syscall (windows-386), type Pointer *struct
|
||||||
pkg syscall (windows-amd64), const TOKEN_ADJUST_SESSIONID = 256
|
pkg syscall (windows-amd64), const TOKEN_ADJUST_SESSIONID = 256
|
||||||
pkg syscall (windows-amd64), const TOKEN_ADJUST_SESSIONID ideal-int
|
pkg syscall (windows-amd64), const TOKEN_ADJUST_SESSIONID ideal-int
|
||||||
pkg syscall (windows-amd64), const TOKEN_ALL_ACCESS = 983551
|
pkg syscall (windows-amd64), const TOKEN_ALL_ACCESS = 983551
|
||||||
|
pkg syscall (windows-amd64), type AddrinfoW struct, Addr Pointer
|
||||||
pkg syscall (windows-amd64), type CertChainPolicyPara struct, ExtraPolicyPara Pointer
|
pkg syscall (windows-amd64), type CertChainPolicyPara struct, ExtraPolicyPara Pointer
|
||||||
pkg syscall (windows-amd64), type CertChainPolicyStatus struct, ExtraPolicyStatus Pointer
|
pkg syscall (windows-amd64), type CertChainPolicyStatus struct, ExtraPolicyStatus Pointer
|
||||||
pkg syscall (windows-amd64), type CertContext struct, CertInfo *CertInfo
|
pkg syscall (windows-amd64), type CertContext struct, CertInfo *CertInfo
|
||||||
|
|
|
||||||
|
|
@ -44,18 +44,16 @@ control repositories.
|
||||||
<h3 id="Workspaces">Workspaces</h3>
|
<h3 id="Workspaces">Workspaces</h3>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
A workspace is a directory hierarchy with three directories at its root:
|
A workspace is a directory hierarchy with two directories at its root:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li><code>src</code> contains Go source files,
|
<li><code>src</code> contains Go source files, and
|
||||||
<li><code>pkg</code> contains package objects, and
|
|
||||||
<li><code>bin</code> contains executable commands.
|
<li><code>bin</code> contains executable commands.
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
The <code>go</code> tool builds source packages and installs the resulting
|
The <code>go</code> tool builds and installs binaries to the <code>bin</code> directory.
|
||||||
binaries to the <code>pkg</code> and <code>bin</code> directories.
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
@ -72,10 +70,6 @@ To give you an idea of how a workspace looks in practice, here's an example:
|
||||||
bin/
|
bin/
|
||||||
hello # command executable
|
hello # command executable
|
||||||
outyet # command executable
|
outyet # command executable
|
||||||
pkg/
|
|
||||||
linux_amd64/
|
|
||||||
github.com/golang/example/
|
|
||||||
stringutil.a # package object
|
|
||||||
src/
|
src/
|
||||||
<a href="https://github.com/golang/example/">github.com/golang/example/</a>
|
<a href="https://github.com/golang/example/">github.com/golang/example/</a>
|
||||||
.git/ # Git repository metadata
|
.git/ # Git repository metadata
|
||||||
|
|
@ -374,9 +368,8 @@ $ <b>go build</b>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
This won't produce an output file. To do that, you must use <code>go
|
This won't produce an output file.
|
||||||
install</code>, which places the package object inside the <code>pkg</code>
|
Instead it saves the compiled package in the local build cache.
|
||||||
directory of the workspace.
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
@ -400,19 +393,13 @@ func main() {
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Whenever the <code>go</code> tool installs a package or binary, it also
|
Install the <code>hello</code> program:
|
||||||
installs whatever dependencies it has.
|
|
||||||
So when you install the <code>hello</code> program
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
$ <b>go install github.com/user/hello</b>
|
$ <b>go install github.com/user/hello</b>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>
|
|
||||||
the <code>stringutil</code> package will be installed as well, automatically.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Running the new version of the program, you should see a new, reversed message:
|
Running the new version of the program, you should see a new, reversed message:
|
||||||
</p>
|
</p>
|
||||||
|
|
@ -429,10 +416,6 @@ After the steps above, your workspace should look like this:
|
||||||
<pre>
|
<pre>
|
||||||
bin/
|
bin/
|
||||||
hello # command executable
|
hello # command executable
|
||||||
pkg/
|
|
||||||
linux_amd64/ # this will reflect your OS and architecture
|
|
||||||
github.com/user/
|
|
||||||
stringutil.a # package object
|
|
||||||
src/
|
src/
|
||||||
github.com/user/
|
github.com/user/
|
||||||
hello/
|
hello/
|
||||||
|
|
@ -441,22 +424,6 @@ src/
|
||||||
reverse.go # package source
|
reverse.go # package source
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>
|
|
||||||
Note that <code>go install</code> placed the <code>stringutil.a</code> object
|
|
||||||
in a directory inside <code>pkg/linux_amd64</code> that mirrors its source
|
|
||||||
directory.
|
|
||||||
This is so that future invocations of the <code>go</code> tool can find the
|
|
||||||
package object and avoid recompiling the package unnecessarily.
|
|
||||||
The <code>linux_amd64</code> part is there to aid in cross-compilation,
|
|
||||||
and will reflect the operating system and architecture of your system.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Go command executables are statically linked; the package objects need not
|
|
||||||
be present to run Go programs.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
<h3 id="PackageNames">Package names</h3>
|
<h3 id="PackageNames">Package names</h3>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
@ -597,12 +564,6 @@ tree should now look like this:
|
||||||
<pre>
|
<pre>
|
||||||
bin/
|
bin/
|
||||||
hello # command executable
|
hello # command executable
|
||||||
pkg/
|
|
||||||
linux_amd64/
|
|
||||||
github.com/golang/example/
|
|
||||||
stringutil.a # package object
|
|
||||||
github.com/user/
|
|
||||||
stringutil.a # package object
|
|
||||||
src/
|
src/
|
||||||
github.com/golang/example/
|
github.com/golang/example/
|
||||||
.git/ # Git repository metadata
|
.git/ # Git repository metadata
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ $ go-contrib-init
|
||||||
<p>
|
<p>
|
||||||
The rest of this chapter elaborates on these instructions.
|
The rest of this chapter elaborates on these instructions.
|
||||||
If you have completed the steps above (either manually or through the tool), jump to
|
If you have completed the steps above (either manually or through the tool), jump to
|
||||||
<a href="#making_a_change">Making a change</a>.
|
<a href="#before_contributing">Before contributing code</a>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h3 id="google_account">Step 0: Select a Google Account</h3>
|
<h3 id="google_account">Step 0: Select a Google Account</h3>
|
||||||
|
|
@ -292,6 +292,25 @@ Most issues will be marked with one of the following workflow labels:
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
You can use GitHub's search functionality to find issues to help out with. Examples:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
Issues that need investigation: <a href="https://github.com/golang/go/issues?q=is%3Aissue+is%3Aopen+label%3ANeedsInvestigation"><code>is:issue is:open label:NeedsInvestigation</code></a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Issues that need a fix: <a href="https://github.com/golang/go/issues?q=is%3Aissue+is%3Aopen+label%3ANeedsFix"><code>is:issue is:open label:NeedsFix</code></a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Issues that need a fix and have a CL: <a href="https://github.com/golang/go/issues?q=is%3Aissue+is%3Aopen+label%3ANeedsFix+%22golang.org%2Fcl%22"><code>is:issue is:open label:NeedsFix "golang.org/cl"</code></a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Issues that need a fix and do not have a CL: <a href="https://github.com/golang/go/issues?q=is%3Aissue+is%3Aopen+label%3ANeedsFix+NOT+%22golang.org%2Fcl%22"><code>is:issue is:open label:NeedsFix NOT "golang.org/cl"</code></a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
<h3 id="design">Open an issue for any new problem</h3>
|
<h3 id="design">Open an issue for any new problem</h3>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
@ -386,7 +405,7 @@ This is an overview of the overall process:
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<b>Step 1:</b> Clone the Go source code from go.googlesource.com
|
<b>Step 1:</b> Clone the Go source code from <code>go.googlesource.com</code>
|
||||||
and make sure it's stable by compiling and testing it once:
|
and make sure it's stable by compiling and testing it once:
|
||||||
<pre>
|
<pre>
|
||||||
$ git clone https://go.googlesource.com/go
|
$ git clone https://go.googlesource.com/go
|
||||||
|
|
@ -450,12 +469,11 @@ In addition to a recent Go installation, you need to have a local copy of the so
|
||||||
checked out from the correct repository.
|
checked out from the correct repository.
|
||||||
You can check out the Go source repo onto your local file system anywhere
|
You can check out the Go source repo onto your local file system anywhere
|
||||||
you want as long as it's outside your <code>GOPATH</code>.
|
you want as long as it's outside your <code>GOPATH</code>.
|
||||||
Either clone from
|
Clone from <code>go.googlesource.com</code> (not GitHub):
|
||||||
<code>go.googlesource.com</code> or from GitHub:
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
$ git clone https://github.com/golang/go # or https://go.googlesource.com/go
|
$ git clone https://go.googlesource.com/go
|
||||||
$ cd go
|
$ cd go
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
@ -678,7 +696,7 @@ Don't use HTML, Markdown, or any other markup language.
|
||||||
<p>
|
<p>
|
||||||
Add any relevant information, such as benchmark data if the change
|
Add any relevant information, such as benchmark data if the change
|
||||||
affects performance.
|
affects performance.
|
||||||
The <a href="https://godoc.org/golang.org/x/tools/cmd/benchcmp">benchcmp</a>
|
The <a href="https://godoc.org/golang.org/x/perf/cmd/benchstat">benchstat</a>
|
||||||
tool is conventionally used to format
|
tool is conventionally used to format
|
||||||
benchmark data for change descriptions.
|
benchmark data for change descriptions.
|
||||||
</p>
|
</p>
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,13 @@ in supported releases as needed by issuing minor revisions
|
||||||
(for example, Go 1.6.1, Go 1.6.2, and so on).
|
(for example, Go 1.6.1, Go 1.6.2, and so on).
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<h2 id="go1.11">go1.11 (released 2018/08/24)</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Go 1.11 is a major release of Go.
|
||||||
|
Read the <a href="/doc/go1.11">Go 1.11 Release Notes</a> for more information.
|
||||||
|
</p>
|
||||||
|
|
||||||
<h2 id="go1.10">go1.10 (released 2018/02/16)</h2>
|
<h2 id="go1.10">go1.10 (released 2018/02/16)</h2>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
@ -57,6 +64,14 @@ See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.10.3">Go
|
||||||
1.10.3 milestone</a> on our issue tracker for details.
|
1.10.3 milestone</a> on our issue tracker for details.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
go1.10.4 (released 2018/08/24) includes fixes to the go command, linker, and the
|
||||||
|
<code>net/http</code>, <code>mime/multipart</code>, <code>ld/macho</code>,
|
||||||
|
<code>bytes</code>, and <code>strings</code> packages.
|
||||||
|
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.10.4">Go
|
||||||
|
1.10.4 milestone</a> on our issue tracker for details.
|
||||||
|
</p>
|
||||||
|
|
||||||
<h2 id="go1.9">go1.9 (released 2017/08/24)</h2>
|
<h2 id="go1.9">go1.9 (released 2017/08/24)</h2>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
|
||||||
772
doc/go1.11.html
772
doc/go1.11.html
|
|
@ -15,14 +15,7 @@ Do not send CLs removing the interior tags from such phrases.
|
||||||
ul li { margin: 0.5em 0; }
|
ul li { margin: 0.5em 0; }
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<h2 id="introduction">DRAFT RELEASE NOTES - Introduction to Go 1.11</h2>
|
<h2 id="introduction">Introduction to Go 1.11</h2>
|
||||||
|
|
||||||
<p>
|
|
||||||
<strong>
|
|
||||||
Go 1.11 is not yet released. These are work-in-progress
|
|
||||||
release notes. Go 1.11 is expected to be released in August 2018.
|
|
||||||
</strong>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
The latest Go release, version 1.11, arrives six months after <a href="go1.10">Go 1.10</a>.
|
The latest Go release, version 1.11, arrives six months after <a href="go1.10">Go 1.10</a>.
|
||||||
|
|
@ -39,10 +32,15 @@ Do not send CLs removing the interior tags from such phrases.
|
||||||
|
|
||||||
<h2 id="ports">Ports</h2>
|
<h2 id="ports">Ports</h2>
|
||||||
|
|
||||||
<p>
|
<p> <!-- CL 94255, CL 115038, etc -->
|
||||||
As <a href="go1.10#ports">announced in the Go 1.10 release notes</a>, Go 1.11 now requires
|
As <a href="go1.10#ports">announced in the Go 1.10 release notes</a>, Go 1.11 now requires
|
||||||
OpenBSD 6.2 or later, macOS 10.10 Yosemite or later, or Windows 7 or later;
|
OpenBSD 6.2 or later, macOS 10.10 Yosemite or later, or Windows 7 or later;
|
||||||
Support for previous versions of these operating systems has been removed.
|
support for previous versions of these operating systems has been removed.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p> <!-- CL 121657 -->
|
||||||
|
Go 1.11 supports the upcoming OpenBSD 6.4 release. Due to changes in
|
||||||
|
the OpenBSD kernel, older versions of Go will not work on OpenBSD 6.4.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
@ -50,21 +48,400 @@ Do not send CLs removing the interior tags from such phrases.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><!-- CL 107935 -->
|
<p><!-- CL 107935 -->
|
||||||
TODO: PPC64LE race detector support
|
The race detector is now supported on <code>linux/ppc64le</code>
|
||||||
|
and, to a lesser extent, on <code>netbsd/amd64</code>. The NetBSD race detector support
|
||||||
|
has <a href="https://golang.org/issue/26403">known issues</a>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h3 id="package-versioning">Package Versioning (vgo)</h3>
|
<p><!-- CL 109255 -->
|
||||||
<p>
|
The memory sanitizer (<code>-msan</code>) is now supported on <code>linux/arm64</code>.
|
||||||
<strong>
|
</p>
|
||||||
NOTE: This is not present in go1.11beta1 but will be available in future
|
|
||||||
betas and subsequent releases.
|
<p><!-- CL 93875 -->
|
||||||
</strong>
|
The build modes <code>c-shared</code> and <code>c-archive</code> are now supported on
|
||||||
Go 1.11 adds experimental, integrated support for package versioning.
|
<code>freebsd/amd64</code>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p id="mips"><!-- CL 108475 -->
|
||||||
|
On 64-bit MIPS systems, the new environment variable settings
|
||||||
|
<code>GOMIPS64=hardfloat</code> (the default) and
|
||||||
|
<code>GOMIPS64=softfloat</code> select whether to use
|
||||||
|
hardware instructions or software emulation for floating-point computations.
|
||||||
|
For 32-bit systems, the environment variable is still <code>GOMIPS</code>,
|
||||||
|
as <a href="go1.10#mips">added in Go 1.10</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 107475 -->
|
||||||
|
On soft-float ARM systems (<code>GOARM=5</code>), Go now uses a more
|
||||||
|
efficient software floating point interface. This is transparent to
|
||||||
|
Go code, but ARM assembly that uses floating-point instructions not
|
||||||
|
guarded on GOARM will break and must be ported to
|
||||||
|
the <a href="https://golang.org/cl/107475">new interface</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 94076 -->
|
||||||
|
Go 1.11 on ARMv7 no longer requires a Linux kernel configured
|
||||||
|
with <code>KUSER_HELPERS</code>. This setting is enabled in default
|
||||||
|
kernel configurations, but is sometimes disabled in stripped-down
|
||||||
|
configurations.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h3 id="wasm">WebAssembly</h3>
|
<h3 id="wasm">WebAssembly</h3>
|
||||||
<p>
|
<p>
|
||||||
Go 1.11 adds an experimental port to WebAssembly (<code>js/wasm</code>).
|
Go 1.11 adds an experimental port to <a href="https://webassembly.org">WebAssembly</a>
|
||||||
|
(<code>js/wasm</code>).
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Go programs currently compile to one WebAssembly module that
|
||||||
|
includes the Go runtime for goroutine scheduling, garbage
|
||||||
|
collection, maps, etc.
|
||||||
|
As a result, the resulting size is at minimum around
|
||||||
|
2 MB, or 500 KB compressed. Go programs can call into JavaScript
|
||||||
|
using the new experimental
|
||||||
|
<a href="/pkg/syscall/js/"><code>syscall/js</code></a> package.
|
||||||
|
Binary size and interop with other languages has not yet been a
|
||||||
|
priority but may be addressed in future releases.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
As a result of the addition of the new <code>GOOS</code> value
|
||||||
|
"<code>js</code>" and <code>GOARCH</code> value "<code>wasm</code>",
|
||||||
|
Go files named <code>*_js.go</code> or <code>*_wasm.go</code> will
|
||||||
|
now be <a href="/pkg/go/build/#hdr-Build_Constraints">ignored by Go
|
||||||
|
tools</a> except when those GOOS/GOARCH values are being used.
|
||||||
|
If you have existing filenames matching those patterns, you will need to rename them.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
More information can be found on the
|
||||||
|
<a href="https://golang.org/wiki/WebAssembly">WebAssembly wiki page</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="riscv">RISC-V GOARCH values reserved</h3>
|
||||||
|
<p><!-- CL 106256 -->
|
||||||
|
The main Go compiler does not yet support the RISC-V architecture <!-- is gonna change everything -->
|
||||||
|
but we've reserved the <code>GOARCH</code> values
|
||||||
|
"<code>riscv</code>" and "<code>riscv64</code>", as used by Gccgo,
|
||||||
|
which does support RISC-V. This means that Go files
|
||||||
|
named <code>*_riscv.go</code> will now also
|
||||||
|
be <a href="/pkg/go/build/#hdr-Build_Constraints">ignored by Go
|
||||||
|
tools</a> except when those GOOS/GOARCH values are being used.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 id="tools">Tools</h2>
|
||||||
|
|
||||||
|
<h3 id="modules">Modules, package versioning, and dependency management</h3>
|
||||||
|
<p>
|
||||||
|
Go 1.11 adds preliminary support for a <a href="/cmd/go/#hdr-Modules__module_versions__and_more">new concept called “modules,”</a>
|
||||||
|
an alternative to GOPATH with integrated support for versioning and
|
||||||
|
package distribution.
|
||||||
|
Using modules, developers are no longer confined to working inside GOPATH,
|
||||||
|
version dependency information is explicit yet lightweight,
|
||||||
|
and builds are more reliable and reproducible.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Module support is considered experimental.
|
||||||
|
Details are likely to change in response to feedback from Go 1.11 users,
|
||||||
|
and we have more tools planned.
|
||||||
|
Although the details of module support may change, projects that convert
|
||||||
|
to modules using Go 1.11 will continue to work with Go 1.12 and later.
|
||||||
|
If you encounter bugs using modules,
|
||||||
|
please <a href="https://golang.org/issue/new">file issues</a>
|
||||||
|
so we can fix them. For more information, see the
|
||||||
|
<a href="/cmd/go#hdr-Modules__module_versions__and_more"><code>go</code> command documentation</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="importpath">Import path restriction</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Because Go module support assigns special meaning to the
|
||||||
|
<code>@</code> symbol in command line operations,
|
||||||
|
the <code>go</code> command now disallows the use of
|
||||||
|
import paths containing <code>@</code> symbols.
|
||||||
|
Such import paths were never allowed by <code>go</code> <code>get</code>,
|
||||||
|
so this restriction can only affect users building
|
||||||
|
custom GOPATH trees by other means.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="gopackages">Package loading</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The new package
|
||||||
|
<a href="https://godoc.org/golang.org/x/tools/go/packages"><code>golang.org/x/tools/go/packages</code></a>
|
||||||
|
provides a simple API for locating and loading packages of Go source code.
|
||||||
|
Although not yet part of the standard library, for many tasks it
|
||||||
|
effectively replaces the <a href="/pkg/go/build"><code>go/build</code></a>
|
||||||
|
package, whose API is unable to fully support modules.
|
||||||
|
Because it runs an external query command such as
|
||||||
|
<a href="/cmd/go/#hdr-List_packages"><code>go list</code></a>
|
||||||
|
to obtain information about Go packages, it enables the construction of
|
||||||
|
analysis tools that work equally well with alternative build systems
|
||||||
|
such as <a href="https://bazel.build">Bazel</a>
|
||||||
|
and <a href="https://buckbuild.com">Buck</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="gocache">Build cache requirement</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Go 1.11 will be the last release to support setting the environment
|
||||||
|
variable <code>GOCACHE=off</code> to disable the
|
||||||
|
<a href="/cmd/go/#hdr-Build_and_test_caching">build cache</a>,
|
||||||
|
introduced in Go 1.10.
|
||||||
|
Starting in Go 1.12, the build cache will be required,
|
||||||
|
as a step toward eliminating <code>$GOPATH/pkg</code>.
|
||||||
|
The module and package loading support described above
|
||||||
|
already require that the build cache be enabled.
|
||||||
|
If you have disabled the build cache to avoid problems you encountered,
|
||||||
|
please <a href="https://golang.org/issue/new">file an issue</a> to let us know about them.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="compiler">Compiler toolchain</h3>
|
||||||
|
|
||||||
|
<p><!-- CL 109918 -->
|
||||||
|
More functions are now eligible for inlining by default, including
|
||||||
|
functions that call <code>panic</code>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 97375 -->
|
||||||
|
The compiler toolchain now supports column information
|
||||||
|
in <a href="/cmd/compile/#hdr-Compiler_Directives">line
|
||||||
|
directives</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 106797 -->
|
||||||
|
A new package export data format has been introduced.
|
||||||
|
This should be transparent to end users, except for speeding up
|
||||||
|
build times for large Go projects.
|
||||||
|
If it does cause problems, it can be turned off again by
|
||||||
|
passing <code>-gcflags=all=-iexport=false</code> to
|
||||||
|
the <code>go</code> tool when building a binary.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 100459 -->
|
||||||
|
The compiler now rejects unused variables declared in a type switch
|
||||||
|
guard, such as <code>x</code> in the following example:
|
||||||
|
</p>
|
||||||
|
<pre>
|
||||||
|
func f(v interface{}) {
|
||||||
|
switch x := v.(type) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
This was already rejected by both <code>gccgo</code>
|
||||||
|
and <a href="/pkg/go/types/">go/types</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="assembler">Assembler</h3>
|
||||||
|
|
||||||
|
<p><!-- CL 113315 -->
|
||||||
|
The assembler for <code>amd64</code> now accepts AVX512 instructions.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="debugging">Debugging</h3>
|
||||||
|
|
||||||
|
<p><!-- CL 100738, CL 93664 -->
|
||||||
|
The compiler now produces significantly more accurate debug
|
||||||
|
information for optimized binaries, including variable location
|
||||||
|
information, line numbers, and breakpoint locations.
|
||||||
|
|
||||||
|
This should make it possible to debug binaries
|
||||||
|
compiled <em>without</em> <code>-N</code> <code>-l</code>.
|
||||||
|
|
||||||
|
There are still limitations to the quality of the debug information,
|
||||||
|
some of which are fundamental, and some of which will continue to
|
||||||
|
improve with future releases.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 118276 -->
|
||||||
|
DWARF sections are now compressed by default because of the expanded
|
||||||
|
and more accurate debug information produced by the compiler.
|
||||||
|
|
||||||
|
This is transparent to most ELF tools (such as debuggers on Linux
|
||||||
|
and *BSD) and is supported by the Delve debugger on all platforms,
|
||||||
|
but has limited support in the native tools on macOS and Windows.
|
||||||
|
|
||||||
|
To disable DWARF compression,
|
||||||
|
pass <code>-ldflags=-compressdwarf=false</code> to
|
||||||
|
the <code>go</code> tool when building a binary.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 109699 -->
|
||||||
|
Go 1.11 adds experimental support for calling Go functions from
|
||||||
|
within a debugger.
|
||||||
|
|
||||||
|
This is useful, for example, to call <code>String</code> methods
|
||||||
|
when paused at a breakpoint.
|
||||||
|
|
||||||
|
This is currently only supported by Delve (version 1.1.0 and up).
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="test">Test</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Since Go 1.10, the <code>go</code> <code>test</code> command runs
|
||||||
|
<code>go</code> <code>vet</code> on the package being tested,
|
||||||
|
to identify problems before running the test. Since <code>vet</code>
|
||||||
|
typechecks the code with <a href="/pkg/go/types/">go/types</a>
|
||||||
|
before running, tests that do not typecheck will now fail.
|
||||||
|
|
||||||
|
In particular, tests that contain an unused variable inside a
|
||||||
|
closure compiled with Go 1.10, because the Go compiler incorrectly
|
||||||
|
accepted them (<a href="https://golang.org/issues/3059">Issue #3059</a>),
|
||||||
|
but will now fail, since <code>go/types</code> correctly reports an
|
||||||
|
"unused variable" error in this case.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 102696 -->
|
||||||
|
The <code>-memprofile</code> flag
|
||||||
|
to <code>go</code> <code>test</code> now defaults to the
|
||||||
|
"allocs" profile, which records the total bytes allocated since the
|
||||||
|
test began (including garbage-collected bytes).
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="vet">Vet</h3>
|
||||||
|
|
||||||
|
<p><!-- CL 108555 -->
|
||||||
|
The <a href="/cmd/vet/"><code>go</code> <code>vet</code></a>
|
||||||
|
command now reports a fatal error when the package under analysis
|
||||||
|
does not typecheck. Previously, a type checking error simply caused
|
||||||
|
a warning to be printed, and <code>vet</code> to exit with status 1.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 108559 -->
|
||||||
|
Additionally, <a href="/cmd/vet"><code>go</code> <code>vet</code></a>
|
||||||
|
has become more robust when format-checking <code>printf</code> wrappers.
|
||||||
|
Vet now detects the mistake in this example:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
func wrapper(s string, args ...interface{}) {
|
||||||
|
fmt.Printf(s, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
wrapper("%s", 42)
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<h3 id="trace">Trace</h3>
|
||||||
|
|
||||||
|
<p><!-- CL 63274 -->
|
||||||
|
With the new <code>runtime/trace</code>
|
||||||
|
package's <a href="/pkg/runtime/trace/#hdr-User_annotation">user
|
||||||
|
annotation API</a>, users can record application-level information
|
||||||
|
in execution traces and create groups of related goroutines.
|
||||||
|
The <code>go</code> <code>tool</code> <code>trace</code>
|
||||||
|
command visualizes this information in the trace view and the new
|
||||||
|
user task/region analysis page.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="cgo">Cgo</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Since Go 1.10, cgo has translated some C pointer types to the Go
|
||||||
|
type <code>uintptr</code>. These types include
|
||||||
|
the <code>CFTypeRef</code> hierarchy in Darwin's CoreFoundation
|
||||||
|
framework and the <code>jobject</code> hierarchy in Java's JNI
|
||||||
|
interface. In Go 1.11, several improvements have been made to the code
|
||||||
|
that detects these types. Code that uses these types may need some
|
||||||
|
updating. See the <a href="go1.10.html#cgo">Go 1.10 release notes</a> for
|
||||||
|
details. <!-- CL 126275, CL 127156, CL 122217, CL 122575, CL 123177 -->
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="godoc">Godoc</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Go 1.11 will be the last release to support <code>godoc</code>'s command-line interface.
|
||||||
|
In future releases, <code>godoc</code> will only be a web server. Users should use
|
||||||
|
<code>go</code> <code>doc</code> for command-line help output instead.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 85396, CL 124495 -->
|
||||||
|
The <code>godoc</code> web server now shows which version of Go introduced
|
||||||
|
new API features. The initial Go version of types, funcs, and methods are shown
|
||||||
|
right-aligned. For example, see <a href="/pkg/os/#UserCacheDir"><code>UserCacheDir</code></a>, with "1.11"
|
||||||
|
on the right side. For struct fields, inline comments are added when the struct field was
|
||||||
|
added in a Go version other than when the type itself was introduced.
|
||||||
|
For a struct field example, see
|
||||||
|
<a href="/pkg/net/http/httptrace/#ClientTrace.Got1xxResponse"><code>ClientTrace.Got1xxResponse</code></a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="gofmt">Gofmt</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
One minor detail of the default formatting of Go source code has changed.
|
||||||
|
When formatting expression lists with inline comments, the comments were
|
||||||
|
aligned according to a heuristic.
|
||||||
|
However, in some cases the alignment would be split up too easily, or
|
||||||
|
introduce too much whitespace.
|
||||||
|
The heuristic has been changed to behave better for human-written code.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Note that these kinds of minor updates to gofmt are expected from time to
|
||||||
|
time.
|
||||||
|
In general, systems that need consistent formatting of Go source code should
|
||||||
|
use a specific version of the <code>gofmt</code> binary.
|
||||||
|
See the <a href="/pkg/go/format/">go/format</a> package documentation for more
|
||||||
|
information.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 id="runtime">Runtime</h2>
|
||||||
|
|
||||||
|
<p><!-- CL 85887 -->
|
||||||
|
The runtime now uses a sparse heap layout so there is no longer a
|
||||||
|
limit to the size of the Go heap (previously, the limit was 512GiB).
|
||||||
|
This also fixes rare "address space conflict" failures in mixed Go/C
|
||||||
|
binaries or binaries compiled with <code>-race</code>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 108679, CL 106156 -->
|
||||||
|
On macOS and iOS, the runtime now uses <code>libSystem.dylib</code> instead of
|
||||||
|
calling the kernel directly. This should make Go binaries more
|
||||||
|
compatible with future versions of macOS and iOS.
|
||||||
|
The <a href="/pkg/syscall">syscall</a> package still makes direct
|
||||||
|
system calls; fixing this is planned for a future release.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 id="performance">Performance</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
As always, the changes are so general and varied that precise
|
||||||
|
statements about performance are difficult to make. Most programs
|
||||||
|
should run a bit faster, due to better generated code and
|
||||||
|
optimizations in the core library.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 74851 -->
|
||||||
|
There were multiple performance changes to the <code>math/big</code>
|
||||||
|
package as well as many changes across the tree specific to <code>GOARCH=arm64</code>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="performance-compiler">Compiler toolchain</h3>
|
||||||
|
|
||||||
|
<p><!-- CL 110055 -->
|
||||||
|
The compiler now optimizes map clearing operations of the form:
|
||||||
|
</p>
|
||||||
|
<pre>
|
||||||
|
for k := range m {
|
||||||
|
delete(m, k)
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p><!-- CL 109517 -->
|
||||||
|
The compiler now optimizes slice extension of the form
|
||||||
|
<code>append(s,</code> <code>make([]T,</code> <code>n)...)</code>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 100277, CL 105635, CL 109776 -->
|
||||||
|
The compiler now performs significantly more aggressive bounds-check
|
||||||
|
and branch elimination. Notably, it now recognizes transitive
|
||||||
|
relations, so if <code>i<j</code> and <code>j<len(s)</code>,
|
||||||
|
it can use these facts to eliminate the bounds check
|
||||||
|
for <code>s[i]</code>. It also understands simple arithmetic such
|
||||||
|
as <code>s[i-10]</code> and can recognize more inductive cases in
|
||||||
|
loops. Furthermore, the compiler now uses bounds information to more
|
||||||
|
aggressively optimize shift operations.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2 id="library">Core library</h2>
|
<h2 id="library">Core library</h2>
|
||||||
|
|
@ -81,34 +458,19 @@ Do not send CLs removing the interior tags from such phrases.
|
||||||
in mind.
|
in mind.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<!-- CL 113315: https://golang.org/cl/113315: cmd/asm: enable AVX512 -->
|
<!-- CL 115095: https://golang.org/cl/115095: yes (`go test pkg` now always builds pkg even if there are no test files): cmd/go: output coverage report even if there are no test files -->
|
||||||
<!-- CL 100459: https://golang.org/cl/100459: cmd/compile: reject type switch with guarded declaration and no cases -->
|
|
||||||
<!-- CL 106797: https://golang.org/cl/106797: cmd/compile: enable indexed export format by default -->
|
|
||||||
<!-- CL 108475: https://golang.org/cl/108475: cmd/compile: add softfloat support to mips64{,le} -->
|
|
||||||
<!-- CL 97375: https://golang.org/cl/97375: cmd/compile, cmd/compile/internal/syntax: print relative column info -->
|
|
||||||
<!-- CL 110395: https://golang.org/cl/110395: cmd/go, cmd/compile: use Windows response files to avoid arg length limits -->
|
<!-- CL 110395: https://golang.org/cl/110395: cmd/go, cmd/compile: use Windows response files to avoid arg length limits -->
|
||||||
<!-- CL 107475: https://golang.org/cl/107475: cmd/internal/obj/arm, runtime: delete old ARM softfloat code -->
|
|
||||||
<!-- CL 112436: https://golang.org/cl/112436: cmd/pprof: add readline support similar to upstream -->
|
<!-- CL 112436: https://golang.org/cl/112436: cmd/pprof: add readline support similar to upstream -->
|
||||||
<dl id="all"><dt><a href="/pkg/all/">all</a></dt>
|
|
||||||
<dd>
|
|
||||||
<p><!-- CL 93875 -->
|
|
||||||
TODO: <a href="https://golang.org/cl/93875">https://golang.org/cl/93875</a>: enable c-shared/c-archive support for freebsd/amd64
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p><!-- CL 94255 -->
|
|
||||||
TODO: <a href="https://golang.org/cl/94255">https://golang.org/cl/94255</a>: drop support for Windows Vista or below (Windows XP)
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p><!-- CL 115038 -->
|
|
||||||
TODO: <a href="https://golang.org/cl/115038">https://golang.org/cl/115038</a>: remove support for macOS 10.9 and earlier
|
|
||||||
</p>
|
|
||||||
|
|
||||||
</dl><!-- all -->
|
|
||||||
|
|
||||||
<dl id="crypto"><dt><a href="/pkg/crypto/">crypto</a></dt>
|
<dl id="crypto"><dt><a href="/pkg/crypto/">crypto</a></dt>
|
||||||
<dd>
|
<dd>
|
||||||
<p><!-- CL 64451 -->
|
<p><!-- CL 64451 -->
|
||||||
TODO: <a href="https://golang.org/cl/64451">https://golang.org/cl/64451</a>: randomly read an extra byte of randomness in some places.
|
Certain crypto operations, including
|
||||||
|
<a href="/pkg/crypto/ecdsa/#Sign"><code>ecdsa.Sign</code></a>,
|
||||||
|
<a href="/pkg/crypto/rsa/#EncryptPKCS1v15"><code>rsa.EncryptPKCS1v15</code></a> and
|
||||||
|
<a href="/pkg/crypto/rsa/#GenerateKey"><code>rsa.GenerateKey</code></a>,
|
||||||
|
now randomly read an extra byte of randomness to ensure tests don't rely on internal behavior.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</dl><!-- crypto -->
|
</dl><!-- crypto -->
|
||||||
|
|
@ -116,7 +478,8 @@ Do not send CLs removing the interior tags from such phrases.
|
||||||
<dl id="crypto/cipher"><dt><a href="/pkg/crypto/cipher/">crypto/cipher</a></dt>
|
<dl id="crypto/cipher"><dt><a href="/pkg/crypto/cipher/">crypto/cipher</a></dt>
|
||||||
<dd>
|
<dd>
|
||||||
<p><!-- CL 48510, CL 116435 -->
|
<p><!-- CL 48510, CL 116435 -->
|
||||||
TODO: <a href="https://golang.org/cl/48510">https://golang.org/cl/48510</a>: add NewGCMWithTagSize for custom tag sizes.
|
The new function <a href="/pkg/crypto/cipher/#NewGCMWithTagSize"><code>NewGCMWithTagSize</code></a>
|
||||||
|
implements Galois Counter Mode with non-standard tag lengths for compatibility with existing cryptosystems.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</dl><!-- crypto/cipher -->
|
</dl><!-- crypto/cipher -->
|
||||||
|
|
@ -124,15 +487,55 @@ Do not send CLs removing the interior tags from such phrases.
|
||||||
<dl id="crypto/rsa"><dt><a href="/pkg/crypto/rsa/">crypto/rsa</a></dt>
|
<dl id="crypto/rsa"><dt><a href="/pkg/crypto/rsa/">crypto/rsa</a></dt>
|
||||||
<dd>
|
<dd>
|
||||||
<p><!-- CL 103876 -->
|
<p><!-- CL 103876 -->
|
||||||
TODO: <a href="https://golang.org/cl/103876">https://golang.org/cl/103876</a>: add PublicKey.Size accessor
|
<a href="/pkg/crypto/rsa/#PublicKey"><code>PublicKey</code></a> now implements a
|
||||||
|
<a href="/pkg/crypto/rsa/#PublicKey.Size"><code>Size</code></a> method that
|
||||||
|
returns the modulus size in bytes.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</dl><!-- crypto/rsa -->
|
</dl><!-- crypto/rsa -->
|
||||||
|
|
||||||
|
<dl id="crypto/tls"><dt><a href="/pkg/crypto/tls/">crypto/tls</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 85115 -->
|
||||||
|
<a href="/pkg/crypto/tls/#ConnectionState"><code>ConnectionState</code></a>'s new
|
||||||
|
<a href="/pkg/crypto/tls/#ConnectionState.ExportKeyingMaterial"><code>ExportKeyingMaterial</code></a>
|
||||||
|
method allows exporting keying material bound to the
|
||||||
|
connection according to RFC 5705.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</dl><!-- crypto/tls -->
|
||||||
|
|
||||||
|
<dl id="crypto/x509"><dt><a href="/pkg/crypto/x509/">crypto/x509</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 123355, CL 123695 -->
|
||||||
|
The deprecated, legacy behavior of treating the <code>CommonName</code> field as
|
||||||
|
a hostname when no Subject Alternative Names are present is now disabled when the CN is not a
|
||||||
|
valid hostname.
|
||||||
|
The <code>CommonName</code> can be completely ignored by adding the experimental value
|
||||||
|
<code>x509ignoreCN=1</code> to the <code>GODEBUG</code> environment variable.
|
||||||
|
When the CN is ignored, certificates without SANs validate under chains with name constraints
|
||||||
|
instead of returning <code>NameConstraintsWithoutSANs</code>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 113475 -->
|
||||||
|
Extended key usage restrictions are again checked only if they appear in the <code>KeyUsages</code>
|
||||||
|
field of <a href="/pkg/crypto/x509/#VerifyOptions"><code>VerifyOptions</code></a>, instead of always being checked.
|
||||||
|
This matches the behavior of Go 1.9 and earlier.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 102699 -->
|
||||||
|
The value returned by <a href="/pkg/crypto/x509/#SystemCertPool"><code>SystemCertPool</code></a>
|
||||||
|
is now cached and might not reflect system changes between invocations.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</dl><!-- crypto/x509 -->
|
||||||
|
|
||||||
<dl id="debug/elf"><dt><a href="/pkg/debug/elf/">debug/elf</a></dt>
|
<dl id="debug/elf"><dt><a href="/pkg/debug/elf/">debug/elf</a></dt>
|
||||||
<dd>
|
<dd>
|
||||||
<p><!-- CL 112115 -->
|
<p><!-- CL 112115 -->
|
||||||
TODO: <a href="https://golang.org/cl/112115">https://golang.org/cl/112115</a>: add machine and OSABI constants
|
More <a href="/pkg/debug/elf/#ELFOSABI_NONE"><code>ELFOSABI</code></a>
|
||||||
|
and <a href="/pkg/debug/elf/#EM_NONE"><code>EM</code></a>
|
||||||
|
constants have been added.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</dl><!-- debug/elf -->
|
</dl><!-- debug/elf -->
|
||||||
|
|
@ -140,7 +543,8 @@ Do not send CLs removing the interior tags from such phrases.
|
||||||
<dl id="encoding/asn1"><dt><a href="/pkg/encoding/asn1/">encoding/asn1</a></dt>
|
<dl id="encoding/asn1"><dt><a href="/pkg/encoding/asn1/">encoding/asn1</a></dt>
|
||||||
<dd>
|
<dd>
|
||||||
<p><!-- CL 110561 -->
|
<p><!-- CL 110561 -->
|
||||||
TODO: <a href="https://golang.org/cl/110561">https://golang.org/cl/110561</a>: allow Marshaling and Unmarshaling private tag class
|
<code>Marshal</code> and <code><a href="/pkg/encoding/asn1/#Unmarshal">Unmarshal</a></code>
|
||||||
|
now support "private" class annotations for fields.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</dl><!-- encoding/asn1 -->
|
</dl><!-- encoding/asn1 -->
|
||||||
|
|
@ -148,7 +552,10 @@ Do not send CLs removing the interior tags from such phrases.
|
||||||
<dl id="encoding/base32"><dt><a href="/pkg/encoding/base32/">encoding/base32</a></dt>
|
<dl id="encoding/base32"><dt><a href="/pkg/encoding/base32/">encoding/base32</a></dt>
|
||||||
<dd>
|
<dd>
|
||||||
<p><!-- CL 112516 -->
|
<p><!-- CL 112516 -->
|
||||||
TODO: <a href="https://golang.org/cl/112516">https://golang.org/cl/112516</a>: handle surplus padding consistently
|
The decoder now consistently
|
||||||
|
returns <code>io.ErrUnexpectedEOF</code> for an incomplete
|
||||||
|
chunk. Previously it would return <code>io.EOF</code> in some
|
||||||
|
cases.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</dl><!-- encoding/base32 -->
|
</dl><!-- encoding/base32 -->
|
||||||
|
|
@ -156,23 +563,34 @@ Do not send CLs removing the interior tags from such phrases.
|
||||||
<dl id="encoding/csv"><dt><a href="/pkg/encoding/csv/">encoding/csv</a></dt>
|
<dl id="encoding/csv"><dt><a href="/pkg/encoding/csv/">encoding/csv</a></dt>
|
||||||
<dd>
|
<dd>
|
||||||
<p><!-- CL 99696 -->
|
<p><!-- CL 99696 -->
|
||||||
TODO: <a href="https://golang.org/cl/99696">https://golang.org/cl/99696</a>: disallow quote for use as Comma
|
The <code>Reader</code> now rejects attempts to set
|
||||||
|
the <a href="/pkg/encoding/csv/#Reader.Comma"><code>Comma</code></a>
|
||||||
|
field to a double-quote character, as double-quote characters
|
||||||
|
already have a special meaning in CSV.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</dl><!-- encoding/csv -->
|
</dl><!-- encoding/csv -->
|
||||||
|
|
||||||
<dl id="go/build, runtime/internal/sys"><dt><a href="/pkg/go/build, runtime/internal/sys/">go/build, runtime/internal/sys</a></dt>
|
<!-- CL 100235 was reverted -->
|
||||||
|
|
||||||
|
<dl id="html/template"><dt><a href="/pkg/html/template/">html/template</a></dt>
|
||||||
<dd>
|
<dd>
|
||||||
<p><!-- CL 106256 -->
|
<p><!-- CL 121815 -->
|
||||||
TODO: <a href="https://golang.org/cl/106256">https://golang.org/cl/106256</a>: reserve RISC-V arch names
|
The package has changed its behavior when a typed interface
|
||||||
|
value is passed to an implicit escaper function. Previously such
|
||||||
|
a value was written out as (an escaped form)
|
||||||
|
of <code><nil></code>. Now such values are ignored, just
|
||||||
|
as an untyped <code>nil</code> value is (and always has been)
|
||||||
|
ignored.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</dl><!-- go/build, runtime/internal/sys -->
|
</dl><!-- html/template -->
|
||||||
|
|
||||||
<dl id="image/gif"><dt><a href="/pkg/image/gif/">image/gif</a></dt>
|
<dl id="image/gif"><dt><a href="/pkg/image/gif/">image/gif</a></dt>
|
||||||
<dd>
|
<dd>
|
||||||
<p><!-- CL 93076 -->
|
<p><!-- CL 93076 -->
|
||||||
TODO: <a href="https://golang.org/cl/93076">https://golang.org/cl/93076</a>: support non-looping animated gifs (LoopCount=-1)
|
Non-looping animated GIFs are now supported. They are denoted by having a
|
||||||
|
<code><a href="/pkg/image/gif/#GIF.LoopCount">LoopCount</a></code> of -1.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</dl><!-- image/gif -->
|
</dl><!-- image/gif -->
|
||||||
|
|
@ -180,67 +598,182 @@ Do not send CLs removing the interior tags from such phrases.
|
||||||
<dl id="io/ioutil"><dt><a href="/pkg/io/ioutil/">io/ioutil</a></dt>
|
<dl id="io/ioutil"><dt><a href="/pkg/io/ioutil/">io/ioutil</a></dt>
|
||||||
<dd>
|
<dd>
|
||||||
<p><!-- CL 105675 -->
|
<p><!-- CL 105675 -->
|
||||||
TODO: <a href="https://golang.org/cl/105675">https://golang.org/cl/105675</a>: change TempFile prefix to a pattern
|
The <code><a href="/pkg/io/ioutil/#TempFile">TempFile</a></code>
|
||||||
|
function now supports specifying where the random characters in
|
||||||
|
the filename are placed. If the <code>prefix</code> argument
|
||||||
|
includes a "<code>*</code>", the random string replaces the
|
||||||
|
"<code>*</code>". For example, a <code>prefix</code> argument of "<code>myname.*.bat</code>" will
|
||||||
|
result in a random filename such as
|
||||||
|
"<code>myname.123456.bat</code>". If no "<code>*</code>" is
|
||||||
|
included the old behavior is retained, and the random digits are
|
||||||
|
appended to the end.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</dl><!-- io/ioutil -->
|
</dl><!-- io/ioutil -->
|
||||||
|
|
||||||
<dl id="math/big"><dt><a href="/pkg/math/big/">math/big</a></dt>
|
<dl id="math/big"><dt><a href="/pkg/math/big/">math/big</a></dt>
|
||||||
<dd>
|
<dd>
|
||||||
<p><!-- CL 74851 -->
|
|
||||||
TODO: <a href="https://golang.org/cl/74851">https://golang.org/cl/74851</a>: speed-up addMulVVW on amd64
|
<p><!-- CL 108996 -->
|
||||||
|
<a href="/pkg/math/big/#Int.ModInverse"><code>ModInverse</code></a> now returns nil when g and n are not relatively prime. The result was previously undefined.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</dl><!-- math/big -->
|
</dl><!-- math/big -->
|
||||||
|
|
||||||
|
<dl id="mime/multipart"><dt><a href="/pkg/mime/multipart/">mime/multipart</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 121055 -->
|
||||||
|
The handling of form-data with missing/empty file names has been
|
||||||
|
restored to the behavior in Go 1.9: in the
|
||||||
|
<a href="/pkg/mime/multipart/#Form"><code>Form</code></a> for
|
||||||
|
the form-data part the value is available in
|
||||||
|
the <code>Value</code> field rather than the <code>File</code>
|
||||||
|
field. In Go releases 1.10 through 1.10.3 a form-data part with
|
||||||
|
a missing/empty file name and a non-empty "Content-Type" field
|
||||||
|
was stored in the <code>File</code> field. This change was a
|
||||||
|
mistake in 1.10 and has been reverted to the 1.9 behavior.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</dl><!-- mime/multipart -->
|
||||||
|
|
||||||
|
<dl id="mime/quotedprintable"><dt><a href="/pkg/mime/quotedprintable/">mime/quotedprintable</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 121095 -->
|
||||||
|
To support invalid input found in the wild, the package now
|
||||||
|
permits non-ASCII bytes but does not validate their encoding.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</dl><!-- mime/quotedprintable -->
|
||||||
|
|
||||||
<dl id="net"><dt><a href="/pkg/net/">net</a></dt>
|
<dl id="net"><dt><a href="/pkg/net/">net</a></dt>
|
||||||
<dd>
|
<dd>
|
||||||
<p><!-- CL 72810 -->
|
<p><!-- CL 72810 -->
|
||||||
TODO: <a href="https://golang.org/cl/72810">https://golang.org/cl/72810</a>: add ListenConfig, Dialer.Control to permit socket opts before listen/dial
|
The new <a href="/pkg/net/#ListenConfig"><code>ListenConfig</code></a> type and the new
|
||||||
|
<a href="/pkg/net/#Dialer.Control"><code>Dialer.Control</code></a> field permit
|
||||||
|
setting socket options before accepting and creating connections, respectively.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><!-- CL 76391 -->
|
<p><!-- CL 76391 -->
|
||||||
TODO: <a href="https://golang.org/cl/76391">https://golang.org/cl/76391</a>: implement (*syscall.RawConn).Read/Write on Windows
|
The <a href="/pkg/syscall/#RawConn"><code>syscall.RawConn</code></a> <code>Read</code>
|
||||||
|
and <code>Write</code> methods now work correctly on Windows.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><!-- CL 107715 -->
|
<p><!-- CL 107715 -->
|
||||||
TODO: <a href="https://golang.org/cl/107715">https://golang.org/cl/107715</a>: add support for splice(2) in (*TCPConn).ReadFrom on Linux
|
The <code>net</code> package now automatically uses the
|
||||||
|
<a href="http://man7.org/linux/man-pages/man2/splice.2.html"><code>splice</code> system call</a>
|
||||||
|
on Linux when copying data between TCP connections in
|
||||||
|
<a href="/pkg/net/#TCPConn.ReadFrom"><code>TCPConn.ReadFrom</code></a>, as called by
|
||||||
|
<a href="/pkg/io/#Copy"><code>io.Copy</code></a>. The result is faster, more efficient TCP proxying.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><!-- CL 108297 -->
|
<p><!-- CL 108297 -->
|
||||||
TODO: <a href="https://golang.org/cl/108297">https://golang.org/cl/108297</a>: calling File leaves the socket in nonblocking mode
|
The <a href="/pkg/net/#TCPConn.File"><code>TCPConn.File</code></a>,
|
||||||
|
<a href="/pkg/net/#UDPConn.File"><code>UDPConn.File</code></a>,
|
||||||
|
<a href="/pkg/net/#UnixCOnn.File"><code>UnixConn.File</code></a>,
|
||||||
|
and <a href="/pkg/net/#IPConn.File"><code>IPConn.File</code></a>
|
||||||
|
methods no longer put the returned <code>*os.File</code> into
|
||||||
|
blocking mode.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</dl><!-- net -->
|
</dl><!-- net -->
|
||||||
|
|
||||||
<dl id="net/http"><dt><a href="/pkg/net/http/">net/http</a></dt>
|
<dl id="net/http"><dt><a href="/pkg/net/http/">net/http</a></dt>
|
||||||
<dd>
|
<dd>
|
||||||
<p><!-- CL 89275 -->
|
<p><!-- CL 71272 -->
|
||||||
TODO: <a href="https://golang.org/cl/89275">https://golang.org/cl/89275</a>: don't sniff Content-type in Server when X-Content-Type-Options:nosniff
|
The <a href="/pkg/net/http/#Transport"><code>Transport</code></a> type has a
|
||||||
|
new <a href="/pkg/net/http/#Transport.MaxConnsPerHost"><code>MaxConnsPerHost</code></a>
|
||||||
|
option that permits limiting the maximum number of connections
|
||||||
|
per host.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 79919 -->
|
||||||
|
The <a href="/pkg/net/http/#Cookie"><code>Cookie</code></a> type has a new
|
||||||
|
<a href="/pkg/net/http/#Cookie.SameSite"><code>SameSite</code></a> field
|
||||||
|
(of new type also named
|
||||||
|
<a href="/pkg/net/http/#SameSite"><code>SameSite</code></a>) to represent the new cookie attribute recently supported by most browsers.
|
||||||
|
The <code>net/http</code>'s <code>Transport</code> does not use the <code>SameSite</code>
|
||||||
|
attribute itself, but the package supports parsing and serializing the
|
||||||
|
attribute for browsers to use.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 81778 -->
|
||||||
|
It is no longer allowed to reuse a <a href="/pkg/net/http/#Server"><code>Server</code></a>
|
||||||
|
after a call to
|
||||||
|
<a href="/pkg/net/http/#Server.Shutdown"><code>Shutdown</code></a> or
|
||||||
|
<a href="/pkg/net/http/#Server.Close"><code>Close</code></a>. It was never officially supported
|
||||||
|
in the past and had often surprising behavior. Now, all future calls to the server's <code>Serve</code>
|
||||||
|
methods will return errors after a shutdown or close.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- CL 89275 was reverted before Go 1.11 -->
|
||||||
|
|
||||||
<p><!-- CL 93296 -->
|
<p><!-- CL 93296 -->
|
||||||
TODO: <a href="https://golang.org/cl/93296">https://golang.org/cl/93296</a>: add StatusMisdirectedRequest (421)
|
The constant <code>StatusMisdirectedRequest</code> is now defined for HTTP status code 421.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 123875 -->
|
||||||
|
The HTTP server will no longer cancel contexts or send on
|
||||||
|
<a href="/pkg/net/http/#CloseNotifier"><code>CloseNotifier</code></a>
|
||||||
|
channels upon receiving pipelined HTTP/1.1 requests. Browsers do
|
||||||
|
not use HTTP pipelining, but some clients (such as
|
||||||
|
Debian's <code>apt</code>) may be configured to do so.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 115255 -->
|
||||||
|
<a href="/pkg/net/http/#ProxyFromEnvironment"><code>ProxyFromEnvironment</code></a>, which is used by the
|
||||||
|
<a href="/pkg/net/http/#DefaultTransport"><code>DefaultTransport</code></a>, now
|
||||||
|
supports CIDR notation and ports in the <code>NO_PROXY</code> environment variable.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</dl><!-- net/http -->
|
</dl><!-- net/http -->
|
||||||
|
|
||||||
|
<dl id="net/http/httputil"><dt><a href="/pkg/net/http/httputil/">net/http/httputil</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 77410 -->
|
||||||
|
The
|
||||||
|
<a href="/pkg/net/http/httputil/#ReverseProxy"><code>ReverseProxy</code></a>
|
||||||
|
has a new
|
||||||
|
<a href="/pkg/net/http/httputil/#ReverseProxy.ErrorHandler"><code>ErrorHandler</code></a>
|
||||||
|
option to permit changing how errors are handled.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 115135 -->
|
||||||
|
The <code>ReverseProxy</code> now also passes
|
||||||
|
"<code>TE:</code> <code>trailers</code>" request headers
|
||||||
|
through to the backend, as required by the gRPC protocol.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</dl><!-- net/http/httputil -->
|
||||||
|
|
||||||
<dl id="os"><dt><a href="/pkg/os/">os</a></dt>
|
<dl id="os"><dt><a href="/pkg/os/">os</a></dt>
|
||||||
<dd>
|
<dd>
|
||||||
<p><!-- CL 78835 -->
|
<p><!-- CL 78835 -->
|
||||||
TODO: <a href="https://golang.org/cl/78835">https://golang.org/cl/78835</a>: add UserCacheDir
|
The new <a href="/pkg/os/#UserCacheDir"><code>UserCacheDir</code></a> function
|
||||||
|
returns the default root directory to use for user-specific cached data.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><!-- CL 94856 -->
|
<p><!-- CL 94856 -->
|
||||||
TODO: <a href="https://golang.org/cl/94856">https://golang.org/cl/94856</a>: add ModeIrregular flag
|
The new <a href="/pkg/os/#ModeIrregular"><code>ModeIrregular</code></a>
|
||||||
|
is a <a href="/pkg/os/#FileMode"><code>FileMode</code></a> bit to represent
|
||||||
|
that a file is not a regular file, but nothing else is known about it, or that
|
||||||
|
it's not a socket, device, named pipe, symlink, or other file type for which
|
||||||
|
Go has a defined mode bit.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><!-- CL 99337 -->
|
<p><!-- CL 99337 -->
|
||||||
TODO: <a href="https://golang.org/cl/99337">https://golang.org/cl/99337</a>: enable symlink creation on Windows 10
|
<a href="/pkg/os/#Symlink"><code>Symlink</code></a> now works
|
||||||
|
for unprivileged users on Windows 10 on machines with Developer
|
||||||
|
Mode enabled.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><!-- CL 100077 -->
|
<p><!-- CL 100077 -->
|
||||||
TODO: <a href="https://golang.org/cl/100077">https://golang.org/cl/100077</a>: use poller when NewFile is called with a blocking descriptor.
|
When a non-blocking descriptor is passed
|
||||||
|
to <a href="/pkg/os#NewFile"><code>NewFile</code></a>, the
|
||||||
|
resulting <code>*File</code> will be kept in non-blocking
|
||||||
|
mode. This means that I/O for that <code>*File</code> will use
|
||||||
|
the runtime poller rather than a separate thread, and that
|
||||||
|
the <a href="/pkg/os/#File.SetDeadline"><code>SetDeadline</code></a>
|
||||||
|
methods will work.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</dl><!-- os -->
|
</dl><!-- os -->
|
||||||
|
|
@ -248,7 +781,8 @@ Do not send CLs removing the interior tags from such phrases.
|
||||||
<dl id="os/signal"><dt><a href="/pkg/os/signal/">os/signal</a></dt>
|
<dl id="os/signal"><dt><a href="/pkg/os/signal/">os/signal</a></dt>
|
||||||
<dd>
|
<dd>
|
||||||
<p><!-- CL 108376 -->
|
<p><!-- CL 108376 -->
|
||||||
TODO: <a href="https://golang.org/cl/108376">https://golang.org/cl/108376</a>: add func Ignored(sig Signal) bool
|
The new <a href="/pkg/os/signal/#Ignored"><code>Ignored</code></a> function reports
|
||||||
|
whether a signal is currently ignored.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</dl><!-- os/signal -->
|
</dl><!-- os/signal -->
|
||||||
|
|
@ -256,59 +790,50 @@ Do not send CLs removing the interior tags from such phrases.
|
||||||
<dl id="os/user"><dt><a href="/pkg/os/user/">os/user</a></dt>
|
<dl id="os/user"><dt><a href="/pkg/os/user/">os/user</a></dt>
|
||||||
<dd>
|
<dd>
|
||||||
<p><!-- CL 92456 -->
|
<p><!-- CL 92456 -->
|
||||||
TODO: <a href="https://golang.org/cl/92456">https://golang.org/cl/92456</a>: add a way to enforce pure Go implementation
|
The <code>os/user</code> package can now be built in pure Go
|
||||||
|
mode using the build tag "<code>osusergo</code>",
|
||||||
|
independent of the use of the environment
|
||||||
|
variable <code>CGO_ENABLED=0</code>. Previously the only way to use
|
||||||
|
the package's pure Go implementation was to disable <code>cgo</code>
|
||||||
|
support across the entire program.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</dl><!-- os/user -->
|
</dl><!-- os/user -->
|
||||||
|
|
||||||
<dl id="runtime"><dt><a href="/pkg/runtime/">runtime</a></dt>
|
<!-- CL 101715 was reverted -->
|
||||||
|
|
||||||
|
<dl id="runtime-again"><dt><a href="/pkg/runtime/">runtime</a></dt>
|
||||||
<dd>
|
<dd>
|
||||||
<p><!-- CL 85887 -->
|
|
||||||
TODO: <a href="https://golang.org/cl/85887">https://golang.org/cl/85887</a>: use sparse mappings for the heap
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p><!-- CL 94076 -->
|
<p><!-- CL 70993 -->
|
||||||
TODO: <a href="https://golang.org/cl/94076">https://golang.org/cl/94076</a>: use native CAS and memory barrier on ARMv7
|
Setting the <code>GODEBUG=tracebackancestors=<em>N</em></code>
|
||||||
</p>
|
environment variable now extends tracebacks with the stacks at
|
||||||
|
which goroutines were created, where <em>N</em> limits the
|
||||||
<p><!-- CL 106156 -->
|
number of ancestor goroutines to report.
|
||||||
TODO: <a href="https://golang.org/cl/106156">https://golang.org/cl/106156</a>: use fixed TLS offsets on darwin/amd64 and darwin/386
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p><!-- CL 109255 -->
|
|
||||||
TODO: <a href="https://golang.org/cl/109255">https://golang.org/cl/109255</a>: enable memory sanitizer on arm64
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</dl><!-- runtime -->
|
</dl><!-- runtime -->
|
||||||
|
|
||||||
<dl id="runtime,cmd/ld"><dt><a href="/pkg/runtime,cmd/ld/">runtime,cmd/ld</a></dt>
|
|
||||||
<dd>
|
|
||||||
<p><!-- CL 108679 -->
|
|
||||||
TODO: <a href="https://golang.org/cl/108679">https://golang.org/cl/108679</a>: on darwin, create theads using libc
|
|
||||||
</p>
|
|
||||||
|
|
||||||
</dl><!-- runtime,cmd/ld -->
|
|
||||||
|
|
||||||
<dl id="runtime/pprof"><dt><a href="/pkg/runtime/pprof/">runtime/pprof</a></dt>
|
<dl id="runtime/pprof"><dt><a href="/pkg/runtime/pprof/">runtime/pprof</a></dt>
|
||||||
<dd>
|
<dd>
|
||||||
<p><!-- CL 102696 -->
|
<p><!-- CL 102696 -->
|
||||||
TODO: <a href="https://golang.org/cl/102696">https://golang.org/cl/102696</a>: introduce "allocs" profile
|
This release adds a new "allocs" profile type that profiles
|
||||||
|
total number of bytes allocated since the program began
|
||||||
|
(including garbage-collected bytes). This is identical to the
|
||||||
|
existing "heap" profile viewed in <code>-alloc_space</code> mode.
|
||||||
|
Now <code>go test -memprofile=...</code> reports an "allocs" profile
|
||||||
|
instead of "heap" profile.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</dl><!-- runtime/pprof -->
|
</dl><!-- runtime/pprof -->
|
||||||
|
|
||||||
<dl id="runtime/traceback"><dt><a href="/pkg/runtime/traceback/">runtime/traceback</a></dt>
|
|
||||||
<dd>
|
|
||||||
<p><!-- CL 70993 -->
|
|
||||||
TODO: <a href="https://golang.org/cl/70993">https://golang.org/cl/70993</a>: support tracking goroutine ancestor tracebacks with GODEBUG="tracebackancestors=N"
|
|
||||||
</p>
|
|
||||||
|
|
||||||
</dl><!-- runtime/traceback -->
|
|
||||||
|
|
||||||
<dl id="sync"><dt><a href="/pkg/sync/">sync</a></dt>
|
<dl id="sync"><dt><a href="/pkg/sync/">sync</a></dt>
|
||||||
<dd>
|
<dd>
|
||||||
<p><!-- CL 87095 -->
|
<p><!-- CL 87095 -->
|
||||||
TODO: <a href="https://golang.org/cl/87095">https://golang.org/cl/87095</a>: enable profiling of RWMutex
|
The mutex profile now includes reader/writer contention
|
||||||
|
for <a href="/pkg/sync/#RWMutex"><code>RWMutex</code></a>.
|
||||||
|
Writer/writer contention was already included in the mutex
|
||||||
|
profile.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</dl><!-- sync -->
|
</dl><!-- sync -->
|
||||||
|
|
@ -316,7 +841,28 @@ Do not send CLs removing the interior tags from such phrases.
|
||||||
<dl id="syscall"><dt><a href="/pkg/syscall/">syscall</a></dt>
|
<dl id="syscall"><dt><a href="/pkg/syscall/">syscall</a></dt>
|
||||||
<dd>
|
<dd>
|
||||||
<p><!-- CL 106275 -->
|
<p><!-- CL 106275 -->
|
||||||
TODO: <a href="https://golang.org/cl/106275">https://golang.org/cl/106275</a>: introduce Pointer type and use it instead of uintptr
|
On Windows, several fields were changed from <code>uintptr</code> to a new
|
||||||
|
<a href="/pkg/syscall/?GOOS=windows&GOARCH=amd64#Pointer"><code>Pointer</code></a>
|
||||||
|
type to avoid problems with Go's garbage collector. The same change was made
|
||||||
|
to the <a href="https://godoc.org/golang.org/x/sys/windows"><code>golang.org/x/sys/windows</code></a>
|
||||||
|
package. For any code affected, users should first migrate away from the <code>syscall</code>
|
||||||
|
package to the <code>golang.org/x/sys/windows</code> package, and then change
|
||||||
|
to using the <code>Pointer</code>, while obeying the
|
||||||
|
<a href="/pkg/unsafe/#Pointer"><code>unsafe.Pointer</code> conversion rules</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 118658 -->
|
||||||
|
On Linux, the <code>flags</code> parameter to
|
||||||
|
<a href="/pkg/syscall/?GOOS=linux&GOARCH=amd64#Faccessat"><code>Faccessat</code></a>
|
||||||
|
is now implemented just as in glibc. In earlier Go releases the
|
||||||
|
flags parameter was ignored.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 118658 -->
|
||||||
|
On Linux, the <code>flags</code> parameter to
|
||||||
|
<a href="/pkg/syscall/?GOOS=linux&GOARCH=amd64#Fchmodat"><code>Fchmodat</code></a>
|
||||||
|
is now validated. Linux's <code>fchmodat</code> doesn't support the <code>flags</code> parameter
|
||||||
|
so we now mimic glibc's behavior and return an error if it's non-zero.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</dl><!-- syscall -->
|
</dl><!-- syscall -->
|
||||||
|
|
@ -324,7 +870,10 @@ Do not send CLs removing the interior tags from such phrases.
|
||||||
<dl id="text/scanner"><dt><a href="/pkg/text/scanner/">text/scanner</a></dt>
|
<dl id="text/scanner"><dt><a href="/pkg/text/scanner/">text/scanner</a></dt>
|
||||||
<dd>
|
<dd>
|
||||||
<p><!-- CL 112037 -->
|
<p><!-- CL 112037 -->
|
||||||
TODO: <a href="https://golang.org/cl/112037">https://golang.org/cl/112037</a>: return RawString token rather than String for raw string literals
|
The <a href="/pkg/text/scanner/#Scanner.Scan"><code>Scanner.Scan</code></a> method now returns
|
||||||
|
the <a href="/pkg/text/scanner/#RawString"><code>RawString</code></a> token
|
||||||
|
instead of <a href="/pkg/text/scanner/#String"><code>String</code></a>
|
||||||
|
for raw string literals.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</dl><!-- text/scanner -->
|
</dl><!-- text/scanner -->
|
||||||
|
|
@ -332,7 +881,19 @@ Do not send CLs removing the interior tags from such phrases.
|
||||||
<dl id="text/template"><dt><a href="/pkg/text/template/">text/template</a></dt>
|
<dl id="text/template"><dt><a href="/pkg/text/template/">text/template</a></dt>
|
||||||
<dd>
|
<dd>
|
||||||
<p><!-- CL 84480 -->
|
<p><!-- CL 84480 -->
|
||||||
TODO: <a href="https://golang.org/cl/84480">https://golang.org/cl/84480</a>: add variable assignments
|
Modifying template variables via assignments is now permitted via the <code>=</code> token:
|
||||||
|
</p>
|
||||||
|
<pre>
|
||||||
|
{{"{{"}} $v := "init" {{"}}"}}
|
||||||
|
{{"{{"}} if true {{"}}"}}
|
||||||
|
{{"{{"}} $v = "changed" {{"}}"}}
|
||||||
|
{{"{{"}} end {{"}}"}}
|
||||||
|
v: {{"{{"}} $v {{"}}"}} {{"{{"}}/* "changed" */{{"}}"}}</pre>
|
||||||
|
|
||||||
|
<p><!-- CL 95215 -->
|
||||||
|
In previous versions untyped <code>nil</code> values passed to
|
||||||
|
template functions were ignored. They are now passed as normal
|
||||||
|
arguments.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</dl><!-- text/template -->
|
</dl><!-- text/template -->
|
||||||
|
|
@ -340,7 +901,10 @@ Do not send CLs removing the interior tags from such phrases.
|
||||||
<dl id="time"><dt><a href="/pkg/time/">time</a></dt>
|
<dl id="time"><dt><a href="/pkg/time/">time</a></dt>
|
||||||
<dd>
|
<dd>
|
||||||
<p><!-- CL 98157 -->
|
<p><!-- CL 98157 -->
|
||||||
TODO: <a href="https://golang.org/cl/98157">https://golang.org/cl/98157</a>: add support for parsing timezones denoted by sign and offset
|
Parsing of timezones denoted by sign and offset is now
|
||||||
|
supported. In previous versions, numeric timezone names
|
||||||
|
(such as <code>+03</code>) were not considered valid, and only
|
||||||
|
three-letter abbreviations (such as <code>MST</code>) were accepted
|
||||||
|
when expecting a timezone name.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</dl><!-- time -->
|
</dl><!-- time -->
|
||||||
|
|
|
||||||
857
doc/go_faq.html
857
doc/go_faq.html
File diff suppressed because it is too large
Load diff
|
|
@ -1,6 +1,6 @@
|
||||||
<!--{
|
<!--{
|
||||||
"Title": "The Go Programming Language Specification",
|
"Title": "The Go Programming Language Specification",
|
||||||
"Subtitle": "Version of May 9, 2018",
|
"Subtitle": "Version of August 30, 2018",
|
||||||
"Path": "/ref/spec"
|
"Path": "/ref/spec"
|
||||||
}-->
|
}-->
|
||||||
|
|
||||||
|
|
@ -2112,8 +2112,8 @@ with initializer expressions but no types:
|
||||||
i, j := 0, 10
|
i, j := 0, 10
|
||||||
f := func() int { return 7 }
|
f := func() int { return 7 }
|
||||||
ch := make(chan int)
|
ch := make(chan int)
|
||||||
r, w := os.Pipe(fd) // os.Pipe() returns two values
|
r, w, _ := os.Pipe() // os.Pipe() returns a connected pair of Files and an error, if any
|
||||||
_, y, _ := coord(p) // coord() returns three values; only interested in y coordinate
|
_, y, _ := coord(p) // coord() returns three values; only interested in y coordinate
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
|
||||||
BIN
doc/gopher/modelsheet.jpg
Normal file
BIN
doc/gopher/modelsheet.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 84 KiB |
|
|
@ -639,14 +639,10 @@ contains further details regarding Go's ARM support.
|
||||||
</p>
|
</p>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li><code>$GOMIPS</code> (for <code>mips</code> and <code>mipsle</code> only)
|
<li><code>$GOMIPS</code> (for <code>mips</code> and <code>mipsle</code> only) <br> <code>$GOMIPS64</code> (for <code>mips64</code> and <code>mips64le</code> only)
|
||||||
<p>
|
<p>
|
||||||
This sets whether to use floating point instructions.
|
These variables set whether to use floating point instructions. Set to "<code>hardfloat</code>" to use floating point instructions; this is the default. Set to "<code>softfloat</code>" to use soft floating point.
|
||||||
</p>
|
</p>
|
||||||
<ul>
|
|
||||||
<li><code>GOMIPS=hardfloat</code>: use floating point instructions (the default)</li>
|
|
||||||
<li><code>GOMIPS=softfloat</code>: use soft floating point</li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ If your OS or architecture is not on the list, you may be able to
|
||||||
<tr><td>FreeBSD 10.3 or later</td> <td>amd64, 386</td> <td>Debian GNU/kFreeBSD not supported</td></tr>
|
<tr><td>FreeBSD 10.3 or later</td> <td>amd64, 386</td> <td>Debian GNU/kFreeBSD not supported</td></tr>
|
||||||
<tr valign='top'><td>Linux 2.6.23 or later with glibc</td> <td>amd64, 386, arm, arm64,<br>s390x, ppc64le</td> <td>CentOS/RHEL 5.x not supported.<br>Install from source for other libc.</td></tr>
|
<tr valign='top'><td>Linux 2.6.23 or later with glibc</td> <td>amd64, 386, arm, arm64,<br>s390x, ppc64le</td> <td>CentOS/RHEL 5.x not supported.<br>Install from source for other libc.</td></tr>
|
||||||
<tr><td>macOS 10.10 or later</td> <td>amd64</td> <td>use the clang or gcc<sup>†</sup> that comes with Xcode<sup>‡</sup> for <code>cgo</code> support</td></tr>
|
<tr><td>macOS 10.10 or later</td> <td>amd64</td> <td>use the clang or gcc<sup>†</sup> that comes with Xcode<sup>‡</sup> for <code>cgo</code> support</td></tr>
|
||||||
<tr><td>Windows XP SP2 or later</td> <td>amd64, 386</td> <td>use MinGW gcc<sup>†</sup>. No need for cygwin or msys.</td></tr>
|
<tr><td>Windows 7, Server 2008R2 or later</td> <td>amd64, 386</td> <td>use MinGW gcc<sup>†</sup>. No need for cygwin or msys.</td></tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ security team directly:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>Primary security coordinator: <a href="mailto:adg@golang.org">Andrew Gerrand</a> (<a href="https://drive.google.com/a/google.com/file/d/0B42ZAZN5yFufRldybEVNandRN2c/view">public key</a>).</li>
|
<li>Primary security coordinator: <a href="mailto:filippo@golang.org">Filippo Valsorda</a> (<a href="https://keybase.io/filippo/pgp_keys.asc">public key</a>).</li>
|
||||||
<li>Secondary coordinator: <a href="mailto:agl@golang.org">Adam Langley</a> (<a href="https://www.imperialviolet.org/key.asc">public key</a>).</li>
|
<li>Secondary coordinator: <a href="mailto:agl@golang.org">Adam Langley</a> (<a href="https://www.imperialviolet.org/key.asc">public key</a>).</li>
|
||||||
<li>If you receive no response, mail <a href="mailto:golang-dev@googlegroups.com">golang-dev@googlegroups.com</a> or use the <a href="https://groups.google.com/forum/#!forum/golang-dev">golang-dev web interface</a>.</li>
|
<li>If you receive no response, mail <a href="mailto:golang-dev@googlegroups.com">golang-dev@googlegroups.com</a> or use the <a href="https://groups.google.com/forum/#!forum/golang-dev">golang-dev web interface</a>.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,8 @@ func Test22906(t *testing.T) { test22906(t) }
|
||||||
func Test24206(t *testing.T) { test24206(t) }
|
func Test24206(t *testing.T) { test24206(t) }
|
||||||
func Test25143(t *testing.T) { test25143(t) }
|
func Test25143(t *testing.T) { test25143(t) }
|
||||||
func Test23356(t *testing.T) { test23356(t) }
|
func Test23356(t *testing.T) { test23356(t) }
|
||||||
|
func Test26066(t *testing.T) { test26066(t) }
|
||||||
|
func Test26213(t *testing.T) { test26213(t) }
|
||||||
|
|
||||||
func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) }
|
func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) }
|
||||||
func BenchmarkGoString(b *testing.B) { benchGoString(b) }
|
func BenchmarkGoString(b *testing.B) { benchGoString(b) }
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,16 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build darwin,cgo,!internal
|
// We skip this test in race mode because, for unknown reasons,
|
||||||
|
// linking against CoreFoundation on macOS 10.10 causes mmap to ignore
|
||||||
|
// the hint address, which makes the Go allocator incompatible with
|
||||||
|
// TSAN. See golang.org/issue/26475.
|
||||||
|
//
|
||||||
|
// TODO(austin): Once support for macOS 10.10 is dropped, remove the
|
||||||
|
// race constraint (and the one in issue21897b.go). See
|
||||||
|
// golang.org/issue/26513.
|
||||||
|
|
||||||
|
// +build darwin,cgo,!internal,!race
|
||||||
|
|
||||||
package cgotest
|
package cgotest
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build !darwin !cgo internal
|
// +build !darwin !cgo internal race
|
||||||
|
|
||||||
package cgotest
|
package cgotest
|
||||||
|
|
||||||
|
|
|
||||||
39
misc/cgo/test/issue24161_darwin_test.go
Normal file
39
misc/cgo/test/issue24161_darwin_test.go
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// See issue21897.go and golang.org/issue/26475 for why this is
|
||||||
|
// skipped in race mode.
|
||||||
|
//
|
||||||
|
// TODO(austin): Once support for macOS 10.10 is dropped, remove the
|
||||||
|
// race constraint. See golang.org/issue/26513.
|
||||||
|
|
||||||
|
// +build !race
|
||||||
|
|
||||||
|
package cgotest
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"./issue24161arg"
|
||||||
|
"./issue24161e0"
|
||||||
|
"./issue24161e1"
|
||||||
|
"./issue24161e2"
|
||||||
|
"./issue24161res"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test24161Arg(t *testing.T) {
|
||||||
|
issue24161arg.Test(t)
|
||||||
|
}
|
||||||
|
func Test24161Res(t *testing.T) {
|
||||||
|
issue24161res.Test(t)
|
||||||
|
}
|
||||||
|
func Test24161Example0(t *testing.T) {
|
||||||
|
issue24161e0.Test(t)
|
||||||
|
}
|
||||||
|
func Test24161Example1(t *testing.T) {
|
||||||
|
issue24161e1.Test(t)
|
||||||
|
}
|
||||||
|
func Test24161Example2(t *testing.T) {
|
||||||
|
issue24161e2.Test(t)
|
||||||
|
}
|
||||||
17
misc/cgo/test/issue24161arg/def.go
Normal file
17
misc/cgo/test/issue24161arg/def.go
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build darwin
|
||||||
|
|
||||||
|
package issue24161arg
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo LDFLAGS: -framework CoreFoundation
|
||||||
|
#include <CoreFoundation/CoreFoundation.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
func test24161array() C.CFArrayRef {
|
||||||
|
return C.CFArrayCreate(0, nil, 0, nil)
|
||||||
|
}
|
||||||
19
misc/cgo/test/issue24161arg/use.go
Normal file
19
misc/cgo/test/issue24161arg/use.go
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build darwin
|
||||||
|
|
||||||
|
package issue24161arg
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo LDFLAGS: -framework CoreFoundation
|
||||||
|
#include <CoreFoundation/CoreFoundation.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func Test(t *testing.T) {
|
||||||
|
a := test24161array()
|
||||||
|
C.CFArrayCreateCopy(0, a)
|
||||||
|
}
|
||||||
29
misc/cgo/test/issue24161e0/main.go
Normal file
29
misc/cgo/test/issue24161e0/main.go
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build darwin
|
||||||
|
|
||||||
|
package issue24161e0
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo CFLAGS: -x objective-c
|
||||||
|
#cgo LDFLAGS: -framework CoreFoundation -framework Security
|
||||||
|
#include <TargetConditionals.h>
|
||||||
|
#include <CoreFoundation/CoreFoundation.h>
|
||||||
|
#include <Security/Security.h>
|
||||||
|
#if TARGET_OS_IPHONE == 0 && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101200
|
||||||
|
typedef CFStringRef SecKeyAlgorithm;
|
||||||
|
static CFDataRef SecKeyCreateSignature(SecKeyRef key, SecKeyAlgorithm algorithm, CFDataRef dataToSign, CFErrorRef *error){return NULL;}
|
||||||
|
#define kSecKeyAlgorithmECDSASignatureDigestX962SHA1 foo()
|
||||||
|
static SecKeyAlgorithm foo(void){return NULL;}
|
||||||
|
#endif
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func f1() {
|
||||||
|
C.SecKeyCreateSignature(0, C.kSecKeyAlgorithmECDSASignatureDigestX962SHA1, 0, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test(t *testing.T) {}
|
||||||
38
misc/cgo/test/issue24161e1/main.go
Normal file
38
misc/cgo/test/issue24161e1/main.go
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build darwin
|
||||||
|
|
||||||
|
package issue24161e1
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo CFLAGS: -x objective-c
|
||||||
|
#cgo LDFLAGS: -framework CoreFoundation -framework Security
|
||||||
|
#include <TargetConditionals.h>
|
||||||
|
#include <CoreFoundation/CoreFoundation.h>
|
||||||
|
#include <Security/Security.h>
|
||||||
|
#if TARGET_OS_IPHONE == 0 && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101200
|
||||||
|
typedef CFStringRef SecKeyAlgorithm;
|
||||||
|
static CFDataRef SecKeyCreateSignature(SecKeyRef key, SecKeyAlgorithm algorithm, CFDataRef dataToSign, CFErrorRef *error){return NULL;}
|
||||||
|
#define kSecKeyAlgorithmECDSASignatureDigestX962SHA1 foo()
|
||||||
|
static SecKeyAlgorithm foo(void){return NULL;}
|
||||||
|
#endif
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func f1() {
|
||||||
|
C.SecKeyCreateSignature(0, C.kSecKeyAlgorithmECDSASignatureDigestX962SHA1, 0, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func f2(e C.CFErrorRef) {
|
||||||
|
if desc := C.CFErrorCopyDescription(e); desc != 0 {
|
||||||
|
fmt.Println(desc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test(t *testing.T) {}
|
||||||
40
misc/cgo/test/issue24161e2/main.go
Normal file
40
misc/cgo/test/issue24161e2/main.go
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build darwin
|
||||||
|
|
||||||
|
package issue24161e2
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo CFLAGS: -x objective-c
|
||||||
|
#cgo LDFLAGS: -framework CoreFoundation -framework Security
|
||||||
|
#include <TargetConditionals.h>
|
||||||
|
#include <CoreFoundation/CoreFoundation.h>
|
||||||
|
#include <Security/Security.h>
|
||||||
|
#if TARGET_OS_IPHONE == 0 && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101200
|
||||||
|
typedef CFStringRef SecKeyAlgorithm;
|
||||||
|
static CFDataRef SecKeyCreateSignature(SecKeyRef key, SecKeyAlgorithm algorithm, CFDataRef dataToSign, CFErrorRef *error){return NULL;}
|
||||||
|
#define kSecKeyAlgorithmECDSASignatureDigestX962SHA1 foo()
|
||||||
|
static SecKeyAlgorithm foo(void){return NULL;}
|
||||||
|
#endif
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ C.CFStringRef
|
||||||
|
|
||||||
|
func f1() {
|
||||||
|
C.SecKeyCreateSignature(0, C.kSecKeyAlgorithmECDSASignatureDigestX962SHA1, 0, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func f2(e C.CFErrorRef) {
|
||||||
|
if desc := C.CFErrorCopyDescription(e); desc != 0 {
|
||||||
|
fmt.Println(desc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test(t *testing.T) {}
|
||||||
23
misc/cgo/test/issue24161res/restype.go
Normal file
23
misc/cgo/test/issue24161res/restype.go
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build darwin
|
||||||
|
|
||||||
|
package issue24161res
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo LDFLAGS: -framework CoreFoundation
|
||||||
|
#include <CoreFoundation/CoreFoundation.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test(t *testing.T) {
|
||||||
|
if k := reflect.TypeOf(C.CFArrayCreate(0, nil, 0, nil)).Kind(); k != reflect.Uintptr {
|
||||||
|
t.Fatalf("bad kind %s\n", k)
|
||||||
|
}
|
||||||
|
}
|
||||||
19
misc/cgo/test/issue26066.go
Normal file
19
misc/cgo/test/issue26066.go
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Wrong type of constant with GCC 8 and newer.
|
||||||
|
|
||||||
|
package cgotest
|
||||||
|
|
||||||
|
// const unsigned long long int issue26066 = (const unsigned long long) -1;
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func test26066(t *testing.T) {
|
||||||
|
var i = int64(C.issue26066)
|
||||||
|
if i != -1 {
|
||||||
|
t.Errorf("got %d, want -1", i)
|
||||||
|
}
|
||||||
|
}
|
||||||
29
misc/cgo/test/issue26213/jni.h
Normal file
29
misc/cgo/test/issue26213/jni.h
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// It's going to be hard to include a whole real JVM to test this.
|
||||||
|
// So we'll simulate a really easy JVM using just the parts we need.
|
||||||
|
|
||||||
|
// This is the relevant part of jni.h.
|
||||||
|
|
||||||
|
// On Android NDK16, jobject is defined like this in C and C++
|
||||||
|
typedef void* jobject;
|
||||||
|
|
||||||
|
typedef jobject jclass;
|
||||||
|
typedef jobject jthrowable;
|
||||||
|
typedef jobject jstring;
|
||||||
|
typedef jobject jarray;
|
||||||
|
typedef jarray jbooleanArray;
|
||||||
|
typedef jarray jbyteArray;
|
||||||
|
typedef jarray jcharArray;
|
||||||
|
typedef jarray jshortArray;
|
||||||
|
typedef jarray jintArray;
|
||||||
|
typedef jarray jlongArray;
|
||||||
|
typedef jarray jfloatArray;
|
||||||
|
typedef jarray jdoubleArray;
|
||||||
|
typedef jarray jobjectArray;
|
||||||
|
|
||||||
|
typedef jobject jweak;
|
||||||
|
|
||||||
|
// Note: jvalue is already a non-pointer type due to it being a C union.
|
||||||
46
misc/cgo/test/issue26213/test26213.go
Normal file
46
misc/cgo/test/issue26213/test26213.go
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package issue26213
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include "jni.h"
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test26213(t *testing.T) {
|
||||||
|
var x1 C.jobject = 0 // Note: 0, not nil. That makes sure we use uintptr for these types.
|
||||||
|
_ = x1
|
||||||
|
var x2 C.jclass = 0
|
||||||
|
_ = x2
|
||||||
|
var x3 C.jthrowable = 0
|
||||||
|
_ = x3
|
||||||
|
var x4 C.jstring = 0
|
||||||
|
_ = x4
|
||||||
|
var x5 C.jarray = 0
|
||||||
|
_ = x5
|
||||||
|
var x6 C.jbooleanArray = 0
|
||||||
|
_ = x6
|
||||||
|
var x7 C.jbyteArray = 0
|
||||||
|
_ = x7
|
||||||
|
var x8 C.jcharArray = 0
|
||||||
|
_ = x8
|
||||||
|
var x9 C.jshortArray = 0
|
||||||
|
_ = x9
|
||||||
|
var x10 C.jintArray = 0
|
||||||
|
_ = x10
|
||||||
|
var x11 C.jlongArray = 0
|
||||||
|
_ = x11
|
||||||
|
var x12 C.jfloatArray = 0
|
||||||
|
_ = x12
|
||||||
|
var x13 C.jdoubleArray = 0
|
||||||
|
_ = x13
|
||||||
|
var x14 C.jobjectArray = 0
|
||||||
|
_ = x14
|
||||||
|
var x15 C.jweak = 0
|
||||||
|
_ = x15
|
||||||
|
}
|
||||||
10
misc/cgo/test/issue26430.go
Normal file
10
misc/cgo/test/issue26430.go
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Issue 26430: incomplete typedef leads to inconsistent typedefs error.
|
||||||
|
// No runtime test; just make sure it compiles.
|
||||||
|
|
||||||
|
package cgotest
|
||||||
|
|
||||||
|
import _ "./issue26430"
|
||||||
|
|
@ -2,6 +2,12 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// This file is here just to make the go tool happy. It allows
|
package a
|
||||||
// empty function declarations (no function body).
|
|
||||||
// It is used with "go:linkname".
|
// typedef struct S ST;
|
||||||
|
// static ST* F() { return 0; }
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
func F1() {
|
||||||
|
C.F()
|
||||||
|
}
|
||||||
13
misc/cgo/test/issue26430/b.go
Normal file
13
misc/cgo/test/issue26430/b.go
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package a
|
||||||
|
|
||||||
|
// typedef struct S ST;
|
||||||
|
// struct S { int f; };
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
func F2(p *C.ST) {
|
||||||
|
p.f = 1
|
||||||
|
}
|
||||||
23
misc/cgo/test/issue26517.go
Normal file
23
misc/cgo/test/issue26517.go
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package cgotest
|
||||||
|
|
||||||
|
// Introduce two pointer types which are distinct, but have the same
|
||||||
|
// base type. Make sure that both of those pointer types get resolved
|
||||||
|
// correctly. Before the fix for 26517 if one of these pointer types
|
||||||
|
// was resolved before the other one was processed, the second one
|
||||||
|
// would never be resolved.
|
||||||
|
// Before this issue was fixed this test failed on Windows,
|
||||||
|
// where va_list expands to a named char* type.
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <stdarg.h>
|
||||||
|
typedef va_list TypeOne;
|
||||||
|
typedef char *TypeTwo;
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
var a C.TypeOne
|
||||||
|
var b C.TypeTwo
|
||||||
10
misc/cgo/test/issue26743.go
Normal file
10
misc/cgo/test/issue26743.go
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Issue 26743: typedef of uint leads to inconsistent typedefs error.
|
||||||
|
// No runtime test; just make sure it compiles.
|
||||||
|
|
||||||
|
package cgotest
|
||||||
|
|
||||||
|
import _ "./issue26743"
|
||||||
11
misc/cgo/test/issue26743/a.go
Normal file
11
misc/cgo/test/issue26743/a.go
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package issue26743
|
||||||
|
|
||||||
|
// typedef unsigned int uint;
|
||||||
|
// int C1(uint x) { return x; }
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
var V1 = C.C1(0)
|
||||||
9
misc/cgo/test/issue26743/b.go
Normal file
9
misc/cgo/test/issue26743/b.go
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package issue26743
|
||||||
|
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
var V2 C.uint
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build !windows
|
// +build !windows,!static
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build !windows
|
// +build !windows,!static
|
||||||
|
|
||||||
package cgotest
|
package cgotest
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build windows
|
// +build windows static
|
||||||
|
|
||||||
package cgotest
|
package cgotest
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ func test9400(t *testing.T) {
|
||||||
|
|
||||||
// Grow the stack and put down a test pattern
|
// Grow the stack and put down a test pattern
|
||||||
const pattern = 0x123456789abcdef
|
const pattern = 0x123456789abcdef
|
||||||
var big [1024]uint64 // len must match assmebly
|
var big [1024]uint64 // len must match assembly
|
||||||
for i := range big {
|
for i := range big {
|
||||||
big[i] = pattern
|
big[i] = pattern
|
||||||
}
|
}
|
||||||
|
|
|
||||||
15
misc/cgo/test/test26213.go
Normal file
15
misc/cgo/test/test26213.go
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package cgotest
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"./issue26213"
|
||||||
|
)
|
||||||
|
|
||||||
|
func test26213(t *testing.T) {
|
||||||
|
issue26213.Test26213(t)
|
||||||
|
}
|
||||||
|
|
@ -14,6 +14,7 @@ import (
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
@ -83,13 +84,17 @@ func init() {
|
||||||
cc = append(cc, []string{"-framework", "CoreFoundation", "-framework", "Foundation"}...)
|
cc = append(cc, []string{"-framework", "CoreFoundation", "-framework", "Foundation"}...)
|
||||||
}
|
}
|
||||||
libgodir = GOOS + "_" + GOARCH
|
libgodir = GOOS + "_" + GOARCH
|
||||||
switch GOOS {
|
if runtime.Compiler == "gccgo" {
|
||||||
case "darwin":
|
libgodir = "gccgo_" + libgodir + "_fPIC"
|
||||||
if GOARCH == "arm" || GOARCH == "arm64" {
|
} else {
|
||||||
|
switch GOOS {
|
||||||
|
case "darwin":
|
||||||
|
if GOARCH == "arm" || GOARCH == "arm64" {
|
||||||
|
libgodir += "_shared"
|
||||||
|
}
|
||||||
|
case "dragonfly", "freebsd", "linux", "netbsd", "openbsd", "solaris":
|
||||||
libgodir += "_shared"
|
libgodir += "_shared"
|
||||||
}
|
}
|
||||||
case "dragonfly", "freebsd", "linux", "netbsd", "openbsd", "solaris":
|
|
||||||
libgodir += "_shared"
|
|
||||||
}
|
}
|
||||||
cc = append(cc, "-I", filepath.Join("pkg", libgodir))
|
cc = append(cc, "-I", filepath.Join("pkg", libgodir))
|
||||||
|
|
||||||
|
|
@ -155,6 +160,9 @@ func testInstall(t *testing.T, exe, libgoa, libgoh string, buildcmd ...string) {
|
||||||
} else {
|
} else {
|
||||||
ccArgs = append(ccArgs, "main_unix.c", libgoa)
|
ccArgs = append(ccArgs, "main_unix.c", libgoa)
|
||||||
}
|
}
|
||||||
|
if runtime.Compiler == "gccgo" {
|
||||||
|
ccArgs = append(ccArgs, "-lgo")
|
||||||
|
}
|
||||||
t.Log(ccArgs)
|
t.Log(ccArgs)
|
||||||
if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
|
if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
|
||||||
t.Logf("%s", out)
|
t.Logf("%s", out)
|
||||||
|
|
@ -163,7 +171,11 @@ func testInstall(t *testing.T, exe, libgoa, libgoh string, buildcmd ...string) {
|
||||||
defer os.Remove(exe)
|
defer os.Remove(exe)
|
||||||
|
|
||||||
binArgs := append(cmdToRun(exe), "arg1", "arg2")
|
binArgs := append(cmdToRun(exe), "arg1", "arg2")
|
||||||
if out, err := exec.Command(binArgs[0], binArgs[1:]...).CombinedOutput(); err != nil {
|
cmd = exec.Command(binArgs[0], binArgs[1:]...)
|
||||||
|
if runtime.Compiler == "gccgo" {
|
||||||
|
cmd.Env = append(os.Environ(), "GCCGO=1")
|
||||||
|
}
|
||||||
|
if out, err := cmd.CombinedOutput(); err != nil {
|
||||||
t.Logf("%s", out)
|
t.Logf("%s", out)
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -194,8 +206,13 @@ func checkLineComments(t *testing.T, hdrname string) {
|
||||||
func TestInstall(t *testing.T) {
|
func TestInstall(t *testing.T) {
|
||||||
defer os.RemoveAll("pkg")
|
defer os.RemoveAll("pkg")
|
||||||
|
|
||||||
|
libgoa := "libgo.a"
|
||||||
|
if runtime.Compiler == "gccgo" {
|
||||||
|
libgoa = "liblibgo.a"
|
||||||
|
}
|
||||||
|
|
||||||
testInstall(t, "./testp1"+exeSuffix,
|
testInstall(t, "./testp1"+exeSuffix,
|
||||||
filepath.Join("pkg", libgodir, "libgo.a"),
|
filepath.Join("pkg", libgodir, libgoa),
|
||||||
filepath.Join("pkg", libgodir, "libgo.h"),
|
filepath.Join("pkg", libgodir, "libgo.h"),
|
||||||
"go", "install", "-i", "-buildmode=c-archive", "libgo")
|
"go", "install", "-i", "-buildmode=c-archive", "libgo")
|
||||||
|
|
||||||
|
|
@ -235,6 +252,9 @@ func TestEarlySignalHandler(t *testing.T) {
|
||||||
checkLineComments(t, "libgo2.h")
|
checkLineComments(t, "libgo2.h")
|
||||||
|
|
||||||
ccArgs := append(cc, "-o", "testp"+exeSuffix, "main2.c", "libgo2.a")
|
ccArgs := append(cc, "-o", "testp"+exeSuffix, "main2.c", "libgo2.a")
|
||||||
|
if runtime.Compiler == "gccgo" {
|
||||||
|
ccArgs = append(ccArgs, "-lgo")
|
||||||
|
}
|
||||||
if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
|
if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
|
||||||
t.Logf("%s", out)
|
t.Logf("%s", out)
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|
@ -265,6 +285,9 @@ func TestSignalForwarding(t *testing.T) {
|
||||||
checkLineComments(t, "libgo2.h")
|
checkLineComments(t, "libgo2.h")
|
||||||
|
|
||||||
ccArgs := append(cc, "-o", "testp"+exeSuffix, "main5.c", "libgo2.a")
|
ccArgs := append(cc, "-o", "testp"+exeSuffix, "main5.c", "libgo2.a")
|
||||||
|
if runtime.Compiler == "gccgo" {
|
||||||
|
ccArgs = append(ccArgs, "-lgo")
|
||||||
|
}
|
||||||
if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
|
if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
|
||||||
t.Logf("%s", out)
|
t.Logf("%s", out)
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|
@ -306,6 +329,9 @@ func TestSignalForwardingExternal(t *testing.T) {
|
||||||
checkLineComments(t, "libgo2.h")
|
checkLineComments(t, "libgo2.h")
|
||||||
|
|
||||||
ccArgs := append(cc, "-o", "testp"+exeSuffix, "main5.c", "libgo2.a")
|
ccArgs := append(cc, "-o", "testp"+exeSuffix, "main5.c", "libgo2.a")
|
||||||
|
if runtime.Compiler == "gccgo" {
|
||||||
|
ccArgs = append(ccArgs, "-lgo")
|
||||||
|
}
|
||||||
if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
|
if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
|
||||||
t.Logf("%s", out)
|
t.Logf("%s", out)
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|
@ -419,6 +445,9 @@ func TestOsSignal(t *testing.T) {
|
||||||
checkLineComments(t, "libgo3.h")
|
checkLineComments(t, "libgo3.h")
|
||||||
|
|
||||||
ccArgs := append(cc, "-o", "testp"+exeSuffix, "main3.c", "libgo3.a")
|
ccArgs := append(cc, "-o", "testp"+exeSuffix, "main3.c", "libgo3.a")
|
||||||
|
if runtime.Compiler == "gccgo" {
|
||||||
|
ccArgs = append(ccArgs, "-lgo")
|
||||||
|
}
|
||||||
if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
|
if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
|
||||||
t.Logf("%s", out)
|
t.Logf("%s", out)
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|
@ -452,6 +481,9 @@ func TestSigaltstack(t *testing.T) {
|
||||||
checkLineComments(t, "libgo4.h")
|
checkLineComments(t, "libgo4.h")
|
||||||
|
|
||||||
ccArgs := append(cc, "-o", "testp"+exeSuffix, "main4.c", "libgo4.a")
|
ccArgs := append(cc, "-o", "testp"+exeSuffix, "main4.c", "libgo4.a")
|
||||||
|
if runtime.Compiler == "gccgo" {
|
||||||
|
ccArgs = append(ccArgs, "-lgo")
|
||||||
|
}
|
||||||
if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
|
if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
|
||||||
t.Logf("%s", out)
|
t.Logf("%s", out)
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|
@ -476,6 +508,9 @@ func TestExtar(t *testing.T) {
|
||||||
case "windows":
|
case "windows":
|
||||||
t.Skip("skipping signal test on Windows")
|
t.Skip("skipping signal test on Windows")
|
||||||
}
|
}
|
||||||
|
if runtime.Compiler == "gccgo" {
|
||||||
|
t.Skip("skipping -extar test when using gccgo")
|
||||||
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
os.Remove("libgo4.a")
|
os.Remove("libgo4.a")
|
||||||
|
|
@ -530,14 +565,26 @@ func TestPIE(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ccArgs := append(cc, "-fPIE", "-pie", "-o", "testp"+exeSuffix, "main.c", "main_unix.c", filepath.Join("pkg", libgodir, "libgo.a"))
|
libgoa := "libgo.a"
|
||||||
|
if runtime.Compiler == "gccgo" {
|
||||||
|
libgoa = "liblibgo.a"
|
||||||
|
}
|
||||||
|
|
||||||
|
ccArgs := append(cc, "-fPIE", "-pie", "-o", "testp"+exeSuffix, "main.c", "main_unix.c", filepath.Join("pkg", libgodir, libgoa))
|
||||||
|
if runtime.Compiler == "gccgo" {
|
||||||
|
ccArgs = append(ccArgs, "-lgo")
|
||||||
|
}
|
||||||
if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
|
if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
|
||||||
t.Logf("%s", out)
|
t.Logf("%s", out)
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
binArgs := append(bin, "arg1", "arg2")
|
binArgs := append(bin, "arg1", "arg2")
|
||||||
if out, err := exec.Command(binArgs[0], binArgs[1:]...).CombinedOutput(); err != nil {
|
cmd = exec.Command(binArgs[0], binArgs[1:]...)
|
||||||
|
if runtime.Compiler == "gccgo" {
|
||||||
|
cmd.Env = append(os.Environ(), "GCCGO=1")
|
||||||
|
}
|
||||||
|
if out, err := cmd.CombinedOutput(); err != nil {
|
||||||
t.Logf("%s", out)
|
t.Logf("%s", out)
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -605,6 +652,9 @@ func TestSIGPROF(t *testing.T) {
|
||||||
checkLineComments(t, "libgo6.h")
|
checkLineComments(t, "libgo6.h")
|
||||||
|
|
||||||
ccArgs := append(cc, "-o", "testp6"+exeSuffix, "main6.c", "libgo6.a")
|
ccArgs := append(cc, "-o", "testp6"+exeSuffix, "main6.c", "libgo6.a")
|
||||||
|
if runtime.Compiler == "gccgo" {
|
||||||
|
ccArgs = append(ccArgs, "-lgo")
|
||||||
|
}
|
||||||
if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
|
if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
|
||||||
t.Logf("%s", out)
|
t.Logf("%s", out)
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|
@ -648,6 +698,9 @@ func TestCompileWithoutShared(t *testing.T) {
|
||||||
// In some cases, -no-pie is needed here, but not accepted everywhere. First try
|
// In some cases, -no-pie is needed here, but not accepted everywhere. First try
|
||||||
// if -no-pie is accepted. See #22126.
|
// if -no-pie is accepted. See #22126.
|
||||||
ccArgs := append(cc, "-o", exe, "-no-pie", "main5.c", "libgo2.a")
|
ccArgs := append(cc, "-o", exe, "-no-pie", "main5.c", "libgo2.a")
|
||||||
|
if runtime.Compiler == "gccgo" {
|
||||||
|
ccArgs = append(ccArgs, "-lgo")
|
||||||
|
}
|
||||||
t.Log(ccArgs)
|
t.Log(ccArgs)
|
||||||
out, err = exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput()
|
out, err = exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
struct sigaction sa;
|
struct sigaction sa;
|
||||||
|
|
@ -30,7 +31,12 @@ int install_handler() {
|
||||||
perror("sigaction");
|
perror("sigaction");
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
if (osa.sa_handler == SIG_DFL || (osa.sa_flags&SA_ONSTACK) == 0) {
|
if (osa.sa_handler == SIG_DFL) {
|
||||||
|
fprintf(stderr, "Go runtime did not install signal handler\n");
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
// gccgo does not set SA_ONSTACK for SIGSEGV.
|
||||||
|
if (getenv("GCCGO") == "" && (osa.sa_flags&SA_ONSTACK) == 0) {
|
||||||
fprintf(stderr, "Go runtime did not install signal handler\n");
|
fprintf(stderr, "Go runtime did not install signal handler\n");
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,13 +29,13 @@ func ResetSIGIO() {
|
||||||
signal.Reset(syscall.SIGIO)
|
signal.Reset(syscall.SIGIO)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SawSIGIO returns whether we saw a SIGIO within a brief pause.
|
// SawSIGIO reports whether we saw a SIGIO.
|
||||||
//export SawSIGIO
|
//export SawSIGIO
|
||||||
func SawSIGIO() C.int {
|
func SawSIGIO() C.int {
|
||||||
select {
|
select {
|
||||||
case <-sigioChan:
|
case <-sigioChan:
|
||||||
return 1
|
return 1
|
||||||
case <-time.After(100 * time.Millisecond):
|
case <-time.After(5 * time.Second):
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -201,6 +201,16 @@ func run(t *testing.T, env []string, args ...string) string {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
cmd := exec.Command(args[0], args[1:]...)
|
cmd := exec.Command(args[0], args[1:]...)
|
||||||
cmd.Env = env
|
cmd.Env = env
|
||||||
|
|
||||||
|
if GOOS != "windows" {
|
||||||
|
// TestUnexportedSymbols relies on file descriptor 30
|
||||||
|
// being closed when the program starts, so enforce
|
||||||
|
// that in all cases. (The first three descriptors are
|
||||||
|
// stdin/stdout/stderr, so we just need to make sure
|
||||||
|
// that cmd.ExtraFiles[27] exists and is nil.)
|
||||||
|
cmd.ExtraFiles = make([]*os.File, 28)
|
||||||
|
}
|
||||||
|
|
||||||
out, err := cmd.CombinedOutput()
|
out, err := cmd.CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("command failed: %v\n%v\n%s\n", args, err, out)
|
t.Fatalf("command failed: %v\n%v\n%s\n", args, err, out)
|
||||||
|
|
|
||||||
18
misc/cgo/testgodefs/fieldtypedef.go
Normal file
18
misc/cgo/testgodefs/fieldtypedef.go
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
// Copyright 2018 The Go Authors. All rights reserve d.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
//
|
||||||
|
// +build ignore
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
/*
|
||||||
|
struct S1 { int f1; };
|
||||||
|
struct S2 { struct S1 s1; };
|
||||||
|
typedef struct S1 S1Type;
|
||||||
|
typedef struct S2 S2Type;
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
type S1 C.S1Type
|
||||||
|
type S2 C.S2Type
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
# We are testing cgo -godefs, which translates Go files that use
|
# We are testing cgo -godefs, which translates Go files that use
|
||||||
# import "C" into Go files with Go definitions of types defined in the
|
# import "C" into Go files with Go definitions of types defined in the
|
||||||
# import "C" block. Add more tests here.
|
# import "C" block. Add more tests here.
|
||||||
FILE_PREFIXES="anonunion issue8478"
|
FILE_PREFIXES="anonunion issue8478 fieldtypedef"
|
||||||
|
|
||||||
RM=
|
RM=
|
||||||
for FP in $FILE_PREFIXES
|
for FP in $FILE_PREFIXES
|
||||||
|
|
|
||||||
106
misc/cgo/testplugin/src/checkdwarf/main.go
Normal file
106
misc/cgo/testplugin/src/checkdwarf/main.go
Normal file
|
|
@ -0,0 +1,106 @@
|
||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Usage:
|
||||||
|
//
|
||||||
|
// checkdwarf <exe> <suffix>
|
||||||
|
//
|
||||||
|
// Opens <exe>, which must be an executable or a library and checks that
|
||||||
|
// there is an entry in .debug_info whose name ends in <suffix>
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"debug/dwarf"
|
||||||
|
"debug/elf"
|
||||||
|
"debug/macho"
|
||||||
|
"debug/pe"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func usage() {
|
||||||
|
fmt.Fprintf(os.Stderr, "checkdwarf executable-or-library DIE-suffix\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
type dwarfer interface {
|
||||||
|
DWARF() (*dwarf.Data, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func openElf(path string) dwarfer {
|
||||||
|
exe, err := elf.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return exe
|
||||||
|
}
|
||||||
|
|
||||||
|
func openMacho(path string) dwarfer {
|
||||||
|
exe, err := macho.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return exe
|
||||||
|
}
|
||||||
|
|
||||||
|
func openPE(path string) dwarfer {
|
||||||
|
exe, err := pe.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return exe
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
if len(os.Args) != 3 {
|
||||||
|
usage()
|
||||||
|
}
|
||||||
|
|
||||||
|
exePath := os.Args[1]
|
||||||
|
dieSuffix := os.Args[2]
|
||||||
|
|
||||||
|
var exe dwarfer
|
||||||
|
|
||||||
|
for _, openfn := range []func(string) dwarfer{openMacho, openPE, openElf} {
|
||||||
|
exe = openfn(exePath)
|
||||||
|
if exe != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if exe == nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "could not open %s\n", exePath)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := exe.DWARF()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "%s: error opening DWARF: %v\n", exePath, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
rdr := data.Reader()
|
||||||
|
for {
|
||||||
|
e, err := rdr.Next()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "%s: error reading DWARF: %v\n", exePath, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
if e == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
name, hasname := e.Val(dwarf.AttrName).(string)
|
||||||
|
if !hasname {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if strings.HasSuffix(name, dieSuffix) {
|
||||||
|
// found
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintf(os.Stderr, "%s: no entry with a name ending in %q was found\n", exePath, dieSuffix)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
@ -32,6 +32,14 @@ GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" -buildmode=plugin -o=unnamed1.so u
|
||||||
GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" -buildmode=plugin -o=unnamed2.so unnamed2/main.go
|
GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" -buildmode=plugin -o=unnamed2.so unnamed2/main.go
|
||||||
GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" host
|
GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" host
|
||||||
|
|
||||||
|
# test that DWARF sections are emitted for plugins and programs importing "plugin"
|
||||||
|
if [ $GOOS != "darwin" ]; then
|
||||||
|
# On macOS, for some reason, the linker doesn't add debug sections to .so,
|
||||||
|
# see issue #27502.
|
||||||
|
go run src/checkdwarf/main.go plugin2.so plugin2.UnexportedNameReuse
|
||||||
|
fi
|
||||||
|
go run src/checkdwarf/main.go host main.main
|
||||||
|
|
||||||
LD_LIBRARY_PATH=$(pwd) ./host
|
LD_LIBRARY_PATH=$(pwd) ./host
|
||||||
|
|
||||||
# Test that types and itabs get properly uniqified.
|
# Test that types and itabs get properly uniqified.
|
||||||
|
|
|
||||||
|
|
@ -381,12 +381,13 @@ func (c *config) checkRuntime() (skip bool, err error) {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
cmd.Args = append(cmd.Args, "-dM", "-E", "../../../src/runtime/cgo/libcgo.h")
|
cmd.Args = append(cmd.Args, "-dM", "-E", "../../../src/runtime/cgo/libcgo.h")
|
||||||
|
cmdStr := strings.Join(cmd.Args, " ")
|
||||||
out, err := cmd.CombinedOutput()
|
out, err := cmd.CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, fmt.Errorf("%#q exited with %v\n%s", strings.Join(cmd.Args, " "), err, out)
|
return false, fmt.Errorf("%#q exited with %v\n%s", cmdStr, err, out)
|
||||||
}
|
}
|
||||||
if !bytes.Contains(out, []byte("#define CGO_TSAN")) {
|
if !bytes.Contains(out, []byte("#define CGO_TSAN")) {
|
||||||
return true, fmt.Errorf("%#q did not define CGO_TSAN")
|
return true, fmt.Errorf("%#q did not define CGO_TSAN", cmdStr)
|
||||||
}
|
}
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ func TestMSAN(t *testing.T) {
|
||||||
{src: "msan3.go"},
|
{src: "msan3.go"},
|
||||||
{src: "msan4.go"},
|
{src: "msan4.go"},
|
||||||
{src: "msan5.go"},
|
{src: "msan5.go"},
|
||||||
|
{src: "msan6.go"},
|
||||||
{src: "msan_fail.go", wantErr: true},
|
{src: "msan_fail.go", wantErr: true},
|
||||||
}
|
}
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
|
|
|
||||||
72
misc/cgo/testsanitizers/src/msan6.go
Normal file
72
misc/cgo/testsanitizers/src/msan6.go
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
// A C function returning a value on the Go stack could leave the Go
|
||||||
|
// stack marked as uninitialized, potentially causing a later error
|
||||||
|
// when the stack is used for something else. Issue 26209.
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo LDFLAGS: -fsanitize=memory
|
||||||
|
#cgo CPPFLAGS: -fsanitize=memory
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uintptr_t a[20];
|
||||||
|
} S;
|
||||||
|
|
||||||
|
S f() {
|
||||||
|
S *p;
|
||||||
|
|
||||||
|
p = (S *)(malloc(sizeof(S)));
|
||||||
|
p->a[0] = 0;
|
||||||
|
return *p;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
// allocateStack extends the stack so that stack copying doesn't
|
||||||
|
// confuse the msan data structures.
|
||||||
|
//go:noinline
|
||||||
|
func allocateStack(i int) int {
|
||||||
|
if i == 0 {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
return allocateStack(i - 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// F1 marks a chunk of stack as uninitialized.
|
||||||
|
// C.f returns an uninitialized struct on the stack, so msan will mark
|
||||||
|
// the stack as uninitialized.
|
||||||
|
//go:noinline
|
||||||
|
func F1() uintptr {
|
||||||
|
s := C.f()
|
||||||
|
return uintptr(s.a[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
// F2 allocates a struct on the stack and converts it to an empty interface,
|
||||||
|
// which will call msanread and see that the data appears uninitialized.
|
||||||
|
//go:noinline
|
||||||
|
func F2() interface{} {
|
||||||
|
return C.S{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func poisonStack(i int) int {
|
||||||
|
if i == 0 {
|
||||||
|
return int(F1())
|
||||||
|
}
|
||||||
|
F1()
|
||||||
|
r := poisonStack(i - 1)
|
||||||
|
F2()
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
allocateStack(16384)
|
||||||
|
poisonStack(128)
|
||||||
|
}
|
||||||
|
|
@ -560,7 +560,7 @@ func TestNotes(t *testing.T) {
|
||||||
abiHashNoteFound = true
|
abiHashNoteFound = true
|
||||||
case 3: // ELF_NOTE_GODEPS_TAG
|
case 3: // ELF_NOTE_GODEPS_TAG
|
||||||
if depsNoteFound {
|
if depsNoteFound {
|
||||||
t.Error("multiple depedency list notes")
|
t.Error("multiple dependency list notes")
|
||||||
}
|
}
|
||||||
testDepsNote(t, f, note)
|
testDepsNote(t, f, note)
|
||||||
depsNoteFound = true
|
depsNoteFound = true
|
||||||
|
|
@ -905,3 +905,9 @@ func TestGlobal(t *testing.T) {
|
||||||
AssertIsLinkedTo(t, "./bin/global", soname)
|
AssertIsLinkedTo(t, "./bin/global", soname)
|
||||||
AssertHasRPath(t, "./bin/global", gorootInstallDir)
|
AssertHasRPath(t, "./bin/global", gorootInstallDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Run a test using -linkshared of an installed shared package.
|
||||||
|
// Issue 26400.
|
||||||
|
func TestTestInstalledShared(t *testing.T) {
|
||||||
|
goCmd(nil, "test", "-linkshared", "-test.short", "sync/atomic")
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//+build !gccgo
|
// +build !gccgo
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,7 @@
|
||||||
|
// Copyright 2016 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 depBase
|
package depBase
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,8 @@
|
||||||
//+build gccgo
|
// Copyright 2016 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.
|
||||||
|
|
||||||
|
// +build gccgo
|
||||||
|
|
||||||
package depBase
|
package depBase
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,8 @@
|
||||||
//+build !gccgo
|
// Copyright 2016 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.
|
||||||
|
|
||||||
|
// +build !gccgo
|
||||||
|
|
||||||
package depBase
|
package depBase
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,8 @@ license that can be found in the LICENSE file.
|
||||||
mod = result.module;
|
mod = result.module;
|
||||||
inst = result.instance;
|
inst = result.instance;
|
||||||
document.getElementById("runButton").disabled = false;
|
document.getElementById("runButton").disabled = false;
|
||||||
|
}).catch((err) => {
|
||||||
|
console.error(err);
|
||||||
});
|
});
|
||||||
|
|
||||||
async function run() {
|
async function run() {
|
||||||
|
|
|
||||||
|
|
@ -27,11 +27,17 @@
|
||||||
global.TextEncoder = util.TextEncoder;
|
global.TextEncoder = util.TextEncoder;
|
||||||
global.TextDecoder = util.TextDecoder;
|
global.TextDecoder = util.TextDecoder;
|
||||||
} else {
|
} else {
|
||||||
window.global = window;
|
if (typeof window !== "undefined") {
|
||||||
|
window.global = window;
|
||||||
|
} else if (typeof self !== "undefined") {
|
||||||
|
self.global = self;
|
||||||
|
} else {
|
||||||
|
throw new Error("cannot export Go (neither window nor self is defined)");
|
||||||
|
}
|
||||||
|
|
||||||
let outputBuf = "";
|
let outputBuf = "";
|
||||||
global.fs = {
|
global.fs = {
|
||||||
constants: { O_WRONLY: -1, O_RDWR: -1, O_CREAT: -1, O_TRUNC: -1, O_APPEND: -1, O_EXCL: -1, O_NONBLOCK: -1, O_SYNC: -1 }, // unused
|
constants: { O_WRONLY: -1, O_RDWR: -1, O_CREAT: -1, O_TRUNC: -1, O_APPEND: -1, O_EXCL: -1 }, // unused
|
||||||
writeSync(fd, buf) {
|
writeSync(fd, buf) {
|
||||||
outputBuf += decoder.decode(buf);
|
outputBuf += decoder.decode(buf);
|
||||||
const nl = outputBuf.lastIndexOf("\n");
|
const nl = outputBuf.lastIndexOf("\n");
|
||||||
|
|
@ -91,9 +97,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
const storeValue = (addr, v) => {
|
const storeValue = (addr, v) => {
|
||||||
|
const nanHead = 0x7FF80000;
|
||||||
|
|
||||||
if (typeof v === "number") {
|
if (typeof v === "number") {
|
||||||
if (isNaN(v)) {
|
if (isNaN(v)) {
|
||||||
mem().setUint32(addr + 4, 0x7FF80000, true); // NaN
|
mem().setUint32(addr + 4, nanHead, true);
|
||||||
mem().setUint32(addr, 0, true);
|
mem().setUint32(addr, 0, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -101,51 +109,44 @@
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mem().setUint32(addr + 4, 0x7FF80000, true); // NaN
|
|
||||||
|
|
||||||
switch (v) {
|
switch (v) {
|
||||||
case undefined:
|
case undefined:
|
||||||
|
mem().setUint32(addr + 4, nanHead, true);
|
||||||
mem().setUint32(addr, 1, true);
|
mem().setUint32(addr, 1, true);
|
||||||
return;
|
return;
|
||||||
case null:
|
case null:
|
||||||
|
mem().setUint32(addr + 4, nanHead, true);
|
||||||
mem().setUint32(addr, 2, true);
|
mem().setUint32(addr, 2, true);
|
||||||
return;
|
return;
|
||||||
case true:
|
case true:
|
||||||
|
mem().setUint32(addr + 4, nanHead, true);
|
||||||
mem().setUint32(addr, 3, true);
|
mem().setUint32(addr, 3, true);
|
||||||
return;
|
return;
|
||||||
case false:
|
case false:
|
||||||
|
mem().setUint32(addr + 4, nanHead, true);
|
||||||
mem().setUint32(addr, 4, true);
|
mem().setUint32(addr, 4, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof v === "string") {
|
let ref = this._refs.get(v);
|
||||||
let ref = this._stringRefs.get(v);
|
|
||||||
if (ref === undefined) {
|
|
||||||
ref = this._values.length;
|
|
||||||
this._values.push(v);
|
|
||||||
this._stringRefs.set(v, ref);
|
|
||||||
}
|
|
||||||
mem().setUint32(addr, ref, true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof v === "symbol") {
|
|
||||||
let ref = this._symbolRefs.get(v);
|
|
||||||
if (ref === undefined) {
|
|
||||||
ref = this._values.length;
|
|
||||||
this._values.push(v);
|
|
||||||
this._symbolRefs.set(v, ref);
|
|
||||||
}
|
|
||||||
mem().setUint32(addr, ref, true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let ref = v[this._refProp];
|
|
||||||
if (ref === undefined) {
|
if (ref === undefined) {
|
||||||
ref = this._values.length;
|
ref = this._values.length;
|
||||||
this._values.push(v);
|
this._values.push(v);
|
||||||
v[this._refProp] = ref;
|
this._refs.set(v, ref);
|
||||||
}
|
}
|
||||||
|
let typeFlag = 0;
|
||||||
|
switch (typeof v) {
|
||||||
|
case "string":
|
||||||
|
typeFlag = 1;
|
||||||
|
break;
|
||||||
|
case "symbol":
|
||||||
|
typeFlag = 2;
|
||||||
|
break;
|
||||||
|
case "function":
|
||||||
|
typeFlag = 3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
mem().setUint32(addr + 4, nanHead | typeFlag, true);
|
||||||
mem().setUint32(addr, ref, true);
|
mem().setUint32(addr, ref, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -176,8 +177,12 @@
|
||||||
go: {
|
go: {
|
||||||
// func wasmExit(code int32)
|
// func wasmExit(code int32)
|
||||||
"runtime.wasmExit": (sp) => {
|
"runtime.wasmExit": (sp) => {
|
||||||
|
const code = mem().getInt32(sp + 8, true);
|
||||||
this.exited = true;
|
this.exited = true;
|
||||||
this.exit(mem().getInt32(sp + 8, true));
|
delete this._inst;
|
||||||
|
delete this._values;
|
||||||
|
delete this._refs;
|
||||||
|
this.exit(code);
|
||||||
},
|
},
|
||||||
|
|
||||||
// func wasmWrite(fd uintptr, p unsafe.Pointer, n int32)
|
// func wasmWrite(fd uintptr, p unsafe.Pointer, n int32)
|
||||||
|
|
@ -328,16 +333,10 @@
|
||||||
false,
|
false,
|
||||||
global,
|
global,
|
||||||
this._inst.exports.mem,
|
this._inst.exports.mem,
|
||||||
() => { // resolveCallbackPromise
|
this,
|
||||||
if (this.exited) {
|
|
||||||
throw new Error("bad callback: Go program has already exited");
|
|
||||||
}
|
|
||||||
setTimeout(this._resolveCallbackPromise, 0); // make sure it is asynchronous
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
this._stringRefs = new Map();
|
this._refs = new Map();
|
||||||
this._symbolRefs = new Map();
|
this._callbackShutdown = false;
|
||||||
this._refProp = Symbol();
|
|
||||||
this.exited = false;
|
this.exited = false;
|
||||||
|
|
||||||
const mem = new DataView(this._inst.exports.mem.buffer)
|
const mem = new DataView(this._inst.exports.mem.buffer)
|
||||||
|
|
@ -374,7 +373,12 @@
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
const callbackPromise = new Promise((resolve) => {
|
const callbackPromise = new Promise((resolve) => {
|
||||||
this._resolveCallbackPromise = resolve;
|
this._resolveCallbackPromise = () => {
|
||||||
|
if (this.exited) {
|
||||||
|
throw new Error("bad callback: Go program has already exited");
|
||||||
|
}
|
||||||
|
setTimeout(resolve, 0); // make sure it is asynchronous
|
||||||
|
};
|
||||||
});
|
});
|
||||||
this._inst.exports.run(argc, argv);
|
this._inst.exports.run(argc, argv);
|
||||||
if (this.exited) {
|
if (this.exited) {
|
||||||
|
|
@ -383,6 +387,28 @@
|
||||||
await callbackPromise;
|
await callbackPromise;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static _makeCallbackHelper(id, pendingCallbacks, go) {
|
||||||
|
return function() {
|
||||||
|
pendingCallbacks.push({ id: id, args: arguments });
|
||||||
|
go._resolveCallbackPromise();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static _makeEventCallbackHelper(preventDefault, stopPropagation, stopImmediatePropagation, fn) {
|
||||||
|
return function(event) {
|
||||||
|
if (preventDefault) {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
if (stopPropagation) {
|
||||||
|
event.stopPropagation();
|
||||||
|
}
|
||||||
|
if (stopImmediatePropagation) {
|
||||||
|
event.stopImmediatePropagation();
|
||||||
|
}
|
||||||
|
fn(event);
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isNodeJS) {
|
if (isNodeJS) {
|
||||||
|
|
@ -396,17 +422,16 @@
|
||||||
go.env = process.env;
|
go.env = process.env;
|
||||||
go.exit = process.exit;
|
go.exit = process.exit;
|
||||||
WebAssembly.instantiate(fs.readFileSync(process.argv[2]), go.importObject).then((result) => {
|
WebAssembly.instantiate(fs.readFileSync(process.argv[2]), go.importObject).then((result) => {
|
||||||
process.on("exit", () => { // Node.js exits if no callback is pending
|
process.on("exit", (code) => { // Node.js exits if no callback is pending
|
||||||
if (!go.exited) {
|
if (code === 0 && !go.exited) {
|
||||||
console.error("error: all goroutines asleep and no JavaScript callback pending - deadlock!");
|
// deadlock, make Go print error and stack traces
|
||||||
process.exit(1);
|
go._callbackShutdown = true;
|
||||||
|
go._inst.exports.run();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return go.run(result.instance);
|
return go.run(result.instance);
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
console.error(err);
|
throw err;
|
||||||
go.exited = true;
|
|
||||||
process.exit(1);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
|
||||||
|
|
@ -160,7 +160,7 @@ func (b *block) V7() *headerV7 { return (*headerV7)(b) }
|
||||||
func (b *block) GNU() *headerGNU { return (*headerGNU)(b) }
|
func (b *block) GNU() *headerGNU { return (*headerGNU)(b) }
|
||||||
func (b *block) STAR() *headerSTAR { return (*headerSTAR)(b) }
|
func (b *block) STAR() *headerSTAR { return (*headerSTAR)(b) }
|
||||||
func (b *block) USTAR() *headerUSTAR { return (*headerUSTAR)(b) }
|
func (b *block) USTAR() *headerUSTAR { return (*headerUSTAR)(b) }
|
||||||
func (b *block) Sparse() sparseArray { return (sparseArray)(b[:]) }
|
func (b *block) Sparse() sparseArray { return sparseArray(b[:]) }
|
||||||
|
|
||||||
// GetFormat checks that the block is a valid tar header based on the checksum.
|
// GetFormat checks that the block is a valid tar header based on the checksum.
|
||||||
// It then attempts to guess the specific format based on magic values.
|
// It then attempts to guess the specific format based on magic values.
|
||||||
|
|
@ -263,7 +263,7 @@ func (h *headerGNU) DevMajor() []byte { return h[329:][:8] }
|
||||||
func (h *headerGNU) DevMinor() []byte { return h[337:][:8] }
|
func (h *headerGNU) DevMinor() []byte { return h[337:][:8] }
|
||||||
func (h *headerGNU) AccessTime() []byte { return h[345:][:12] }
|
func (h *headerGNU) AccessTime() []byte { return h[345:][:12] }
|
||||||
func (h *headerGNU) ChangeTime() []byte { return h[357:][:12] }
|
func (h *headerGNU) ChangeTime() []byte { return h[357:][:12] }
|
||||||
func (h *headerGNU) Sparse() sparseArray { return (sparseArray)(h[386:][:24*4+1]) }
|
func (h *headerGNU) Sparse() sparseArray { return sparseArray(h[386:][:24*4+1]) }
|
||||||
func (h *headerGNU) RealSize() []byte { return h[483:][:12] }
|
func (h *headerGNU) RealSize() []byte { return h[483:][:12] }
|
||||||
|
|
||||||
type headerSTAR [blockSize]byte
|
type headerSTAR [blockSize]byte
|
||||||
|
|
@ -293,7 +293,7 @@ func (h *headerUSTAR) Prefix() []byte { return h[345:][:155] }
|
||||||
|
|
||||||
type sparseArray []byte
|
type sparseArray []byte
|
||||||
|
|
||||||
func (s sparseArray) Entry(i int) sparseElem { return (sparseElem)(s[i*24:]) }
|
func (s sparseArray) Entry(i int) sparseElem { return sparseElem(s[i*24:]) }
|
||||||
func (s sparseArray) IsExtended() []byte { return s[24*s.MaxEntries():][:1] }
|
func (s sparseArray) IsExtended() []byte { return s[24*s.MaxEntries():][:1] }
|
||||||
func (s sparseArray) MaxEntries() int { return len(s) / 24 }
|
func (s sparseArray) MaxEntries() int { return len(s) / 24 }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,9 @@ func OpenReader(name string) (*ReadCloser, error) {
|
||||||
// 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.
|
// have the given size in bytes.
|
||||||
func NewReader(r io.ReaderAt, size int64) (*Reader, error) {
|
func NewReader(r io.ReaderAt, size int64) (*Reader, error) {
|
||||||
|
if size < 0 {
|
||||||
|
return nil, errors.New("zip: size cannot be negative")
|
||||||
|
}
|
||||||
zr := new(Reader)
|
zr := new(Reader)
|
||||||
if err := zr.init(r, size); err != nil {
|
if err := zr.init(r, size); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
||||||
|
|
@ -658,6 +658,12 @@ func TestInvalidFiles(t *testing.T) {
|
||||||
if err != ErrFormat {
|
if err != ErrFormat {
|
||||||
t.Errorf("sigs: error=%v, want %v", err, ErrFormat)
|
t.Errorf("sigs: error=%v, want %v", err, ErrFormat)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// negative size
|
||||||
|
_, err = NewReader(bytes.NewReader([]byte("foobar")), -1)
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("archive/zip.NewReader: expected error when negative size is passed")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func messWith(fileName string, corrupter func(b []byte)) (r io.ReaderAt, size int64) {
|
func messWith(fileName string, corrupter func(b []byte)) (r io.ReaderAt, size int64) {
|
||||||
|
|
|
||||||
|
|
@ -303,8 +303,8 @@ func (h *FileHeader) SetMode(mode os.FileMode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// isZip64 reports whether the file size exceeds the 32 bit limit
|
// isZip64 reports whether the file size exceeds the 32 bit limit
|
||||||
func (fh *FileHeader) isZip64() bool {
|
func (h *FileHeader) isZip64() bool {
|
||||||
return fh.CompressedSize64 >= uint32max || fh.UncompressedSize64 >= uint32max
|
return h.CompressedSize64 >= uint32max || h.UncompressedSize64 >= uint32max
|
||||||
}
|
}
|
||||||
|
|
||||||
func msdosModeToFileMode(m uint32) (mode os.FileMode) {
|
func msdosModeToFileMode(m uint32) (mode os.FileMode) {
|
||||||
|
|
|
||||||
|
|
@ -336,6 +336,12 @@ func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error) {
|
||||||
fh.Method = Store
|
fh.Method = Store
|
||||||
fh.Flags &^= 0x8 // we will not write a data descriptor
|
fh.Flags &^= 0x8 // we will not write a data descriptor
|
||||||
|
|
||||||
|
// Explicitly clear sizes as they have no meaning for directories.
|
||||||
|
fh.CompressedSize = 0
|
||||||
|
fh.CompressedSize64 = 0
|
||||||
|
fh.UncompressedSize = 0
|
||||||
|
fh.UncompressedSize64 = 0
|
||||||
|
|
||||||
ow = dirWriter{}
|
ow = dirWriter{}
|
||||||
} else {
|
} else {
|
||||||
fh.Flags |= 0x8 // we will write a data descriptor
|
fh.Flags |= 0x8 // we will write a data descriptor
|
||||||
|
|
@ -419,7 +425,10 @@ func (w *Writer) compressor(method uint16) Compressor {
|
||||||
|
|
||||||
type dirWriter struct{}
|
type dirWriter struct{}
|
||||||
|
|
||||||
func (dirWriter) Write([]byte) (int, error) {
|
func (dirWriter) Write(b []byte) (int, error) {
|
||||||
|
if len(b) == 0 {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
return 0, errors.New("zip: write to directory")
|
return 0, errors.New("zip: write to directory")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -306,21 +306,28 @@ func TestWriterDir(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
if _, err := dw.Write(nil); err != nil {
|
||||||
|
t.Errorf("Write(nil) to directory: got %v, want nil", err)
|
||||||
|
}
|
||||||
if _, err := dw.Write([]byte("hello")); err == nil {
|
if _, err := dw.Write([]byte("hello")); err == nil {
|
||||||
t.Error("Write to directory: got nil error, want non-nil")
|
t.Error(`Write("hello") to directory: got nil error, want non-nil`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWriterDirAttributes(t *testing.T) {
|
func TestWriterDirAttributes(t *testing.T) {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
w := NewWriter(&buf)
|
w := NewWriter(&buf)
|
||||||
if _, err := w.Create("dir/"); err != nil {
|
if _, err := w.CreateHeader(&FileHeader{
|
||||||
|
Name: "dir/",
|
||||||
|
Method: Deflate,
|
||||||
|
CompressedSize64: 1234,
|
||||||
|
UncompressedSize64: 5678,
|
||||||
|
}); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if err := w.Close(); err != nil {
|
if err := w.Close(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
b := buf.Bytes()
|
b := buf.Bytes()
|
||||||
|
|
||||||
var sig [4]byte
|
var sig [4]byte
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ func NewReader(rd io.Reader) *Reader {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Size returns the size of the underlying buffer in bytes.
|
// Size returns the size of the underlying buffer in bytes.
|
||||||
func (r *Reader) Size() int { return len(r.buf) }
|
func (b *Reader) Size() int { return len(b.buf) }
|
||||||
|
|
||||||
// Reset discards any buffered data, resets all state, and switches
|
// Reset discards any buffered data, resets all state, and switches
|
||||||
// the buffered reader to read from r.
|
// the buffered reader to read from r.
|
||||||
|
|
@ -314,9 +314,11 @@ func (b *Reader) Buffered() int { return b.w - b.r }
|
||||||
// ReadBytes or ReadString instead.
|
// ReadBytes or ReadString instead.
|
||||||
// ReadSlice returns err != nil if and only if line does not end in delim.
|
// ReadSlice returns err != nil if and only if line does not end in delim.
|
||||||
func (b *Reader) ReadSlice(delim byte) (line []byte, err error) {
|
func (b *Reader) ReadSlice(delim byte) (line []byte, err error) {
|
||||||
|
s := 0 // search start index
|
||||||
for {
|
for {
|
||||||
// Search buffer.
|
// Search buffer.
|
||||||
if i := bytes.IndexByte(b.buf[b.r:b.w], delim); i >= 0 {
|
if i := bytes.IndexByte(b.buf[b.r+s:b.w], delim); i >= 0 {
|
||||||
|
i += s
|
||||||
line = b.buf[b.r : b.r+i+1]
|
line = b.buf[b.r : b.r+i+1]
|
||||||
b.r += i + 1
|
b.r += i + 1
|
||||||
break
|
break
|
||||||
|
|
@ -338,6 +340,8 @@ func (b *Reader) ReadSlice(delim byte) (line []byte, err error) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s = b.w - b.r // do not rescan area we scanned before
|
||||||
|
|
||||||
b.fill() // buffer is not full
|
b.fill() // buffer is not full
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -441,9 +441,9 @@ func (b *Buffer) ReadString(delim byte) (line string, err error) {
|
||||||
// NewBuffer creates and initializes a new Buffer using buf as its
|
// NewBuffer creates and initializes a new Buffer using buf as its
|
||||||
// initial contents. The new Buffer takes ownership of buf, and the
|
// initial contents. The new Buffer takes ownership of buf, and the
|
||||||
// caller should not use buf after this call. NewBuffer is intended to
|
// 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 size
|
// prepare a Buffer to read existing data. It can also be used to set
|
||||||
// the internal buffer for writing. To do that, buf should have the
|
// the initial size of the internal buffer for writing. To do that,
|
||||||
// desired capacity but a length of zero.
|
// buf should have the desired capacity but a length of zero.
|
||||||
//
|
//
|
||||||
// In most cases, new(Buffer) (or just declaring a Buffer variable) is
|
// In most cases, new(Buffer) (or just declaring a Buffer variable) is
|
||||||
// sufficient to initialize a Buffer.
|
// sufficient to initialize a Buffer.
|
||||||
|
|
|
||||||
|
|
@ -293,7 +293,7 @@ func TestReadFromPanicReader(t *testing.T) {
|
||||||
}
|
}
|
||||||
check(t, "TestReadFromPanicReader (1)", &buf, "")
|
check(t, "TestReadFromPanicReader (1)", &buf, "")
|
||||||
|
|
||||||
// Confirm that when Reader panics, the emtpy buffer remains empty
|
// Confirm that when Reader panics, the empty buffer remains empty
|
||||||
var buf2 Buffer
|
var buf2 Buffer
|
||||||
defer func() {
|
defer func() {
|
||||||
recover()
|
recover()
|
||||||
|
|
|
||||||
|
|
@ -489,19 +489,19 @@ func ToTitle(s []byte) []byte { return Map(unicode.ToTitle, s) }
|
||||||
// ToUpperSpecial treats s as UTF-8-encoded bytes and returns a copy with all the Unicode letters mapped to their
|
// ToUpperSpecial treats s as UTF-8-encoded bytes and returns a copy with all the Unicode letters mapped to their
|
||||||
// upper case, giving priority to the special casing rules.
|
// upper case, giving priority to the special casing rules.
|
||||||
func ToUpperSpecial(c unicode.SpecialCase, s []byte) []byte {
|
func ToUpperSpecial(c unicode.SpecialCase, s []byte) []byte {
|
||||||
return Map(func(r rune) rune { return c.ToUpper(r) }, s)
|
return Map(c.ToUpper, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToLowerSpecial treats s as UTF-8-encoded bytes and returns a copy with all the Unicode letters mapped to their
|
// ToLowerSpecial treats s as UTF-8-encoded bytes and returns a copy with all the Unicode letters mapped to their
|
||||||
// lower case, giving priority to the special casing rules.
|
// lower case, giving priority to the special casing rules.
|
||||||
func ToLowerSpecial(c unicode.SpecialCase, s []byte) []byte {
|
func ToLowerSpecial(c unicode.SpecialCase, s []byte) []byte {
|
||||||
return Map(func(r rune) rune { return c.ToLower(r) }, s)
|
return Map(c.ToLower, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToTitleSpecial treats s as UTF-8-encoded bytes and returns a copy with all the Unicode letters mapped to their
|
// ToTitleSpecial treats s as UTF-8-encoded bytes and returns a copy with all the Unicode letters mapped to their
|
||||||
// title case, giving priority to the special casing rules.
|
// title case, giving priority to the special casing rules.
|
||||||
func ToTitleSpecial(c unicode.SpecialCase, s []byte) []byte {
|
func ToTitleSpecial(c unicode.SpecialCase, s []byte) []byte {
|
||||||
return Map(func(r rune) rune { return c.ToTitle(r) }, s)
|
return Map(c.ToTitle, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
// isSeparator reports whether the rune could mark a word boundary.
|
// isSeparator reports whether the rune could mark a word boundary.
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ package bytes_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
. "bytes"
|
. "bytes"
|
||||||
|
"internal/testenv"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -58,10 +59,20 @@ func TestCompareIdenticalSlice(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCompareBytes(t *testing.T) {
|
func TestCompareBytes(t *testing.T) {
|
||||||
n := 128
|
lengths := make([]int, 0) // lengths to test in ascending order
|
||||||
|
for i := 0; i <= 128; i++ {
|
||||||
|
lengths = append(lengths, i)
|
||||||
|
}
|
||||||
|
lengths = append(lengths, 256, 512, 1024, 1333, 4095, 4096, 4097)
|
||||||
|
|
||||||
|
if !testing.Short() || testenv.Builder() != "" {
|
||||||
|
lengths = append(lengths, 65535, 65536, 65537, 99999)
|
||||||
|
}
|
||||||
|
|
||||||
|
n := lengths[len(lengths)-1]
|
||||||
a := make([]byte, n+1)
|
a := make([]byte, n+1)
|
||||||
b := make([]byte, n+1)
|
b := make([]byte, n+1)
|
||||||
for len := 0; len < 128; len++ {
|
for _, len := range lengths {
|
||||||
// randomish but deterministic data. No 0 or 255.
|
// randomish but deterministic data. No 0 or 255.
|
||||||
for i := 0; i < len; i++ {
|
for i := 0; i < len; i++ {
|
||||||
a[i] = byte(1 + 31*i%254)
|
a[i] = byte(1 + 31*i%254)
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,14 @@ func ExampleBuffer_Grow() {
|
||||||
// Output: "64 bytes or fewer"
|
// Output: "64 bytes or fewer"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExampleBuffer_Len() {
|
||||||
|
var b bytes.Buffer
|
||||||
|
b.Grow(64)
|
||||||
|
b.Write([]byte("abcde"))
|
||||||
|
fmt.Printf("%d", b.Len())
|
||||||
|
// Output: 5
|
||||||
|
}
|
||||||
|
|
||||||
func ExampleCompare() {
|
func ExampleCompare() {
|
||||||
// Interpret Compare's result by comparing it to zero.
|
// Interpret Compare's result by comparing it to zero.
|
||||||
var a, b []byte
|
var a, b []byte
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package arch defines architecture-specific information and support functions.
|
||||||
package arch
|
package arch
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
||||||
|
|
@ -74,11 +74,12 @@ func IsARM64STLXR(op obj.As) bool {
|
||||||
arm64.ASTXRB, arm64.ASTXRH, arm64.ASTXRW, arm64.ASTXR,
|
arm64.ASTXRB, arm64.ASTXRH, arm64.ASTXRW, arm64.ASTXR,
|
||||||
arm64.ASTXP, arm64.ASTXPW, arm64.ASTLXP, arm64.ASTLXPW,
|
arm64.ASTXP, arm64.ASTXPW, arm64.ASTLXP, arm64.ASTLXPW,
|
||||||
arm64.ASWPB, arm64.ASWPH, arm64.ASWPW, arm64.ASWPD,
|
arm64.ASWPB, arm64.ASWPH, arm64.ASWPW, arm64.ASWPD,
|
||||||
|
arm64.ASWPALB, arm64.ASWPALH, arm64.ASWPALW, arm64.ASWPALD,
|
||||||
arm64.ALDADDB, arm64.ALDADDH, arm64.ALDADDW, arm64.ALDADDD,
|
arm64.ALDADDB, arm64.ALDADDH, arm64.ALDADDW, arm64.ALDADDD,
|
||||||
arm64.ALDANDB, arm64.ALDANDH, arm64.ALDANDW, arm64.ALDANDD,
|
arm64.ALDANDB, arm64.ALDANDH, arm64.ALDANDW, arm64.ALDANDD,
|
||||||
arm64.ALDEORB, arm64.ALDEORH, arm64.ALDEORW, arm64.ALDEORD,
|
arm64.ALDEORB, arm64.ALDEORH, arm64.ALDEORW, arm64.ALDEORD,
|
||||||
arm64.ALDORB, arm64.ALDORH, arm64.ALDORW, arm64.ALDORD,
|
arm64.ALDORB, arm64.ALDORH, arm64.ALDORW, arm64.ALDORD,
|
||||||
arm64.ALDADDALD, arm64.ALDADDALW:
|
arm64.ALDADDALD, arm64.ALDADDALW, arm64.ALDADDALH, arm64.ALDADDALB:
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
|
|
||||||
|
|
@ -137,7 +137,7 @@ func (p *Parser) asmText(operands [][]lex.Token) {
|
||||||
// Bizarre syntax: $frameSize-argSize is two words, not subtraction.
|
// Bizarre syntax: $frameSize-argSize is two words, not subtraction.
|
||||||
// Both frameSize and argSize must be simple integers; only frameSize
|
// Both frameSize and argSize must be simple integers; only frameSize
|
||||||
// can be negative.
|
// can be negative.
|
||||||
// The "-argSize" may be missing; if so, set it to obj.ArgsSizeUnknown.
|
// The "-argSize" may be missing; if so, set it to objabi.ArgsSizeUnknown.
|
||||||
// Parse left to right.
|
// Parse left to right.
|
||||||
op := operands[next]
|
op := operands[next]
|
||||||
if len(op) < 2 || op[0].ScanToken != '$' {
|
if len(op) < 2 || op[0].ScanToken != '$' {
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ func newParser(goarch string) *Parser {
|
||||||
|
|
||||||
// tryParse executes parse func in panicOnError=true context.
|
// tryParse executes parse func in panicOnError=true context.
|
||||||
// parse is expected to call any parsing methods that may panic.
|
// parse is expected to call any parsing methods that may panic.
|
||||||
// Returns error gathered from recover; nil if no parse errors occured.
|
// Returns error gathered from recover; nil if no parse errors occurred.
|
||||||
//
|
//
|
||||||
// For unexpected panics, calls t.Fatal.
|
// For unexpected panics, calls t.Fatal.
|
||||||
func tryParse(t *testing.T, parse func()) (err error) {
|
func tryParse(t *testing.T, parse func()) (err error) {
|
||||||
|
|
|
||||||
|
|
@ -911,7 +911,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
|
||||||
VADDPD.BCST.Z (AX), Z2, K1, Z1 // 62f1edd95808
|
VADDPD.BCST.Z (AX), Z2, K1, Z1 // 62f1edd95808
|
||||||
VMAXPD.BCST (AX), Z2, K1, Z1 // 62f1ed595f08
|
VMAXPD.BCST (AX), Z2, K1, Z1 // 62f1ed595f08
|
||||||
VMAXPD.BCST.Z (AX), Z2, K1, Z1 // 62f1edd95f08
|
VMAXPD.BCST.Z (AX), Z2, K1, Z1 // 62f1edd95f08
|
||||||
// EVEX: surpress all exceptions (SAE).
|
// EVEX: suppress all exceptions (SAE).
|
||||||
VMAXPD.SAE Z3, Z2, K1, Z1 // 62f1ed595fcb or 62f1ed195fcb
|
VMAXPD.SAE Z3, Z2, K1, Z1 // 62f1ed595fcb or 62f1ed195fcb
|
||||||
VMAXPD.SAE.Z Z3, Z2, K1, Z1 // 62f1edd95fcb or 62f1ed995fcb
|
VMAXPD.SAE.Z Z3, Z2, K1, Z1 // 62f1edd95fcb or 62f1ed995fcb
|
||||||
VMAXPD (AX), Z2, K1, Z1 // 62f1ed495f08
|
VMAXPD (AX), Z2, K1, Z1 // 62f1ed495f08
|
||||||
|
|
|
||||||
111
src/cmd/asm/internal/asm/testdata/arm64.s
vendored
111
src/cmd/asm/internal/asm/testdata/arm64.s
vendored
|
|
@ -163,6 +163,21 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
|
||||||
MOVB (R29)(R30<<0), R14 // ae7bbe38
|
MOVB (R29)(R30<<0), R14 // ae7bbe38
|
||||||
MOVB (R29)(R30), R14 // MOVB (R29)(R30*1), R14 // ae6bbe38
|
MOVB (R29)(R30), R14 // MOVB (R29)(R30*1), R14 // ae6bbe38
|
||||||
MOVB R4, (R2)(R6.SXTX) // 44e82638
|
MOVB R4, (R2)(R6.SXTX) // 44e82638
|
||||||
|
FMOVS $(4.0), F0 // 0010221e
|
||||||
|
FMOVD $(4.0), F0 // 0010621e
|
||||||
|
FMOVS $(0.265625), F1 // 01302a1e
|
||||||
|
FMOVD $(0.1796875), F2 // 02f0681e
|
||||||
|
FMOVS $(0.96875), F3 // 03f02d1e
|
||||||
|
FMOVD $(28.0), F4 // 0490671e
|
||||||
|
|
||||||
|
FMOVS (R2)(R6), F4 // FMOVS (R2)(R6*1), F4 // 446866bc
|
||||||
|
FMOVS (R2)(R6<<2), F4 // 447866bc
|
||||||
|
FMOVD (R2)(R6), F4 // FMOVD (R2)(R6*1), F4 // 446866fc
|
||||||
|
FMOVD (R2)(R6<<3), F4 // 447866fc
|
||||||
|
FMOVS F4, (R2)(R6) // FMOVS F4, (R2)(R6*1) // 446826bc
|
||||||
|
FMOVS F4, (R2)(R6<<2) // 447826bc
|
||||||
|
FMOVD F4, (R2)(R6) // FMOVD F4, (R2)(R6*1) // 446826fc
|
||||||
|
FMOVD F4, (R2)(R6<<3) // 447826fc
|
||||||
|
|
||||||
// LTYPE1 imsr ',' spreg ','
|
// LTYPE1 imsr ',' spreg ','
|
||||||
// {
|
// {
|
||||||
|
|
@ -470,14 +485,14 @@ again:
|
||||||
// {
|
// {
|
||||||
// outcode($1, &$2, NREG, &$4);
|
// outcode($1, &$2, NREG, &$4);
|
||||||
// }
|
// }
|
||||||
FADDD $0.5, F1 // FADDD $(0.5), F1
|
// FADDD $0.5, F1 // FADDD $(0.5), F1
|
||||||
FADDD F1, F2
|
FADDD F1, F2
|
||||||
|
|
||||||
// LTYPEK frcon ',' freg ',' freg
|
// LTYPEK frcon ',' freg ',' freg
|
||||||
// {
|
// {
|
||||||
// outcode($1, &$2, $4.reg, &$6);
|
// outcode($1, &$2, $4.reg, &$6);
|
||||||
// }
|
// }
|
||||||
FADDD $0.7, F1, F2 // FADDD $(0.69999999999999996), F1, F2
|
// FADDD $0.7, F1, F2 // FADDD $(0.69999999999999996), F1, F2
|
||||||
FADDD F1, F2, F3
|
FADDD F1, F2, F3
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
@ -572,6 +587,14 @@ again:
|
||||||
SWPH R5, (RSP), R7 // e7832578
|
SWPH R5, (RSP), R7 // e7832578
|
||||||
SWPB R5, (R6), R7 // c7802538
|
SWPB R5, (R6), R7 // c7802538
|
||||||
SWPB R5, (RSP), R7 // e7832538
|
SWPB R5, (RSP), R7 // e7832538
|
||||||
|
SWPALD R5, (R6), R7 // c780e5f8
|
||||||
|
SWPALD R5, (RSP), R7 // e783e5f8
|
||||||
|
SWPALW R5, (R6), R7 // c780e5b8
|
||||||
|
SWPALW R5, (RSP), R7 // e783e5b8
|
||||||
|
SWPALH R5, (R6), R7 // c780e578
|
||||||
|
SWPALH R5, (RSP), R7 // e783e578
|
||||||
|
SWPALB R5, (R6), R7 // c780e538
|
||||||
|
SWPALB R5, (RSP), R7 // e783e538
|
||||||
LDADDD R5, (R6), R7 // c70025f8
|
LDADDD R5, (R6), R7 // c70025f8
|
||||||
LDADDD R5, (RSP), R7 // e70325f8
|
LDADDD R5, (RSP), R7 // e70325f8
|
||||||
LDADDW R5, (R6), R7 // c70025b8
|
LDADDW R5, (R6), R7 // c70025b8
|
||||||
|
|
@ -605,7 +628,9 @@ again:
|
||||||
LDORB R5, (R6), R7 // c7302538
|
LDORB R5, (R6), R7 // c7302538
|
||||||
LDORB R5, (RSP), R7 // e7332538
|
LDORB R5, (RSP), R7 // e7332538
|
||||||
LDADDALD R2, (R1), R3 // 2300e2f8
|
LDADDALD R2, (R1), R3 // 2300e2f8
|
||||||
LDADDALW R5, (R4), R6 // 8600e5b8
|
LDADDALW R2, (R1), R3 // 2300e2b8
|
||||||
|
LDADDALH R2, (R1), R3 // 2300e278
|
||||||
|
LDADDALB R2, (R1), R3 // 2300e238
|
||||||
|
|
||||||
// RET
|
// RET
|
||||||
//
|
//
|
||||||
|
|
@ -716,6 +741,86 @@ again:
|
||||||
STPW (R3, R4), x(SB)
|
STPW (R3, R4), x(SB)
|
||||||
STPW (R3, R4), x+8(SB)
|
STPW (R3, R4), x+8(SB)
|
||||||
|
|
||||||
|
// bit field operation
|
||||||
|
BFI $0, R1, $1, R2 // 220040b3
|
||||||
|
BFIW $0, R1, $1, R2 // 22000033
|
||||||
|
SBFIZ $0, R1, $1, R2 // 22004093
|
||||||
|
SBFIZW $0, R1, $1, R2 // 22000013
|
||||||
|
UBFIZ $0, R1, $1, R2 // 220040d3
|
||||||
|
UBFIZW $0, R1, $1, R2 // 22000053
|
||||||
|
|
||||||
|
// FSTPD/FSTPS/FLDPD/FLDPS
|
||||||
|
FLDPD (R0), (F1, F2) // 0108406d
|
||||||
|
FLDPD 8(R0), (F1, F2) // 0188406d
|
||||||
|
FLDPD -8(R0), (F1, F2) // 01887f6d
|
||||||
|
FLDPD 11(R0), (F1, F2) // 1b2c0091610b406d
|
||||||
|
FLDPD 1024(R0), (F1, F2) // 1b001091610b406d
|
||||||
|
FLDPD.W 8(R0), (F1, F2) // 0188c06d
|
||||||
|
FLDPD.P 8(R0), (F1, F2) // 0188c06c
|
||||||
|
FLDPD (RSP), (F1, F2) // e10b406d
|
||||||
|
FLDPD 8(RSP), (F1, F2) // e18b406d
|
||||||
|
FLDPD -8(RSP), (F1, F2) // e18b7f6d
|
||||||
|
FLDPD 11(RSP), (F1, F2) // fb2f0091610b406d
|
||||||
|
FLDPD 1024(RSP), (F1, F2) // fb031091610b406d
|
||||||
|
FLDPD.W 8(RSP), (F1, F2) // e18bc06d
|
||||||
|
FLDPD.P 8(RSP), (F1, F2) // e18bc06c
|
||||||
|
FLDPD -31(R0), (F1, F2) // 1b7c00d1610b406d
|
||||||
|
FLDPD -4(R0), (F1, F2) // 1b1000d1610b406d
|
||||||
|
FLDPD -8(R0), (F1, F2) // 01887f6d
|
||||||
|
FLDPD x(SB), (F1, F2)
|
||||||
|
FLDPD x+8(SB), (F1, F2)
|
||||||
|
FLDPS -5(R0), (F1, F2) // 1b1400d1610b402d
|
||||||
|
FLDPS (R0), (F1, F2) // 0108402d
|
||||||
|
FLDPS 4(R0), (F1, F2) // 0188402d
|
||||||
|
FLDPS -4(R0), (F1, F2) // 01887f2d
|
||||||
|
FLDPS.W 4(R0), (F1, F2) // 0188c02d
|
||||||
|
FLDPS.P 4(R0), (F1, F2) // 0188c02c
|
||||||
|
FLDPS 11(R0), (F1, F2) // 1b2c0091610b402d
|
||||||
|
FLDPS 1024(R0), (F1, F2) // 1b001091610b402d
|
||||||
|
FLDPS (RSP), (F1, F2) // e10b402d
|
||||||
|
FLDPS 4(RSP), (F1, F2) // e18b402d
|
||||||
|
FLDPS -4(RSP), (F1, F2) // e18b7f2d
|
||||||
|
FLDPS.W 4(RSP), (F1, F2) // e18bc02d
|
||||||
|
FLDPS.P 4(RSP), (F1, F2) // e18bc02c
|
||||||
|
FLDPS 11(RSP), (F1, F2) // fb2f0091610b402d
|
||||||
|
FLDPS 1024(RSP), (F1, F2) // fb031091610b402d
|
||||||
|
FLDPS x(SB), (F1, F2)
|
||||||
|
FLDPS x+8(SB), (F1, F2)
|
||||||
|
FSTPD (F3, F4), (R5) // a310006d
|
||||||
|
FSTPD (F3, F4), 8(R5) // a390006d
|
||||||
|
FSTPD.W (F3, F4), 8(R5) // a390806d
|
||||||
|
FSTPD.P (F3, F4), 8(R5) // a390806c
|
||||||
|
FSTPD (F3, F4), -8(R5) // a3903f6d
|
||||||
|
FSTPD (F3, F4), -4(R5) // bb1000d16313006d
|
||||||
|
FSTPD (F3, F4), 11(R0) // 1b2c00916313006d
|
||||||
|
FSTPD (F3, F4), 1024(R0) // 1b0010916313006d
|
||||||
|
FSTPD (F3, F4), (RSP) // e313006d
|
||||||
|
FSTPD (F3, F4), 8(RSP) // e393006d
|
||||||
|
FSTPD.W (F3, F4), 8(RSP) // e393806d
|
||||||
|
FSTPD.P (F3, F4), 8(RSP) // e393806c
|
||||||
|
FSTPD (F3, F4), -8(RSP) // e3933f6d
|
||||||
|
FSTPD (F3, F4), 11(RSP) // fb2f00916313006d
|
||||||
|
FSTPD (F3, F4), 1024(RSP) // fb0310916313006d
|
||||||
|
FSTPD (F3, F4), x(SB)
|
||||||
|
FSTPD (F3, F4), x+8(SB)
|
||||||
|
FSTPS (F3, F4), (R5) // a310002d
|
||||||
|
FSTPS (F3, F4), 4(R5) // a390002d
|
||||||
|
FSTPS.W (F3, F4), 4(R5) // a390802d
|
||||||
|
FSTPS.P (F3, F4), 4(R5) // a390802c
|
||||||
|
FSTPS (F3, F4), -4(R5) // a3903f2d
|
||||||
|
FSTPS (F3, F4), -5(R5) // bb1400d16313002d
|
||||||
|
FSTPS (F3, F4), 11(R0) // 1b2c00916313002d
|
||||||
|
FSTPS (F3, F4), 1024(R0) // 1b0010916313002d
|
||||||
|
FSTPS (F3, F4), (RSP) // e313002d
|
||||||
|
FSTPS (F3, F4), 4(RSP) // e393002d
|
||||||
|
FSTPS.W (F3, F4), 4(RSP) // e393802d
|
||||||
|
FSTPS.P (F3, F4), 4(RSP) // e393802c
|
||||||
|
FSTPS (F3, F4), -4(RSP) // e3933f2d
|
||||||
|
FSTPS (F3, F4), 11(RSP) // fb2f00916313002d
|
||||||
|
FSTPS (F3, F4), 1024(RSP) // fb0310916313002d
|
||||||
|
FSTPS (F3, F4), x(SB)
|
||||||
|
FSTPS (F3, F4), x+8(SB)
|
||||||
|
|
||||||
// END
|
// END
|
||||||
//
|
//
|
||||||
// LTYPEE comma
|
// LTYPEE comma
|
||||||
|
|
|
||||||
|
|
@ -89,4 +89,9 @@ TEXT errors(SB),$0
|
||||||
CSEL LT, R1, R2 // ERROR "illegal combination"
|
CSEL LT, R1, R2 // ERROR "illegal combination"
|
||||||
AND $0x22220000, R2, RSP // ERROR "illegal combination"
|
AND $0x22220000, R2, RSP // ERROR "illegal combination"
|
||||||
ANDS $0x22220000, R2, RSP // ERROR "illegal combination"
|
ANDS $0x22220000, R2, RSP // ERROR "illegal combination"
|
||||||
|
LDP (R0), (F0, F1) // ERROR "invalid register pair"
|
||||||
|
LDP (R0), (R3, ZR) // ERROR "invalid register pair"
|
||||||
|
STP (F2, F3), (R0) // ERROR "invalid register pair"
|
||||||
|
FLDPD (R0), (R1, R2) // ERROR "invalid register pair"
|
||||||
|
FSTPD (R1, R2), (R0) // ERROR "invalid register pair"
|
||||||
RET
|
RET
|
||||||
|
|
|
||||||
1
src/cmd/asm/internal/asm/testdata/s390x.s
vendored
1
src/cmd/asm/internal/asm/testdata/s390x.s
vendored
|
|
@ -115,6 +115,7 @@ TEXT main·foo(SB),DUPOK|NOSPLIT,$16-0 // TEXT main.foo(SB), DUPOK|NOSPLIT, $16-
|
||||||
NEGW R1 // b9130011
|
NEGW R1 // b9130011
|
||||||
NEGW R1, R2 // b9130021
|
NEGW R1, R2 // b9130021
|
||||||
FLOGR R2, R2 // b9830022
|
FLOGR R2, R2 // b9830022
|
||||||
|
POPCNT R3, R4 // b9e10043
|
||||||
|
|
||||||
AND R1, R2 // b9800021
|
AND R1, R2 // b9800021
|
||||||
AND R1, R2, R3 // b9e42031
|
AND R1, R2, R3 // b9e42031
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,7 @@ func (f *File) ParseGo(name string, src []byte) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !sawC {
|
if !sawC {
|
||||||
error_(token.NoPos, `cannot find import "C"`)
|
error_(ast1.Package, `cannot find import "C"`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// In ast2, strip the import "C" line.
|
// In ast2, strip the import "C" line.
|
||||||
|
|
|
||||||
|
|
@ -104,10 +104,13 @@ compiled with the C compiler. Any .cc, .cpp, or .cxx files will be
|
||||||
compiled with the C++ compiler. Any .f, .F, .for or .f90 files will be
|
compiled with the C++ compiler. Any .f, .F, .for or .f90 files will be
|
||||||
compiled with the fortran compiler. Any .h, .hh, .hpp, or .hxx files will
|
compiled with the fortran compiler. Any .h, .hh, .hpp, or .hxx files will
|
||||||
not be compiled separately, but, if these header files are changed,
|
not be compiled separately, but, if these header files are changed,
|
||||||
the C and C++ files will be recompiled. The default C and C++
|
the package (including its non-Go source files) will be recompiled.
|
||||||
compilers may be changed by the CC and CXX environment variables,
|
Note that changes to files in other directories do not cause the package
|
||||||
respectively; those environment variables may include command line
|
to be recompiled, so all non-Go source code for the package should be
|
||||||
options.
|
stored in the package directory, not in subdirectories.
|
||||||
|
The default C and C++ compilers may be changed by the CC and CXX
|
||||||
|
environment variables, respectively; those environment variables
|
||||||
|
may include command line options.
|
||||||
|
|
||||||
The cgo tool is enabled by default for native builds on systems where
|
The cgo tool is enabled by default for native builds on systems where
|
||||||
it is expected to work. It is disabled by default when
|
it is expected to work. It is disabled by default when
|
||||||
|
|
@ -377,6 +380,14 @@ and of course there is nothing stopping the C code from doing anything
|
||||||
it likes. However, programs that break these rules are likely to fail
|
it likes. However, programs that break these rules are likely to fail
|
||||||
in unexpected and unpredictable ways.
|
in unexpected and unpredictable ways.
|
||||||
|
|
||||||
|
Note: the current implementation has a bug. While Go code is permitted
|
||||||
|
to write nil or a C pointer (but not a Go pointer) to C memory, the
|
||||||
|
current implementation may sometimes cause a runtime error if the
|
||||||
|
contents of the C memory appear to be a Go pointer. Therefore, avoid
|
||||||
|
passing uninitialized C memory to Go code if the Go code is going to
|
||||||
|
store pointer values in it. Zero out the memory in C before passing it
|
||||||
|
to Go.
|
||||||
|
|
||||||
Special cases
|
Special cases
|
||||||
|
|
||||||
A few special C types which would normally be represented by a pointer
|
A few special C types which would normally be represented by a pointer
|
||||||
|
|
|
||||||
|
|
@ -164,9 +164,29 @@ func (p *Package) Translate(f *File) {
|
||||||
cref.Name.C = cname(cref.Name.Go)
|
cref.Name.C = cname(cref.Name.Go)
|
||||||
}
|
}
|
||||||
p.loadDefines(f)
|
p.loadDefines(f)
|
||||||
needType := p.guessKinds(f)
|
p.typedefs = map[string]bool{}
|
||||||
if len(needType) > 0 {
|
p.typedefList = nil
|
||||||
p.loadDWARF(f, needType)
|
numTypedefs := -1
|
||||||
|
for len(p.typedefs) > numTypedefs {
|
||||||
|
numTypedefs = len(p.typedefs)
|
||||||
|
// Also ask about any typedefs we've seen so far.
|
||||||
|
for _, a := range p.typedefList {
|
||||||
|
f.Name[a] = &Name{
|
||||||
|
Go: a,
|
||||||
|
C: a,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
needType := p.guessKinds(f)
|
||||||
|
if len(needType) > 0 {
|
||||||
|
p.loadDWARF(f, needType)
|
||||||
|
}
|
||||||
|
|
||||||
|
// In godefs mode we're OK with the typedefs, which
|
||||||
|
// will presumably also be defined in the file, we
|
||||||
|
// don't want to resolve them to their base types.
|
||||||
|
if *godefs {
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if p.rewriteCalls(f) {
|
if p.rewriteCalls(f) {
|
||||||
// Add `import _cgo_unsafe "unsafe"` after the package statement.
|
// Add `import _cgo_unsafe "unsafe"` after the package statement.
|
||||||
|
|
@ -551,6 +571,7 @@ func (p *Package) loadDWARF(f *File, names []*Name) {
|
||||||
fatalf("malformed __cgo__ name: %s", name)
|
fatalf("malformed __cgo__ name: %s", name)
|
||||||
}
|
}
|
||||||
types[i] = t.Type
|
types[i] = t.Type
|
||||||
|
p.recordTypedefs(t.Type)
|
||||||
}
|
}
|
||||||
if e.Tag != dwarf.TagCompileUnit {
|
if e.Tag != dwarf.TagCompileUnit {
|
||||||
r.SkipChildren()
|
r.SkipChildren()
|
||||||
|
|
@ -586,7 +607,25 @@ func (p *Package) loadDWARF(f *File, names []*Name) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case "fconst":
|
case "fconst":
|
||||||
if i < len(floats) {
|
if i >= len(floats) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
switch base(types[i]).(type) {
|
||||||
|
case *dwarf.IntType, *dwarf.UintType:
|
||||||
|
// This has an integer type so it's
|
||||||
|
// not really a floating point
|
||||||
|
// constant. This can happen when the
|
||||||
|
// C compiler complains about using
|
||||||
|
// the value as an integer constant,
|
||||||
|
// but not as a general constant.
|
||||||
|
// Treat this as a variable of the
|
||||||
|
// appropriate type, not a constant,
|
||||||
|
// to get C-style type handling,
|
||||||
|
// avoiding the problem that C permits
|
||||||
|
// uint64(-1) but Go does not.
|
||||||
|
// See issue 26066.
|
||||||
|
n.Kind = "var"
|
||||||
|
default:
|
||||||
n.Const = fmt.Sprintf("%f", floats[i])
|
n.Const = fmt.Sprintf("%f", floats[i])
|
||||||
}
|
}
|
||||||
case "sconst":
|
case "sconst":
|
||||||
|
|
@ -599,6 +638,47 @@ func (p *Package) loadDWARF(f *File, names []*Name) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// recordTypedefs remembers in p.typedefs all the typedefs used in dtypes and its children.
|
||||||
|
func (p *Package) recordTypedefs(dtype dwarf.Type) {
|
||||||
|
p.recordTypedefs1(dtype, map[dwarf.Type]bool{})
|
||||||
|
}
|
||||||
|
func (p *Package) recordTypedefs1(dtype dwarf.Type, visited map[dwarf.Type]bool) {
|
||||||
|
if dtype == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if visited[dtype] {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
visited[dtype] = true
|
||||||
|
switch dt := dtype.(type) {
|
||||||
|
case *dwarf.TypedefType:
|
||||||
|
if strings.HasPrefix(dt.Name, "__builtin") {
|
||||||
|
// Don't look inside builtin types. There be dragons.
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !p.typedefs[dt.Name] {
|
||||||
|
p.typedefs[dt.Name] = true
|
||||||
|
p.typedefList = append(p.typedefList, dt.Name)
|
||||||
|
p.recordTypedefs1(dt.Type, visited)
|
||||||
|
}
|
||||||
|
case *dwarf.PtrType:
|
||||||
|
p.recordTypedefs1(dt.Type, visited)
|
||||||
|
case *dwarf.ArrayType:
|
||||||
|
p.recordTypedefs1(dt.Type, visited)
|
||||||
|
case *dwarf.QualType:
|
||||||
|
p.recordTypedefs1(dt.Type, visited)
|
||||||
|
case *dwarf.FuncType:
|
||||||
|
p.recordTypedefs1(dt.ReturnType, visited)
|
||||||
|
for _, a := range dt.ParamType {
|
||||||
|
p.recordTypedefs1(a, visited)
|
||||||
|
}
|
||||||
|
case *dwarf.StructType:
|
||||||
|
for _, f := range dt.Field {
|
||||||
|
p.recordTypedefs1(f.Type, visited)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// mangleName does name mangling to translate names
|
// mangleName does name mangling to translate names
|
||||||
// from the original Go source files to the names
|
// from the original Go source files to the names
|
||||||
// used in the final Go files generated by cgo.
|
// used in the final Go files generated by cgo.
|
||||||
|
|
@ -1613,6 +1693,9 @@ func (p *Package) gccErrors(stdin []byte) string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Force -O0 optimization
|
||||||
|
nargs = append(nargs, "-O0")
|
||||||
|
|
||||||
if *debugGcc {
|
if *debugGcc {
|
||||||
fmt.Fprintf(os.Stderr, "$ %s <<EOF\n", strings.Join(nargs, " "))
|
fmt.Fprintf(os.Stderr, "$ %s <<EOF\n", strings.Join(nargs, " "))
|
||||||
os.Stderr.Write(stdin)
|
os.Stderr.Write(stdin)
|
||||||
|
|
@ -1659,6 +1742,7 @@ type typeConv struct {
|
||||||
// Map from types to incomplete pointers to those types.
|
// Map from types to incomplete pointers to those types.
|
||||||
ptrs map[dwarf.Type][]*Type
|
ptrs map[dwarf.Type][]*Type
|
||||||
// Keys of ptrs in insertion order (deterministic worklist)
|
// Keys of ptrs in insertion order (deterministic worklist)
|
||||||
|
// ptrKeys contains exactly the keys in ptrs.
|
||||||
ptrKeys []dwarf.Type
|
ptrKeys []dwarf.Type
|
||||||
|
|
||||||
// Type names X for which there exists an XGetTypeID function with type func() CFTypeID.
|
// Type names X for which there exists an XGetTypeID function with type func() CFTypeID.
|
||||||
|
|
@ -1801,14 +1885,15 @@ func (c *typeConv) FinishType(pos token.Pos) {
|
||||||
for len(c.ptrKeys) > 0 {
|
for len(c.ptrKeys) > 0 {
|
||||||
dtype := c.ptrKeys[0]
|
dtype := c.ptrKeys[0]
|
||||||
c.ptrKeys = c.ptrKeys[1:]
|
c.ptrKeys = c.ptrKeys[1:]
|
||||||
|
ptrs := c.ptrs[dtype]
|
||||||
|
delete(c.ptrs, dtype)
|
||||||
|
|
||||||
// Note Type might invalidate c.ptrs[dtype].
|
// Note Type might invalidate c.ptrs[dtype].
|
||||||
t := c.Type(dtype, pos)
|
t := c.Type(dtype, pos)
|
||||||
for _, ptr := range c.ptrs[dtype] {
|
for _, ptr := range ptrs {
|
||||||
ptr.Go.(*ast.StarExpr).X = t.Go
|
ptr.Go.(*ast.StarExpr).X = t.Go
|
||||||
ptr.C.Set("%s*", t.C)
|
ptr.C.Set("%s*", t.C)
|
||||||
}
|
}
|
||||||
c.ptrs[dtype] = nil // retain the map key
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2085,6 +2170,10 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
|
||||||
s := *sub
|
s := *sub
|
||||||
s.Go = c.uintptr
|
s.Go = c.uintptr
|
||||||
sub = &s
|
sub = &s
|
||||||
|
// Make sure we update any previously computed type.
|
||||||
|
if oldType := typedef[name.Name]; oldType != nil {
|
||||||
|
oldType.Go = sub.Go
|
||||||
|
}
|
||||||
}
|
}
|
||||||
t.Go = name
|
t.Go = name
|
||||||
if unionWithPointer[sub.Go] {
|
if unionWithPointer[sub.Go] {
|
||||||
|
|
@ -2246,7 +2335,7 @@ func (c *typeConv) FuncArg(dtype dwarf.Type, pos token.Pos) *Type {
|
||||||
}
|
}
|
||||||
// ...or the typedef is one in which we expect bad pointers.
|
// ...or the typedef is one in which we expect bad pointers.
|
||||||
// It will be a uintptr instead of *X.
|
// It will be a uintptr instead of *X.
|
||||||
if c.badPointerTypedef(dt) {
|
if c.baseBadPointerTypedef(dt) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2598,6 +2687,19 @@ func (c *typeConv) badPointerTypedef(dt *dwarf.TypedefType) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// baseBadPointerTypedef reports whether the base of a chain of typedefs is a bad typedef
|
||||||
|
// as badPointerTypedef reports.
|
||||||
|
func (c *typeConv) baseBadPointerTypedef(dt *dwarf.TypedefType) bool {
|
||||||
|
for {
|
||||||
|
if t, ok := dt.Type.(*dwarf.TypedefType); ok {
|
||||||
|
dt = t
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
return c.badPointerTypedef(dt)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *typeConv) badCFType(dt *dwarf.TypedefType) bool {
|
func (c *typeConv) badCFType(dt *dwarf.TypedefType) bool {
|
||||||
// The real bad types are CFNumberRef and CFDateRef.
|
// The real bad types are CFNumberRef and CFDateRef.
|
||||||
// Sometimes non-pointers are stored in these types.
|
// Sometimes non-pointers are stored in these types.
|
||||||
|
|
@ -2686,13 +2788,31 @@ func (c *typeConv) badJNI(dt *dwarf.TypedefType) bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that the typedef is:
|
// Check that the typedef is either:
|
||||||
// struct _jobject;
|
// 1:
|
||||||
// typedef struct _jobject *jobject;
|
// struct _jobject;
|
||||||
|
// typedef struct _jobject *jobject;
|
||||||
|
// 2: (in NDK16 in C++)
|
||||||
|
// class _jobject {};
|
||||||
|
// typedef _jobject* jobject;
|
||||||
|
// 3: (in NDK16 in C)
|
||||||
|
// typedef void* jobject;
|
||||||
if ptr, ok := w.Type.(*dwarf.PtrType); ok {
|
if ptr, ok := w.Type.(*dwarf.PtrType); ok {
|
||||||
if str, ok := ptr.Type.(*dwarf.StructType); ok {
|
switch v := ptr.Type.(type) {
|
||||||
if str.StructName == "_jobject" && str.Kind == "struct" && len(str.Field) == 0 && str.Incomplete {
|
case *dwarf.VoidType:
|
||||||
return true
|
return true
|
||||||
|
case *dwarf.StructType:
|
||||||
|
if v.StructName == "_jobject" && len(v.Field) == 0 {
|
||||||
|
switch v.Kind {
|
||||||
|
case "struct":
|
||||||
|
if v.Incomplete {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case "class":
|
||||||
|
if !v.Incomplete {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,9 +43,11 @@ type Package struct {
|
||||||
Name map[string]*Name // accumulated Name from Files
|
Name map[string]*Name // accumulated Name from Files
|
||||||
ExpFunc []*ExpFunc // accumulated ExpFunc from Files
|
ExpFunc []*ExpFunc // accumulated ExpFunc from Files
|
||||||
Decl []ast.Decl
|
Decl []ast.Decl
|
||||||
GoFiles []string // list of Go files
|
GoFiles []string // list of Go files
|
||||||
GccFiles []string // list of gcc output files
|
GccFiles []string // list of gcc output files
|
||||||
Preamble string // collected preamble for _cgo_export.h
|
Preamble string // collected preamble for _cgo_export.h
|
||||||
|
typedefs map[string]bool // type names that appear in the types of the objects we're interested in
|
||||||
|
typedefList []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// A File collects information about a single Go input file.
|
// A File collects information about a single Go input file.
|
||||||
|
|
@ -261,6 +263,9 @@ func main() {
|
||||||
if arg == "-fsanitize=thread" {
|
if arg == "-fsanitize=thread" {
|
||||||
tsanProlog = yesTsanProlog
|
tsanProlog = yesTsanProlog
|
||||||
}
|
}
|
||||||
|
if arg == "-fsanitize=memory" {
|
||||||
|
msanProlog = yesMsanProlog
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p := newPackage(args[:i])
|
p := newPackage(args[:i])
|
||||||
|
|
@ -394,6 +399,14 @@ func (p *Package) Record(f *File) {
|
||||||
for k, v := range f.Name {
|
for k, v := range f.Name {
|
||||||
if p.Name[k] == nil {
|
if p.Name[k] == nil {
|
||||||
p.Name[k] = v
|
p.Name[k] = v
|
||||||
|
} else if p.incompleteTypedef(p.Name[k].Type) {
|
||||||
|
p.Name[k] = v
|
||||||
|
} else if p.incompleteTypedef(v.Type) {
|
||||||
|
// Nothing to do.
|
||||||
|
} else if _, ok := nameToC[k]; ok {
|
||||||
|
// Names we predefine may appear inconsistent
|
||||||
|
// if some files typedef them and some don't.
|
||||||
|
// Issue 26743.
|
||||||
} else if !reflect.DeepEqual(p.Name[k], v) {
|
} else if !reflect.DeepEqual(p.Name[k], v) {
|
||||||
error_(token.NoPos, "inconsistent definitions for C.%s", fixGo(k))
|
error_(token.NoPos, "inconsistent definitions for C.%s", fixGo(k))
|
||||||
}
|
}
|
||||||
|
|
@ -406,3 +419,9 @@ func (p *Package) Record(f *File) {
|
||||||
}
|
}
|
||||||
p.Decl = append(p.Decl, f.AST.Decls...)
|
p.Decl = append(p.Decl, f.AST.Decls...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// incompleteTypedef reports whether t appears to be an incomplete
|
||||||
|
// typedef definition.
|
||||||
|
func (p *Package) incompleteTypedef(t *Type) bool {
|
||||||
|
return t == nil || (t.Size == 0 && t.Align == -1)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -272,10 +272,7 @@ func dynimport(obj string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sym, err := f.ImportedSymbols()
|
sym, _ := f.ImportedSymbols()
|
||||||
if err != nil {
|
|
||||||
fatalf("cannot load imported symbols from ELF file %s: %v", obj, err)
|
|
||||||
}
|
|
||||||
for _, s := range sym {
|
for _, s := range sym {
|
||||||
targ := s.Name
|
targ := s.Name
|
||||||
if s.Version != "" {
|
if s.Version != "" {
|
||||||
|
|
@ -283,10 +280,7 @@ func dynimport(obj string) {
|
||||||
}
|
}
|
||||||
fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", s.Name, targ, s.Library)
|
fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", s.Name, targ, s.Library)
|
||||||
}
|
}
|
||||||
lib, err := f.ImportedLibraries()
|
lib, _ := f.ImportedLibraries()
|
||||||
if err != nil {
|
|
||||||
fatalf("cannot load imported libraries from ELF file %s: %v", obj, err)
|
|
||||||
}
|
|
||||||
for _, l := range lib {
|
for _, l := range lib {
|
||||||
fmt.Fprintf(stdout, "//go:cgo_import_dynamic _ _ %q\n", l)
|
fmt.Fprintf(stdout, "//go:cgo_import_dynamic _ _ %q\n", l)
|
||||||
}
|
}
|
||||||
|
|
@ -294,20 +288,14 @@ func dynimport(obj string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if f, err := macho.Open(obj); err == nil {
|
if f, err := macho.Open(obj); err == nil {
|
||||||
sym, err := f.ImportedSymbols()
|
sym, _ := f.ImportedSymbols()
|
||||||
if err != nil {
|
|
||||||
fatalf("cannot load imported symbols from Mach-O file %s: %v", obj, err)
|
|
||||||
}
|
|
||||||
for _, s := range sym {
|
for _, s := range sym {
|
||||||
if len(s) > 0 && s[0] == '_' {
|
if len(s) > 0 && s[0] == '_' {
|
||||||
s = s[1:]
|
s = s[1:]
|
||||||
}
|
}
|
||||||
fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", s, s, "")
|
fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", s, s, "")
|
||||||
}
|
}
|
||||||
lib, err := f.ImportedLibraries()
|
lib, _ := f.ImportedLibraries()
|
||||||
if err != nil {
|
|
||||||
fatalf("cannot load imported libraries from Mach-O file %s: %v", obj, err)
|
|
||||||
}
|
|
||||||
for _, l := range lib {
|
for _, l := range lib {
|
||||||
fmt.Fprintf(stdout, "//go:cgo_import_dynamic _ _ %q\n", l)
|
fmt.Fprintf(stdout, "//go:cgo_import_dynamic _ _ %q\n", l)
|
||||||
}
|
}
|
||||||
|
|
@ -315,10 +303,7 @@ func dynimport(obj string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if f, err := pe.Open(obj); err == nil {
|
if f, err := pe.Open(obj); err == nil {
|
||||||
sym, err := f.ImportedSymbols()
|
sym, _ := f.ImportedSymbols()
|
||||||
if err != nil {
|
|
||||||
fatalf("cannot load imported symbols from PE file %s: %v", obj, err)
|
|
||||||
}
|
|
||||||
for _, s := range sym {
|
for _, s := range sym {
|
||||||
ss := strings.Split(s, ":")
|
ss := strings.Split(s, ":")
|
||||||
name := strings.Split(ss[0], "@")[0]
|
name := strings.Split(ss[0], "@")[0]
|
||||||
|
|
@ -537,7 +522,7 @@ func (p *Package) writeOutput(f *File, srcfile string) {
|
||||||
|
|
||||||
// Write Go output: Go input with rewrites of C.xxx to _C_xxx.
|
// Write Go output: Go input with rewrites of C.xxx to _C_xxx.
|
||||||
fmt.Fprintf(fgo1, "// Code generated by cmd/cgo; DO NOT EDIT.\n\n")
|
fmt.Fprintf(fgo1, "// Code generated by cmd/cgo; DO NOT EDIT.\n\n")
|
||||||
fmt.Fprintf(fgo1, "//line %s:1\n", srcfile)
|
fmt.Fprintf(fgo1, "//line %s:1:1\n", srcfile)
|
||||||
fgo1.Write(f.Edit.Bytes())
|
fgo1.Write(f.Edit.Bytes())
|
||||||
|
|
||||||
// While we process the vars and funcs, also write gcc output.
|
// While we process the vars and funcs, also write gcc output.
|
||||||
|
|
@ -546,6 +531,7 @@ func (p *Package) writeOutput(f *File, srcfile string) {
|
||||||
fmt.Fprintf(fgcc, "%s\n", f.Preamble)
|
fmt.Fprintf(fgcc, "%s\n", f.Preamble)
|
||||||
fmt.Fprintf(fgcc, "%s\n", gccProlog)
|
fmt.Fprintf(fgcc, "%s\n", gccProlog)
|
||||||
fmt.Fprintf(fgcc, "%s\n", tsanProlog)
|
fmt.Fprintf(fgcc, "%s\n", tsanProlog)
|
||||||
|
fmt.Fprintf(fgcc, "%s\n", msanProlog)
|
||||||
|
|
||||||
for _, key := range nameKeys(f.Name) {
|
for _, key := range nameKeys(f.Name) {
|
||||||
n := f.Name[key]
|
n := f.Name[key]
|
||||||
|
|
@ -651,6 +637,16 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
|
||||||
fmt.Fprintf(fgcc, "\t_cgo_a = (void*)((char*)_cgo_a + (_cgo_topofstack() - _cgo_stktop));\n")
|
fmt.Fprintf(fgcc, "\t_cgo_a = (void*)((char*)_cgo_a + (_cgo_topofstack() - _cgo_stktop));\n")
|
||||||
// Save the return value.
|
// Save the return value.
|
||||||
fmt.Fprintf(fgcc, "\t_cgo_a->r = _cgo_r;\n")
|
fmt.Fprintf(fgcc, "\t_cgo_a->r = _cgo_r;\n")
|
||||||
|
// The return value is on the Go stack. If we are using msan,
|
||||||
|
// and if the C value is partially or completely uninitialized,
|
||||||
|
// the assignment will mark the Go stack as uninitialized.
|
||||||
|
// The Go compiler does not update msan for changes to the
|
||||||
|
// stack. It is possible that the stack will remain
|
||||||
|
// uninitialized, and then later be used in a way that is
|
||||||
|
// visible to msan, possibly leading to a false positive.
|
||||||
|
// Mark the stack space as written, to avoid this problem.
|
||||||
|
// See issue 26209.
|
||||||
|
fmt.Fprintf(fgcc, "\t_cgo_msan_write(&_cgo_a->r, sizeof(_cgo_a->r));\n")
|
||||||
}
|
}
|
||||||
if n.AddError {
|
if n.AddError {
|
||||||
fmt.Fprintf(fgcc, "\treturn _cgo_errno;\n")
|
fmt.Fprintf(fgcc, "\treturn _cgo_errno;\n")
|
||||||
|
|
@ -749,6 +745,7 @@ func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) {
|
||||||
fmt.Fprintf(fgcc, "extern void _cgo_release_context(__SIZE_TYPE__);\n\n")
|
fmt.Fprintf(fgcc, "extern void _cgo_release_context(__SIZE_TYPE__);\n\n")
|
||||||
fmt.Fprintf(fgcc, "extern char* _cgo_topofstack(void);")
|
fmt.Fprintf(fgcc, "extern char* _cgo_topofstack(void);")
|
||||||
fmt.Fprintf(fgcc, "%s\n", tsanProlog)
|
fmt.Fprintf(fgcc, "%s\n", tsanProlog)
|
||||||
|
fmt.Fprintf(fgcc, "%s\n", msanProlog)
|
||||||
|
|
||||||
for _, exp := range p.ExpFunc {
|
for _, exp := range p.ExpFunc {
|
||||||
fn := exp.Func
|
fn := exp.Func
|
||||||
|
|
@ -986,6 +983,7 @@ func (p *Package) writeGccgoExports(fgo2, fm, fgcc, fgcch io.Writer) {
|
||||||
|
|
||||||
fmt.Fprintf(fgcc, "%s\n", gccgoExportFileProlog)
|
fmt.Fprintf(fgcc, "%s\n", gccgoExportFileProlog)
|
||||||
fmt.Fprintf(fgcc, "%s\n", tsanProlog)
|
fmt.Fprintf(fgcc, "%s\n", tsanProlog)
|
||||||
|
fmt.Fprintf(fgcc, "%s\n", msanProlog)
|
||||||
|
|
||||||
for _, exp := range p.ExpFunc {
|
for _, exp := range p.ExpFunc {
|
||||||
fn := exp.Func
|
fn := exp.Func
|
||||||
|
|
@ -1398,6 +1396,25 @@ static void _cgo_tsan_release() {
|
||||||
// Set to yesTsanProlog if we see -fsanitize=thread in the flags for gcc.
|
// Set to yesTsanProlog if we see -fsanitize=thread in the flags for gcc.
|
||||||
var tsanProlog = noTsanProlog
|
var tsanProlog = noTsanProlog
|
||||||
|
|
||||||
|
// noMsanProlog is a prologue defining an MSAN function in C.
|
||||||
|
// This is used when not compiling with -fsanitize=memory.
|
||||||
|
const noMsanProlog = `
|
||||||
|
#define _cgo_msan_write(addr, sz)
|
||||||
|
`
|
||||||
|
|
||||||
|
// yesMsanProlog is a prologue defining an MSAN function in C.
|
||||||
|
// This is used when compiling with -fsanitize=memory.
|
||||||
|
// See the comment above where _cgo_msan_write is called.
|
||||||
|
const yesMsanProlog = `
|
||||||
|
extern void __msan_unpoison(const volatile void *, size_t);
|
||||||
|
|
||||||
|
#define _cgo_msan_write(addr, sz) __msan_unpoison((addr), (sz))
|
||||||
|
`
|
||||||
|
|
||||||
|
// msanProlog is set to yesMsanProlog if we see -fsanitize=memory in the flags
|
||||||
|
// for the C compiler.
|
||||||
|
var msanProlog = noMsanProlog
|
||||||
|
|
||||||
const builtinProlog = `
|
const builtinProlog = `
|
||||||
#line 1 "cgo-builtin-prolog"
|
#line 1 "cgo-builtin-prolog"
|
||||||
#include <stddef.h> /* for ptrdiff_t and size_t below */
|
#include <stddef.h> /* for ptrdiff_t and size_t below */
|
||||||
|
|
@ -1415,7 +1432,7 @@ void *CBytes(_GoBytes_);
|
||||||
void *_CMalloc(size_t);
|
void *_CMalloc(size_t);
|
||||||
|
|
||||||
__attribute__ ((unused))
|
__attribute__ ((unused))
|
||||||
static size_t _GoStringLen(_GoString_ s) { return s.n; }
|
static size_t _GoStringLen(_GoString_ s) { return (size_t)s.n; }
|
||||||
|
|
||||||
__attribute__ ((unused))
|
__attribute__ ((unused))
|
||||||
static const char *_GoStringPtr(_GoString_ s) { return s.p; }
|
static const char *_GoStringPtr(_GoString_ s) { return s.p; }
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,8 @@ func run(stdin []byte, argv []string) (stdout, stderr []byte, ok bool) {
|
||||||
var bout, berr bytes.Buffer
|
var bout, berr bytes.Buffer
|
||||||
p.Stdout = &bout
|
p.Stdout = &bout
|
||||||
p.Stderr = &berr
|
p.Stderr = &berr
|
||||||
|
// Disable escape codes in clang error messages.
|
||||||
|
p.Env = append(os.Environ(), "TERM=dumb")
|
||||||
err := p.Run()
|
err := p.Run()
|
||||||
if _, ok := err.(*exec.ExitError); err != nil && !ok {
|
if _, ok := err.(*exec.ExitError); err != nil && !ok {
|
||||||
fatalf("%s", err)
|
fatalf("%s", err)
|
||||||
|
|
@ -97,6 +99,8 @@ func error_(pos token.Pos, msg string, args ...interface{}) {
|
||||||
nerrors++
|
nerrors++
|
||||||
if pos.IsValid() {
|
if pos.IsValid() {
|
||||||
fmt.Fprintf(os.Stderr, "%s: ", fset.Position(pos).String())
|
fmt.Fprintf(os.Stderr, "%s: ", fset.Position(pos).String())
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(os.Stderr, "cgo: ")
|
||||||
}
|
}
|
||||||
fmt.Fprintf(os.Stderr, msg, args...)
|
fmt.Fprintf(os.Stderr, msg, args...)
|
||||||
fmt.Fprintf(os.Stderr, "\n")
|
fmt.Fprintf(os.Stderr, "\n")
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
|
<!---
|
||||||
// Copyright 2018 The Go Authors. All rights reserved.
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
-->
|
||||||
|
|
||||||
## Introduction to the Go compiler
|
## Introduction to the Go compiler
|
||||||
|
|
||||||
|
|
@ -19,7 +21,7 @@ the `go/*` packages were developed to enable writing tools working with Go code,
|
||||||
such as `gofmt` and `vet`.
|
such as `gofmt` and `vet`.
|
||||||
|
|
||||||
It should be clarified that the name "gc" stands for "Go compiler", and has
|
It should be clarified that the name "gc" stands for "Go compiler", and has
|
||||||
little to do with uppercase GC, which stands for garbage collection.
|
little to do with uppercase "GC", which stands for garbage collection.
|
||||||
|
|
||||||
### 1. Parsing
|
### 1. Parsing
|
||||||
|
|
||||||
|
|
@ -113,4 +115,4 @@ and debugging information.
|
||||||
### Further reading
|
### Further reading
|
||||||
|
|
||||||
To dig deeper into how the SSA package works, including its passes and rules,
|
To dig deeper into how the SSA package works, including its passes and rules,
|
||||||
head to `cmd/compile/internal/ssa/README.md`.
|
head to [cmd/compile/internal/ssa/README.md](internal/ssa/README.md).
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,9 @@ type File struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFormats(t *testing.T) {
|
func TestFormats(t *testing.T) {
|
||||||
|
if testing.Short() {
|
||||||
|
t.Skip("Skipping in short mode")
|
||||||
|
}
|
||||||
testenv.MustHaveGoBuild(t) // more restrictive than necessary, but that's ok
|
testenv.MustHaveGoBuild(t) // more restrictive than necessary, but that's ok
|
||||||
|
|
||||||
// process all directories
|
// process all directories
|
||||||
|
|
@ -721,6 +724,7 @@ var knownFormats = map[string]string{
|
||||||
"uint16 %d": "",
|
"uint16 %d": "",
|
||||||
"uint16 %v": "",
|
"uint16 %v": "",
|
||||||
"uint16 %x": "",
|
"uint16 %x": "",
|
||||||
|
"uint32 %#x": "",
|
||||||
"uint32 %d": "",
|
"uint32 %d": "",
|
||||||
"uint32 %v": "",
|
"uint32 %v": "",
|
||||||
"uint32 %x": "",
|
"uint32 %x": "",
|
||||||
|
|
|
||||||
|
|
@ -524,6 +524,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
||||||
case ssa.OpAMD64LEAQ1, ssa.OpAMD64LEAQ2, ssa.OpAMD64LEAQ4, ssa.OpAMD64LEAQ8,
|
case ssa.OpAMD64LEAQ1, ssa.OpAMD64LEAQ2, ssa.OpAMD64LEAQ4, ssa.OpAMD64LEAQ8,
|
||||||
ssa.OpAMD64LEAL1, ssa.OpAMD64LEAL2, ssa.OpAMD64LEAL4, ssa.OpAMD64LEAL8,
|
ssa.OpAMD64LEAL1, ssa.OpAMD64LEAL2, ssa.OpAMD64LEAL4, ssa.OpAMD64LEAL8,
|
||||||
ssa.OpAMD64LEAW1, ssa.OpAMD64LEAW2, ssa.OpAMD64LEAW4, ssa.OpAMD64LEAW8:
|
ssa.OpAMD64LEAW1, ssa.OpAMD64LEAW2, ssa.OpAMD64LEAW4, ssa.OpAMD64LEAW8:
|
||||||
|
o := v.Reg()
|
||||||
r := v.Args[0].Reg()
|
r := v.Args[0].Reg()
|
||||||
i := v.Args[1].Reg()
|
i := v.Args[1].Reg()
|
||||||
p := s.Prog(v.Op.Asm())
|
p := s.Prog(v.Op.Asm())
|
||||||
|
|
@ -543,9 +544,24 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
||||||
p.From.Type = obj.TYPE_MEM
|
p.From.Type = obj.TYPE_MEM
|
||||||
p.From.Reg = r
|
p.From.Reg = r
|
||||||
p.From.Index = i
|
p.From.Index = i
|
||||||
gc.AddAux(&p.From, v)
|
|
||||||
p.To.Type = obj.TYPE_REG
|
p.To.Type = obj.TYPE_REG
|
||||||
p.To.Reg = v.Reg()
|
p.To.Reg = o
|
||||||
|
if v.AuxInt != 0 && v.Aux == nil {
|
||||||
|
// Emit an additional LEA to add the displacement instead of creating a slow 3 operand LEA.
|
||||||
|
switch v.Op {
|
||||||
|
case ssa.OpAMD64LEAQ1, ssa.OpAMD64LEAQ2, ssa.OpAMD64LEAQ4, ssa.OpAMD64LEAQ8:
|
||||||
|
p = s.Prog(x86.ALEAQ)
|
||||||
|
case ssa.OpAMD64LEAL1, ssa.OpAMD64LEAL2, ssa.OpAMD64LEAL4, ssa.OpAMD64LEAL8:
|
||||||
|
p = s.Prog(x86.ALEAL)
|
||||||
|
case ssa.OpAMD64LEAW1, ssa.OpAMD64LEAW2, ssa.OpAMD64LEAW4, ssa.OpAMD64LEAW8:
|
||||||
|
p = s.Prog(x86.ALEAW)
|
||||||
|
}
|
||||||
|
p.From.Type = obj.TYPE_MEM
|
||||||
|
p.From.Reg = o
|
||||||
|
p.To.Type = obj.TYPE_REG
|
||||||
|
p.To.Reg = o
|
||||||
|
}
|
||||||
|
gc.AddAux(&p.From, v)
|
||||||
case ssa.OpAMD64LEAQ, ssa.OpAMD64LEAL, ssa.OpAMD64LEAW:
|
case ssa.OpAMD64LEAQ, ssa.OpAMD64LEAL, ssa.OpAMD64LEAW:
|
||||||
p := s.Prog(v.Op.Asm())
|
p := s.Prog(v.Op.Asm())
|
||||||
p.From.Type = obj.TYPE_MEM
|
p.From.Type = obj.TYPE_MEM
|
||||||
|
|
@ -683,7 +699,9 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
||||||
gc.AddAux(&p.From, v)
|
gc.AddAux(&p.From, v)
|
||||||
p.To.Type = obj.TYPE_REG
|
p.To.Type = obj.TYPE_REG
|
||||||
p.To.Reg = v.Reg()
|
p.To.Reg = v.Reg()
|
||||||
case ssa.OpAMD64MOVQstore, ssa.OpAMD64MOVSSstore, ssa.OpAMD64MOVSDstore, ssa.OpAMD64MOVLstore, ssa.OpAMD64MOVWstore, ssa.OpAMD64MOVBstore, ssa.OpAMD64MOVOstore:
|
case ssa.OpAMD64MOVQstore, ssa.OpAMD64MOVSSstore, ssa.OpAMD64MOVSDstore, ssa.OpAMD64MOVLstore, ssa.OpAMD64MOVWstore, ssa.OpAMD64MOVBstore, ssa.OpAMD64MOVOstore,
|
||||||
|
ssa.OpAMD64ADDQmodify, ssa.OpAMD64SUBQmodify, ssa.OpAMD64ANDQmodify, ssa.OpAMD64ORQmodify, ssa.OpAMD64XORQmodify,
|
||||||
|
ssa.OpAMD64ADDLmodify, ssa.OpAMD64SUBLmodify, ssa.OpAMD64ANDLmodify, ssa.OpAMD64ORLmodify, ssa.OpAMD64XORLmodify:
|
||||||
p := s.Prog(v.Op.Asm())
|
p := s.Prog(v.Op.Asm())
|
||||||
p.From.Type = obj.TYPE_REG
|
p.From.Type = obj.TYPE_REG
|
||||||
p.From.Reg = v.Args[1].Reg()
|
p.From.Reg = v.Args[1].Reg()
|
||||||
|
|
@ -754,6 +772,17 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
||||||
p.To.Reg = v.Args[0].Reg()
|
p.To.Reg = v.Args[0].Reg()
|
||||||
gc.AddAux2(&p.To, v, off)
|
gc.AddAux2(&p.To, v, off)
|
||||||
}
|
}
|
||||||
|
case ssa.OpAMD64ANDQconstmodify, ssa.OpAMD64ANDLconstmodify, ssa.OpAMD64ORQconstmodify, ssa.OpAMD64ORLconstmodify,
|
||||||
|
ssa.OpAMD64XORQconstmodify, ssa.OpAMD64XORLconstmodify:
|
||||||
|
sc := v.AuxValAndOff()
|
||||||
|
off := sc.Off()
|
||||||
|
val := sc.Val()
|
||||||
|
p := s.Prog(v.Op.Asm())
|
||||||
|
p.From.Type = obj.TYPE_CONST
|
||||||
|
p.From.Offset = val
|
||||||
|
p.To.Type = obj.TYPE_MEM
|
||||||
|
p.To.Reg = v.Args[0].Reg()
|
||||||
|
gc.AddAux2(&p.To, v, off)
|
||||||
case ssa.OpAMD64MOVQstoreconst, ssa.OpAMD64MOVLstoreconst, ssa.OpAMD64MOVWstoreconst, ssa.OpAMD64MOVBstoreconst:
|
case ssa.OpAMD64MOVQstoreconst, ssa.OpAMD64MOVLstoreconst, ssa.OpAMD64MOVWstoreconst, ssa.OpAMD64MOVBstoreconst:
|
||||||
p := s.Prog(v.Op.Asm())
|
p := s.Prog(v.Op.Asm())
|
||||||
p.From.Type = obj.TYPE_CONST
|
p.From.Type = obj.TYPE_CONST
|
||||||
|
|
@ -810,7 +839,8 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
||||||
case ssa.OpAMD64ADDQload, ssa.OpAMD64ADDLload, ssa.OpAMD64SUBQload, ssa.OpAMD64SUBLload,
|
case ssa.OpAMD64ADDQload, ssa.OpAMD64ADDLload, ssa.OpAMD64SUBQload, ssa.OpAMD64SUBLload,
|
||||||
ssa.OpAMD64ANDQload, ssa.OpAMD64ANDLload, ssa.OpAMD64ORQload, ssa.OpAMD64ORLload,
|
ssa.OpAMD64ANDQload, ssa.OpAMD64ANDLload, ssa.OpAMD64ORQload, ssa.OpAMD64ORLload,
|
||||||
ssa.OpAMD64XORQload, ssa.OpAMD64XORLload, ssa.OpAMD64ADDSDload, ssa.OpAMD64ADDSSload,
|
ssa.OpAMD64XORQload, ssa.OpAMD64XORLload, ssa.OpAMD64ADDSDload, ssa.OpAMD64ADDSSload,
|
||||||
ssa.OpAMD64SUBSDload, ssa.OpAMD64SUBSSload, ssa.OpAMD64MULSDload, ssa.OpAMD64MULSSload:
|
ssa.OpAMD64SUBSDload, ssa.OpAMD64SUBSSload, ssa.OpAMD64MULSDload, ssa.OpAMD64MULSSload,
|
||||||
|
ssa.OpAMD64DIVSDload, ssa.OpAMD64DIVSSload:
|
||||||
p := s.Prog(v.Op.Asm())
|
p := s.Prog(v.Op.Asm())
|
||||||
p.From.Type = obj.TYPE_MEM
|
p.From.Type = obj.TYPE_MEM
|
||||||
p.From.Reg = v.Args[1].Reg()
|
p.From.Reg = v.Args[1].Reg()
|
||||||
|
|
|
||||||
|
|
@ -14,10 +14,10 @@ import (
|
||||||
var darwin = objabi.GOOS == "darwin"
|
var darwin = objabi.GOOS == "darwin"
|
||||||
|
|
||||||
func padframe(frame int64) int64 {
|
func padframe(frame int64) int64 {
|
||||||
// arm64 requires that the frame size (not counting saved LR)
|
// arm64 requires that the frame size (not counting saved FP&LR)
|
||||||
// be empty or be 8 mod 16. If not, pad it.
|
// be 16 bytes aligned. If not, pad it.
|
||||||
if frame != 0 && frame%16 != 8 {
|
if frame%16 != 0 {
|
||||||
frame += 8
|
frame += 16 - (frame % 16)
|
||||||
}
|
}
|
||||||
return frame
|
return frame
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -212,7 +212,11 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
||||||
ssa.OpARM64FMSUBS,
|
ssa.OpARM64FMSUBS,
|
||||||
ssa.OpARM64FMSUBD,
|
ssa.OpARM64FMSUBD,
|
||||||
ssa.OpARM64FNMSUBS,
|
ssa.OpARM64FNMSUBS,
|
||||||
ssa.OpARM64FNMSUBD:
|
ssa.OpARM64FNMSUBD,
|
||||||
|
ssa.OpARM64MADD,
|
||||||
|
ssa.OpARM64MADDW,
|
||||||
|
ssa.OpARM64MSUB,
|
||||||
|
ssa.OpARM64MSUBW:
|
||||||
rt := v.Reg()
|
rt := v.Reg()
|
||||||
ra := v.Args[0].Reg()
|
ra := v.Args[0].Reg()
|
||||||
rm := v.Args[1].Reg()
|
rm := v.Args[1].Reg()
|
||||||
|
|
@ -369,6 +373,8 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
||||||
ssa.OpARM64MOVWloadidx,
|
ssa.OpARM64MOVWloadidx,
|
||||||
ssa.OpARM64MOVWUloadidx,
|
ssa.OpARM64MOVWUloadidx,
|
||||||
ssa.OpARM64MOVDloadidx,
|
ssa.OpARM64MOVDloadidx,
|
||||||
|
ssa.OpARM64FMOVSloadidx,
|
||||||
|
ssa.OpARM64FMOVDloadidx,
|
||||||
ssa.OpARM64MOVHloadidx2,
|
ssa.OpARM64MOVHloadidx2,
|
||||||
ssa.OpARM64MOVHUloadidx2,
|
ssa.OpARM64MOVHUloadidx2,
|
||||||
ssa.OpARM64MOVWloadidx4,
|
ssa.OpARM64MOVWloadidx4,
|
||||||
|
|
@ -404,6 +410,8 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
||||||
ssa.OpARM64MOVHstoreidx,
|
ssa.OpARM64MOVHstoreidx,
|
||||||
ssa.OpARM64MOVWstoreidx,
|
ssa.OpARM64MOVWstoreidx,
|
||||||
ssa.OpARM64MOVDstoreidx,
|
ssa.OpARM64MOVDstoreidx,
|
||||||
|
ssa.OpARM64FMOVSstoreidx,
|
||||||
|
ssa.OpARM64FMOVDstoreidx,
|
||||||
ssa.OpARM64MOVHstoreidx2,
|
ssa.OpARM64MOVHstoreidx2,
|
||||||
ssa.OpARM64MOVWstoreidx4,
|
ssa.OpARM64MOVWstoreidx4,
|
||||||
ssa.OpARM64MOVDstoreidx8:
|
ssa.OpARM64MOVDstoreidx8:
|
||||||
|
|
|
||||||
|
|
@ -464,19 +464,22 @@ func (p *exporter) markType(t *types.Type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recursively mark any types that can be produced given a
|
// Recursively mark any types that can be produced given a
|
||||||
// value of type t: dereferencing a pointer; indexing an
|
// value of type t: dereferencing a pointer; indexing or
|
||||||
// array, slice, or map; receiving from a channel; accessing a
|
// iterating over an array, slice, or map; receiving from a
|
||||||
// struct field or interface method; or calling a function.
|
// channel; accessing a struct field or interface method; or
|
||||||
|
// calling a function.
|
||||||
//
|
//
|
||||||
// Notably, we don't mark map key or function parameter types,
|
// Notably, we don't mark function parameter types, because
|
||||||
// because the user already needs some way to construct values
|
// the user already needs some way to construct values of
|
||||||
// of those types.
|
// those types.
|
||||||
//
|
|
||||||
// It's not critical for correctness that this algorithm is
|
|
||||||
// perfect. Worst case, we might miss opportunities to inline
|
|
||||||
// some function calls in downstream packages.
|
|
||||||
switch t.Etype {
|
switch t.Etype {
|
||||||
case TPTR32, TPTR64, TARRAY, TSLICE, TCHAN, TMAP:
|
case TPTR32, TPTR64, TARRAY, TSLICE, TCHAN:
|
||||||
|
// TODO(mdempsky): Skip marking element type for
|
||||||
|
// send-only channels?
|
||||||
|
p.markType(t.Elem())
|
||||||
|
|
||||||
|
case TMAP:
|
||||||
|
p.markType(t.Key())
|
||||||
p.markType(t.Elem())
|
p.markType(t.Elem())
|
||||||
|
|
||||||
case TSTRUCT:
|
case TSTRUCT:
|
||||||
|
|
|
||||||
|
|
@ -227,17 +227,6 @@ type bvecSet struct {
|
||||||
uniq []bvec // unique bvecs, in insertion order
|
uniq []bvec // unique bvecs, in insertion order
|
||||||
}
|
}
|
||||||
|
|
||||||
func newBvecSet(size int) bvecSet {
|
|
||||||
// bvecSet is a linear probing hash table.
|
|
||||||
// The hash table has 4n entries to keep the linear
|
|
||||||
// scan short.
|
|
||||||
index := make([]int, size*4)
|
|
||||||
for i := range index {
|
|
||||||
index[i] = -1
|
|
||||||
}
|
|
||||||
return bvecSet{index, nil}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *bvecSet) grow() {
|
func (m *bvecSet) grow() {
|
||||||
// Allocate new index.
|
// Allocate new index.
|
||||||
n := len(m.index) * 2
|
n := len(m.index) * 2
|
||||||
|
|
|
||||||
|
|
@ -382,10 +382,7 @@ func walkclosure(clo *Node, init *Nodes) *Node {
|
||||||
clos.List.Set(append([]*Node{nod(OCFUNC, xfunc.Func.Nname, nil)}, clo.Func.Enter.Slice()...))
|
clos.List.Set(append([]*Node{nod(OCFUNC, xfunc.Func.Nname, nil)}, clo.Func.Enter.Slice()...))
|
||||||
|
|
||||||
// Force type conversion from *struct to the func type.
|
// Force type conversion from *struct to the func type.
|
||||||
clos = nod(OCONVNOP, clos, nil)
|
clos = convnop(clos, clo.Type)
|
||||||
clos.Type = clo.Type
|
|
||||||
|
|
||||||
clos = typecheck(clos, Erv)
|
|
||||||
|
|
||||||
// typecheck will insert a PTRLIT node under CONVNOP,
|
// typecheck will insert a PTRLIT node under CONVNOP,
|
||||||
// tag it with escape analysis result.
|
// tag it with escape analysis result.
|
||||||
|
|
@ -511,10 +508,7 @@ func walkpartialcall(n *Node, init *Nodes) *Node {
|
||||||
clos.List.Append(n.Left)
|
clos.List.Append(n.Left)
|
||||||
|
|
||||||
// Force type conversion from *struct to the func type.
|
// Force type conversion from *struct to the func type.
|
||||||
clos = nod(OCONVNOP, clos, nil)
|
clos = convnop(clos, n.Type)
|
||||||
clos.Type = n.Type
|
|
||||||
|
|
||||||
clos = typecheck(clos, Erv)
|
|
||||||
|
|
||||||
// typecheck will insert a PTRLIT node under CONVNOP,
|
// typecheck will insert a PTRLIT node under CONVNOP,
|
||||||
// tag it with escape analysis result.
|
// tag it with escape analysis result.
|
||||||
|
|
|
||||||
|
|
@ -121,6 +121,17 @@ func (n *Node) Int64() int64 {
|
||||||
return n.Val().U.(*Mpint).Int64()
|
return n.Val().U.(*Mpint).Int64()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CanInt64 reports whether it is safe to call Int64() on n.
|
||||||
|
func (n *Node) CanInt64() bool {
|
||||||
|
if !Isconst(n, CTINT) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the value inside n cannot be represented as an int64, the
|
||||||
|
// return value of Int64 is undefined
|
||||||
|
return n.Val().U.(*Mpint).CmpInt64(n.Int64()) == 0
|
||||||
|
}
|
||||||
|
|
||||||
// Bool returns n as a bool.
|
// Bool returns n as a bool.
|
||||||
// n must be a boolean constant.
|
// n must be a boolean constant.
|
||||||
func (n *Node) Bool() bool {
|
func (n *Node) Bool() bool {
|
||||||
|
|
@ -766,7 +777,7 @@ func evconst(n *Node) {
|
||||||
v.U.(*Mpint).Neg()
|
v.U.(*Mpint).Neg()
|
||||||
|
|
||||||
case OCOM_ | CTINT_:
|
case OCOM_ | CTINT_:
|
||||||
var et types.EType = Txxx
|
et := Txxx
|
||||||
if nl.Type != nil {
|
if nl.Type != nil {
|
||||||
et = nl.Type.Etype
|
et = nl.Type.Etype
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ import (
|
||||||
"cmd/internal/dwarf"
|
"cmd/internal/dwarf"
|
||||||
"cmd/internal/obj"
|
"cmd/internal/obj"
|
||||||
"cmd/internal/src"
|
"cmd/internal/src"
|
||||||
"sort"
|
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -96,7 +95,6 @@ func assembleInlines(fnsym *obj.LSym, dwVars []*dwarf.Var) dwarf.InlCalls {
|
||||||
// the pre-inlining decls for the target function and assign child
|
// the pre-inlining decls for the target function and assign child
|
||||||
// index accordingly.
|
// index accordingly.
|
||||||
for ii, sl := range vmap {
|
for ii, sl := range vmap {
|
||||||
sort.Sort(byClassThenName(sl))
|
|
||||||
var m map[varPos]int
|
var m map[varPos]int
|
||||||
if ii == 0 {
|
if ii == 0 {
|
||||||
if !fnsym.WasInlined() {
|
if !fnsym.WasInlined() {
|
||||||
|
|
@ -142,7 +140,7 @@ func assembleInlines(fnsym *obj.LSym, dwVars []*dwarf.Var) dwarf.InlCalls {
|
||||||
// return temps (~r%d) that were created during
|
// return temps (~r%d) that were created during
|
||||||
// lowering, or unnamed params ("_").
|
// lowering, or unnamed params ("_").
|
||||||
v.ChildIndex = int32(synthCount)
|
v.ChildIndex = int32(synthCount)
|
||||||
synthCount += 1
|
synthCount++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -311,31 +309,6 @@ func beginRange(calls []dwarf.InlCall, p *obj.Prog, ii int, imap map[int]int) *d
|
||||||
return &call.Ranges[len(call.Ranges)-1]
|
return &call.Ranges[len(call.Ranges)-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
func cmpDwarfVar(a, b *dwarf.Var) bool {
|
|
||||||
// named before artificial
|
|
||||||
aart := 0
|
|
||||||
if strings.HasPrefix(a.Name, "~r") {
|
|
||||||
aart = 1
|
|
||||||
}
|
|
||||||
bart := 0
|
|
||||||
if strings.HasPrefix(b.Name, "~r") {
|
|
||||||
bart = 1
|
|
||||||
}
|
|
||||||
if aart != bart {
|
|
||||||
return aart < bart
|
|
||||||
}
|
|
||||||
|
|
||||||
// otherwise sort by name
|
|
||||||
return a.Name < b.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
// byClassThenName implements sort.Interface for []*dwarf.Var using cmpDwarfVar.
|
|
||||||
type byClassThenName []*dwarf.Var
|
|
||||||
|
|
||||||
func (s byClassThenName) Len() int { return len(s) }
|
|
||||||
func (s byClassThenName) Less(i, j int) bool { return cmpDwarfVar(s[i], s[j]) }
|
|
||||||
func (s byClassThenName) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
|
||||||
|
|
||||||
func dumpInlCall(inlcalls dwarf.InlCalls, idx, ilevel int) {
|
func dumpInlCall(inlcalls dwarf.InlCalls, idx, ilevel int) {
|
||||||
for i := 0; i < ilevel; i++ {
|
for i := 0; i < ilevel; i++ {
|
||||||
Ctxt.Logf(" ")
|
Ctxt.Logf(" ")
|
||||||
|
|
|
||||||
|
|
@ -502,8 +502,6 @@ func escAnalyze(all []*Node, recursive bool) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// print("escapes: %d e.dsts, %d edges\n", e.dstcount, e.edgecount);
|
|
||||||
|
|
||||||
// visit the upstream of each dst, mark address nodes with
|
// visit the upstream of each dst, mark address nodes with
|
||||||
// addrescapes, mark parameters unsafe
|
// addrescapes, mark parameters unsafe
|
||||||
escapes := make([]uint16, len(e.dsts))
|
escapes := make([]uint16, len(e.dsts))
|
||||||
|
|
@ -551,7 +549,6 @@ func escAnalyze(all []*Node, recursive bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *EscState) escfunc(fn *Node) {
|
func (e *EscState) escfunc(fn *Node) {
|
||||||
// print("escfunc %N %s\n", fn.Func.Nname, e.recursive?"(recursive)":"");
|
|
||||||
if fn.Esc != EscFuncPlanned {
|
if fn.Esc != EscFuncPlanned {
|
||||||
Fatalf("repeat escfunc %v", fn.Func.Nname)
|
Fatalf("repeat escfunc %v", fn.Func.Nname)
|
||||||
}
|
}
|
||||||
|
|
@ -630,8 +627,6 @@ func (e *EscState) escloopdepth(n *Node) {
|
||||||
|
|
||||||
// Walk will complain about this label being already defined, but that's not until
|
// Walk will complain about this label being already defined, but that's not until
|
||||||
// after escape analysis. in the future, maybe pull label & goto analysis out of walk and put before esc
|
// after escape analysis. in the future, maybe pull label & goto analysis out of walk and put before esc
|
||||||
// if(n.Left.Sym.Label != nil)
|
|
||||||
// fatal("escape analysis messed up analyzing label: %+N", n);
|
|
||||||
n.Left.Sym.Label = asTypesNode(&nonlooping)
|
n.Left.Sym.Label = asTypesNode(&nonlooping)
|
||||||
|
|
||||||
case OGOTO:
|
case OGOTO:
|
||||||
|
|
@ -659,6 +654,58 @@ func (e *EscState) esclist(l Nodes, parent *Node) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// isSelfAssign reports whether assignment from src to dst can
|
||||||
|
// be ignored by the escape analysis as it's effectively a self-assignment.
|
||||||
|
func (e *EscState) isSelfAssign(dst, src *Node) bool {
|
||||||
|
if dst == nil || src == nil || dst.Op != src.Op {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
switch dst.Op {
|
||||||
|
case ODOT, ODOTPTR:
|
||||||
|
// Safe trailing accessors that are permitted to differ.
|
||||||
|
case OINDEX:
|
||||||
|
if e.mayAffectMemory(dst.Right) || e.mayAffectMemory(src.Right) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// The expression prefix must be both "safe" and identical.
|
||||||
|
return samesafeexpr(dst.Left, src.Left)
|
||||||
|
}
|
||||||
|
|
||||||
|
// mayAffectMemory reports whether n evaluation may affect program memory state.
|
||||||
|
// If expression can't affect it, then it can be safely ignored by the escape analysis.
|
||||||
|
func (e *EscState) mayAffectMemory(n *Node) bool {
|
||||||
|
// We may want to use "memory safe" black list instead of general
|
||||||
|
// "side-effect free", which can include all calls and other ops
|
||||||
|
// that can affect allocate or change global state.
|
||||||
|
// It's safer to start from a whitelist for now.
|
||||||
|
//
|
||||||
|
// We're ignoring things like division by zero, index out of range,
|
||||||
|
// and nil pointer dereference here.
|
||||||
|
switch n.Op {
|
||||||
|
case ONAME, OCLOSUREVAR, OLITERAL:
|
||||||
|
return false
|
||||||
|
case ODOT, ODOTPTR:
|
||||||
|
return e.mayAffectMemory(n.Left)
|
||||||
|
case OIND, OCONVNOP:
|
||||||
|
return e.mayAffectMemory(n.Left)
|
||||||
|
case OCONV:
|
||||||
|
return e.mayAffectMemory(n.Left)
|
||||||
|
case OINDEX:
|
||||||
|
return e.mayAffectMemory(n.Left) || e.mayAffectMemory(n.Right)
|
||||||
|
case OADD, OSUB, OOR, OXOR, OMUL, OLSH, ORSH, OAND, OANDNOT, ODIV, OMOD:
|
||||||
|
return e.mayAffectMemory(n.Left) || e.mayAffectMemory(n.Right)
|
||||||
|
case ONOT, OCOM, OPLUS, OMINUS, OALIGNOF, OOFFSETOF, OSIZEOF:
|
||||||
|
return e.mayAffectMemory(n.Left)
|
||||||
|
default:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (e *EscState) esc(n *Node, parent *Node) {
|
func (e *EscState) esc(n *Node, parent *Node) {
|
||||||
if n == nil {
|
if n == nil {
|
||||||
return
|
return
|
||||||
|
|
@ -756,10 +803,6 @@ opSwitch:
|
||||||
e.loopdepth++
|
e.loopdepth++
|
||||||
}
|
}
|
||||||
|
|
||||||
// See case OLABEL in escloopdepth above
|
|
||||||
// else if(n.Left.Sym.Label == nil)
|
|
||||||
// fatal("escape analysis missed or messed up a label: %+N", n);
|
|
||||||
|
|
||||||
n.Left.Sym.Label = nil
|
n.Left.Sym.Label = nil
|
||||||
|
|
||||||
case ORANGE:
|
case ORANGE:
|
||||||
|
|
@ -822,13 +865,30 @@ opSwitch:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Also skip trivial assignments that assign back to the same object.
|
||||||
|
//
|
||||||
|
// It covers these cases:
|
||||||
|
// val.x = val.y
|
||||||
|
// val.x[i] = val.y[j]
|
||||||
|
// val.x1.x2 = val.x1.y2
|
||||||
|
// ... etc
|
||||||
|
//
|
||||||
|
// These assignments do not change assigned object lifetime.
|
||||||
|
if e.isSelfAssign(n.Left, n.Right) {
|
||||||
|
if Debug['m'] != 0 {
|
||||||
|
Warnl(n.Pos, "%v ignoring self-assignment in %S", e.curfnSym(n), n)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
e.escassign(n.Left, n.Right, e.stepAssignWhere(nil, nil, "", n))
|
e.escassign(n.Left, n.Right, e.stepAssignWhere(nil, nil, "", n))
|
||||||
|
|
||||||
case OAS2: // x,y = a,b
|
case OAS2: // x,y = a,b
|
||||||
if n.List.Len() == n.Rlist.Len() {
|
if n.List.Len() == n.Rlist.Len() {
|
||||||
rs := n.Rlist.Slice()
|
rs := n.Rlist.Slice()
|
||||||
|
where := n
|
||||||
for i, n := range n.List.Slice() {
|
for i, n := range n.List.Slice() {
|
||||||
e.escassignWhyWhere(n, rs[i], "assign-pair", n)
|
e.escassignWhyWhere(n, rs[i], "assign-pair", where)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -869,11 +929,12 @@ opSwitch:
|
||||||
// esccall already done on n.Rlist.First(). tie it's Retval to n.List
|
// esccall already done on n.Rlist.First(). tie it's Retval to n.List
|
||||||
case OAS2FUNC: // x,y = f()
|
case OAS2FUNC: // x,y = f()
|
||||||
rs := e.nodeEscState(n.Rlist.First()).Retval.Slice()
|
rs := e.nodeEscState(n.Rlist.First()).Retval.Slice()
|
||||||
|
where := n
|
||||||
for i, n := range n.List.Slice() {
|
for i, n := range n.List.Slice() {
|
||||||
if i >= len(rs) {
|
if i >= len(rs) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
e.escassignWhyWhere(n, rs[i], "assign-pair-func-call", n)
|
e.escassignWhyWhere(n, rs[i], "assign-pair-func-call", where)
|
||||||
}
|
}
|
||||||
if n.List.Len() != len(rs) {
|
if n.List.Len() != len(rs) {
|
||||||
Fatalf("esc oas2func")
|
Fatalf("esc oas2func")
|
||||||
|
|
@ -1561,12 +1622,11 @@ func (e *EscState) esccall(call *Node, parent *Node) {
|
||||||
cE := e.nodeEscState(call)
|
cE := e.nodeEscState(call)
|
||||||
if fn != nil && fn.Op == ONAME && fn.Class() == PFUNC &&
|
if fn != nil && fn.Op == ONAME && fn.Class() == PFUNC &&
|
||||||
fn.Name.Defn != nil && fn.Name.Defn.Nbody.Len() != 0 && fn.Name.Param.Ntype != nil && fn.Name.Defn.Esc < EscFuncTagged {
|
fn.Name.Defn != nil && fn.Name.Defn.Nbody.Len() != 0 && fn.Name.Param.Ntype != nil && fn.Name.Defn.Esc < EscFuncTagged {
|
||||||
|
// function in same mutually recursive group. Incorporate into flow graph.
|
||||||
if Debug['m'] > 3 {
|
if Debug['m'] > 3 {
|
||||||
fmt.Printf("%v::esccall:: %S in recursive group\n", linestr(lineno), call)
|
fmt.Printf("%v::esccall:: %S in recursive group\n", linestr(lineno), call)
|
||||||
}
|
}
|
||||||
|
|
||||||
// function in same mutually recursive group. Incorporate into flow graph.
|
|
||||||
// print("esc local fn: %N\n", fn.Func.Ntype);
|
|
||||||
if fn.Name.Defn.Esc == EscFuncUnknown || cE.Retval.Len() != 0 {
|
if fn.Name.Defn.Esc == EscFuncUnknown || cE.Retval.Len() != 0 {
|
||||||
Fatalf("graph inconsistency")
|
Fatalf("graph inconsistency")
|
||||||
}
|
}
|
||||||
|
|
@ -1629,8 +1689,6 @@ func (e *EscState) esccall(call *Node, parent *Node) {
|
||||||
// set up out list on this call node with dummy auto ONAMES in the current (calling) function.
|
// set up out list on this call node with dummy auto ONAMES in the current (calling) function.
|
||||||
e.initEscRetval(call, fntype)
|
e.initEscRetval(call, fntype)
|
||||||
|
|
||||||
// print("esc analyzed fn: %#N (%+T) returning (%+H)\n", fn, fntype, e.nodeEscState(call).Retval);
|
|
||||||
|
|
||||||
// Receiver.
|
// Receiver.
|
||||||
if call.Op != OCALLFUNC {
|
if call.Op != OCALLFUNC {
|
||||||
rf := fntype.Recv()
|
rf := fntype.Recv()
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ func dumpexport(bout *bio.Writer) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func importsym(ipkg *types.Pkg, pos src.XPos, s *types.Sym, op Op) *Node {
|
func importsym(ipkg *types.Pkg, s *types.Sym, op Op) *Node {
|
||||||
n := asNode(s.PkgDef())
|
n := asNode(s.PkgDef())
|
||||||
if n == nil {
|
if n == nil {
|
||||||
// iimport should have created a stub ONONAME
|
// iimport should have created a stub ONONAME
|
||||||
|
|
@ -113,7 +113,7 @@ func importsym(ipkg *types.Pkg, pos src.XPos, s *types.Sym, op Op) *Node {
|
||||||
// If no such type has been declared yet, a forward declaration is returned.
|
// If no such type has been declared yet, a forward declaration is returned.
|
||||||
// ipkg is the package being imported
|
// ipkg is the package being imported
|
||||||
func importtype(ipkg *types.Pkg, pos src.XPos, s *types.Sym) *types.Type {
|
func importtype(ipkg *types.Pkg, pos src.XPos, s *types.Sym) *types.Type {
|
||||||
n := importsym(ipkg, pos, s, OTYPE)
|
n := importsym(ipkg, s, OTYPE)
|
||||||
if n.Op != OTYPE {
|
if n.Op != OTYPE {
|
||||||
t := types.New(TFORW)
|
t := types.New(TFORW)
|
||||||
t.Sym = s
|
t.Sym = s
|
||||||
|
|
@ -135,7 +135,7 @@ func importtype(ipkg *types.Pkg, pos src.XPos, s *types.Sym) *types.Type {
|
||||||
// importobj declares symbol s as an imported object representable by op.
|
// importobj declares symbol s as an imported object representable by op.
|
||||||
// ipkg is the package being imported
|
// ipkg is the package being imported
|
||||||
func importobj(ipkg *types.Pkg, pos src.XPos, s *types.Sym, op Op, ctxt Class, t *types.Type) *Node {
|
func importobj(ipkg *types.Pkg, pos src.XPos, s *types.Sym, op Op, ctxt Class, t *types.Type) *Node {
|
||||||
n := importsym(ipkg, pos, s, op)
|
n := importsym(ipkg, s, op)
|
||||||
if n.Op != ONONAME {
|
if n.Op != ONONAME {
|
||||||
if n.Op == op && (n.Class() != ctxt || !eqtype(n.Type, t)) {
|
if n.Op == op && (n.Class() != ctxt || !eqtype(n.Type, t)) {
|
||||||
redeclare(lineno, s, fmt.Sprintf("during import %q", ipkg.Path))
|
redeclare(lineno, s, fmt.Sprintf("during import %q", ipkg.Path))
|
||||||
|
|
|
||||||
|
|
@ -362,6 +362,117 @@ func TestFloatConvertFolded(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFloat32StoreToLoadConstantFold(t *testing.T) {
|
||||||
|
// Test that math.Float32{,from}bits constant fold correctly.
|
||||||
|
// In particular we need to be careful that signalling NaN (sNaN) values
|
||||||
|
// are not converted to quiet NaN (qNaN) values during compilation.
|
||||||
|
// See issue #27193 for more information.
|
||||||
|
|
||||||
|
// signalling NaNs
|
||||||
|
{
|
||||||
|
const nan = uint32(0x7f800001) // sNaN
|
||||||
|
if x := math.Float32bits(math.Float32frombits(nan)); x != nan {
|
||||||
|
t.Errorf("got %#x, want %#x", x, nan)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const nan = uint32(0x7fbfffff) // sNaN
|
||||||
|
if x := math.Float32bits(math.Float32frombits(nan)); x != nan {
|
||||||
|
t.Errorf("got %#x, want %#x", x, nan)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const nan = uint32(0xff800001) // sNaN
|
||||||
|
if x := math.Float32bits(math.Float32frombits(nan)); x != nan {
|
||||||
|
t.Errorf("got %#x, want %#x", x, nan)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const nan = uint32(0xffbfffff) // sNaN
|
||||||
|
if x := math.Float32bits(math.Float32frombits(nan)); x != nan {
|
||||||
|
t.Errorf("got %#x, want %#x", x, nan)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// quiet NaNs
|
||||||
|
{
|
||||||
|
const nan = uint32(0x7fc00000) // qNaN
|
||||||
|
if x := math.Float32bits(math.Float32frombits(nan)); x != nan {
|
||||||
|
t.Errorf("got %#x, want %#x", x, nan)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const nan = uint32(0x7fffffff) // qNaN
|
||||||
|
if x := math.Float32bits(math.Float32frombits(nan)); x != nan {
|
||||||
|
t.Errorf("got %#x, want %#x", x, nan)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const nan = uint32(0x8fc00000) // qNaN
|
||||||
|
if x := math.Float32bits(math.Float32frombits(nan)); x != nan {
|
||||||
|
t.Errorf("got %#x, want %#x", x, nan)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const nan = uint32(0x8fffffff) // qNaN
|
||||||
|
if x := math.Float32bits(math.Float32frombits(nan)); x != nan {
|
||||||
|
t.Errorf("got %#x, want %#x", x, nan)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// infinities
|
||||||
|
{
|
||||||
|
const inf = uint32(0x7f800000) // +∞
|
||||||
|
if x := math.Float32bits(math.Float32frombits(inf)); x != inf {
|
||||||
|
t.Errorf("got %#x, want %#x", x, inf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const negInf = uint32(0xff800000) // -∞
|
||||||
|
if x := math.Float32bits(math.Float32frombits(negInf)); x != negInf {
|
||||||
|
t.Errorf("got %#x, want %#x", x, negInf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// numbers
|
||||||
|
{
|
||||||
|
const zero = uint32(0) // +0.0
|
||||||
|
if x := math.Float32bits(math.Float32frombits(zero)); x != zero {
|
||||||
|
t.Errorf("got %#x, want %#x", x, zero)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const negZero = uint32(1 << 31) // -0.0
|
||||||
|
if x := math.Float32bits(math.Float32frombits(negZero)); x != negZero {
|
||||||
|
t.Errorf("got %#x, want %#x", x, negZero)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const one = uint32(0x3f800000) // 1.0
|
||||||
|
if x := math.Float32bits(math.Float32frombits(one)); x != one {
|
||||||
|
t.Errorf("got %#x, want %#x", x, one)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const negOne = uint32(0xbf800000) // -1.0
|
||||||
|
if x := math.Float32bits(math.Float32frombits(negOne)); x != negOne {
|
||||||
|
t.Errorf("got %#x, want %#x", x, negOne)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const frac = uint32(0x3fc00000) // +1.5
|
||||||
|
if x := math.Float32bits(math.Float32frombits(frac)); x != frac {
|
||||||
|
t.Errorf("got %#x, want %#x", x, frac)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const negFrac = uint32(0xbfc00000) // -1.5
|
||||||
|
if x := math.Float32bits(math.Float32frombits(negFrac)); x != negFrac {
|
||||||
|
t.Errorf("got %#x, want %#x", x, negFrac)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var sinkFloat float64
|
var sinkFloat float64
|
||||||
|
|
||||||
func BenchmarkMul2(b *testing.B) {
|
func BenchmarkMul2(b *testing.B) {
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ package gc
|
||||||
import (
|
import (
|
||||||
"cmd/compile/internal/types"
|
"cmd/compile/internal/types"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
@ -1836,6 +1837,10 @@ func dumplist(s string, l Nodes) {
|
||||||
fmt.Printf("%s%+v\n", s, l)
|
fmt.Printf("%s%+v\n", s, l)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func fdumplist(w io.Writer, s string, l Nodes) {
|
||||||
|
fmt.Fprintf(w, "%s%+v\n", s, l)
|
||||||
|
}
|
||||||
|
|
||||||
func Dump(s string, n *Node) {
|
func Dump(s string, n *Node) {
|
||||||
fmt.Printf("%s [%p]%+v\n", s, n, n)
|
fmt.Printf("%s [%p]%+v\n", s, n, n)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -281,7 +281,7 @@ var (
|
||||||
assertE2I2,
|
assertE2I2,
|
||||||
assertI2I,
|
assertI2I,
|
||||||
assertI2I2,
|
assertI2I2,
|
||||||
Deferproc,
|
deferproc,
|
||||||
Deferreturn,
|
Deferreturn,
|
||||||
Duffcopy,
|
Duffcopy,
|
||||||
Duffzero,
|
Duffzero,
|
||||||
|
|
@ -290,7 +290,7 @@ var (
|
||||||
growslice,
|
growslice,
|
||||||
msanread,
|
msanread,
|
||||||
msanwrite,
|
msanwrite,
|
||||||
Newproc,
|
newproc,
|
||||||
panicdivide,
|
panicdivide,
|
||||||
panicdottypeE,
|
panicdottypeE,
|
||||||
panicdottypeI,
|
panicdottypeI,
|
||||||
|
|
|
||||||
|
|
@ -595,7 +595,7 @@ func (p *iexporter) typOff(t *types.Type) uint64 {
|
||||||
if !ok {
|
if !ok {
|
||||||
w := p.newWriter()
|
w := p.newWriter()
|
||||||
w.doTyp(t)
|
w.doTyp(t)
|
||||||
off = predeclReserved + uint64(w.flush())
|
off = predeclReserved + w.flush()
|
||||||
p.typIndex[t] = off
|
p.typIndex[t] = off
|
||||||
}
|
}
|
||||||
return off
|
return off
|
||||||
|
|
@ -952,6 +952,16 @@ func (w *exportWriter) funcExt(n *Node) {
|
||||||
if n.Func.ExportInline() {
|
if n.Func.ExportInline() {
|
||||||
w.p.doInline(n)
|
w.p.doInline(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Endlineno for inlined function.
|
||||||
|
if n.Name.Defn != nil {
|
||||||
|
w.pos(n.Name.Defn.Func.Endlineno)
|
||||||
|
} else {
|
||||||
|
// When the exported node was defined externally,
|
||||||
|
// e.g. io exports atomic.(*Value).Load or bytes exports errors.New.
|
||||||
|
// Keep it as we don't distinguish this case in iimport.go.
|
||||||
|
w.pos(n.Func.Endlineno)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
w.uint64(0)
|
w.uint64(0)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -296,8 +296,23 @@ func (r *importReader) doDecl(n *Node) {
|
||||||
// declaration before recursing.
|
// declaration before recursing.
|
||||||
t := importtype(r.p.ipkg, pos, n.Sym)
|
t := importtype(r.p.ipkg, pos, n.Sym)
|
||||||
|
|
||||||
|
// We also need to defer width calculations until
|
||||||
|
// after the underlying type has been assigned.
|
||||||
|
//
|
||||||
|
// TODO(mdempsky): Add nesting support directly to
|
||||||
|
// {defer,resume}checkwidth? Width calculations are
|
||||||
|
// already deferred during initial typechecking, but
|
||||||
|
// not when we're expanding inline function bodies, so
|
||||||
|
// we currently need to handle both cases here.
|
||||||
|
deferring := defercalc != 0
|
||||||
|
if !deferring {
|
||||||
|
defercheckwidth()
|
||||||
|
}
|
||||||
underlying := r.typ()
|
underlying := r.typ()
|
||||||
copytype(typenod(t), underlying)
|
copytype(typenod(t), underlying)
|
||||||
|
if !deferring {
|
||||||
|
resumecheckwidth()
|
||||||
|
}
|
||||||
|
|
||||||
if underlying.IsInterface() {
|
if underlying.IsInterface() {
|
||||||
break
|
break
|
||||||
|
|
@ -576,6 +591,10 @@ func (r *importReader) typ1() *types.Type {
|
||||||
t := types.New(TINTER)
|
t := types.New(TINTER)
|
||||||
t.SetPkg(r.currPkg)
|
t.SetPkg(r.currPkg)
|
||||||
t.SetInterface(append(embeddeds, methods...))
|
t.SetInterface(append(embeddeds, methods...))
|
||||||
|
|
||||||
|
// Ensure we expand the interface in the frontend (#25055).
|
||||||
|
checkwidth(t)
|
||||||
|
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -660,6 +679,7 @@ func (r *importReader) funcExt(n *Node) {
|
||||||
n.Func.Inl = &Inline{
|
n.Func.Inl = &Inline{
|
||||||
Cost: int32(u - 1),
|
Cost: int32(u - 1),
|
||||||
}
|
}
|
||||||
|
n.Func.Endlineno = r.pos()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue