mirror of
https://github.com/golang/go
synced 2024-09-15 22:20:06 +00:00
[dev.boringcrypto] all: merge master into dev.boringcrypto
Change-Id: Ia8ddd4e52dcfe87f9daef2edd37c8155fcae7f5a
This commit is contained in:
commit
4d1aa482b8
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-cgo), const SYS_KILL = 37
|
||||
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 CertChainPolicyStatus struct, ExtraPolicyStatus 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, OidSpecificInfo 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 CertChainPolicyStatus struct, ExtraPolicyStatus 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, OidSpecificInfo 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/rsa, method (*PrivateKey) 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, type DBStats struct, Idle 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 ListenConfig struct
|
||||
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 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, 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 FileMode
|
||||
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 ideal-int
|
||||
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 CertChainPolicyStatus struct, ExtraPolicyStatus Pointer
|
||||
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 ideal-int
|
||||
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 CertChainPolicyStatus struct, ExtraPolicyStatus Pointer
|
||||
pkg syscall (windows-amd64), type CertContext struct, CertInfo *CertInfo
|
||||
|
|
|
@ -44,18 +44,16 @@ control repositories.
|
|||
<h3 id="Workspaces">Workspaces</h3>
|
||||
|
||||
<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>
|
||||
|
||||
<ul>
|
||||
<li><code>src</code> contains Go source files,
|
||||
<li><code>pkg</code> contains package objects, and
|
||||
<li><code>src</code> contains Go source files, and
|
||||
<li><code>bin</code> contains executable commands.
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
The <code>go</code> tool builds source packages and installs the resulting
|
||||
binaries to the <code>pkg</code> and <code>bin</code> directories.
|
||||
The <code>go</code> tool builds and installs binaries to the <code>bin</code> directory.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
@ -72,10 +70,6 @@ To give you an idea of how a workspace looks in practice, here's an example:
|
|||
bin/
|
||||
hello # command executable
|
||||
outyet # command executable
|
||||
pkg/
|
||||
linux_amd64/
|
||||
github.com/golang/example/
|
||||
stringutil.a # package object
|
||||
src/
|
||||
<a href="https://github.com/golang/example/">github.com/golang/example/</a>
|
||||
.git/ # Git repository metadata
|
||||
|
@ -374,9 +368,8 @@ $ <b>go build</b>
|
|||
</pre>
|
||||
|
||||
<p>
|
||||
This won't produce an output file. To do that, you must use <code>go
|
||||
install</code>, which places the package object inside the <code>pkg</code>
|
||||
directory of the workspace.
|
||||
This won't produce an output file.
|
||||
Instead it saves the compiled package in the local build cache.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
@ -400,19 +393,13 @@ func main() {
|
|||
</pre>
|
||||
|
||||
<p>
|
||||
Whenever the <code>go</code> tool installs a package or binary, it also
|
||||
installs whatever dependencies it has.
|
||||
So when you install the <code>hello</code> program
|
||||
Install the <code>hello</code> program:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
$ <b>go install github.com/user/hello</b>
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
the <code>stringutil</code> package will be installed as well, automatically.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Running the new version of the program, you should see a new, reversed message:
|
||||
</p>
|
||||
|
@ -429,10 +416,6 @@ After the steps above, your workspace should look like this:
|
|||
<pre>
|
||||
bin/
|
||||
hello # command executable
|
||||
pkg/
|
||||
linux_amd64/ # this will reflect your OS and architecture
|
||||
github.com/user/
|
||||
stringutil.a # package object
|
||||
src/
|
||||
github.com/user/
|
||||
hello/
|
||||
|
@ -441,22 +424,6 @@ src/
|
|||
reverse.go # package source
|
||||
</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>
|
||||
|
||||
<p>
|
||||
|
@ -597,12 +564,6 @@ tree should now look like this:
|
|||
<pre>
|
||||
bin/
|
||||
hello # command executable
|
||||
pkg/
|
||||
linux_amd64/
|
||||
github.com/golang/example/
|
||||
stringutil.a # package object
|
||||
github.com/user/
|
||||
stringutil.a # package object
|
||||
src/
|
||||
github.com/golang/example/
|
||||
.git/ # Git repository metadata
|
||||
|
|
|
@ -73,7 +73,7 @@ $ go-contrib-init
|
|||
<p>
|
||||
The rest of this chapter elaborates on these instructions.
|
||||
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>
|
||||
|
||||
<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>
|
||||
</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>
|
||||
|
||||
<p>
|
||||
|
@ -386,7 +405,7 @@ This is an overview of the overall process:
|
|||
|
||||
<ul>
|
||||
<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:
|
||||
<pre>
|
||||
$ 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.
|
||||
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>.
|
||||
Either clone from
|
||||
<code>go.googlesource.com</code> or from GitHub:
|
||||
Clone from <code>go.googlesource.com</code> (not GitHub):
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
$ git clone https://github.com/golang/go # or https://go.googlesource.com/go
|
||||
$ git clone https://go.googlesource.com/go
|
||||
$ cd go
|
||||
</pre>
|
||||
|
||||
|
@ -678,7 +696,7 @@ Don't use HTML, Markdown, or any other markup language.
|
|||
<p>
|
||||
Add any relevant information, such as benchmark data if the change
|
||||
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
|
||||
benchmark data for change descriptions.
|
||||
</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).
|
||||
</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>
|
||||
|
||||
<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.
|
||||
</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>
|
||||
|
||||
<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; }
|
||||
</style>
|
||||
|
||||
<h2 id="introduction">DRAFT RELEASE NOTES - 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>
|
||||
<h2 id="introduction">Introduction to Go 1.11</h2>
|
||||
|
||||
<p>
|
||||
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>
|
||||
|
||||
<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
|
||||
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>
|
||||
|
@ -50,21 +48,400 @@ Do not send CLs removing the interior tags from such phrases.
|
|||
</p>
|
||||
|
||||
<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>
|
||||
|
||||
<h3 id="package-versioning">Package Versioning (vgo)</h3>
|
||||
<p>
|
||||
<strong>
|
||||
NOTE: This is not present in go1.11beta1 but will be available in future
|
||||
betas and subsequent releases.
|
||||
</strong>
|
||||
Go 1.11 adds experimental, integrated support for package versioning.
|
||||
<p><!-- CL 109255 -->
|
||||
The memory sanitizer (<code>-msan</code>) is now supported on <code>linux/arm64</code>.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 93875 -->
|
||||
The build modes <code>c-shared</code> and <code>c-archive</code> are now supported on
|
||||
<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>
|
||||
|
||||
<h3 id="wasm">WebAssembly</h3>
|
||||
<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>
|
||||
|
||||
<h2 id="library">Core library</h2>
|
||||
|
@ -81,34 +458,19 @@ Do not send CLs removing the interior tags from such phrases.
|
|||
in mind.
|
||||
</p>
|
||||
|
||||
<!-- CL 113315: https://golang.org/cl/113315: cmd/asm: enable AVX512 -->
|
||||
<!-- 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 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 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 -->
|
||||
<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>
|
||||
<dd>
|
||||
<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>
|
||||
|
||||
</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>
|
||||
<dd>
|
||||
<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>
|
||||
|
||||
</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>
|
||||
<dd>
|
||||
<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>
|
||||
|
||||
</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>
|
||||
<dd>
|
||||
<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>
|
||||
|
||||
</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>
|
||||
<dd>
|
||||
<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>
|
||||
|
||||
</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>
|
||||
<dd>
|
||||
<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>
|
||||
|
||||
</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>
|
||||
<dd>
|
||||
<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>
|
||||
|
||||
</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>
|
||||
<p><!-- CL 106256 -->
|
||||
TODO: <a href="https://golang.org/cl/106256">https://golang.org/cl/106256</a>: reserve RISC-V arch names
|
||||
<p><!-- CL 121815 -->
|
||||
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>
|
||||
|
||||
</dl><!-- go/build, runtime/internal/sys -->
|
||||
</dl><!-- html/template -->
|
||||
|
||||
<dl id="image/gif"><dt><a href="/pkg/image/gif/">image/gif</a></dt>
|
||||
<dd>
|
||||
<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>
|
||||
|
||||
</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>
|
||||
<dd>
|
||||
<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>
|
||||
|
||||
</dl><!-- io/ioutil -->
|
||||
|
||||
<dl id="math/big"><dt><a href="/pkg/math/big/">math/big</a></dt>
|
||||
<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>
|
||||
|
||||
</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>
|
||||
<dd>
|
||||
<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><!-- 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><!-- 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><!-- 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>
|
||||
|
||||
</dl><!-- net -->
|
||||
|
||||
<dl id="net/http"><dt><a href="/pkg/net/http/">net/http</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 89275 -->
|
||||
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
|
||||
<p><!-- CL 71272 -->
|
||||
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><!-- 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 -->
|
||||
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>
|
||||
|
||||
</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>
|
||||
<dd>
|
||||
<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><!-- 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><!-- 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><!-- 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>
|
||||
|
||||
</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>
|
||||
<dd>
|
||||
<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>
|
||||
|
||||
</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>
|
||||
<dd>
|
||||
<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>
|
||||
|
||||
</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>
|
||||
<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 -->
|
||||
TODO: <a href="https://golang.org/cl/94076">https://golang.org/cl/94076</a>: use native CAS and memory barrier on ARMv7
|
||||
</p>
|
||||
|
||||
<p><!-- CL 106156 -->
|
||||
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><!-- CL 70993 -->
|
||||
Setting the <code>GODEBUG=tracebackancestors=<em>N</em></code>
|
||||
environment variable now extends tracebacks with the stacks at
|
||||
which goroutines were created, where <em>N</em> limits the
|
||||
number of ancestor goroutines to report.
|
||||
</p>
|
||||
|
||||
</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>
|
||||
<dd>
|
||||
<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>
|
||||
|
||||
</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>
|
||||
<dd>
|
||||
<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>
|
||||
|
||||
</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>
|
||||
<dd>
|
||||
<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>
|
||||
|
||||
</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>
|
||||
<dd>
|
||||
<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>
|
||||
|
||||
</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>
|
||||
<dd>
|
||||
<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>
|
||||
|
||||
</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>
|
||||
<dd>
|
||||
<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>
|
||||
|
||||
</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",
|
||||
"Subtitle": "Version of May 9, 2018",
|
||||
"Subtitle": "Version of August 30, 2018",
|
||||
"Path": "/ref/spec"
|
||||
}-->
|
||||
|
||||
|
@ -2112,8 +2112,8 @@ with initializer expressions but no types:
|
|||
i, j := 0, 10
|
||||
f := func() int { return 7 }
|
||||
ch := make(chan int)
|
||||
r, w := os.Pipe(fd) // os.Pipe() returns two values
|
||||
_, y, _ := coord(p) // coord() returns three values; only interested in y coordinate
|
||||
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
|
||||
</pre>
|
||||
|
||||
<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>
|
||||
</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>
|
||||
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>
|
||||
<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>
|
||||
|
||||
</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 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>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>
|
||||
|
||||
<p>
|
||||
|
|
|
@ -38,7 +38,7 @@ security team directly:
|
|||
</p>
|
||||
|
||||
<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>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>
|
||||
|
|
|
@ -90,6 +90,8 @@ func Test22906(t *testing.T) { test22906(t) }
|
|||
func Test24206(t *testing.T) { test24206(t) }
|
||||
func Test25143(t *testing.T) { test25143(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 BenchmarkGoString(b *testing.B) { benchGoString(b) }
|
||||
|
|
|
@ -2,7 +2,16 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// 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
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !darwin !cgo internal
|
||||
// +build !darwin !cgo internal race
|
||||
|
||||
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
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file is here just to make the go tool happy. It allows
|
||||
// empty function declarations (no function body).
|
||||
// It is used with "go:linkname".
|
||||
package a
|
||||
|
||||
// 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
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !windows
|
||||
// +build !windows,!static
|
||||
|
||||
#include <stdint.h>
|
||||
#include <dlfcn.h>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !windows
|
||||
// +build !windows,!static
|
||||
|
||||
package cgotest
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build windows
|
||||
// +build windows static
|
||||
|
||||
package cgotest
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ func test9400(t *testing.T) {
|
|||
|
||||
// Grow the stack and put down a test pattern
|
||||
const pattern = 0x123456789abcdef
|
||||
var big [1024]uint64 // len must match assmebly
|
||||
var big [1024]uint64 // len must match assembly
|
||||
for i := range big {
|
||||
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"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strings"
|
||||
"syscall"
|
||||
"testing"
|
||||
|
@ -83,13 +84,17 @@ func init() {
|
|||
cc = append(cc, []string{"-framework", "CoreFoundation", "-framework", "Foundation"}...)
|
||||
}
|
||||
libgodir = GOOS + "_" + GOARCH
|
||||
switch GOOS {
|
||||
case "darwin":
|
||||
if GOARCH == "arm" || GOARCH == "arm64" {
|
||||
if runtime.Compiler == "gccgo" {
|
||||
libgodir = "gccgo_" + libgodir + "_fPIC"
|
||||
} else {
|
||||
switch GOOS {
|
||||
case "darwin":
|
||||
if GOARCH == "arm" || GOARCH == "arm64" {
|
||||
libgodir += "_shared"
|
||||
}
|
||||
case "dragonfly", "freebsd", "linux", "netbsd", "openbsd", "solaris":
|
||||
libgodir += "_shared"
|
||||
}
|
||||
case "dragonfly", "freebsd", "linux", "netbsd", "openbsd", "solaris":
|
||||
libgodir += "_shared"
|
||||
}
|
||||
cc = append(cc, "-I", filepath.Join("pkg", libgodir))
|
||||
|
||||
|
@ -155,6 +160,9 @@ func testInstall(t *testing.T, exe, libgoa, libgoh string, buildcmd ...string) {
|
|||
} else {
|
||||
ccArgs = append(ccArgs, "main_unix.c", libgoa)
|
||||
}
|
||||
if runtime.Compiler == "gccgo" {
|
||||
ccArgs = append(ccArgs, "-lgo")
|
||||
}
|
||||
t.Log(ccArgs)
|
||||
if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
|
||||
t.Logf("%s", out)
|
||||
|
@ -163,7 +171,11 @@ func testInstall(t *testing.T, exe, libgoa, libgoh string, buildcmd ...string) {
|
|||
defer os.Remove(exe)
|
||||
|
||||
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.Fatal(err)
|
||||
}
|
||||
|
@ -194,8 +206,13 @@ func checkLineComments(t *testing.T, hdrname string) {
|
|||
func TestInstall(t *testing.T) {
|
||||
defer os.RemoveAll("pkg")
|
||||
|
||||
libgoa := "libgo.a"
|
||||
if runtime.Compiler == "gccgo" {
|
||||
libgoa = "liblibgo.a"
|
||||
}
|
||||
|
||||
testInstall(t, "./testp1"+exeSuffix,
|
||||
filepath.Join("pkg", libgodir, "libgo.a"),
|
||||
filepath.Join("pkg", libgodir, libgoa),
|
||||
filepath.Join("pkg", libgodir, "libgo.h"),
|
||||
"go", "install", "-i", "-buildmode=c-archive", "libgo")
|
||||
|
||||
|
@ -235,6 +252,9 @@ func TestEarlySignalHandler(t *testing.T) {
|
|||
checkLineComments(t, "libgo2.h")
|
||||
|
||||
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 {
|
||||
t.Logf("%s", out)
|
||||
t.Fatal(err)
|
||||
|
@ -265,6 +285,9 @@ func TestSignalForwarding(t *testing.T) {
|
|||
checkLineComments(t, "libgo2.h")
|
||||
|
||||
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 {
|
||||
t.Logf("%s", out)
|
||||
t.Fatal(err)
|
||||
|
@ -306,6 +329,9 @@ func TestSignalForwardingExternal(t *testing.T) {
|
|||
checkLineComments(t, "libgo2.h")
|
||||
|
||||
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 {
|
||||
t.Logf("%s", out)
|
||||
t.Fatal(err)
|
||||
|
@ -419,6 +445,9 @@ func TestOsSignal(t *testing.T) {
|
|||
checkLineComments(t, "libgo3.h")
|
||||
|
||||
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 {
|
||||
t.Logf("%s", out)
|
||||
t.Fatal(err)
|
||||
|
@ -452,6 +481,9 @@ func TestSigaltstack(t *testing.T) {
|
|||
checkLineComments(t, "libgo4.h")
|
||||
|
||||
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 {
|
||||
t.Logf("%s", out)
|
||||
t.Fatal(err)
|
||||
|
@ -476,6 +508,9 @@ func TestExtar(t *testing.T) {
|
|||
case "windows":
|
||||
t.Skip("skipping signal test on Windows")
|
||||
}
|
||||
if runtime.Compiler == "gccgo" {
|
||||
t.Skip("skipping -extar test when using gccgo")
|
||||
}
|
||||
|
||||
defer func() {
|
||||
os.Remove("libgo4.a")
|
||||
|
@ -530,14 +565,26 @@ func TestPIE(t *testing.T) {
|
|||
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 {
|
||||
t.Logf("%s", out)
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
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.Fatal(err)
|
||||
}
|
||||
|
@ -605,6 +652,9 @@ func TestSIGPROF(t *testing.T) {
|
|||
checkLineComments(t, "libgo6.h")
|
||||
|
||||
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 {
|
||||
t.Logf("%s", out)
|
||||
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
|
||||
// if -no-pie is accepted. See #22126.
|
||||
ccArgs := append(cc, "-o", exe, "-no-pie", "main5.c", "libgo2.a")
|
||||
if runtime.Compiler == "gccgo" {
|
||||
ccArgs = append(ccArgs, "-lgo")
|
||||
}
|
||||
t.Log(ccArgs)
|
||||
out, err = exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput()
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <signal.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
struct sigaction sa;
|
||||
|
@ -30,7 +31,12 @@ int install_handler() {
|
|||
perror("sigaction");
|
||||
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");
|
||||
return 2;
|
||||
}
|
||||
|
|
|
@ -29,13 +29,13 @@ func ResetSIGIO() {
|
|||
signal.Reset(syscall.SIGIO)
|
||||
}
|
||||
|
||||
// SawSIGIO returns whether we saw a SIGIO within a brief pause.
|
||||
// SawSIGIO reports whether we saw a SIGIO.
|
||||
//export SawSIGIO
|
||||
func SawSIGIO() C.int {
|
||||
select {
|
||||
case <-sigioChan:
|
||||
return 1
|
||||
case <-time.After(100 * time.Millisecond):
|
||||
case <-time.After(5 * time.Second):
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
|
|
@ -201,6 +201,16 @@ func run(t *testing.T, env []string, args ...string) string {
|
|||
t.Helper()
|
||||
cmd := exec.Command(args[0], args[1:]...)
|
||||
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()
|
||||
if err != nil {
|
||||
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
|
||||
# import "C" into Go files with Go definitions of types defined in the
|
||||
# import "C" block. Add more tests here.
|
||||
FILE_PREFIXES="anonunion issue8478"
|
||||
FILE_PREFIXES="anonunion issue8478 fieldtypedef"
|
||||
|
||||
RM=
|
||||
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" 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
|
||||
|
||||
# Test that types and itabs get properly uniqified.
|
||||
|
|
|
@ -381,12 +381,13 @@ func (c *config) checkRuntime() (skip bool, err error) {
|
|||
return false, err
|
||||
}
|
||||
cmd.Args = append(cmd.Args, "-dM", "-E", "../../../src/runtime/cgo/libcgo.h")
|
||||
cmdStr := strings.Join(cmd.Args, " ")
|
||||
out, err := cmd.CombinedOutput()
|
||||
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")) {
|
||||
return true, fmt.Errorf("%#q did not define CGO_TSAN")
|
||||
return true, fmt.Errorf("%#q did not define CGO_TSAN", cmdStr)
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ func TestMSAN(t *testing.T) {
|
|||
{src: "msan3.go"},
|
||||
{src: "msan4.go"},
|
||||
{src: "msan5.go"},
|
||||
{src: "msan6.go"},
|
||||
{src: "msan_fail.go", wantErr: true},
|
||||
}
|
||||
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
|
||||
case 3: // ELF_NOTE_GODEPS_TAG
|
||||
if depsNoteFound {
|
||||
t.Error("multiple depedency list notes")
|
||||
t.Error("multiple dependency list notes")
|
||||
}
|
||||
testDepsNote(t, f, note)
|
||||
depsNoteFound = true
|
||||
|
@ -905,3 +905,9 @@ func TestGlobal(t *testing.T) {
|
|||
AssertIsLinkedTo(t, "./bin/global", soname)
|
||||
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
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//+build !gccgo
|
||||
// +build !gccgo
|
||||
|
||||
#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
|
||||
|
||||
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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -27,6 +27,8 @@ license that can be found in the LICENSE file.
|
|||
mod = result.module;
|
||||
inst = result.instance;
|
||||
document.getElementById("runButton").disabled = false;
|
||||
}).catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
async function run() {
|
||||
|
|
|
@ -27,11 +27,17 @@
|
|||
global.TextEncoder = util.TextEncoder;
|
||||
global.TextDecoder = util.TextDecoder;
|
||||
} 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 = "";
|
||||
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) {
|
||||
outputBuf += decoder.decode(buf);
|
||||
const nl = outputBuf.lastIndexOf("\n");
|
||||
|
@ -91,9 +97,11 @@
|
|||
}
|
||||
|
||||
const storeValue = (addr, v) => {
|
||||
const nanHead = 0x7FF80000;
|
||||
|
||||
if (typeof v === "number") {
|
||||
if (isNaN(v)) {
|
||||
mem().setUint32(addr + 4, 0x7FF80000, true); // NaN
|
||||
mem().setUint32(addr + 4, nanHead, true);
|
||||
mem().setUint32(addr, 0, true);
|
||||
return;
|
||||
}
|
||||
|
@ -101,51 +109,44 @@
|
|||
return;
|
||||
}
|
||||
|
||||
mem().setUint32(addr + 4, 0x7FF80000, true); // NaN
|
||||
|
||||
switch (v) {
|
||||
case undefined:
|
||||
mem().setUint32(addr + 4, nanHead, true);
|
||||
mem().setUint32(addr, 1, true);
|
||||
return;
|
||||
case null:
|
||||
mem().setUint32(addr + 4, nanHead, true);
|
||||
mem().setUint32(addr, 2, true);
|
||||
return;
|
||||
case true:
|
||||
mem().setUint32(addr + 4, nanHead, true);
|
||||
mem().setUint32(addr, 3, true);
|
||||
return;
|
||||
case false:
|
||||
mem().setUint32(addr + 4, nanHead, true);
|
||||
mem().setUint32(addr, 4, true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof v === "string") {
|
||||
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];
|
||||
let ref = this._refs.get(v);
|
||||
if (ref === undefined) {
|
||||
ref = this._values.length;
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -176,8 +177,12 @@
|
|||
go: {
|
||||
// func wasmExit(code int32)
|
||||
"runtime.wasmExit": (sp) => {
|
||||
const code = mem().getInt32(sp + 8, 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)
|
||||
|
@ -328,16 +333,10 @@
|
|||
false,
|
||||
global,
|
||||
this._inst.exports.mem,
|
||||
() => { // resolveCallbackPromise
|
||||
if (this.exited) {
|
||||
throw new Error("bad callback: Go program has already exited");
|
||||
}
|
||||
setTimeout(this._resolveCallbackPromise, 0); // make sure it is asynchronous
|
||||
},
|
||||
this,
|
||||
];
|
||||
this._stringRefs = new Map();
|
||||
this._symbolRefs = new Map();
|
||||
this._refProp = Symbol();
|
||||
this._refs = new Map();
|
||||
this._callbackShutdown = false;
|
||||
this.exited = false;
|
||||
|
||||
const mem = new DataView(this._inst.exports.mem.buffer)
|
||||
|
@ -374,7 +373,12 @@
|
|||
|
||||
while (true) {
|
||||
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);
|
||||
if (this.exited) {
|
||||
|
@ -383,6 +387,28 @@
|
|||
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) {
|
||||
|
@ -396,17 +422,16 @@
|
|||
go.env = process.env;
|
||||
go.exit = process.exit;
|
||||
WebAssembly.instantiate(fs.readFileSync(process.argv[2]), go.importObject).then((result) => {
|
||||
process.on("exit", () => { // Node.js exits if no callback is pending
|
||||
if (!go.exited) {
|
||||
console.error("error: all goroutines asleep and no JavaScript callback pending - deadlock!");
|
||||
process.exit(1);
|
||||
process.on("exit", (code) => { // Node.js exits if no callback is pending
|
||||
if (code === 0 && !go.exited) {
|
||||
// deadlock, make Go print error and stack traces
|
||||
go._callbackShutdown = true;
|
||||
go._inst.exports.run();
|
||||
}
|
||||
});
|
||||
return go.run(result.instance);
|
||||
}).catch((err) => {
|
||||
console.error(err);
|
||||
go.exited = true;
|
||||
process.exit(1);
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
})();
|
||||
|
|
|
@ -160,7 +160,7 @@ func (b *block) V7() *headerV7 { return (*headerV7)(b) }
|
|||
func (b *block) GNU() *headerGNU { return (*headerGNU)(b) }
|
||||
func (b *block) STAR() *headerSTAR { return (*headerSTAR)(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.
|
||||
// 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) AccessTime() []byte { return h[345:][: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] }
|
||||
|
||||
type headerSTAR [blockSize]byte
|
||||
|
@ -293,7 +293,7 @@ func (h *headerUSTAR) Prefix() []byte { return h[345:][:155] }
|
|||
|
||||
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) 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
|
||||
// have the given size in bytes.
|
||||
func NewReader(r io.ReaderAt, size int64) (*Reader, error) {
|
||||
if size < 0 {
|
||||
return nil, errors.New("zip: size cannot be negative")
|
||||
}
|
||||
zr := new(Reader)
|
||||
if err := zr.init(r, size); err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -658,6 +658,12 @@ func TestInvalidFiles(t *testing.T) {
|
|||
if 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) {
|
||||
|
|
|
@ -303,8 +303,8 @@ func (h *FileHeader) SetMode(mode os.FileMode) {
|
|||
}
|
||||
|
||||
// isZip64 reports whether the file size exceeds the 32 bit limit
|
||||
func (fh *FileHeader) isZip64() bool {
|
||||
return fh.CompressedSize64 >= uint32max || fh.UncompressedSize64 >= uint32max
|
||||
func (h *FileHeader) isZip64() bool {
|
||||
return h.CompressedSize64 >= uint32max || h.UncompressedSize64 >= uint32max
|
||||
}
|
||||
|
||||
func msdosModeToFileMode(m uint32) (mode os.FileMode) {
|
||||
|
|
|
@ -336,6 +336,12 @@ func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error) {
|
|||
fh.Method = Store
|
||||
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{}
|
||||
} else {
|
||||
fh.Flags |= 0x8 // we will write a data descriptor
|
||||
|
@ -419,7 +425,10 @@ func (w *Writer) compressor(method uint16) Compressor {
|
|||
|
||||
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")
|
||||
}
|
||||
|
||||
|
|
|
@ -306,21 +306,28 @@ func TestWriterDir(t *testing.T) {
|
|||
if err != nil {
|
||||
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 {
|
||||
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) {
|
||||
var buf bytes.Buffer
|
||||
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)
|
||||
}
|
||||
if err := w.Close(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
b := buf.Bytes()
|
||||
|
||||
var sig [4]byte
|
||||
|
|
|
@ -63,7 +63,7 @@ func NewReader(rd io.Reader) *Reader {
|
|||
}
|
||||
|
||||
// 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
|
||||
// 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.
|
||||
// ReadSlice returns err != nil if and only if line does not end in delim.
|
||||
func (b *Reader) ReadSlice(delim byte) (line []byte, err error) {
|
||||
s := 0 // search start index
|
||||
for {
|
||||
// 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]
|
||||
b.r += i + 1
|
||||
break
|
||||
|
@ -338,6 +340,8 @@ func (b *Reader) ReadSlice(delim byte) (line []byte, err error) {
|
|||
break
|
||||
}
|
||||
|
||||
s = b.w - b.r // do not rescan area we scanned before
|
||||
|
||||
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
|
||||
// initial contents. The new Buffer takes ownership of buf, and the
|
||||
// caller should not use buf after this call. NewBuffer is intended to
|
||||
// prepare a Buffer to read existing data. It can also be used to size
|
||||
// the internal buffer for writing. To do that, buf should have the
|
||||
// desired capacity but a length of zero.
|
||||
// prepare a Buffer to read existing data. It can also be used to set
|
||||
// the initial size of the internal buffer for writing. To do that,
|
||||
// buf should have the desired capacity but a length of zero.
|
||||
//
|
||||
// In most cases, new(Buffer) (or just declaring a Buffer variable) is
|
||||
// sufficient to initialize a Buffer.
|
||||
|
|
|
@ -293,7 +293,7 @@ func TestReadFromPanicReader(t *testing.T) {
|
|||
}
|
||||
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
|
||||
defer func() {
|
||||
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
|
||||
// upper case, giving priority to the special casing rules.
|
||||
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
|
||||
// lower case, giving priority to the special casing rules.
|
||||
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
|
||||
// title case, giving priority to the special casing rules.
|
||||
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.
|
||||
|
|
|
@ -6,6 +6,7 @@ package bytes_test
|
|||
|
||||
import (
|
||||
. "bytes"
|
||||
"internal/testenv"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
@ -58,10 +59,20 @@ func TestCompareIdenticalSlice(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)
|
||||
b := make([]byte, n+1)
|
||||
for len := 0; len < 128; len++ {
|
||||
for _, len := range lengths {
|
||||
// randomish but deterministic data. No 0 or 255.
|
||||
for i := 0; i < len; i++ {
|
||||
a[i] = byte(1 + 31*i%254)
|
||||
|
|
|
@ -39,6 +39,14 @@ func ExampleBuffer_Grow() {
|
|||
// 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() {
|
||||
// Interpret Compare's result by comparing it to zero.
|
||||
var a, b []byte
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package arch defines architecture-specific information and support functions.
|
||||
package arch
|
||||
|
||||
import (
|
||||
|
|
|
@ -74,11 +74,12 @@ func IsARM64STLXR(op obj.As) bool {
|
|||
arm64.ASTXRB, arm64.ASTXRH, arm64.ASTXRW, arm64.ASTXR,
|
||||
arm64.ASTXP, arm64.ASTXPW, arm64.ASTLXP, arm64.ASTLXPW,
|
||||
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.ALDANDB, arm64.ALDANDH, arm64.ALDANDW, arm64.ALDANDD,
|
||||
arm64.ALDEORB, arm64.ALDEORH, arm64.ALDEORW, arm64.ALDEORD,
|
||||
arm64.ALDORB, arm64.ALDORH, arm64.ALDORW, arm64.ALDORD,
|
||||
arm64.ALDADDALD, arm64.ALDADDALW:
|
||||
arm64.ALDADDALD, arm64.ALDADDALW, arm64.ALDADDALH, arm64.ALDADDALB:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
|
|
@ -137,7 +137,7 @@ func (p *Parser) asmText(operands [][]lex.Token) {
|
|||
// Bizarre syntax: $frameSize-argSize is two words, not subtraction.
|
||||
// Both frameSize and argSize must be simple integers; only frameSize
|
||||
// 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.
|
||||
op := operands[next]
|
||||
if len(op) < 2 || op[0].ScanToken != '$' {
|
||||
|
|
|
@ -33,7 +33,7 @@ func newParser(goarch string) *Parser {
|
|||
|
||||
// tryParse executes parse func in panicOnError=true context.
|
||||
// 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.
|
||||
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
|
||||
VMAXPD.BCST (AX), Z2, K1, Z1 // 62f1ed595f08
|
||||
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.Z Z3, Z2, K1, Z1 // 62f1edd95fcb or 62f1ed995fcb
|
||||
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), R14 // MOVB (R29)(R30*1), R14 // ae6bbe38
|
||||
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 ','
|
||||
// {
|
||||
|
@ -470,14 +485,14 @@ again:
|
|||
// {
|
||||
// outcode($1, &$2, NREG, &$4);
|
||||
// }
|
||||
FADDD $0.5, F1 // FADDD $(0.5), F1
|
||||
// FADDD $0.5, F1 // FADDD $(0.5), F1
|
||||
FADDD F1, F2
|
||||
|
||||
// LTYPEK frcon ',' freg ',' freg
|
||||
// {
|
||||
// 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
|
||||
|
||||
//
|
||||
|
@ -572,6 +587,14 @@ again:
|
|||
SWPH R5, (RSP), R7 // e7832578
|
||||
SWPB R5, (R6), R7 // c7802538
|
||||
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, (RSP), R7 // e70325f8
|
||||
LDADDW R5, (R6), R7 // c70025b8
|
||||
|
@ -605,7 +628,9 @@ again:
|
|||
LDORB R5, (R6), R7 // c7302538
|
||||
LDORB R5, (RSP), R7 // e7332538
|
||||
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
|
||||
//
|
||||
|
@ -716,6 +741,86 @@ again:
|
|||
STPW (R3, R4), x(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
|
||||
//
|
||||
// LTYPEE comma
|
||||
|
|
|
@ -89,4 +89,9 @@ TEXT errors(SB),$0
|
|||
CSEL LT, R1, R2 // ERROR "illegal combination"
|
||||
AND $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
|
||||
|
|
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, R2 // b9130021
|
||||
FLOGR R2, R2 // b9830022
|
||||
POPCNT R3, R4 // b9e10043
|
||||
|
||||
AND R1, R2 // b9800021
|
||||
AND R1, R2, R3 // b9e42031
|
||||
|
|
|
@ -95,7 +95,7 @@ func (f *File) ParseGo(name string, src []byte) {
|
|||
}
|
||||
}
|
||||
if !sawC {
|
||||
error_(token.NoPos, `cannot find import "C"`)
|
||||
error_(ast1.Package, `cannot find import "C"`)
|
||||
}
|
||||
|
||||
// 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 fortran compiler. Any .h, .hh, .hpp, or .hxx files will
|
||||
not be compiled separately, but, if these header files are changed,
|
||||
the C and C++ files will be recompiled. 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 package (including its non-Go source files) will be recompiled.
|
||||
Note that changes to files in other directories do not cause the package
|
||||
to be recompiled, so all non-Go source code for the package should be
|
||||
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
|
||||
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
|
||||
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
|
||||
|
||||
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)
|
||||
}
|
||||
p.loadDefines(f)
|
||||
needType := p.guessKinds(f)
|
||||
if len(needType) > 0 {
|
||||
p.loadDWARF(f, needType)
|
||||
p.typedefs = map[string]bool{}
|
||||
p.typedefList = nil
|
||||
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) {
|
||||
// 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)
|
||||
}
|
||||
types[i] = t.Type
|
||||
p.recordTypedefs(t.Type)
|
||||
}
|
||||
if e.Tag != dwarf.TagCompileUnit {
|
||||
r.SkipChildren()
|
||||
|
@ -586,7 +607,25 @@ func (p *Package) loadDWARF(f *File, names []*Name) {
|
|||
}
|
||||
}
|
||||
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])
|
||||
}
|
||||
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
|
||||
// from the original Go source files to the names
|
||||
// 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 {
|
||||
fmt.Fprintf(os.Stderr, "$ %s <<EOF\n", strings.Join(nargs, " "))
|
||||
os.Stderr.Write(stdin)
|
||||
|
@ -1659,6 +1742,7 @@ type typeConv struct {
|
|||
// Map from types to incomplete pointers to those types.
|
||||
ptrs map[dwarf.Type][]*Type
|
||||
// Keys of ptrs in insertion order (deterministic worklist)
|
||||
// ptrKeys contains exactly the keys in ptrs.
|
||||
ptrKeys []dwarf.Type
|
||||
|
||||
// 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 {
|
||||
dtype := c.ptrKeys[0]
|
||||
c.ptrKeys = c.ptrKeys[1:]
|
||||
ptrs := c.ptrs[dtype]
|
||||
delete(c.ptrs, dtype)
|
||||
|
||||
// Note Type might invalidate c.ptrs[dtype].
|
||||
t := c.Type(dtype, pos)
|
||||
for _, ptr := range c.ptrs[dtype] {
|
||||
for _, ptr := range ptrs {
|
||||
ptr.Go.(*ast.StarExpr).X = t.Go
|
||||
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.Go = c.uintptr
|
||||
sub = &s
|
||||
// Make sure we update any previously computed type.
|
||||
if oldType := typedef[name.Name]; oldType != nil {
|
||||
oldType.Go = sub.Go
|
||||
}
|
||||
}
|
||||
t.Go = name
|
||||
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.
|
||||
// It will be a uintptr instead of *X.
|
||||
if c.badPointerTypedef(dt) {
|
||||
if c.baseBadPointerTypedef(dt) {
|
||||
break
|
||||
}
|
||||
|
||||
|
@ -2598,6 +2687,19 @@ func (c *typeConv) badPointerTypedef(dt *dwarf.TypedefType) bool {
|
|||
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 {
|
||||
// The real bad types are CFNumberRef and CFDateRef.
|
||||
// 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:
|
||||
// struct _jobject;
|
||||
// typedef struct _jobject *jobject;
|
||||
// Check that the typedef is either:
|
||||
// 1:
|
||||
// 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 str, ok := ptr.Type.(*dwarf.StructType); ok {
|
||||
if str.StructName == "_jobject" && str.Kind == "struct" && len(str.Field) == 0 && str.Incomplete {
|
||||
return true
|
||||
switch v := ptr.Type.(type) {
|
||||
case *dwarf.VoidType:
|
||||
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
|
||||
ExpFunc []*ExpFunc // accumulated ExpFunc from Files
|
||||
Decl []ast.Decl
|
||||
GoFiles []string // list of Go files
|
||||
GccFiles []string // list of gcc output files
|
||||
Preamble string // collected preamble for _cgo_export.h
|
||||
GoFiles []string // list of Go files
|
||||
GccFiles []string // list of gcc output files
|
||||
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.
|
||||
|
@ -261,6 +263,9 @@ func main() {
|
|||
if arg == "-fsanitize=thread" {
|
||||
tsanProlog = yesTsanProlog
|
||||
}
|
||||
if arg == "-fsanitize=memory" {
|
||||
msanProlog = yesMsanProlog
|
||||
}
|
||||
}
|
||||
|
||||
p := newPackage(args[:i])
|
||||
|
@ -394,6 +399,14 @@ func (p *Package) Record(f *File) {
|
|||
for k, v := range f.Name {
|
||||
if p.Name[k] == nil {
|
||||
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) {
|
||||
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...)
|
||||
}
|
||||
|
||||
// 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()
|
||||
if err != nil {
|
||||
fatalf("cannot load imported symbols from ELF file %s: %v", obj, err)
|
||||
}
|
||||
sym, _ := f.ImportedSymbols()
|
||||
for _, s := range sym {
|
||||
targ := s.Name
|
||||
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)
|
||||
}
|
||||
lib, err := f.ImportedLibraries()
|
||||
if err != nil {
|
||||
fatalf("cannot load imported libraries from ELF file %s: %v", obj, err)
|
||||
}
|
||||
lib, _ := f.ImportedLibraries()
|
||||
for _, l := range lib {
|
||||
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 {
|
||||
sym, err := f.ImportedSymbols()
|
||||
if err != nil {
|
||||
fatalf("cannot load imported symbols from Mach-O file %s: %v", obj, err)
|
||||
}
|
||||
sym, _ := f.ImportedSymbols()
|
||||
for _, s := range sym {
|
||||
if len(s) > 0 && s[0] == '_' {
|
||||
s = s[1:]
|
||||
}
|
||||
fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", s, s, "")
|
||||
}
|
||||
lib, err := f.ImportedLibraries()
|
||||
if err != nil {
|
||||
fatalf("cannot load imported libraries from Mach-O file %s: %v", obj, err)
|
||||
}
|
||||
lib, _ := f.ImportedLibraries()
|
||||
for _, l := range lib {
|
||||
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 {
|
||||
sym, err := f.ImportedSymbols()
|
||||
if err != nil {
|
||||
fatalf("cannot load imported symbols from PE file %s: %v", obj, err)
|
||||
}
|
||||
sym, _ := f.ImportedSymbols()
|
||||
for _, s := range sym {
|
||||
ss := strings.Split(s, ":")
|
||||
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.
|
||||
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())
|
||||
|
||||
// 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", gccProlog)
|
||||
fmt.Fprintf(fgcc, "%s\n", tsanProlog)
|
||||
fmt.Fprintf(fgcc, "%s\n", msanProlog)
|
||||
|
||||
for _, key := range nameKeys(f.Name) {
|
||||
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")
|
||||
// Save the return value.
|
||||
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 {
|
||||
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 char* _cgo_topofstack(void);")
|
||||
fmt.Fprintf(fgcc, "%s\n", tsanProlog)
|
||||
fmt.Fprintf(fgcc, "%s\n", msanProlog)
|
||||
|
||||
for _, exp := range p.ExpFunc {
|
||||
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", tsanProlog)
|
||||
fmt.Fprintf(fgcc, "%s\n", msanProlog)
|
||||
|
||||
for _, exp := range p.ExpFunc {
|
||||
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.
|
||||
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 = `
|
||||
#line 1 "cgo-builtin-prolog"
|
||||
#include <stddef.h> /* for ptrdiff_t and size_t below */
|
||||
|
@ -1415,7 +1432,7 @@ void *CBytes(_GoBytes_);
|
|||
void *_CMalloc(size_t);
|
||||
|
||||
__attribute__ ((unused))
|
||||
static size_t _GoStringLen(_GoString_ s) { return s.n; }
|
||||
static size_t _GoStringLen(_GoString_ s) { return (size_t)s.n; }
|
||||
|
||||
__attribute__ ((unused))
|
||||
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
|
||||
p.Stdout = &bout
|
||||
p.Stderr = &berr
|
||||
// Disable escape codes in clang error messages.
|
||||
p.Env = append(os.Environ(), "TERM=dumb")
|
||||
err := p.Run()
|
||||
if _, ok := err.(*exec.ExitError); err != nil && !ok {
|
||||
fatalf("%s", err)
|
||||
|
@ -97,6 +99,8 @@ func error_(pos token.Pos, msg string, args ...interface{}) {
|
|||
nerrors++
|
||||
if pos.IsValid() {
|
||||
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, "\n")
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
<!---
|
||||
// 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.
|
||||
-->
|
||||
|
||||
## 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`.
|
||||
|
||||
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
|
||||
|
||||
|
@ -113,4 +115,4 @@ and debugging information.
|
|||
### Further reading
|
||||
|
||||
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) {
|
||||
if testing.Short() {
|
||||
t.Skip("Skipping in short mode")
|
||||
}
|
||||
testenv.MustHaveGoBuild(t) // more restrictive than necessary, but that's ok
|
||||
|
||||
// process all directories
|
||||
|
@ -721,6 +724,7 @@ var knownFormats = map[string]string{
|
|||
"uint16 %d": "",
|
||||
"uint16 %v": "",
|
||||
"uint16 %x": "",
|
||||
"uint32 %#x": "",
|
||||
"uint32 %d": "",
|
||||
"uint32 %v": "",
|
||||
"uint32 %x": "",
|
||||
|
|
|
@ -524,6 +524,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
|||
case ssa.OpAMD64LEAQ1, ssa.OpAMD64LEAQ2, ssa.OpAMD64LEAQ4, ssa.OpAMD64LEAQ8,
|
||||
ssa.OpAMD64LEAL1, ssa.OpAMD64LEAL2, ssa.OpAMD64LEAL4, ssa.OpAMD64LEAL8,
|
||||
ssa.OpAMD64LEAW1, ssa.OpAMD64LEAW2, ssa.OpAMD64LEAW4, ssa.OpAMD64LEAW8:
|
||||
o := v.Reg()
|
||||
r := v.Args[0].Reg()
|
||||
i := v.Args[1].Reg()
|
||||
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.Reg = r
|
||||
p.From.Index = i
|
||||
gc.AddAux(&p.From, v)
|
||||
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:
|
||||
p := s.Prog(v.Op.Asm())
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
|
@ -683,7 +699,9 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
|||
gc.AddAux(&p.From, v)
|
||||
p.To.Type = obj.TYPE_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.From.Type = obj.TYPE_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()
|
||||
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:
|
||||
p := s.Prog(v.Op.Asm())
|
||||
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,
|
||||
ssa.OpAMD64ANDQload, ssa.OpAMD64ANDLload, ssa.OpAMD64ORQload, ssa.OpAMD64ORLload,
|
||||
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.From.Type = obj.TYPE_MEM
|
||||
p.From.Reg = v.Args[1].Reg()
|
||||
|
|
|
@ -14,10 +14,10 @@ import (
|
|||
var darwin = objabi.GOOS == "darwin"
|
||||
|
||||
func padframe(frame int64) int64 {
|
||||
// arm64 requires that the frame size (not counting saved LR)
|
||||
// be empty or be 8 mod 16. If not, pad it.
|
||||
if frame != 0 && frame%16 != 8 {
|
||||
frame += 8
|
||||
// arm64 requires that the frame size (not counting saved FP&LR)
|
||||
// be 16 bytes aligned. If not, pad it.
|
||||
if frame%16 != 0 {
|
||||
frame += 16 - (frame % 16)
|
||||
}
|
||||
return frame
|
||||
}
|
||||
|
|
|
@ -212,7 +212,11 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
|||
ssa.OpARM64FMSUBS,
|
||||
ssa.OpARM64FMSUBD,
|
||||
ssa.OpARM64FNMSUBS,
|
||||
ssa.OpARM64FNMSUBD:
|
||||
ssa.OpARM64FNMSUBD,
|
||||
ssa.OpARM64MADD,
|
||||
ssa.OpARM64MADDW,
|
||||
ssa.OpARM64MSUB,
|
||||
ssa.OpARM64MSUBW:
|
||||
rt := v.Reg()
|
||||
ra := v.Args[0].Reg()
|
||||
rm := v.Args[1].Reg()
|
||||
|
@ -369,6 +373,8 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
|||
ssa.OpARM64MOVWloadidx,
|
||||
ssa.OpARM64MOVWUloadidx,
|
||||
ssa.OpARM64MOVDloadidx,
|
||||
ssa.OpARM64FMOVSloadidx,
|
||||
ssa.OpARM64FMOVDloadidx,
|
||||
ssa.OpARM64MOVHloadidx2,
|
||||
ssa.OpARM64MOVHUloadidx2,
|
||||
ssa.OpARM64MOVWloadidx4,
|
||||
|
@ -404,6 +410,8 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
|||
ssa.OpARM64MOVHstoreidx,
|
||||
ssa.OpARM64MOVWstoreidx,
|
||||
ssa.OpARM64MOVDstoreidx,
|
||||
ssa.OpARM64FMOVSstoreidx,
|
||||
ssa.OpARM64FMOVDstoreidx,
|
||||
ssa.OpARM64MOVHstoreidx2,
|
||||
ssa.OpARM64MOVWstoreidx4,
|
||||
ssa.OpARM64MOVDstoreidx8:
|
||||
|
|
|
@ -464,19 +464,22 @@ func (p *exporter) markType(t *types.Type) {
|
|||
}
|
||||
|
||||
// Recursively mark any types that can be produced given a
|
||||
// value of type t: dereferencing a pointer; indexing an
|
||||
// array, slice, or map; receiving from a channel; accessing a
|
||||
// struct field or interface method; or calling a function.
|
||||
// value of type t: dereferencing a pointer; indexing or
|
||||
// iterating over an array, slice, or map; receiving from a
|
||||
// channel; accessing a struct field or interface method; or
|
||||
// calling a function.
|
||||
//
|
||||
// Notably, we don't mark map key or function parameter types,
|
||||
// because the user already needs some way to construct values
|
||||
// of 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.
|
||||
// Notably, we don't mark function parameter types, because
|
||||
// the user already needs some way to construct values of
|
||||
// those types.
|
||||
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())
|
||||
|
||||
case TSTRUCT:
|
||||
|
|
|
@ -227,17 +227,6 @@ type bvecSet struct {
|
|||
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() {
|
||||
// Allocate new index.
|
||||
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()...))
|
||||
|
||||
// Force type conversion from *struct to the func type.
|
||||
clos = nod(OCONVNOP, clos, nil)
|
||||
clos.Type = clo.Type
|
||||
|
||||
clos = typecheck(clos, Erv)
|
||||
clos = convnop(clos, clo.Type)
|
||||
|
||||
// typecheck will insert a PTRLIT node under CONVNOP,
|
||||
// tag it with escape analysis result.
|
||||
|
@ -511,10 +508,7 @@ func walkpartialcall(n *Node, init *Nodes) *Node {
|
|||
clos.List.Append(n.Left)
|
||||
|
||||
// Force type conversion from *struct to the func type.
|
||||
clos = nod(OCONVNOP, clos, nil)
|
||||
clos.Type = n.Type
|
||||
|
||||
clos = typecheck(clos, Erv)
|
||||
clos = convnop(clos, n.Type)
|
||||
|
||||
// typecheck will insert a PTRLIT node under CONVNOP,
|
||||
// tag it with escape analysis result.
|
||||
|
|
|
@ -121,6 +121,17 @@ func (n *Node) Int64() 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.
|
||||
// n must be a boolean constant.
|
||||
func (n *Node) Bool() bool {
|
||||
|
@ -766,7 +777,7 @@ func evconst(n *Node) {
|
|||
v.U.(*Mpint).Neg()
|
||||
|
||||
case OCOM_ | CTINT_:
|
||||
var et types.EType = Txxx
|
||||
et := Txxx
|
||||
if nl.Type != nil {
|
||||
et = nl.Type.Etype
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ import (
|
|||
"cmd/internal/dwarf"
|
||||
"cmd/internal/obj"
|
||||
"cmd/internal/src"
|
||||
"sort"
|
||||
"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
|
||||
// index accordingly.
|
||||
for ii, sl := range vmap {
|
||||
sort.Sort(byClassThenName(sl))
|
||||
var m map[varPos]int
|
||||
if ii == 0 {
|
||||
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
|
||||
// lowering, or unnamed params ("_").
|
||||
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]
|
||||
}
|
||||
|
||||
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) {
|
||||
for i := 0; i < ilevel; i++ {
|
||||
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
|
||||
// addrescapes, mark parameters unsafe
|
||||
escapes := make([]uint16, len(e.dsts))
|
||||
|
@ -551,7 +549,6 @@ func escAnalyze(all []*Node, recursive bool) {
|
|||
}
|
||||
|
||||
func (e *EscState) escfunc(fn *Node) {
|
||||
// print("escfunc %N %s\n", fn.Func.Nname, e.recursive?"(recursive)":"");
|
||||
if fn.Esc != EscFuncPlanned {
|
||||
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
|
||||
// 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)
|
||||
|
||||
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) {
|
||||
if n == nil {
|
||||
return
|
||||
|
@ -756,10 +803,6 @@ opSwitch:
|
|||
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
|
||||
|
||||
case ORANGE:
|
||||
|
@ -822,13 +865,30 @@ opSwitch:
|
|||
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))
|
||||
|
||||
case OAS2: // x,y = a,b
|
||||
if n.List.Len() == n.Rlist.Len() {
|
||||
rs := n.Rlist.Slice()
|
||||
where := n
|
||||
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
|
||||
case OAS2FUNC: // x,y = f()
|
||||
rs := e.nodeEscState(n.Rlist.First()).Retval.Slice()
|
||||
where := n
|
||||
for i, n := range n.List.Slice() {
|
||||
if i >= len(rs) {
|
||||
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) {
|
||||
Fatalf("esc oas2func")
|
||||
|
@ -1561,12 +1622,11 @@ func (e *EscState) esccall(call *Node, parent *Node) {
|
|||
cE := e.nodeEscState(call)
|
||||
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 {
|
||||
// function in same mutually recursive group. Incorporate into flow graph.
|
||||
if Debug['m'] > 3 {
|
||||
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 {
|
||||
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.
|
||||
e.initEscRetval(call, fntype)
|
||||
|
||||
// print("esc analyzed fn: %#N (%+T) returning (%+H)\n", fn, fntype, e.nodeEscState(call).Retval);
|
||||
|
||||
// Receiver.
|
||||
if call.Op != OCALLFUNC {
|
||||
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())
|
||||
if n == nil {
|
||||
// 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.
|
||||
// ipkg is the package being imported
|
||||
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 {
|
||||
t := types.New(TFORW)
|
||||
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.
|
||||
// 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 {
|
||||
n := importsym(ipkg, pos, s, op)
|
||||
n := importsym(ipkg, s, op)
|
||||
if n.Op != ONONAME {
|
||||
if n.Op == op && (n.Class() != ctxt || !eqtype(n.Type, t)) {
|
||||
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
|
||||
|
||||
func BenchmarkMul2(b *testing.B) {
|
||||
|
|
|
@ -7,6 +7,7 @@ package gc
|
|||
import (
|
||||
"cmd/compile/internal/types"
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
|
@ -1836,6 +1837,10 @@ func dumplist(s string, l Nodes) {
|
|||
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) {
|
||||
fmt.Printf("%s [%p]%+v\n", s, n, n)
|
||||
}
|
||||
|
|
|
@ -281,7 +281,7 @@ var (
|
|||
assertE2I2,
|
||||
assertI2I,
|
||||
assertI2I2,
|
||||
Deferproc,
|
||||
deferproc,
|
||||
Deferreturn,
|
||||
Duffcopy,
|
||||
Duffzero,
|
||||
|
@ -290,7 +290,7 @@ var (
|
|||
growslice,
|
||||
msanread,
|
||||
msanwrite,
|
||||
Newproc,
|
||||
newproc,
|
||||
panicdivide,
|
||||
panicdottypeE,
|
||||
panicdottypeI,
|
||||
|
|
|
@ -595,7 +595,7 @@ func (p *iexporter) typOff(t *types.Type) uint64 {
|
|||
if !ok {
|
||||
w := p.newWriter()
|
||||
w.doTyp(t)
|
||||
off = predeclReserved + uint64(w.flush())
|
||||
off = predeclReserved + w.flush()
|
||||
p.typIndex[t] = off
|
||||
}
|
||||
return off
|
||||
|
@ -952,6 +952,16 @@ func (w *exportWriter) funcExt(n *Node) {
|
|||
if n.Func.ExportInline() {
|
||||
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 {
|
||||
w.uint64(0)
|
||||
}
|
||||
|
|
|
@ -296,8 +296,23 @@ func (r *importReader) doDecl(n *Node) {
|
|||
// declaration before recursing.
|
||||
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()
|
||||
copytype(typenod(t), underlying)
|
||||
if !deferring {
|
||||
resumecheckwidth()
|
||||
}
|
||||
|
||||
if underlying.IsInterface() {
|
||||
break
|
||||
|
@ -576,6 +591,10 @@ func (r *importReader) typ1() *types.Type {
|
|||
t := types.New(TINTER)
|
||||
t.SetPkg(r.currPkg)
|
||||
t.SetInterface(append(embeddeds, methods...))
|
||||
|
||||
// Ensure we expand the interface in the frontend (#25055).
|
||||
checkwidth(t)
|
||||
|
||||
return t
|
||||
}
|
||||
}
|
||||
|
@ -660,6 +679,7 @@ func (r *importReader) funcExt(n *Node) {
|
|||
n.Func.Inl = &Inline{
|
||||
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…
Reference in a new issue