diff --git a/doc/go1.16.html b/doc/go1.16.html
index 6e371b9617..504165f3ea 100644
--- a/doc/go1.16.html
+++ b/doc/go1.16.html
@@ -26,12 +26,12 @@ Do not send CLs removing the interior tags from such phrases.
Changes to the language
- TODO
+ There are no changes to the language.
Ports
-Darwin
+Darwin and iOS
Go 1.16 adds support of 64-bit ARM architecture on macOS (also known as
@@ -43,15 +43,24 @@ Do not send CLs removing the interior tags from such phrases.
- The iOS port, which was previously darwin/arm64
, is now
- moved to ios/arm64
. GOOS=ios
implies the
+ The iOS port, which was previously darwin/arm64
, has
+ been renamed to ios/arm64
. GOOS=ios
+ implies the
darwin
build tag, just as GOOS=android
- implies the linux
build tag.
+ implies the linux
build tag. This change should be
+ transparent to anyone using gomobile to build iOS apps.
- The ios/amd64
port is added, targetting the iOS simulator
- running on AMD64-based macOS.
+ Go 1.16 adds an ios/amd64
port, which targets the iOS
+ simulator running on AMD64-based macOS. Previously this was
+ unofficially supported through darwin/amd64
with
+ the ios
build tag set.
+
+
+
+ Go 1.16 is the last release that will run on macOS 10.12 Sierra.
+ Go 1.17 will require macOS 10.13 High Sierra or later.
NetBSD
@@ -61,6 +70,14 @@ Do not send CLs removing the interior tags from such phrases.
netbsd/arm64
port).
+OpenBSD
+
+
+ Go now supports the MIPS64 architecture on OpenBSD
+ (the openbsd/mips64
port). This port does not yet
+ support cgo.
+
+
386
@@ -72,6 +89,14 @@ Do not send CLs removing the interior tags from such phrases.
with GO386=softfloat
.
+RISC-V
+
+
+ The linux/riscv64
port now supports cgo and
+ -buildmode=pie
. This release also includes performance
+ optimizations and code generation improvements for RISC-V.
+
+
@@ -80,17 +105,16 @@ Do not send CLs removing the interior tags from such phrases.
Go command
-
- TODO
-
-
-
-
-
-
-
Modules
+
+ Module-aware mode is enabled by default, regardless of whether a
+ go.mod
file is present in the current working directory or a
+ parent directory. More precisely, the GO111MODULE
environment
+ variable now defaults to on
. To switch to the previous behavior,
+ set GO111MODULE
to auto
.
+
+
Build commands like go
build
and go
test
no longer modify go.mod
and go.sum
@@ -107,9 +131,7 @@ Do not send CLs removing the interior tags from such phrases.
install
to build and install packages in module-aware mode,
ignoring the go.mod
file in the current directory or any parent
directory, if there is one. This is useful for installing executables without
- affecting the dependencies of the main module.
- TODO: write and link to section in golang.org/ref/mod
- TODO: write and link to blog post
+ affecting the dependencies of the main module.
@@ -127,8 +149,6 @@ Do not send CLs removing the interior tags from such phrases.
to indicate that certain published versions of the module should not be used
by other modules. A module author may retract a version after a severe problem
is discovered or if the version was published unintentionally.
- TODO: write and link to section in golang.org/ref/mod
- TODO: write and link to tutorial or blog post
@@ -138,6 +158,25 @@ Do not send CLs removing the interior tags from such phrases.
resolving missing packages.
+
+ The go
command now ignores requirements on module versions
+ excluded by exclude
directives in the main module. Previously,
+ the go
command used the next version higher than an excluded
+ version, but that version could change over time, resulting in
+ non-reproducible builds.
+
+
+Embedding Files
+
+
+ The go
command now supports including
+ static files and file trees as part of the final executable,
+ using the new //go:embed
directive.
+ See the documentation for the new
+ embed
+ package for details.
+
+
go
test
@@ -150,19 +189,26 @@ Do not send CLs removing the interior tags from such phrases.
that is still considered to be a passing test.
+
+ go
test
reports an error when the -c
+ or -i
flags are used together with unknown flags. Normally,
+ unknown flags are passed to tests, but when -c
or -i
+ are used, tests are not run.
+
+
+go
get
+
The go
get
-insecure
flag is
deprecated and will be removed in a future version. This flag permits
fetching from repositories and resolving custom domains using insecure
- schemes such as HTTP, and also bypassess module sum validation using the
+ schemes such as HTTP, and also bypasses module sum validation using the
checksum database. To permit the use of insecure schemes, use the
GOINSECURE
environment variable instead. To bypass module
sum validation, use GOPRIVATE
or GONOSUMDB
.
See go
help
environment
for details.
-go
get
-
go
get
example.com/mod@patch
now
requires that some version of example.com/mod
already be
@@ -171,6 +217,21 @@ Do not send CLs removing the interior tags from such phrases.
to patch even newly-added dependencies.)
+GOVCS
environment variable
+
+
+ GOVCS
is a new environment variable that limits which version
+ control tools the go
command may use to download source code.
+ This mitigates security issues with tools that are typically used in trusted,
+ authenticated environments. By default, git
and hg
+ may be used to download code from any repository. svn
,
+ bzr
, and fossil
may only be used to download code
+ from repositories with module paths or package paths matching patterns in
+ the GOPRIVATE
environment variable. See
+ go
+ help
vcs
for details.
+
+
The all
pattern
@@ -232,10 +293,41 @@ Do not send CLs removing the interior tags from such phrases.
+
+ The vet tool now warns about amd64 assembly that clobbers the BP
+ register (the frame pointer) without saving and restoring it,
+ contrary to the calling convention. Code that doesn't preserve the
+ BP register must be modified to either not use BP at all or preserve
+ BP by saving and restoring it. An easy way to preserve BP is to set
+ the frame size to a nonzero value, which causes the generated
+ prologue and epilogue to preserve the BP register for you.
+ See CL 248260 for example
+ fixes.
+
+
Runtime
- TODO
+ The new runtime/metrics
package
+ introduces a stable interface for reading
+ implementation-defined metrics from the Go runtime.
+ It supersedes existing functions like
+ runtime.ReadMemStats
+ and
+ debug.GCStats
+ and is significantly more general and efficient.
+ See the package documentation for more details.
+
+
+
+ Setting the GODEBUG
environment variable
+ to inittrace=1
now causes the runtime to emit a single
+ line to standard error for each package init
,
+ summarizing its execution time and memory allocation. This trace can
+ be used to find bottlenecks or regressions in Go startup
+ performance.
+ The GODEBUG
<
+ documentation describes the format.
@@ -250,10 +342,21 @@ Do not send CLs removing the interior tags from such phrases.
variable.
+
+ Go 1.16 fixes a discrepancy between the race detector and
+ the Go memory model . The race detector now
+ more precisely follows the channel synchronization rules of the
+ memory model. As a result, the detector may now report races it
+ previously missed.
+
+
Compiler
-
- TODO
+
+ The compiler can now inline functions with
+ non-labeled for
loops, method values, and type
+ switches. The inliner can also detect more indirect calls where
+ inlining is possible.
Linker
@@ -272,13 +375,10 @@ Do not send CLs removing the interior tags from such phrases.
supported architecture/OS combinations (the 1.15 performance improvements
were primarily focused on ELF
-based OSes and
amd64
architectures). For a representative set of
- large Go programs, linking is 20-35% faster than 1.15 and requires
+ large Go programs, linking is 20-25% faster than 1.15 and requires
5-15% less memory on average for linux/amd64
, with larger
- improvements for other architectures and OSes.
-
-
-
- TODO: update with final numbers later in the release.
+ improvements for other architectures and OSes. Most binaries are
+ also smaller as a result of more aggressive symbol pruning.
@@ -288,9 +388,54 @@ Do not send CLs removing the interior tags from such phrases.
Core library
+Embedded Files
+
- TODO: mention significant additions like new packages (io/fs
),
- new proposal-scoped features (//go:embed
), and so on
+ The new embed
package
+ provides access to files embedded in the program during compilation
+ using the new //go:embed
directive .
+
+
+File Systems
+
+
+ The new io/fs
package
+ defines an abstraction for read-only trees of files,
+ the fs.FS
interface,
+ and the standard library packages have
+ been adapted to make use of the interface as appropriate.
+
+
+
+ On the producer side of the interface,
+ the new embed.FS type
+ implements fs.FS
, as does
+ zip.Reader
.
+ The new os.DirFS
function
+ provides an implementation of fs.FS
backed by a tree
+ of operating system files.
+
+
+
+ On the consumer side,
+ the new http.FS
+ function converts an fs.FS
to an
+ http.Handler
.
+ Also, the html/template
+ and text/template
+ packages’ ParseFS
+ functions and methods read templates from an fs.FS
.
+
+
+
+ For testing code that implements fs.FS
,
+ the new testing/fstest
+ package provides a TestFS
+ function that checks for and reports common mistakes.
+ It also provides a simple in-memory file system implementation,
+ MapFS
,
+ which can be useful for testing code that accepts fs.FS
+ implementations.
@@ -322,9 +467,10 @@ Do not send CLs removing the interior tags from such phrases.
crypto/hmac
- New will now panic if separate calls to
- the hash generation function fail to return new values. Previously, the
- behavior was undefined and invalid outputs were sometimes generated.
+ New
will now panic if
+ separate calls to the hash generation function fail to return new values.
+ Previously, the behavior was undefined and invalid outputs were sometimes
+ generated.
@@ -332,81 +478,83 @@ Do not send CLs removing the interior tags from such phrases.
crypto/tls
- I/O operations on closing or closed TLS connections can now be detected using
- the new ErrClosed error. A typical use
- would be errors.Is(err, net.ErrClosed)
. In earlier releases
- the only way to reliably detect this case was to match the string returned
- by the Error
method with "tls: use of closed connection"
.
+ I/O operations on closing or closed TLS connections can now be detected
+ using the new net.ErrClosed
+ error. A typical use would be errors.Is(err, net.ErrClosed)
.
- A default deadline is set in Close
- before sending the close notify alert, in order to prevent blocking
+ A default write deadline is now set in
+ Conn.Close
+ before sending the "close notify" alert, in order to prevent blocking
indefinitely.
- (*Conn).HandshakeContext was added to
- allow the user to control cancellation of an in-progress TLS Handshake.
- The context provided is propagated into the
- ClientHelloInfo
- and CertificateRequestInfo
- structs and accessible through the new
- (*ClientHelloInfo).Context
- and
-
- (*CertificateRequestInfo).Context
- methods respectively. Canceling the context after the handshake has finished
- has no effect.
+ The new Conn.HandshakeContext
+ method allows cancellation of an in-progress handshake. The provided
+ context is accessible through the new
+ ClientHelloInfo.Context
+ and
+ CertificateRequestInfo.Context
methods. Canceling the
+ context after the handshake has finished has no effect.
- Clients now ensure that the server selects
+ Clients now return a handshake error if the server selects
- an ALPN protocol from
+ an ALPN protocol that was not in
the list advertised by the client .
- TLS servers will now prefer other AEAD cipher suites (such as ChaCha20Poly1305)
+ Servers will now prefer other available AEAD cipher suites (such as ChaCha20Poly1305)
over AES-GCM cipher suites if either the client or server doesn't have AES hardware
- support, unless the application set both
- Config.PreferServerCipherSuites
+ support, unless both
+ Config.PreferServerCipherSuites
and Config.CipherSuites
- or there are no other AEAD cipher suites supported.
- The client is assumed not to have AES hardware support if it does not signal a
- preference for AES-GCM cipher suites.
+ are set. The client is assumed not to have AES hardware support if it does
+ not signal a preference for AES-GCM cipher suites.
- TODO: https://golang.org/cl/246637 : make config.Clone return nil if the source is nil
+ Config.Clone
now
+ returns nil if the receiver is nil, rather than panicking.
crypto/x509
+
+ The GODEBUG=x509ignoreCN=0
flag will be removed in Go 1.17.
+ It enables the legacy behavior of treating the CommonName
+ field on X.509 certificates as a host name when no Subject Alternative
+ Names are present.
+
+
- ParseCertificate and
- CreateCertificate both
- now enforce string encoding restrictions for the fields DNSNames
,
- EmailAddresses
, and URIs
. These fields can only
- contain strings with characters within the ASCII range.
+ ParseCertificate
and
+ CreateCertificate
+ now enforce string encoding restrictions for the DNSNames
,
+ EmailAddresses
, and URIs
fields. These fields
+ can only contain strings with characters within the ASCII range.
- CreateCertificate now
- verifies the generated certificate's signature using the signer's
- public key. If the signature is invalid, an error is returned, instead
- of a malformed certificate.
+ CreateCertificate
+ now verifies the generated certificate's signature using the signer's
+ public key. If the signature is invalid, an error is returned, instead of
+ a malformed certificate.
A number of additional fields have been added to the
- CertificateRequest type.
- These fields are now parsed in ParseCertificateRequest
- and marshalled in CreateCertificateRequest .
+ CertificateRequest
type.
+ These fields are now parsed in
+ ParseCertificateRequest
and marshalled in
+ CreateCertificateRequest
.
@@ -416,25 +564,39 @@ Do not send CLs removing the interior tags from such phrases.
- TODO: https://golang.org/cl/257257 : return additional chains from Verify on Windows
+ On Windows, Certificate.Verify
+ will now return all certificate chains that are built by the platform
+ certificate verifier, instead of just the highest ranked chain.
- TODO: https://golang.org/cl/262343 : add Unwrap to SystemRootsError
+ The new SystemRootsError.Unwrap
+ method allows accessing the Err
+ field through the errors
package functions.
+encoding/asn1
+
+
+ Unmarshal
and
+ UnmarshalWithParams
+ now return an error instead of panicking when the argument is not
+ a pointer or is nil. This change matches the behavior of other
+ encoding packages such as encoding/json
.
+
+
+
+
encoding/json
-
- The error message for
- SyntaxError
- now begins with "json: ", matching the other errors in the package.
-
-
- TODO: https://golang.org/cl/234818 : allow semicolon in field key / struct tag
+ The json
struct field tags understood by
+ Marshal
,
+ Unmarshal
,
+ and related functionality now permit semicolon characters within
+ a JSON object name for a Go struct field.
@@ -456,7 +618,10 @@ Do not send CLs removing the interior tags from such phrases.
flag
- TODO: https://golang.org/cl/240014 : add Func
+ The new Func
function
+ allows registering a flag implemented by calling a function,
+ as a lighter-weight alternative to implementing the
+ Value
interface.
@@ -464,7 +629,8 @@ Do not send CLs removing the interior tags from such phrases.
io
- TODO: https://golang.org/cl/261577 : add a new ReadSeekCloser interface
+ The package now defines a
+ ReadSeekCloser
interface.
@@ -472,7 +638,8 @@ Do not send CLs removing the interior tags from such phrases.
log
- TODO: https://golang.org/cl/264460 : expose std via new Default function
+ The new Default
function
+ provides access to the default Logger
.
@@ -480,7 +647,11 @@ Do not send CLs removing the interior tags from such phrases.
log/syslog
- TODO: https://golang.org/cl/264297 : set local to true if network is any of "unix", or "unixgram"
+ The Writer
+ now uses the local message format
+ (omitting the host name and using a shorter time stamp)
+ when logging to custom Unix domain sockets,
+ matching the format already used for the default log socket.
@@ -488,7 +659,10 @@ Do not send CLs removing the interior tags from such phrases.
mime/multipart
- TODO: https://golang.org/cl/247477 : return overflow errors in Reader.ReadForm
+ The Reader
's
+ ReadForm
+ method no longer rejects form data
+ when passed the maximum int64 value as a limit.
@@ -512,7 +686,10 @@ Do not send CLs removing the interior tags from such phrases.
- TODO: https://golang.org/cl/238629 : prefer /etc/hosts over DNS when no /etc/nsswitch.conf is present
+ On Linux, host name lookups no longer use DNS before checking
+ /etc/hosts
when /etc/nsswitch.conf
+ is missing; this is common on musl-based systems and makes
+ Go programs match the behavior of C programs on those systems.
@@ -540,23 +717,29 @@ Do not send CLs removing the interior tags from such phrases.
- Cookies set with SameSiteDefaultMode
now behave according to the current
- spec (no attribute is set) instead of generating a SameSite key without a value.
+ Cookies set with SameSiteDefaultMode
+ now behave according to the current spec (no attribute is set) instead of
+ generating a SameSite key without a value.
- The net/http
package now uses the new
- (*tls.Conn).HandshakeContext
- with the Request
context
- when performing TLS handshakes in the client or server.
+ The net/http
package now passes the
+ Request
context to
+ tls.Conn.HandshakeContext
+ when performing TLS handshakes.
- TODO: https://golang.org/cl/250039 : set Content-Length:0 for empty PATCH requests as with POST, PATCH
+ The Client now sends
+ an explicit Content-Length:
0
+ header in PATCH
requests with empty bodies,
+ matching the existing behavior of POST
and PUT
.
- TODO: https://golang.org/cl/249440 : match http scheme when selecting http_proxy
+ The ProxyFromEnvironment function
+ no longer returns the setting of the HTTP_PROXY
environment
+ variable for https://
URLs when HTTPS_PROXY
is unset.
@@ -564,7 +747,9 @@ Do not send CLs removing the interior tags from such phrases.
net/http/httputil
- TODO: https://golang.org/cl/260637 : flush ReverseProxy immediately if Content-Length is -1
+ The ReverseProxy
+ now flushes buffered data more aggressively when proxying
+ streamed responses with unknown body lengths.
@@ -572,7 +757,10 @@ Do not send CLs removing the interior tags from such phrases.
net/smtp
- TODO: https://golang.org/cl/247257 : adds support for the SMTPUTF8 extension
+ The Client 's
+ Mail
+ method now sends the SMTPUTF8
directive to
+ servers that support it, signaling that addresses are encoded in UTF-8.
@@ -580,7 +768,10 @@ Do not send CLs removing the interior tags from such phrases.
os
- TODO: https://golang.org/cl/242998 : export errFinished as ErrProcessDone
+ Process.Signal
now
+ returns ErrProcessDone
+ instead of the unexported errFinished
when the process has
+ already finished.
@@ -588,55 +779,55 @@ Do not send CLs removing the interior tags from such phrases.
os/signal
- TODO: https://golang.org/cl/219640 : add NotifyContext to cancel context using system signals
+ The new
+ NotifyContext
+ function allows creating contexts that are canceled upon arrival of
+ specific signals.
path
-
- TODO: https://golang.org/cl/264397 : validate patterns in Match, Glob
+
+ The Match
and Glob
functions now
+ return an error if the unmatched part of the pattern has a
+ syntax error. Previously, the functions returned early on a failed
+ match, and thus did not report any later syntax error in the
+ pattern.
path/filepath
-
- TODO: https://golang.org/cl/264397 : validate patterns in Match, Glob
+
+ The Match
and Glob
functions now
+ return an error if the unmatched part of the pattern has a
+ syntax error. Previously, the functions returned early on a failed
+ match, and thus did not report any later syntax error in the
+ pattern.
reflect
-
- TODO: https://golang.org/cl/248341 : support multiple keys in struct tags
+
+ StructTag
now allows multiple space-separated keys
+ in key:value pairs, as in `json xml:"field1"`
+ (equivalent to `json:"field1" xml:"field1"`
).
-runtime
-
-
- TODO: https://golang.org/cl/37222 : make stack traces of endless recursion print only top and bottom 50
-
-
-
- TODO: https://golang.org/cl/242258 : add 24 byte allocation size class
-
-
-
- TODO: https://golang.org/cl/254659 : implement GODEBUG=inittrace=1 support
-
-
-
-
runtime/debug
- TODO: https://golang.org/cl/249677 : provide Addr method for errors from SetPanicOnFault
+ The runtime.Error
values
+ used when SetPanicOnFault
is enabled may now have an
+ Addr
method. If that method exists, it returns the memory
+ address that triggered the fault.
@@ -656,24 +847,39 @@ Do not send CLs removing the interior tags from such phrases.
syscall
+
+ NewCallback
+ and
+ NewCallbackCDecl
+ now correctly support callback functions with multiple
+ sub-uintptr
-sized arguments in a row. This may
+ require changing uses of these functions to eliminate manual
+ padding between small arguments.
+
+
- SysProcAttr
on Windows has a new NoInheritHandles field that disables inheriting handles when creating a new process.
+ SysProcAttr
on Windows has a new NoInheritHandles field that disables inheriting handles when creating a new process.
- DLLError
on Windows now has an Unwrap function for unwrapping its underlying error.
+ DLLError
on Windows now has an Unwrap function for unwrapping its underlying error.
- TODO: https://golang.org/cl/210639 : support POSIX semantics for Linux syscalls
+ On Linux,
+ Setgid
,
+ Setuid
,
+ and related calls are now implemented.
+ Previously, they returned an syscall.EOPNOTSUPP
error.
text/template
-
- TODO: https://golang.org/cl/254257 : allow newlines inside action delimiters
+
+ Newlines characters are now allowed inside action delimiters,
+ permitting actions to span multiple lines.
diff --git a/doc/go1.html b/doc/go1.html
index 34e305b93c..939ee24df5 100644
--- a/doc/go1.html
+++ b/doc/go1.html
@@ -1647,14 +1647,14 @@ c := signal.Incoming()
is
-c := make(chan os.Signal)
+c := make(chan os.Signal, 1)
signal.Notify(c) // ask for all signals
but most code should list the specific signals it wants to handle instead:
-c := make(chan os.Signal)
+c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT)
diff --git a/misc/cgo/testsanitizers/msan_test.go b/misc/cgo/testsanitizers/msan_test.go
index 88b90d3d70..5e2f9759ba 100644
--- a/misc/cgo/testsanitizers/msan_test.go
+++ b/misc/cgo/testsanitizers/msan_test.go
@@ -28,6 +28,7 @@ func TestMSAN(t *testing.T) {
{src: "msan4.go"},
{src: "msan5.go"},
{src: "msan6.go"},
+ {src: "msan7.go"},
{src: "msan_fail.go", wantErr: true},
}
for _, tc := range cases {
diff --git a/misc/cgo/testsanitizers/testdata/msan7.go b/misc/cgo/testsanitizers/testdata/msan7.go
new file mode 100644
index 0000000000..2f29fd21b2
--- /dev/null
+++ b/misc/cgo/testsanitizers/testdata/msan7.go
@@ -0,0 +1,38 @@
+// Copyright 2020 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
+
+// Test passing C struct to exported Go function.
+
+/*
+#include
+#include
+
+// T is a C struct with alignment padding after b.
+// The padding bytes are not considered initialized by MSAN.
+// It is big enough to be passed on stack in C ABI (and least
+// on AMD64).
+typedef struct { char b; uintptr_t x, y; } T;
+
+extern void F(T);
+
+// Use weak as a hack to permit defining a function even though we use export.
+void CF(int x) __attribute__ ((weak));
+void CF(int x) {
+ T *t = malloc(sizeof(T));
+ t->b = (char)x;
+ t->x = x;
+ t->y = x;
+ F(*t);
+}
+*/
+import "C"
+
+//export F
+func F(t C.T) { println(t.b, t.x, t.y) }
+
+func main() {
+ C.CF(C.int(0))
+}
diff --git a/src/archive/tar/reader_test.go b/src/archive/tar/reader_test.go
index 411d1e0b99..789ddc1bc0 100644
--- a/src/archive/tar/reader_test.go
+++ b/src/archive/tar/reader_test.go
@@ -10,7 +10,6 @@ import (
"errors"
"fmt"
"io"
- "io/ioutil"
"math"
"os"
"path"
@@ -773,7 +772,7 @@ func TestReadTruncation(t *testing.T) {
"testdata/pax-path-hdr.tar",
"testdata/sparse-formats.tar",
} {
- buf, err := ioutil.ReadFile(p)
+ buf, err := os.ReadFile(p)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
diff --git a/src/archive/tar/tar_test.go b/src/archive/tar/tar_test.go
index d4a3d42312..91b38401b6 100644
--- a/src/archive/tar/tar_test.go
+++ b/src/archive/tar/tar_test.go
@@ -11,7 +11,6 @@ import (
"internal/testenv"
"io"
"io/fs"
- "io/ioutil"
"math"
"os"
"path"
@@ -263,7 +262,7 @@ func TestFileInfoHeaderDir(t *testing.T) {
func TestFileInfoHeaderSymlink(t *testing.T) {
testenv.MustHaveSymlink(t)
- tmpdir, err := ioutil.TempDir("", "TestFileInfoHeaderSymlink")
+ tmpdir, err := os.MkdirTemp("", "TestFileInfoHeaderSymlink")
if err != nil {
t.Fatal(err)
}
diff --git a/src/archive/tar/writer_test.go b/src/archive/tar/writer_test.go
index 30556d27d0..a00f02d8fa 100644
--- a/src/archive/tar/writer_test.go
+++ b/src/archive/tar/writer_test.go
@@ -9,7 +9,6 @@ import (
"encoding/hex"
"errors"
"io"
- "io/ioutil"
"os"
"path"
"reflect"
@@ -520,7 +519,7 @@ func TestWriter(t *testing.T) {
}
if v.file != "" {
- want, err := ioutil.ReadFile(v.file)
+ want, err := os.ReadFile(v.file)
if err != nil {
t.Fatalf("ReadFile() = %v, want nil", err)
}
diff --git a/src/archive/zip/reader_test.go b/src/archive/zip/reader_test.go
index b7a7d7a757..34e96f7da4 100644
--- a/src/archive/zip/reader_test.go
+++ b/src/archive/zip/reader_test.go
@@ -11,7 +11,6 @@ import (
"internal/obscuretestdata"
"io"
"io/fs"
- "io/ioutil"
"os"
"path/filepath"
"regexp"
@@ -629,7 +628,7 @@ func readTestFile(t *testing.T, zt ZipTest, ft ZipTestFile, f *File) {
var c []byte
if ft.Content != nil {
c = ft.Content
- } else if c, err = ioutil.ReadFile("testdata/" + ft.File); err != nil {
+ } else if c, err = os.ReadFile("testdata/" + ft.File); err != nil {
t.Error(err)
return
}
@@ -685,7 +684,7 @@ func TestInvalidFiles(t *testing.T) {
}
func messWith(fileName string, corrupter func(b []byte)) (r io.ReaderAt, size int64) {
- data, err := ioutil.ReadFile(filepath.Join("testdata", fileName))
+ data, err := os.ReadFile(filepath.Join("testdata", fileName))
if err != nil {
panic("Error reading " + fileName + ": " + err.Error())
}
@@ -792,17 +791,17 @@ func returnRecursiveZip() (r io.ReaderAt, size int64) {
//
// func main() {
// bigZip := makeZip("big.file", io.LimitReader(zeros{}, 1<<32-1))
-// if err := ioutil.WriteFile("/tmp/big.zip", bigZip, 0666); err != nil {
+// if err := os.WriteFile("/tmp/big.zip", bigZip, 0666); err != nil {
// log.Fatal(err)
// }
//
// biggerZip := makeZip("big.zip", bytes.NewReader(bigZip))
-// if err := ioutil.WriteFile("/tmp/bigger.zip", biggerZip, 0666); err != nil {
+// if err := os.WriteFile("/tmp/bigger.zip", biggerZip, 0666); err != nil {
// log.Fatal(err)
// }
//
// biggestZip := makeZip("bigger.zip", bytes.NewReader(biggerZip))
-// if err := ioutil.WriteFile("/tmp/biggest.zip", biggestZip, 0666); err != nil {
+// if err := os.WriteFile("/tmp/biggest.zip", biggestZip, 0666); err != nil {
// log.Fatal(err)
// }
// }
diff --git a/src/archive/zip/writer_test.go b/src/archive/zip/writer_test.go
index 2c32eaf4a5..5985144e5c 100644
--- a/src/archive/zip/writer_test.go
+++ b/src/archive/zip/writer_test.go
@@ -10,8 +10,8 @@ import (
"fmt"
"io"
"io/fs"
- "io/ioutil"
"math/rand"
+ "os"
"strings"
"testing"
"time"
@@ -237,7 +237,7 @@ func TestWriterTime(t *testing.T) {
t.Fatalf("unexpected Close error: %v", err)
}
- want, err := ioutil.ReadFile("testdata/time-go.zip")
+ want, err := os.ReadFile("testdata/time-go.zip")
if err != nil {
t.Fatalf("unexpected ReadFile error: %v", err)
}
diff --git a/src/bufio/bufio_test.go b/src/bufio/bufio_test.go
index 75086f1f24..d7b34bd0d8 100644
--- a/src/bufio/bufio_test.go
+++ b/src/bufio/bufio_test.go
@@ -146,7 +146,7 @@ func TestReader(t *testing.T) {
for i := 0; i < len(texts)-1; i++ {
texts[i] = str + "\n"
all += texts[i]
- str += string(rune(i)%26 + 'a')
+ str += string(rune(i%26 + 'a'))
}
texts[len(texts)-1] = all
diff --git a/src/cmd/addr2line/addr2line_test.go b/src/cmd/addr2line/addr2line_test.go
index 7973aa2fe1..992d7ac11e 100644
--- a/src/cmd/addr2line/addr2line_test.go
+++ b/src/cmd/addr2line/addr2line_test.go
@@ -8,7 +8,6 @@ import (
"bufio"
"bytes"
"internal/testenv"
- "io/ioutil"
"os"
"os/exec"
"path/filepath"
@@ -98,8 +97,8 @@ func testAddr2Line(t *testing.T, exepath, addr string) {
if !os.SameFile(fi1, fi2) {
t.Fatalf("addr2line_test.go and %s are not same file", srcPath)
}
- if srcLineNo != "107" {
- t.Fatalf("line number = %v; want 107", srcLineNo)
+ if srcLineNo != "106" {
+ t.Fatalf("line number = %v; want 106", srcLineNo)
}
}
@@ -107,7 +106,7 @@ func testAddr2Line(t *testing.T, exepath, addr string) {
func TestAddr2Line(t *testing.T) {
testenv.MustHaveGoBuild(t)
- tmpDir, err := ioutil.TempDir("", "TestAddr2Line")
+ tmpDir, err := os.MkdirTemp("", "TestAddr2Line")
if err != nil {
t.Fatal("TempDir failed: ", err)
}
diff --git a/src/cmd/api/goapi.go b/src/cmd/api/goapi.go
index b14d57c236..ba42812fa6 100644
--- a/src/cmd/api/goapi.go
+++ b/src/cmd/api/goapi.go
@@ -17,7 +17,6 @@ import (
"go/token"
"go/types"
"io"
- "io/ioutil"
"log"
"os"
"os/exec"
@@ -342,7 +341,7 @@ func fileFeatures(filename string) []string {
if filename == "" {
return nil
}
- bs, err := ioutil.ReadFile(filename)
+ bs, err := os.ReadFile(filename)
if err != nil {
log.Fatalf("Error reading file %s: %v", filename, err)
}
diff --git a/src/cmd/api/goapi_test.go b/src/cmd/api/goapi_test.go
index 24620a94af..16e0058e5e 100644
--- a/src/cmd/api/goapi_test.go
+++ b/src/cmd/api/goapi_test.go
@@ -9,7 +9,6 @@ import (
"flag"
"fmt"
"go/build"
- "io/ioutil"
"os"
"path/filepath"
"sort"
@@ -75,7 +74,7 @@ func TestGolden(t *testing.T) {
f.Close()
}
- bs, err := ioutil.ReadFile(goldenFile)
+ bs, err := os.ReadFile(goldenFile)
if err != nil {
t.Fatalf("opening golden.txt for package %q: %v", fi.Name(), err)
}
diff --git a/src/cmd/asm/internal/asm/testdata/riscvenc.s b/src/cmd/asm/internal/asm/testdata/riscvenc.s
index e30a576473..9a49d96ca0 100644
--- a/src/cmd/asm/internal/asm/testdata/riscvenc.s
+++ b/src/cmd/asm/internal/asm/testdata/riscvenc.s
@@ -340,11 +340,11 @@ start:
// Branch pseudo-instructions
BEQZ X5, start // BEQZ X5, 2 // e38602c0
BGEZ X5, start // BGEZ X5, 2 // e3d402c0
- BGT X5, X6, start // BGT X5, X6, 2 // e3c262c0
- BGTU X5, X6, start // BGTU X5, X6, 2 // e3e062c0
+ BGT X5, X6, start // BGT X5, X6, 2 // e34253c0
+ BGTU X5, X6, start // BGTU X5, X6, 2 // e36053c0
BGTZ X5, start // BGTZ X5, 2 // e34e50be
- BLE X5, X6, start // BLE X5, X6, 2 // e3dc62be
- BLEU X5, X6, start // BLEU X5, X6, 2 // e3fa62be
+ BLE X5, X6, start // BLE X5, X6, 2 // e35c53be
+ BLEU X5, X6, start // BLEU X5, X6, 2 // e37a53be
BLEZ X5, start // BLEZ X5, 2 // e35850be
BLTZ X5, start // BLTZ X5, 2 // e3c602be
BNEZ X5, start // BNEZ X5, 2 // e39402be
diff --git a/src/cmd/buildid/buildid.go b/src/cmd/buildid/buildid.go
index 699d977950..8e02a7ae10 100644
--- a/src/cmd/buildid/buildid.go
+++ b/src/cmd/buildid/buildid.go
@@ -62,7 +62,7 @@ func main() {
return
}
- f, err = os.OpenFile(file, os.O_WRONLY, 0)
+ f, err = os.OpenFile(file, os.O_RDWR, 0)
if err != nil {
log.Fatal(err)
}
diff --git a/src/cmd/compile/fmt_test.go b/src/cmd/compile/fmt_test.go
index e372259c78..6398a84f8f 100644
--- a/src/cmd/compile/fmt_test.go
+++ b/src/cmd/compile/fmt_test.go
@@ -52,6 +52,7 @@ import (
"go/types"
"internal/testenv"
"io"
+ "io/fs"
"io/ioutil"
"log"
"os"
@@ -89,7 +90,7 @@ func TestFormats(t *testing.T) {
testenv.MustHaveGoBuild(t) // more restrictive than necessary, but that's ok
// process all directories
- filepath.Walk(".", func(path string, info os.FileInfo, err error) error {
+ filepath.WalkDir(".", func(path string, info fs.DirEntry, err error) error {
if info.IsDir() {
if info.Name() == "testdata" {
return filepath.SkipDir
@@ -124,6 +125,12 @@ func TestFormats(t *testing.T) {
typ := p.types[index]
format := typ + " " + in // e.g., "*Node %n"
+ // Do not bother reporting basic types, nor %v, %T, %p.
+ // Vet handles basic types, and those three formats apply to all types.
+ if !strings.Contains(typ, ".") || (in == "%v" || in == "%T" || in == "%p") {
+ return in
+ }
+
// check if format is known
out, known := knownFormats[format]
@@ -412,7 +419,17 @@ func nodeString(n ast.Node) string {
// typeString returns a string representation of n.
func typeString(typ types.Type) string {
- return filepath.ToSlash(typ.String())
+ s := filepath.ToSlash(typ.String())
+
+ // Report all the concrete IR types as Node, to shorten fmtmap.
+ const ir = "cmd/compile/internal/ir."
+ if s == "*"+ir+"Name" || s == "*"+ir+"Func" || s == "*"+ir+"Decl" ||
+ s == ir+"Ntype" || s == ir+"Expr" || s == ir+"Stmt" ||
+ strings.HasPrefix(s, "*"+ir) && (strings.HasSuffix(s, "Expr") || strings.HasSuffix(s, "Stmt")) {
+ return "cmd/compile/internal/ir.Node"
+ }
+
+ return s
}
// stringLit returns the unquoted string value and true if
diff --git a/src/cmd/compile/fmtmap_test.go b/src/cmd/compile/fmtmap_test.go
index 3b94b05bfb..9105bac191 100644
--- a/src/cmd/compile/fmtmap_test.go
+++ b/src/cmd/compile/fmtmap_test.go
@@ -20,229 +20,83 @@ package main_test
// An absent entry means that the format is not recognized as valid.
// An empty new format means that the format should remain unchanged.
var knownFormats = map[string]string{
- "*bytes.Buffer %s": "",
- "*cmd/compile/internal/gc.EscLocation %v": "",
- "*cmd/compile/internal/ir.node %v": "",
- "*cmd/compile/internal/ssa.Block %s": "",
- "*cmd/compile/internal/ssa.Block %v": "",
- "*cmd/compile/internal/ssa.Func %s": "",
- "*cmd/compile/internal/ssa.Func %v": "",
- "*cmd/compile/internal/ssa.Register %s": "",
- "*cmd/compile/internal/ssa.Register %v": "",
- "*cmd/compile/internal/ssa.SparseTreeNode %v": "",
- "*cmd/compile/internal/ssa.Value %s": "",
- "*cmd/compile/internal/ssa.Value %v": "",
- "*cmd/compile/internal/ssa.sparseTreeMapEntry %v": "",
- "*cmd/compile/internal/syntax.CallExpr %s": "",
- "*cmd/compile/internal/syntax.CallExpr %v": "",
- "*cmd/compile/internal/syntax.FuncLit %s": "",
- "*cmd/compile/internal/syntax.IndexExpr %s": "",
- "*cmd/compile/internal/types.Field %p": "",
- "*cmd/compile/internal/types.Field %v": "",
- "*cmd/compile/internal/types.Sym %0S": "",
- "*cmd/compile/internal/types.Sym %S": "",
- "*cmd/compile/internal/types.Sym %p": "",
- "*cmd/compile/internal/types.Sym %v": "",
- "*cmd/compile/internal/types.Type %#L": "",
- "*cmd/compile/internal/types.Type %#v": "",
- "*cmd/compile/internal/types.Type %-S": "",
- "*cmd/compile/internal/types.Type %0S": "",
- "*cmd/compile/internal/types.Type %L": "",
- "*cmd/compile/internal/types.Type %S": "",
- "*cmd/compile/internal/types.Type %p": "",
- "*cmd/compile/internal/types.Type %s": "",
- "*cmd/compile/internal/types.Type %v": "",
- "*cmd/compile/internal/types2.Basic %s": "",
- "*cmd/compile/internal/types2.Chan %s": "",
- "*cmd/compile/internal/types2.Func %s": "",
- "*cmd/compile/internal/types2.Initializer %s": "",
- "*cmd/compile/internal/types2.Interface %s": "",
- "*cmd/compile/internal/types2.MethodSet %s": "",
- "*cmd/compile/internal/types2.Named %s": "",
- "*cmd/compile/internal/types2.Named %v": "",
- "*cmd/compile/internal/types2.Package %s": "",
- "*cmd/compile/internal/types2.Package %v": "",
- "*cmd/compile/internal/types2.Scope %p": "",
- "*cmd/compile/internal/types2.Selection %s": "",
- "*cmd/compile/internal/types2.Signature %s": "",
- "*cmd/compile/internal/types2.TypeName %s": "",
- "*cmd/compile/internal/types2.TypeName %v": "",
- "*cmd/compile/internal/types2.TypeParam %s": "",
- "*cmd/compile/internal/types2.Var %s": "",
- "*cmd/compile/internal/types2.operand %s": "",
- "*cmd/compile/internal/types2.substMap %s": "",
- "*cmd/internal/obj.Addr %v": "",
- "*cmd/internal/obj.LSym %v": "",
- "*math/big.Float %f": "",
- "*math/big.Int %s": "",
- "[16]byte %x": "",
- "[]*cmd/compile/internal/ssa.Block %v": "",
- "[]*cmd/compile/internal/ssa.Value %v": "",
- "[]*cmd/compile/internal/types2.Func %v": "",
- "[]*cmd/compile/internal/types2.TypeName %s": "",
- "[][]string %q": "",
- "[]byte %s": "",
- "[]byte %x": "",
- "[]cmd/compile/internal/ssa.Edge %v": "",
- "[]cmd/compile/internal/ssa.ID %v": "",
- "[]cmd/compile/internal/ssa.posetNode %v": "",
- "[]cmd/compile/internal/ssa.posetUndo %v": "",
- "[]cmd/compile/internal/syntax.token %s": "",
- "[]cmd/compile/internal/types2.Type %s": "",
- "[]int %v": "",
- "[]string %v": "",
- "[]uint32 %v": "",
- "bool %v": "",
- "byte %08b": "",
- "byte %c": "",
- "byte %q": "",
- "byte %v": "",
- "cmd/compile/internal/arm.shift %d": "",
- "cmd/compile/internal/gc.initKind %d": "",
- "cmd/compile/internal/gc.itag %v": "",
- "cmd/compile/internal/importer.itag %v": "",
- "cmd/compile/internal/ir.Class %d": "",
- "cmd/compile/internal/ir.Class %v": "",
- "cmd/compile/internal/ir.FmtMode %d": "",
- "cmd/compile/internal/ir.Node %#v": "",
- "cmd/compile/internal/ir.Node %+S": "",
- "cmd/compile/internal/ir.Node %+v": "",
- "cmd/compile/internal/ir.Node %L": "",
- "cmd/compile/internal/ir.Node %S": "",
- "cmd/compile/internal/ir.Node %j": "",
- "cmd/compile/internal/ir.Node %p": "",
- "cmd/compile/internal/ir.Node %v": "",
- "cmd/compile/internal/ir.Nodes %#v": "",
- "cmd/compile/internal/ir.Nodes %+v": "",
- "cmd/compile/internal/ir.Nodes %.v": "",
- "cmd/compile/internal/ir.Nodes %v": "",
- "cmd/compile/internal/ir.Op %#v": "",
- "cmd/compile/internal/ir.Op %v": "",
- "cmd/compile/internal/ssa.BranchPrediction %d": "",
- "cmd/compile/internal/ssa.Edge %v": "",
- "cmd/compile/internal/ssa.ID %d": "",
- "cmd/compile/internal/ssa.ID %v": "",
- "cmd/compile/internal/ssa.LocalSlot %s": "",
- "cmd/compile/internal/ssa.LocalSlot %v": "",
- "cmd/compile/internal/ssa.Location %s": "",
- "cmd/compile/internal/ssa.Op %s": "",
- "cmd/compile/internal/ssa.Op %v": "",
- "cmd/compile/internal/ssa.Sym %v": "",
- "cmd/compile/internal/ssa.ValAndOff %s": "",
- "cmd/compile/internal/ssa.domain %v": "",
- "cmd/compile/internal/ssa.flagConstant %s": "",
- "cmd/compile/internal/ssa.posetNode %v": "",
- "cmd/compile/internal/ssa.posetTestOp %v": "",
- "cmd/compile/internal/ssa.rbrank %d": "",
- "cmd/compile/internal/ssa.regMask %d": "",
- "cmd/compile/internal/ssa.register %d": "",
- "cmd/compile/internal/ssa.relation %s": "",
- "cmd/compile/internal/syntax.ChanDir %d": "",
- "cmd/compile/internal/syntax.Decl %T": "",
- "cmd/compile/internal/syntax.Error %q": "",
- "cmd/compile/internal/syntax.Error %v": "",
- "cmd/compile/internal/syntax.Expr %#v": "",
- "cmd/compile/internal/syntax.Expr %T": "",
- "cmd/compile/internal/syntax.Expr %s": "",
- "cmd/compile/internal/syntax.LitKind %d": "",
- "cmd/compile/internal/syntax.Node %T": "",
- "cmd/compile/internal/syntax.Operator %s": "",
- "cmd/compile/internal/syntax.Pos %s": "",
- "cmd/compile/internal/syntax.Pos %v": "",
- "cmd/compile/internal/syntax.position %s": "",
- "cmd/compile/internal/syntax.token %q": "",
- "cmd/compile/internal/syntax.token %s": "",
- "cmd/compile/internal/types.EType %d": "",
- "cmd/compile/internal/types.EType %s": "",
- "cmd/compile/internal/types.EType %v": "",
- "cmd/compile/internal/types2.Object %T": "",
- "cmd/compile/internal/types2.Object %p": "",
- "cmd/compile/internal/types2.Object %s": "",
- "cmd/compile/internal/types2.Object %v": "",
- "cmd/compile/internal/types2.Type %T": "",
- "cmd/compile/internal/types2.Type %s": "",
- "cmd/compile/internal/types2.Type %v": "",
- "cmd/compile/internal/types2.color %s": "",
- "cmd/internal/obj.ABI %v": "",
- "error %s": "",
- "error %v": "",
- "float64 %.2f": "",
- "float64 %.3f": "",
- "float64 %g": "",
- "go/constant.Kind %v": "",
- "go/constant.Value %#v": "",
- "go/constant.Value %s": "",
- "go/constant.Value %v": "",
- "int %#x": "",
- "int %-12d": "",
- "int %-6d": "",
- "int %-8o": "",
- "int %02d": "",
- "int %6d": "",
- "int %c": "",
- "int %d": "",
- "int %v": "",
- "int %x": "",
- "int16 %d": "",
- "int16 %x": "",
- "int32 %#x": "",
- "int32 %d": "",
- "int32 %v": "",
- "int32 %x": "",
- "int64 %#x": "",
- "int64 %-10d": "",
- "int64 %.5d": "",
- "int64 %d": "",
- "int64 %v": "",
- "int64 %x": "",
- "int8 %d": "",
- "int8 %v": "",
- "int8 %x": "",
- "interface{} %#v": "",
- "interface{} %T": "",
- "interface{} %p": "",
- "interface{} %q": "",
- "interface{} %s": "",
- "interface{} %v": "",
+ "*bytes.Buffer %s": "",
+ "*cmd/compile/internal/ssa.Block %s": "",
+ "*cmd/compile/internal/ssa.Func %s": "",
+ "*cmd/compile/internal/ssa.Register %s": "",
+ "*cmd/compile/internal/ssa.Value %s": "",
+ "*cmd/compile/internal/syntax.CallExpr %s": "",
+ "*cmd/compile/internal/syntax.FuncLit %s": "",
+ "*cmd/compile/internal/syntax.IndexExpr %s": "",
+ "*cmd/compile/internal/types.Sym %+v": "",
+ "*cmd/compile/internal/types.Sym %S": "",
+ "*cmd/compile/internal/types.Type %+v": "",
+ "*cmd/compile/internal/types.Type %-S": "",
+ "*cmd/compile/internal/types.Type %L": "",
+ "*cmd/compile/internal/types.Type %S": "",
+ "*cmd/compile/internal/types.Type %s": "",
+ "*cmd/compile/internal/types2.Basic %s": "",
+ "*cmd/compile/internal/types2.Chan %s": "",
+ "*cmd/compile/internal/types2.Func %s": "",
+ "*cmd/compile/internal/types2.Initializer %s": "",
+ "*cmd/compile/internal/types2.Interface %s": "",
+ "*cmd/compile/internal/types2.MethodSet %s": "",
+ "*cmd/compile/internal/types2.Named %s": "",
+ "*cmd/compile/internal/types2.Package %s": "",
+ "*cmd/compile/internal/types2.Selection %s": "",
+ "*cmd/compile/internal/types2.Signature %s": "",
+ "*cmd/compile/internal/types2.TypeName %s": "",
+ "*cmd/compile/internal/types2.TypeParam %s": "",
+ "*cmd/compile/internal/types2.Var %s": "",
+ "*cmd/compile/internal/types2.operand %s": "",
+ "*cmd/compile/internal/types2.substMap %s": "",
+ "*math/big.Float %f": "",
+ "*math/big.Int %s": "",
+ "[]*cmd/compile/internal/types2.TypeName %s": "",
+ "[]cmd/compile/internal/syntax.token %s": "",
+ "[]cmd/compile/internal/types2.Type %s": "",
+ "cmd/compile/internal/arm.shift %d": "",
+ "cmd/compile/internal/gc.RegIndex %d": "",
+ "cmd/compile/internal/gc.initKind %d": "",
+ "cmd/compile/internal/ir.Class %d": "",
+ "cmd/compile/internal/ir.Node %+v": "",
+ "cmd/compile/internal/ir.Node %L": "",
+ "cmd/compile/internal/ir.Nodes %+v": "",
+ "cmd/compile/internal/ir.Nodes %.v": "",
+ "cmd/compile/internal/ir.Op %+v": "",
+ "cmd/compile/internal/ssa.Aux %#v": "",
+ "cmd/compile/internal/ssa.Aux %q": "",
+ "cmd/compile/internal/ssa.Aux %s": "",
+ "cmd/compile/internal/ssa.BranchPrediction %d": "",
+ "cmd/compile/internal/ssa.ID %d": "",
+ "cmd/compile/internal/ssa.LocalSlot %s": "",
+ "cmd/compile/internal/ssa.Location %s": "",
+ "cmd/compile/internal/ssa.Op %s": "",
+ "cmd/compile/internal/ssa.ValAndOff %s": "",
+ "cmd/compile/internal/ssa.flagConstant %s": "",
+ "cmd/compile/internal/ssa.rbrank %d": "",
+ "cmd/compile/internal/ssa.regMask %d": "",
+ "cmd/compile/internal/ssa.register %d": "",
+ "cmd/compile/internal/ssa.relation %s": "",
+ "cmd/compile/internal/syntax.ChanDir %d": "",
+ "cmd/compile/internal/syntax.Error %q": "",
+ "cmd/compile/internal/syntax.Expr %#v": "",
+ "cmd/compile/internal/syntax.Expr %s": "",
+ "cmd/compile/internal/syntax.LitKind %d": "",
+ "cmd/compile/internal/syntax.Operator %s": "",
+ "cmd/compile/internal/syntax.Pos %s": "",
+ "cmd/compile/internal/syntax.position %s": "",
+ "cmd/compile/internal/syntax.token %q": "",
+ "cmd/compile/internal/syntax.token %s": "",
+ "cmd/compile/internal/types.Kind %d": "",
+ "cmd/compile/internal/types.Kind %s": "",
+ "cmd/compile/internal/types2.Object %s": "",
+ "cmd/compile/internal/types2.Type %s": "",
+ "cmd/compile/internal/types2.color %s": "",
+ "go/constant.Value %#v": "",
+ "go/constant.Value %s": "",
"map[*cmd/compile/internal/types2.TypeParam]cmd/compile/internal/types2.Type %s": "",
- "map[cmd/compile/internal/ir.Node]*cmd/compile/internal/ssa.Value %v": "",
- "map[cmd/compile/internal/ir.Node][]cmd/compile/internal/ir.Node %v": "",
- "map[cmd/compile/internal/ssa.ID]uint32 %v": "",
- "map[int64]uint32 %v": "",
- "math/big.Accuracy %s": "",
- "reflect.Type %s": "",
- "reflect.Type %v": "",
- "rune %#U": "",
- "rune %c": "",
- "rune %q": "",
- "string %-*s": "",
- "string %-16s": "",
- "string %-6s": "",
- "string %T": "",
- "string %q": "",
- "string %s": "",
- "string %v": "",
- "time.Duration %d": "",
- "time.Duration %v": "",
- "uint %04x": "",
- "uint %5d": "",
- "uint %d": "",
- "uint %x": "",
- "uint16 %d": "",
- "uint16 %x": "",
- "uint32 %#U": "",
- "uint32 %#x": "",
- "uint32 %d": "",
- "uint32 %v": "",
- "uint32 %x": "",
- "uint64 %08x": "",
- "uint64 %b": "",
- "uint64 %d": "",
- "uint64 %v": "",
- "uint64 %x": "",
- "uint8 %#x": "",
- "uint8 %d": "",
- "uint8 %v": "",
- "uint8 %x": "",
- "uintptr %d": "",
+ "math/big.Accuracy %s": "",
+ "reflect.Type %s": "",
+ "time.Duration %d": "",
}
diff --git a/src/cmd/compile/internal/arm/ssa.go b/src/cmd/compile/internal/arm/ssa.go
index b34e2973b2..8b155712aa 100644
--- a/src/cmd/compile/internal/arm/ssa.go
+++ b/src/cmd/compile/internal/arm/ssa.go
@@ -546,7 +546,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
case *obj.LSym:
wantreg = "SB"
gc.AddAux(&p.From, v)
- case ir.Node:
+ case *ir.Name:
wantreg = "SP"
gc.AddAux(&p.From, v)
case nil:
diff --git a/src/cmd/compile/internal/arm64/ssa.go b/src/cmd/compile/internal/arm64/ssa.go
index d5bd9687cf..3eb0ae6557 100644
--- a/src/cmd/compile/internal/arm64/ssa.go
+++ b/src/cmd/compile/internal/arm64/ssa.go
@@ -396,7 +396,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
case *obj.LSym:
wantreg = "SB"
gc.AddAux(&p.From, v)
- case ir.Node:
+ case *ir.Name:
wantreg = "SP"
gc.AddAux(&p.From, v)
case nil:
diff --git a/src/cmd/compile/internal/gc/abiutils.go b/src/cmd/compile/internal/gc/abiutils.go
new file mode 100644
index 0000000000..19de14d48c
--- /dev/null
+++ b/src/cmd/compile/internal/gc/abiutils.go
@@ -0,0 +1,351 @@
+// Copyright 2020 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 gc
+
+import (
+ "cmd/compile/internal/types"
+ "cmd/internal/src"
+ "fmt"
+ "sync"
+)
+
+//......................................................................
+//
+// Public/exported bits of the ABI utilities.
+//
+
+// ABIParamResultInfo stores the results of processing a given
+// function type to compute stack layout and register assignments. For
+// each input and output parameter we capture whether the param was
+// register-assigned (and to which register(s)) or the stack offset
+// for the param if is not going to be passed in registers according
+// to the rules in the Go internal ABI specification (1.17).
+type ABIParamResultInfo struct {
+ inparams []ABIParamAssignment // Includes receiver for method calls. Does NOT include hidden closure pointer.
+ outparams []ABIParamAssignment
+ intSpillSlots int
+ floatSpillSlots int
+ offsetToSpillArea int64
+ config ABIConfig // to enable String() method
+}
+
+// RegIndex stores the index into the set of machine registers used by
+// the ABI on a specific architecture for parameter passing. RegIndex
+// values 0 through N-1 (where N is the number of integer registers
+// used for param passing according to the ABI rules) describe integer
+// registers; values N through M (where M is the number of floating
+// point registers used). Thus if the ABI says there are 5 integer
+// registers and 7 floating point registers, then RegIndex value of 4
+// indicates the 5th integer register, and a RegIndex value of 11
+// indicates the 7th floating point register.
+type RegIndex uint8
+
+// ABIParamAssignment holds information about how a specific param or
+// result will be passed: in registers (in which case 'Registers' is
+// populated) or on the stack (in which case 'Offset' is set to a
+// non-negative stack offset. The values in 'Registers' are indices (as
+// described above), not architected registers.
+type ABIParamAssignment struct {
+ Type *types.Type
+ Registers []RegIndex
+ Offset int32
+}
+
+// RegAmounts holds a specified number of integer/float registers.
+type RegAmounts struct {
+ intRegs int
+ floatRegs int
+}
+
+// ABIConfig captures the number of registers made available
+// by the ABI rules for parameter passing and result returning.
+type ABIConfig struct {
+ // Do we need anything more than this?
+ regAmounts RegAmounts
+}
+
+// ABIAnalyze takes a function type 't' and an ABI rules description
+// 'config' and analyzes the function to determine how its parameters
+// and results will be passed (in registers or on the stack), returning
+// an ABIParamResultInfo object that holds the results of the analysis.
+func ABIAnalyze(t *types.Type, config ABIConfig) ABIParamResultInfo {
+ setup()
+ s := assignState{
+ rTotal: config.regAmounts,
+ }
+ result := ABIParamResultInfo{config: config}
+
+ // Receiver
+ ft := t.FuncType()
+ if t.NumRecvs() != 0 {
+ rfsl := ft.Receiver.FieldSlice()
+ result.inparams = append(result.inparams,
+ s.assignParamOrReturn(rfsl[0].Type))
+ }
+
+ // Inputs
+ ifsl := ft.Params.FieldSlice()
+ for _, f := range ifsl {
+ result.inparams = append(result.inparams,
+ s.assignParamOrReturn(f.Type))
+ }
+ s.stackOffset = Rnd(s.stackOffset, int64(Widthreg))
+
+ // Record number of spill slots needed.
+ result.intSpillSlots = s.rUsed.intRegs
+ result.floatSpillSlots = s.rUsed.floatRegs
+
+ // Outputs
+ s.rUsed = RegAmounts{}
+ ofsl := ft.Results.FieldSlice()
+ for _, f := range ofsl {
+ result.outparams = append(result.outparams, s.assignParamOrReturn(f.Type))
+ }
+ result.offsetToSpillArea = s.stackOffset
+
+ return result
+}
+
+//......................................................................
+//
+// Non-public portions.
+
+// regString produces a human-readable version of a RegIndex.
+func (c *RegAmounts) regString(r RegIndex) string {
+ if int(r) < c.intRegs {
+ return fmt.Sprintf("I%d", int(r))
+ } else if int(r) < c.intRegs+c.floatRegs {
+ return fmt.Sprintf("F%d", int(r)-c.intRegs)
+ }
+ return fmt.Sprintf(">%d", r)
+}
+
+// toString method renders an ABIParamAssignment in human-readable
+// form, suitable for debugging or unit testing.
+func (ri *ABIParamAssignment) toString(config ABIConfig) string {
+ regs := "R{"
+ for _, r := range ri.Registers {
+ regs += " " + config.regAmounts.regString(r)
+ }
+ return fmt.Sprintf("%s } offset: %d typ: %v", regs, ri.Offset, ri.Type)
+}
+
+// toString method renders an ABIParamResultInfo in human-readable
+// form, suitable for debugging or unit testing.
+func (ri *ABIParamResultInfo) String() string {
+ res := ""
+ for k, p := range ri.inparams {
+ res += fmt.Sprintf("IN %d: %s\n", k, p.toString(ri.config))
+ }
+ for k, r := range ri.outparams {
+ res += fmt.Sprintf("OUT %d: %s\n", k, r.toString(ri.config))
+ }
+ res += fmt.Sprintf("intspill: %d floatspill: %d offsetToSpillArea: %d",
+ ri.intSpillSlots, ri.floatSpillSlots, ri.offsetToSpillArea)
+ return res
+}
+
+// assignState holds intermediate state during the register assigning process
+// for a given function signature.
+type assignState struct {
+ rTotal RegAmounts // total reg amounts from ABI rules
+ rUsed RegAmounts // regs used by params completely assigned so far
+ pUsed RegAmounts // regs used by the current param (or pieces therein)
+ stackOffset int64 // current stack offset
+}
+
+// stackSlot returns a stack offset for a param or result of the
+// specified type.
+func (state *assignState) stackSlot(t *types.Type) int64 {
+ if t.Align > 0 {
+ state.stackOffset = Rnd(state.stackOffset, int64(t.Align))
+ }
+ rv := state.stackOffset
+ state.stackOffset += t.Width
+ return rv
+}
+
+// allocateRegs returns a set of register indices for a parameter or result
+// that we've just determined to be register-assignable. The number of registers
+// needed is assumed to be stored in state.pUsed.
+func (state *assignState) allocateRegs() []RegIndex {
+ regs := []RegIndex{}
+
+ // integer
+ for r := state.rUsed.intRegs; r < state.rUsed.intRegs+state.pUsed.intRegs; r++ {
+ regs = append(regs, RegIndex(r))
+ }
+ state.rUsed.intRegs += state.pUsed.intRegs
+
+ // floating
+ for r := state.rUsed.floatRegs; r < state.rUsed.floatRegs+state.pUsed.floatRegs; r++ {
+ regs = append(regs, RegIndex(r+state.rTotal.intRegs))
+ }
+ state.rUsed.floatRegs += state.pUsed.floatRegs
+
+ return regs
+}
+
+// regAllocate creates a register ABIParamAssignment object for a param
+// or result with the specified type, as a final step (this assumes
+// that all of the safety/suitability analysis is complete).
+func (state *assignState) regAllocate(t *types.Type) ABIParamAssignment {
+ return ABIParamAssignment{
+ Type: t,
+ Registers: state.allocateRegs(),
+ Offset: -1,
+ }
+}
+
+// stackAllocate creates a stack memory ABIParamAssignment object for
+// a param or result with the specified type, as a final step (this
+// assumes that all of the safety/suitability analysis is complete).
+func (state *assignState) stackAllocate(t *types.Type) ABIParamAssignment {
+ return ABIParamAssignment{
+ Type: t,
+ Offset: int32(state.stackSlot(t)),
+ }
+}
+
+// intUsed returns the number of integer registers consumed
+// at a given point within an assignment stage.
+func (state *assignState) intUsed() int {
+ return state.rUsed.intRegs + state.pUsed.intRegs
+}
+
+// floatUsed returns the number of floating point registers consumed at
+// a given point within an assignment stage.
+func (state *assignState) floatUsed() int {
+ return state.rUsed.floatRegs + state.pUsed.floatRegs
+}
+
+// regassignIntegral examines a param/result of integral type 't' to
+// determines whether it can be register-assigned. Returns TRUE if we
+// can register allocate, FALSE otherwise (and updates state
+// accordingly).
+func (state *assignState) regassignIntegral(t *types.Type) bool {
+ regsNeeded := int(Rnd(t.Width, int64(Widthptr)) / int64(Widthptr))
+
+ // Floating point and complex.
+ if t.IsFloat() || t.IsComplex() {
+ if regsNeeded+state.floatUsed() > state.rTotal.floatRegs {
+ // not enough regs
+ return false
+ }
+ state.pUsed.floatRegs += regsNeeded
+ return true
+ }
+
+ // Non-floating point
+ if regsNeeded+state.intUsed() > state.rTotal.intRegs {
+ // not enough regs
+ return false
+ }
+ state.pUsed.intRegs += regsNeeded
+ return true
+}
+
+// regassignArray processes an array type (or array component within some
+// other enclosing type) to determine if it can be register assigned.
+// Returns TRUE if we can register allocate, FALSE otherwise.
+func (state *assignState) regassignArray(t *types.Type) bool {
+
+ nel := t.NumElem()
+ if nel == 0 {
+ return true
+ }
+ if nel > 1 {
+ // Not an array of length 1: stack assign
+ return false
+ }
+ // Visit element
+ return state.regassign(t.Elem())
+}
+
+// regassignStruct processes a struct type (or struct component within
+// some other enclosing type) to determine if it can be register
+// assigned. Returns TRUE if we can register allocate, FALSE otherwise.
+func (state *assignState) regassignStruct(t *types.Type) bool {
+ for _, field := range t.FieldSlice() {
+ if !state.regassign(field.Type) {
+ return false
+ }
+ }
+ return true
+}
+
+// synthOnce ensures that we only create the synth* fake types once.
+var synthOnce sync.Once
+
+// synthSlice, synthString, and syncIface are synthesized struct types
+// meant to capture the underlying implementations of string/slice/interface.
+var synthSlice *types.Type
+var synthString *types.Type
+var synthIface *types.Type
+
+// setup performs setup for the register assignment utilities, manufacturing
+// a small set of synthesized types that we'll need along the way.
+func setup() {
+ synthOnce.Do(func() {
+ fname := types.BuiltinPkg.Lookup
+ nxp := src.NoXPos
+ unsp := types.Types[types.TUNSAFEPTR]
+ ui := types.Types[types.TUINTPTR]
+ synthSlice = types.NewStruct(types.NoPkg, []*types.Field{
+ types.NewField(nxp, fname("ptr"), unsp),
+ types.NewField(nxp, fname("len"), ui),
+ types.NewField(nxp, fname("cap"), ui),
+ })
+ synthString = types.NewStruct(types.NoPkg, []*types.Field{
+ types.NewField(nxp, fname("data"), unsp),
+ types.NewField(nxp, fname("len"), ui),
+ })
+ synthIface = types.NewStruct(types.NoPkg, []*types.Field{
+ types.NewField(nxp, fname("f1"), unsp),
+ types.NewField(nxp, fname("f2"), unsp),
+ })
+ })
+}
+
+// regassign examines a given param type (or component within some
+// composite) to determine if it can be register assigned. Returns
+// TRUE if we can register allocate, FALSE otherwise.
+func (state *assignState) regassign(pt *types.Type) bool {
+ typ := pt.Kind()
+ if pt.IsScalar() || pt.IsPtrShaped() {
+ return state.regassignIntegral(pt)
+ }
+ switch typ {
+ case types.TARRAY:
+ return state.regassignArray(pt)
+ case types.TSTRUCT:
+ return state.regassignStruct(pt)
+ case types.TSLICE:
+ return state.regassignStruct(synthSlice)
+ case types.TSTRING:
+ return state.regassignStruct(synthString)
+ case types.TINTER:
+ return state.regassignStruct(synthIface)
+ default:
+ panic("not expected")
+ }
+}
+
+// assignParamOrReturn processes a given receiver, param, or result
+// of type 'pt' to determine whether it can be register assigned.
+// The result of the analysis is recorded in the result
+// ABIParamResultInfo held in 'state'.
+func (state *assignState) assignParamOrReturn(pt *types.Type) ABIParamAssignment {
+ state.pUsed = RegAmounts{}
+ if pt.Width == types.BADWIDTH {
+ panic("should never happen")
+ } else if pt.Width == 0 {
+ return state.stackAllocate(pt)
+ } else if state.regassign(pt) {
+ return state.regAllocate(pt)
+ } else {
+ return state.stackAllocate(pt)
+ }
+}
diff --git a/src/cmd/compile/internal/gc/abiutils_test.go b/src/cmd/compile/internal/gc/abiutils_test.go
new file mode 100644
index 0000000000..16bd787bea
--- /dev/null
+++ b/src/cmd/compile/internal/gc/abiutils_test.go
@@ -0,0 +1,270 @@
+// Copyright 2020 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 gc
+
+import (
+ "bufio"
+ "cmd/compile/internal/base"
+ "cmd/compile/internal/types"
+ "cmd/internal/obj"
+ "cmd/internal/obj/x86"
+ "cmd/internal/src"
+ "os"
+ "testing"
+)
+
+// AMD64 registers available:
+// - integer: RAX, RBX, RCX, RDI, RSI, R8, R9, r10, R11
+// - floating point: X0 - X14
+var configAMD64 = ABIConfig{
+ regAmounts: RegAmounts{
+ intRegs: 9,
+ floatRegs: 15,
+ },
+}
+
+func TestMain(m *testing.M) {
+ thearch.LinkArch = &x86.Linkamd64
+ thearch.REGSP = x86.REGSP
+ thearch.MAXWIDTH = 1 << 50
+ base.Ctxt = obj.Linknew(thearch.LinkArch)
+ base.Ctxt.DiagFunc = base.Errorf
+ base.Ctxt.DiagFlush = base.FlushErrors
+ base.Ctxt.Bso = bufio.NewWriter(os.Stdout)
+ Widthptr = thearch.LinkArch.PtrSize
+ Widthreg = thearch.LinkArch.RegSize
+ initializeTypesPackage()
+ os.Exit(m.Run())
+}
+
+func TestABIUtilsBasic1(t *testing.T) {
+
+ // func(x int32) int32
+ i32 := types.Types[types.TINT32]
+ ft := mkFuncType(nil, []*types.Type{i32}, []*types.Type{i32})
+
+ // expected results
+ exp := makeExpectedDump(`
+ IN 0: R{ I0 } offset: -1 typ: int32
+ OUT 0: R{ I0 } offset: -1 typ: int32
+ intspill: 1 floatspill: 0 offsetToSpillArea: 0
+`)
+
+ abitest(t, ft, exp)
+}
+
+func TestABIUtilsBasic2(t *testing.T) {
+ // func(x int32, y float64) (int32, float64, float64)
+ i8 := types.Types[types.TINT8]
+ i16 := types.Types[types.TINT16]
+ i32 := types.Types[types.TINT32]
+ i64 := types.Types[types.TINT64]
+ f32 := types.Types[types.TFLOAT32]
+ f64 := types.Types[types.TFLOAT64]
+ c64 := types.Types[types.TCOMPLEX64]
+ c128 := types.Types[types.TCOMPLEX128]
+ ft := mkFuncType(nil,
+ []*types.Type{
+ i8, i16, i32, i64,
+ f32, f32, f64, f64,
+ i8, i16, i32, i64,
+ f32, f32, f64, f64,
+ c128, c128, c128, c128, c64,
+ i8, i16, i32, i64,
+ i8, i16, i32, i64},
+ []*types.Type{i32, f64, f64})
+ exp := makeExpectedDump(`
+ IN 0: R{ I0 } offset: -1 typ: int8
+ IN 1: R{ I1 } offset: -1 typ: int16
+ IN 2: R{ I2 } offset: -1 typ: int32
+ IN 3: R{ I3 } offset: -1 typ: int64
+ IN 4: R{ F0 } offset: -1 typ: float32
+ IN 5: R{ F1 } offset: -1 typ: float32
+ IN 6: R{ F2 } offset: -1 typ: float64
+ IN 7: R{ F3 } offset: -1 typ: float64
+ IN 8: R{ I4 } offset: -1 typ: int8
+ IN 9: R{ I5 } offset: -1 typ: int16
+ IN 10: R{ I6 } offset: -1 typ: int32
+ IN 11: R{ I7 } offset: -1 typ: int64
+ IN 12: R{ F4 } offset: -1 typ: float32
+ IN 13: R{ F5 } offset: -1 typ: float32
+ IN 14: R{ F6 } offset: -1 typ: float64
+ IN 15: R{ F7 } offset: -1 typ: float64
+ IN 16: R{ F8 F9 } offset: -1 typ: complex128
+ IN 17: R{ F10 F11 } offset: -1 typ: complex128
+ IN 18: R{ F12 F13 } offset: -1 typ: complex128
+ IN 19: R{ } offset: 0 typ: complex128
+ IN 20: R{ F14 } offset: -1 typ: complex64
+ IN 21: R{ I8 } offset: -1 typ: int8
+ IN 22: R{ } offset: 16 typ: int16
+ IN 23: R{ } offset: 20 typ: int32
+ IN 24: R{ } offset: 24 typ: int64
+ IN 25: R{ } offset: 32 typ: int8
+ IN 26: R{ } offset: 34 typ: int16
+ IN 27: R{ } offset: 36 typ: int32
+ IN 28: R{ } offset: 40 typ: int64
+ OUT 0: R{ I0 } offset: -1 typ: int32
+ OUT 1: R{ F0 } offset: -1 typ: float64
+ OUT 2: R{ F1 } offset: -1 typ: float64
+ intspill: 9 floatspill: 15 offsetToSpillArea: 48
+`)
+
+ abitest(t, ft, exp)
+}
+
+func TestABIUtilsArrays(t *testing.T) {
+ i32 := types.Types[types.TINT32]
+ ae := types.NewArray(i32, 0)
+ a1 := types.NewArray(i32, 1)
+ a2 := types.NewArray(i32, 2)
+ aa1 := types.NewArray(a1, 1)
+ ft := mkFuncType(nil, []*types.Type{a1, ae, aa1, a2},
+ []*types.Type{a2, a1, ae, aa1})
+
+ exp := makeExpectedDump(`
+ IN 0: R{ I0 } offset: -1 typ: [1]int32
+ IN 1: R{ } offset: 0 typ: [0]int32
+ IN 2: R{ I1 } offset: -1 typ: [1][1]int32
+ IN 3: R{ } offset: 0 typ: [2]int32
+ OUT 0: R{ } offset: 8 typ: [2]int32
+ OUT 1: R{ I0 } offset: -1 typ: [1]int32
+ OUT 2: R{ } offset: 16 typ: [0]int32
+ OUT 3: R{ I1 } offset: -1 typ: [1][1]int32
+ intspill: 2 floatspill: 0 offsetToSpillArea: 16
+`)
+
+ abitest(t, ft, exp)
+}
+
+func TestABIUtilsStruct1(t *testing.T) {
+ i8 := types.Types[types.TINT8]
+ i16 := types.Types[types.TINT16]
+ i32 := types.Types[types.TINT32]
+ i64 := types.Types[types.TINT64]
+ s := mkstruct([]*types.Type{i8, i8, mkstruct([]*types.Type{}), i8, i16})
+ ft := mkFuncType(nil, []*types.Type{i8, s, i64},
+ []*types.Type{s, i8, i32})
+
+ exp := makeExpectedDump(`
+ IN 0: R{ I0 } offset: -1 typ: int8
+ IN 1: R{ I1 I2 I3 I4 } offset: -1 typ: struct { int8; int8; struct {}; int8; int16 }
+ IN 2: R{ I5 } offset: -1 typ: int64
+ OUT 0: R{ I0 I1 I2 I3 } offset: -1 typ: struct { int8; int8; struct {}; int8; int16 }
+ OUT 1: R{ I4 } offset: -1 typ: int8
+ OUT 2: R{ I5 } offset: -1 typ: int32
+ intspill: 6 floatspill: 0 offsetToSpillArea: 0
+`)
+
+ abitest(t, ft, exp)
+}
+
+func TestABIUtilsStruct2(t *testing.T) {
+ f64 := types.Types[types.TFLOAT64]
+ i64 := types.Types[types.TINT64]
+ s := mkstruct([]*types.Type{i64, mkstruct([]*types.Type{})})
+ fs := mkstruct([]*types.Type{f64, s, mkstruct([]*types.Type{})})
+ ft := mkFuncType(nil, []*types.Type{s, s, fs},
+ []*types.Type{fs, fs})
+
+ exp := makeExpectedDump(`
+ IN 0: R{ I0 } offset: -1 typ: struct { int64; struct {} }
+ IN 1: R{ I1 } offset: -1 typ: struct { int64; struct {} }
+ IN 2: R{ I2 F0 } offset: -1 typ: struct { float64; struct { int64; struct {} }; struct {} }
+ OUT 0: R{ I0 F0 } offset: -1 typ: struct { float64; struct { int64; struct {} }; struct {} }
+ OUT 1: R{ I1 F1 } offset: -1 typ: struct { float64; struct { int64; struct {} }; struct {} }
+ intspill: 3 floatspill: 1 offsetToSpillArea: 0
+`)
+
+ abitest(t, ft, exp)
+}
+
+func TestABIUtilsSliceString(t *testing.T) {
+ i32 := types.Types[types.TINT32]
+ sli32 := types.NewSlice(i32)
+ str := types.New(types.TSTRING)
+ i8 := types.Types[types.TINT8]
+ i64 := types.Types[types.TINT64]
+ ft := mkFuncType(nil, []*types.Type{sli32, i8, sli32, i8, str, i8, i64, sli32},
+ []*types.Type{str, i64, str, sli32})
+
+ exp := makeExpectedDump(`
+ IN 0: R{ I0 I1 I2 } offset: -1 typ: []int32
+ IN 1: R{ I3 } offset: -1 typ: int8
+ IN 2: R{ I4 I5 I6 } offset: -1 typ: []int32
+ IN 3: R{ I7 } offset: -1 typ: int8
+ IN 4: R{ } offset: 0 typ: string
+ IN 5: R{ I8 } offset: -1 typ: int8
+ IN 6: R{ } offset: 16 typ: int64
+ IN 7: R{ } offset: 24 typ: []int32
+ OUT 0: R{ I0 I1 } offset: -1 typ: string
+ OUT 1: R{ I2 } offset: -1 typ: int64
+ OUT 2: R{ I3 I4 } offset: -1 typ: string
+ OUT 3: R{ I5 I6 I7 } offset: -1 typ: []int32
+ intspill: 9 floatspill: 0 offsetToSpillArea: 48
+`)
+
+ abitest(t, ft, exp)
+}
+
+func TestABIUtilsMethod(t *testing.T) {
+ i16 := types.Types[types.TINT16]
+ i64 := types.Types[types.TINT64]
+ f64 := types.Types[types.TFLOAT64]
+
+ s1 := mkstruct([]*types.Type{i16, i16, i16})
+ ps1 := types.NewPtr(s1)
+ a7 := types.NewArray(ps1, 7)
+ ft := mkFuncType(s1, []*types.Type{ps1, a7, f64, i16, i16, i16},
+ []*types.Type{a7, f64, i64})
+
+ exp := makeExpectedDump(`
+ IN 0: R{ I0 I1 I2 } offset: -1 typ: struct { int16; int16; int16 }
+ IN 1: R{ I3 } offset: -1 typ: *struct { int16; int16; int16 }
+ IN 2: R{ } offset: 0 typ: [7]*struct { int16; int16; int16 }
+ IN 3: R{ F0 } offset: -1 typ: float64
+ IN 4: R{ I4 } offset: -1 typ: int16
+ IN 5: R{ I5 } offset: -1 typ: int16
+ IN 6: R{ I6 } offset: -1 typ: int16
+ OUT 0: R{ } offset: 56 typ: [7]*struct { int16; int16; int16 }
+ OUT 1: R{ F0 } offset: -1 typ: float64
+ OUT 2: R{ I0 } offset: -1 typ: int64
+ intspill: 7 floatspill: 1 offsetToSpillArea: 112
+`)
+
+ abitest(t, ft, exp)
+}
+
+func TestABIUtilsInterfaces(t *testing.T) {
+ ei := types.Types[types.TINTER] // interface{}
+ pei := types.NewPtr(ei) // *interface{}
+ fldt := mkFuncType(types.FakeRecvType(), []*types.Type{},
+ []*types.Type{types.UntypedString})
+ field := types.NewField(src.NoXPos, nil, fldt)
+ // interface{ ...() string }
+ nei := types.NewInterface(types.LocalPkg, []*types.Field{field})
+
+ i16 := types.Types[types.TINT16]
+ tb := types.Types[types.TBOOL]
+ s1 := mkstruct([]*types.Type{i16, i16, tb})
+
+ ft := mkFuncType(nil, []*types.Type{s1, ei, ei, nei, pei, nei, i16},
+ []*types.Type{ei, nei, pei})
+
+ exp := makeExpectedDump(`
+ IN 0: R{ I0 I1 I2 } offset: -1 typ: struct { int16; int16; bool }
+ IN 1: R{ I3 I4 } offset: -1 typ: interface {}
+ IN 2: R{ I5 I6 } offset: -1 typ: interface {}
+ IN 3: R{ I7 I8 } offset: -1 typ: interface { () untyped string }
+ IN 4: R{ } offset: 0 typ: *interface {}
+ IN 5: R{ } offset: 8 typ: interface { () untyped string }
+ IN 6: R{ } offset: 24 typ: int16
+ OUT 0: R{ I0 I1 } offset: -1 typ: interface {}
+ OUT 1: R{ I2 I3 } offset: -1 typ: interface { () untyped string }
+ OUT 2: R{ I4 } offset: -1 typ: *interface {}
+ intspill: 9 floatspill: 0 offsetToSpillArea: 32
+`)
+
+ abitest(t, ft, exp)
+}
diff --git a/src/cmd/compile/internal/gc/abiutilsaux_test.go b/src/cmd/compile/internal/gc/abiutilsaux_test.go
new file mode 100644
index 0000000000..d90d1d45a0
--- /dev/null
+++ b/src/cmd/compile/internal/gc/abiutilsaux_test.go
@@ -0,0 +1,157 @@
+// Copyright 2020 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 gc
+
+// This file contains utility routines and harness infrastructure used
+// by the ABI tests in "abiutils_test.go".
+
+import (
+ "cmd/compile/internal/ir"
+ "cmd/compile/internal/types"
+ "cmd/internal/src"
+ "fmt"
+ "strings"
+ "testing"
+ "text/scanner"
+)
+
+func mkParamResultField(t *types.Type, s *types.Sym, which ir.Class) *types.Field {
+ field := types.NewField(src.NoXPos, s, t)
+ n := NewName(s)
+ n.SetClass(which)
+ field.Nname = n
+ n.SetType(t)
+ return field
+}
+
+// mkstruct is a helper routine to create a struct type with fields
+// of the types specified in 'fieldtypes'.
+func mkstruct(fieldtypes []*types.Type) *types.Type {
+ fields := make([]*types.Field, len(fieldtypes))
+ for k, t := range fieldtypes {
+ if t == nil {
+ panic("bad -- field has no type")
+ }
+ f := types.NewField(src.NoXPos, nil, t)
+ fields[k] = f
+ }
+ s := types.NewStruct(types.LocalPkg, fields)
+ return s
+}
+
+func mkFuncType(rcvr *types.Type, ins []*types.Type, outs []*types.Type) *types.Type {
+ q := lookup("?")
+ inf := []*types.Field{}
+ for _, it := range ins {
+ inf = append(inf, mkParamResultField(it, q, ir.PPARAM))
+ }
+ outf := []*types.Field{}
+ for _, ot := range outs {
+ outf = append(outf, mkParamResultField(ot, q, ir.PPARAMOUT))
+ }
+ var rf *types.Field
+ if rcvr != nil {
+ rf = mkParamResultField(rcvr, q, ir.PPARAM)
+ }
+ return types.NewSignature(types.LocalPkg, rf, inf, outf)
+}
+
+type expectedDump struct {
+ dump string
+ file string
+ line int
+}
+
+func tokenize(src string) []string {
+ var s scanner.Scanner
+ s.Init(strings.NewReader(src))
+ res := []string{}
+ for tok := s.Scan(); tok != scanner.EOF; tok = s.Scan() {
+ res = append(res, s.TokenText())
+ }
+ return res
+}
+
+func verifyParamResultOffset(t *testing.T, f *types.Field, r ABIParamAssignment, which string, idx int) int {
+ n := ir.AsNode(f.Nname)
+ if n == nil {
+ panic("not expected")
+ }
+ if n.Offset() != int64(r.Offset) {
+ t.Errorf("%s %d: got offset %d wanted %d t=%v",
+ which, idx, r.Offset, n.Offset(), f.Type)
+ return 1
+ }
+ return 0
+}
+
+func makeExpectedDump(e string) expectedDump {
+ return expectedDump{dump: e}
+}
+
+func difftokens(atoks []string, etoks []string) string {
+ if len(atoks) != len(etoks) {
+ return fmt.Sprintf("expected %d tokens got %d",
+ len(etoks), len(atoks))
+ }
+ for i := 0; i < len(etoks); i++ {
+ if etoks[i] == atoks[i] {
+ continue
+ }
+
+ return fmt.Sprintf("diff at token %d: expected %q got %q",
+ i, etoks[i], atoks[i])
+ }
+ return ""
+}
+
+func abitest(t *testing.T, ft *types.Type, exp expectedDump) {
+
+ dowidth(ft)
+
+ // Analyze with full set of registers.
+ regRes := ABIAnalyze(ft, configAMD64)
+ regResString := strings.TrimSpace(regRes.String())
+
+ // Check results.
+ reason := difftokens(tokenize(regResString), tokenize(exp.dump))
+ if reason != "" {
+ t.Errorf("\nexpected:\n%s\ngot:\n%s\nreason: %s",
+ strings.TrimSpace(exp.dump), regResString, reason)
+ }
+
+ // Analyze again with empty register set.
+ empty := ABIConfig{}
+ emptyRes := ABIAnalyze(ft, empty)
+ emptyResString := emptyRes.String()
+
+ // Walk the results and make sure the offsets assigned match
+ // up with those assiged by dowidth. This checks to make sure that
+ // when we have no available registers the ABI assignment degenerates
+ // back to the original ABI0.
+
+ // receiver
+ failed := 0
+ rfsl := ft.Recvs().Fields().Slice()
+ poff := 0
+ if len(rfsl) != 0 {
+ failed |= verifyParamResultOffset(t, rfsl[0], emptyRes.inparams[0], "receiver", 0)
+ poff = 1
+ }
+ // params
+ pfsl := ft.Params().Fields().Slice()
+ for k, f := range pfsl {
+ verifyParamResultOffset(t, f, emptyRes.inparams[k+poff], "param", k)
+ }
+ // results
+ ofsl := ft.Results().Fields().Slice()
+ for k, f := range ofsl {
+ failed |= verifyParamResultOffset(t, f, emptyRes.outparams[k], "result", k)
+ }
+
+ if failed != 0 {
+ t.Logf("emptyres:\n%s\n", emptyResString)
+ }
+}
diff --git a/src/cmd/compile/internal/gc/alg.go b/src/cmd/compile/internal/gc/alg.go
index d2762126ad..c786a27415 100644
--- a/src/cmd/compile/internal/gc/alg.go
+++ b/src/cmd/compile/internal/gc/alg.go
@@ -68,7 +68,7 @@ func IncomparableField(t *types.Type) *types.Field {
// EqCanPanic reports whether == on type t could panic (has an interface somewhere).
// t must be comparable.
func EqCanPanic(t *types.Type) bool {
- switch t.Etype {
+ switch t.Kind() {
default:
return false
case types.TINTER:
@@ -120,7 +120,7 @@ func algtype1(t *types.Type) (AlgKind, *types.Type) {
return ANOEQ, t
}
- switch t.Etype {
+ switch t.Kind() {
case types.TANY, types.TFORW:
// will be defined later.
return ANOEQ, t
@@ -274,7 +274,7 @@ func genhash(t *types.Type) *obj.LSym {
// (And the closure generated by genhash will also get
// dead-code eliminated, as we call the subtype hashers
// directly.)
- switch t.Etype {
+ switch t.Kind() {
case types.TARRAY:
genhash(t.Elem())
case types.TSTRUCT:
@@ -292,18 +292,18 @@ func genhash(t *types.Type) *obj.LSym {
dclcontext = ir.PEXTERN
// func sym(p *T, h uintptr) uintptr
- tfn := ir.Nod(ir.OTFUNC, nil, nil)
- tfn.PtrList().Set2(
+ args := []*ir.Field{
namedfield("p", types.NewPtr(t)),
namedfield("h", types.Types[types.TUINTPTR]),
- )
- tfn.PtrRlist().Set1(anonfield(types.Types[types.TUINTPTR]))
+ }
+ results := []*ir.Field{anonfield(types.Types[types.TUINTPTR])}
+ tfn := ir.NewFuncType(base.Pos, nil, args, results)
fn := dclfunc(sym, tfn)
np := ir.AsNode(tfn.Type().Params().Field(0).Nname)
nh := ir.AsNode(tfn.Type().Params().Field(1).Nname)
- switch t.Etype {
+ switch t.Kind() {
case types.TARRAY:
// An array of pure memory would be handled by the
// standard algorithm, so the element type must not be
@@ -311,7 +311,7 @@ func genhash(t *types.Type) *obj.LSym {
hashel := hashfor(t.Elem())
n := ir.Nod(ir.ORANGE, nil, ir.Nod(ir.ODEREF, np, nil))
- ni := NewName(lookup("i"))
+ ni := ir.Node(NewName(lookup("i")))
ni.SetType(types.Types[types.TINT])
n.PtrList().Set1(ni)
n.SetColas(true)
@@ -382,8 +382,8 @@ func genhash(t *types.Type) *obj.LSym {
funcbody()
- fn.Func().SetDupok(true)
- fn = typecheck(fn, ctxStmt)
+ fn.SetDupok(true)
+ typecheckFunc(fn)
Curfn = fn
typecheckslice(fn.Body().Slice(), ctxStmt)
@@ -393,7 +393,7 @@ func genhash(t *types.Type) *obj.LSym {
testdclstack()
}
- fn.Func().SetNilCheckDisabled(true)
+ fn.SetNilCheckDisabled(true)
xtop = append(xtop, fn)
// Build closure. It doesn't close over any variables, so
@@ -432,10 +432,10 @@ func hashfor(t *types.Type) ir.Node {
n := NewName(sym)
setNodeNameFunc(n)
- n.SetType(functype(nil, []ir.Node{
+ n.SetType(functype(nil, []*ir.Field{
anonfield(types.NewPtr(t)),
anonfield(types.Types[types.TUINTPTR]),
- }, []ir.Node{
+ }, []*ir.Field{
anonfield(types.Types[types.TUINTPTR]),
}))
return n
@@ -521,12 +521,9 @@ func geneq(t *types.Type) *obj.LSym {
dclcontext = ir.PEXTERN
// func sym(p, q *T) bool
- tfn := ir.Nod(ir.OTFUNC, nil, nil)
- tfn.PtrList().Set2(
- namedfield("p", types.NewPtr(t)),
- namedfield("q", types.NewPtr(t)),
- )
- tfn.PtrRlist().Set1(namedfield("r", types.Types[types.TBOOL]))
+ tfn := ir.NewFuncType(base.Pos, nil,
+ []*ir.Field{namedfield("p", types.NewPtr(t)), namedfield("q", types.NewPtr(t))},
+ []*ir.Field{namedfield("r", types.Types[types.TBOOL])})
fn := dclfunc(sym, tfn)
np := ir.AsNode(tfn.Type().Params().Field(0).Nname)
@@ -539,7 +536,7 @@ func geneq(t *types.Type) *obj.LSym {
// We reach here only for types that have equality but
// cannot be handled by the standard algorithms,
// so t must be either an array or a struct.
- switch t.Etype {
+ switch t.Kind() {
default:
base.Fatalf("geneq %v", t)
@@ -616,7 +613,7 @@ func geneq(t *types.Type) *obj.LSym {
}
}
- switch t.Elem().Etype {
+ switch t.Elem().Kind() {
case types.TSTRING:
// Do two loops. First, check that all the lengths match (cheap).
// Second, check that all the contents match (expensive).
@@ -761,8 +758,8 @@ func geneq(t *types.Type) *obj.LSym {
funcbody()
- fn.Func().SetDupok(true)
- fn = typecheck(fn, ctxStmt)
+ fn.SetDupok(true)
+ typecheckFunc(fn)
Curfn = fn
typecheckslice(fn.Body().Slice(), ctxStmt)
@@ -776,7 +773,7 @@ func geneq(t *types.Type) *obj.LSym {
// We are comparing a struct or an array,
// neither of which can be nil, and our comparisons
// are shallow.
- fn.Func().SetNilCheckDisabled(true)
+ fn.SetNilCheckDisabled(true)
xtop = append(xtop, fn)
// Generate a closure which points at the function we just generated.
@@ -785,37 +782,14 @@ func geneq(t *types.Type) *obj.LSym {
return closure
}
-func hasCall(n ir.Node) bool {
- if n.Op() == ir.OCALL || n.Op() == ir.OCALLFUNC {
- return true
- }
- if n.Left() != nil && hasCall(n.Left()) {
- return true
- }
- if n.Right() != nil && hasCall(n.Right()) {
- return true
- }
- for _, x := range n.Init().Slice() {
- if hasCall(x) {
- return true
+func hasCall(fn *ir.Func) bool {
+ found := ir.Find(fn, func(n ir.Node) interface{} {
+ if op := n.Op(); op == ir.OCALL || op == ir.OCALLFUNC {
+ return n
}
- }
- for _, x := range n.Body().Slice() {
- if hasCall(x) {
- return true
- }
- }
- for _, x := range n.List().Slice() {
- if hasCall(x) {
- return true
- }
- }
- for _, x := range n.Rlist().Slice() {
- if hasCall(x) {
- return true
- }
- }
- return false
+ return nil
+ })
+ return found != nil
}
// eqfield returns the node
diff --git a/src/cmd/compile/internal/gc/align.go b/src/cmd/compile/internal/gc/align.go
index edf7d263a3..212e4c46ae 100644
--- a/src/cmd/compile/internal/gc/align.go
+++ b/src/cmd/compile/internal/gc/align.go
@@ -126,8 +126,8 @@ func widstruct(errtype *types.Type, t *types.Type, o int64, flag int) int64 {
// NOTE(rsc): This comment may be stale.
// It's possible the ordering has changed and this is
// now the common case. I'm not sure.
- if n.Name().Param.Stackcopy != nil {
- n.Name().Param.Stackcopy.SetOffset(o)
+ if n.Name().Stackcopy != nil {
+ n.Name().Stackcopy.SetOffset(o)
n.SetOffset(0)
} else {
n.SetOffset(o)
@@ -185,11 +185,18 @@ func findTypeLoop(t *types.Type, path *[]*types.Type) bool {
// We implement a simple DFS loop-finding algorithm. This
// could be faster, but type cycles are rare.
- if t.Sym != nil {
+ if t.Sym() != nil {
// Declared type. Check for loops and otherwise
// recurse on the type expression used in the type
// declaration.
+ // Type imported from package, so it can't be part of
+ // a type loop (otherwise that package should have
+ // failed to compile).
+ if t.Sym().Pkg != types.LocalPkg {
+ return false
+ }
+
for i, x := range *path {
if x == t {
*path = (*path)[i:]
@@ -198,14 +205,14 @@ func findTypeLoop(t *types.Type, path *[]*types.Type) bool {
}
*path = append(*path, t)
- if p := ir.AsNode(t.Nod).Name().Param; p != nil && findTypeLoop(p.Ntype.Type(), path) {
+ if findTypeLoop(t.Obj().(*ir.Name).Ntype.Type(), path) {
return true
}
*path = (*path)[:len(*path)-1]
} else {
// Anonymous type. Recurse on contained types.
- switch t.Etype {
+ switch t.Kind() {
case types.TARRAY:
if findTypeLoop(t.Elem(), path) {
return true
@@ -307,22 +314,22 @@ func dowidth(t *types.Type) {
defercheckwidth()
lno := base.Pos
- if ir.AsNode(t.Nod) != nil {
- base.Pos = ir.AsNode(t.Nod).Pos()
+ if pos := t.Pos(); pos.IsKnown() {
+ base.Pos = pos
}
t.Width = -2
t.Align = 0 // 0 means use t.Width, below
- et := t.Etype
+ et := t.Kind()
switch et {
case types.TFUNC, types.TCHAN, types.TMAP, types.TSTRING:
break
// simtype == 0 during bootstrap
default:
- if simtype[t.Etype] != 0 {
- et = simtype[t.Etype]
+ if simtype[t.Kind()] != 0 {
+ et = simtype[t.Kind()]
}
}
diff --git a/src/cmd/compile/internal/gc/bexport.go b/src/cmd/compile/internal/gc/bexport.go
index a470b842ff..43c4ce7150 100644
--- a/src/cmd/compile/internal/gc/bexport.go
+++ b/src/cmd/compile/internal/gc/bexport.go
@@ -16,7 +16,7 @@ type exporter struct {
// markObject visits a reachable object.
func (p *exporter) markObject(n ir.Node) {
if n.Op() == ir.ONAME && n.Class() == ir.PFUNC {
- inlFlood(n)
+ inlFlood(n.(*ir.Name))
}
p.markType(n.Type())
@@ -35,7 +35,7 @@ func (p *exporter) markType(t *types.Type) {
// only their unexpanded method set (i.e., exclusive of
// interface embeddings), and the switch statement below
// handles their full method set.
- if t.Sym != nil && t.Etype != types.TINTER {
+ if t.Sym() != nil && t.Kind() != types.TINTER {
for _, m := range t.Methods().Slice() {
if types.IsExported(m.Sym.Name) {
p.markObject(ir.AsNode(m.Nname))
@@ -52,7 +52,7 @@ func (p *exporter) markType(t *types.Type) {
// Notably, we don't mark function parameter types, because
// the user already needs some way to construct values of
// those types.
- switch t.Etype {
+ switch t.Kind() {
case types.TPTR, types.TARRAY, types.TSLICE:
p.markType(t.Elem())
@@ -153,11 +153,11 @@ func predeclared() []*types.Type {
types.Types[types.TSTRING],
// basic type aliases
- types.Bytetype,
- types.Runetype,
+ types.ByteType,
+ types.RuneType,
// error
- types.Errortype,
+ types.ErrorType,
// untyped types
types.UntypedBool,
diff --git a/src/cmd/compile/internal/gc/bimport.go b/src/cmd/compile/internal/gc/bimport.go
index c0c18e728e..5a7018d8e6 100644
--- a/src/cmd/compile/internal/gc/bimport.go
+++ b/src/cmd/compile/internal/gc/bimport.go
@@ -6,6 +6,7 @@ package gc
import (
"cmd/compile/internal/ir"
+ "cmd/compile/internal/types"
"cmd/internal/src"
)
@@ -15,5 +16,5 @@ func npos(pos src.XPos, n ir.Node) ir.Node {
}
func builtinCall(op ir.Op) ir.Node {
- return ir.Nod(ir.OCALL, mkname(ir.BuiltinPkg.Lookup(ir.OpNames[op])), nil)
+ return ir.Nod(ir.OCALL, mkname(types.BuiltinPkg.Lookup(ir.OpNames[op])), nil)
}
diff --git a/src/cmd/compile/internal/gc/builtin.go b/src/cmd/compile/internal/gc/builtin.go
index a57c611559..d3e3f9ade6 100644
--- a/src/cmd/compile/internal/gc/builtin.go
+++ b/src/cmd/compile/internal/gc/builtin.go
@@ -187,16 +187,17 @@ var runtimeDecls = [...]struct {
{"racewriterange", funcTag, 121},
{"msanread", funcTag, 121},
{"msanwrite", funcTag, 121},
- {"checkptrAlignment", funcTag, 122},
- {"checkptrArithmetic", funcTag, 124},
- {"libfuzzerTraceCmp1", funcTag, 126},
- {"libfuzzerTraceCmp2", funcTag, 128},
- {"libfuzzerTraceCmp4", funcTag, 129},
- {"libfuzzerTraceCmp8", funcTag, 130},
- {"libfuzzerTraceConstCmp1", funcTag, 126},
- {"libfuzzerTraceConstCmp2", funcTag, 128},
- {"libfuzzerTraceConstCmp4", funcTag, 129},
- {"libfuzzerTraceConstCmp8", funcTag, 130},
+ {"msanmove", funcTag, 122},
+ {"checkptrAlignment", funcTag, 123},
+ {"checkptrArithmetic", funcTag, 125},
+ {"libfuzzerTraceCmp1", funcTag, 127},
+ {"libfuzzerTraceCmp2", funcTag, 129},
+ {"libfuzzerTraceCmp4", funcTag, 130},
+ {"libfuzzerTraceCmp8", funcTag, 131},
+ {"libfuzzerTraceConstCmp1", funcTag, 127},
+ {"libfuzzerTraceConstCmp2", funcTag, 129},
+ {"libfuzzerTraceConstCmp4", funcTag, 130},
+ {"libfuzzerTraceConstCmp8", funcTag, 131},
{"x86HasPOPCNT", varTag, 6},
{"x86HasSSE41", varTag, 6},
{"x86HasFMA", varTag, 6},
@@ -205,137 +206,138 @@ var runtimeDecls = [...]struct {
}
func runtimeTypes() []*types.Type {
- var typs [131]*types.Type
- typs[0] = types.Bytetype
+ var typs [132]*types.Type
+ typs[0] = types.ByteType
typs[1] = types.NewPtr(typs[0])
typs[2] = types.Types[types.TANY]
typs[3] = types.NewPtr(typs[2])
- typs[4] = functype(nil, []ir.Node{anonfield(typs[1])}, []ir.Node{anonfield(typs[3])})
+ typs[4] = functype(nil, []*ir.Field{anonfield(typs[1])}, []*ir.Field{anonfield(typs[3])})
typs[5] = types.Types[types.TUINTPTR]
typs[6] = types.Types[types.TBOOL]
typs[7] = types.Types[types.TUNSAFEPTR]
- typs[8] = functype(nil, []ir.Node{anonfield(typs[5]), anonfield(typs[1]), anonfield(typs[6])}, []ir.Node{anonfield(typs[7])})
+ typs[8] = functype(nil, []*ir.Field{anonfield(typs[5]), anonfield(typs[1]), anonfield(typs[6])}, []*ir.Field{anonfield(typs[7])})
typs[9] = functype(nil, nil, nil)
typs[10] = types.Types[types.TINTER]
- typs[11] = functype(nil, []ir.Node{anonfield(typs[10])}, nil)
+ typs[11] = functype(nil, []*ir.Field{anonfield(typs[10])}, nil)
typs[12] = types.Types[types.TINT32]
typs[13] = types.NewPtr(typs[12])
- typs[14] = functype(nil, []ir.Node{anonfield(typs[13])}, []ir.Node{anonfield(typs[10])})
+ typs[14] = functype(nil, []*ir.Field{anonfield(typs[13])}, []*ir.Field{anonfield(typs[10])})
typs[15] = types.Types[types.TINT]
- typs[16] = functype(nil, []ir.Node{anonfield(typs[15]), anonfield(typs[15])}, nil)
+ typs[16] = functype(nil, []*ir.Field{anonfield(typs[15]), anonfield(typs[15])}, nil)
typs[17] = types.Types[types.TUINT]
- typs[18] = functype(nil, []ir.Node{anonfield(typs[17]), anonfield(typs[15])}, nil)
- typs[19] = functype(nil, []ir.Node{anonfield(typs[6])}, nil)
+ typs[18] = functype(nil, []*ir.Field{anonfield(typs[17]), anonfield(typs[15])}, nil)
+ typs[19] = functype(nil, []*ir.Field{anonfield(typs[6])}, nil)
typs[20] = types.Types[types.TFLOAT64]
- typs[21] = functype(nil, []ir.Node{anonfield(typs[20])}, nil)
+ typs[21] = functype(nil, []*ir.Field{anonfield(typs[20])}, nil)
typs[22] = types.Types[types.TINT64]
- typs[23] = functype(nil, []ir.Node{anonfield(typs[22])}, nil)
+ typs[23] = functype(nil, []*ir.Field{anonfield(typs[22])}, nil)
typs[24] = types.Types[types.TUINT64]
- typs[25] = functype(nil, []ir.Node{anonfield(typs[24])}, nil)
+ typs[25] = functype(nil, []*ir.Field{anonfield(typs[24])}, nil)
typs[26] = types.Types[types.TCOMPLEX128]
- typs[27] = functype(nil, []ir.Node{anonfield(typs[26])}, nil)
+ typs[27] = functype(nil, []*ir.Field{anonfield(typs[26])}, nil)
typs[28] = types.Types[types.TSTRING]
- typs[29] = functype(nil, []ir.Node{anonfield(typs[28])}, nil)
- typs[30] = functype(nil, []ir.Node{anonfield(typs[2])}, nil)
- typs[31] = functype(nil, []ir.Node{anonfield(typs[5])}, nil)
+ typs[29] = functype(nil, []*ir.Field{anonfield(typs[28])}, nil)
+ typs[30] = functype(nil, []*ir.Field{anonfield(typs[2])}, nil)
+ typs[31] = functype(nil, []*ir.Field{anonfield(typs[5])}, nil)
typs[32] = types.NewArray(typs[0], 32)
typs[33] = types.NewPtr(typs[32])
- typs[34] = functype(nil, []ir.Node{anonfield(typs[33]), anonfield(typs[28]), anonfield(typs[28])}, []ir.Node{anonfield(typs[28])})
- typs[35] = functype(nil, []ir.Node{anonfield(typs[33]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28])}, []ir.Node{anonfield(typs[28])})
- typs[36] = functype(nil, []ir.Node{anonfield(typs[33]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28])}, []ir.Node{anonfield(typs[28])})
- typs[37] = functype(nil, []ir.Node{anonfield(typs[33]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28])}, []ir.Node{anonfield(typs[28])})
+ typs[34] = functype(nil, []*ir.Field{anonfield(typs[33]), anonfield(typs[28]), anonfield(typs[28])}, []*ir.Field{anonfield(typs[28])})
+ typs[35] = functype(nil, []*ir.Field{anonfield(typs[33]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28])}, []*ir.Field{anonfield(typs[28])})
+ typs[36] = functype(nil, []*ir.Field{anonfield(typs[33]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28])}, []*ir.Field{anonfield(typs[28])})
+ typs[37] = functype(nil, []*ir.Field{anonfield(typs[33]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28])}, []*ir.Field{anonfield(typs[28])})
typs[38] = types.NewSlice(typs[28])
- typs[39] = functype(nil, []ir.Node{anonfield(typs[33]), anonfield(typs[38])}, []ir.Node{anonfield(typs[28])})
- typs[40] = functype(nil, []ir.Node{anonfield(typs[28]), anonfield(typs[28])}, []ir.Node{anonfield(typs[15])})
+ typs[39] = functype(nil, []*ir.Field{anonfield(typs[33]), anonfield(typs[38])}, []*ir.Field{anonfield(typs[28])})
+ typs[40] = functype(nil, []*ir.Field{anonfield(typs[28]), anonfield(typs[28])}, []*ir.Field{anonfield(typs[15])})
typs[41] = types.NewArray(typs[0], 4)
typs[42] = types.NewPtr(typs[41])
- typs[43] = functype(nil, []ir.Node{anonfield(typs[42]), anonfield(typs[22])}, []ir.Node{anonfield(typs[28])})
- typs[44] = functype(nil, []ir.Node{anonfield(typs[33]), anonfield(typs[1]), anonfield(typs[15])}, []ir.Node{anonfield(typs[28])})
- typs[45] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[15])}, []ir.Node{anonfield(typs[28])})
- typs[46] = types.Runetype
+ typs[43] = functype(nil, []*ir.Field{anonfield(typs[42]), anonfield(typs[22])}, []*ir.Field{anonfield(typs[28])})
+ typs[44] = functype(nil, []*ir.Field{anonfield(typs[33]), anonfield(typs[1]), anonfield(typs[15])}, []*ir.Field{anonfield(typs[28])})
+ typs[45] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[15])}, []*ir.Field{anonfield(typs[28])})
+ typs[46] = types.RuneType
typs[47] = types.NewSlice(typs[46])
- typs[48] = functype(nil, []ir.Node{anonfield(typs[33]), anonfield(typs[47])}, []ir.Node{anonfield(typs[28])})
+ typs[48] = functype(nil, []*ir.Field{anonfield(typs[33]), anonfield(typs[47])}, []*ir.Field{anonfield(typs[28])})
typs[49] = types.NewSlice(typs[0])
- typs[50] = functype(nil, []ir.Node{anonfield(typs[33]), anonfield(typs[28])}, []ir.Node{anonfield(typs[49])})
+ typs[50] = functype(nil, []*ir.Field{anonfield(typs[33]), anonfield(typs[28])}, []*ir.Field{anonfield(typs[49])})
typs[51] = types.NewArray(typs[46], 32)
typs[52] = types.NewPtr(typs[51])
- typs[53] = functype(nil, []ir.Node{anonfield(typs[52]), anonfield(typs[28])}, []ir.Node{anonfield(typs[47])})
- typs[54] = functype(nil, []ir.Node{anonfield(typs[3]), anonfield(typs[15]), anonfield(typs[3]), anonfield(typs[15]), anonfield(typs[5])}, []ir.Node{anonfield(typs[15])})
- typs[55] = functype(nil, []ir.Node{anonfield(typs[28]), anonfield(typs[15])}, []ir.Node{anonfield(typs[46]), anonfield(typs[15])})
- typs[56] = functype(nil, []ir.Node{anonfield(typs[28])}, []ir.Node{anonfield(typs[15])})
- typs[57] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[2])}, []ir.Node{anonfield(typs[2])})
- typs[58] = functype(nil, []ir.Node{anonfield(typs[2])}, []ir.Node{anonfield(typs[7])})
- typs[59] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[3])}, []ir.Node{anonfield(typs[2])})
- typs[60] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[2])}, []ir.Node{anonfield(typs[2]), anonfield(typs[6])})
- typs[61] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[1])}, nil)
- typs[62] = functype(nil, []ir.Node{anonfield(typs[1])}, nil)
+ typs[53] = functype(nil, []*ir.Field{anonfield(typs[52]), anonfield(typs[28])}, []*ir.Field{anonfield(typs[47])})
+ typs[54] = functype(nil, []*ir.Field{anonfield(typs[3]), anonfield(typs[15]), anonfield(typs[3]), anonfield(typs[15]), anonfield(typs[5])}, []*ir.Field{anonfield(typs[15])})
+ typs[55] = functype(nil, []*ir.Field{anonfield(typs[28]), anonfield(typs[15])}, []*ir.Field{anonfield(typs[46]), anonfield(typs[15])})
+ typs[56] = functype(nil, []*ir.Field{anonfield(typs[28])}, []*ir.Field{anonfield(typs[15])})
+ typs[57] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[2])}, []*ir.Field{anonfield(typs[2])})
+ typs[58] = functype(nil, []*ir.Field{anonfield(typs[2])}, []*ir.Field{anonfield(typs[7])})
+ typs[59] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[3])}, []*ir.Field{anonfield(typs[2])})
+ typs[60] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[2])}, []*ir.Field{anonfield(typs[2]), anonfield(typs[6])})
+ typs[61] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[1])}, nil)
+ typs[62] = functype(nil, []*ir.Field{anonfield(typs[1])}, nil)
typs[63] = types.NewPtr(typs[5])
- typs[64] = functype(nil, []ir.Node{anonfield(typs[63]), anonfield(typs[7]), anonfield(typs[7])}, []ir.Node{anonfield(typs[6])})
+ typs[64] = functype(nil, []*ir.Field{anonfield(typs[63]), anonfield(typs[7]), anonfield(typs[7])}, []*ir.Field{anonfield(typs[6])})
typs[65] = types.Types[types.TUINT32]
- typs[66] = functype(nil, nil, []ir.Node{anonfield(typs[65])})
+ typs[66] = functype(nil, nil, []*ir.Field{anonfield(typs[65])})
typs[67] = types.NewMap(typs[2], typs[2])
- typs[68] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[22]), anonfield(typs[3])}, []ir.Node{anonfield(typs[67])})
- typs[69] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[3])}, []ir.Node{anonfield(typs[67])})
- typs[70] = functype(nil, nil, []ir.Node{anonfield(typs[67])})
- typs[71] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3])}, []ir.Node{anonfield(typs[3])})
- typs[72] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[2])}, []ir.Node{anonfield(typs[3])})
- typs[73] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3]), anonfield(typs[1])}, []ir.Node{anonfield(typs[3])})
- typs[74] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3])}, []ir.Node{anonfield(typs[3]), anonfield(typs[6])})
- typs[75] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[2])}, []ir.Node{anonfield(typs[3]), anonfield(typs[6])})
- typs[76] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3]), anonfield(typs[1])}, []ir.Node{anonfield(typs[3]), anonfield(typs[6])})
- typs[77] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3])}, nil)
- typs[78] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[2])}, nil)
- typs[79] = functype(nil, []ir.Node{anonfield(typs[3])}, nil)
- typs[80] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[67])}, nil)
+ typs[68] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[22]), anonfield(typs[3])}, []*ir.Field{anonfield(typs[67])})
+ typs[69] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[3])}, []*ir.Field{anonfield(typs[67])})
+ typs[70] = functype(nil, nil, []*ir.Field{anonfield(typs[67])})
+ typs[71] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3])}, []*ir.Field{anonfield(typs[3])})
+ typs[72] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[2])}, []*ir.Field{anonfield(typs[3])})
+ typs[73] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3]), anonfield(typs[1])}, []*ir.Field{anonfield(typs[3])})
+ typs[74] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3])}, []*ir.Field{anonfield(typs[3]), anonfield(typs[6])})
+ typs[75] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[2])}, []*ir.Field{anonfield(typs[3]), anonfield(typs[6])})
+ typs[76] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3]), anonfield(typs[1])}, []*ir.Field{anonfield(typs[3]), anonfield(typs[6])})
+ typs[77] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3])}, nil)
+ typs[78] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[2])}, nil)
+ typs[79] = functype(nil, []*ir.Field{anonfield(typs[3])}, nil)
+ typs[80] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[67])}, nil)
typs[81] = types.NewChan(typs[2], types.Cboth)
- typs[82] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[22])}, []ir.Node{anonfield(typs[81])})
- typs[83] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[15])}, []ir.Node{anonfield(typs[81])})
+ typs[82] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[22])}, []*ir.Field{anonfield(typs[81])})
+ typs[83] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[15])}, []*ir.Field{anonfield(typs[81])})
typs[84] = types.NewChan(typs[2], types.Crecv)
- typs[85] = functype(nil, []ir.Node{anonfield(typs[84]), anonfield(typs[3])}, nil)
- typs[86] = functype(nil, []ir.Node{anonfield(typs[84]), anonfield(typs[3])}, []ir.Node{anonfield(typs[6])})
+ typs[85] = functype(nil, []*ir.Field{anonfield(typs[84]), anonfield(typs[3])}, nil)
+ typs[86] = functype(nil, []*ir.Field{anonfield(typs[84]), anonfield(typs[3])}, []*ir.Field{anonfield(typs[6])})
typs[87] = types.NewChan(typs[2], types.Csend)
- typs[88] = functype(nil, []ir.Node{anonfield(typs[87]), anonfield(typs[3])}, nil)
+ typs[88] = functype(nil, []*ir.Field{anonfield(typs[87]), anonfield(typs[3])}, nil)
typs[89] = types.NewArray(typs[0], 3)
- typs[90] = tostruct([]ir.Node{namedfield("enabled", typs[6]), namedfield("pad", typs[89]), namedfield("needed", typs[6]), namedfield("cgo", typs[6]), namedfield("alignme", typs[24])})
- typs[91] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[3])}, nil)
- typs[92] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[3])}, nil)
- typs[93] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[15]), anonfield(typs[3]), anonfield(typs[15])}, []ir.Node{anonfield(typs[15])})
- typs[94] = functype(nil, []ir.Node{anonfield(typs[87]), anonfield(typs[3])}, []ir.Node{anonfield(typs[6])})
- typs[95] = functype(nil, []ir.Node{anonfield(typs[3]), anonfield(typs[84])}, []ir.Node{anonfield(typs[6])})
+ typs[90] = tostruct([]*ir.Field{namedfield("enabled", typs[6]), namedfield("pad", typs[89]), namedfield("needed", typs[6]), namedfield("cgo", typs[6]), namedfield("alignme", typs[24])})
+ typs[91] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[3])}, nil)
+ typs[92] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[3])}, nil)
+ typs[93] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[15]), anonfield(typs[3]), anonfield(typs[15])}, []*ir.Field{anonfield(typs[15])})
+ typs[94] = functype(nil, []*ir.Field{anonfield(typs[87]), anonfield(typs[3])}, []*ir.Field{anonfield(typs[6])})
+ typs[95] = functype(nil, []*ir.Field{anonfield(typs[3]), anonfield(typs[84])}, []*ir.Field{anonfield(typs[6])})
typs[96] = types.NewPtr(typs[6])
- typs[97] = functype(nil, []ir.Node{anonfield(typs[3]), anonfield(typs[96]), anonfield(typs[84])}, []ir.Node{anonfield(typs[6])})
- typs[98] = functype(nil, []ir.Node{anonfield(typs[63])}, nil)
- typs[99] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[63]), anonfield(typs[15]), anonfield(typs[15]), anonfield(typs[6])}, []ir.Node{anonfield(typs[15]), anonfield(typs[6])})
- typs[100] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[15])}, []ir.Node{anonfield(typs[7])})
- typs[101] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[22]), anonfield(typs[22])}, []ir.Node{anonfield(typs[7])})
- typs[102] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[15]), anonfield(typs[7])}, []ir.Node{anonfield(typs[7])})
+ typs[97] = functype(nil, []*ir.Field{anonfield(typs[3]), anonfield(typs[96]), anonfield(typs[84])}, []*ir.Field{anonfield(typs[6])})
+ typs[98] = functype(nil, []*ir.Field{anonfield(typs[63])}, nil)
+ typs[99] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[63]), anonfield(typs[15]), anonfield(typs[15]), anonfield(typs[6])}, []*ir.Field{anonfield(typs[15]), anonfield(typs[6])})
+ typs[100] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[15])}, []*ir.Field{anonfield(typs[7])})
+ typs[101] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[22]), anonfield(typs[22])}, []*ir.Field{anonfield(typs[7])})
+ typs[102] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[15]), anonfield(typs[7])}, []*ir.Field{anonfield(typs[7])})
typs[103] = types.NewSlice(typs[2])
- typs[104] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[103]), anonfield(typs[15])}, []ir.Node{anonfield(typs[103])})
- typs[105] = functype(nil, []ir.Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[5])}, nil)
- typs[106] = functype(nil, []ir.Node{anonfield(typs[7]), anonfield(typs[5])}, nil)
- typs[107] = functype(nil, []ir.Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[5])}, []ir.Node{anonfield(typs[6])})
- typs[108] = functype(nil, []ir.Node{anonfield(typs[3]), anonfield(typs[3])}, []ir.Node{anonfield(typs[6])})
- typs[109] = functype(nil, []ir.Node{anonfield(typs[7]), anonfield(typs[7])}, []ir.Node{anonfield(typs[6])})
- typs[110] = functype(nil, []ir.Node{anonfield(typs[7]), anonfield(typs[5]), anonfield(typs[5])}, []ir.Node{anonfield(typs[5])})
- typs[111] = functype(nil, []ir.Node{anonfield(typs[7]), anonfield(typs[5])}, []ir.Node{anonfield(typs[5])})
- typs[112] = functype(nil, []ir.Node{anonfield(typs[22]), anonfield(typs[22])}, []ir.Node{anonfield(typs[22])})
- typs[113] = functype(nil, []ir.Node{anonfield(typs[24]), anonfield(typs[24])}, []ir.Node{anonfield(typs[24])})
- typs[114] = functype(nil, []ir.Node{anonfield(typs[20])}, []ir.Node{anonfield(typs[22])})
- typs[115] = functype(nil, []ir.Node{anonfield(typs[20])}, []ir.Node{anonfield(typs[24])})
- typs[116] = functype(nil, []ir.Node{anonfield(typs[20])}, []ir.Node{anonfield(typs[65])})
- typs[117] = functype(nil, []ir.Node{anonfield(typs[22])}, []ir.Node{anonfield(typs[20])})
- typs[118] = functype(nil, []ir.Node{anonfield(typs[24])}, []ir.Node{anonfield(typs[20])})
- typs[119] = functype(nil, []ir.Node{anonfield(typs[65])}, []ir.Node{anonfield(typs[20])})
- typs[120] = functype(nil, []ir.Node{anonfield(typs[26]), anonfield(typs[26])}, []ir.Node{anonfield(typs[26])})
- typs[121] = functype(nil, []ir.Node{anonfield(typs[5]), anonfield(typs[5])}, nil)
- typs[122] = functype(nil, []ir.Node{anonfield(typs[7]), anonfield(typs[1]), anonfield(typs[5])}, nil)
- typs[123] = types.NewSlice(typs[7])
- typs[124] = functype(nil, []ir.Node{anonfield(typs[7]), anonfield(typs[123])}, nil)
- typs[125] = types.Types[types.TUINT8]
- typs[126] = functype(nil, []ir.Node{anonfield(typs[125]), anonfield(typs[125])}, nil)
- typs[127] = types.Types[types.TUINT16]
- typs[128] = functype(nil, []ir.Node{anonfield(typs[127]), anonfield(typs[127])}, nil)
- typs[129] = functype(nil, []ir.Node{anonfield(typs[65]), anonfield(typs[65])}, nil)
- typs[130] = functype(nil, []ir.Node{anonfield(typs[24]), anonfield(typs[24])}, nil)
+ typs[104] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[103]), anonfield(typs[15])}, []*ir.Field{anonfield(typs[103])})
+ typs[105] = functype(nil, []*ir.Field{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[5])}, nil)
+ typs[106] = functype(nil, []*ir.Field{anonfield(typs[7]), anonfield(typs[5])}, nil)
+ typs[107] = functype(nil, []*ir.Field{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[5])}, []*ir.Field{anonfield(typs[6])})
+ typs[108] = functype(nil, []*ir.Field{anonfield(typs[3]), anonfield(typs[3])}, []*ir.Field{anonfield(typs[6])})
+ typs[109] = functype(nil, []*ir.Field{anonfield(typs[7]), anonfield(typs[7])}, []*ir.Field{anonfield(typs[6])})
+ typs[110] = functype(nil, []*ir.Field{anonfield(typs[7]), anonfield(typs[5]), anonfield(typs[5])}, []*ir.Field{anonfield(typs[5])})
+ typs[111] = functype(nil, []*ir.Field{anonfield(typs[7]), anonfield(typs[5])}, []*ir.Field{anonfield(typs[5])})
+ typs[112] = functype(nil, []*ir.Field{anonfield(typs[22]), anonfield(typs[22])}, []*ir.Field{anonfield(typs[22])})
+ typs[113] = functype(nil, []*ir.Field{anonfield(typs[24]), anonfield(typs[24])}, []*ir.Field{anonfield(typs[24])})
+ typs[114] = functype(nil, []*ir.Field{anonfield(typs[20])}, []*ir.Field{anonfield(typs[22])})
+ typs[115] = functype(nil, []*ir.Field{anonfield(typs[20])}, []*ir.Field{anonfield(typs[24])})
+ typs[116] = functype(nil, []*ir.Field{anonfield(typs[20])}, []*ir.Field{anonfield(typs[65])})
+ typs[117] = functype(nil, []*ir.Field{anonfield(typs[22])}, []*ir.Field{anonfield(typs[20])})
+ typs[118] = functype(nil, []*ir.Field{anonfield(typs[24])}, []*ir.Field{anonfield(typs[20])})
+ typs[119] = functype(nil, []*ir.Field{anonfield(typs[65])}, []*ir.Field{anonfield(typs[20])})
+ typs[120] = functype(nil, []*ir.Field{anonfield(typs[26]), anonfield(typs[26])}, []*ir.Field{anonfield(typs[26])})
+ typs[121] = functype(nil, []*ir.Field{anonfield(typs[5]), anonfield(typs[5])}, nil)
+ typs[122] = functype(nil, []*ir.Field{anonfield(typs[5]), anonfield(typs[5]), anonfield(typs[5])}, nil)
+ typs[123] = functype(nil, []*ir.Field{anonfield(typs[7]), anonfield(typs[1]), anonfield(typs[5])}, nil)
+ typs[124] = types.NewSlice(typs[7])
+ typs[125] = functype(nil, []*ir.Field{anonfield(typs[7]), anonfield(typs[124])}, nil)
+ typs[126] = types.Types[types.TUINT8]
+ typs[127] = functype(nil, []*ir.Field{anonfield(typs[126]), anonfield(typs[126])}, nil)
+ typs[128] = types.Types[types.TUINT16]
+ typs[129] = functype(nil, []*ir.Field{anonfield(typs[128]), anonfield(typs[128])}, nil)
+ typs[130] = functype(nil, []*ir.Field{anonfield(typs[65]), anonfield(typs[65])}, nil)
+ typs[131] = functype(nil, []*ir.Field{anonfield(typs[24]), anonfield(typs[24])}, nil)
return typs[:]
}
diff --git a/src/cmd/compile/internal/gc/builtin/runtime.go b/src/cmd/compile/internal/gc/builtin/runtime.go
index aac2de38c6..acb69c7b28 100644
--- a/src/cmd/compile/internal/gc/builtin/runtime.go
+++ b/src/cmd/compile/internal/gc/builtin/runtime.go
@@ -237,6 +237,7 @@ func racewriterange(addr, size uintptr)
// memory sanitizer
func msanread(addr, size uintptr)
func msanwrite(addr, size uintptr)
+func msanmove(dst, src, size uintptr)
func checkptrAlignment(unsafe.Pointer, *byte, uintptr)
func checkptrArithmetic(unsafe.Pointer, []unsafe.Pointer)
diff --git a/src/cmd/compile/internal/gc/closure.go b/src/cmd/compile/internal/gc/closure.go
index 2901ae41d6..b56e255d10 100644
--- a/src/cmd/compile/internal/gc/closure.go
+++ b/src/cmd/compile/internal/gc/closure.go
@@ -17,28 +17,26 @@ func (p *noder) funcLit(expr *syntax.FuncLit) ir.Node {
xtype := p.typeExpr(expr.Type)
ntype := p.typeExpr(expr.Type)
- dcl := p.nod(expr, ir.ODCLFUNC, nil, nil)
- fn := dcl.Func()
+ fn := ir.NewFunc(p.pos(expr))
fn.SetIsHiddenClosure(Curfn != nil)
- fn.Nname = newfuncnamel(p.pos(expr), ir.BlankNode.Sym(), fn) // filled in by typecheckclosure
- fn.Nname.Name().Param.Ntype = xtype
- fn.Nname.Name().Defn = dcl
+ fn.Nname = newFuncNameAt(p.pos(expr), ir.BlankNode.Sym(), fn) // filled in by typecheckclosure
+ fn.Nname.Ntype = xtype
+ fn.Nname.Defn = fn
- clo := p.nod(expr, ir.OCLOSURE, nil, nil)
- clo.SetFunc(fn)
+ clo := ir.NewClosureExpr(p.pos(expr), fn)
fn.ClosureType = ntype
fn.OClosure = clo
- p.funcBody(dcl, expr.Body)
+ p.funcBody(fn, expr.Body)
// closure-specific variables are hanging off the
// ordinary ones in the symbol table; see oldname.
// unhook them.
// make the list of pointers for the closure call.
- for _, v := range fn.ClosureVars.Slice() {
+ for _, v := range fn.ClosureVars {
// Unlink from v1; see comment in syntax.go type Param for these fields.
- v1 := v.Name().Defn
- v1.Name().Param.Innermost = v.Name().Param.Outer
+ v1 := v.Defn
+ v1.Name().Innermost = v.Outer
// If the closure usage of v is not dense,
// we need to make it dense; now that we're out
@@ -68,7 +66,7 @@ func (p *noder) funcLit(expr *syntax.FuncLit) ir.Node {
// obtains f3's v, creating it if necessary (as it is in the example).
//
// capturevars will decide whether to use v directly or &v.
- v.Name().Param.Outer = oldname(v.Sym())
+ v.Outer = oldname(v.Sym()).(*ir.Name)
}
return clo
@@ -80,30 +78,29 @@ func (p *noder) funcLit(expr *syntax.FuncLit) ir.Node {
// separate pass from type-checking.
func typecheckclosure(clo ir.Node, top int) {
fn := clo.Func()
- dcl := fn.Decl
// Set current associated iota value, so iota can be used inside
// function in ConstSpec, see issue #22344
if x := getIotaValue(); x >= 0 {
- dcl.SetIota(x)
+ fn.SetIota(x)
}
fn.ClosureType = typecheck(fn.ClosureType, ctxType)
clo.SetType(fn.ClosureType.Type())
- fn.ClosureCalled = top&ctxCallee != 0
+ fn.SetClosureCalled(top&ctxCallee != 0)
- // Do not typecheck dcl twice, otherwise, we will end up pushing
- // dcl to xtop multiple times, causing initLSym called twice.
+ // Do not typecheck fn twice, otherwise, we will end up pushing
+ // fn to xtop multiple times, causing initLSym called twice.
// See #30709
- if dcl.Typecheck() == 1 {
+ if fn.Typecheck() == 1 {
return
}
- for _, ln := range fn.ClosureVars.Slice() {
- n := ln.Name().Defn
+ for _, ln := range fn.ClosureVars {
+ n := ln.Defn
if !n.Name().Captured() {
n.Name().SetCaptured(true)
if n.Name().Decldepth == 0 {
- base.Fatalf("typecheckclosure: var %S does not have decldepth assigned", n)
+ base.Fatalf("typecheckclosure: var %v does not have decldepth assigned", n)
}
// Ignore assignments to the variable in straightline code
@@ -116,7 +113,7 @@ func typecheckclosure(clo ir.Node, top int) {
fn.Nname.SetSym(closurename(Curfn))
setNodeNameFunc(fn.Nname)
- dcl = typecheck(dcl, ctxStmt)
+ typecheckFunc(fn)
// Type check the body now, but only if we're inside a function.
// At top level (in a variable initialization: curfn==nil) we're not
@@ -124,29 +121,29 @@ func typecheckclosure(clo ir.Node, top int) {
// underlying closure function we create is added to xtop.
if Curfn != nil && clo.Type() != nil {
oldfn := Curfn
- Curfn = dcl
+ Curfn = fn
olddd := decldepth
decldepth = 1
- typecheckslice(dcl.Body().Slice(), ctxStmt)
+ typecheckslice(fn.Body().Slice(), ctxStmt)
decldepth = olddd
Curfn = oldfn
}
- xtop = append(xtop, dcl)
+ xtop = append(xtop, fn)
}
// globClosgen is like Func.Closgen, but for the global scope.
-var globClosgen int
+var globClosgen int32
// closurename generates a new unique name for a closure within
// outerfunc.
-func closurename(outerfunc ir.Node) *types.Sym {
+func closurename(outerfunc *ir.Func) *types.Sym {
outer := "glob."
prefix := "func"
gen := &globClosgen
if outerfunc != nil {
- if outerfunc.Func().OClosure != nil {
+ if outerfunc.OClosure != nil {
prefix = ""
}
@@ -155,8 +152,8 @@ func closurename(outerfunc ir.Node) *types.Sym {
// There may be multiple functions named "_". In those
// cases, we can't use their individual Closgens as it
// would lead to name clashes.
- if !ir.IsBlank(outerfunc.Func().Nname) {
- gen = &outerfunc.Func().Closgen
+ if !ir.IsBlank(outerfunc.Nname) {
+ gen = &outerfunc.Closgen
}
}
@@ -172,11 +169,10 @@ var capturevarscomplete bool
// by value or by reference.
// We use value capturing for values <= 128 bytes that are never reassigned
// after capturing (effectively constant).
-func capturevars(dcl ir.Node) {
+func capturevars(fn *ir.Func) {
lno := base.Pos
- base.Pos = dcl.Pos()
- fn := dcl.Func()
- cvars := fn.ClosureVars.Slice()
+ base.Pos = fn.Pos()
+ cvars := fn.ClosureVars
out := cvars[:0]
for _, v := range cvars {
if v.Type() == nil {
@@ -194,12 +190,13 @@ func capturevars(dcl ir.Node) {
// so that the outer frame also grabs them and knows they escape.
dowidth(v.Type())
- outer := v.Name().Param.Outer
- outermost := v.Name().Defn
+ var outer ir.Node
+ outer = v.Outer
+ outermost := v.Defn
// out parameters will be assigned to implicitly upon return.
if outermost.Class() != ir.PPARAMOUT && !outermost.Name().Addrtaken() && !outermost.Name().Assigned() && v.Type().Width <= 128 {
- v.Name().SetByval(true)
+ v.SetByval(true)
} else {
outermost.Name().SetAddrtaken(true)
outer = ir.Nod(ir.OADDR, outer, nil)
@@ -207,11 +204,11 @@ func capturevars(dcl ir.Node) {
if base.Flag.LowerM > 1 {
var name *types.Sym
- if v.Name().Curfn != nil && v.Name().Curfn.Func().Nname != nil {
- name = v.Name().Curfn.Func().Nname.Sym()
+ if v.Curfn != nil && v.Curfn.Nname != nil {
+ name = v.Curfn.Sym()
}
how := "ref"
- if v.Name().Byval() {
+ if v.Byval() {
how = "value"
}
base.WarnfAt(v.Pos(), "%v capturing by %s: %v (addr=%v assign=%v width=%d)", name, how, v.Sym(), outermost.Name().Addrtaken(), outermost.Name().Assigned(), int32(v.Type().Width))
@@ -221,18 +218,17 @@ func capturevars(dcl ir.Node) {
fn.ClosureEnter.Append(outer)
}
- fn.ClosureVars.Set(out)
+ fn.ClosureVars = out
base.Pos = lno
}
// transformclosure is called in a separate phase after escape analysis.
// It transform closure bodies to properly reference captured variables.
-func transformclosure(dcl ir.Node) {
+func transformclosure(fn *ir.Func) {
lno := base.Pos
- base.Pos = dcl.Pos()
- fn := dcl.Func()
+ base.Pos = fn.Pos()
- if fn.ClosureCalled {
+ if fn.ClosureCalled() {
// If the closure is directly called, we transform it to a plain function call
// with variables passed as args. This avoids allocation of a closure object.
// Here we do only a part of the transformation. Walk of OCALLFUNC(OCLOSURE)
@@ -253,16 +249,16 @@ func transformclosure(dcl ir.Node) {
// We are going to insert captured variables before input args.
var params []*types.Field
- var decls []ir.Node
- for _, v := range fn.ClosureVars.Slice() {
- if !v.Name().Byval() {
+ var decls []*ir.Name
+ for _, v := range fn.ClosureVars {
+ if !v.Byval() {
// If v of type T is captured by reference,
// we introduce function param &v *T
// and v remains PAUTOHEAP with &v heapaddr
// (accesses will implicitly deref &v).
addr := NewName(lookup("&" + v.Sym().Name))
addr.SetType(types.NewPtr(v.Type()))
- v.Name().Param.Heapaddr = addr
+ v.Heapaddr = addr
v = addr
}
@@ -281,42 +277,41 @@ func transformclosure(dcl ir.Node) {
}
dowidth(f.Type())
- dcl.SetType(f.Type()) // update type of ODCLFUNC
+ fn.SetType(f.Type()) // update type of ODCLFUNC
} else {
// The closure is not called, so it is going to stay as closure.
var body []ir.Node
offset := int64(Widthptr)
- for _, v := range fn.ClosureVars.Slice() {
+ for _, v := range fn.ClosureVars {
// cv refers to the field inside of closure OSTRUCTLIT.
- cv := ir.Nod(ir.OCLOSUREVAR, nil, nil)
-
- cv.SetType(v.Type())
- if !v.Name().Byval() {
- cv.SetType(types.NewPtr(v.Type()))
+ typ := v.Type()
+ if !v.Byval() {
+ typ = types.NewPtr(typ)
}
- offset = Rnd(offset, int64(cv.Type().Align))
- cv.SetOffset(offset)
- offset += cv.Type().Width
+ offset = Rnd(offset, int64(typ.Align))
+ cr := ir.NewClosureRead(typ, offset)
+ offset += typ.Width
- if v.Name().Byval() && v.Type().Width <= int64(2*Widthptr) {
+ if v.Byval() && v.Type().Width <= int64(2*Widthptr) {
// If it is a small variable captured by value, downgrade it to PAUTO.
v.SetClass(ir.PAUTO)
fn.Dcl = append(fn.Dcl, v)
- body = append(body, ir.Nod(ir.OAS, v, cv))
+ body = append(body, ir.Nod(ir.OAS, v, cr))
} else {
// Declare variable holding addresses taken from closure
// and initialize in entry prologue.
addr := NewName(lookup("&" + v.Sym().Name))
addr.SetType(types.NewPtr(v.Type()))
addr.SetClass(ir.PAUTO)
- addr.Name().SetUsed(true)
- addr.Name().Curfn = dcl
+ addr.SetUsed(true)
+ addr.Curfn = fn
fn.Dcl = append(fn.Dcl, addr)
- v.Name().Param.Heapaddr = addr
- if v.Name().Byval() {
- cv = ir.Nod(ir.OADDR, cv, nil)
+ v.Heapaddr = addr
+ var src ir.Node = cr
+ if v.Byval() {
+ src = ir.Nod(ir.OADDR, cr, nil)
}
- body = append(body, ir.Nod(ir.OAS, addr, cv))
+ body = append(body, ir.Nod(ir.OAS, addr, src))
}
}
@@ -333,7 +328,7 @@ func transformclosure(dcl ir.Node) {
// hasemptycvars reports whether closure clo has an
// empty list of captured vars.
func hasemptycvars(clo ir.Node) bool {
- return clo.Func().ClosureVars.Len() == 0
+ return len(clo.Func().ClosureVars) == 0
}
// closuredebugruntimecheck applies boilerplate checks for debug flags
@@ -368,12 +363,12 @@ func closureType(clo ir.Node) *types.Type {
// The information appears in the binary in the form of type descriptors;
// the struct is unnamed so that closures in multiple packages with the
// same struct type can share the descriptor.
- fields := []ir.Node{
+ fields := []*ir.Field{
namedfield(".F", types.Types[types.TUINTPTR]),
}
- for _, v := range clo.Func().ClosureVars.Slice() {
+ for _, v := range clo.Func().ClosureVars {
typ := v.Type()
- if !v.Name().Byval() {
+ if !v.Byval() {
typ = types.NewPtr(typ)
}
fields = append(fields, symfield(v.Sym(), typ))
@@ -397,7 +392,7 @@ func walkclosure(clo ir.Node, init *ir.Nodes) ir.Node {
typ := closureType(clo)
- clos := ir.Nod(ir.OCOMPLIT, nil, typenod(typ))
+ clos := ir.Nod(ir.OCOMPLIT, nil, ir.TypeNode(typ))
clos.SetEsc(clo.Esc())
clos.PtrList().Set(append([]ir.Node{ir.Nod(ir.OCFUNC, fn.Nname, nil)}, fn.ClosureEnter.Slice()...))
@@ -419,7 +414,7 @@ func walkclosure(clo ir.Node, init *ir.Nodes) ir.Node {
return walkexpr(clos, init)
}
-func typecheckpartialcall(dot ir.Node, sym *types.Sym) {
+func typecheckpartialcall(dot ir.Node, sym *types.Sym) *ir.CallPartExpr {
switch dot.Op() {
case ir.ODOTINTER, ir.ODOTMETH:
break
@@ -429,23 +424,20 @@ func typecheckpartialcall(dot ir.Node, sym *types.Sym) {
}
// Create top-level function.
- dcl := makepartialcall(dot, dot.Type(), sym)
- dcl.Func().SetWrapper(true)
- dot.SetOp(ir.OCALLPART)
- dot.SetRight(NewName(sym))
- dot.SetType(dcl.Type())
- dot.SetFunc(dcl.Func())
- dot.SetOpt(nil) // clear types.Field from ODOTMETH
+ fn := makepartialcall(dot, dot.Type(), sym)
+ fn.SetWrapper(true)
+
+ return ir.NewCallPartExpr(dot.Pos(), dot.Left(), dot.(*ir.SelectorExpr).Selection, fn)
}
// makepartialcall returns a DCLFUNC node representing the wrapper function (*-fm) needed
// for partial calls.
-func makepartialcall(dot ir.Node, t0 *types.Type, meth *types.Sym) ir.Node {
+func makepartialcall(dot ir.Node, t0 *types.Type, meth *types.Sym) *ir.Func {
rcvrtype := dot.Left().Type()
sym := methodSymSuffix(rcvrtype, meth, "-fm")
if sym.Uniq() {
- return ir.AsNode(sym.Def)
+ return sym.Def.(*ir.Func)
}
sym.SetUniq(true)
@@ -464,33 +456,26 @@ func makepartialcall(dot ir.Node, t0 *types.Type, meth *types.Sym) ir.Node {
// number at the use of the method expression in this
// case. See issue 29389.
- tfn := ir.Nod(ir.OTFUNC, nil, nil)
- tfn.PtrList().Set(structargs(t0.Params(), true))
- tfn.PtrRlist().Set(structargs(t0.Results(), false))
+ tfn := ir.NewFuncType(base.Pos, nil,
+ structargs(t0.Params(), true),
+ structargs(t0.Results(), false))
- dcl := dclfunc(sym, tfn)
- fn := dcl.Func()
+ fn := dclfunc(sym, tfn)
fn.SetDupok(true)
fn.SetNeedctxt(true)
- tfn.Type().SetPkg(t0.Pkg())
-
// Declare and initialize variable holding receiver.
-
- cv := ir.Nod(ir.OCLOSUREVAR, nil, nil)
- cv.SetType(rcvrtype)
- cv.SetOffset(Rnd(int64(Widthptr), int64(cv.Type().Align)))
-
+ cr := ir.NewClosureRead(rcvrtype, Rnd(int64(Widthptr), int64(rcvrtype.Align)))
ptr := NewName(lookup(".this"))
declare(ptr, ir.PAUTO)
- ptr.Name().SetUsed(true)
+ ptr.SetUsed(true)
var body []ir.Node
if rcvrtype.IsPtr() || rcvrtype.IsInterface() {
ptr.SetType(rcvrtype)
- body = append(body, ir.Nod(ir.OAS, ptr, cv))
+ body = append(body, ir.Nod(ir.OAS, ptr, cr))
} else {
ptr.SetType(types.NewPtr(rcvrtype))
- body = append(body, ir.Nod(ir.OAS, ptr, ir.Nod(ir.OADDR, cv, nil)))
+ body = append(body, ir.Nod(ir.OAS, ptr, ir.Nod(ir.OADDR, cr, nil)))
}
call := ir.Nod(ir.OCALL, nodSym(ir.OXDOT, ptr, meth), nil)
@@ -503,27 +488,27 @@ func makepartialcall(dot ir.Node, t0 *types.Type, meth *types.Sym) ir.Node {
}
body = append(body, call)
- dcl.PtrBody().Set(body)
+ fn.PtrBody().Set(body)
funcbody()
- dcl = typecheck(dcl, ctxStmt)
+ typecheckFunc(fn)
// Need to typecheck the body of the just-generated wrapper.
// typecheckslice() requires that Curfn is set when processing an ORETURN.
- Curfn = dcl
- typecheckslice(dcl.Body().Slice(), ctxStmt)
- sym.Def = dcl
- xtop = append(xtop, dcl)
+ Curfn = fn
+ typecheckslice(fn.Body().Slice(), ctxStmt)
+ sym.Def = fn
+ xtop = append(xtop, fn)
Curfn = savecurfn
base.Pos = saveLineNo
- return dcl
+ return fn
}
// partialCallType returns the struct type used to hold all the information
// needed in the closure for n (n must be a OCALLPART node).
// The address of a variable of the returned type can be cast to a func.
func partialCallType(n ir.Node) *types.Type {
- t := tostruct([]ir.Node{
+ t := tostruct([]*ir.Field{
namedfield("F", types.Types[types.TUINTPTR]),
namedfield("R", n.Left().Type()),
})
@@ -531,7 +516,7 @@ func partialCallType(n ir.Node) *types.Type {
return t
}
-func walkpartialcall(n ir.Node, init *ir.Nodes) ir.Node {
+func walkpartialcall(n *ir.CallPartExpr, init *ir.Nodes) ir.Node {
// Create closure in the form of a composite literal.
// For x.M with receiver (x) type T, the generated code looks like:
//
@@ -555,7 +540,7 @@ func walkpartialcall(n ir.Node, init *ir.Nodes) ir.Node {
typ := partialCallType(n)
- clos := ir.Nod(ir.OCOMPLIT, nil, typenod(typ))
+ clos := ir.Nod(ir.OCOMPLIT, nil, ir.TypeNode(typ))
clos.SetEsc(n.Esc())
clos.PtrList().Set2(ir.Nod(ir.OCFUNC, n.Func().Nname, nil), n.Left())
@@ -580,16 +565,5 @@ func walkpartialcall(n ir.Node, init *ir.Nodes) ir.Node {
// callpartMethod returns the *types.Field representing the method
// referenced by method value n.
func callpartMethod(n ir.Node) *types.Field {
- if n.Op() != ir.OCALLPART {
- base.Fatalf("expected OCALLPART, got %v", n)
- }
-
- // TODO(mdempsky): Optimize this. If necessary,
- // makepartialcall could save m for us somewhere.
- var m *types.Field
- if lookdot0(n.Right().Sym(), n.Left().Type(), &m, false) != 1 {
- base.Fatalf("failed to find field for OCALLPART")
- }
-
- return m
+ return n.(*ir.CallPartExpr).Method
}
diff --git a/src/cmd/compile/internal/gc/const.go b/src/cmd/compile/internal/gc/const.go
index 4beb85245f..677ed17dd9 100644
--- a/src/cmd/compile/internal/gc/const.go
+++ b/src/cmd/compile/internal/gc/const.go
@@ -115,17 +115,12 @@ func convlit1(n ir.Node, t *types.Type, explicit bool, context func() string) ir
return n
}
- if n.Op() == ir.OLITERAL || n.Op() == ir.ONIL {
- // Can't always set n.Type directly on OLITERAL nodes.
- // See discussion on CL 20813.
- n = n.RawCopy()
- }
-
// Nil is technically not a constant, so handle it specially.
- if n.Type().Etype == types.TNIL {
+ if n.Type().Kind() == types.TNIL {
if n.Op() != ir.ONIL {
base.Fatalf("unexpected op: %v (%v)", n, n.Op())
}
+ n = ir.Copy(n)
if t == nil {
base.Errorf("use of untyped nil")
n.SetDiag(true)
@@ -142,7 +137,7 @@ func convlit1(n ir.Node, t *types.Type, explicit bool, context func() string) ir
return n
}
- if t == nil || !ir.OKForConst[t.Etype] {
+ if t == nil || !ir.OKForConst[t.Kind()] {
t = defaultType(n.Type())
}
@@ -153,10 +148,11 @@ func convlit1(n ir.Node, t *types.Type, explicit bool, context func() string) ir
case ir.OLITERAL:
v := convertVal(n.Val(), t, explicit)
if v.Kind() == constant.Unknown {
+ n = ir.NewConstExpr(n.Val(), n)
break
}
+ n = ir.NewConstExpr(v, n)
n.SetType(t)
- n.SetVal(v)
return n
case ir.OPLUS, ir.ONEG, ir.OBITNOT, ir.ONOT, ir.OREAL, ir.OIMAG:
@@ -240,7 +236,7 @@ func operandType(op ir.Op, t *types.Type) *types.Type {
return complexForFloat(t)
}
default:
- if okfor[op][t.Etype] {
+ if okfor[op][t.Kind()] {
return t
}
}
@@ -388,7 +384,7 @@ func overflow(v constant.Value, t *types.Type) bool {
return true
}
if doesoverflow(v, t) {
- base.Errorf("constant %v overflows %v", ir.FmtConst(v, 0), t)
+ base.Errorf("constant %v overflows %v", types.FmtConst(v, false), t)
return true
}
return false
@@ -494,12 +490,12 @@ func evalConst(n ir.Node) ir.Node {
}
case ir.OCONV, ir.ORUNESTR:
- if ir.OKForConst[n.Type().Etype] && nl.Op() == ir.OLITERAL {
+ if ir.OKForConst[n.Type().Kind()] && nl.Op() == ir.OLITERAL {
return origConst(n, convertVal(nl.Val(), n.Type(), true))
}
case ir.OCONVNOP:
- if ir.OKForConst[n.Type().Etype] && nl.Op() == ir.OLITERAL {
+ if ir.OKForConst[n.Type().Kind()] && nl.Op() == ir.OLITERAL {
// set so n.Orig gets OCONV instead of OCONVNOP
n.SetOp(ir.OCONV)
return origConst(n, nl.Val())
@@ -521,7 +517,7 @@ func evalConst(n ir.Node) ir.Node {
if need == 1 {
var strs []string
for _, c := range s {
- strs = append(strs, c.StringVal())
+ strs = append(strs, ir.StringVal(c))
}
return origConst(n, constant.MakeString(strings.Join(strs, "")))
}
@@ -532,12 +528,13 @@ func evalConst(n ir.Node) ir.Node {
var strs []string
i2 := i
for i2 < len(s) && ir.IsConst(s[i2], constant.String) {
- strs = append(strs, s[i2].StringVal())
+ strs = append(strs, ir.StringVal(s[i2]))
i2++
}
- nl := origConst(s[i], constant.MakeString(strings.Join(strs, "")))
- nl.SetOrig(nl) // it's bigger than just s[i]
+ nl := ir.Copy(n)
+ nl.PtrList().Set(s[i:i2])
+ nl = origConst(nl, constant.MakeString(strings.Join(strs, "")))
newList = append(newList, nl)
i = i2 - 1
} else {
@@ -550,13 +547,13 @@ func evalConst(n ir.Node) ir.Node {
return n
case ir.OCAP, ir.OLEN:
- switch nl.Type().Etype {
+ switch nl.Type().Kind() {
case types.TSTRING:
if ir.IsConst(nl, constant.String) {
- return origIntConst(n, int64(len(nl.StringVal())))
+ return origIntConst(n, int64(len(ir.StringVal(nl))))
}
case types.TARRAY:
- if !hascallchan(nl) {
+ if !hasCallOrChan(nl) {
return origIntConst(n, nl.Type().NumElem())
}
}
@@ -640,12 +637,7 @@ func origConst(n ir.Node, v constant.Value) ir.Node {
return n
}
- orig := n
- n = ir.NodAt(orig.Pos(), ir.OLITERAL, nil, nil)
- n.SetOrig(orig)
- n.SetType(orig.Type())
- n.SetVal(v)
- return n
+ return ir.NewConstExpr(v, n)
}
func origBoolConst(n ir.Node, v bool) ir.Node {
@@ -724,7 +716,7 @@ func mixUntyped(t1, t2 *types.Type) *types.Type {
}
func defaultType(t *types.Type) *types.Type {
- if !t.IsUntyped() || t.Etype == types.TNIL {
+ if !t.IsUntyped() || t.Kind() == types.TNIL {
return t
}
@@ -736,7 +728,7 @@ func defaultType(t *types.Type) *types.Type {
case types.UntypedInt:
return types.Types[types.TINT]
case types.UntypedRune:
- return types.Runetype
+ return types.RuneType
case types.UntypedFloat:
return types.Types[types.TFLOAT64]
case types.UntypedComplex:
@@ -764,7 +756,7 @@ func indexconst(n ir.Node) int64 {
if n.Op() != ir.OLITERAL {
return -1
}
- if !n.Type().IsInteger() && n.Type().Etype != types.TIDEAL {
+ if !n.Type().IsInteger() && n.Type().Kind() != types.TIDEAL {
return -1
}
@@ -775,7 +767,7 @@ func indexconst(n ir.Node) int64 {
if doesoverflow(v, types.Types[types.TINT]) {
return -2
}
- return ir.Int64Val(types.Types[types.TINT], v)
+ return ir.IntVal(types.Types[types.TINT], v)
}
// isGoConst reports whether n is a Go language constant (as opposed to a
@@ -787,49 +779,35 @@ func isGoConst(n ir.Node) bool {
return n.Op() == ir.OLITERAL
}
-func hascallchan(n ir.Node) bool {
- if n == nil {
- return false
- }
- switch n.Op() {
- case ir.OAPPEND,
- ir.OCALL,
- ir.OCALLFUNC,
- ir.OCALLINTER,
- ir.OCALLMETH,
- ir.OCAP,
- ir.OCLOSE,
- ir.OCOMPLEX,
- ir.OCOPY,
- ir.ODELETE,
- ir.OIMAG,
- ir.OLEN,
- ir.OMAKE,
- ir.ONEW,
- ir.OPANIC,
- ir.OPRINT,
- ir.OPRINTN,
- ir.OREAL,
- ir.ORECOVER,
- ir.ORECV:
- return true
- }
-
- if hascallchan(n.Left()) || hascallchan(n.Right()) {
- return true
- }
- for _, n1 := range n.List().Slice() {
- if hascallchan(n1) {
- return true
+// hasCallOrChan reports whether n contains any calls or channel operations.
+func hasCallOrChan(n ir.Node) bool {
+ found := ir.Find(n, func(n ir.Node) interface{} {
+ switch n.Op() {
+ case ir.OAPPEND,
+ ir.OCALL,
+ ir.OCALLFUNC,
+ ir.OCALLINTER,
+ ir.OCALLMETH,
+ ir.OCAP,
+ ir.OCLOSE,
+ ir.OCOMPLEX,
+ ir.OCOPY,
+ ir.ODELETE,
+ ir.OIMAG,
+ ir.OLEN,
+ ir.OMAKE,
+ ir.ONEW,
+ ir.OPANIC,
+ ir.OPRINT,
+ ir.OPRINTN,
+ ir.OREAL,
+ ir.ORECOVER,
+ ir.ORECV:
+ return n
}
- }
- for _, n2 := range n.Rlist().Slice() {
- if hascallchan(n2) {
- return true
- }
- }
-
- return false
+ return nil
+ })
+ return found != nil
}
// A constSet represents a set of Go constant expressions.
@@ -880,9 +858,9 @@ func (s *constSet) add(pos src.XPos, n ir.Node, what, where string) {
typ := n.Type()
switch typ {
- case types.Bytetype:
+ case types.ByteType:
typ = types.Types[types.TUINT8]
- case types.Runetype:
+ case types.RuneType:
typ = types.Types[types.TINT32]
}
k := constSetKey{typ, ir.ConstValue(n)}
@@ -909,7 +887,7 @@ func (s *constSet) add(pos src.XPos, n ir.Node, what, where string) {
//
// TODO(mdempsky): This could probably be a fmt.go flag.
func nodeAndVal(n ir.Node) string {
- show := n.String()
+ show := fmt.Sprint(n)
val := ir.ConstValue(n)
if s := fmt.Sprintf("%#v", val); show != s {
show += " (value " + s + ")"
diff --git a/src/cmd/compile/internal/gc/dcl.go b/src/cmd/compile/internal/gc/dcl.go
index 2a7be137c0..1ebadd9213 100644
--- a/src/cmd/compile/internal/gc/dcl.go
+++ b/src/cmd/compile/internal/gc/dcl.go
@@ -12,7 +12,6 @@ import (
"cmd/internal/obj"
"cmd/internal/src"
"fmt"
- "go/constant"
"strings"
)
@@ -59,20 +58,15 @@ var declare_typegen int
// declare records that Node n declares symbol n.Sym in the specified
// declaration context.
-func declare(n ir.Node, ctxt ir.Class) {
+func declare(n *ir.Name, ctxt ir.Class) {
if ir.IsBlank(n) {
return
}
- if n.Name() == nil {
- // named OLITERAL needs Name; most OLITERALs don't.
- n.SetName(new(ir.Name))
- }
-
s := n.Sym()
// kludgy: typecheckok means we're past parsing. Eg genwrapper may declare out of package names later.
- if !inimport && !typecheckok && s.Pkg != ir.LocalPkg {
+ if !inimport && !typecheckok && s.Pkg != types.LocalPkg {
base.ErrorfAt(n.Pos(), "cannot declare name %v", s)
}
@@ -90,8 +84,8 @@ func declare(n ir.Node, ctxt ir.Class) {
base.Pos = n.Pos()
base.Fatalf("automatic outside function")
}
- if Curfn != nil && ctxt != ir.PFUNC {
- Curfn.Func().Dcl = append(Curfn.Func().Dcl, n)
+ if Curfn != nil && ctxt != ir.PFUNC && n.Op() == ir.ONAME {
+ Curfn.Dcl = append(Curfn.Dcl, n)
}
if n.Op() == ir.OTYPE {
declare_typegen++
@@ -101,7 +95,7 @@ func declare(n ir.Node, ctxt ir.Class) {
gen = vargen
}
types.Pushdcl(s)
- n.Name().Curfn = Curfn
+ n.Curfn = Curfn
}
if ctxt == ir.PAUTO {
@@ -119,7 +113,7 @@ func declare(n ir.Node, ctxt ir.Class) {
s.Block = types.Block
s.Lastlineno = base.Pos
s.Def = n
- n.Name().Vargen = int32(gen)
+ n.Vargen = int32(gen)
n.SetClass(ctxt)
if ctxt == ir.PFUNC {
n.Sym().SetFunc(true)
@@ -128,19 +122,9 @@ func declare(n ir.Node, ctxt ir.Class) {
autoexport(n, ctxt)
}
-func addvar(n ir.Node, t *types.Type, ctxt ir.Class) {
- if n == nil || n.Sym() == nil || (n.Op() != ir.ONAME && n.Op() != ir.ONONAME) || t == nil {
- base.Fatalf("addvar: n=%v t=%v nil", n, t)
- }
-
- n.SetOp(ir.ONAME)
- declare(n, ctxt)
- n.SetType(t)
-}
-
// declare variables from grammar
// new_name_list (type | [type] = expr_list)
-func variter(vl []ir.Node, t ir.Node, el []ir.Node) []ir.Node {
+func variter(vl []ir.Node, t ir.Ntype, el []ir.Node) []ir.Node {
var init []ir.Node
doexpr := len(el) > 0
@@ -150,10 +134,11 @@ func variter(vl []ir.Node, t ir.Node, el []ir.Node) []ir.Node {
as2.PtrList().Set(vl)
as2.PtrRlist().Set1(e)
for _, v := range vl {
+ v := v.(*ir.Name)
v.SetOp(ir.ONAME)
declare(v, dclcontext)
- v.Name().Param.Ntype = t
- v.Name().Defn = as2
+ v.Ntype = t
+ v.Defn = as2
if Curfn != nil {
init = append(init, ir.Nod(ir.ODCL, v, nil))
}
@@ -164,6 +149,7 @@ func variter(vl []ir.Node, t ir.Node, el []ir.Node) []ir.Node {
nel := len(el)
for _, v := range vl {
+ v := v.(*ir.Name)
var e ir.Node
if doexpr {
if len(el) == 0 {
@@ -176,7 +162,7 @@ func variter(vl []ir.Node, t ir.Node, el []ir.Node) []ir.Node {
v.SetOp(ir.ONAME)
declare(v, dclcontext)
- v.Name().Param.Ntype = t
+ v.Ntype = t
if e != nil || Curfn != nil || ir.IsBlank(v) {
if Curfn != nil {
@@ -185,7 +171,7 @@ func variter(vl []ir.Node, t ir.Node, el []ir.Node) []ir.Node {
e = ir.Nod(ir.OAS, v, e)
init = append(init, e)
if e.Right() != nil {
- v.Name().Defn = e
+ v.Defn = e
}
}
}
@@ -196,21 +182,10 @@ func variter(vl []ir.Node, t ir.Node, el []ir.Node) []ir.Node {
return init
}
-// newnoname returns a new ONONAME Node associated with symbol s.
-func newnoname(s *types.Sym) ir.Node {
- if s == nil {
- base.Fatalf("newnoname nil")
- }
- n := ir.Nod(ir.ONONAME, nil, nil)
- n.SetSym(s)
- n.SetOffset(0)
- return n
-}
-
-// newfuncnamel generates a new name node for a function or method.
-func newfuncnamel(pos src.XPos, s *types.Sym, fn *ir.Func) ir.Node {
+// newFuncNameAt generates a new name node for a function or method.
+func newFuncNameAt(pos src.XPos, s *types.Sym, fn *ir.Func) *ir.Name {
if fn.Nname != nil {
- base.Fatalf("newfuncnamel - already have name")
+ base.Fatalf("newFuncName - already have name")
}
n := ir.NewNameAt(pos, s)
n.SetFunc(fn)
@@ -218,43 +193,16 @@ func newfuncnamel(pos src.XPos, s *types.Sym, fn *ir.Func) ir.Node {
return n
}
-// this generates a new name node for a name
-// being declared.
-func dclname(s *types.Sym) ir.Node {
- n := NewName(s)
- n.SetOp(ir.ONONAME) // caller will correct it
- return n
-}
-
-func typenod(t *types.Type) ir.Node {
- return typenodl(src.NoXPos, t)
-}
-
-func typenodl(pos src.XPos, t *types.Type) ir.Node {
- // if we copied another type with *t = *u
- // then t->nod might be out of date, so
- // check t->nod->type too
- if ir.AsNode(t.Nod) == nil || ir.AsNode(t.Nod).Type() != t {
- t.Nod = ir.NodAt(pos, ir.OTYPE, nil, nil)
- ir.AsNode(t.Nod).SetType(t)
- ir.AsNode(t.Nod).SetSym(t.Sym)
- }
-
- return ir.AsNode(t.Nod)
-}
-
-func anonfield(typ *types.Type) ir.Node {
+func anonfield(typ *types.Type) *ir.Field {
return symfield(nil, typ)
}
-func namedfield(s string, typ *types.Type) ir.Node {
+func namedfield(s string, typ *types.Type) *ir.Field {
return symfield(lookup(s), typ)
}
-func symfield(s *types.Sym, typ *types.Type) ir.Node {
- n := nodSym(ir.ODCLFIELD, nil, s)
- n.SetType(typ)
- return n
+func symfield(s *types.Sym, typ *types.Type) *ir.Field {
+ return ir.NewField(base.Pos, s, nil, typ)
}
// oldname returns the Node that declares symbol s in the current scope.
@@ -267,7 +215,7 @@ func oldname(s *types.Sym) ir.Node {
// Maybe a top-level declaration will come along later to
// define s. resolve will check s.Def again once all input
// source has been processed.
- return newnoname(s)
+ return ir.NewIdent(base.Pos, s)
}
if Curfn != nil && n.Op() == ir.ONAME && n.Name().Curfn != nil && n.Name().Curfn != Curfn {
@@ -277,21 +225,21 @@ func oldname(s *types.Sym) ir.Node {
// are parsing x := 5 inside the closure, until we get to
// the := it looks like a reference to the outer x so we'll
// make x a closure variable unnecessarily.
- c := n.Name().Param.Innermost
- if c == nil || c.Name().Curfn != Curfn {
+ c := n.Name().Innermost
+ if c == nil || c.Curfn != Curfn {
// Do not have a closure var for the active closure yet; make one.
c = NewName(s)
c.SetClass(ir.PAUTOHEAP)
- c.Name().SetIsClosureVar(true)
+ c.SetIsClosureVar(true)
c.SetIsDDD(n.IsDDD())
- c.Name().Defn = n
+ c.Defn = n
// Link into list of active closure variables.
// Popped from list in func funcLit.
- c.Name().Param.Outer = n.Name().Param.Innermost
- n.Name().Param.Innermost = c
+ c.Outer = n.Name().Innermost
+ n.Name().Innermost = c
- Curfn.Func().ClosureVars.Append(c)
+ Curfn.ClosureVars = append(Curfn.ClosureVars, c)
}
// return ref to closure var, not original
@@ -301,10 +249,11 @@ func oldname(s *types.Sym) ir.Node {
return n
}
-// importName is like oldname, but it reports an error if sym is from another package and not exported.
+// importName is like oldname,
+// but it reports an error if sym is from another package and not exported.
func importName(sym *types.Sym) ir.Node {
n := oldname(sym)
- if !types.IsExported(sym.Name) && sym.Pkg != ir.LocalPkg {
+ if !types.IsExported(sym.Name) && sym.Pkg != types.LocalPkg {
n.SetDiag(true)
base.Errorf("cannot refer to unexported name %s.%s", sym.Pkg.Name, sym.Name)
}
@@ -356,9 +305,9 @@ func colasdefn(left []ir.Node, defn ir.Node) {
}
nnew++
- n = NewName(n.Sym())
+ n := NewName(n.Sym())
declare(n, dclcontext)
- n.Name().Defn = defn
+ n.Defn = defn
defn.PtrInit().Append(ir.Nod(ir.ODCL, n, nil))
left[i] = n
}
@@ -368,38 +317,26 @@ func colasdefn(left []ir.Node, defn ir.Node) {
}
}
-// declare the arguments in an
-// interface field declaration.
-func ifacedcl(n ir.Node) {
- if n.Op() != ir.ODCLFIELD || n.Left() == nil {
- base.Fatalf("ifacedcl")
- }
-
- if n.Sym().IsBlank() {
- base.Errorf("methods must have a unique non-blank name")
- }
-}
-
// declare the function proper
// and declare the arguments.
// called in extern-declaration context
// returns in auto-declaration context.
-func funchdr(n ir.Node) {
+func funchdr(fn *ir.Func) {
// change the declaration context from extern to auto
funcStack = append(funcStack, funcStackEnt{Curfn, dclcontext})
- Curfn = n
+ Curfn = fn
dclcontext = ir.PAUTO
types.Markdcl()
- if n.Func().Nname != nil && n.Func().Nname.Name().Param.Ntype != nil {
- funcargs(n.Func().Nname.Name().Param.Ntype)
+ if fn.Nname.Ntype != nil {
+ funcargs(fn.Nname.Ntype.(*ir.FuncType))
} else {
- funcargs2(n.Type())
+ funcargs2(fn.Type())
}
}
-func funcargs(nt ir.Node) {
+func funcargs(nt *ir.FuncType) {
if nt.Op() != ir.OTFUNC {
base.Fatalf("funcargs %v", nt.Op())
}
@@ -411,13 +348,13 @@ func funcargs(nt ir.Node) {
// TODO(mdempsky): This is ugly, and only necessary because
// esc.go uses Vargen to figure out result parameters' index
// within the result tuple.
- vargen = nt.Rlist().Len()
+ vargen = len(nt.Results)
// declare the receiver and in arguments.
- if nt.Left() != nil {
- funcarg(nt.Left(), ir.PPARAM)
+ if nt.Recv != nil {
+ funcarg(nt.Recv, ir.PPARAM)
}
- for _, n := range nt.List().Slice() {
+ for _, n := range nt.Params {
funcarg(n, ir.PPARAM)
}
@@ -425,21 +362,21 @@ func funcargs(nt ir.Node) {
vargen = 0
// declare the out arguments.
- gen := nt.List().Len()
- for _, n := range nt.Rlist().Slice() {
- if n.Sym() == nil {
+ gen := len(nt.Params)
+ for _, n := range nt.Results {
+ if n.Sym == nil {
// Name so that escape analysis can track it. ~r stands for 'result'.
- n.SetSym(lookupN("~r", gen))
+ n.Sym = lookupN("~r", gen)
gen++
}
- if n.Sym().IsBlank() {
+ if n.Sym.IsBlank() {
// Give it a name so we can assign to it during return. ~b stands for 'blank'.
// The name must be different from ~r above because if you have
// func f() (_ int)
// func g() int
// f is allowed to use a plain 'return' with no arguments, while g is not.
// So the two cases must be distinguished.
- n.SetSym(lookupN("~b", gen))
+ n.Sym = lookupN("~b", gen)
gen++
}
@@ -449,28 +386,26 @@ func funcargs(nt ir.Node) {
vargen = oldvargen
}
-func funcarg(n ir.Node, ctxt ir.Class) {
- if n.Op() != ir.ODCLFIELD {
- base.Fatalf("funcarg %v", n.Op())
- }
- if n.Sym() == nil {
+func funcarg(n *ir.Field, ctxt ir.Class) {
+ if n.Sym == nil {
return
}
- n.SetRight(ir.NewNameAt(n.Pos(), n.Sym()))
- n.Right().Name().Param.Ntype = n.Left()
- n.Right().SetIsDDD(n.IsDDD())
- declare(n.Right(), ctxt)
+ name := ir.NewNameAt(n.Pos, n.Sym)
+ n.Decl = name
+ name.Ntype = n.Ntype
+ name.SetIsDDD(n.IsDDD)
+ declare(name, ctxt)
vargen++
- n.Right().Name().Vargen = int32(vargen)
+ n.Decl.Vargen = int32(vargen)
}
// Same as funcargs, except run over an already constructed TFUNC.
// This happens during import, where the hidden_fndcl rule has
// used functype directly to parse the function's type.
func funcargs2(t *types.Type) {
- if t.Etype != types.TFUNC {
+ if t.Kind() != types.TFUNC {
base.Fatalf("funcargs2 %v", t)
}
@@ -499,7 +434,7 @@ func funcarg2(f *types.Field, ctxt ir.Class) {
var funcStack []funcStackEnt // stack of previous values of Curfn/dclcontext
type funcStackEnt struct {
- curfn ir.Node
+ curfn *ir.Func
dclcontext ir.Class
}
@@ -521,7 +456,7 @@ func checkembeddedtype(t *types.Type) {
return
}
- if t.Sym == nil && t.IsPtr() {
+ if t.Sym() == nil && t.IsPtr() {
t = t.Elem()
if t.IsInterface() {
base.Errorf("embedded type cannot be a pointer to interface")
@@ -530,38 +465,11 @@ func checkembeddedtype(t *types.Type) {
if t.IsPtr() || t.IsUnsafePtr() {
base.Errorf("embedded type cannot be a pointer")
- } else if t.Etype == types.TFORW && !t.ForwardType().Embedlineno.IsKnown() {
+ } else if t.Kind() == types.TFORW && !t.ForwardType().Embedlineno.IsKnown() {
t.ForwardType().Embedlineno = base.Pos
}
}
-func structfield(n ir.Node) *types.Field {
- lno := base.Pos
- base.Pos = n.Pos()
-
- if n.Op() != ir.ODCLFIELD {
- base.Fatalf("structfield: oops %v\n", n)
- }
-
- if n.Left() != nil {
- n.SetLeft(typecheck(n.Left(), ctxType))
- n.SetType(n.Left().Type())
- n.SetLeft(nil)
- }
-
- f := types.NewField(n.Pos(), n.Sym(), n.Type())
- if n.Embedded() {
- checkembeddedtype(n.Type())
- f.Embedded = 1
- }
- if n.HasVal() {
- f.Note = constant.StringVal(n.Val())
- }
-
- base.Pos = lno
- return f
-}
-
// checkdupfields emits errors for duplicately named fields or methods in
// a list of struct or interface types.
func checkdupfields(what string, fss ...[]*types.Field) {
@@ -582,103 +490,53 @@ func checkdupfields(what string, fss ...[]*types.Field) {
// convert a parsed id/type list into
// a type for struct/interface/arglist
-func tostruct(l []ir.Node) *types.Type {
- t := types.New(types.TSTRUCT)
-
- fields := make([]*types.Field, len(l))
- for i, n := range l {
- f := structfield(n)
- if f.Broke() {
- t.SetBroke(true)
- }
- fields[i] = f
- }
- t.SetFields(fields)
-
- checkdupfields("field", t.FieldSlice())
-
- if !t.Broke() {
- checkwidth(t)
- }
-
- return t
-}
-
-func tofunargs(l []ir.Node, funarg types.Funarg) *types.Type {
- t := types.New(types.TSTRUCT)
- t.StructType().Funarg = funarg
-
- fields := make([]*types.Field, len(l))
- for i, n := range l {
- f := structfield(n)
- f.SetIsDDD(n.IsDDD())
- if n.Right() != nil {
- n.Right().SetType(f.Type)
- f.Nname = n.Right()
- }
- if f.Broke() {
- t.SetBroke(true)
- }
- fields[i] = f
- }
- t.SetFields(fields)
- return t
-}
-
-func tofunargsfield(fields []*types.Field, funarg types.Funarg) *types.Type {
- t := types.New(types.TSTRUCT)
- t.StructType().Funarg = funarg
- t.SetFields(fields)
- return t
-}
-
-func interfacefield(n ir.Node) *types.Field {
+func tostruct(l []*ir.Field) *types.Type {
lno := base.Pos
- base.Pos = n.Pos()
- if n.Op() != ir.ODCLFIELD {
- base.Fatalf("interfacefield: oops %v\n", n)
+ fields := make([]*types.Field, len(l))
+ for i, n := range l {
+ base.Pos = n.Pos
+
+ if n.Ntype != nil {
+ n.Type = typecheckNtype(n.Ntype).Type()
+ n.Ntype = nil
+ }
+ f := types.NewField(n.Pos, n.Sym, n.Type)
+ if n.Embedded {
+ checkembeddedtype(n.Type)
+ f.Embedded = 1
+ }
+ f.Note = n.Note
+ fields[i] = f
}
-
- if n.HasVal() {
- base.Errorf("interface method cannot have annotation")
- }
-
- // MethodSpec = MethodName Signature | InterfaceTypeName .
- //
- // If Sym != nil, then Sym is MethodName and Left is Signature.
- // Otherwise, Left is InterfaceTypeName.
-
- if n.Left() != nil {
- n.SetLeft(typecheck(n.Left(), ctxType))
- n.SetType(n.Left().Type())
- n.SetLeft(nil)
- }
-
- f := types.NewField(n.Pos(), n.Sym(), n.Type())
+ checkdupfields("field", fields)
base.Pos = lno
- return f
+ return types.NewStruct(types.LocalPkg, fields)
}
-func tointerface(l []ir.Node) *types.Type {
- if len(l) == 0 {
+func tointerface(nmethods []*ir.Field) *types.Type {
+ if len(nmethods) == 0 {
return types.Types[types.TINTER]
}
- t := types.New(types.TINTER)
- var fields []*types.Field
- for _, n := range l {
- f := interfacefield(n)
- if f.Broke() {
- t.SetBroke(true)
+
+ lno := base.Pos
+
+ methods := make([]*types.Field, len(nmethods))
+ for i, n := range nmethods {
+ base.Pos = n.Pos
+ if n.Ntype != nil {
+ n.Type = typecheckNtype(n.Ntype).Type()
+ n.Ntype = nil
}
- fields = append(fields, f)
+ methods[i] = types.NewField(n.Pos, n.Sym, n.Type)
}
- t.SetInterface(fields)
- return t
+
+ base.Pos = lno
+ return types.NewInterface(types.LocalPkg, methods)
}
-func fakeRecv() ir.Node {
+func fakeRecv() *ir.Field {
return anonfield(types.FakeRecvType())
}
@@ -694,42 +552,47 @@ func isifacemethod(f *types.Type) bool {
}
// turn a parsed function declaration into a type
-func functype(this ir.Node, in, out []ir.Node) *types.Type {
- t := types.New(types.TFUNC)
+func functype(nrecv *ir.Field, nparams, nresults []*ir.Field) *types.Type {
+ funarg := func(n *ir.Field) *types.Field {
+ lno := base.Pos
+ base.Pos = n.Pos
- var rcvr []ir.Node
- if this != nil {
- rcvr = []ir.Node{this}
+ if n.Ntype != nil {
+ n.Type = typecheckNtype(n.Ntype).Type()
+ n.Ntype = nil
+ }
+
+ f := types.NewField(n.Pos, n.Sym, n.Type)
+ f.SetIsDDD(n.IsDDD)
+ if n.Decl != nil {
+ n.Decl.SetType(f.Type)
+ f.Nname = n.Decl
+ }
+
+ base.Pos = lno
+ return f
+ }
+ funargs := func(nn []*ir.Field) []*types.Field {
+ res := make([]*types.Field, len(nn))
+ for i, n := range nn {
+ res[i] = funarg(n)
+ }
+ return res
}
- t.FuncType().Receiver = tofunargs(rcvr, types.FunargRcvr)
- t.FuncType().Params = tofunargs(in, types.FunargParams)
- t.FuncType().Results = tofunargs(out, types.FunargResults)
+ var recv *types.Field
+ if nrecv != nil {
+ recv = funarg(nrecv)
+ }
+
+ t := types.NewSignature(types.LocalPkg, recv, funargs(nparams), funargs(nresults))
checkdupfields("argument", t.Recvs().FieldSlice(), t.Params().FieldSlice(), t.Results().FieldSlice())
-
- if t.Recvs().Broke() || t.Results().Broke() || t.Params().Broke() {
- t.SetBroke(true)
- }
-
- t.FuncType().Outnamed = t.NumResults() > 0 && ir.OrigSym(t.Results().Field(0).Sym) != nil
-
return t
}
-func functypefield(this *types.Field, in, out []*types.Field) *types.Type {
- t := types.New(types.TFUNC)
-
- var rcvr []*types.Field
- if this != nil {
- rcvr = []*types.Field{this}
- }
- t.FuncType().Receiver = tofunargsfield(rcvr, types.FunargRcvr)
- t.FuncType().Params = tofunargsfield(in, types.FunargParams)
- t.FuncType().Results = tofunargsfield(out, types.FunargResults)
-
- t.FuncType().Outnamed = t.NumResults() > 0 && ir.OrigSym(t.Results().Field(0).Sym) != nil
-
- return t
+func hasNamedResults(fn *ir.Func) bool {
+ typ := fn.Type()
+ return typ.NumResults() > 0 && types.OrigSym(typ.Results().Field(0).Sym) != nil
}
// methodSym returns the method symbol representing a method name
@@ -754,12 +617,12 @@ func methodSymSuffix(recv *types.Type, msym *types.Sym, suffix string) *types.Sy
base.Fatalf("blank method name")
}
- rsym := recv.Sym
+ rsym := recv.Sym()
if recv.IsPtr() {
if rsym != nil {
base.Fatalf("declared pointer receiver type: %v", recv)
}
- rsym = recv.Elem().Sym
+ rsym = recv.Elem().Sym()
}
// Find the package the receiver type appeared in. For
@@ -799,7 +662,7 @@ func methodSymSuffix(recv *types.Type, msym *types.Sym, suffix string) *types.Sy
// - msym is the method symbol
// - t is function type (with receiver)
// Returns a pointer to the existing or added Field; or nil if there's an error.
-func addmethod(n ir.Node, msym *types.Sym, t *types.Type, local, nointerface bool) *types.Field {
+func addmethod(n *ir.Func, msym *types.Sym, t *types.Type, local, nointerface bool) *types.Field {
if msym == nil {
base.Fatalf("no method symbol")
}
@@ -812,11 +675,11 @@ func addmethod(n ir.Node, msym *types.Sym, t *types.Type, local, nointerface boo
}
mt := methtype(rf.Type)
- if mt == nil || mt.Sym == nil {
+ if mt == nil || mt.Sym() == nil {
pa := rf.Type
t := pa
if t != nil && t.IsPtr() {
- if t.Sym != nil {
+ if t.Sym() != nil {
base.Errorf("invalid receiver type %v (%v is a pointer type)", pa, t)
return nil
}
@@ -826,7 +689,7 @@ func addmethod(n ir.Node, msym *types.Sym, t *types.Type, local, nointerface boo
switch {
case t == nil || t.Broke():
// rely on typecheck having complained before
- case t.Sym == nil:
+ case t.Sym() == nil:
base.Errorf("invalid receiver type %v (%v is not a defined type)", pa, t)
case t.IsPtr():
base.Errorf("invalid receiver type %v (%v is a pointer type)", pa, t)
@@ -840,7 +703,7 @@ func addmethod(n ir.Node, msym *types.Sym, t *types.Type, local, nointerface boo
return nil
}
- if local && mt.Sym.Pkg != ir.LocalPkg {
+ if local && mt.Sym().Pkg != types.LocalPkg {
base.Errorf("cannot define new methods on non-local type %v", mt)
return nil
}
@@ -872,7 +735,7 @@ func addmethod(n ir.Node, msym *types.Sym, t *types.Type, local, nointerface boo
}
f := types.NewField(base.Pos, msym, t)
- f.Nname = n.Func().Nname
+ f.Nname = n.Nname
f.SetNointerface(nointerface)
mt.Methods().Append(f)
@@ -944,18 +807,18 @@ func setNodeNameFunc(n ir.Node) {
n.Sym().SetFunc(true)
}
-func dclfunc(sym *types.Sym, tfn ir.Node) ir.Node {
+func dclfunc(sym *types.Sym, tfn ir.Ntype) *ir.Func {
if tfn.Op() != ir.OTFUNC {
base.Fatalf("expected OTFUNC node, got %v", tfn)
}
- fn := ir.Nod(ir.ODCLFUNC, nil, nil)
- fn.Func().Nname = newfuncnamel(base.Pos, sym, fn.Func())
- fn.Func().Nname.Name().Defn = fn
- fn.Func().Nname.Name().Param.Ntype = tfn
- setNodeNameFunc(fn.Func().Nname)
+ fn := ir.NewFunc(base.Pos)
+ fn.Nname = newFuncNameAt(base.Pos, sym, fn)
+ fn.Nname.Defn = fn
+ fn.Nname.Ntype = tfn
+ setNodeNameFunc(fn.Nname)
funchdr(fn)
- fn.Func().Nname.Name().Param.Ntype = typecheck(fn.Func().Nname.Name().Param.Ntype, ctxType)
+ fn.Nname.Ntype = typecheckNtype(fn.Nname.Ntype)
return fn
}
@@ -963,14 +826,14 @@ type nowritebarrierrecChecker struct {
// extraCalls contains extra function calls that may not be
// visible during later analysis. It maps from the ODCLFUNC of
// the caller to a list of callees.
- extraCalls map[ir.Node][]nowritebarrierrecCall
+ extraCalls map[*ir.Func][]nowritebarrierrecCall
// curfn is the current function during AST walks.
- curfn ir.Node
+ curfn *ir.Func
}
type nowritebarrierrecCall struct {
- target ir.Node // ODCLFUNC of caller or callee
+ target *ir.Func // caller or callee
lineno src.XPos // line of call
}
@@ -978,7 +841,7 @@ type nowritebarrierrecCall struct {
// must be called before transformclosure and walk.
func newNowritebarrierrecChecker() *nowritebarrierrecChecker {
c := &nowritebarrierrecChecker{
- extraCalls: make(map[ir.Node][]nowritebarrierrecCall),
+ extraCalls: make(map[*ir.Func][]nowritebarrierrecCall),
}
// Find all systemstack calls and record their targets. In
@@ -990,7 +853,7 @@ func newNowritebarrierrecChecker() *nowritebarrierrecChecker {
if n.Op() != ir.ODCLFUNC {
continue
}
- c.curfn = n
+ c.curfn = n.(*ir.Func)
ir.Inspect(n, c.findExtraCalls)
}
c.curfn = nil
@@ -1009,13 +872,13 @@ func (c *nowritebarrierrecChecker) findExtraCalls(n ir.Node) bool {
return true
}
- var callee ir.Node
+ var callee *ir.Func
arg := n.List().First()
switch arg.Op() {
case ir.ONAME:
- callee = arg.Name().Defn
+ callee = arg.Name().Defn.(*ir.Func)
case ir.OCLOSURE:
- callee = arg.Func().Decl
+ callee = arg.Func()
default:
base.Fatalf("expected ONAME or OCLOSURE node, got %+v", arg)
}
@@ -1034,13 +897,8 @@ func (c *nowritebarrierrecChecker) findExtraCalls(n ir.Node) bool {
// because that's all we know after we start SSA.
//
// This can be called concurrently for different from Nodes.
-func (c *nowritebarrierrecChecker) recordCall(from ir.Node, to *obj.LSym, pos src.XPos) {
- if from.Op() != ir.ODCLFUNC {
- base.Fatalf("expected ODCLFUNC, got %v", from)
- }
- // We record this information on the *Func so this is
- // concurrent-safe.
- fn := from.Func()
+func (c *nowritebarrierrecChecker) recordCall(fn *ir.Func, to *obj.LSym, pos src.XPos) {
+ // We record this information on the *Func so this is concurrent-safe.
if fn.NWBRCalls == nil {
fn.NWBRCalls = new([]ir.SymAndPos)
}
@@ -1052,39 +910,40 @@ func (c *nowritebarrierrecChecker) check() {
// capture all calls created by lowering, but this means we
// only get to see the obj.LSyms of calls. symToFunc lets us
// get back to the ODCLFUNCs.
- symToFunc := make(map[*obj.LSym]ir.Node)
+ symToFunc := make(map[*obj.LSym]*ir.Func)
// funcs records the back-edges of the BFS call graph walk. It
// maps from the ODCLFUNC of each function that must not have
// write barriers to the call that inhibits them. Functions
// that are directly marked go:nowritebarrierrec are in this
// map with a zero-valued nowritebarrierrecCall. This also
// acts as the set of marks for the BFS of the call graph.
- funcs := make(map[ir.Node]nowritebarrierrecCall)
+ funcs := make(map[*ir.Func]nowritebarrierrecCall)
// q is the queue of ODCLFUNC Nodes to visit in BFS order.
- var q ir.NodeQueue
+ var q ir.NameQueue
for _, n := range xtop {
if n.Op() != ir.ODCLFUNC {
continue
}
+ fn := n.(*ir.Func)
- symToFunc[n.Func().LSym] = n
+ symToFunc[fn.LSym] = fn
// Make nowritebarrierrec functions BFS roots.
- if n.Func().Pragma&ir.Nowritebarrierrec != 0 {
- funcs[n] = nowritebarrierrecCall{}
- q.PushRight(n)
+ if fn.Pragma&ir.Nowritebarrierrec != 0 {
+ funcs[fn] = nowritebarrierrecCall{}
+ q.PushRight(fn.Nname)
}
// Check go:nowritebarrier functions.
- if n.Func().Pragma&ir.Nowritebarrier != 0 && n.Func().WBPos.IsKnown() {
- base.ErrorfAt(n.Func().WBPos, "write barrier prohibited")
+ if fn.Pragma&ir.Nowritebarrier != 0 && fn.WBPos.IsKnown() {
+ base.ErrorfAt(fn.WBPos, "write barrier prohibited")
}
}
// Perform a BFS of the call graph from all
// go:nowritebarrierrec functions.
- enqueue := func(src, target ir.Node, pos src.XPos) {
- if target.Func().Pragma&ir.Yeswritebarrierrec != 0 {
+ enqueue := func(src, target *ir.Func, pos src.XPos) {
+ if target.Pragma&ir.Yeswritebarrierrec != 0 {
// Don't flow into this function.
return
}
@@ -1095,20 +954,20 @@ func (c *nowritebarrierrecChecker) check() {
// Record the path.
funcs[target] = nowritebarrierrecCall{target: src, lineno: pos}
- q.PushRight(target)
+ q.PushRight(target.Nname)
}
for !q.Empty() {
- fn := q.PopLeft()
+ fn := q.PopLeft().Func()
// Check fn.
- if fn.Func().WBPos.IsKnown() {
+ if fn.WBPos.IsKnown() {
var err bytes.Buffer
call := funcs[fn]
for call.target != nil {
- fmt.Fprintf(&err, "\n\t%v: called by %v", base.FmtPos(call.lineno), call.target.Func().Nname)
+ fmt.Fprintf(&err, "\n\t%v: called by %v", base.FmtPos(call.lineno), call.target.Nname)
call = funcs[call.target]
}
- base.ErrorfAt(fn.Func().WBPos, "write barrier prohibited by caller; %v%s", fn.Func().Nname, err.String())
+ base.ErrorfAt(fn.WBPos, "write barrier prohibited by caller; %v%s", fn.Nname, err.String())
continue
}
@@ -1116,10 +975,10 @@ func (c *nowritebarrierrecChecker) check() {
for _, callee := range c.extraCalls[fn] {
enqueue(fn, callee.target, callee.lineno)
}
- if fn.Func().NWBRCalls == nil {
+ if fn.NWBRCalls == nil {
continue
}
- for _, callee := range *fn.Func().NWBRCalls {
+ for _, callee := range *fn.NWBRCalls {
target := symToFunc[callee.Sym]
if target != nil {
enqueue(fn, target, callee.Pos)
diff --git a/src/cmd/compile/internal/gc/dwinl.go b/src/cmd/compile/internal/gc/dwinl.go
index 1e4e43caad..d9eb930037 100644
--- a/src/cmd/compile/internal/gc/dwinl.go
+++ b/src/cmd/compile/internal/gc/dwinl.go
@@ -6,6 +6,7 @@ package gc
import (
"cmd/compile/internal/base"
+ "cmd/compile/internal/ir"
"cmd/internal/dwarf"
"cmd/internal/obj"
"cmd/internal/src"
@@ -211,6 +212,7 @@ func genAbstractFunc(fn *obj.LSym) {
base.Ctxt.Diag("failed to locate precursor fn for %v", fn)
return
}
+ _ = ifn.(*ir.Func)
if base.Debug.DwarfInl != 0 {
base.Ctxt.Logf("DwarfAbstractFunc(%v)\n", fn.Name)
}
diff --git a/src/cmd/compile/internal/gc/embed.go b/src/cmd/compile/internal/gc/embed.go
index 33b05a5bf0..7664bde1c5 100644
--- a/src/cmd/compile/internal/gc/embed.go
+++ b/src/cmd/compile/internal/gc/embed.go
@@ -28,7 +28,7 @@ const (
var numLocalEmbed int
-func varEmbed(p *noder, names []ir.Node, typ ir.Node, exprs []ir.Node, embeds []PragmaEmbed) (newExprs []ir.Node) {
+func varEmbed(p *noder, names []ir.Node, typ ir.Ntype, exprs []ir.Node, embeds []PragmaEmbed) (newExprs []ir.Node) {
haveEmbed := false
for _, decl := range p.file.DeclList {
imp, ok := decl.(*syntax.ImportDecl)
@@ -115,13 +115,13 @@ func varEmbed(p *noder, names []ir.Node, typ ir.Node, exprs []ir.Node, embeds []
numLocalEmbed++
v = ir.NewNameAt(v.Pos(), lookupN("embed.", numLocalEmbed))
v.Sym().Def = v
- v.Name().Param.Ntype = typ
+ v.Name().Ntype = typ
v.SetClass(ir.PEXTERN)
externdcl = append(externdcl, v)
exprs = []ir.Node{v}
}
- v.Name().Param.SetEmbedFiles(list)
+ v.Name().SetEmbedFiles(list)
embedlist = append(embedlist, v)
return exprs
}
@@ -131,31 +131,33 @@ func varEmbed(p *noder, names []ir.Node, typ ir.Node, exprs []ir.Node, embeds []
// can't tell whether "string" and "byte" really mean "string" and "byte".
// The result must be confirmed later, after type checking, using embedKind.
func embedKindApprox(typ ir.Node) int {
- if typ.Sym() != nil && typ.Sym().Name == "FS" && (typ.Sym().Pkg.Path == "embed" || (typ.Sym().Pkg == ir.LocalPkg && base.Ctxt.Pkgpath == "embed")) {
+ if typ.Sym() != nil && typ.Sym().Name == "FS" && (typ.Sym().Pkg.Path == "embed" || (typ.Sym().Pkg == types.LocalPkg && base.Ctxt.Pkgpath == "embed")) {
return embedFiles
}
// These are not guaranteed to match only string and []byte -
// maybe the local package has redefined one of those words.
// But it's the best we can do now during the noder.
// The stricter check happens later, in initEmbed calling embedKind.
- if typ.Sym() != nil && typ.Sym().Name == "string" && typ.Sym().Pkg == ir.LocalPkg {
+ if typ.Sym() != nil && typ.Sym().Name == "string" && typ.Sym().Pkg == types.LocalPkg {
return embedString
}
- if typ.Op() == ir.OTARRAY && typ.Left() == nil && typ.Right().Sym() != nil && typ.Right().Sym().Name == "byte" && typ.Right().Sym().Pkg == ir.LocalPkg {
- return embedBytes
+ if typ, ok := typ.(*ir.SliceType); ok {
+ if sym := typ.Elem.Sym(); sym != nil && sym.Name == "byte" && sym.Pkg == types.LocalPkg {
+ return embedBytes
+ }
}
return embedUnknown
}
// embedKind determines the kind of embedding variable.
func embedKind(typ *types.Type) int {
- if typ.Sym != nil && typ.Sym.Name == "FS" && (typ.Sym.Pkg.Path == "embed" || (typ.Sym.Pkg == ir.LocalPkg && base.Ctxt.Pkgpath == "embed")) {
+ if typ.Sym() != nil && typ.Sym().Name == "FS" && (typ.Sym().Pkg.Path == "embed" || (typ.Sym().Pkg == types.LocalPkg && base.Ctxt.Pkgpath == "embed")) {
return embedFiles
}
if typ == types.Types[types.TSTRING] {
return embedString
}
- if typ.Sym == nil && typ.IsSlice() && typ.Elem() == types.Bytetype {
+ if typ.Sym() == nil && typ.IsSlice() && typ.Elem() == types.ByteType {
return embedBytes
}
return embedUnknown
@@ -193,7 +195,7 @@ func dumpembeds() {
// initEmbed emits the init data for a //go:embed variable,
// which is either a string, a []byte, or an embed.FS.
func initEmbed(v ir.Node) {
- files := v.Name().Param.EmbedFiles()
+ files := v.Name().EmbedFiles()
switch kind := embedKind(v.Type()); kind {
case embedUnknown:
base.ErrorfAt(v.Pos(), "go:embed cannot apply to var of type %v", v.Type())
diff --git a/src/cmd/compile/internal/gc/escape.go b/src/cmd/compile/internal/gc/escape.go
index 783bc8c41d..f317e9999c 100644
--- a/src/cmd/compile/internal/gc/escape.go
+++ b/src/cmd/compile/internal/gc/escape.go
@@ -85,8 +85,9 @@ import (
type Escape struct {
allLocs []*EscLocation
+ labels map[*types.Sym]labelState // known labels
- curfn ir.Node
+ curfn *ir.Func
// loopDepth counts the current loop nesting depth within
// curfn. It increments within each "for" loop and at each
@@ -102,7 +103,7 @@ type Escape struct {
// variable.
type EscLocation struct {
n ir.Node // represented variable or expression, if any
- curfn ir.Node // enclosing function
+ curfn *ir.Func // enclosing function
edges []EscEdge // incoming edges
loopDepth int // loopDepth at declaration
@@ -147,7 +148,7 @@ func init() {
}
// escFmt is called from node printing to print information about escape analysis results.
-func escFmt(n ir.Node, short bool) string {
+func escFmt(n ir.Node) string {
text := ""
switch n.Esc() {
case EscUnknown:
@@ -160,9 +161,7 @@ func escFmt(n ir.Node, short bool) string {
text = "esc(no)"
case EscNever:
- if !short {
- text = "esc(N)"
- }
+ text = "esc(N)"
default:
text = fmt.Sprintf("esc(%d)", n.Esc())
@@ -179,7 +178,7 @@ func escFmt(n ir.Node, short bool) string {
// escapeFuncs performs escape analysis on a minimal batch of
// functions.
-func escapeFuncs(fns []ir.Node, recursive bool) {
+func escapeFuncs(fns []*ir.Func, recursive bool) {
for _, fn := range fns {
if fn.Op() != ir.ODCLFUNC {
base.Fatalf("unexpected node: %v", fn)
@@ -202,8 +201,8 @@ func escapeFuncs(fns []ir.Node, recursive bool) {
e.finish(fns)
}
-func (e *Escape) initFunc(fn ir.Node) {
- if fn.Op() != ir.ODCLFUNC || fn.Esc() != EscFuncUnknown {
+func (e *Escape) initFunc(fn *ir.Func) {
+ if fn.Esc() != EscFuncUnknown {
base.Fatalf("unexpected node: %v", fn)
}
fn.SetEsc(EscFuncPlanned)
@@ -215,27 +214,30 @@ func (e *Escape) initFunc(fn ir.Node) {
e.loopDepth = 1
// Allocate locations for local variables.
- for _, dcl := range fn.Func().Dcl {
+ for _, dcl := range fn.Dcl {
if dcl.Op() == ir.ONAME {
e.newLoc(dcl, false)
}
}
}
-func (e *Escape) walkFunc(fn ir.Node) {
+func (e *Escape) walkFunc(fn *ir.Func) {
fn.SetEsc(EscFuncStarted)
// Identify labels that mark the head of an unstructured loop.
ir.InspectList(fn.Body(), func(n ir.Node) bool {
switch n.Op() {
case ir.OLABEL:
- n.Sym().Label = nonlooping
+ if e.labels == nil {
+ e.labels = make(map[*types.Sym]labelState)
+ }
+ e.labels[n.Sym()] = nonlooping
case ir.OGOTO:
// If we visited the label before the goto,
// then this is a looping label.
- if n.Sym().Label == nonlooping {
- n.Sym().Label = looping
+ if e.labels[n.Sym()] == nonlooping {
+ e.labels[n.Sym()] = looping
}
}
@@ -245,6 +247,10 @@ func (e *Escape) walkFunc(fn ir.Node) {
e.curfn = fn
e.loopDepth = 1
e.block(fn.Body())
+
+ if len(e.labels) != 0 {
+ base.FatalfAt(fn.Pos(), "leftover labels after walkFunc")
+ }
}
// Below we implement the methods for walking the AST and recording
@@ -294,7 +300,7 @@ func (e *Escape) stmt(n ir.Node) {
default:
base.Fatalf("unexpected stmt: %v", n)
- case ir.ODCLCONST, ir.ODCLTYPE, ir.OEMPTY, ir.OFALL, ir.OINLMARK:
+ case ir.ODCLCONST, ir.ODCLTYPE, ir.OFALL, ir.OINLMARK:
// nop
case ir.OBREAK, ir.OCONTINUE, ir.OGOTO:
@@ -310,7 +316,7 @@ func (e *Escape) stmt(n ir.Node) {
}
case ir.OLABEL:
- switch ir.AsNode(n.Sym().Label) {
+ switch e.labels[n.Sym()] {
case nonlooping:
if base.Flag.LowerM > 2 {
fmt.Printf("%v:%v non-looping label\n", base.FmtPos(base.Pos), n)
@@ -323,7 +329,7 @@ func (e *Escape) stmt(n ir.Node) {
default:
base.Fatalf("label missing tag")
}
- n.Sym().Label = nil
+ delete(e.labels, n.Sym())
case ir.OIF:
e.discard(n.Left())
@@ -386,8 +392,8 @@ func (e *Escape) stmt(n ir.Node) {
case ir.OSELRECV:
e.assign(n.Left(), n.Right(), "selrecv", n)
case ir.OSELRECV2:
- e.assign(n.Left(), n.Right(), "selrecv", n)
- e.assign(n.List().First(), nil, "selrecv", n)
+ e.assign(n.List().First(), n.Rlist().First(), "selrecv", n)
+ e.assign(n.List().Second(), nil, "selrecv", n)
case ir.ORECV:
// TODO(mdempsky): Consider e.discard(n.Left).
e.exprSkipInit(e.discardHole(), n) // already visited n.Ninit
@@ -404,18 +410,18 @@ func (e *Escape) stmt(n ir.Node) {
}
case ir.OAS2DOTTYPE: // v, ok = x.(type)
- e.assign(n.List().First(), n.Right(), "assign-pair-dot-type", n)
+ e.assign(n.List().First(), n.Rlist().First(), "assign-pair-dot-type", n)
e.assign(n.List().Second(), nil, "assign-pair-dot-type", n)
case ir.OAS2MAPR: // v, ok = m[k]
- e.assign(n.List().First(), n.Right(), "assign-pair-mapr", n)
+ e.assign(n.List().First(), n.Rlist().First(), "assign-pair-mapr", n)
e.assign(n.List().Second(), nil, "assign-pair-mapr", n)
case ir.OAS2RECV: // v, ok = <-ch
- e.assign(n.List().First(), n.Right(), "assign-pair-receive", n)
+ e.assign(n.List().First(), n.Rlist().First(), "assign-pair-receive", n)
e.assign(n.List().Second(), nil, "assign-pair-receive", n)
case ir.OAS2FUNC:
- e.stmts(n.Right().Init())
- e.call(e.addrs(n.List()), n.Right(), nil)
+ e.stmts(n.Rlist().First().Init())
+ e.call(e.addrs(n.List()), n.Rlist().First(), nil)
case ir.ORETURN:
results := e.curfn.Type().Results().FieldSlice()
for i, v := range n.List().Slice() {
@@ -478,7 +484,7 @@ func (e *Escape) exprSkipInit(k EscHole, n ir.Node) {
default:
base.Fatalf("unexpected expr: %v", n)
- case ir.OLITERAL, ir.ONIL, ir.OGETG, ir.OCLOSUREVAR, ir.OTYPE, ir.OMETHEXPR:
+ case ir.OLITERAL, ir.ONIL, ir.OGETG, ir.OCLOSUREREAD, ir.OTYPE, ir.OMETHEXPR:
// nop
case ir.ONAME:
@@ -581,7 +587,8 @@ func (e *Escape) exprSkipInit(k EscHole, n ir.Node) {
for i := m.Type.NumResults(); i > 0; i-- {
ks = append(ks, e.heapHole())
}
- paramK := e.tagHole(ks, ir.AsNode(m.Nname), m.Type.Recv())
+ name, _ := m.Nname.(*ir.Name)
+ paramK := e.tagHole(ks, name, m.Type.Recv())
e.expr(e.teeHole(paramK, closureK), n.Left())
@@ -625,17 +632,13 @@ func (e *Escape) exprSkipInit(k EscHole, n ir.Node) {
k = e.spill(k, n)
// Link addresses of captured variables to closure.
- for _, v := range n.Func().ClosureVars.Slice() {
- if v.Op() == ir.OXXX { // unnamed out argument; see dcl.go:/^funcargs
- continue
- }
-
+ for _, v := range n.Func().ClosureVars {
k := k
- if !v.Name().Byval() {
+ if !v.Byval() {
k = k.addr(v, "reference")
}
- e.expr(k.note(n, "captured by a closure"), v.Name().Defn)
+ e.expr(k.note(n, "captured by a closure"), v.Defn)
}
case ir.ORUNES2STR, ir.OBYTES2STR, ir.OSTR2RUNES, ir.OSTR2BYTES, ir.ORUNESTR:
@@ -654,7 +657,7 @@ func (e *Escape) exprSkipInit(k EscHole, n ir.Node) {
// unsafeValue evaluates a uintptr-typed arithmetic expression looking
// for conversions from an unsafe.Pointer.
func (e *Escape) unsafeValue(k EscHole, n ir.Node) {
- if n.Type().Etype != types.TUINTPTR {
+ if n.Type().Kind() != types.TUINTPTR {
base.Fatalf("unexpected type %v for %v", n.Type(), n)
}
@@ -704,8 +707,7 @@ func (e *Escape) discards(l ir.Nodes) {
// that represents storing into the represented location.
func (e *Escape) addr(n ir.Node) EscHole {
if n == nil || ir.IsBlank(n) {
- // Can happen at least in OSELRECV.
- // TODO(mdempsky): Anywhere else?
+ // Can happen in select case, range, maybe others.
return e.discardHole()
}
@@ -755,7 +757,7 @@ func (e *Escape) assign(dst, src ir.Node, why string, where ir.Node) {
// Filter out some no-op assignments for escape analysis.
ignore := dst != nil && src != nil && isSelfAssign(dst, src)
if ignore && base.Flag.LowerM != 0 {
- base.WarnfAt(where.Pos(), "%v ignoring self-assignment in %S", funcSym(e.curfn), where)
+ base.WarnfAt(where.Pos(), "%v ignoring self-assignment in %v", funcSym(e.curfn), where)
}
k := e.addr(dst)
@@ -799,18 +801,19 @@ func (e *Escape) call(ks []EscHole, call, where ir.Node) {
switch call.Op() {
default:
+ ir.Dump("esc", call)
base.Fatalf("unexpected call op: %v", call.Op())
case ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER:
fixVariadicCall(call)
// Pick out the function callee, if statically known.
- var fn ir.Node
+ var fn *ir.Name
switch call.Op() {
case ir.OCALLFUNC:
switch v := staticValue(call.Left()); {
case v.Op() == ir.ONAME && v.Class() == ir.PFUNC:
- fn = v
+ fn = v.(*ir.Name)
case v.Op() == ir.OCLOSURE:
fn = v.Func().Nname
}
@@ -894,7 +897,7 @@ func (e *Escape) call(ks []EscHole, call, where ir.Node) {
// ks should contain the holes representing where the function
// callee's results flows. fn is the statically-known callee function,
// if any.
-func (e *Escape) tagHole(ks []EscHole, fn ir.Node, param *types.Field) EscHole {
+func (e *Escape) tagHole(ks []EscHole, fn *ir.Name, param *types.Field) EscHole {
// If this is a dynamic call, we can't rely on param.Note.
if fn == nil {
return e.heapHole()
@@ -935,9 +938,9 @@ func (e *Escape) tagHole(ks []EscHole, fn ir.Node, param *types.Field) EscHole {
// fn has not yet been analyzed, so its parameters and results
// should be incorporated directly into the flow graph instead of
// relying on its escape analysis tagging.
-func (e *Escape) inMutualBatch(fn ir.Node) bool {
- if fn.Name().Defn != nil && fn.Name().Defn.Esc() < EscFuncTagged {
- if fn.Name().Defn.Esc() == EscFuncUnknown {
+func (e *Escape) inMutualBatch(fn *ir.Name) bool {
+ if fn.Defn != nil && fn.Defn.Esc() < EscFuncTagged {
+ if fn.Defn.Esc() == EscFuncUnknown {
base.Fatalf("graph inconsistency")
}
return true
@@ -1084,7 +1087,7 @@ func (e *Escape) newLoc(n ir.Node, transient bool) *EscLocation {
base.Fatalf("curfn mismatch: %v != %v", n.Name().Curfn, e.curfn)
}
- if n.HasOpt() {
+ if n.Opt() != nil {
base.Fatalf("%v already has a location", n)
}
n.SetOpt(loc)
@@ -1360,7 +1363,7 @@ func (e *Escape) outlives(l, other *EscLocation) bool {
//
// var u int // okay to stack allocate
// *(func() *int { return &u }()) = 42
- if containsClosure(other.curfn, l.curfn) && l.curfn.Func().ClosureCalled {
+ if containsClosure(other.curfn, l.curfn) && l.curfn.ClosureCalled() {
return false
}
@@ -1394,11 +1397,7 @@ func (e *Escape) outlives(l, other *EscLocation) bool {
}
// containsClosure reports whether c is a closure contained within f.
-func containsClosure(f, c ir.Node) bool {
- if f.Op() != ir.ODCLFUNC || c.Op() != ir.ODCLFUNC {
- base.Fatalf("bad containsClosure: %v, %v", f, c)
- }
-
+func containsClosure(f, c *ir.Func) bool {
// Common case.
if f == c {
return false
@@ -1406,8 +1405,8 @@ func containsClosure(f, c ir.Node) bool {
// Closures within function Foo are named like "Foo.funcN..."
// TODO(mdempsky): Better way to recognize this.
- fn := f.Func().Nname.Sym().Name
- cn := c.Func().Nname.Sym().Name
+ fn := f.Sym().Name
+ cn := c.Sym().Name
return len(cn) > len(fn) && cn[:len(fn)] == fn && cn[len(fn)] == '.'
}
@@ -1429,7 +1428,7 @@ func (l *EscLocation) leakTo(sink *EscLocation, derefs int) {
l.paramEsc.AddHeap(derefs)
}
-func (e *Escape) finish(fns []ir.Node) {
+func (e *Escape) finish(fns []*ir.Func) {
// Record parameter tags for package export data.
for _, fn := range fns {
fn.SetEsc(EscFuncTagged)
@@ -1455,7 +1454,7 @@ func (e *Escape) finish(fns []ir.Node) {
if loc.escapes {
if n.Op() != ir.ONAME {
if base.Flag.LowerM != 0 {
- base.WarnfAt(n.Pos(), "%S escapes to heap", n)
+ base.WarnfAt(n.Pos(), "%v escapes to heap", n)
}
if logopt.Enabled() {
logopt.LogOpt(n.Pos(), "escape", "escape", ir.FuncName(e.curfn))
@@ -1465,7 +1464,7 @@ func (e *Escape) finish(fns []ir.Node) {
addrescapes(n)
} else {
if base.Flag.LowerM != 0 && n.Op() != ir.ONAME {
- base.WarnfAt(n.Pos(), "%S does not escape", n)
+ base.WarnfAt(n.Pos(), "%v does not escape", n)
}
n.SetEsc(EscNone)
if loc.transient {
@@ -1606,20 +1605,20 @@ const (
EscNever // By construction will not escape.
)
-// funcSym returns fn.Func.Nname.Sym if no nils are encountered along the way.
-func funcSym(fn ir.Node) *types.Sym {
- if fn == nil || fn.Func().Nname == nil {
+// funcSym returns fn.Nname.Sym if no nils are encountered along the way.
+func funcSym(fn *ir.Func) *types.Sym {
+ if fn == nil || fn.Nname == nil {
return nil
}
- return fn.Func().Nname.Sym()
+ return fn.Sym()
}
// Mark labels that have no backjumps to them as not increasing e.loopdepth.
-// Walk hasn't generated (goto|label).Left.Sym.Label yet, so we'll cheat
-// and set it to one of the following two. Then in esc we'll clear it again.
-var (
- looping = ir.Nod(ir.OXXX, nil, nil)
- nonlooping = ir.Nod(ir.OXXX, nil, nil)
+type labelState int
+
+const (
+ looping labelState = 1 + iota
+ nonlooping
)
func isSliceSelfAssign(dst, src ir.Node) bool {
@@ -1717,7 +1716,7 @@ func mayAffectMemory(n ir.Node) bool {
// We're ignoring things like division by zero, index out of range,
// and nil pointer dereference here.
switch n.Op() {
- case ir.ONAME, ir.OCLOSUREVAR, ir.OLITERAL, ir.ONIL:
+ case ir.ONAME, ir.OCLOSUREREAD, ir.OLITERAL, ir.ONIL:
return false
// Left+Right group.
@@ -1769,7 +1768,7 @@ func heapAllocReason(n ir.Node) string {
if !smallintconst(r) {
return "non-constant size"
}
- if t := n.Type(); t.Elem().Width != 0 && r.Int64Val() >= maxImplicitStackVarSize/t.Elem().Width {
+ if t := n.Type(); t.Elem().Width != 0 && ir.Int64Val(r) >= maxImplicitStackVarSize/t.Elem().Width {
return "too large for stack"
}
}
@@ -1790,6 +1789,7 @@ func addrescapes(n ir.Node) {
// Nothing to do.
case ir.ONAME:
+ n := n.(*ir.Name)
if n == nodfp {
break
}
@@ -1801,8 +1801,8 @@ func addrescapes(n ir.Node) {
}
// If a closure reference escapes, mark the outer variable as escaping.
- if n.Name().IsClosureVar() {
- addrescapes(n.Name().Defn)
+ if n.IsClosureVar() {
+ addrescapes(n.Defn)
break
}
@@ -1823,11 +1823,7 @@ func addrescapes(n ir.Node) {
// then we're analyzing the inner closure but we need to move x to the
// heap in f, not in the inner closure. Flip over to f before calling moveToHeap.
oldfn := Curfn
- Curfn = n.Name().Curfn
- if Curfn.Op() == ir.OCLOSURE {
- Curfn = Curfn.Func().Decl
- panic("can't happen")
- }
+ Curfn = n.Curfn
ln := base.Pos
base.Pos = Curfn.Pos()
moveToHeap(n)
@@ -1847,7 +1843,7 @@ func addrescapes(n ir.Node) {
}
// moveToHeap records the parameter or local variable n as moved to the heap.
-func moveToHeap(n ir.Node) {
+func moveToHeap(n *ir.Name) {
if base.Flag.LowerR != 0 {
ir.Dump("MOVE", n)
}
@@ -1863,13 +1859,13 @@ func moveToHeap(n ir.Node) {
// temp will add it to the function declaration list automatically.
heapaddr := temp(types.NewPtr(n.Type()))
heapaddr.SetSym(lookup("&" + n.Sym().Name))
- heapaddr.Orig().SetSym(heapaddr.Sym())
+ ir.Orig(heapaddr).SetSym(heapaddr.Sym())
heapaddr.SetPos(n.Pos())
// Unset AutoTemp to persist the &foo variable name through SSA to
// liveness analysis.
// TODO(mdempsky/drchase): Cleaner solution?
- heapaddr.Name().SetAutoTemp(false)
+ heapaddr.SetAutoTemp(false)
// Parameters have a local stack copy used at function start/end
// in addition to the copy in the heap that may live longer than
@@ -1887,24 +1883,24 @@ func moveToHeap(n ir.Node) {
stackcopy.SetType(n.Type())
stackcopy.SetOffset(n.Offset())
stackcopy.SetClass(n.Class())
- stackcopy.Name().Param.Heapaddr = heapaddr
+ stackcopy.Heapaddr = heapaddr
if n.Class() == ir.PPARAMOUT {
// Make sure the pointer to the heap copy is kept live throughout the function.
// The function could panic at any point, and then a defer could recover.
// Thus, we need the pointer to the heap copy always available so the
// post-deferreturn code can copy the return value back to the stack.
// See issue 16095.
- heapaddr.Name().SetIsOutputParamHeapAddr(true)
+ heapaddr.SetIsOutputParamHeapAddr(true)
}
- n.Name().Param.Stackcopy = stackcopy
+ n.Stackcopy = stackcopy
// Substitute the stackcopy into the function variable list so that
// liveness and other analyses use the underlying stack slot
// and not the now-pseudo-variable n.
found := false
- for i, d := range Curfn.Func().Dcl {
+ for i, d := range Curfn.Dcl {
if d == n {
- Curfn.Func().Dcl[i] = stackcopy
+ Curfn.Dcl[i] = stackcopy
found = true
break
}
@@ -1917,13 +1913,13 @@ func moveToHeap(n ir.Node) {
if !found {
base.Fatalf("cannot find %v in local variable list", n)
}
- Curfn.Func().Dcl = append(Curfn.Func().Dcl, n)
+ Curfn.Dcl = append(Curfn.Dcl, n)
}
// Modify n in place so that uses of n now mean indirection of the heapaddr.
n.SetClass(ir.PAUTOHEAP)
n.SetOffset(0)
- n.Name().Param.Heapaddr = heapaddr
+ n.Heapaddr = heapaddr
n.SetEsc(EscHeap)
if base.Flag.LowerM != 0 {
base.WarnfAt(n.Pos(), "moved to heap: %v", n)
diff --git a/src/cmd/compile/internal/gc/export.go b/src/cmd/compile/internal/gc/export.go
index 10033793bf..593dd3b2f8 100644
--- a/src/cmd/compile/internal/gc/export.go
+++ b/src/cmd/compile/internal/gc/export.go
@@ -24,7 +24,7 @@ func exportf(bout *bio.Writer, format string, args ...interface{}) {
var asmlist []ir.Node
// exportsym marks n for export (or reexport).
-func exportsym(n ir.Node) {
+func exportsym(n *ir.Name) {
if n.Sym().OnExportList() {
return
}
@@ -41,8 +41,8 @@ func initname(s string) bool {
return s == "init"
}
-func autoexport(n ir.Node, ctxt ir.Class) {
- if n.Sym().Pkg != ir.LocalPkg {
+func autoexport(n *ir.Name, ctxt ir.Class) {
+ if n.Sym().Pkg != types.LocalPkg {
return
}
if (ctxt != ir.PEXTERN && ctxt != ir.PFUNC) || dclcontext != ir.PEXTERN {
@@ -85,7 +85,7 @@ func importsym(ipkg *types.Pkg, s *types.Sym, op ir.Op) ir.Node {
base.Fatalf("missing ONONAME for %v\n", s)
}
- n = dclname(s)
+ n = ir.NewDeclNameAt(src.NoXPos, s)
s.SetPkgDef(n)
s.Importdef = ipkg
}
@@ -101,9 +101,7 @@ func importsym(ipkg *types.Pkg, s *types.Sym, op ir.Op) ir.Node {
func importtype(ipkg *types.Pkg, pos src.XPos, s *types.Sym) *types.Type {
n := importsym(ipkg, s, ir.OTYPE)
if n.Op() != ir.OTYPE {
- t := types.New(types.TFORW)
- t.Sym = s
- t.Nod = n
+ t := types.NewNamed(n)
n.SetOp(ir.OTYPE)
n.SetPos(pos)
@@ -161,8 +159,12 @@ func importfunc(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type) {
if n == nil {
return
}
+ name := n.(*ir.Name)
- n.SetFunc(new(ir.Func))
+ fn := ir.NewFunc(pos)
+ fn.SetType(t)
+ name.SetFunc(fn)
+ fn.Nname = name
if base.Flag.E != 0 {
fmt.Printf("import func %v%S\n", s, t)
@@ -200,7 +202,7 @@ func dumpasmhdr() {
if err != nil {
base.Fatalf("%v", err)
}
- fmt.Fprintf(b, "// generated by compile -asmhdr from package %s\n\n", ir.LocalPkg.Name)
+ fmt.Fprintf(b, "// generated by compile -asmhdr from package %s\n\n", types.LocalPkg.Name)
for _, n := range asmlist {
if n.Sym().IsBlank() {
continue
diff --git a/src/cmd/compile/internal/gc/gen.go b/src/cmd/compile/internal/gc/gen.go
index 44e918f2c1..39e9425978 100644
--- a/src/cmd/compile/internal/gc/gen.go
+++ b/src/cmd/compile/internal/gc/gen.go
@@ -31,13 +31,13 @@ func sysvar(name string) *obj.LSym {
// isParamStackCopy reports whether this is the on-stack copy of a
// function parameter that moved to the heap.
func isParamStackCopy(n ir.Node) bool {
- return n.Op() == ir.ONAME && (n.Class() == ir.PPARAM || n.Class() == ir.PPARAMOUT) && n.Name().Param.Heapaddr != nil
+ return n.Op() == ir.ONAME && (n.Class() == ir.PPARAM || n.Class() == ir.PPARAMOUT) && n.Name().Heapaddr != nil
}
// isParamHeapCopy reports whether this is the on-heap copy of
// a function parameter that moved to the heap.
func isParamHeapCopy(n ir.Node) bool {
- return n.Op() == ir.ONAME && n.Class() == ir.PAUTOHEAP && n.Name().Param.Stackcopy != nil
+ return n.Op() == ir.ONAME && n.Class() == ir.PAUTOHEAP && n.Name().Stackcopy != nil
}
// autotmpname returns the name for an autotmp variable numbered n.
@@ -52,7 +52,7 @@ func autotmpname(n int) string {
}
// make a new Node off the books
-func tempAt(pos src.XPos, curfn ir.Node, t *types.Type) ir.Node {
+func tempAt(pos src.XPos, curfn *ir.Func, t *types.Type) *ir.Name {
if curfn == nil {
base.Fatalf("no curfn for tempAt")
}
@@ -65,24 +65,24 @@ func tempAt(pos src.XPos, curfn ir.Node, t *types.Type) ir.Node {
}
s := &types.Sym{
- Name: autotmpname(len(curfn.Func().Dcl)),
- Pkg: ir.LocalPkg,
+ Name: autotmpname(len(curfn.Dcl)),
+ Pkg: types.LocalPkg,
}
n := ir.NewNameAt(pos, s)
s.Def = n
n.SetType(t)
n.SetClass(ir.PAUTO)
n.SetEsc(EscNever)
- n.Name().Curfn = curfn
- n.Name().SetUsed(true)
- n.Name().SetAutoTemp(true)
- curfn.Func().Dcl = append(curfn.Func().Dcl, n)
+ n.Curfn = curfn
+ n.SetUsed(true)
+ n.SetAutoTemp(true)
+ curfn.Dcl = append(curfn.Dcl, n)
dowidth(t)
- return n.Orig()
+ return n
}
-func temp(t *types.Type) ir.Node {
+func temp(t *types.Type) *ir.Name {
return tempAt(base.Pos, Curfn, t)
}
diff --git a/src/cmd/compile/internal/gc/go.go b/src/cmd/compile/internal/gc/go.go
index 0c6b81ffb7..960426ac5e 100644
--- a/src/cmd/compile/internal/gc/go.go
+++ b/src/cmd/compile/internal/gc/go.go
@@ -37,7 +37,7 @@ var (
// isRuntimePkg reports whether p is package runtime.
func isRuntimePkg(p *types.Pkg) bool {
- if base.Flag.CompilingRuntime && p == ir.LocalPkg {
+ if base.Flag.CompilingRuntime && p == types.LocalPkg {
return true
}
return p.Path == "runtime"
@@ -45,7 +45,7 @@ func isRuntimePkg(p *types.Pkg) bool {
// isReflectPkg reports whether p is package reflect.
func isReflectPkg(p *types.Pkg) bool {
- if p == ir.LocalPkg {
+ if p == types.LocalPkg {
return base.Ctxt.Pkgpath == "reflect"
}
return p.Path == "reflect"
@@ -104,7 +104,7 @@ var gopkg *types.Pkg // pseudo-package for method symbols on anonymous receiver
var zerosize int64
-var simtype [types.NTYPE]types.EType
+var simtype [types.NTYPE]types.Kind
var (
isInt [types.NTYPE]bool
@@ -132,9 +132,9 @@ var (
var xtop []ir.Node
-var exportlist []ir.Node
+var exportlist []*ir.Name
-var importlist []ir.Node // imported functions and methods with inlinable bodies
+var importlist []*ir.Func // imported functions and methods with inlinable bodies
var (
funcsymsmu sync.Mutex // protects funcsyms and associated package lookups (see func funcsym)
@@ -143,7 +143,7 @@ var (
var dclcontext ir.Class // PEXTERN/PAUTO
-var Curfn ir.Node
+var Curfn *ir.Func
var Widthptr int
@@ -158,7 +158,7 @@ var instrumenting bool
// Whether we are tracking lexical scopes for DWARF.
var trackScopes bool
-var nodfp ir.Node
+var nodfp *ir.Name
var autogeneratedPos src.XPos
@@ -211,6 +211,7 @@ var (
growslice,
msanread,
msanwrite,
+ msanmove,
newobject,
newproc,
panicdivide,
diff --git a/src/cmd/compile/internal/gc/gsubr.go b/src/cmd/compile/internal/gc/gsubr.go
index 950033a8a3..79ca669dfb 100644
--- a/src/cmd/compile/internal/gc/gsubr.go
+++ b/src/cmd/compile/internal/gc/gsubr.go
@@ -47,7 +47,7 @@ type Progs struct {
next *obj.Prog // next Prog
pc int64 // virtual PC; count of Progs
pos src.XPos // position to use for new Progs
- curfn ir.Node // fn these Progs are for
+ curfn *ir.Func // fn these Progs are for
progcache []obj.Prog // local progcache
cacheidx int // first free element of progcache
@@ -57,7 +57,7 @@ type Progs struct {
// newProgs returns a new Progs for fn.
// worker indicates which of the backend workers will use the Progs.
-func newProgs(fn ir.Node, worker int) *Progs {
+func newProgs(fn *ir.Func, worker int) *Progs {
pp := new(Progs)
if base.Ctxt.CanReuseProgs() {
sz := len(sharedProgArray) / base.Flag.LowerC
@@ -174,17 +174,17 @@ func (pp *Progs) Appendpp(p *obj.Prog, as obj.As, ftype obj.AddrType, freg int16
return q
}
-func (pp *Progs) settext(fn ir.Node) {
+func (pp *Progs) settext(fn *ir.Func) {
if pp.Text != nil {
base.Fatalf("Progs.settext called twice")
}
ptxt := pp.Prog(obj.ATEXT)
pp.Text = ptxt
- fn.Func().LSym.Func().Text = ptxt
+ fn.LSym.Func().Text = ptxt
ptxt.From.Type = obj.TYPE_MEM
ptxt.From.Name = obj.NAME_EXTERN
- ptxt.From.Sym = fn.Func().LSym
+ ptxt.From.Sym = fn.LSym
}
// initLSym defines f's obj.LSym and initializes it based on the
@@ -281,7 +281,7 @@ func initLSym(f *ir.Func, hasBody bool) {
// See test/recover.go for test cases and src/reflect/value.go
// for the actual functions being considered.
if base.Ctxt.Pkgpath == "reflect" {
- switch f.Nname.Sym().Name {
+ switch f.Sym().Name {
case "callReflect", "callMethod":
flag |= obj.WRAPPER
}
diff --git a/src/cmd/compile/internal/gc/iexport.go b/src/cmd/compile/internal/gc/iexport.go
index ef52e40f21..14356013de 100644
--- a/src/cmd/compile/internal/gc/iexport.go
+++ b/src/cmd/compile/internal/gc/iexport.go
@@ -259,8 +259,8 @@ func iexport(out *bufio.Writer) {
p := iexporter{
allPkgs: map[*types.Pkg]bool{},
stringIndex: map[string]uint64{},
- declIndex: map[ir.Node]uint64{},
- inlineIndex: map[ir.Node]uint64{},
+ declIndex: map[*types.Sym]uint64{},
+ inlineIndex: map[*types.Sym]uint64{},
typIndex: map[*types.Type]uint64{},
}
@@ -290,6 +290,10 @@ func iexport(out *bufio.Writer) {
w.writeIndex(p.inlineIndex, false)
w.flush()
+ if *base.Flag.LowerV {
+ fmt.Printf("export: hdr strings %v, data %v, index %v\n", p.strings.Len(), dataLen, p.data0.Len())
+ }
+
// Assemble header.
var hdr intWriter
hdr.WriteByte('i')
@@ -310,37 +314,34 @@ func iexport(out *bufio.Writer) {
out.Write(base.Ctxt.Fingerprint[:])
}
-// writeIndex writes out an object index. mainIndex indicates whether
+// writeIndex writes out a symbol index. mainIndex indicates whether
// we're writing out the main index, which is also read by
// non-compiler tools and includes a complete package description
// (i.e., name and height).
-func (w *exportWriter) writeIndex(index map[ir.Node]uint64, mainIndex bool) {
- // Build a map from packages to objects from that package.
- pkgObjs := map[*types.Pkg][]ir.Node{}
+func (w *exportWriter) writeIndex(index map[*types.Sym]uint64, mainIndex bool) {
+ // Build a map from packages to symbols from that package.
+ pkgSyms := map[*types.Pkg][]*types.Sym{}
// For the main index, make sure to include every package that
// we reference, even if we're not exporting (or reexporting)
// any symbols from it.
if mainIndex {
- pkgObjs[ir.LocalPkg] = nil
+ pkgSyms[types.LocalPkg] = nil
for pkg := range w.p.allPkgs {
- pkgObjs[pkg] = nil
+ pkgSyms[pkg] = nil
}
}
- for n := range index {
- pkgObjs[n.Sym().Pkg] = append(pkgObjs[n.Sym().Pkg], n)
+ // Group symbols by package.
+ for sym := range index {
+ pkgSyms[sym.Pkg] = append(pkgSyms[sym.Pkg], sym)
}
+ // Sort packages by path.
var pkgs []*types.Pkg
- for pkg, objs := range pkgObjs {
+ for pkg := range pkgSyms {
pkgs = append(pkgs, pkg)
-
- sort.Slice(objs, func(i, j int) bool {
- return objs[i].Sym().Name < objs[j].Sym().Name
- })
}
-
sort.Slice(pkgs, func(i, j int) bool {
return pkgs[i].Path < pkgs[j].Path
})
@@ -353,11 +354,16 @@ func (w *exportWriter) writeIndex(index map[ir.Node]uint64, mainIndex bool) {
w.uint64(uint64(pkg.Height))
}
- objs := pkgObjs[pkg]
- w.uint64(uint64(len(objs)))
- for _, n := range objs {
- w.string(n.Sym().Name)
- w.uint64(index[n])
+ // Sort symbols within a package by name.
+ syms := pkgSyms[pkg]
+ sort.Slice(syms, func(i, j int) bool {
+ return syms[i].Name < syms[j].Name
+ })
+
+ w.uint64(uint64(len(syms)))
+ for _, sym := range syms {
+ w.string(sym.Name)
+ w.uint64(index[sym])
}
}
}
@@ -368,14 +374,14 @@ type iexporter struct {
// main index.
allPkgs map[*types.Pkg]bool
- declTodo ir.NodeQueue
+ declTodo ir.NameQueue
strings intWriter
stringIndex map[string]uint64
data0 intWriter
- declIndex map[ir.Node]uint64
- inlineIndex map[ir.Node]uint64
+ declIndex map[*types.Sym]uint64
+ inlineIndex map[*types.Sym]uint64
typIndex map[*types.Type]uint64
}
@@ -387,6 +393,10 @@ func (p *iexporter) stringOff(s string) uint64 {
off = uint64(p.strings.Len())
p.stringIndex[s] = off
+ if *base.Flag.LowerV {
+ fmt.Printf("export: str %v %.40q\n", off, s)
+ }
+
p.strings.uint64(uint64(len(s)))
p.strings.WriteString(s)
}
@@ -394,21 +404,21 @@ func (p *iexporter) stringOff(s string) uint64 {
}
// pushDecl adds n to the declaration work queue, if not already present.
-func (p *iexporter) pushDecl(n ir.Node) {
- if n.Sym() == nil || ir.AsNode(n.Sym().Def) != n && n.Op() != ir.OTYPE {
+func (p *iexporter) pushDecl(n *ir.Name) {
+ if n.Sym() == nil || n.Sym().Def != n && n.Op() != ir.OTYPE {
base.Fatalf("weird Sym: %v, %v", n, n.Sym())
}
// Don't export predeclared declarations.
- if n.Sym().Pkg == ir.BuiltinPkg || n.Sym().Pkg == unsafepkg {
+ if n.Sym().Pkg == types.BuiltinPkg || n.Sym().Pkg == unsafepkg {
return
}
- if _, ok := p.declIndex[n]; ok {
+ if _, ok := p.declIndex[n.Sym()]; ok {
return
}
- p.declIndex[n] = ^uint64(0) // mark n present in work queue
+ p.declIndex[n.Sym()] = ^uint64(0) // mark n present in work queue
p.declTodo.PushRight(n)
}
@@ -423,7 +433,7 @@ type exportWriter struct {
prevColumn int64
}
-func (p *iexporter) doDecl(n ir.Node) {
+func (p *iexporter) doDecl(n *ir.Name) {
w := p.newWriter()
w.setPkg(n.Sym().Pkg, false)
@@ -454,7 +464,8 @@ func (p *iexporter) doDecl(n ir.Node) {
case ir.OLITERAL:
// Constant.
- n = typecheck(n, ctxExpr)
+ // TODO(mdempsky): Do we still need this typecheck? If so, why?
+ n = typecheck(n, ctxExpr).(*ir.Name)
w.tag('C')
w.pos(n.Pos())
w.value(n.Type(), n.Val())
@@ -472,15 +483,15 @@ func (p *iexporter) doDecl(n ir.Node) {
w.tag('T')
w.pos(n.Pos())
- underlying := n.Type().Orig
- if underlying == types.Errortype.Orig {
+ underlying := n.Type().Underlying()
+ if underlying == types.ErrorType.Underlying() {
// For "type T error", use error as the
// underlying type instead of error's own
// underlying anonymous interface. This
// ensures consistency with how importers may
// declare error (e.g., go/types uses nil Pkg
// for predeclared objects).
- underlying = types.Errortype
+ underlying = types.ErrorType
}
w.typ(underlying)
@@ -508,20 +519,28 @@ func (p *iexporter) doDecl(n ir.Node) {
base.Fatalf("unexpected node: %v", n)
}
- p.declIndex[n] = w.flush()
+ w.finish("dcl", p.declIndex, n.Sym())
}
func (w *exportWriter) tag(tag byte) {
w.data.WriteByte(tag)
}
-func (p *iexporter) doInline(f ir.Node) {
+func (w *exportWriter) finish(what string, index map[*types.Sym]uint64, sym *types.Sym) {
+ off := w.flush()
+ if *base.Flag.LowerV {
+ fmt.Printf("export: %v %v %v\n", what, off, sym)
+ }
+ index[sym] = off
+}
+
+func (p *iexporter) doInline(f *ir.Name) {
w := p.newWriter()
w.setPkg(fnpkg(f), false)
w.stmtList(ir.AsNodes(f.Func().Inl.Body))
- p.inlineIndex[f] = w.flush()
+ w.finish("inl", p.inlineIndex, f.Sym())
}
func (w *exportWriter) pos(pos src.XPos) {
@@ -572,7 +591,7 @@ func (w *exportWriter) pkg(pkg *types.Pkg) {
func (w *exportWriter) qualifiedIdent(n ir.Node) {
// Ensure any referenced declarations are written out too.
- w.p.pushDecl(n)
+ w.p.pushDecl(n.Name())
s := n.Sym()
w.string(s.Name)
@@ -593,7 +612,7 @@ func (w *exportWriter) selector(s *types.Sym) {
} else {
pkg := w.currPkg
if types.IsExported(name) {
- pkg = ir.LocalPkg
+ pkg = types.LocalPkg
}
if s.Pkg != pkg {
base.Fatalf("package mismatch in selector: %v in package %q, but want %q", s, s.Pkg.Path, pkg.Path)
@@ -622,7 +641,11 @@ func (p *iexporter) typOff(t *types.Type) uint64 {
if !ok {
w := p.newWriter()
w.doTyp(t)
- off = predeclReserved + w.flush()
+ rawOff := w.flush()
+ if *base.Flag.LowerV {
+ fmt.Printf("export: typ %v %v\n", rawOff, t)
+ }
+ off = predeclReserved + rawOff
p.typIndex[t] = off
}
return off
@@ -633,17 +656,17 @@ func (w *exportWriter) startType(k itag) {
}
func (w *exportWriter) doTyp(t *types.Type) {
- if t.Sym != nil {
- if t.Sym.Pkg == ir.BuiltinPkg || t.Sym.Pkg == unsafepkg {
+ if t.Sym() != nil {
+ if t.Sym().Pkg == types.BuiltinPkg || t.Sym().Pkg == unsafepkg {
base.Fatalf("builtin type missing from typIndex: %v", t)
}
w.startType(definedType)
- w.qualifiedIdent(typenod(t))
+ w.qualifiedIdent(t.Obj().(*ir.Name))
return
}
- switch t.Etype {
+ switch t.Kind() {
case types.TPTR:
w.startType(pointerType)
w.typ(t.Elem())
@@ -717,10 +740,8 @@ func (w *exportWriter) doTyp(t *types.Type) {
}
func (w *exportWriter) setPkg(pkg *types.Pkg, write bool) {
- if pkg == nil {
- // TODO(mdempsky): Proactively set Pkg for types and
- // remove this fallback logic.
- pkg = ir.LocalPkg
+ if pkg == types.NoPkg {
+ base.Fatalf("missing pkg")
}
if write {
@@ -747,7 +768,7 @@ func (w *exportWriter) paramList(fs []*types.Field) {
func (w *exportWriter) param(f *types.Field) {
w.pos(f.Pos)
- w.localIdent(ir.OrigSym(f.Sym), 0)
+ w.localIdent(types.OrigSym(f.Sym), 0)
w.typ(f.Type)
}
@@ -761,7 +782,7 @@ func constTypeOf(typ *types.Type) constant.Kind {
return constant.Complex
}
- switch typ.Etype {
+ switch typ.Kind() {
case types.TBOOL:
return constant.Bool
case types.TSTRING:
@@ -808,7 +829,7 @@ func intSize(typ *types.Type) (signed bool, maxBytes uint) {
return true, Mpprec / 8
}
- switch typ.Etype {
+ switch typ.Kind() {
case types.TFLOAT32, types.TCOMPLEX64:
return true, 3
case types.TFLOAT64, types.TCOMPLEX128:
@@ -820,7 +841,7 @@ func intSize(typ *types.Type) (signed bool, maxBytes uint) {
// The go/types API doesn't expose sizes to importers, so they
// don't know how big these types are.
- switch typ.Etype {
+ switch typ.Kind() {
case types.TINT, types.TUINT, types.TUINTPTR:
maxBytes = 8
}
@@ -960,7 +981,7 @@ func (w *exportWriter) varExt(n ir.Node) {
w.symIdx(n.Sym())
}
-func (w *exportWriter) funcExt(n ir.Node) {
+func (w *exportWriter) funcExt(n *ir.Name) {
w.linkname(n.Sym())
w.symIdx(n.Sym())
@@ -979,14 +1000,7 @@ func (w *exportWriter) funcExt(n ir.Node) {
}
// 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)
- }
+ w.pos(n.Func().Endlineno)
} else {
w.uint64(0)
}
@@ -994,7 +1008,7 @@ func (w *exportWriter) funcExt(n ir.Node) {
func (w *exportWriter) methExt(m *types.Field) {
w.bool(m.Nointerface())
- w.funcExt(ir.AsNode(m.Nname))
+ w.funcExt(m.Nname.(*ir.Name))
}
func (w *exportWriter) linkname(s *types.Sym) {
@@ -1056,15 +1070,23 @@ func (w *exportWriter) stmt(n ir.Node) {
}
switch op := n.Op(); op {
+ case ir.OBLOCK:
+ // No OBLOCK in export data.
+ // Inline content into this statement list,
+ // like the init list above.
+ // (At the moment neither the parser nor the typechecker
+ // generate OBLOCK nodes except to denote an empty
+ // function body, although that may change.)
+ for _, n := range n.List().Slice() {
+ w.stmt(n)
+ }
+
case ir.ODCL:
w.op(ir.ODCL)
w.pos(n.Left().Pos())
w.localName(n.Left())
w.typ(n.Left().Type())
- // case ODCLFIELD:
- // unimplemented - handled by default case
-
case ir.OAS:
// Don't export "v = " initializing statements, hope they're always
// preceded by the DCL which will be re-parsed and typecheck to reproduce
@@ -1085,18 +1107,12 @@ func (w *exportWriter) stmt(n ir.Node) {
w.expr(n.Right())
}
- case ir.OAS2:
+ case ir.OAS2, ir.OAS2DOTTYPE, ir.OAS2FUNC, ir.OAS2MAPR, ir.OAS2RECV:
w.op(ir.OAS2)
w.pos(n.Pos())
w.exprList(n.List())
w.exprList(n.Rlist())
- case ir.OAS2DOTTYPE, ir.OAS2FUNC, ir.OAS2MAPR, ir.OAS2RECV:
- w.op(ir.OAS2)
- w.pos(n.Pos())
- w.exprList(n.List())
- w.exprList(ir.AsNodes([]ir.Node{n.Right()}))
-
case ir.ORETURN:
w.op(ir.ORETURN)
w.pos(n.Pos())
@@ -1146,18 +1162,14 @@ func (w *exportWriter) stmt(n ir.Node) {
w.op(ir.OFALL)
w.pos(n.Pos())
- case ir.OBREAK, ir.OCONTINUE:
+ case ir.OBREAK, ir.OCONTINUE, ir.OGOTO, ir.OLABEL:
w.op(op)
w.pos(n.Pos())
- w.exprsOrNil(n.Left(), nil)
-
- case ir.OEMPTY:
- // nothing to emit
-
- case ir.OGOTO, ir.OLABEL:
- w.op(op)
- w.pos(n.Pos())
- w.string(n.Sym().Name)
+ label := ""
+ if sym := n.Sym(); sym != nil {
+ label = sym.Name
+ }
+ w.string(label)
default:
base.Fatalf("exporter: CANNOT EXPORT: %v\nPlease notify gri@\n", n.Op())
@@ -1211,11 +1223,7 @@ func (w *exportWriter) expr(n ir.Node) {
if !n.Type().HasNil() {
base.Fatalf("unexpected type for nil: %v", n.Type())
}
- if n.Orig() != nil && n.Orig() != n {
- w.expr(n.Orig())
- break
- }
- w.op(ir.OLITERAL)
+ w.op(ir.ONIL)
w.pos(n.Pos())
w.typ(n.Type())
@@ -1304,8 +1312,7 @@ func (w *exportWriter) expr(n ir.Node) {
w.op(ir.OXDOT)
w.pos(n.Pos())
w.expr(n.Left())
- // Right node should be ONAME
- w.selector(n.Right().Sym())
+ w.selector(n.Sym())
case ir.OXDOT, ir.ODOT, ir.ODOTPTR, ir.ODOTINTER, ir.ODOTMETH:
w.op(ir.OXDOT)
@@ -1464,7 +1471,7 @@ func (w *exportWriter) localName(n ir.Node) {
// PPARAM/PPARAMOUT, because we only want to include vargen in
// non-param names.
var v int32
- if n.Class() == ir.PAUTO || (n.Class() == ir.PAUTOHEAP && n.Name().Param.Stackcopy == nil) {
+ if n.Class() == ir.PAUTO || (n.Class() == ir.PAUTOHEAP && n.Name().Stackcopy == nil) {
v = n.Name().Vargen
}
diff --git a/src/cmd/compile/internal/gc/iimport.go b/src/cmd/compile/internal/gc/iimport.go
index 77078c118a..3c9693e5fc 100644
--- a/src/cmd/compile/internal/gc/iimport.go
+++ b/src/cmd/compile/internal/gc/iimport.go
@@ -41,7 +41,7 @@ var (
inlineImporter = map[*types.Sym]iimporterAndOffset{}
)
-func expandDecl(n ir.Node) {
+func expandDecl(n *ir.Name) {
if n.Op() != ir.ONONAME {
return
}
@@ -55,12 +55,12 @@ func expandDecl(n ir.Node) {
r.doDecl(n)
}
-func expandInline(fn ir.Node) {
- if fn.Func().Inl.Body != nil {
+func expandInline(fn *ir.Func) {
+ if fn.Inl.Body != nil {
return
}
- r := importReaderFor(fn, inlineImporter)
+ r := importReaderFor(fn.Nname, inlineImporter)
if r == nil {
base.Fatalf("missing import reader for %v", fn)
}
@@ -68,7 +68,7 @@ func expandInline(fn ir.Node) {
r.doInline(fn)
}
-func importReaderFor(n ir.Node, importers map[*types.Sym]iimporterAndOffset) *importReader {
+func importReaderFor(n *ir.Name, importers map[*types.Sym]iimporterAndOffset) *importReader {
x, ok := importers[n.Sym()]
if !ok {
return nil
@@ -148,7 +148,7 @@ func iimport(pkg *types.Pkg, in *bio.Reader) (fingerprint goobj.FingerprintType)
if pkg.Name == "" {
pkg.Name = pkgName
pkg.Height = pkgHeight
- ir.NumImport[pkgName]++
+ types.NumImport[pkgName]++
// TODO(mdempsky): This belongs somewhere else.
pkg.Lookup("_").Def = ir.BlankNode
@@ -175,7 +175,7 @@ func iimport(pkg *types.Pkg, in *bio.Reader) (fingerprint goobj.FingerprintType)
if s.Def != nil {
base.Fatalf("unexpected definition for %v: %v", s, ir.AsNode(s.Def))
}
- s.Def = npos(src.NoXPos, dclname(s))
+ s.Def = ir.NewDeclNameAt(src.NoXPos, s)
}
}
@@ -316,7 +316,7 @@ func (r *importReader) doDecl(n ir.Node) {
// after the underlying type has been assigned.
defercheckwidth()
underlying := r.typ()
- setUnderlying(t, underlying)
+ t.SetUnderlying(underlying)
resumecheckwidth()
if underlying.IsInterface() {
@@ -331,7 +331,9 @@ func (r *importReader) doDecl(n ir.Node) {
recv := r.param()
mtyp := r.signature(recv)
- m := newfuncnamel(mpos, methodSym(recv.Type, msym), new(ir.Func))
+ fn := ir.NewFunc(mpos)
+ fn.SetType(mtyp)
+ m := newFuncNameAt(mpos, methodSym(recv.Type, msym), fn)
m.SetType(mtyp)
m.SetClass(ir.PFUNC)
// methodSym already marked m.Sym as a function.
@@ -435,7 +437,7 @@ func (r *importReader) ident() *types.Sym {
}
pkg := r.currPkg
if types.IsExported(name) {
- pkg = ir.LocalPkg
+ pkg = types.LocalPkg
}
return pkg.Lookup(name)
}
@@ -501,7 +503,7 @@ func (r *importReader) typ1() *types.Type {
// type.
n := ir.AsNode(r.qualifiedIdent().PkgDef())
if n.Op() == ir.ONONAME {
- expandDecl(n)
+ expandDecl(n.(*ir.Name))
}
if n.Op() != ir.OTYPE {
base.Fatalf("expected OTYPE, got %v: %v, %v", n.Op(), n.Sym(), n)
@@ -543,10 +545,7 @@ func (r *importReader) typ1() *types.Type {
fs[i] = f
}
- t := types.New(types.TSTRUCT)
- t.SetPkg(r.currPkg)
- t.SetFields(fs)
- return t
+ return types.NewStruct(r.currPkg, fs)
case interfaceType:
r.setPkg()
@@ -568,9 +567,7 @@ func (r *importReader) typ1() *types.Type {
methods[i] = types.NewField(pos, sym, typ)
}
- t := types.New(types.TINTER)
- t.SetPkg(r.currPkg)
- t.SetInterface(append(embeddeds, methods...))
+ t := types.NewInterface(r.currPkg, append(embeddeds, methods...))
// Ensure we expand the interface in the frontend (#25055).
checkwidth(t)
@@ -588,9 +585,7 @@ func (r *importReader) signature(recv *types.Field) *types.Type {
if n := len(params); n > 0 {
params[n-1].SetIsDDD(r.bool())
}
- t := functypefield(recv, params, results)
- t.SetPkg(r.currPkg)
- return t
+ return types.NewSignature(r.currPkg, recv, params, results)
}
func (r *importReader) paramList() []*types.Field {
@@ -695,12 +690,12 @@ func (r *importReader) typeExt(t *types.Type) {
// so we can use index to reference the symbol.
var typeSymIdx = make(map[*types.Type][2]int64)
-func (r *importReader) doInline(n ir.Node) {
- if len(n.Func().Inl.Body) != 0 {
- base.Fatalf("%v already has inline body", n)
+func (r *importReader) doInline(fn *ir.Func) {
+ if len(fn.Inl.Body) != 0 {
+ base.Fatalf("%v already has inline body", fn)
}
- funchdr(n)
+ funchdr(fn)
body := r.stmtList()
funcbody()
if body == nil {
@@ -712,15 +707,15 @@ func (r *importReader) doInline(n ir.Node) {
// functions).
body = []ir.Node{}
}
- n.Func().Inl.Body = body
+ fn.Inl.Body = body
- importlist = append(importlist, n)
+ importlist = append(importlist, fn)
if base.Flag.E > 0 && base.Flag.LowerM > 2 {
if base.Flag.LowerM > 3 {
- fmt.Printf("inl body for %v %#v: %+v\n", n, n.Type(), ir.AsNodes(n.Func().Inl.Body))
+ fmt.Printf("inl body for %v %v: %+v\n", fn, fn.Type(), ir.AsNodes(fn.Inl.Body))
} else {
- fmt.Printf("inl body for %v %#v: %v\n", n, n.Type(), ir.AsNodes(n.Func().Inl.Body))
+ fmt.Printf("inl body for %v %v: %v\n", fn, fn.Type(), ir.AsNodes(fn.Inl.Body))
}
}
}
@@ -747,7 +742,9 @@ func (r *importReader) stmtList() []ir.Node {
if n == nil {
break
}
- // OBLOCK nodes may be created when importing ODCL nodes - unpack them
+ // OBLOCK nodes are not written to the import data directly,
+ // but the handling of ODCL calls liststmt, which creates one.
+ // Inline them into the statement list.
if n.Op() == ir.OBLOCK {
list = append(list, n.List().Slice()...)
} else {
@@ -772,7 +769,7 @@ func (r *importReader) caseList(sw ir.Node) []ir.Node {
caseVar := ir.NewNameAt(cas.Pos(), r.ident())
declare(caseVar, dclcontext)
cas.PtrRlist().Set1(caseVar)
- caseVar.Name().Defn = sw.Left()
+ caseVar.Defn = sw.Left()
}
cas.PtrBody().Set(r.stmtList())
cases[i] = cas
@@ -807,20 +804,19 @@ func (r *importReader) node() ir.Node {
// case OPAREN:
// unreachable - unpacked by exporter
- // case ONIL:
- // unreachable - mapped to OLITERAL
+ case ir.ONIL:
+ pos := r.pos()
+ typ := r.typ()
+
+ n := npos(pos, nodnil())
+ n.SetType(typ)
+ return n
case ir.OLITERAL:
pos := r.pos()
typ := r.typ()
- var n ir.Node
- if typ.HasNil() {
- n = nodnil()
- } else {
- n = ir.NewLiteral(r.value(typ))
- }
- n = npos(pos, n)
+ n := npos(pos, ir.NewLiteral(r.value(typ)))
n.SetType(typ)
return n
@@ -834,16 +830,16 @@ func (r *importReader) node() ir.Node {
// unreachable - should have been resolved by typechecking
case ir.OTYPE:
- return typenod(r.typ())
+ return ir.TypeNode(r.typ())
case ir.OTYPESW:
- n := ir.NodAt(r.pos(), ir.OTYPESW, nil, nil)
+ pos := r.pos()
+ var tag *ir.Ident
if s := r.ident(); s != nil {
- n.SetLeft(npos(n.Pos(), newnoname(s)))
+ tag = ir.NewIdent(pos, s)
}
- right, _ := r.exprsOrNil()
- n.SetRight(right)
- return n
+ expr, _ := r.exprsOrNil()
+ return ir.NewTypeSwitchGuard(pos, tag, expr)
// case OTARRAY, OTMAP, OTCHAN, OTSTRUCT, OTINTER, OTFUNC:
// unreachable - should have been resolved by typechecking
@@ -858,7 +854,7 @@ func (r *importReader) node() ir.Node {
// TODO(mdempsky): Export position information for OSTRUCTKEY nodes.
savedlineno := base.Pos
base.Pos = r.pos()
- n := ir.NodAt(base.Pos, ir.OCOMPLIT, nil, typenod(r.typ()))
+ n := ir.NodAt(base.Pos, ir.OCOMPLIT, nil, ir.TypeNode(r.typ()))
n.PtrList().Set(r.elemList()) // special handling of field names
base.Pos = savedlineno
return n
@@ -867,7 +863,7 @@ func (r *importReader) node() ir.Node {
// unreachable - mapped to case OCOMPLIT below by exporter
case ir.OCOMPLIT:
- n := ir.NodAt(r.pos(), ir.OCOMPLIT, nil, typenod(r.typ()))
+ n := ir.NodAt(r.pos(), ir.OCOMPLIT, nil, ir.TypeNode(r.typ()))
n.PtrList().Set(r.exprList())
return n
@@ -942,7 +938,7 @@ func (r *importReader) node() ir.Node {
case ir.OMAKEMAP, ir.OMAKECHAN, ir.OMAKESLICE:
n := npos(r.pos(), builtinCall(ir.OMAKE))
- n.PtrList().Append(typenod(r.typ()))
+ n.PtrList().Append(ir.TypeNode(r.typ()))
n.PtrList().Append(r.exprList()...)
return n
@@ -968,13 +964,10 @@ func (r *importReader) node() ir.Node {
// statements
case ir.ODCL:
pos := r.pos()
- lhs := npos(pos, dclname(r.ident()))
- typ := typenod(r.typ())
+ lhs := ir.NewDeclNameAt(pos, r.ident())
+ typ := ir.TypeNode(r.typ())
return npos(pos, liststmt(variter([]ir.Node{lhs}, typ, nil))) // TODO(gri) avoid list creation
- // case ODCLFIELD:
- // unimplemented
-
// case OAS, OASWB:
// unreachable - mapped to OAS case below by exporter
@@ -1052,20 +1045,14 @@ func (r *importReader) node() ir.Node {
n := ir.NodAt(r.pos(), ir.OFALL, nil, nil)
return n
- case ir.OBREAK, ir.OCONTINUE:
- pos := r.pos()
- left, _ := r.exprsOrNil()
- if left != nil {
- left = NewName(left.Sym())
- }
- return ir.NodAt(pos, op, left, nil)
-
// case OEMPTY:
// unreachable - not emitted by exporter
- case ir.OGOTO, ir.OLABEL:
+ case ir.OBREAK, ir.OCONTINUE, ir.OGOTO, ir.OLABEL:
n := ir.NodAt(r.pos(), op, nil, nil)
- n.SetSym(lookup(r.string()))
+ if label := r.string(); label != "" {
+ n.SetSym(lookup(label))
+ }
return n
case ir.OEND:
diff --git a/src/cmd/compile/internal/gc/init.go b/src/cmd/compile/internal/gc/init.go
index 2b7ecd1d05..e0907f952c 100644
--- a/src/cmd/compile/internal/gc/init.go
+++ b/src/cmd/compile/internal/gc/init.go
@@ -19,7 +19,7 @@ var renameinitgen int
// Function collecting autotmps generated during typechecking,
// to be included in the package-level init function.
-var initTodo = ir.Nod(ir.ODCLFUNC, nil, nil)
+var initTodo = ir.NewFunc(base.Pos)
func renameinit() *types.Sym {
s := lookupN("init.", renameinitgen)
@@ -27,6 +27,9 @@ func renameinit() *types.Sym {
return s
}
+// List of imported packages, in source code order. See #31636.
+var sourceOrderImports []*types.Pkg
+
// fninit makes an initialization record for the package.
// See runtime/proc.go:initTask for its layout.
// The 3 tasks for initialization are:
@@ -40,32 +43,39 @@ func fninit(n []ir.Node) {
var fns []*obj.LSym // functions to call for package initialization
// Find imported packages with init tasks.
- for _, s := range types.InitSyms {
- deps = append(deps, s.Linksym())
+ for _, pkg := range sourceOrderImports {
+ n := resolve(ir.AsNode(pkg.Lookup(".inittask").Def))
+ if n == nil {
+ continue
+ }
+ if n.Op() != ir.ONAME || n.Class() != ir.PEXTERN {
+ base.Fatalf("bad inittask: %v", n)
+ }
+ deps = append(deps, n.Sym().Linksym())
}
// Make a function that contains all the initialization statements.
if len(nf) > 0 {
base.Pos = nf[0].Pos() // prolog/epilog gets line number of first init stmt
initializers := lookup("init")
- fn := dclfunc(initializers, ir.Nod(ir.OTFUNC, nil, nil))
- for _, dcl := range initTodo.Func().Dcl {
- dcl.Name().Curfn = fn
+ fn := dclfunc(initializers, ir.NewFuncType(base.Pos, nil, nil, nil))
+ for _, dcl := range initTodo.Dcl {
+ dcl.Curfn = fn
}
- fn.Func().Dcl = append(fn.Func().Dcl, initTodo.Func().Dcl...)
- initTodo.Func().Dcl = nil
+ fn.Dcl = append(fn.Dcl, initTodo.Dcl...)
+ initTodo.Dcl = nil
fn.PtrBody().Set(nf)
funcbody()
- fn = typecheck(fn, ctxStmt)
+ typecheckFunc(fn)
Curfn = fn
typecheckslice(nf, ctxStmt)
Curfn = nil
xtop = append(xtop, fn)
fns = append(fns, initializers.Linksym())
}
- if initTodo.Func().Dcl != nil {
+ if initTodo.Dcl != nil {
// We only generate temps using initTodo if there
// are package-scope initialization statements, so
// something's weird if we get here.
@@ -78,13 +88,15 @@ func fninit(n []ir.Node) {
s := lookupN("init.", i)
fn := ir.AsNode(s.Def).Name().Defn
// Skip init functions with empty bodies.
- if fn.Body().Len() == 1 && fn.Body().First().Op() == ir.OEMPTY {
- continue
+ if fn.Body().Len() == 1 {
+ if stmt := fn.Body().First(); stmt.Op() == ir.OBLOCK && stmt.List().Len() == 0 {
+ continue
+ }
}
fns = append(fns, s.Linksym())
}
- if len(deps) == 0 && len(fns) == 0 && ir.LocalPkg.Name != "main" && ir.LocalPkg.Name != "runtime" {
+ if len(deps) == 0 && len(fns) == 0 && types.LocalPkg.Name != "main" && types.LocalPkg.Name != "runtime" {
return // nothing to initialize
}
diff --git a/src/cmd/compile/internal/gc/initorder.go b/src/cmd/compile/internal/gc/initorder.go
index 1003f131b8..7f1f3cba92 100644
--- a/src/cmd/compile/internal/gc/initorder.go
+++ b/src/cmd/compile/internal/gc/initorder.go
@@ -110,7 +110,7 @@ func initOrder(l []ir.Node) []ir.Node {
// first.
base.ExitIfErrors()
- findInitLoopAndExit(firstLHS(n), new([]ir.Node))
+ findInitLoopAndExit(firstLHS(n), new([]*ir.Name))
base.Fatalf("initialization unfinished, but failed to identify loop")
}
}
@@ -136,7 +136,7 @@ func (o *InitOrder) processAssign(n ir.Node) {
// Compute number of variable dependencies and build the
// inverse dependency ("blocking") graph.
for dep := range collectDeps(n, true) {
- defn := dep.Name().Defn
+ defn := dep.Defn
// Skip dependencies on functions (PFUNC) and
// variables already initialized (InitDone).
if dep.Class() != ir.PEXTERN || defn.Initorder() == InitDone {
@@ -183,7 +183,7 @@ func (o *InitOrder) flushReady(initialize func(ir.Node)) {
// path points to a slice used for tracking the sequence of
// variables/functions visited. Using a pointer to a slice allows the
// slice capacity to grow and limit reallocations.
-func findInitLoopAndExit(n ir.Node, path *[]ir.Node) {
+func findInitLoopAndExit(n *ir.Name, path *[]*ir.Name) {
// We implement a simple DFS loop-finding algorithm. This
// could be faster, but initialization cycles are rare.
@@ -196,14 +196,14 @@ func findInitLoopAndExit(n ir.Node, path *[]ir.Node) {
// There might be multiple loops involving n; by sorting
// references, we deterministically pick the one reported.
- refers := collectDeps(n.Name().Defn, false).Sorted(func(ni, nj ir.Node) bool {
+ refers := collectDeps(n.Name().Defn, false).Sorted(func(ni, nj *ir.Name) bool {
return ni.Pos().Before(nj.Pos())
})
*path = append(*path, n)
for _, ref := range refers {
// Short-circuit variables that were initialized.
- if ref.Class() == ir.PEXTERN && ref.Name().Defn.Initorder() == InitDone {
+ if ref.Class() == ir.PEXTERN && ref.Defn.Initorder() == InitDone {
continue
}
@@ -215,7 +215,7 @@ func findInitLoopAndExit(n ir.Node, path *[]ir.Node) {
// reportInitLoopAndExit reports and initialization loop as an error
// and exits. However, if l is not actually an initialization loop, it
// simply returns instead.
-func reportInitLoopAndExit(l []ir.Node) {
+func reportInitLoopAndExit(l []*ir.Name) {
// Rotate loop so that the earliest variable declaration is at
// the start.
i := -1
@@ -250,13 +250,13 @@ func reportInitLoopAndExit(l []ir.Node) {
// variables that declaration n depends on. If transitive is true,
// then it also includes the transitive dependencies of any depended
// upon functions (but not variables).
-func collectDeps(n ir.Node, transitive bool) ir.NodeSet {
+func collectDeps(n ir.Node, transitive bool) ir.NameSet {
d := initDeps{transitive: transitive}
switch n.Op() {
case ir.OAS:
d.inspect(n.Right())
case ir.OAS2DOTTYPE, ir.OAS2FUNC, ir.OAS2MAPR, ir.OAS2RECV:
- d.inspect(n.Right())
+ d.inspect(n.Rlist().First())
case ir.ODCLFUNC:
d.inspectList(n.Body())
default:
@@ -267,7 +267,7 @@ func collectDeps(n ir.Node, transitive bool) ir.NodeSet {
type initDeps struct {
transitive bool
- seen ir.NodeSet
+ seen ir.NameSet
}
func (d *initDeps) inspect(n ir.Node) { ir.Inspect(n, d.visit) }
@@ -284,11 +284,11 @@ func (d *initDeps) visit(n ir.Node) bool {
case ir.ONAME:
switch n.Class() {
case ir.PEXTERN, ir.PFUNC:
- d.foundDep(n)
+ d.foundDep(n.(*ir.Name))
}
case ir.OCLOSURE:
- d.inspectList(n.Func().Decl.Body())
+ d.inspectList(n.Func().Body())
case ir.ODOTMETH, ir.OCALLPART:
d.foundDep(methodExprName(n))
@@ -299,7 +299,7 @@ func (d *initDeps) visit(n ir.Node) bool {
// foundDep records that we've found a dependency on n by adding it to
// seen.
-func (d *initDeps) foundDep(n ir.Node) {
+func (d *initDeps) foundDep(n *ir.Name) {
// Can happen with method expressions involving interface
// types; e.g., fixedbugs/issue4495.go.
if n == nil {
@@ -308,7 +308,7 @@ func (d *initDeps) foundDep(n ir.Node) {
// Names without definitions aren't interesting as far as
// initialization ordering goes.
- if n.Name().Defn == nil {
+ if n.Defn == nil {
return
}
@@ -317,7 +317,7 @@ func (d *initDeps) foundDep(n ir.Node) {
}
d.seen.Add(n)
if d.transitive && n.Class() == ir.PFUNC {
- d.inspectList(n.Name().Defn.Body())
+ d.inspectList(n.Defn.Body())
}
}
@@ -345,12 +345,12 @@ func (s *declOrder) Pop() interface{} {
// firstLHS returns the first expression on the left-hand side of
// assignment n.
-func firstLHS(n ir.Node) ir.Node {
+func firstLHS(n ir.Node) *ir.Name {
switch n.Op() {
case ir.OAS:
- return n.Left()
+ return n.Left().Name()
case ir.OAS2DOTTYPE, ir.OAS2FUNC, ir.OAS2RECV, ir.OAS2MAPR:
- return n.List().First()
+ return n.List().First().Name()
}
base.Fatalf("unexpected Op: %v", n.Op())
diff --git a/src/cmd/compile/internal/gc/inl.go b/src/cmd/compile/internal/gc/inl.go
index 6310762c1f..37e5167c25 100644
--- a/src/cmd/compile/internal/gc/inl.go
+++ b/src/cmd/compile/internal/gc/inl.go
@@ -33,6 +33,7 @@ import (
"cmd/compile/internal/types"
"cmd/internal/obj"
"cmd/internal/src"
+ "errors"
"fmt"
"go/constant"
"strings"
@@ -53,7 +54,7 @@ const (
// Get the function's package. For ordinary functions it's on the ->sym, but for imported methods
// the ->sym can be re-used in the local package, so peel it off the receiver's type.
-func fnpkg(fn ir.Node) *types.Pkg {
+func fnpkg(fn *ir.Name) *types.Pkg {
if ir.IsMethod(fn) {
// method
rcvr := fn.Type().Recv().Type
@@ -61,10 +62,10 @@ func fnpkg(fn ir.Node) *types.Pkg {
if rcvr.IsPtr() {
rcvr = rcvr.Elem()
}
- if rcvr.Sym == nil {
+ if rcvr.Sym() == nil {
base.Fatalf("receiver with no sym: [%v] %L (%v)", fn.Sym(), fn, rcvr)
}
- return rcvr.Sym.Pkg
+ return rcvr.Sym().Pkg
}
// non-method
@@ -73,8 +74,8 @@ func fnpkg(fn ir.Node) *types.Pkg {
// Lazy typechecking of imported bodies. For local functions, caninl will set ->typecheck
// because they're a copy of an already checked body.
-func typecheckinl(fn ir.Node) {
- lno := setlineno(fn)
+func typecheckinl(fn *ir.Func) {
+ lno := setlineno(fn.Nname)
expandInline(fn)
@@ -82,19 +83,19 @@ func typecheckinl(fn ir.Node) {
// their bodies may refer to unsafe as long as the package
// was marked safe during import (which was checked then).
// the ->inl of a local function has been typechecked before caninl copied it.
- pkg := fnpkg(fn)
+ pkg := fnpkg(fn.Nname)
- if pkg == ir.LocalPkg || pkg == nil {
+ if pkg == types.LocalPkg || pkg == nil {
return // typecheckinl on local function
}
if base.Flag.LowerM > 2 || base.Debug.Export != 0 {
- fmt.Printf("typecheck import [%v] %L { %#v }\n", fn.Sym(), fn, ir.AsNodes(fn.Func().Inl.Body))
+ fmt.Printf("typecheck import [%v] %L { %v }\n", fn.Sym(), fn, ir.AsNodes(fn.Inl.Body))
}
savefn := Curfn
Curfn = fn
- typecheckslice(fn.Func().Inl.Body, ctxStmt)
+ typecheckslice(fn.Inl.Body, ctxStmt)
Curfn = savefn
// During expandInline (which imports fn.Func.Inl.Body),
@@ -102,8 +103,8 @@ func typecheckinl(fn ir.Node) {
// to fn.Func.Inl.Dcl for consistency with how local functions
// behave. (Append because typecheckinl may be called multiple
// times.)
- fn.Func().Inl.Dcl = append(fn.Func().Inl.Dcl, fn.Func().Dcl...)
- fn.Func().Dcl = nil
+ fn.Inl.Dcl = append(fn.Inl.Dcl, fn.Dcl...)
+ fn.Dcl = nil
base.Pos = lno
}
@@ -111,11 +112,8 @@ func typecheckinl(fn ir.Node) {
// Caninl determines whether fn is inlineable.
// If so, caninl saves fn->nbody in fn->inl and substitutes it with a copy.
// fn and ->nbody will already have been typechecked.
-func caninl(fn ir.Node) {
- if fn.Op() != ir.ODCLFUNC {
- base.Fatalf("caninl %v", fn)
- }
- if fn.Func().Nname == nil {
+func caninl(fn *ir.Func) {
+ if fn.Nname == nil {
base.Fatalf("caninl no nname %+v", fn)
}
@@ -124,7 +122,7 @@ func caninl(fn ir.Node) {
defer func() {
if reason != "" {
if base.Flag.LowerM > 1 {
- fmt.Printf("%v: cannot inline %v: %s\n", ir.Line(fn), fn.Func().Nname, reason)
+ fmt.Printf("%v: cannot inline %v: %s\n", ir.Line(fn), fn.Nname, reason)
}
if logopt.Enabled() {
logopt.LogOpt(fn.Pos(), "cannotInlineFunction", "inline", ir.FuncName(fn), reason)
@@ -134,33 +132,33 @@ func caninl(fn ir.Node) {
}
// If marked "go:noinline", don't inline
- if fn.Func().Pragma&ir.Noinline != 0 {
+ if fn.Pragma&ir.Noinline != 0 {
reason = "marked go:noinline"
return
}
// If marked "go:norace" and -race compilation, don't inline.
- if base.Flag.Race && fn.Func().Pragma&ir.Norace != 0 {
+ if base.Flag.Race && fn.Pragma&ir.Norace != 0 {
reason = "marked go:norace with -race compilation"
return
}
// If marked "go:nocheckptr" and -d checkptr compilation, don't inline.
- if base.Debug.Checkptr != 0 && fn.Func().Pragma&ir.NoCheckPtr != 0 {
+ if base.Debug.Checkptr != 0 && fn.Pragma&ir.NoCheckPtr != 0 {
reason = "marked go:nocheckptr"
return
}
// If marked "go:cgo_unsafe_args", don't inline, since the
// function makes assumptions about its argument frame layout.
- if fn.Func().Pragma&ir.CgoUnsafeArgs != 0 {
+ if fn.Pragma&ir.CgoUnsafeArgs != 0 {
reason = "marked go:cgo_unsafe_args"
return
}
// If marked as "go:uintptrescapes", don't inline, since the
// escape information is lost during inlining.
- if fn.Func().Pragma&ir.UintptrEscapes != 0 {
+ if fn.Pragma&ir.UintptrEscapes != 0 {
reason = "marked as having an escaping uintptr argument"
return
}
@@ -169,7 +167,7 @@ func caninl(fn ir.Node) {
// granularity, so inlining yeswritebarrierrec functions can
// confuse it (#22342). As a workaround, disallow inlining
// them for now.
- if fn.Func().Pragma&ir.Yeswritebarrierrec != 0 {
+ if fn.Pragma&ir.Yeswritebarrierrec != 0 {
reason = "marked go:yeswritebarrierrec"
return
}
@@ -184,7 +182,7 @@ func caninl(fn ir.Node) {
base.Fatalf("caninl on non-typechecked function %v", fn)
}
- n := fn.Func().Nname
+ n := fn.Nname
if n.Func().InlinabilityChecked() {
return
}
@@ -207,25 +205,21 @@ func caninl(fn ir.Node) {
visitor := hairyVisitor{
budget: inlineMaxBudget,
extraCallCost: cc,
- usedLocals: make(map[ir.Node]bool),
+ usedLocals: make(map[*ir.Name]bool),
}
- if visitor.visitList(fn.Body()) {
+ if visitor.tooHairy(fn) {
reason = visitor.reason
return
}
- if visitor.budget < 0 {
- reason = fmt.Sprintf("function too complex: cost %d exceeds budget %d", inlineMaxBudget-visitor.budget, inlineMaxBudget)
- return
- }
n.Func().Inl = &ir.Inline{
Cost: inlineMaxBudget - visitor.budget,
- Dcl: inlcopylist(pruneUnusedAutos(n.Name().Defn.Func().Dcl, &visitor)),
- Body: inlcopylist(fn.Body().Slice()),
+ Dcl: pruneUnusedAutos(n.Defn.Func().Dcl, &visitor),
+ Body: ir.DeepCopyList(src.NoXPos, fn.Body().Slice()),
}
if base.Flag.LowerM > 1 {
- fmt.Printf("%v: can inline %#v with cost %d as: %#v { %#v }\n", ir.Line(fn), n, inlineMaxBudget-visitor.budget, fn.Type(), ir.AsNodes(n.Func().Inl.Body))
+ fmt.Printf("%v: can inline %v with cost %d as: %v { %v }\n", ir.Line(fn), n, inlineMaxBudget-visitor.budget, fn.Type(), ir.AsNodes(n.Func().Inl.Body))
} else if base.Flag.LowerM != 0 {
fmt.Printf("%v: can inline %v\n", ir.Line(fn), n)
}
@@ -236,36 +230,38 @@ func caninl(fn ir.Node) {
// inlFlood marks n's inline body for export and recursively ensures
// all called functions are marked too.
-func inlFlood(n ir.Node) {
+func inlFlood(n *ir.Name) {
if n == nil {
return
}
if n.Op() != ir.ONAME || n.Class() != ir.PFUNC {
base.Fatalf("inlFlood: unexpected %v, %v, %v", n, n.Op(), n.Class())
}
- if n.Func() == nil {
+ fn := n.Func()
+ if fn == nil {
base.Fatalf("inlFlood: missing Func on %v", n)
}
- if n.Func().Inl == nil {
+ if fn.Inl == nil {
return
}
- if n.Func().ExportInline() {
+ if fn.ExportInline() {
return
}
- n.Func().SetExportInline(true)
+ fn.SetExportInline(true)
- typecheckinl(n)
+ typecheckinl(fn)
// Recursively identify all referenced functions for
// reexport. We want to include even non-called functions,
// because after inlining they might be callable.
- ir.InspectList(ir.AsNodes(n.Func().Inl.Body), func(n ir.Node) bool {
+ ir.InspectList(ir.AsNodes(fn.Inl.Body), func(n ir.Node) bool {
switch n.Op() {
- case ir.OMETHEXPR:
+ case ir.OMETHEXPR, ir.ODOTMETH:
inlFlood(methodExprName(n))
case ir.ONAME:
+ n := n.(*ir.Name)
switch n.Class() {
case ir.PFUNC:
inlFlood(n)
@@ -274,10 +270,6 @@ func inlFlood(n ir.Node) {
exportsym(n)
}
- case ir.ODOTMETH:
- fn := methodExprName(n)
- inlFlood(fn)
-
case ir.OCALLPART:
// Okay, because we don't yet inline indirect
// calls to method values.
@@ -300,22 +292,30 @@ type hairyVisitor struct {
budget int32
reason string
extraCallCost int32
- usedLocals map[ir.Node]bool
+ usedLocals map[*ir.Name]bool
+ do func(ir.Node) error
}
-// Look for anything we want to punt on.
-func (v *hairyVisitor) visitList(ll ir.Nodes) bool {
- for _, n := range ll.Slice() {
- if v.visit(n) {
- return true
- }
+var errBudget = errors.New("too expensive")
+
+func (v *hairyVisitor) tooHairy(fn *ir.Func) bool {
+ v.do = v.doNode // cache closure
+
+ err := ir.DoChildren(fn, v.do)
+ if err != nil {
+ v.reason = err.Error()
+ return true
+ }
+ if v.budget < 0 {
+ v.reason = fmt.Sprintf("function too complex: cost %d exceeds budget %d", inlineMaxBudget-v.budget, inlineMaxBudget)
+ return true
}
return false
}
-func (v *hairyVisitor) visit(n ir.Node) bool {
+func (v *hairyVisitor) doNode(n ir.Node) error {
if n == nil {
- return false
+ return nil
}
switch n.Op() {
@@ -328,8 +328,7 @@ func (v *hairyVisitor) visit(n ir.Node) bool {
if n.Left().Op() == ir.ONAME && n.Left().Class() == ir.PFUNC && isRuntimePkg(n.Left().Sym().Pkg) {
fn := n.Left().Sym().Name
if fn == "getcallerpc" || fn == "getcallersp" {
- v.reason = "call to " + fn
- return true
+ return errors.New("call to " + fn)
}
if fn == "throw" {
v.budget -= inlineExtraThrowCost
@@ -342,8 +341,8 @@ func (v *hairyVisitor) visit(n ir.Node) bool {
break
}
- if fn := inlCallee(n.Left()); fn != nil && fn.Func().Inl != nil {
- v.budget -= fn.Func().Inl.Cost
+ if fn := inlCallee(n.Left()); fn != nil && fn.Inl != nil {
+ v.budget -= fn.Inl.Cost
break
}
@@ -385,8 +384,7 @@ func (v *hairyVisitor) visit(n ir.Node) bool {
case ir.ORECOVER:
// recover matches the argument frame pointer to find
// the right panic value, so it needs an argument frame.
- v.reason = "call to recover"
- return true
+ return errors.New("call to recover")
case ir.OCLOSURE,
ir.ORANGE,
@@ -395,119 +393,88 @@ func (v *hairyVisitor) visit(n ir.Node) bool {
ir.ODEFER,
ir.ODCLTYPE, // can't print yet
ir.ORETJMP:
- v.reason = "unhandled op " + n.Op().String()
- return true
+ return errors.New("unhandled op " + n.Op().String())
case ir.OAPPEND:
v.budget -= inlineExtraAppendCost
- case ir.ODCLCONST, ir.OEMPTY, ir.OFALL:
+ case ir.ODCLCONST, ir.OFALL:
// These nodes don't produce code; omit from inlining budget.
- return false
+ return nil
- case ir.OLABEL:
- // TODO(mdempsky): Add support for inlining labeled control statements.
- if labeledControl(n) != nil {
- v.reason = "labeled control"
- return true
+ case ir.OFOR, ir.OFORUNTIL, ir.OSWITCH:
+ // ORANGE, OSELECT in "unhandled" above
+ if n.Sym() != nil {
+ return errors.New("labeled control")
}
case ir.OBREAK, ir.OCONTINUE:
if n.Sym() != nil {
- // Should have short-circuited due to labeledControl above.
+ // Should have short-circuited due to labeled control error above.
base.Fatalf("unexpected labeled break/continue: %v", n)
}
case ir.OIF:
if ir.IsConst(n.Left(), constant.Bool) {
// This if and the condition cost nothing.
- return v.visitList(n.Init()) || v.visitList(n.Body()) ||
- v.visitList(n.Rlist())
+ // TODO(rsc): It seems strange that we visit the dead branch.
+ if err := ir.DoList(n.Init(), v.do); err != nil {
+ return err
+ }
+ if err := ir.DoList(n.Body(), v.do); err != nil {
+ return err
+ }
+ if err := ir.DoList(n.Rlist(), v.do); err != nil {
+ return err
+ }
+ return nil
}
case ir.ONAME:
+ n := n.(*ir.Name)
if n.Class() == ir.PAUTO {
v.usedLocals[n] = true
}
+ case ir.OBLOCK:
+ // The only OBLOCK we should see at this point is an empty one.
+ // In any event, let the visitList(n.List()) below take care of the statements,
+ // and don't charge for the OBLOCK itself. The ++ undoes the -- below.
+ v.budget++
+
+ case ir.OCALLPART:
+ v.budget-- // Hack for toolstash -cmp.
}
v.budget--
// When debugging, don't stop early, to get full cost of inlining this function
if v.budget < 0 && base.Flag.LowerM < 2 && !logopt.Enabled() {
- return true
+ return errBudget
}
- return v.visit(n.Left()) || v.visit(n.Right()) ||
- v.visitList(n.List()) || v.visitList(n.Rlist()) ||
- v.visitList(n.Init()) || v.visitList(n.Body())
+ return ir.DoChildren(n, v.do)
}
-// inlcopylist (together with inlcopy) recursively copies a list of nodes, except
-// that it keeps the same ONAME, OTYPE, and OLITERAL nodes. It is used for copying
-// the body and dcls of an inlineable function.
-func inlcopylist(ll []ir.Node) []ir.Node {
- s := make([]ir.Node, 0, len(ll))
- for _, n := range ll {
- s = append(s, inlcopy(n))
- }
- return s
-}
-
-func inlcopy(n ir.Node) ir.Node {
- if n == nil {
+func isBigFunc(fn *ir.Func) bool {
+ budget := inlineBigFunctionNodes
+ over := ir.Find(fn, func(n ir.Node) interface{} {
+ budget--
+ if budget <= 0 {
+ return n
+ }
return nil
- }
-
- switch n.Op() {
- case ir.ONAME, ir.OTYPE, ir.OLITERAL, ir.ONIL:
- return n
- }
-
- m := ir.Copy(n)
- if n.Op() != ir.OCALLPART && m.Func() != nil {
- base.Fatalf("unexpected Func: %v", m)
- }
- m.SetLeft(inlcopy(n.Left()))
- m.SetRight(inlcopy(n.Right()))
- m.PtrList().Set(inlcopylist(n.List().Slice()))
- m.PtrRlist().Set(inlcopylist(n.Rlist().Slice()))
- m.PtrInit().Set(inlcopylist(n.Init().Slice()))
- m.PtrBody().Set(inlcopylist(n.Body().Slice()))
-
- return m
-}
-
-func countNodes(n ir.Node) int {
- if n == nil {
- return 0
- }
- cnt := 1
- cnt += countNodes(n.Left())
- cnt += countNodes(n.Right())
- for _, n1 := range n.Init().Slice() {
- cnt += countNodes(n1)
- }
- for _, n1 := range n.Body().Slice() {
- cnt += countNodes(n1)
- }
- for _, n1 := range n.List().Slice() {
- cnt += countNodes(n1)
- }
- for _, n1 := range n.Rlist().Slice() {
- cnt += countNodes(n1)
- }
- return cnt
+ })
+ return over != nil
}
// Inlcalls/nodelist/node walks fn's statements and expressions and substitutes any
// calls made to inlineable functions. This is the external entry point.
-func inlcalls(fn ir.Node) {
+func inlcalls(fn *ir.Func) {
savefn := Curfn
Curfn = fn
maxCost := int32(inlineMaxBudget)
- if countNodes(fn) >= inlineBigFunctionNodes {
+ if isBigFunc(fn) {
maxCost = inlineBigFunctionMaxCost
}
// Map to keep track of functions that have been inlined at a particular
@@ -516,23 +483,21 @@ func inlcalls(fn ir.Node) {
// but allow inlining if there is a recursion cycle of many functions.
// Most likely, the inlining will stop before we even hit the beginning of
// the cycle again, but the map catches the unusual case.
- inlMap := make(map[ir.Node]bool)
- fn = inlnode(fn, maxCost, inlMap)
- if fn != Curfn {
- base.Fatalf("inlnode replaced curfn")
+ inlMap := make(map[*ir.Func]bool)
+ var edit func(ir.Node) ir.Node
+ edit = func(n ir.Node) ir.Node {
+ return inlnode(n, maxCost, inlMap, edit)
}
+ ir.EditChildren(fn, edit)
Curfn = savefn
}
// Turn an OINLCALL into a statement.
-func inlconv2stmt(n ir.Node) {
- n.SetOp(ir.OBLOCK)
-
- // n->ninit stays
- n.PtrList().Set(n.Body().Slice())
-
- n.PtrBody().Set(nil)
- n.PtrRlist().Set(nil)
+func inlconv2stmt(inlcall ir.Node) ir.Node {
+ n := ir.NodAt(inlcall.Pos(), ir.OBLOCK, nil, nil)
+ n.SetList(inlcall.Init())
+ n.PtrList().AppendNodes(inlcall.PtrBody())
+ return n
}
// Turn an OINLCALL into a single valued expression.
@@ -540,13 +505,13 @@ func inlconv2stmt(n ir.Node) {
// n.Left = inlconv2expr(n.Left)
func inlconv2expr(n ir.Node) ir.Node {
r := n.Rlist().First()
- return addinit(r, append(n.Init().Slice(), n.Body().Slice()...))
+ return initExpr(append(n.Init().Slice(), n.Body().Slice()...), r)
}
// Turn the rlist (with the return values) of the OINLCALL in
// n into an expression list lumping the ninit and body
// containing the inlined statements on the first list element so
-// order will be preserved Used in return, oas2func and call
+// order will be preserved. Used in return, oas2func and call
// statements.
func inlconv2list(n ir.Node) []ir.Node {
if n.Op() != ir.OINLCALL || n.Rlist().Len() == 0 {
@@ -554,17 +519,10 @@ func inlconv2list(n ir.Node) []ir.Node {
}
s := n.Rlist().Slice()
- s[0] = addinit(s[0], append(n.Init().Slice(), n.Body().Slice()...))
+ s[0] = initExpr(append(n.Init().Slice(), n.Body().Slice()...), s[0])
return s
}
-func inlnodelist(l ir.Nodes, maxCost int32, inlMap map[ir.Node]bool) {
- s := l.Slice()
- for i := range s {
- s[i] = inlnode(s[i], maxCost, inlMap)
- }
-}
-
// inlnode recurses over the tree to find inlineable calls, which will
// be turned into OINLCALLs by mkinlcall. When the recursion comes
// back up will examine left, right, list, rlist, ninit, ntest, nincr,
@@ -578,7 +536,7 @@ func inlnodelist(l ir.Nodes, maxCost int32, inlMap map[ir.Node]bool) {
// shorter and less complicated.
// The result of inlnode MUST be assigned back to n, e.g.
// n.Left = inlnode(n.Left)
-func inlnode(n ir.Node, maxCost int32, inlMap map[ir.Node]bool) ir.Node {
+func inlnode(n ir.Node, maxCost int32, inlMap map[*ir.Func]bool, edit func(ir.Node) ir.Node) ir.Node {
if n == nil {
return n
}
@@ -604,66 +562,13 @@ func inlnode(n ir.Node, maxCost int32, inlMap map[ir.Node]bool) ir.Node {
lno := setlineno(n)
- inlnodelist(n.Init(), maxCost, inlMap)
- for _, n1 := range n.Init().Slice() {
- if n1.Op() == ir.OINLCALL {
- inlconv2stmt(n1)
- }
- }
+ ir.EditChildren(n, edit)
- n.SetLeft(inlnode(n.Left(), maxCost, inlMap))
- if n.Left() != nil && n.Left().Op() == ir.OINLCALL {
- n.SetLeft(inlconv2expr(n.Left()))
- }
-
- n.SetRight(inlnode(n.Right(), maxCost, inlMap))
- if n.Right() != nil && n.Right().Op() == ir.OINLCALL {
- if n.Op() == ir.OFOR || n.Op() == ir.OFORUNTIL {
- inlconv2stmt(n.Right())
- } else if n.Op() == ir.OAS2FUNC {
- n.PtrRlist().Set(inlconv2list(n.Right()))
- n.SetRight(nil)
- n.SetOp(ir.OAS2)
- n.SetTypecheck(0)
- n = typecheck(n, ctxStmt)
- } else {
- n.SetRight(inlconv2expr(n.Right()))
- }
- }
-
- inlnodelist(n.List(), maxCost, inlMap)
- if n.Op() == ir.OBLOCK {
- for _, n2 := range n.List().Slice() {
- if n2.Op() == ir.OINLCALL {
- inlconv2stmt(n2)
- }
- }
- } else {
- s := n.List().Slice()
- for i1, n1 := range s {
- if n1 != nil && n1.Op() == ir.OINLCALL {
- s[i1] = inlconv2expr(s[i1])
- }
- }
- }
-
- inlnodelist(n.Rlist(), maxCost, inlMap)
- s := n.Rlist().Slice()
- for i1, n1 := range s {
- if n1.Op() == ir.OINLCALL {
- if n.Op() == ir.OIF {
- inlconv2stmt(n1)
- } else {
- s[i1] = inlconv2expr(s[i1])
- }
- }
- }
-
- inlnodelist(n.Body(), maxCost, inlMap)
- for _, n := range n.Body().Slice() {
- if n.Op() == ir.OINLCALL {
- inlconv2stmt(n)
- }
+ if n.Op() == ir.OAS2FUNC && n.Rlist().First().Op() == ir.OINLCALL {
+ n.PtrRlist().Set(inlconv2list(n.Rlist().First()))
+ n.SetOp(ir.OAS2)
+ n.SetTypecheck(0)
+ n = typecheck(n, ctxStmt)
}
// with all the branches out of the way, it is now time to
@@ -676,19 +581,22 @@ func inlnode(n ir.Node, maxCost int32, inlMap map[ir.Node]bool) ir.Node {
}
}
+ var call ir.Node
switch n.Op() {
case ir.OCALLFUNC:
+ call = n
if base.Flag.LowerM > 3 {
fmt.Printf("%v:call to func %+v\n", ir.Line(n), n.Left())
}
if isIntrinsicCall(n) {
break
}
- if fn := inlCallee(n.Left()); fn != nil && fn.Func().Inl != nil {
- n = mkinlcall(n, fn, maxCost, inlMap)
+ if fn := inlCallee(n.Left()); fn != nil && fn.Inl != nil {
+ n = mkinlcall(n, fn, maxCost, inlMap, edit)
}
case ir.OCALLMETH:
+ call = n
if base.Flag.LowerM > 3 {
fmt.Printf("%v:call to meth %L\n", ir.Line(n), n.Left().Right())
}
@@ -698,16 +606,31 @@ func inlnode(n ir.Node, maxCost int32, inlMap map[ir.Node]bool) ir.Node {
base.Fatalf("no function type for [%p] %+v\n", n.Left(), n.Left())
}
- n = mkinlcall(n, methodExprName(n.Left()), maxCost, inlMap)
+ n = mkinlcall(n, methodExprName(n.Left()).Func(), maxCost, inlMap, edit)
}
base.Pos = lno
+
+ if n.Op() == ir.OINLCALL {
+ switch call.(*ir.CallExpr).Use {
+ default:
+ ir.Dump("call", call)
+ base.Fatalf("call missing use")
+ case ir.CallUseExpr:
+ n = inlconv2expr(n)
+ case ir.CallUseStmt:
+ n = inlconv2stmt(n)
+ case ir.CallUseList:
+ // leave for caller to convert
+ }
+ }
+
return n
}
// inlCallee takes a function-typed expression and returns the underlying function ONAME
// that it refers to if statically known. Otherwise, it returns nil.
-func inlCallee(fn ir.Node) ir.Node {
+func inlCallee(fn ir.Node) *ir.Func {
fn = staticValue(fn)
switch {
case fn.Op() == ir.OMETHEXPR:
@@ -718,13 +641,13 @@ func inlCallee(fn ir.Node) ir.Node {
if n == nil || !types.Identical(n.Type().Recv().Type, fn.Left().Type()) {
return nil
}
- return n
+ return n.Func()
case fn.Op() == ir.ONAME && fn.Class() == ir.PFUNC:
- return fn
+ return fn.Func()
case fn.Op() == ir.OCLOSURE:
- c := fn.Func().Decl
+ c := fn.Func()
caninl(c)
- return c.Func().Nname
+ return c
}
return nil
}
@@ -777,99 +700,54 @@ FindRHS:
base.Fatalf("RHS is nil: %v", defn)
}
- unsafe, _ := reassigned(n)
- if unsafe {
+ if reassigned(n.(*ir.Name)) {
return nil
}
return rhs
}
+var errFound = errors.New("found")
+
// reassigned takes an ONAME node, walks the function in which it is defined, and returns a boolean
// indicating whether the name has any assignments other than its declaration.
// The second return value is the first such assignment encountered in the walk, if any. It is mostly
// useful for -m output documenting the reason for inhibited optimizations.
// NB: global variables are always considered to be re-assigned.
// TODO: handle initial declaration not including an assignment and followed by a single assignment?
-func reassigned(n ir.Node) (bool, ir.Node) {
- if n.Op() != ir.ONAME {
- base.Fatalf("reassigned %v", n)
+func reassigned(name *ir.Name) bool {
+ if name.Op() != ir.ONAME {
+ base.Fatalf("reassigned %v", name)
}
// no way to reliably check for no-reassignment of globals, assume it can be
- if n.Name().Curfn == nil {
- return true, nil
+ if name.Curfn == nil {
+ return true
}
- f := n.Name().Curfn
- // There just might be a good reason for this although this can be pretty surprising:
- // local variables inside a closure have Curfn pointing to the OCLOSURE node instead
- // of the corresponding ODCLFUNC.
- // We need to walk the function body to check for reassignments so we follow the
- // linkage to the ODCLFUNC node as that is where body is held.
- if f.Op() == ir.OCLOSURE {
- f = f.Func().Decl
- }
- v := reassignVisitor{name: n}
- a := v.visitList(f.Body())
- return a != nil, a
-}
-
-type reassignVisitor struct {
- name ir.Node
-}
-
-func (v *reassignVisitor) visit(n ir.Node) ir.Node {
- if n == nil {
- return nil
- }
- switch n.Op() {
- case ir.OAS:
- if n.Left() == v.name && n != v.name.Name().Defn {
- return n
- }
- case ir.OAS2, ir.OAS2FUNC, ir.OAS2MAPR, ir.OAS2DOTTYPE:
- for _, p := range n.List().Slice() {
- if p == v.name && n != v.name.Name().Defn {
+ a := ir.Find(name.Curfn, func(n ir.Node) interface{} {
+ switch n.Op() {
+ case ir.OAS:
+ if n.Left() == name && n != name.Defn {
return n
}
+ case ir.OAS2, ir.OAS2FUNC, ir.OAS2MAPR, ir.OAS2DOTTYPE:
+ for _, p := range n.List().Slice() {
+ if p == name && n != name.Defn {
+ return n
+ }
+ }
}
- }
- if a := v.visit(n.Left()); a != nil {
- return a
- }
- if a := v.visit(n.Right()); a != nil {
- return a
- }
- if a := v.visitList(n.List()); a != nil {
- return a
- }
- if a := v.visitList(n.Rlist()); a != nil {
- return a
- }
- if a := v.visitList(n.Init()); a != nil {
- return a
- }
- if a := v.visitList(n.Body()); a != nil {
- return a
- }
- return nil
+ return nil
+ })
+ return a != nil
}
-func (v *reassignVisitor) visitList(l ir.Nodes) ir.Node {
- for _, n := range l.Slice() {
- if a := v.visit(n); a != nil {
- return a
- }
- }
- return nil
-}
-
-func inlParam(t *types.Field, as ir.Node, inlvars map[ir.Node]ir.Node) ir.Node {
+func inlParam(t *types.Field, as ir.Node, inlvars map[*ir.Name]ir.Node) ir.Node {
n := ir.AsNode(t.Nname)
if n == nil || ir.IsBlank(n) {
return ir.BlankNode
}
- inlvar := inlvars[n]
+ inlvar := inlvars[n.(*ir.Name)]
if inlvar == nil {
base.Fatalf("missing inlvar for %v", n)
}
@@ -887,25 +765,25 @@ var inlgen int
// parameters.
// The result of mkinlcall MUST be assigned back to n, e.g.
// n.Left = mkinlcall(n.Left, fn, isddd)
-func mkinlcall(n, fn ir.Node, maxCost int32, inlMap map[ir.Node]bool) ir.Node {
- if fn.Func().Inl == nil {
+func mkinlcall(n ir.Node, fn *ir.Func, maxCost int32, inlMap map[*ir.Func]bool, edit func(ir.Node) ir.Node) ir.Node {
+ if fn.Inl == nil {
if logopt.Enabled() {
logopt.LogOpt(n.Pos(), "cannotInlineCall", "inline", ir.FuncName(Curfn),
fmt.Sprintf("%s cannot be inlined", ir.PkgFuncName(fn)))
}
return n
}
- if fn.Func().Inl.Cost > maxCost {
+ if fn.Inl.Cost > maxCost {
// The inlined function body is too big. Typically we use this check to restrict
// inlining into very big functions. See issue 26546 and 17566.
if logopt.Enabled() {
logopt.LogOpt(n.Pos(), "cannotInlineCall", "inline", ir.FuncName(Curfn),
- fmt.Sprintf("cost %d of %s exceeds max large caller cost %d", fn.Func().Inl.Cost, ir.PkgFuncName(fn), maxCost))
+ fmt.Sprintf("cost %d of %s exceeds max large caller cost %d", fn.Inl.Cost, ir.PkgFuncName(fn), maxCost))
}
return n
}
- if fn == Curfn || fn.Name().Defn == Curfn {
+ if fn == Curfn {
// Can't recursively inline a function into itself.
if logopt.Enabled() {
logopt.LogOpt(n.Pos(), "cannotInlineCall", "inline", fmt.Sprintf("recursive call to %s", ir.FuncName(Curfn)))
@@ -939,7 +817,7 @@ func mkinlcall(n, fn ir.Node, maxCost int32, inlMap map[ir.Node]bool) ir.Node {
// We have a function node, and it has an inlineable body.
if base.Flag.LowerM > 1 {
- fmt.Printf("%v: inlining call to %v %#v { %#v }\n", ir.Line(n), fn.Sym(), fn.Type(), ir.AsNodes(fn.Func().Inl.Body))
+ fmt.Printf("%v: inlining call to %v %v { %v }\n", ir.Line(n), fn.Sym(), fn.Type(), ir.AsNodes(fn.Inl.Body))
} else if base.Flag.LowerM != 0 {
fmt.Printf("%v: inlining call to %v\n", ir.Line(n), fn)
}
@@ -969,50 +847,48 @@ func mkinlcall(n, fn ir.Node, maxCost int32, inlMap map[ir.Node]bool) ir.Node {
}
// Make temp names to use instead of the originals.
- inlvars := make(map[ir.Node]ir.Node)
+ inlvars := make(map[*ir.Name]ir.Node)
// record formals/locals for later post-processing
var inlfvars []ir.Node
// Handle captured variables when inlining closures.
- if fn.Name().Defn != nil {
- if c := fn.Name().Defn.Func().OClosure; c != nil {
- for _, v := range c.Func().ClosureVars.Slice() {
- if v.Op() == ir.OXXX {
- continue
- }
+ if c := fn.OClosure; c != nil {
+ for _, v := range fn.ClosureVars {
+ if v.Op() == ir.OXXX {
+ continue
+ }
- o := v.Name().Param.Outer
- // make sure the outer param matches the inlining location
- // NB: if we enabled inlining of functions containing OCLOSURE or refined
- // the reassigned check via some sort of copy propagation this would most
- // likely need to be changed to a loop to walk up to the correct Param
- if o == nil || (o.Name().Curfn != Curfn && o.Name().Curfn.Func().OClosure != Curfn) {
- base.Fatalf("%v: unresolvable capture %v %v\n", ir.Line(n), fn, v)
- }
+ o := v.Outer
+ // make sure the outer param matches the inlining location
+ // NB: if we enabled inlining of functions containing OCLOSURE or refined
+ // the reassigned check via some sort of copy propagation this would most
+ // likely need to be changed to a loop to walk up to the correct Param
+ if o == nil || o.Curfn != Curfn {
+ base.Fatalf("%v: unresolvable capture %v %v\n", ir.Line(n), fn, v)
+ }
- if v.Name().Byval() {
- iv := typecheck(inlvar(v), ctxExpr)
- ninit.Append(ir.Nod(ir.ODCL, iv, nil))
- ninit.Append(typecheck(ir.Nod(ir.OAS, iv, o), ctxStmt))
- inlvars[v] = iv
- } else {
- addr := NewName(lookup("&" + v.Sym().Name))
- addr.SetType(types.NewPtr(v.Type()))
- ia := typecheck(inlvar(addr), ctxExpr)
- ninit.Append(ir.Nod(ir.ODCL, ia, nil))
- ninit.Append(typecheck(ir.Nod(ir.OAS, ia, ir.Nod(ir.OADDR, o, nil)), ctxStmt))
- inlvars[addr] = ia
+ if v.Byval() {
+ iv := typecheck(inlvar(v), ctxExpr)
+ ninit.Append(ir.Nod(ir.ODCL, iv, nil))
+ ninit.Append(typecheck(ir.Nod(ir.OAS, iv, o), ctxStmt))
+ inlvars[v] = iv
+ } else {
+ addr := NewName(lookup("&" + v.Sym().Name))
+ addr.SetType(types.NewPtr(v.Type()))
+ ia := typecheck(inlvar(addr), ctxExpr)
+ ninit.Append(ir.Nod(ir.ODCL, ia, nil))
+ ninit.Append(typecheck(ir.Nod(ir.OAS, ia, ir.Nod(ir.OADDR, o, nil)), ctxStmt))
+ inlvars[addr] = ia
- // When capturing by reference, all occurrence of the captured var
- // must be substituted with dereference of the temporary address
- inlvars[v] = typecheck(ir.Nod(ir.ODEREF, ia, nil), ctxExpr)
- }
+ // When capturing by reference, all occurrence of the captured var
+ // must be substituted with dereference of the temporary address
+ inlvars[v] = typecheck(ir.Nod(ir.ODEREF, ia, nil), ctxExpr)
}
}
}
- for _, ln := range fn.Func().Inl.Dcl {
+ for _, ln := range fn.Inl.Dcl {
if ln.Op() != ir.ONAME {
continue
}
@@ -1040,7 +916,7 @@ func mkinlcall(n, fn ir.Node, maxCost int32, inlMap map[ir.Node]bool) ir.Node {
}
nreturns := 0
- ir.InspectList(ir.AsNodes(fn.Func().Inl.Body), func(n ir.Node) bool {
+ ir.InspectList(ir.AsNodes(fn.Inl.Body), func(n ir.Node) bool {
if n != nil && n.Op() == ir.ORETURN {
nreturns++
}
@@ -1057,6 +933,7 @@ func mkinlcall(n, fn ir.Node, maxCost int32, inlMap map[ir.Node]bool) ir.Node {
for i, t := range fn.Type().Results().Fields().Slice() {
var m ir.Node
if n := ir.AsNode(t.Nname); n != nil && !ir.IsBlank(n) && !strings.HasPrefix(n.Sym().Name, "~r") {
+ n := n.(*ir.Name)
m = inlvar(n)
m = typecheck(m, ctxExpr)
inlvars[n] = m
@@ -1122,7 +999,7 @@ func mkinlcall(n, fn ir.Node, maxCost int32, inlMap map[ir.Node]bool) ir.Node {
vas.SetRight(nodnil())
vas.Right().SetType(param.Type)
} else {
- vas.SetRight(ir.Nod(ir.OCOMPLIT, nil, typenod(param.Type)))
+ vas.SetRight(ir.Nod(ir.OCOMPLIT, nil, ir.TypeNode(param.Type)))
vas.Right().PtrList().Set(varargs)
}
}
@@ -1155,7 +1032,9 @@ func mkinlcall(n, fn ir.Node, maxCost int32, inlMap map[ir.Node]bool) ir.Node {
if b := base.Ctxt.PosTable.Pos(n.Pos()).Base(); b != nil {
parent = b.InliningIndex()
}
- newIndex := base.Ctxt.InlTree.Add(parent, n.Pos(), fn.Sym().Linksym())
+
+ sym := fn.Sym().Linksym()
+ newIndex := base.Ctxt.InlTree.Add(parent, n.Pos(), sym)
// Add an inline mark just before the inlined body.
// This mark is inline in the code so that it's a reasonable spot
@@ -1168,9 +1047,9 @@ func mkinlcall(n, fn ir.Node, maxCost int32, inlMap map[ir.Node]bool) ir.Node {
ninit.Append(inlMark)
if base.Flag.GenDwarfInl > 0 {
- if !fn.Sym().Linksym().WasInlined() {
- base.Ctxt.DwFixups.SetPrecursorFunc(fn.Sym().Linksym(), fn)
- fn.Sym().Linksym().Set(obj.AttrWasInlined, true)
+ if !sym.WasInlined() {
+ base.Ctxt.DwFixups.SetPrecursorFunc(sym, fn)
+ sym.Set(obj.AttrWasInlined, true)
}
}
@@ -1182,8 +1061,9 @@ func mkinlcall(n, fn ir.Node, maxCost int32, inlMap map[ir.Node]bool) ir.Node {
bases: make(map[*src.PosBase]*src.PosBase),
newInlIndex: newIndex,
}
+ subst.edit = subst.node
- body := subst.list(ir.AsNodes(fn.Func().Inl.Body))
+ body := subst.list(ir.AsNodes(fn.Inl.Body))
lab := nodSym(ir.OLABEL, nil, retlabel)
body = append(body, lab)
@@ -1211,12 +1091,7 @@ func mkinlcall(n, fn ir.Node, maxCost int32, inlMap map[ir.Node]bool) ir.Node {
// instead we emit the things that the body needs
// and each use must redo the inlining.
// luckily these are small.
- inlnodelist(call.Body(), maxCost, inlMap)
- for _, n := range call.Body().Slice() {
- if n.Op() == ir.OINLCALL {
- inlconv2stmt(n)
- }
- }
+ ir.EditChildren(call, edit)
if base.Flag.LowerM > 2 {
fmt.Printf("%v: After inlining %+v\n\n", ir.Line(call), call)
@@ -1236,11 +1111,11 @@ func inlvar(var_ ir.Node) ir.Node {
n := NewName(var_.Sym())
n.SetType(var_.Type())
n.SetClass(ir.PAUTO)
- n.Name().SetUsed(true)
- n.Name().Curfn = Curfn // the calling function, not the called one
- n.Name().SetAddrtaken(var_.Name().Addrtaken())
+ n.SetUsed(true)
+ n.Curfn = Curfn // the calling function, not the called one
+ n.SetAddrtaken(var_.Name().Addrtaken())
- Curfn.Func().Dcl = append(Curfn.Func().Dcl, n)
+ Curfn.Dcl = append(Curfn.Dcl, n)
return n
}
@@ -1249,9 +1124,9 @@ func retvar(t *types.Field, i int) ir.Node {
n := NewName(lookupN("~R", i))
n.SetType(t.Type)
n.SetClass(ir.PAUTO)
- n.Name().SetUsed(true)
- n.Name().Curfn = Curfn // the calling function, not the called one
- Curfn.Func().Dcl = append(Curfn.Func().Dcl, n)
+ n.SetUsed(true)
+ n.Curfn = Curfn // the calling function, not the called one
+ Curfn.Dcl = append(Curfn.Dcl, n)
return n
}
@@ -1261,9 +1136,9 @@ func argvar(t *types.Type, i int) ir.Node {
n := NewName(lookupN("~arg", i))
n.SetType(t.Elem())
n.SetClass(ir.PAUTO)
- n.Name().SetUsed(true)
- n.Name().Curfn = Curfn // the calling function, not the called one
- Curfn.Func().Dcl = append(Curfn.Func().Dcl, n)
+ n.SetUsed(true)
+ n.Curfn = Curfn // the calling function, not the called one
+ Curfn.Dcl = append(Curfn.Dcl, n)
return n
}
@@ -1280,7 +1155,7 @@ type inlsubst struct {
// "return" statement.
delayretvars bool
- inlvars map[ir.Node]ir.Node
+ inlvars map[*ir.Name]ir.Node
// bases maps from original PosBase to PosBase with an extra
// inlined call frame.
@@ -1289,6 +1164,8 @@ type inlsubst struct {
// newInlIndex is the index of the inlined call frame to
// insert for inlined nodes.
newInlIndex int
+
+ edit func(ir.Node) ir.Node // cached copy of subst.node method value closure
}
// list inlines a list of nodes.
@@ -1311,6 +1188,7 @@ func (subst *inlsubst) node(n ir.Node) ir.Node {
switch n.Op() {
case ir.ONAME:
+ n := n.(*ir.Name)
if inlvar := subst.inlvars[n]; inlvar != nil { // These will be set during inlnode
if base.Flag.LowerM > 2 {
fmt.Printf("substituting name %+v -> %+v\n", n, inlvar)
@@ -1338,9 +1216,7 @@ func (subst *inlsubst) node(n ir.Node) ir.Node {
// dump("Return before substitution", n);
case ir.ORETURN:
- m := nodSym(ir.OGOTO, nil, subst.retlabel)
- m.PtrInit().Set(subst.list(n.Init()))
-
+ init := subst.list(n.Init())
if len(subst.retvars) != 0 && n.List().Len() != 0 {
as := ir.Nod(ir.OAS2, nil, nil)
@@ -1360,14 +1236,11 @@ func (subst *inlsubst) node(n ir.Node) ir.Node {
}
as = typecheck(as, ctxStmt)
- m.PtrInit().Append(as)
+ init = append(init, as)
}
-
- typecheckslice(m.Init().Slice(), ctxStmt)
- m = typecheck(m, ctxStmt)
-
- // dump("Return after substitution", m);
- return m
+ init = append(init, nodSym(ir.OGOTO, nil, subst.retlabel))
+ typecheckslice(init, ctxStmt)
+ return ir.NewBlockStmt(base.Pos, init)
case ir.OGOTO, ir.OLABEL:
m := ir.Copy(n)
@@ -1379,21 +1252,13 @@ func (subst *inlsubst) node(n ir.Node) ir.Node {
return m
}
- m := ir.Copy(n)
- m.SetPos(subst.updatedPos(m.Pos()))
- m.PtrInit().Set(nil)
-
if n.Op() == ir.OCLOSURE {
base.Fatalf("cannot inline function containing closure: %+v", n)
}
- m.SetLeft(subst.node(n.Left()))
- m.SetRight(subst.node(n.Right()))
- m.PtrList().Set(subst.list(n.List()))
- m.PtrRlist().Set(subst.list(n.Rlist()))
- m.PtrInit().Set(append(m.Init().Slice(), subst.list(n.Init())...))
- m.PtrBody().Set(subst.list(n.Body()))
-
+ m := ir.Copy(n)
+ m.SetPos(subst.updatedPos(m.Pos()))
+ ir.EditChildren(m, subst.edit)
return m
}
@@ -1409,8 +1274,8 @@ func (subst *inlsubst) updatedPos(xpos src.XPos) src.XPos {
return base.Ctxt.PosTable.XPos(pos)
}
-func pruneUnusedAutos(ll []ir.Node, vis *hairyVisitor) []ir.Node {
- s := make([]ir.Node, 0, len(ll))
+func pruneUnusedAutos(ll []*ir.Name, vis *hairyVisitor) []*ir.Name {
+ s := make([]*ir.Name, 0, len(ll))
for _, n := range ll {
if n.Class() == ir.PAUTO {
if _, found := vis.usedLocals[n]; !found {
@@ -1424,7 +1289,7 @@ func pruneUnusedAutos(ll []ir.Node, vis *hairyVisitor) []ir.Node {
// devirtualize replaces interface method calls within fn with direct
// concrete-type method calls where applicable.
-func devirtualize(fn ir.Node) {
+func devirtualize(fn *ir.Func) {
Curfn = fn
ir.InspectList(fn.Body(), func(n ir.Node) bool {
if n.Op() == ir.OCALLINTER {
diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go
index 69a457da4d..bbc228b313 100644
--- a/src/cmd/compile/internal/gc/main.go
+++ b/src/cmd/compile/internal/gc/main.go
@@ -43,6 +43,9 @@ func hidePanic() {
// about a panic too; let the user clean up
// the code and try again.
if err := recover(); err != nil {
+ if err == "-h" {
+ panic(err)
+ }
base.ErrorExit()
}
}
@@ -74,17 +77,17 @@ func Main(archInit func(*Arch)) {
// See bugs 31188 and 21945 (CLs 170638, 98075, 72371).
base.Ctxt.UseBASEntries = base.Ctxt.Headtype != objabi.Hdarwin
- ir.LocalPkg = types.NewPkg("", "")
- ir.LocalPkg.Prefix = "\"\""
+ types.LocalPkg = types.NewPkg("", "")
+ types.LocalPkg.Prefix = "\"\""
// We won't know localpkg's height until after import
// processing. In the mean time, set to MaxPkgHeight to ensure
// height comparisons at least work until then.
- ir.LocalPkg.Height = types.MaxPkgHeight
+ types.LocalPkg.Height = types.MaxPkgHeight
// pseudo-package, for scoping
- ir.BuiltinPkg = types.NewPkg("go.builtin", "") // TODO(gri) name this package go.builtin?
- ir.BuiltinPkg.Prefix = "go.builtin" // not go%2ebuiltin
+ types.BuiltinPkg = types.NewPkg("go.builtin", "") // TODO(gri) name this package go.builtin?
+ types.BuiltinPkg.Prefix = "go.builtin" // not go%2ebuiltin
// pseudo-package, accessed by import "unsafe"
unsafepkg = types.NewPkg("unsafe", "unsafe")
@@ -207,19 +210,7 @@ func Main(archInit func(*Arch)) {
// initialize types package
// (we need to do this to break dependencies that otherwise
// would lead to import cycles)
- types.Widthptr = Widthptr
- types.Dowidth = dowidth
- types.Fatalf = base.Fatalf
- ir.InstallTypeFormats()
- types.TypeLinkSym = func(t *types.Type) *obj.LSym {
- return typenamesym(t).Linksym()
- }
- types.FmtLeft = int(ir.FmtLeft)
- types.FmtUnsigned = int(ir.FmtUnsigned)
- types.FErr = int(ir.FErr)
- types.Ctxt = base.Ctxt
-
- initUniverse()
+ initializeTypesPackage()
dclcontext = ir.PEXTERN
@@ -258,7 +249,7 @@ func Main(archInit func(*Arch)) {
timings.Start("fe", "typecheck", "top1")
for i := 0; i < len(xtop); i++ {
n := xtop[i]
- if op := n.Op(); op != ir.ODCL && op != ir.OAS && op != ir.OAS2 && (op != ir.ODCLTYPE || !n.Left().Name().Param.Alias()) {
+ if op := n.Op(); op != ir.ODCL && op != ir.OAS && op != ir.OAS2 && (op != ir.ODCLTYPE || !n.Left().Name().Alias()) {
xtop[i] = typecheck(n, ctxStmt)
}
}
@@ -270,7 +261,7 @@ func Main(archInit func(*Arch)) {
timings.Start("fe", "typecheck", "top2")
for i := 0; i < len(xtop); i++ {
n := xtop[i]
- if op := n.Op(); op == ir.ODCL || op == ir.OAS || op == ir.OAS2 || op == ir.ODCLTYPE && n.Left().Name().Param.Alias() {
+ if op := n.Op(); op == ir.ODCL || op == ir.OAS || op == ir.OAS2 || op == ir.ODCLTYPE && n.Left().Name().Alias() {
xtop[i] = typecheck(n, ctxStmt)
}
}
@@ -282,7 +273,7 @@ func Main(archInit func(*Arch)) {
for i := 0; i < len(xtop); i++ {
n := xtop[i]
if n.Op() == ir.ODCLFUNC {
- Curfn = n
+ Curfn = n.(*ir.Func)
decldepth = 1
errorsBefore := base.Errors()
typecheckslice(Curfn.Body().Slice(), ctxStmt)
@@ -312,8 +303,8 @@ func Main(archInit func(*Arch)) {
timings.Start("fe", "capturevars")
for _, n := range xtop {
if n.Op() == ir.ODCLFUNC && n.Func().OClosure != nil {
- Curfn = n
- capturevars(n)
+ Curfn = n.(*ir.Func)
+ capturevars(Curfn)
}
}
capturevarscomplete = true
@@ -326,7 +317,7 @@ func Main(archInit func(*Arch)) {
// Typecheck imported function bodies if Debug.l > 1,
// otherwise lazily when used or re-exported.
for _, n := range importlist {
- if n.Func().Inl != nil {
+ if n.Inl != nil {
typecheckinl(n)
}
}
@@ -335,7 +326,7 @@ func Main(archInit func(*Arch)) {
if base.Flag.LowerL != 0 {
// Find functions that can be inlined and clone them before walk expands them.
- visitBottomUp(xtop, func(list []ir.Node, recursive bool) {
+ visitBottomUp(xtop, func(list []*ir.Func, recursive bool) {
numfns := numNonClosures(list)
for _, n := range list {
if !recursive || numfns > 1 {
@@ -345,7 +336,7 @@ func Main(archInit func(*Arch)) {
caninl(n)
} else {
if base.Flag.LowerM > 1 {
- fmt.Printf("%v: cannot inline %v: recursive\n", ir.Line(n), n.Func().Nname)
+ fmt.Printf("%v: cannot inline %v: recursive\n", ir.Line(n), n.Nname)
}
}
inlcalls(n)
@@ -355,7 +346,7 @@ func Main(archInit func(*Arch)) {
for _, n := range xtop {
if n.Op() == ir.ODCLFUNC {
- devirtualize(n)
+ devirtualize(n.(*ir.Func))
}
}
Curfn = nil
@@ -385,8 +376,8 @@ func Main(archInit func(*Arch)) {
timings.Start("fe", "xclosures")
for _, n := range xtop {
if n.Op() == ir.ODCLFUNC && n.Func().OClosure != nil {
- Curfn = n
- transformclosure(n)
+ Curfn = n.(*ir.Func)
+ transformclosure(Curfn)
}
}
@@ -408,7 +399,7 @@ func Main(archInit func(*Arch)) {
for i := 0; i < len(xtop); i++ {
n := xtop[i]
if n.Op() == ir.ODCLFUNC {
- funccompile(n)
+ funccompile(n.(*ir.Func))
fcount++
}
}
@@ -486,10 +477,10 @@ func Main(archInit func(*Arch)) {
}
// numNonClosures returns the number of functions in list which are not closures.
-func numNonClosures(list []ir.Node) int {
+func numNonClosures(list []*ir.Func) int {
count := 0
- for _, n := range list {
- if n.Func().OClosure == nil {
+ for _, fn := range list {
+ if fn.OClosure == nil {
count++
}
}
@@ -929,14 +920,14 @@ func pkgnotused(lineno src.XPos, path string, name string) {
}
func mkpackage(pkgname string) {
- if ir.LocalPkg.Name == "" {
+ if types.LocalPkg.Name == "" {
if pkgname == "_" {
base.Errorf("invalid package name _")
}
- ir.LocalPkg.Name = pkgname
+ types.LocalPkg.Name = pkgname
} else {
- if pkgname != ir.LocalPkg.Name {
- base.Errorf("package %s; expected %s", pkgname, ir.LocalPkg.Name)
+ if pkgname != types.LocalPkg.Name {
+ base.Errorf("package %s; expected %s", pkgname, types.LocalPkg.Name)
}
}
}
@@ -949,7 +940,7 @@ func clearImports() {
}
var unused []importedPkg
- for _, s := range ir.LocalPkg.Syms {
+ for _, s := range types.LocalPkg.Syms {
n := ir.AsNode(s.Def)
if n == nil {
continue
@@ -960,8 +951,9 @@ func clearImports() {
// leave s->block set to cause redeclaration
// errors if a conflicting top-level name is
// introduced by a different file.
- if !n.Name().Used() && base.SyntaxErrors() == 0 {
- unused = append(unused, importedPkg{n.Pos(), n.Name().Pkg.Path, s.Name})
+ p := n.(*ir.PkgName)
+ if !p.Used && base.SyntaxErrors() == 0 {
+ unused = append(unused, importedPkg{p.Pos(), p.Pkg.Path, s.Name})
}
s.Def = nil
continue
@@ -969,9 +961,9 @@ func clearImports() {
if IsAlias(s) {
// throw away top-level name left over
// from previous import . "x"
- if n.Name() != nil && n.Name().Pack != nil && !n.Name().Pack.Name().Used() && base.SyntaxErrors() == 0 {
- unused = append(unused, importedPkg{n.Name().Pack.Pos(), n.Name().Pack.Name().Pkg.Path, ""})
- n.Name().Pack.Name().SetUsed(true)
+ if name := n.Name(); name != nil && name.PkgName != nil && !name.PkgName.Used && base.SyntaxErrors() == 0 {
+ unused = append(unused, importedPkg{name.PkgName.Pos(), name.PkgName.Pkg.Path, ""})
+ name.PkgName.Used = true
}
s.Def = nil
continue
@@ -985,7 +977,7 @@ func clearImports() {
}
func IsAlias(sym *types.Sym) bool {
- return sym.Def != nil && ir.AsNode(sym.Def).Sym() != sym
+ return sym.Def != nil && sym.Def.Sym() != sym
}
// recordFlags records the specified command-line flags to be placed
@@ -1052,7 +1044,7 @@ func recordPackageName() {
// together two package main archives. So allow dups.
s.Set(obj.AttrDuplicateOK, true)
base.Ctxt.Data = append(base.Ctxt.Data, s)
- s.P = []byte(ir.LocalPkg.Name)
+ s.P = []byte(types.LocalPkg.Name)
}
// currentLang returns the current language version.
@@ -1079,9 +1071,9 @@ var langWant lang
func langSupported(major, minor int, pkg *types.Pkg) bool {
if pkg == nil {
// TODO(mdempsky): Set Pkg for local types earlier.
- pkg = ir.LocalPkg
+ pkg = types.LocalPkg
}
- if pkg != ir.LocalPkg {
+ if pkg != types.LocalPkg {
// Assume imported packages passed type-checking.
return true
}
@@ -1132,3 +1124,13 @@ func parseLang(s string) (lang, error) {
}
return lang{major: major, minor: minor}, nil
}
+
+func initializeTypesPackage() {
+ types.Widthptr = Widthptr
+ types.Dowidth = dowidth
+ types.TypeLinkSym = func(t *types.Type) *obj.LSym {
+ return typenamesym(t).Linksym()
+ }
+
+ initUniverse()
+}
diff --git a/src/cmd/compile/internal/gc/mkbuiltin.go b/src/cmd/compile/internal/gc/mkbuiltin.go
index d763f1ebee..38aa601645 100644
--- a/src/cmd/compile/internal/gc/mkbuiltin.go
+++ b/src/cmd/compile/internal/gc/mkbuiltin.go
@@ -143,9 +143,9 @@ func (i *typeInterner) mktype(t ast.Expr) string {
case *ast.Ident:
switch t.Name {
case "byte":
- return "types.Bytetype"
+ return "types.ByteType"
case "rune":
- return "types.Runetype"
+ return "types.RuneType"
}
return fmt.Sprintf("types.Types[types.T%s]", strings.ToUpper(t.Name))
case *ast.SelectorExpr:
@@ -207,7 +207,7 @@ func (i *typeInterner) fields(fl *ast.FieldList, keepNames bool) string {
}
}
}
- return fmt.Sprintf("[]ir.Node{%s}", strings.Join(res, ", "))
+ return fmt.Sprintf("[]*ir.Field{%s}", strings.Join(res, ", "))
}
func intconst(e ast.Expr) int64 {
diff --git a/src/cmd/compile/internal/gc/noder.go b/src/cmd/compile/internal/gc/noder.go
index 4eaeedb63b..7ec81e34b0 100644
--- a/src/cmd/compile/internal/gc/noder.go
+++ b/src/cmd/compile/internal/gc/noder.go
@@ -139,7 +139,7 @@ func parseFiles(filenames []string) (lines uint) {
testdclstack()
}
- ir.LocalPkg.Height = myheight
+ types.LocalPkg.Height = myheight
return
}
@@ -160,7 +160,11 @@ func parseFiles(filenames []string) (lines uint) {
testdclstack()
}
- ir.LocalPkg.Height = myheight
+ for _, p := range noders {
+ p.processPragmas()
+ }
+
+ types.LocalPkg.Height = myheight
return
}
@@ -279,7 +283,7 @@ func (p *noder) use(x *syntax.Name) types2.Object {
return p.typeInfo.Uses[x]
}
-func (p *noder) funcBody(fn ir.Node, block *syntax.BlockStmt) {
+func (p *noder) funcBody(fn *ir.Func, block *syntax.BlockStmt) {
oldScope := p.scope
p.scope = 0
funchdr(fn)
@@ -287,12 +291,12 @@ func (p *noder) funcBody(fn ir.Node, block *syntax.BlockStmt) {
if block != nil {
body := p.stmts(block.List)
if body == nil {
- body = []ir.Node{ir.Nod(ir.OEMPTY, nil, nil)}
+ body = []ir.Node{ir.Nod(ir.OBLOCK, nil, nil)}
}
fn.PtrBody().Set(body)
base.Pos = p.makeXPos(block.Rbrace)
- fn.Func().Endlineno = base.Pos
+ fn.Endlineno = base.Pos
}
funcbody()
@@ -303,9 +307,9 @@ func (p *noder) openScope(pos syntax.Pos) {
types.Markdcl()
if trackScopes {
- Curfn.Func().Parents = append(Curfn.Func().Parents, p.scope)
- p.scopeVars = append(p.scopeVars, len(Curfn.Func().Dcl))
- p.scope = ir.ScopeID(len(Curfn.Func().Parents))
+ Curfn.Parents = append(Curfn.Parents, p.scope)
+ p.scopeVars = append(p.scopeVars, len(Curfn.Dcl))
+ p.scope = ir.ScopeID(len(Curfn.Parents))
p.markScope(pos)
}
@@ -318,29 +322,29 @@ func (p *noder) closeScope(pos syntax.Pos) {
if trackScopes {
scopeVars := p.scopeVars[len(p.scopeVars)-1]
p.scopeVars = p.scopeVars[:len(p.scopeVars)-1]
- if scopeVars == len(Curfn.Func().Dcl) {
+ if scopeVars == len(Curfn.Dcl) {
// no variables were declared in this scope, so we can retract it.
- if int(p.scope) != len(Curfn.Func().Parents) {
+ if int(p.scope) != len(Curfn.Parents) {
base.Fatalf("scope tracking inconsistency, no variables declared but scopes were not retracted")
}
- p.scope = Curfn.Func().Parents[p.scope-1]
- Curfn.Func().Parents = Curfn.Func().Parents[:len(Curfn.Func().Parents)-1]
+ p.scope = Curfn.Parents[p.scope-1]
+ Curfn.Parents = Curfn.Parents[:len(Curfn.Parents)-1]
- nmarks := len(Curfn.Func().Marks)
- Curfn.Func().Marks[nmarks-1].Scope = p.scope
+ nmarks := len(Curfn.Marks)
+ Curfn.Marks[nmarks-1].Scope = p.scope
prevScope := ir.ScopeID(0)
if nmarks >= 2 {
- prevScope = Curfn.Func().Marks[nmarks-2].Scope
+ prevScope = Curfn.Marks[nmarks-2].Scope
}
- if Curfn.Func().Marks[nmarks-1].Scope == prevScope {
- Curfn.Func().Marks = Curfn.Func().Marks[:nmarks-1]
+ if Curfn.Marks[nmarks-1].Scope == prevScope {
+ Curfn.Marks = Curfn.Marks[:nmarks-1]
}
return
}
- p.scope = Curfn.Func().Parents[p.scope-1]
+ p.scope = Curfn.Parents[p.scope-1]
p.markScope(pos)
}
@@ -348,10 +352,10 @@ func (p *noder) closeScope(pos syntax.Pos) {
func (p *noder) markScope(pos syntax.Pos) {
xpos := p.makeXPos(pos)
- if i := len(Curfn.Func().Marks); i > 0 && Curfn.Func().Marks[i-1].Pos == xpos {
- Curfn.Func().Marks[i-1].Scope = p.scope
+ if i := len(Curfn.Marks); i > 0 && Curfn.Marks[i-1].Pos == xpos {
+ Curfn.Marks[i-1].Scope = p.scope
} else {
- Curfn.Func().Marks = append(Curfn.Func().Marks, ir.Mark{Pos: xpos, Scope: p.scope})
+ Curfn.Marks = append(Curfn.Marks, ir.Mark{Pos: xpos, Scope: p.scope})
}
}
@@ -385,23 +389,27 @@ func (p *noder) node() {
xtop = append(xtop, p.decls(p.file.DeclList)...)
- for _, n := range p.linknames {
+ base.Pos = src.NoXPos
+ clearImports()
+}
+
+func (p *noder) processPragmas() {
+ for _, l := range p.linknames {
if !p.importedUnsafe {
- p.errorAt(n.pos, "//go:linkname only allowed in Go files that import \"unsafe\"")
+ p.errorAt(l.pos, "//go:linkname only allowed in Go files that import \"unsafe\"")
continue
}
- s := lookup(n.local)
- if n.remote != "" {
- s.Linkname = n.remote
- } else {
- // Use the default object symbol name if the
- // user didn't provide one.
- if base.Ctxt.Pkgpath == "" {
- p.errorAt(n.pos, "//go:linkname requires linkname argument or -p compiler flag")
- } else {
- s.Linkname = objabi.PathToPrefix(base.Ctxt.Pkgpath) + "." + n.local
- }
+ n := ir.AsNode(lookup(l.local).Def)
+ if n == nil || n.Op() != ir.ONAME {
+ // TODO(mdempsky): Change to p.errorAt before Go 1.17 release.
+ // base.WarnfAt(p.makeXPos(l.pos), "//go:linkname must refer to declared function or variable (will be an error in Go 1.17)")
+ continue
}
+ if n.Sym().Linkname != "" {
+ p.errorAt(l.pos, "duplicate //go:linkname for %s", l.local)
+ continue
+ }
+ n.Sym().Linkname = l.remote
}
// The linker expects an ABI0 wrapper for all cgo-exported
@@ -417,8 +425,6 @@ func (p *noder) node() {
}
pragcgobuf = append(pragcgobuf, p.pragcgobuf...)
- base.Pos = src.NoXPos
- clearImports()
}
func (p *noder) decls(decls []syntax.Decl) (l []ir.Node) {
@@ -474,6 +480,9 @@ func (p *noder) importDecl(imp *syntax.ImportDecl) {
p.importedEmbed = true
}
+ if !ipkg.Direct {
+ sourceOrderImports = append(sourceOrderImports, ipkg)
+ }
ipkg.Direct = true
var my *types.Sym
@@ -483,9 +492,7 @@ func (p *noder) importDecl(imp *syntax.ImportDecl) {
my = lookup(ipkg.Name)
}
- pack := p.nod(imp, ir.OPACK, nil, nil)
- pack.SetSym(my)
- pack.Name().Pkg = ipkg
+ pack := ir.NewPkgName(p.pos(imp), my, ipkg)
switch my.Name {
case ".":
@@ -541,7 +548,7 @@ func (p *noder) varDecl(decl *syntax.VarDecl) []ir.Node {
// constant declarations are handled correctly (e.g., issue 15550).
type constState struct {
group *syntax.Group
- typ ir.Node
+ typ ir.Ntype
values []ir.Node
iota int64
}
@@ -573,20 +580,21 @@ func (p *noder) constDecl(decl *syntax.ConstDecl, cs *constState) []ir.Node {
nn := make([]ir.Node, 0, len(names))
for i, n := range names {
+ n := n.(*ir.Name)
if i >= len(values) {
base.Errorf("missing value in const declaration")
break
}
v := values[i]
if decl.Values == nil {
- v = treecopy(v, n.Pos())
+ v = ir.DeepCopy(n.Pos(), v)
}
n.SetOp(ir.OLITERAL)
declare(n, dclcontext)
- n.Name().Param.Ntype = typ
- n.Name().Defn = v
+ n.Ntype = typ
+ n.Defn = v
n.SetIota(cs.iota)
nn = append(nn, p.nod(decl, ir.ODCLCONST, n, nil))
@@ -609,19 +617,18 @@ func (p *noder) typeDecl(decl *syntax.TypeDecl) ir.Node {
// decl.Type may be nil but in that case we got a syntax error during parsing
typ := p.typeExprOrNil(decl.Type)
- param := n.Name().Param
- param.Ntype = typ
- param.SetAlias(decl.Alias)
+ n.Ntype = typ
+ n.SetAlias(decl.Alias)
if pragma, ok := decl.Pragma.(*Pragma); ok {
if !decl.Alias {
- param.SetPragma(pragma.Flag & TypePragmas)
+ n.SetPragma(pragma.Flag & TypePragmas)
pragma.Flag &^= TypePragmas
}
p.checkUnused(pragma)
}
nod := p.nod(decl, ir.ODCLTYPE, n, nil)
- if param.Alias() && !langSupported(1, 9, ir.LocalPkg) {
+ if n.Alias() && !langSupported(1, 9, types.LocalPkg) {
base.ErrorfAt(nod.Pos(), "type aliases only supported as of -lang=go1.9")
}
return nod
@@ -635,16 +642,14 @@ func (p *noder) declNames(names []*syntax.Name) []ir.Node {
return nodes
}
-func (p *noder) declName(name *syntax.Name) ir.Node {
- n := dclname(p.name(name))
- n.SetPos(p.pos(name))
- return n
+func (p *noder) declName(name *syntax.Name) *ir.Name {
+ return ir.NewDeclNameAt(p.pos(name), p.name(name))
}
func (p *noder) funcDecl(fun *syntax.FuncDecl) ir.Node {
name := p.name(fun.Name)
t := p.signature(fun.Recv, fun.Type)
- f := p.nod(fun, ir.ODCLFUNC, nil, nil)
+ f := ir.NewFunc(p.pos(fun))
if fun.Recv == nil {
if name.Name == "init" {
@@ -654,22 +659,22 @@ func (p *noder) funcDecl(fun *syntax.FuncDecl) ir.Node {
}
}
- if ir.LocalPkg.Name == "main" && name.Name == "main" {
+ if types.LocalPkg.Name == "main" && name.Name == "main" {
if t.List().Len() > 0 || t.Rlist().Len() > 0 {
base.ErrorfAt(f.Pos(), "func main must have no arguments and no return values")
}
}
} else {
- f.Func().Shortname = name
+ f.Shortname = name
name = ir.BlankNode.Sym() // filled in by typecheckfunc
}
- f.Func().Nname = newfuncnamel(p.pos(fun.Name), name, f.Func())
- f.Func().Nname.Name().Defn = f
- f.Func().Nname.Name().Param.Ntype = t
+ f.Nname = newFuncNameAt(p.pos(fun.Name), name, f)
+ f.Nname.Defn = f
+ f.Nname.Ntype = t
if pragma, ok := fun.Pragma.(*Pragma); ok {
- f.Func().Pragma = pragma.Flag & FuncPragmas
+ f.Pragma = pragma.Flag & FuncPragmas
if pragma.Flag&ir.Systemstack != 0 && pragma.Flag&ir.Nosplit != 0 {
base.ErrorfAt(f.Pos(), "go:nosplit and go:systemstack cannot be combined")
}
@@ -678,13 +683,13 @@ func (p *noder) funcDecl(fun *syntax.FuncDecl) ir.Node {
}
if fun.Recv == nil {
- declare(f.Func().Nname, ir.PFUNC)
+ declare(f.Nname, ir.PFUNC)
}
p.funcBody(f, fun.Body)
if fun.Body != nil {
- if f.Func().Pragma&ir.Noescape != 0 {
+ if f.Pragma&ir.Noescape != 0 {
base.ErrorfAt(f.Pos(), "can only use //go:noescape with external func implementations")
}
} else {
@@ -707,18 +712,18 @@ func (p *noder) funcDecl(fun *syntax.FuncDecl) ir.Node {
return f
}
-func (p *noder) signature(recv *syntax.Field, typ *syntax.FuncType) ir.Node {
- n := p.nod(typ, ir.OTFUNC, nil, nil)
+func (p *noder) signature(recv *syntax.Field, typ *syntax.FuncType) *ir.FuncType {
+ var rcvr *ir.Field
if recv != nil {
- n.SetLeft(p.param(recv, false, false))
+ rcvr = p.param(recv, false, false)
}
- n.PtrList().Set(p.params(typ.ParamList, true))
- n.PtrRlist().Set(p.params(typ.ResultList, false))
- return n
+ return ir.NewFuncType(p.pos(typ), rcvr,
+ p.params(typ.ParamList, true),
+ p.params(typ.ResultList, false))
}
-func (p *noder) params(params []*syntax.Field, dddOk bool) []ir.Node {
- nodes := make([]ir.Node, 0, len(params))
+func (p *noder) params(params []*syntax.Field, dddOk bool) []*ir.Field {
+ nodes := make([]*ir.Field, 0, len(params))
for i, param := range params {
p.setlineno(param)
nodes = append(nodes, p.param(param, dddOk, i+1 == len(params)))
@@ -726,17 +731,17 @@ func (p *noder) params(params []*syntax.Field, dddOk bool) []ir.Node {
return nodes
}
-func (p *noder) param(param *syntax.Field, dddOk, final bool) ir.Node {
+func (p *noder) param(param *syntax.Field, dddOk, final bool) *ir.Field {
var name *types.Sym
if param.Name != nil {
name = p.name(param.Name)
}
typ := p.typeExpr(param.Type)
- n := p.nodSym(param, ir.ODCLFIELD, typ, name)
+ n := ir.NewField(p.pos(param), name, typ, nil)
// rewrite ...T parameter
- if typ.Op() == ir.ODDD {
+ if typ, ok := typ.(*ir.SliceType); ok && typ.DDD {
if !dddOk {
// We mark these as syntax errors to get automatic elimination
// of multiple such errors per line (see ErrorfAt in subr.go).
@@ -748,13 +753,8 @@ func (p *noder) param(param *syntax.Field, dddOk, final bool) ir.Node {
p.errorAt(param.Name.Pos(), "syntax error: cannot use ... with non-final parameter %s", param.Name.Value)
}
}
- typ.SetOp(ir.OTARRAY)
- typ.SetRight(typ.Left())
- typ.SetLeft(nil)
- n.SetIsDDD(true)
- if n.Left() != nil {
- n.Left().SetIsDDD(true)
- }
+ typ.DDD = false
+ n.IsDDD = true
}
return n
@@ -812,8 +812,9 @@ func (p *noder) expr(expr syntax.Expr) ir.Node {
// parser.new_dotname
obj := p.expr(expr.X)
if obj.Op() == ir.OPACK {
- obj.Name().SetUsed(true)
- return importName(obj.Name().Pkg.Lookup(expr.Sel.Value))
+ pack := obj.(*ir.PkgName)
+ pack.Used = true
+ return importName(pack.Pkg.Lookup(expr.Sel.Value))
}
n := nodSym(ir.OXDOT, obj, p.name(expr.Sel))
n.SetPos(p.pos(expr)) // lineno may have been changed by p.expr(expr.X)
@@ -855,14 +856,14 @@ func (p *noder) expr(expr syntax.Expr) ir.Node {
var len ir.Node
if expr.Len != nil {
len = p.expr(expr.Len)
- } else {
- len = p.nod(expr, ir.ODDD, nil, nil)
}
- return p.nod(expr, ir.OTARRAY, len, p.typeExpr(expr.Elem))
+ return ir.NewArrayType(p.pos(expr), len, p.typeExpr(expr.Elem))
case *syntax.SliceType:
- return p.nod(expr, ir.OTARRAY, nil, p.typeExpr(expr.Elem))
+ return ir.NewSliceType(p.pos(expr), p.typeExpr(expr.Elem))
case *syntax.DotsType:
- return p.nod(expr, ir.ODDD, p.typeExpr(expr.Elem), nil)
+ t := ir.NewSliceType(p.pos(expr), p.typeExpr(expr.Elem))
+ t.DDD = true
+ return t
case *syntax.StructType:
return p.structType(expr)
case *syntax.InterfaceType:
@@ -870,21 +871,21 @@ func (p *noder) expr(expr syntax.Expr) ir.Node {
case *syntax.FuncType:
return p.signature(nil, expr)
case *syntax.MapType:
- return p.nod(expr, ir.OTMAP, p.typeExpr(expr.Key), p.typeExpr(expr.Value))
+ return ir.NewMapType(p.pos(expr),
+ p.typeExpr(expr.Key), p.typeExpr(expr.Value))
case *syntax.ChanType:
- n := p.nod(expr, ir.OTCHAN, p.typeExpr(expr.Elem), nil)
- n.SetTChanDir(p.chanDir(expr.Dir))
- return n
+ return ir.NewChanType(p.pos(expr),
+ p.typeExpr(expr.Elem), p.chanDir(expr.Dir))
case *syntax.TypeSwitchGuard:
- n := p.nod(expr, ir.OTYPESW, nil, p.expr(expr.X))
+ var tag *ir.Ident
if expr.Lhs != nil {
- n.SetLeft(p.declName(expr.Lhs))
- if ir.IsBlank(n.Left()) {
- base.Errorf("invalid variable name %v in type switch", n.Left())
+ tag = ir.NewIdent(p.pos(expr.Lhs), p.name(expr.Lhs))
+ if ir.IsBlank(tag) {
+ base.Errorf("invalid variable name %v in type switch", tag)
}
}
- return n
+ return ir.NewTypeSwitchGuard(p.pos(expr), tag, p.expr(expr.X))
}
panic("unhandled Expr")
}
@@ -933,7 +934,7 @@ func (p *noder) sum(x syntax.Expr) ir.Node {
n := p.expr(x)
if ir.IsConst(n, constant.String) && n.Sym() == nil {
nstr = n
- chunks = append(chunks, nstr.StringVal())
+ chunks = append(chunks, ir.StringVal(nstr))
}
for i := len(adds) - 1; i >= 0; i-- {
@@ -943,12 +944,12 @@ func (p *noder) sum(x syntax.Expr) ir.Node {
if ir.IsConst(r, constant.String) && r.Sym() == nil {
if nstr != nil {
// Collapse r into nstr instead of adding to n.
- chunks = append(chunks, r.StringVal())
+ chunks = append(chunks, ir.StringVal(r))
continue
}
nstr = r
- chunks = append(chunks, nstr.StringVal())
+ chunks = append(chunks, ir.StringVal(nstr))
} else {
if len(chunks) > 1 {
nstr.SetVal(constant.MakeString(strings.Join(chunks, "")))
@@ -965,14 +966,21 @@ func (p *noder) sum(x syntax.Expr) ir.Node {
return n
}
-func (p *noder) typeExpr(typ syntax.Expr) ir.Node {
+func (p *noder) typeExpr(typ syntax.Expr) ir.Ntype {
// TODO(mdempsky): Be stricter? typecheck should handle errors anyway.
- return p.expr(typ)
+ n := p.expr(typ)
+ if n == nil {
+ return nil
+ }
+ if _, ok := n.(ir.Ntype); !ok {
+ ir.Dump("NOT NTYPE", n)
+ }
+ return n.(ir.Ntype)
}
-func (p *noder) typeExprOrNil(typ syntax.Expr) ir.Node {
+func (p *noder) typeExprOrNil(typ syntax.Expr) ir.Ntype {
if typ != nil {
- return p.expr(typ)
+ return p.typeExpr(typ)
}
return nil
}
@@ -990,55 +998,54 @@ func (p *noder) chanDir(dir syntax.ChanDir) types.ChanDir {
}
func (p *noder) structType(expr *syntax.StructType) ir.Node {
- l := make([]ir.Node, 0, len(expr.FieldList))
+ l := make([]*ir.Field, 0, len(expr.FieldList))
for i, field := range expr.FieldList {
p.setlineno(field)
- var n ir.Node
+ var n *ir.Field
if field.Name == nil {
n = p.embedded(field.Type)
} else {
- n = p.nodSym(field, ir.ODCLFIELD, p.typeExpr(field.Type), p.name(field.Name))
+ n = ir.NewField(p.pos(field), p.name(field.Name), p.typeExpr(field.Type), nil)
}
if i < len(expr.TagList) && expr.TagList[i] != nil {
- n.SetVal(p.basicLit(expr.TagList[i]))
+ n.Note = constant.StringVal(p.basicLit(expr.TagList[i]))
}
l = append(l, n)
}
p.setlineno(expr)
- n := p.nod(expr, ir.OTSTRUCT, nil, nil)
- n.PtrList().Set(l)
- return n
+ return ir.NewStructType(p.pos(expr), l)
}
func (p *noder) interfaceType(expr *syntax.InterfaceType) ir.Node {
- l := make([]ir.Node, 0, len(expr.MethodList))
+ l := make([]*ir.Field, 0, len(expr.MethodList))
for _, method := range expr.MethodList {
p.setlineno(method)
- var n ir.Node
+ var n *ir.Field
if method.Name == nil {
- n = p.nodSym(method, ir.ODCLFIELD, importName(p.packname(method.Type)), nil)
+ n = ir.NewField(p.pos(method), nil, importName(p.packname(method.Type)).(ir.Ntype), nil)
} else {
mname := p.name(method.Name)
- sig := p.typeExpr(method.Type)
- sig.SetLeft(fakeRecv())
- n = p.nodSym(method, ir.ODCLFIELD, sig, mname)
- ifacedcl(n)
+ if mname.IsBlank() {
+ base.Errorf("methods must have a unique non-blank name")
+ continue
+ }
+ sig := p.typeExpr(method.Type).(*ir.FuncType)
+ sig.Recv = fakeRecv()
+ n = ir.NewField(p.pos(method), mname, sig, nil)
}
l = append(l, n)
}
- n := p.nod(expr, ir.OTINTER, nil, nil)
- n.PtrList().Set(l)
- return n
+ return ir.NewInterfaceType(p.pos(expr), l)
}
func (p *noder) packname(expr syntax.Expr) *types.Sym {
switch expr := expr.(type) {
case *syntax.Name:
name := p.name(expr)
- if n := oldname(name); n.Name() != nil && n.Name().Pack != nil {
- n.Name().Pack.Name().SetUsed(true)
+ if n := oldname(name); n.Name() != nil && n.Name().PkgName != nil {
+ n.Name().PkgName.Used = true
}
return name
case *syntax.SelectorExpr:
@@ -1051,17 +1058,18 @@ func (p *noder) packname(expr syntax.Expr) *types.Sym {
var pkg *types.Pkg
if def.Op() != ir.OPACK {
base.Errorf("%v is not a package", name)
- pkg = ir.LocalPkg
+ pkg = types.LocalPkg
} else {
- def.Name().SetUsed(true)
- pkg = def.Name().Pkg
+ def := def.(*ir.PkgName)
+ def.Used = true
+ pkg = def.Pkg
}
return pkg.Lookup(expr.Sel.Value)
}
panic(fmt.Sprintf("unexpected packname: %#v", expr))
}
-func (p *noder) embedded(typ syntax.Expr) ir.Node {
+func (p *noder) embedded(typ syntax.Expr) *ir.Field {
op, isStar := typ.(*syntax.Operation)
if isStar {
if op.Op != syntax.Mul || op.Y != nil {
@@ -1071,11 +1079,11 @@ func (p *noder) embedded(typ syntax.Expr) ir.Node {
}
sym := p.packname(typ)
- n := p.nodSym(typ, ir.ODCLFIELD, importName(sym), lookup(sym.Name))
- n.SetEmbedded(true)
+ n := ir.NewField(p.pos(typ), lookup(sym.Name), importName(sym).(ir.Ntype), nil)
+ n.Embedded = true
if isStar {
- n.SetLeft(p.nod(op, ir.ODEREF, n.Left(), nil))
+ n.Ntype = ir.NewStarExpr(p.pos(op), n.Ntype)
}
return n
}
@@ -1089,7 +1097,9 @@ func (p *noder) stmtsFall(stmts []syntax.Stmt, fallOK bool) []ir.Node {
for i, stmt := range stmts {
s := p.stmtFall(stmt, fallOK && i+1 == len(stmts))
if s == nil {
- } else if s.Op() == ir.OBLOCK && s.Init().Len() == 0 {
+ } else if s.Op() == ir.OBLOCK && s.List().Len() > 0 {
+ // Inline non-empty block.
+ // Empty blocks must be preserved for checkreturn.
nodes = append(nodes, s.List().Slice()...)
} else {
nodes = append(nodes, s)
@@ -1113,7 +1123,7 @@ func (p *noder) stmtFall(stmt syntax.Stmt, fallOK bool) ir.Node {
l := p.blockStmt(stmt)
if len(l) == 0 {
// TODO(mdempsky): Line number?
- return ir.Nod(ir.OEMPTY, nil, nil)
+ return ir.Nod(ir.OBLOCK, nil, nil)
}
return liststmt(l)
case *syntax.ExprStmt:
@@ -1130,20 +1140,17 @@ func (p *noder) stmtFall(stmt syntax.Stmt, fallOK bool) ir.Node {
return n
}
- n := p.nod(stmt, ir.OAS, nil, nil) // assume common case
-
rhs := p.exprList(stmt.Rhs)
- lhs := p.assignList(stmt.Lhs, n, stmt.Op == syntax.Def)
-
- if len(lhs) == 1 && len(rhs) == 1 {
- // common case
- n.SetLeft(lhs[0])
- n.SetRight(rhs[0])
- } else {
- n.SetOp(ir.OAS2)
- n.PtrList().Set(lhs)
+ if list, ok := stmt.Lhs.(*syntax.ListExpr); ok && len(list.ElemList) != 1 || len(rhs) != 1 {
+ n := p.nod(stmt, ir.OAS2, nil, nil)
+ n.PtrList().Set(p.assignList(stmt.Lhs, n, stmt.Op == syntax.Def))
n.PtrRlist().Set(rhs)
+ return n
}
+
+ n := p.nod(stmt, ir.OAS, nil, nil)
+ n.SetLeft(p.assignList(stmt.Lhs, n, stmt.Op == syntax.Def)[0])
+ n.SetRight(rhs[0])
return n
case *syntax.BranchStmt:
@@ -1187,14 +1194,14 @@ func (p *noder) stmtFall(stmt syntax.Stmt, fallOK bool) ir.Node {
n := p.nod(stmt, ir.ORETURN, nil, nil)
n.PtrList().Set(results)
if n.List().Len() == 0 && Curfn != nil {
- for _, ln := range Curfn.Func().Dcl {
+ for _, ln := range Curfn.Dcl {
if ln.Class() == ir.PPARAM {
continue
}
if ln.Class() != ir.PPARAMOUT {
break
}
- if ir.AsNode(ln.Sym().Def) != ln {
+ if ln.Sym().Def != ln {
base.Errorf("%s is shadowed during return", ln.Sym().Name)
}
}
@@ -1261,7 +1268,7 @@ func (p *noder) assignList(expr syntax.Expr, defn ir.Node, colas bool) []ir.Node
newOrErr = true
n := NewName(sym)
declare(n, dclcontext)
- n.Name().Defn = defn
+ n.Defn = defn
defn.PtrInit().Append(ir.Nod(ir.ODCL, n, nil))
res[i] = n
}
@@ -1291,7 +1298,7 @@ func (p *noder) ifStmt(stmt *syntax.IfStmt) ir.Node {
n.PtrBody().Set(p.blockStmt(stmt.Then))
if stmt.Else != nil {
e := p.stmt(stmt.Else)
- if e.Op() == ir.OBLOCK && e.Init().Len() == 0 {
+ if e.Op() == ir.OBLOCK {
n.PtrRlist().Set(e.List().Slice())
} else {
n.PtrRlist().Set1(e)
@@ -1368,7 +1375,7 @@ func (p *noder) caseClauses(clauses []*syntax.CaseClause, tswitch ir.Node, rbrac
declare(nn, dclcontext)
n.PtrRlist().Set1(nn)
// keep track of the instances for reporting unused
- nn.Name().Defn = tswitch
+ nn.Defn = tswitch
}
// Trim trailing empty statements. We omit them from
@@ -1429,17 +1436,22 @@ func (p *noder) commClauses(clauses []*syntax.CommClause, rbrace syntax.Pos) []i
}
func (p *noder) labeledStmt(label *syntax.LabeledStmt, fallOK bool) ir.Node {
- lhs := p.nodSym(label, ir.OLABEL, nil, p.name(label.Label))
+ sym := p.name(label.Label)
+ lhs := p.nodSym(label, ir.OLABEL, nil, sym)
var ls ir.Node
if label.Stmt != nil { // TODO(mdempsky): Should always be present.
ls = p.stmtFall(label.Stmt, fallOK)
+ switch label.Stmt.(type) {
+ case *syntax.ForStmt, *syntax.SwitchStmt, *syntax.SelectStmt:
+ // Attach label directly to control statement too.
+ ls.SetSym(sym)
+ }
}
- lhs.Name().Defn = ls
l := []ir.Node{lhs}
if ls != nil {
- if ls.Op() == ir.OBLOCK && ls.Init().Len() == 0 {
+ if ls.Op() == ir.OBLOCK {
l = append(l, ls.List().Slice()...)
} else {
l = append(l, ls)
@@ -1502,7 +1514,7 @@ func (p *noder) binOp(op syntax.Operator) ir.Op {
// literal is not compatible with the current language version.
func checkLangCompat(lit *syntax.BasicLit) {
s := lit.Value
- if len(s) <= 2 || langSupported(1, 13, ir.LocalPkg) {
+ if len(s) <= 2 || langSupported(1, 13, types.LocalPkg) {
return
}
// len(s) > 2
@@ -1716,6 +1728,13 @@ func (p *noder) pragma(pos syntax.Pos, blankLine bool, text string, old syntax.P
var target string
if len(f) == 3 {
target = f[2]
+ } else if base.Ctxt.Pkgpath != "" {
+ // Use the default object symbol name if the
+ // user didn't provide one.
+ target = objabi.PathToPrefix(base.Ctxt.Pkgpath) + "." + f[1]
+ } else {
+ p.error(syntax.Error{Pos: pos, Msg: "//go:linkname requires linkname argument or -p compiler flag"})
+ break
}
p.linknames = append(p.linknames, linkname{pos, f[1], target})
@@ -1797,8 +1816,8 @@ func safeArg(name string) bool {
func mkname(sym *types.Sym) ir.Node {
n := oldname(sym)
- if n.Name() != nil && n.Name().Pack != nil {
- n.Name().Pack.Name().SetUsed(true)
+ if n.Name() != nil && n.Name().PkgName != nil {
+ n.Name().PkgName.Used = true
}
return n
}
diff --git a/src/cmd/compile/internal/gc/obj.go b/src/cmd/compile/internal/gc/obj.go
index d566959d9e..c34a86d4eb 100644
--- a/src/cmd/compile/internal/gc/obj.go
+++ b/src/cmd/compile/internal/gc/obj.go
@@ -84,7 +84,7 @@ func printObjHeader(bout *bio.Writer) {
if base.Flag.BuildID != "" {
fmt.Fprintf(bout, "build id %q\n", base.Flag.BuildID)
}
- if ir.LocalPkg.Name == "main" {
+ if types.LocalPkg.Name == "main" {
fmt.Fprintf(bout, "main\n")
}
fmt.Fprintf(bout, "\n") // header ends with blank line
@@ -143,7 +143,7 @@ func dumpdata() {
for i := xtops; i < len(xtop); i++ {
n := xtop[i]
if n.Op() == ir.ODCLFUNC {
- funccompile(n)
+ funccompile(n.(*ir.Func))
}
}
xtops = len(xtop)
@@ -200,7 +200,7 @@ func dumpLinkerObj(bout *bio.Writer) {
}
func addptabs() {
- if !base.Ctxt.Flag_dynlink || ir.LocalPkg.Name != "main" {
+ if !base.Ctxt.Flag_dynlink || types.LocalPkg.Name != "main" {
return
}
for _, exportn := range exportlist {
@@ -218,12 +218,12 @@ func addptabs() {
if s.Pkg.Name != "main" {
continue
}
- if n.Type().Etype == types.TFUNC && n.Class() == ir.PFUNC {
+ if n.Type().Kind() == types.TFUNC && n.Class() == ir.PFUNC {
// function
- ptabs = append(ptabs, ptabEntry{s: s, t: ir.AsNode(s.Def).Type()})
+ ptabs = append(ptabs, ptabEntry{s: s, t: s.Def.Type()})
} else {
// variable
- ptabs = append(ptabs, ptabEntry{s: s, t: types.NewPtr(ir.AsNode(s.Def).Type())})
+ ptabs = append(ptabs, ptabEntry{s: s, t: types.NewPtr(s.Def.Type())})
}
}
}
@@ -235,7 +235,7 @@ func dumpGlobal(n ir.Node) {
if n.Class() == ir.PFUNC {
return
}
- if n.Sym().Pkg != ir.LocalPkg {
+ if n.Sym().Pkg != types.LocalPkg {
return
}
dowidth(n.Type())
@@ -248,7 +248,7 @@ func dumpGlobalConst(n ir.Node) {
if t == nil {
return
}
- if n.Sym().Pkg != ir.LocalPkg {
+ if n.Sym().Pkg != types.LocalPkg {
return
}
// only export integer constants for now
@@ -263,7 +263,7 @@ func dumpGlobalConst(n ir.Node) {
return
}
}
- base.Ctxt.DwarfIntConst(base.Ctxt.Pkgpath, n.Sym().Name, typesymname(t), ir.Int64Val(t, v))
+ base.Ctxt.DwarfIntConst(base.Ctxt.Pkgpath, n.Sym().Name, typesymname(t), ir.IntVal(t, v))
}
func dumpglobls() {
@@ -478,7 +478,7 @@ var slicedataGen int
func slicedata(pos src.XPos, s string) ir.Node {
slicedataGen++
symname := fmt.Sprintf(".gobytes.%d", slicedataGen)
- sym := ir.LocalPkg.Lookup(symname)
+ sym := types.LocalPkg.Lookup(symname)
symnode := NewName(sym)
sym.Def = symnode
@@ -598,11 +598,11 @@ func litsym(n, c ir.Node, wid int) {
s.WriteInt(base.Ctxt, n.Offset(), wid, i)
case constant.Int:
- s.WriteInt(base.Ctxt, n.Offset(), wid, ir.Int64Val(n.Type(), u))
+ s.WriteInt(base.Ctxt, n.Offset(), wid, ir.IntVal(n.Type(), u))
case constant.Float:
f, _ := constant.Float64Val(u)
- switch n.Type().Etype {
+ switch n.Type().Kind() {
case types.TFLOAT32:
s.WriteFloat32(base.Ctxt, n.Offset(), float32(f))
case types.TFLOAT64:
@@ -612,7 +612,7 @@ func litsym(n, c ir.Node, wid int) {
case constant.Complex:
re, _ := constant.Float64Val(constant.Real(u))
im, _ := constant.Float64Val(constant.Imag(u))
- switch n.Type().Etype {
+ switch n.Type().Kind() {
case types.TCOMPLEX64:
s.WriteFloat32(base.Ctxt, n.Offset(), float32(re))
s.WriteFloat32(base.Ctxt, n.Offset()+4, float32(im))
diff --git a/src/cmd/compile/internal/gc/order.go b/src/cmd/compile/internal/gc/order.go
index b7d713439b..c3645256a6 100644
--- a/src/cmd/compile/internal/gc/order.go
+++ b/src/cmd/compile/internal/gc/order.go
@@ -44,27 +44,27 @@ import (
// Order holds state during the ordering process.
type Order struct {
- out []ir.Node // list of generated statements
- temp []ir.Node // stack of temporary variables
- free map[string][]ir.Node // free list of unused temporaries, by type.LongString().
+ out []ir.Node // list of generated statements
+ temp []*ir.Name // stack of temporary variables
+ free map[string][]*ir.Name // free list of unused temporaries, by type.LongString().
}
// Order rewrites fn.Nbody to apply the ordering constraints
// described in the comment at the top of the file.
-func order(fn ir.Node) {
+func order(fn *ir.Func) {
if base.Flag.W > 1 {
- s := fmt.Sprintf("\nbefore order %v", fn.Func().Nname.Sym())
+ s := fmt.Sprintf("\nbefore order %v", fn.Sym())
ir.DumpList(s, fn.Body())
}
- orderBlock(fn.PtrBody(), map[string][]ir.Node{})
+ orderBlock(fn.PtrBody(), map[string][]*ir.Name{})
}
// newTemp allocates a new temporary with the given type,
// pushes it onto the temp stack, and returns it.
// If clear is true, newTemp emits code to zero the temporary.
-func (o *Order) newTemp(t *types.Type, clear bool) ir.Node {
- var v ir.Node
+func (o *Order) newTemp(t *types.Type, clear bool) *ir.Name {
+ var v *ir.Name
// Note: LongString is close to the type equality we want,
// but not exactly. We still need to double-check with types.Identical.
key := t.LongString()
@@ -93,17 +93,26 @@ func (o *Order) newTemp(t *types.Type, clear bool) ir.Node {
// copyExpr behaves like newTemp but also emits
// code to initialize the temporary to the value n.
-//
-// The clear argument is provided for use when the evaluation
-// of tmp = n turns into a function call that is passed a pointer
-// to the temporary as the output space. If the call blocks before
-// tmp has been written, the garbage collector will still treat the
-// temporary as live, so we must zero it before entering that call.
+func (o *Order) copyExpr(n ir.Node) ir.Node {
+ return o.copyExpr1(n, false)
+}
+
+// copyExprClear is like copyExpr but clears the temp before assignment.
+// It is provided for use when the evaluation of tmp = n turns into
+// a function call that is passed a pointer to the temporary as the output space.
+// If the call blocks before tmp has been written,
+// the garbage collector will still treat the temporary as live,
+// so we must zero it before entering that call.
// Today, this only happens for channel receive operations.
// (The other candidate would be map access, but map access
// returns a pointer to the result data instead of taking a pointer
// to be filled in.)
-func (o *Order) copyExpr(n ir.Node, t *types.Type, clear bool) ir.Node {
+func (o *Order) copyExprClear(n ir.Node) *ir.Name {
+ return o.copyExpr1(n, true)
+}
+
+func (o *Order) copyExpr1(n ir.Node, clear bool) *ir.Name {
+ t := n.Type()
v := o.newTemp(t, clear)
a := ir.Nod(ir.OAS, v, n)
a = typecheck(a, ctxStmt)
@@ -133,7 +142,7 @@ func (o *Order) cheapExpr(n ir.Node) ir.Node {
return typecheck(a, ctxExpr)
}
- return o.copyExpr(n, n.Type(), false)
+ return o.copyExpr(n)
}
// safeExpr returns a safe version of n.
@@ -220,7 +229,7 @@ func (o *Order) addrTemp(n ir.Node) ir.Node {
if isaddrokay(n) {
return n
}
- return o.copyExpr(n, n.Type(), false)
+ return o.copyExpr(n)
}
// mapKeyTemp prepares n to be a key in a map runtime call and returns n.
@@ -406,7 +415,7 @@ func (o *Order) edge() {
// orderBlock orders the block of statements in n into a new slice,
// and then replaces the old slice in n with the new slice.
// free is a map that can be used to obtain temporary variables by type.
-func orderBlock(n *ir.Nodes, free map[string][]ir.Node) {
+func orderBlock(n *ir.Nodes, free map[string][]*ir.Name) {
var order Order
order.free = free
mark := order.markTemp()
@@ -424,7 +433,7 @@ func (o *Order) exprInPlace(n ir.Node) ir.Node {
var order Order
order.free = o.free
n = order.expr(n, nil)
- n = addinit(n, order.out)
+ n = initExpr(order.out, n)
// insert new temporaries from order
// at head of outer list.
@@ -437,7 +446,7 @@ func (o *Order) exprInPlace(n ir.Node) ir.Node {
// The result of orderStmtInPlace MUST be assigned back to n, e.g.
// n.Left = orderStmtInPlace(n.Left)
// free is a map that can be used to obtain temporary variables by type.
-func orderStmtInPlace(n ir.Node, free map[string][]ir.Node) ir.Node {
+func orderStmtInPlace(n ir.Node, free map[string][]*ir.Name) ir.Node {
var order Order
order.free = free
mark := order.markTemp()
@@ -489,7 +498,7 @@ func (o *Order) call(n ir.Node) {
// by copying it into a temp and marking that temp
// still alive when we pop the temp stack.
if arg.Op() == ir.OCONVNOP && arg.Left().Type().IsUnsafePtr() {
- x := o.copyExpr(arg.Left(), arg.Left().Type(), false)
+ x := o.copyExpr(arg.Left())
arg.SetLeft(x)
x.Name().SetAddrtaken(true) // ensure SSA keeps the x variable
n.PtrBody().Append(typecheck(ir.Nod(ir.OVARLIVE, x, nil), ctxStmt))
@@ -551,10 +560,10 @@ func (o *Order) mapAssign(n ir.Node) {
switch {
case m.Op() == ir.OINDEXMAP:
if !ir.IsAutoTmp(m.Left()) {
- m.SetLeft(o.copyExpr(m.Left(), m.Left().Type(), false))
+ m.SetLeft(o.copyExpr(m.Left()))
}
if !ir.IsAutoTmp(m.Right()) {
- m.SetRight(o.copyExpr(m.Right(), m.Right().Type(), false))
+ m.SetRight(o.copyExpr(m.Right()))
}
fallthrough
case instrumenting && n.Op() == ir.OAS2FUNC && !ir.IsBlank(m):
@@ -606,20 +615,19 @@ func (o *Order) stmt(n ir.Node) {
// that we can ensure that if op panics
// because r is zero, the panic happens before
// the map assignment.
-
- n.SetLeft(o.safeExpr(n.Left()))
-
- l := treecopy(n.Left(), src.NoXPos)
- if l.Op() == ir.OINDEXMAP {
- l.SetIndexMapLValue(false)
+ // DeepCopy is a big hammer here, but safeExpr
+ // makes sure there is nothing too deep being copied.
+ l1 := o.safeExpr(n.Left())
+ l2 := ir.DeepCopy(src.NoXPos, l1)
+ if l1.Op() == ir.OINDEXMAP {
+ l2.SetIndexMapLValue(false)
}
- l = o.copyExpr(l, n.Left().Type(), false)
- n.SetRight(ir.Nod(n.SubOp(), l, n.Right()))
- n.SetRight(typecheck(n.Right(), ctxExpr))
- n.SetRight(o.expr(n.Right(), nil))
-
- n.SetOp(ir.OAS)
- n.ResetAux()
+ l2 = o.copyExpr(l2)
+ r := ir.NodAt(n.Pos(), n.SubOp(), l2, n.Right())
+ r = typecheck(r, ctxExpr)
+ r = o.expr(r, nil)
+ n = ir.NodAt(n.Pos(), ir.OAS, l1, r)
+ n = typecheck(n, ctxStmt)
}
o.mapAssign(n)
@@ -636,8 +644,8 @@ func (o *Order) stmt(n ir.Node) {
case ir.OAS2FUNC:
t := o.markTemp()
o.exprList(n.List())
- o.init(n.Right())
- o.call(n.Right())
+ o.init(n.Rlist().First())
+ o.call(n.Rlist().First())
o.as2(n)
o.cleanTemp(t)
@@ -651,7 +659,7 @@ func (o *Order) stmt(n ir.Node) {
t := o.markTemp()
o.exprList(n.List())
- switch r := n.Right(); r.Op() {
+ switch r := n.Rlist().First(); r.Op() {
case ir.ODOTTYPE2, ir.ORECV:
r.SetLeft(o.expr(r.Left(), nil))
case ir.OINDEXMAP:
@@ -668,7 +676,7 @@ func (o *Order) stmt(n ir.Node) {
o.cleanTemp(t)
// Special: does not save n onto out.
- case ir.OBLOCK, ir.OEMPTY:
+ case ir.OBLOCK:
o.stmtList(n.List())
// Special: n->left is not an expression; save as is.
@@ -776,7 +784,7 @@ func (o *Order) stmt(n ir.Node) {
n.SetRight(o.expr(n.Right(), nil))
orderBody := true
- switch n.Type().Etype {
+ switch n.Type().Kind() {
default:
base.Fatalf("order.stmt range %v", n.Type())
@@ -799,7 +807,7 @@ func (o *Order) stmt(n ir.Node) {
r = typecheck(r, ctxExpr)
}
- n.SetRight(o.copyExpr(r, r.Type(), false))
+ n.SetRight(o.copyExpr(r))
case types.TMAP:
if isMapClear(n) {
@@ -814,7 +822,7 @@ func (o *Order) stmt(n ir.Node) {
// TODO(rsc): Make tmp = literal expressions reuse tmp.
// For maps tmp is just one word so it hardly matters.
r := n.Right()
- n.SetRight(o.copyExpr(r, r.Type(), false))
+ n.SetRight(o.copyExpr(r))
// prealloc[n] is the temp for the iterator.
// hiter contains pointers and needs to be zeroed.
@@ -863,38 +871,39 @@ func (o *Order) stmt(n ir.Node) {
ir.Dump("select case", r)
base.Fatalf("unknown op in select %v", r.Op())
- // If this is case x := <-ch or case x, y := <-ch, the case has
- // the ODCL nodes to declare x and y. We want to delay that
- // declaration (and possible allocation) until inside the case body.
- // Delete the ODCL nodes here and recreate them inside the body below.
case ir.OSELRECV, ir.OSELRECV2:
- if r.Colas() {
- i := 0
- if r.Init().Len() != 0 && r.Init().First().Op() == ir.ODCL && r.Init().First().Left() == r.Left() {
- i++
- }
- if i < r.Init().Len() && r.Init().Index(i).Op() == ir.ODCL && r.List().Len() != 0 && r.Init().Index(i).Left() == r.List().First() {
- i++
- }
- if i >= r.Init().Len() {
- r.PtrInit().Set(nil)
- }
+ var dst, ok, recv ir.Node
+ if r.Op() == ir.OSELRECV {
+ // case x = <-c
+ // case <-c (dst is ir.BlankNode)
+ dst, ok, recv = r.Left(), ir.BlankNode, r.Right()
+ } else {
+ // case x, ok = <-c
+ dst, ok, recv = r.List().First(), r.List().Second(), r.Rlist().First()
}
+ // If this is case x := <-ch or case x, y := <-ch, the case has
+ // the ODCL nodes to declare x and y. We want to delay that
+ // declaration (and possible allocation) until inside the case body.
+ // Delete the ODCL nodes here and recreate them inside the body below.
+ if r.Colas() {
+ init := r.Init().Slice()
+ if len(init) > 0 && init[0].Op() == ir.ODCL && init[0].Left() == dst {
+ init = init[1:]
+ }
+ if len(init) > 0 && init[0].Op() == ir.ODCL && init[0].Left() == ok {
+ init = init[1:]
+ }
+ r.PtrInit().Set(init)
+ }
if r.Init().Len() != 0 {
ir.DumpList("ninit", r.Init())
base.Fatalf("ninit on select recv")
}
- // case x = <-c
- // case x, ok = <-c
- // r->left is x, r->ntest is ok, r->right is ORECV, r->right->left is c.
- // r->left == N means 'case <-c'.
- // c is always evaluated; x and ok are only evaluated when assigned.
- r.Right().SetLeft(o.expr(r.Right().Left(), nil))
-
- if r.Right().Left().Op() != ir.ONAME {
- r.Right().SetLeft(o.copyExpr(r.Right().Left(), r.Right().Left().Type(), false))
+ recv.SetLeft(o.expr(recv.Left(), nil))
+ if recv.Left().Op() != ir.ONAME {
+ recv.SetLeft(o.copyExpr(recv.Left()))
}
// Introduce temporary for receive and move actual copy into case body.
@@ -903,42 +912,41 @@ func (o *Order) stmt(n ir.Node) {
// temporary per distinct type, sharing the temp among all receives
// with that temp. Similarly one ok bool could be shared among all
// the x,ok receives. Not worth doing until there's a clear need.
- if r.Left() != nil && ir.IsBlank(r.Left()) {
- r.SetLeft(nil)
- }
- if r.Left() != nil {
+ if !ir.IsBlank(dst) {
// use channel element type for temporary to avoid conversions,
// such as in case interfacevalue = <-intchan.
// the conversion happens in the OAS instead.
- tmp1 := r.Left()
-
if r.Colas() {
- tmp2 := ir.Nod(ir.ODCL, tmp1, nil)
- tmp2 = typecheck(tmp2, ctxStmt)
- n2.PtrInit().Append(tmp2)
+ dcl := ir.Nod(ir.ODCL, dst, nil)
+ dcl = typecheck(dcl, ctxStmt)
+ n2.PtrInit().Append(dcl)
}
- r.SetLeft(o.newTemp(r.Right().Left().Type().Elem(), r.Right().Left().Type().Elem().HasPointers()))
- tmp2 := ir.Nod(ir.OAS, tmp1, r.Left())
- tmp2 = typecheck(tmp2, ctxStmt)
- n2.PtrInit().Append(tmp2)
+ tmp := o.newTemp(recv.Left().Type().Elem(), recv.Left().Type().Elem().HasPointers())
+ as := ir.Nod(ir.OAS, dst, tmp)
+ as = typecheck(as, ctxStmt)
+ n2.PtrInit().Append(as)
+ dst = tmp
}
-
- if r.List().Len() != 0 && ir.IsBlank(r.List().First()) {
- r.PtrList().Set(nil)
- }
- if r.List().Len() != 0 {
- tmp1 := r.List().First()
+ if !ir.IsBlank(ok) {
if r.Colas() {
- tmp2 := ir.Nod(ir.ODCL, tmp1, nil)
- tmp2 = typecheck(tmp2, ctxStmt)
- n2.PtrInit().Append(tmp2)
+ dcl := ir.Nod(ir.ODCL, ok, nil)
+ dcl = typecheck(dcl, ctxStmt)
+ n2.PtrInit().Append(dcl)
}
- r.PtrList().Set1(o.newTemp(types.Types[types.TBOOL], false))
- tmp2 := okas(tmp1, r.List().First())
- tmp2 = typecheck(tmp2, ctxStmt)
- n2.PtrInit().Append(tmp2)
+ tmp := o.newTemp(types.Types[types.TBOOL], false)
+ as := ir.Nod(ir.OAS, ok, conv(tmp, ok.Type()))
+ as = typecheck(as, ctxStmt)
+ n2.PtrInit().Append(as)
+ ok = tmp
+ }
+
+ if r.Op() == ir.OSELRECV {
+ r.SetLeft(dst)
+ } else {
+ r.List().SetIndex(0, dst)
+ r.List().SetIndex(1, ok)
}
orderBlock(n2.PtrInit(), o.free)
@@ -953,11 +961,11 @@ func (o *Order) stmt(n ir.Node) {
r.SetLeft(o.expr(r.Left(), nil))
if !ir.IsAutoTmp(r.Left()) {
- r.SetLeft(o.copyExpr(r.Left(), r.Left().Type(), false))
+ r.SetLeft(o.copyExpr(r.Left()))
}
r.SetRight(o.expr(r.Right(), nil))
if !ir.IsAutoTmp(r.Right()) {
- r.SetRight(o.copyExpr(r.Right(), r.Right().Type(), false))
+ r.SetRight(o.copyExpr(r.Right()))
}
}
}
@@ -985,7 +993,7 @@ func (o *Order) stmt(n ir.Node) {
if instrumenting {
// Force copying to the stack so that (chan T)(nil) <- x
// is still instrumented as a read of x.
- n.SetRight(o.copyExpr(n.Right(), n.Right().Type(), false))
+ n.SetRight(o.copyExpr(n.Right()))
} else {
n.SetRight(o.addrTemp(n.Right()))
}
@@ -1054,6 +1062,10 @@ func (o *Order) exprListInPlace(l ir.Nodes) {
// prealloc[x] records the allocation to use for x.
var prealloc = map[ir.Node]ir.Node{}
+func (o *Order) exprNoLHS(n ir.Node) ir.Node {
+ return o.expr(n, nil)
+}
+
// expr orders a single expression, appending side
// effects to o.out as needed.
// If this is part of an assignment lhs = *np, lhs is given.
@@ -1071,10 +1083,7 @@ func (o *Order) expr(n, lhs ir.Node) ir.Node {
switch n.Op() {
default:
- n.SetLeft(o.expr(n.Left(), nil))
- n.SetRight(o.expr(n.Right(), nil))
- o.exprList(n.List())
- o.exprList(n.Rlist())
+ ir.EditChildren(n, o.exprNoLHS)
// Addition of strings turns into a function call.
// Allocate a temporary to hold the strings.
@@ -1099,7 +1108,7 @@ func (o *Order) expr(n, lhs ir.Node) ir.Node {
haslit := false
for _, n1 := range n.List().Slice() {
hasbyte = hasbyte || n1.Op() == ir.OBYTES2STR
- haslit = haslit || n1.Op() == ir.OLITERAL && len(n1.StringVal()) != 0
+ haslit = haslit || n1.Op() == ir.OLITERAL && len(ir.StringVal(n1)) != 0
}
if haslit && hasbyte {
@@ -1123,8 +1132,7 @@ func (o *Order) expr(n, lhs ir.Node) ir.Node {
needCopy = mapKeyReplaceStrConv(n.Right())
if instrumenting {
- // Race detector needs the copy so it can
- // call treecopy on the result.
+ // Race detector needs the copy.
needCopy = true
}
}
@@ -1132,7 +1140,7 @@ func (o *Order) expr(n, lhs ir.Node) ir.Node {
// key must be addressable
n.SetRight(o.mapKeyTemp(n.Left().Type(), n.Right()))
if needCopy {
- n = o.copyExpr(n, n.Type(), false)
+ n = o.copyExpr(n)
}
// concrete type (not interface) argument might need an addressable
@@ -1157,7 +1165,7 @@ func (o *Order) expr(n, lhs ir.Node) ir.Node {
o.init(n.Left())
o.call(n.Left())
if lhs == nil || lhs.Op() != ir.ONAME || instrumenting {
- n = o.copyExpr(n, n.Type(), false)
+ n = o.copyExpr(n)
}
} else {
n.SetLeft(o.expr(n.Left(), nil))
@@ -1227,7 +1235,7 @@ func (o *Order) expr(n, lhs ir.Node) ir.Node {
}
if lhs == nil || lhs.Op() != ir.ONAME || instrumenting {
- n = o.copyExpr(n, n.Type(), false)
+ n = o.copyExpr(n)
}
case ir.OAPPEND:
@@ -1240,7 +1248,7 @@ func (o *Order) expr(n, lhs ir.Node) ir.Node {
}
if lhs == nil || lhs.Op() != ir.ONAME && !samesafeexpr(lhs, n.List().First()) {
- n = o.copyExpr(n, n.Type(), false)
+ n = o.copyExpr(n)
}
case ir.OSLICE, ir.OSLICEARR, ir.OSLICESTR, ir.OSLICE3, ir.OSLICE3ARR:
@@ -1254,11 +1262,11 @@ func (o *Order) expr(n, lhs ir.Node) ir.Node {
max = o.cheapExpr(max)
n.SetSliceBounds(low, high, max)
if lhs == nil || lhs.Op() != ir.ONAME && !samesafeexpr(lhs, n.Left()) {
- n = o.copyExpr(n, n.Type(), false)
+ n = o.copyExpr(n)
}
case ir.OCLOSURE:
- if n.Transient() && n.Func().ClosureVars.Len() > 0 {
+ if n.Transient() && len(n.Func().ClosureVars) > 0 {
prealloc[n] = o.newTemp(closureType(n), false)
}
@@ -1271,7 +1279,7 @@ func (o *Order) expr(n, lhs ir.Node) ir.Node {
var t *types.Type
switch n.Op() {
case ir.OSLICELIT:
- t = types.NewArray(n.Type().Elem(), n.Right().Int64Val())
+ t = types.NewArray(n.Type().Elem(), ir.Int64Val(n.Right()))
case ir.OCALLPART:
t = partialCallType(n)
}
@@ -1281,12 +1289,12 @@ func (o *Order) expr(n, lhs ir.Node) ir.Node {
case ir.ODOTTYPE, ir.ODOTTYPE2:
n.SetLeft(o.expr(n.Left(), nil))
if !isdirectiface(n.Type()) || instrumenting {
- n = o.copyExpr(n, n.Type(), true)
+ n = o.copyExprClear(n)
}
case ir.ORECV:
n.SetLeft(o.expr(n.Left(), nil))
- n = o.copyExpr(n, n.Type(), true)
+ n = o.copyExprClear(n)
case ir.OEQ, ir.ONE, ir.OLT, ir.OLE, ir.OGT, ir.OGE:
n.SetLeft(o.expr(n.Left(), nil))
@@ -1375,15 +1383,6 @@ func (o *Order) expr(n, lhs ir.Node) ir.Node {
return n
}
-// okas creates and returns an assignment of val to ok,
-// including an explicit conversion if necessary.
-func okas(ok, val ir.Node) ir.Node {
- if !ir.IsBlank(ok) {
- val = conv(val, ok.Type())
- }
- return ir.Nod(ir.OAS, ok, val)
-}
-
// as2 orders OAS2XXXX nodes. It creates temporaries to ensure left-to-right assignment.
// The caller should order the right-hand side of the assignment before calling order.as2.
// It rewrites,
@@ -1418,7 +1417,7 @@ func (o *Order) as2(n ir.Node) {
func (o *Order) okAs2(n ir.Node) {
var tmp1, tmp2 ir.Node
if !ir.IsBlank(n.List().First()) {
- typ := n.Right().Type()
+ typ := n.Rlist().First().Type()
tmp1 = o.newTemp(typ, typ.HasPointers())
}
@@ -1435,7 +1434,7 @@ func (o *Order) okAs2(n ir.Node) {
n.List().SetFirst(tmp1)
}
if tmp2 != nil {
- r := okas(n.List().Second(), tmp2)
+ r := ir.Nod(ir.OAS, n.List().Second(), conv(tmp2, n.List().Second().Type()))
r = typecheck(r, ctxStmt)
o.mapAssign(r)
n.List().SetSecond(tmp2)
diff --git a/src/cmd/compile/internal/gc/pgen.go b/src/cmd/compile/internal/gc/pgen.go
index 221b733a07..5b04e10657 100644
--- a/src/cmd/compile/internal/gc/pgen.go
+++ b/src/cmd/compile/internal/gc/pgen.go
@@ -24,14 +24,14 @@ import (
// "Portable" code generation.
var (
- compilequeue []ir.Node // functions waiting to be compiled
+ compilequeue []*ir.Func // functions waiting to be compiled
)
-func emitptrargsmap(fn ir.Node) {
- if ir.FuncName(fn) == "_" || fn.Func().Nname.Sym().Linkname != "" {
+func emitptrargsmap(fn *ir.Func) {
+ if ir.FuncName(fn) == "_" || fn.Sym().Linkname != "" {
return
}
- lsym := base.Ctxt.Lookup(fn.Func().LSym.Name + ".args_stackmap")
+ lsym := base.Ctxt.Lookup(fn.LSym.Name + ".args_stackmap")
nptr := int(fn.Type().ArgWidth() / int64(Widthptr))
bv := bvalloc(int32(nptr) * 2)
@@ -68,7 +68,7 @@ func emitptrargsmap(fn ir.Node) {
// really means, in memory, things with pointers needing zeroing at
// the top of the stack and increasing in size.
// Non-autos sort on offset.
-func cmpstackvarlt(a, b ir.Node) bool {
+func cmpstackvarlt(a, b *ir.Name) bool {
if (a.Class() == ir.PAUTO) != (b.Class() == ir.PAUTO) {
return b.Class() == ir.PAUTO
}
@@ -77,8 +77,8 @@ func cmpstackvarlt(a, b ir.Node) bool {
return a.Offset() < b.Offset()
}
- if a.Name().Used() != b.Name().Used() {
- return a.Name().Used()
+ if a.Used() != b.Used() {
+ return a.Used()
}
ap := a.Type().HasPointers()
@@ -87,8 +87,8 @@ func cmpstackvarlt(a, b ir.Node) bool {
return ap
}
- ap = a.Name().Needzero()
- bp = b.Name().Needzero()
+ ap = a.Needzero()
+ bp = b.Needzero()
if ap != bp {
return ap
}
@@ -101,7 +101,7 @@ func cmpstackvarlt(a, b ir.Node) bool {
}
// byStackvar implements sort.Interface for []*Node using cmpstackvarlt.
-type byStackVar []ir.Node
+type byStackVar []*ir.Name
func (s byStackVar) Len() int { return len(s) }
func (s byStackVar) Less(i, j int) bool { return cmpstackvarlt(s[i], s[j]) }
@@ -110,12 +110,12 @@ func (s byStackVar) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s *ssafn) AllocFrame(f *ssa.Func) {
s.stksize = 0
s.stkptrsize = 0
- fn := s.curfn.Func()
+ fn := s.curfn
// Mark the PAUTO's unused.
for _, ln := range fn.Dcl {
if ln.Class() == ir.PAUTO {
- ln.Name().SetUsed(false)
+ ln.SetUsed(false)
}
}
@@ -128,7 +128,7 @@ func (s *ssafn) AllocFrame(f *ssa.Func) {
scratchUsed := false
for _, b := range f.Blocks {
for _, v := range b.Values {
- if n, ok := v.Aux.(ir.Node); ok {
+ if n, ok := v.Aux.(*ir.Name); ok {
switch n.Class() {
case ir.PPARAM, ir.PPARAMOUT:
// Don't modify nodfp; it is a global.
@@ -158,7 +158,7 @@ func (s *ssafn) AllocFrame(f *ssa.Func) {
if n.Op() != ir.ONAME || n.Class() != ir.PAUTO {
continue
}
- if !n.Name().Used() {
+ if !n.Used() {
fn.Dcl = fn.Dcl[:i]
break
}
@@ -193,9 +193,9 @@ func (s *ssafn) AllocFrame(f *ssa.Func) {
s.stkptrsize = Rnd(s.stkptrsize, int64(Widthreg))
}
-func funccompile(fn ir.Node) {
+func funccompile(fn *ir.Func) {
if Curfn != nil {
- base.Fatalf("funccompile %v inside %v", fn.Func().Nname.Sym(), Curfn.Func().Nname.Sym())
+ base.Fatalf("funccompile %v inside %v", fn.Sym(), Curfn.Sym())
}
if fn.Type() == nil {
@@ -210,21 +210,19 @@ func funccompile(fn ir.Node) {
if fn.Body().Len() == 0 {
// Initialize ABI wrappers if necessary.
- initLSym(fn.Func(), false)
+ initLSym(fn, false)
emitptrargsmap(fn)
return
}
dclcontext = ir.PAUTO
Curfn = fn
-
compile(fn)
-
Curfn = nil
dclcontext = ir.PEXTERN
}
-func compile(fn ir.Node) {
+func compile(fn *ir.Func) {
errorsBefore := base.Errors()
order(fn)
if base.Errors() > errorsBefore {
@@ -234,7 +232,7 @@ func compile(fn ir.Node) {
// Set up the function's LSym early to avoid data races with the assemblers.
// Do this before walk, as walk needs the LSym to set attributes/relocations
// (e.g. in markTypeUsedInInterface).
- initLSym(fn.Func(), true)
+ initLSym(fn, true)
walk(fn)
if base.Errors() > errorsBefore {
@@ -259,15 +257,15 @@ func compile(fn ir.Node) {
// be types of stack objects. We need to do this here
// because symbols must be allocated before the parallel
// phase of the compiler.
- for _, n := range fn.Func().Dcl {
+ for _, n := range fn.Dcl {
switch n.Class() {
case ir.PPARAM, ir.PPARAMOUT, ir.PAUTO:
- if livenessShouldTrack(n) && n.Name().Addrtaken() {
+ if livenessShouldTrack(n) && n.Addrtaken() {
dtypesym(n.Type())
// Also make sure we allocate a linker symbol
// for the stack object data, for the same reason.
- if fn.Func().LSym.Func().StackObjects == nil {
- fn.Func().LSym.Func().StackObjects = base.Ctxt.Lookup(fn.Func().LSym.Name + ".stkobj")
+ if fn.LSym.Func().StackObjects == nil {
+ fn.LSym.Func().StackObjects = base.Ctxt.Lookup(fn.LSym.Name + ".stkobj")
}
}
}
@@ -284,7 +282,7 @@ func compile(fn ir.Node) {
// If functions are not compiled immediately,
// they are enqueued in compilequeue,
// which is drained by compileFunctions.
-func compilenow(fn ir.Node) bool {
+func compilenow(fn *ir.Func) bool {
// Issue 38068: if this function is a method AND an inline
// candidate AND was not inlined (yet), put it onto the compile
// queue instead of compiling it immediately. This is in case we
@@ -299,8 +297,8 @@ func compilenow(fn ir.Node) bool {
// isInlinableButNotInlined returns true if 'fn' was marked as an
// inline candidate but then never inlined (presumably because we
// found no call sites).
-func isInlinableButNotInlined(fn ir.Node) bool {
- if fn.Func().Nname.Func().Inl == nil {
+func isInlinableButNotInlined(fn *ir.Func) bool {
+ if fn.Inl == nil {
return false
}
if fn.Sym() == nil {
@@ -315,7 +313,7 @@ const maxStackSize = 1 << 30
// uses it to generate a plist,
// and flushes that plist to machine code.
// worker indicates which of the backend workers is doing the processing.
-func compileSSA(fn ir.Node, worker int) {
+func compileSSA(fn *ir.Func, worker int) {
f := buildssa(fn, worker)
// Note: check arg size to fix issue 25507.
if f.Frontend().(*ssafn).stksize >= maxStackSize || fn.Type().ArgWidth() >= maxStackSize {
@@ -343,7 +341,7 @@ func compileSSA(fn ir.Node, worker int) {
pp.Flush() // assemble, fill in boilerplate, etc.
// fieldtrack must be called after pp.Flush. See issue 20014.
- fieldtrack(pp.Text.From.Sym, fn.Func().FieldTrack)
+ fieldtrack(pp.Text.From.Sym, fn.FieldTrack)
}
func init() {
@@ -360,7 +358,7 @@ func compileFunctions() {
sizeCalculationDisabled = true // not safe to calculate sizes concurrently
if race.Enabled {
// Randomize compilation order to try to shake out races.
- tmp := make([]ir.Node, len(compilequeue))
+ tmp := make([]*ir.Func, len(compilequeue))
perm := rand.Perm(len(compilequeue))
for i, v := range perm {
tmp[v] = compilequeue[i]
@@ -376,7 +374,7 @@ func compileFunctions() {
}
var wg sync.WaitGroup
base.Ctxt.InParallel = true
- c := make(chan ir.Node, base.Flag.LowerC)
+ c := make(chan *ir.Func, base.Flag.LowerC)
for i := 0; i < base.Flag.LowerC; i++ {
wg.Add(1)
go func(worker int) {
@@ -398,9 +396,10 @@ func compileFunctions() {
}
func debuginfo(fnsym *obj.LSym, infosym *obj.LSym, curfn interface{}) ([]dwarf.Scope, dwarf.InlCalls) {
- fn := curfn.(ir.Node)
- if fn.Func().Nname != nil {
- if expect := fn.Func().Nname.Sym().Linksym(); fnsym != expect {
+ fn := curfn.(*ir.Func)
+
+ if fn.Nname != nil {
+ if expect := fn.Sym().Linksym(); fnsym != expect {
base.Fatalf("unexpected fnsym: %v != %v", fnsym, expect)
}
}
@@ -430,18 +429,25 @@ func debuginfo(fnsym *obj.LSym, infosym *obj.LSym, curfn interface{}) ([]dwarf.S
//
// These two adjustments keep toolstash -cmp working for now.
// Deciding the right answer is, as they say, future work.
- isODCLFUNC := fn.Op() == ir.ODCLFUNC
+ //
+ // We can tell the difference between the old ODCLFUNC and ONAME
+ // cases by looking at the infosym.Name. If it's empty, DebugInfo is
+ // being called from (*obj.Link).populateDWARF, which used to use
+ // the ODCLFUNC. If it's non-empty (the name will end in $abstract),
+ // DebugInfo is being called from (*obj.Link).DwarfAbstractFunc,
+ // which used to use the ONAME form.
+ isODCLFUNC := infosym.Name == ""
- var apdecls []ir.Node
+ var apdecls []*ir.Name
// Populate decls for fn.
if isODCLFUNC {
- for _, n := range fn.Func().Dcl {
+ for _, n := range fn.Dcl {
if n.Op() != ir.ONAME { // might be OTYPE or OLITERAL
continue
}
switch n.Class() {
case ir.PAUTO:
- if !n.Name().Used() {
+ if !n.Used() {
// Text == nil -> generating abstract function
if fnsym.Func().Text != nil {
base.Fatalf("debuginfo unused node (AllocFrame should truncate fn.Func.Dcl)")
@@ -457,7 +463,7 @@ func debuginfo(fnsym *obj.LSym, infosym *obj.LSym, curfn interface{}) ([]dwarf.S
}
}
- decls, dwarfVars := createDwarfVars(fnsym, isODCLFUNC, fn.Func(), apdecls)
+ decls, dwarfVars := createDwarfVars(fnsym, isODCLFUNC, fn, apdecls)
// For each type referenced by the functions auto vars but not
// already referenced by a dwarf var, attach an R_USETYPE relocation to
@@ -478,7 +484,7 @@ func debuginfo(fnsym *obj.LSym, infosym *obj.LSym, curfn interface{}) ([]dwarf.S
var varScopes []ir.ScopeID
for _, decl := range decls {
pos := declPos(decl)
- varScopes = append(varScopes, findScope(fn.Func().Marks, pos))
+ varScopes = append(varScopes, findScope(fn.Marks, pos))
}
scopes := assembleScopes(fnsym, fn, dwarfVars, varScopes)
@@ -489,7 +495,7 @@ func debuginfo(fnsym *obj.LSym, infosym *obj.LSym, curfn interface{}) ([]dwarf.S
return scopes, inlcalls
}
-func declPos(decl ir.Node) src.XPos {
+func declPos(decl *ir.Name) src.XPos {
if decl.Name().Defn != nil && (decl.Name().Captured() || decl.Name().Byval()) {
// It's not clear which position is correct for captured variables here:
// * decl.Pos is the wrong position for captured variables, in the inner
@@ -512,10 +518,10 @@ func declPos(decl ir.Node) src.XPos {
// createSimpleVars creates a DWARF entry for every variable declared in the
// function, claiming that they are permanently on the stack.
-func createSimpleVars(fnsym *obj.LSym, apDecls []ir.Node) ([]ir.Node, []*dwarf.Var, map[ir.Node]bool) {
+func createSimpleVars(fnsym *obj.LSym, apDecls []*ir.Name) ([]*ir.Name, []*dwarf.Var, map[*ir.Name]bool) {
var vars []*dwarf.Var
- var decls []ir.Node
- selected := make(map[ir.Node]bool)
+ var decls []*ir.Name
+ selected := make(map[*ir.Name]bool)
for _, n := range apDecls {
if ir.IsAutoTmp(n) {
continue
@@ -528,7 +534,7 @@ func createSimpleVars(fnsym *obj.LSym, apDecls []ir.Node) ([]ir.Node, []*dwarf.V
return decls, vars, selected
}
-func createSimpleVar(fnsym *obj.LSym, n ir.Node) *dwarf.Var {
+func createSimpleVar(fnsym *obj.LSym, n *ir.Name) *dwarf.Var {
var abbrev int
offs := n.Offset()
@@ -579,13 +585,13 @@ func createSimpleVar(fnsym *obj.LSym, n ir.Node) *dwarf.Var {
// createComplexVars creates recomposed DWARF vars with location lists,
// suitable for describing optimized code.
-func createComplexVars(fnsym *obj.LSym, fn *ir.Func) ([]ir.Node, []*dwarf.Var, map[ir.Node]bool) {
+func createComplexVars(fnsym *obj.LSym, fn *ir.Func) ([]*ir.Name, []*dwarf.Var, map[*ir.Name]bool) {
debugInfo := fn.DebugInfo.(*ssa.FuncDebug)
// Produce a DWARF variable entry for each user variable.
- var decls []ir.Node
+ var decls []*ir.Name
var vars []*dwarf.Var
- ssaVars := make(map[ir.Node]bool)
+ ssaVars := make(map[*ir.Name]bool)
for varID, dvar := range debugInfo.Vars {
n := dvar
@@ -605,11 +611,11 @@ func createComplexVars(fnsym *obj.LSym, fn *ir.Func) ([]ir.Node, []*dwarf.Var, m
// createDwarfVars process fn, returning a list of DWARF variables and the
// Nodes they represent.
-func createDwarfVars(fnsym *obj.LSym, complexOK bool, fn *ir.Func, apDecls []ir.Node) ([]ir.Node, []*dwarf.Var) {
+func createDwarfVars(fnsym *obj.LSym, complexOK bool, fn *ir.Func, apDecls []*ir.Name) ([]*ir.Name, []*dwarf.Var) {
// Collect a raw list of DWARF vars.
var vars []*dwarf.Var
- var decls []ir.Node
- var selected map[ir.Node]bool
+ var decls []*ir.Name
+ var selected map[*ir.Name]bool
if base.Ctxt.Flag_locationlists && base.Ctxt.Flag_optimize && fn.DebugInfo != nil && complexOK {
decls, vars, selected = createComplexVars(fnsym, fn)
} else {
@@ -667,7 +673,7 @@ func createDwarfVars(fnsym *obj.LSym, complexOK bool, fn *ir.Func, apDecls []ir.
// misleading location for the param (we want pointer-to-heap
// and not stack).
// TODO(thanm): generate a better location expression
- stackcopy := n.Name().Param.Stackcopy
+ stackcopy := n.Name().Stackcopy
if stackcopy != nil && (stackcopy.Class() == ir.PPARAM || stackcopy.Class() == ir.PPARAMOUT) {
abbrev = dwarf.DW_ABRV_PARAM_LOCLIST
isReturnValue = (stackcopy.Class() == ir.PPARAMOUT)
@@ -708,10 +714,10 @@ func createDwarfVars(fnsym *obj.LSym, complexOK bool, fn *ir.Func, apDecls []ir.
// function that is not local to the package being compiled, then the
// names of the variables may have been "versioned" to avoid conflicts
// with local vars; disregard this versioning when sorting.
-func preInliningDcls(fnsym *obj.LSym) []ir.Node {
- fn := base.Ctxt.DwFixups.GetPrecursorFunc(fnsym).(ir.Node)
- var rdcl []ir.Node
- for _, n := range fn.Func().Inl.Dcl {
+func preInliningDcls(fnsym *obj.LSym) []*ir.Name {
+ fn := base.Ctxt.DwFixups.GetPrecursorFunc(fnsym).(*ir.Func)
+ var rdcl []*ir.Name
+ for _, n := range fn.Inl.Dcl {
c := n.Sym().Name[0]
// Avoid reporting "_" parameters, since if there are more than
// one, it can result in a collision later on, as in #23179.
diff --git a/src/cmd/compile/internal/gc/pgen_test.go b/src/cmd/compile/internal/gc/pgen_test.go
index 1984f9aa08..ad8b87c6f5 100644
--- a/src/cmd/compile/internal/gc/pgen_test.go
+++ b/src/cmd/compile/internal/gc/pgen_test.go
@@ -7,38 +7,37 @@ package gc
import (
"cmd/compile/internal/ir"
"cmd/compile/internal/types"
+ "cmd/internal/src"
"reflect"
"sort"
"testing"
)
func typeWithoutPointers() *types.Type {
- t := types.New(types.TSTRUCT)
- f := &types.Field{Type: types.New(types.TINT)}
- t.SetFields([]*types.Field{f})
- return t
+ return types.NewStruct(types.NoPkg, []*types.Field{
+ types.NewField(src.NoXPos, nil, types.New(types.TINT)),
+ })
}
func typeWithPointers() *types.Type {
- t := types.New(types.TSTRUCT)
- f := &types.Field{Type: types.NewPtr(types.New(types.TINT))}
- t.SetFields([]*types.Field{f})
- return t
+ return types.NewStruct(types.NoPkg, []*types.Field{
+ types.NewField(src.NoXPos, nil, types.NewPtr(types.New(types.TINT))),
+ })
}
-func markUsed(n ir.Node) ir.Node {
- n.Name().SetUsed(true)
+func markUsed(n *ir.Name) *ir.Name {
+ n.SetUsed(true)
return n
}
-func markNeedZero(n ir.Node) ir.Node {
- n.Name().SetNeedzero(true)
+func markNeedZero(n *ir.Name) *ir.Name {
+ n.SetNeedzero(true)
return n
}
// Test all code paths for cmpstackvarlt.
func TestCmpstackvar(t *testing.T) {
- nod := func(xoffset int64, t *types.Type, s *types.Sym, cl ir.Class) ir.Node {
+ nod := func(xoffset int64, t *types.Type, s *types.Sym, cl ir.Class) *ir.Name {
if s == nil {
s = &types.Sym{Name: "."}
}
@@ -49,7 +48,7 @@ func TestCmpstackvar(t *testing.T) {
return n
}
testdata := []struct {
- a, b ir.Node
+ a, b *ir.Name
lt bool
}{
{
@@ -146,24 +145,24 @@ func TestCmpstackvar(t *testing.T) {
for _, d := range testdata {
got := cmpstackvarlt(d.a, d.b)
if got != d.lt {
- t.Errorf("want %#v < %#v", d.a, d.b)
+ t.Errorf("want %v < %v", d.a, d.b)
}
// If we expect a < b to be true, check that b < a is false.
if d.lt && cmpstackvarlt(d.b, d.a) {
- t.Errorf("unexpected %#v < %#v", d.b, d.a)
+ t.Errorf("unexpected %v < %v", d.b, d.a)
}
}
}
func TestStackvarSort(t *testing.T) {
- nod := func(xoffset int64, t *types.Type, s *types.Sym, cl ir.Class) ir.Node {
+ nod := func(xoffset int64, t *types.Type, s *types.Sym, cl ir.Class) *ir.Name {
n := NewName(s)
n.SetType(t)
n.SetOffset(xoffset)
n.SetClass(cl)
return n
}
- inp := []ir.Node{
+ inp := []*ir.Name{
nod(0, &types.Type{}, &types.Sym{}, ir.PFUNC),
nod(0, &types.Type{}, &types.Sym{}, ir.PAUTO),
nod(0, &types.Type{}, &types.Sym{}, ir.PFUNC),
@@ -178,7 +177,7 @@ func TestStackvarSort(t *testing.T) {
nod(0, &types.Type{}, &types.Sym{Name: "abc"}, ir.PAUTO),
nod(0, &types.Type{}, &types.Sym{Name: "xyz"}, ir.PAUTO),
}
- want := []ir.Node{
+ want := []*ir.Name{
nod(0, &types.Type{}, &types.Sym{}, ir.PFUNC),
nod(0, &types.Type{}, &types.Sym{}, ir.PFUNC),
nod(10, &types.Type{}, &types.Sym{}, ir.PFUNC),
diff --git a/src/cmd/compile/internal/gc/phi.go b/src/cmd/compile/internal/gc/phi.go
index 677bfc92df..32c330b584 100644
--- a/src/cmd/compile/internal/gc/phi.go
+++ b/src/cmd/compile/internal/gc/phi.go
@@ -23,6 +23,14 @@ const smallBlocks = 500
const debugPhi = false
+// FwdRefAux wraps an arbitrary ir.Node as an ssa.Aux for use with OpFwdref.
+type FwdRefAux struct {
+ _ [0]func() // ensure ir.Node isn't compared for equality
+ N ir.Node
+}
+
+func (FwdRefAux) CanBeAnSSAAux() {}
+
// insertPhis finds all the places in the function where a phi is
// necessary and inserts them.
// Uses FwdRef ops to find all uses of variables, and s.defvars to find
@@ -79,7 +87,7 @@ func (s *phiState) insertPhis() {
if v.Op != ssa.OpFwdRef {
continue
}
- var_ := v.Aux.(ir.Node)
+ var_ := v.Aux.(FwdRefAux).N
// Optimization: look back 1 block for the definition.
if len(b.Preds) == 1 {
@@ -180,6 +188,11 @@ levels:
if v.Op == ssa.OpPhi {
v.AuxInt = 0
}
+ // Any remaining FwdRefs are dead code.
+ if v.Op == ssa.OpFwdRef {
+ v.Op = ssa.OpUnknown
+ v.Aux = nil
+ }
}
}
}
@@ -319,7 +332,7 @@ func (s *phiState) resolveFwdRefs() {
if v.Op != ssa.OpFwdRef {
continue
}
- n := s.varnum[v.Aux.(ir.Node)]
+ n := s.varnum[v.Aux.(FwdRefAux).N]
v.Op = ssa.OpCopy
v.Aux = nil
v.AddArg(values[n])
@@ -450,7 +463,7 @@ func (s *simplePhiState) insertPhis() {
continue
}
s.fwdrefs = append(s.fwdrefs, v)
- var_ := v.Aux.(ir.Node)
+ var_ := v.Aux.(FwdRefAux).N
if _, ok := s.defvars[b.ID][var_]; !ok {
s.defvars[b.ID][var_] = v // treat FwdDefs as definitions.
}
@@ -464,7 +477,7 @@ loop:
v := s.fwdrefs[len(s.fwdrefs)-1]
s.fwdrefs = s.fwdrefs[:len(s.fwdrefs)-1]
b := v.Block
- var_ := v.Aux.(ir.Node)
+ var_ := v.Aux.(FwdRefAux).N
if b == s.f.Entry {
// No variable should be live at entry.
s.s.Fatalf("Value live at entry. It shouldn't be. func %s, node %v, value %v", s.f.Name, var_, v)
@@ -531,7 +544,7 @@ func (s *simplePhiState) lookupVarOutgoing(b *ssa.Block, t *types.Type, var_ ir.
}
}
// Generate a FwdRef for the variable and return that.
- v := b.NewValue0A(line, ssa.OpFwdRef, t, var_)
+ v := b.NewValue0A(line, ssa.OpFwdRef, t, FwdRefAux{N: var_})
s.defvars[b.ID][var_] = v
s.s.addNamedValue(var_, v)
s.fwdrefs = append(s.fwdrefs, v)
diff --git a/src/cmd/compile/internal/gc/plive.go b/src/cmd/compile/internal/gc/plive.go
index bd7696d859..9952bfcf36 100644
--- a/src/cmd/compile/internal/gc/plive.go
+++ b/src/cmd/compile/internal/gc/plive.go
@@ -101,10 +101,10 @@ type BlockEffects struct {
// A collection of global state used by liveness analysis.
type Liveness struct {
- fn ir.Node
+ fn *ir.Func
f *ssa.Func
- vars []ir.Node
- idx map[ir.Node]int32
+ vars []*ir.Name
+ idx map[*ir.Name]int32
stkptrsize int64
be []BlockEffects
@@ -212,14 +212,14 @@ func livenessShouldTrack(n ir.Node) bool {
// getvariables returns the list of on-stack variables that we need to track
// and a map for looking up indices by *Node.
-func getvariables(fn ir.Node) ([]ir.Node, map[ir.Node]int32) {
- var vars []ir.Node
- for _, n := range fn.Func().Dcl {
+func getvariables(fn *ir.Func) ([]*ir.Name, map[*ir.Name]int32) {
+ var vars []*ir.Name
+ for _, n := range fn.Dcl {
if livenessShouldTrack(n) {
vars = append(vars, n)
}
}
- idx := make(map[ir.Node]int32, len(vars))
+ idx := make(map[*ir.Name]int32, len(vars))
for i, n := range vars {
idx[n] = int32(i)
}
@@ -276,13 +276,14 @@ func (lv *Liveness) valueEffects(v *ssa.Value) (int32, liveEffect) {
return -1, 0
}
+ nn := n.(*ir.Name)
// AllocFrame has dropped unused variables from
// lv.fn.Func.Dcl, but they might still be referenced by
// OpVarFoo pseudo-ops. Ignore them to prevent "lost track of
// variable" ICEs (issue 19632).
switch v.Op {
case ssa.OpVarDef, ssa.OpVarKill, ssa.OpVarLive, ssa.OpKeepAlive:
- if !n.Name().Used() {
+ if !nn.Name().Used() {
return -1, 0
}
}
@@ -305,7 +306,7 @@ func (lv *Liveness) valueEffects(v *ssa.Value) (int32, liveEffect) {
return -1, 0
}
- if pos, ok := lv.idx[n]; ok {
+ if pos, ok := lv.idx[nn]; ok {
return pos, effect
}
return -1, 0
@@ -323,9 +324,9 @@ func affectedNode(v *ssa.Value) (ir.Node, ssa.SymEffect) {
return n, ssa.SymWrite
case ssa.OpVarLive:
- return v.Aux.(ir.Node), ssa.SymRead
+ return v.Aux.(*ir.Name), ssa.SymRead
case ssa.OpVarDef, ssa.OpVarKill:
- return v.Aux.(ir.Node), ssa.SymWrite
+ return v.Aux.(*ir.Name), ssa.SymWrite
case ssa.OpKeepAlive:
n, _ := AutoVar(v.Args[0])
return n, ssa.SymRead
@@ -340,7 +341,7 @@ func affectedNode(v *ssa.Value) (ir.Node, ssa.SymEffect) {
case nil, *obj.LSym:
// ok, but no node
return nil, e
- case ir.Node:
+ case *ir.Name:
return a, e
default:
base.Fatalf("weird aux: %s", v.LongString())
@@ -356,7 +357,7 @@ type livenessFuncCache struct {
// Constructs a new liveness structure used to hold the global state of the
// liveness computation. The cfg argument is a slice of *BasicBlocks and the
// vars argument is a slice of *Nodes.
-func newliveness(fn ir.Node, f *ssa.Func, vars []ir.Node, idx map[ir.Node]int32, stkptrsize int64) *Liveness {
+func newliveness(fn *ir.Func, f *ssa.Func, vars []*ir.Name, idx map[*ir.Name]int32, stkptrsize int64) *Liveness {
lv := &Liveness{
fn: fn,
f: f,
@@ -416,7 +417,7 @@ func onebitwalktype1(t *types.Type, off int64, bv bvec) {
return
}
- switch t.Etype {
+ switch t.Kind() {
case types.TPTR, types.TUNSAFEPTR, types.TFUNC, types.TCHAN, types.TMAP:
if off&int64(Widthptr-1) != 0 {
base.Fatalf("onebitwalktype1: invalid alignment, %v", t)
@@ -482,7 +483,7 @@ func onebitwalktype1(t *types.Type, off int64, bv bvec) {
// Generates live pointer value maps for arguments and local variables. The
// this argument and the in arguments are always assumed live. The vars
// argument is a slice of *Nodes.
-func (lv *Liveness) pointerMap(liveout bvec, vars []ir.Node, args, locals bvec) {
+func (lv *Liveness) pointerMap(liveout bvec, vars []*ir.Name, args, locals bvec) {
for i := int32(0); ; i++ {
i = liveout.Next(i)
if i < 0 {
@@ -788,14 +789,14 @@ func (lv *Liveness) epilogue() {
// pointers to copy values back to the stack).
// TODO: if the output parameter is heap-allocated, then we
// don't need to keep the stack copy live?
- if lv.fn.Func().HasDefer() {
+ if lv.fn.HasDefer() {
for i, n := range lv.vars {
if n.Class() == ir.PPARAMOUT {
if n.Name().IsOutputParamHeapAddr() {
// Just to be paranoid. Heap addresses are PAUTOs.
base.Fatalf("variable %v both output param and heap output param", n)
}
- if n.Name().Param.Heapaddr != nil {
+ if n.Name().Heapaddr != nil {
// If this variable moved to the heap, then
// its stack copy is not live.
continue
@@ -891,7 +892,7 @@ func (lv *Liveness) epilogue() {
if n.Class() == ir.PPARAM {
continue // ok
}
- base.Fatalf("bad live variable at entry of %v: %L", lv.fn.Func().Nname, n)
+ base.Fatalf("bad live variable at entry of %v: %L", lv.fn.Nname, n)
}
// Record live variables.
@@ -904,7 +905,7 @@ func (lv *Liveness) epilogue() {
}
// If we have an open-coded deferreturn call, make a liveness map for it.
- if lv.fn.Func().OpenCodedDeferDisallowed() {
+ if lv.fn.OpenCodedDeferDisallowed() {
lv.livenessMap.deferreturn = LivenessDontCare
} else {
lv.livenessMap.deferreturn = LivenessIndex{
@@ -922,7 +923,7 @@ func (lv *Liveness) epilogue() {
// input parameters.
for j, n := range lv.vars {
if n.Class() != ir.PPARAM && lv.stackMaps[0].Get(int32(j)) {
- lv.f.Fatalf("%v %L recorded as live on entry", lv.fn.Func().Nname, n)
+ lv.f.Fatalf("%v %L recorded as live on entry", lv.fn.Nname, n)
}
}
}
@@ -980,7 +981,7 @@ func (lv *Liveness) showlive(v *ssa.Value, live bvec) {
return
}
- pos := lv.fn.Func().Nname.Pos()
+ pos := lv.fn.Nname.Pos()
if v != nil {
pos = v.Pos
}
@@ -1090,7 +1091,7 @@ func (lv *Liveness) printDebug() {
if b == lv.f.Entry {
live := lv.stackMaps[0]
- fmt.Printf("(%s) function entry\n", base.FmtPos(lv.fn.Func().Nname.Pos()))
+ fmt.Printf("(%s) function entry\n", base.FmtPos(lv.fn.Nname.Pos()))
fmt.Printf("\tlive=")
printed = false
for j, n := range lv.vars {
@@ -1266,7 +1267,7 @@ func liveness(e *ssafn, f *ssa.Func, pp *Progs) LivenessMap {
}
// Emit the live pointer map data structures
- ls := e.curfn.Func().LSym
+ ls := e.curfn.LSym
fninfo := ls.Func()
fninfo.GCArgs, fninfo.GCLocals = lv.emit()
@@ -1300,7 +1301,7 @@ func liveness(e *ssafn, f *ssa.Func, pp *Progs) LivenessMap {
// to fully initialize t.
func isfat(t *types.Type) bool {
if t != nil {
- switch t.Etype {
+ switch t.Kind() {
case types.TSLICE, types.TSTRING,
types.TINTER: // maybe remove later
return true
diff --git a/src/cmd/compile/internal/gc/racewalk.go b/src/cmd/compile/internal/gc/racewalk.go
index c41d923f78..6b5d53e806 100644
--- a/src/cmd/compile/internal/gc/racewalk.go
+++ b/src/cmd/compile/internal/gc/racewalk.go
@@ -60,13 +60,13 @@ func ispkgin(pkgs []string) bool {
return false
}
-func instrument(fn ir.Node) {
- if fn.Func().Pragma&ir.Norace != 0 {
+func instrument(fn *ir.Func) {
+ if fn.Pragma&ir.Norace != 0 {
return
}
if !base.Flag.Race || !ispkgin(norace_inst_pkgs) {
- fn.Func().SetInstrumentBody(true)
+ fn.SetInstrumentBody(true)
}
if base.Flag.Race {
@@ -74,8 +74,8 @@ func instrument(fn ir.Node) {
base.Pos = src.NoXPos
if thearch.LinkArch.Arch.Family != sys.AMD64 {
- fn.Func().Enter.Prepend(mkcall("racefuncenterfp", nil, nil))
- fn.Func().Exit.Append(mkcall("racefuncexit", nil, nil))
+ fn.Enter.Prepend(mkcall("racefuncenterfp", nil, nil))
+ fn.Exit.Append(mkcall("racefuncexit", nil, nil))
} else {
// nodpc is the PC of the caller as extracted by
@@ -83,12 +83,12 @@ func instrument(fn ir.Node) {
// This only works for amd64. This will not
// work on arm or others that might support
// race in the future.
- nodpc := ir.Copy(nodfp)
+ nodpc := ir.Copy(nodfp).(*ir.Name)
nodpc.SetType(types.Types[types.TUINTPTR])
nodpc.SetOffset(int64(-Widthptr))
- fn.Func().Dcl = append(fn.Func().Dcl, nodpc)
- fn.Func().Enter.Prepend(mkcall("racefuncenter", nil, nil, nodpc))
- fn.Func().Exit.Append(mkcall("racefuncexit", nil, nil))
+ fn.Dcl = append(fn.Dcl, nodpc)
+ fn.Enter.Prepend(mkcall("racefuncenter", nil, nil, nodpc))
+ fn.Exit.Append(mkcall("racefuncexit", nil, nil))
}
base.Pos = lno
}
diff --git a/src/cmd/compile/internal/gc/range.go b/src/cmd/compile/internal/gc/range.go
index 0ff00cca44..8025119c5e 100644
--- a/src/cmd/compile/internal/gc/range.go
+++ b/src/cmd/compile/internal/gc/range.go
@@ -49,7 +49,7 @@ func typecheckrangeExpr(n ir.Node) {
// delicate little dance. see typecheckas2
ls := n.List().Slice()
for i1, n1 := range ls {
- if n1.Name() == nil || n1.Name().Defn != n {
+ if !ir.DeclaredBy(n1, n) {
ls[i1] = typecheck(ls[i1], ctxExpr|ctxAssign)
}
}
@@ -61,7 +61,7 @@ func typecheckrangeExpr(n ir.Node) {
var t1, t2 *types.Type
toomany := false
- switch t.Etype {
+ switch t.Kind() {
default:
base.ErrorfAt(n.Pos(), "cannot range over %L", n.Right())
return
@@ -88,7 +88,7 @@ func typecheckrangeExpr(n ir.Node) {
case types.TSTRING:
t1 = types.Types[types.TINT]
- t2 = types.Runetype
+ t2 = types.RuneType
}
if n.List().Len() > 2 || toomany {
@@ -115,7 +115,7 @@ func typecheckrangeExpr(n ir.Node) {
}
if v1 != nil {
- if v1.Name() != nil && v1.Name().Defn == n {
+ if ir.DeclaredBy(v1, n) {
v1.SetType(t1)
} else if v1.Type() != nil {
if op, why := assignop(t1, v1.Type()); op == ir.OXXX {
@@ -126,7 +126,7 @@ func typecheckrangeExpr(n ir.Node) {
}
if v2 != nil {
- if v2.Name() != nil && v2.Name().Defn == n {
+ if ir.DeclaredBy(v2, n) {
v2.SetType(t2)
} else if v2.Type() != nil {
if op, why := assignop(t2, v2.Type()); op == ir.OXXX {
@@ -157,15 +157,19 @@ func cheapComputableIndex(width int64) bool {
// simpler forms. The result must be assigned back to n.
// Node n may also be modified in place, and may also be
// the returned node.
-func walkrange(n ir.Node) ir.Node {
- if isMapClear(n) {
- m := n.Right()
+func walkrange(nrange ir.Node) ir.Node {
+ if isMapClear(nrange) {
+ m := nrange.Right()
lno := setlineno(m)
- n = mapClear(m)
+ n := mapClear(m)
base.Pos = lno
return n
}
+ nfor := ir.NodAt(nrange.Pos(), ir.OFOR, nil, nil)
+ nfor.SetInit(nrange.Init())
+ nfor.SetSym(nrange.Sym())
+
// variable name conventions:
// ohv1, hv1, hv2: hidden (old) val 1, 2
// ha, hit: hidden aggregate, iterator
@@ -173,20 +177,19 @@ func walkrange(n ir.Node) ir.Node {
// hb: hidden bool
// a, v1, v2: not hidden aggregate, val 1, 2
- t := n.Type()
+ t := nrange.Type()
- a := n.Right()
+ a := nrange.Right()
lno := setlineno(a)
- n.SetRight(nil)
var v1, v2 ir.Node
- l := n.List().Len()
+ l := nrange.List().Len()
if l > 0 {
- v1 = n.List().First()
+ v1 = nrange.List().First()
}
if l > 1 {
- v2 = n.List().Second()
+ v2 = nrange.List().Second()
}
if ir.IsBlank(v2) {
@@ -201,24 +204,18 @@ func walkrange(n ir.Node) ir.Node {
base.Fatalf("walkrange: v2 != nil while v1 == nil")
}
- // n.List has no meaning anymore, clear it
- // to avoid erroneous processing by racewalk.
- n.PtrList().Set(nil)
-
var ifGuard ir.Node
- translatedLoopOp := ir.OFOR
-
var body []ir.Node
var init []ir.Node
- switch t.Etype {
+ switch t.Kind() {
default:
base.Fatalf("walkrange")
case types.TARRAY, types.TSLICE:
- if arrayClear(n, v1, v2, a) {
+ if nn := arrayClear(nrange, v1, v2, a); nn != nil {
base.Pos = lno
- return n
+ return nn
}
// order.stmt arranged for a copy of the array/slice variable if needed.
@@ -230,8 +227,8 @@ func walkrange(n ir.Node) ir.Node {
init = append(init, ir.Nod(ir.OAS, hv1, nil))
init = append(init, ir.Nod(ir.OAS, hn, ir.Nod(ir.OLEN, ha, nil)))
- n.SetLeft(ir.Nod(ir.OLT, hv1, hn))
- n.SetRight(ir.Nod(ir.OAS, hv1, ir.Nod(ir.OADD, hv1, nodintconst(1))))
+ nfor.SetLeft(ir.Nod(ir.OLT, hv1, hn))
+ nfor.SetRight(ir.Nod(ir.OAS, hv1, ir.Nod(ir.OADD, hv1, nodintconst(1))))
// for range ha { body }
if v1 == nil {
@@ -245,7 +242,7 @@ func walkrange(n ir.Node) ir.Node {
}
// for v1, v2 := range ha { body }
- if cheapComputableIndex(n.Type().Elem().Width) {
+ if cheapComputableIndex(nrange.Type().Elem().Width) {
// v1, v2 = hv1, ha[hv1]
tmp := ir.Nod(ir.OINDEX, ha, hv1)
tmp.SetBounded(true)
@@ -272,9 +269,9 @@ func walkrange(n ir.Node) ir.Node {
// Enhance the prove pass to understand this.
ifGuard = ir.Nod(ir.OIF, nil, nil)
ifGuard.SetLeft(ir.Nod(ir.OLT, hv1, hn))
- translatedLoopOp = ir.OFORUNTIL
+ nfor.SetOp(ir.OFORUNTIL)
- hp := temp(types.NewPtr(n.Type().Elem()))
+ hp := temp(types.NewPtr(nrange.Type().Elem()))
tmp := ir.Nod(ir.OINDEX, ha, nodintconst(0))
tmp.SetBounded(true)
init = append(init, ir.Nod(ir.OAS, hp, ir.Nod(ir.OADDR, tmp, nil)))
@@ -293,16 +290,15 @@ func walkrange(n ir.Node) ir.Node {
// end of the allocation.
a = ir.Nod(ir.OAS, hp, addptr(hp, t.Elem().Width))
a = typecheck(a, ctxStmt)
- n.PtrList().Set1(a)
+ nfor.PtrList().Set1(a)
case types.TMAP:
// order.stmt allocated the iterator for us.
// we only use a once, so no copy needed.
ha := a
- hit := prealloc[n]
+ hit := prealloc[nrange]
th := hit.Type()
- n.SetLeft(nil)
keysym := th.Field(0).Sym // depends on layout of iterator struct. See reflect.go:hiter
elemsym := th.Field(1).Sym // ditto
@@ -310,11 +306,11 @@ func walkrange(n ir.Node) ir.Node {
fn = substArgTypes(fn, t.Key(), t.Elem(), th)
init = append(init, mkcall1(fn, nil, nil, typename(t), ha, ir.Nod(ir.OADDR, hit, nil)))
- n.SetLeft(ir.Nod(ir.ONE, nodSym(ir.ODOT, hit, keysym), nodnil()))
+ nfor.SetLeft(ir.Nod(ir.ONE, nodSym(ir.ODOT, hit, keysym), nodnil()))
fn = syslook("mapiternext")
fn = substArgTypes(fn, th)
- n.SetRight(mkcall1(fn, nil, nil, ir.Nod(ir.OADDR, hit, nil)))
+ nfor.SetRight(mkcall1(fn, nil, nil, ir.Nod(ir.OADDR, hit, nil)))
key := nodSym(ir.ODOT, hit, keysym)
key = ir.Nod(ir.ODEREF, key, nil)
@@ -335,8 +331,6 @@ func walkrange(n ir.Node) ir.Node {
// order.stmt arranged for a copy of the channel variable.
ha := a
- n.SetLeft(nil)
-
hv1 := temp(t.Elem())
hv1.SetTypecheck(1)
if t.Elem().HasPointers() {
@@ -344,12 +338,12 @@ func walkrange(n ir.Node) ir.Node {
}
hb := temp(types.Types[types.TBOOL])
- n.SetLeft(ir.Nod(ir.ONE, hb, nodbool(false)))
+ nfor.SetLeft(ir.Nod(ir.ONE, hb, nodbool(false)))
a := ir.Nod(ir.OAS2RECV, nil, nil)
a.SetTypecheck(1)
a.PtrList().Set2(hv1, hb)
- a.SetRight(ir.Nod(ir.ORECV, ha, nil))
- n.Left().PtrInit().Set1(a)
+ a.PtrRlist().Set1(ir.Nod(ir.ORECV, ha, nil))
+ nfor.Left().PtrInit().Set1(a)
if v1 == nil {
body = nil
} else {
@@ -381,13 +375,13 @@ func walkrange(n ir.Node) ir.Node {
hv1 := temp(types.Types[types.TINT])
hv1t := temp(types.Types[types.TINT])
- hv2 := temp(types.Runetype)
+ hv2 := temp(types.RuneType)
// hv1 := 0
init = append(init, ir.Nod(ir.OAS, hv1, nil))
// hv1 < len(ha)
- n.SetLeft(ir.Nod(ir.OLT, hv1, ir.Nod(ir.OLEN, ha, nil)))
+ nfor.SetLeft(ir.Nod(ir.OLT, hv1, ir.Nod(ir.OLEN, ha, nil)))
if v1 != nil {
// hv1t = hv1
@@ -397,7 +391,7 @@ func walkrange(n ir.Node) ir.Node {
// hv2 := rune(ha[hv1])
nind := ir.Nod(ir.OINDEX, ha, hv1)
nind.SetBounded(true)
- body = append(body, ir.Nod(ir.OAS, hv2, conv(nind, types.Runetype)))
+ body = append(body, ir.Nod(ir.OAS, hv2, conv(nind, types.RuneType)))
// if hv2 < utf8.RuneSelf
nif := ir.Nod(ir.OIF, nil, nil)
@@ -431,24 +425,25 @@ func walkrange(n ir.Node) ir.Node {
}
}
- n.SetOp(translatedLoopOp)
typecheckslice(init, ctxStmt)
if ifGuard != nil {
ifGuard.PtrInit().Append(init...)
ifGuard = typecheck(ifGuard, ctxStmt)
} else {
- n.PtrInit().Append(init...)
+ nfor.PtrInit().Append(init...)
}
- typecheckslice(n.Left().Init().Slice(), ctxStmt)
+ typecheckslice(nfor.Left().Init().Slice(), ctxStmt)
- n.SetLeft(typecheck(n.Left(), ctxExpr))
- n.SetLeft(defaultlit(n.Left(), nil))
- n.SetRight(typecheck(n.Right(), ctxStmt))
+ nfor.SetLeft(typecheck(nfor.Left(), ctxExpr))
+ nfor.SetLeft(defaultlit(nfor.Left(), nil))
+ nfor.SetRight(typecheck(nfor.Right(), ctxStmt))
typecheckslice(body, ctxStmt)
- n.PtrBody().Prepend(body...)
+ nfor.PtrBody().Append(body...)
+ nfor.PtrBody().Append(nrange.Body().Slice()...)
+ var n ir.Node = nfor
if ifGuard != nil {
ifGuard.PtrBody().Set1(n)
n = ifGuard
@@ -472,7 +467,7 @@ func isMapClear(n ir.Node) bool {
return false
}
- if n.Op() != ir.ORANGE || n.Type().Etype != types.TMAP || n.List().Len() != 1 {
+ if n.Op() != ir.ORANGE || n.Type().Kind() != types.TMAP || n.List().Len() != 1 {
return false
}
@@ -482,7 +477,7 @@ func isMapClear(n ir.Node) bool {
}
// Require k to be a new variable name.
- if k.Name() == nil || k.Name().Defn != n {
+ if !ir.DeclaredBy(k, n) {
return false
}
@@ -534,31 +529,31 @@ func mapClear(m ir.Node) ir.Node {
// in which the evaluation of a is side-effect-free.
//
// Parameters are as in walkrange: "for v1, v2 = range a".
-func arrayClear(n, v1, v2, a ir.Node) bool {
+func arrayClear(loop, v1, v2, a ir.Node) ir.Node {
if base.Flag.N != 0 || instrumenting {
- return false
+ return nil
}
if v1 == nil || v2 != nil {
- return false
+ return nil
}
- if n.Body().Len() != 1 || n.Body().First() == nil {
- return false
+ if loop.Body().Len() != 1 || loop.Body().First() == nil {
+ return nil
}
- stmt := n.Body().First() // only stmt in body
+ stmt := loop.Body().First() // only stmt in body
if stmt.Op() != ir.OAS || stmt.Left().Op() != ir.OINDEX {
- return false
+ return nil
}
if !samesafeexpr(stmt.Left().Left(), a) || !samesafeexpr(stmt.Left().Right(), v1) {
- return false
+ return nil
}
- elemsize := n.Type().Elem().Width
+ elemsize := loop.Type().Elem().Width
if elemsize <= 0 || !isZero(stmt.Right()) {
- return false
+ return nil
}
// Convert to
@@ -568,8 +563,7 @@ func arrayClear(n, v1, v2, a ir.Node) bool {
// memclr{NoHeap,Has}Pointers(hp, hn)
// i = len(a) - 1
// }
- n.SetOp(ir.OIF)
-
+ n := ir.Nod(ir.OIF, nil, nil)
n.PtrBody().Set(nil)
n.SetLeft(ir.Nod(ir.ONE, ir.Nod(ir.OLEN, a, nil), nodintconst(0)))
@@ -593,7 +587,7 @@ func arrayClear(n, v1, v2, a ir.Node) bool {
var fn ir.Node
if a.Type().Elem().HasPointers() {
// memclrHasPointers(hp, hn)
- Curfn.Func().SetWBPos(stmt.Pos())
+ Curfn.SetWBPos(stmt.Pos())
fn = mkcall("memclrHasPointers", nil, nil, hp, hn)
} else {
// memclrNoHeapPointers(hp, hn)
@@ -611,7 +605,7 @@ func arrayClear(n, v1, v2, a ir.Node) bool {
n.SetLeft(defaultlit(n.Left(), nil))
typecheckslice(n.Body().Slice(), ctxStmt)
n = walkstmt(n)
- return true
+ return n
}
// addptr returns (*T)(uintptr(p) + n).
diff --git a/src/cmd/compile/internal/gc/reflect.go b/src/cmd/compile/internal/gc/reflect.go
index dc9efc07fe..9b8f26a84b 100644
--- a/src/cmd/compile/internal/gc/reflect.go
+++ b/src/cmd/compile/internal/gc/reflect.go
@@ -68,7 +68,7 @@ func imethodSize() int { return 4 + 4 } // Sizeof(runtime.imeth
func commonSize() int { return 4*Widthptr + 8 + 8 } // Sizeof(runtime._type{})
func uncommonSize(t *types.Type) int { // Sizeof(runtime.uncommontype{})
- if t.Sym == nil && len(methods(t)) == 0 {
+ if t.Sym() == nil && len(methods(t)) == 0 {
return 0
}
return 4 + 2 + 2 + 4 + 4
@@ -85,7 +85,6 @@ func bmap(t *types.Type) *types.Type {
return t.MapType().Bucket
}
- bucket := types.New(types.TSTRUCT)
keytype := t.Key()
elemtype := t.Elem()
dowidth(keytype)
@@ -119,7 +118,7 @@ func bmap(t *types.Type) *types.Type {
// Arrange for the bucket to have no pointers by changing
// the type of the overflow field to uintptr in this case.
// See comment on hmap.overflow in runtime/map.go.
- otyp := types.NewPtr(bucket)
+ otyp := types.Types[types.TUNSAFEPTR]
if !elemtype.HasPointers() && !keytype.HasPointers() {
otyp = types.Types[types.TUINTPTR]
}
@@ -127,8 +126,8 @@ func bmap(t *types.Type) *types.Type {
field = append(field, overflow)
// link up fields
+ bucket := types.NewStruct(types.NoPkg, field[:])
bucket.SetNoalg(true)
- bucket.SetFields(field[:])
dowidth(bucket)
// Check invariants that map code depends on.
@@ -221,9 +220,8 @@ func hmap(t *types.Type) *types.Type {
makefield("extra", types.Types[types.TUNSAFEPTR]),
}
- hmap := types.New(types.TSTRUCT)
+ hmap := types.NewStruct(types.NoPkg, fields)
hmap.SetNoalg(true)
- hmap.SetFields(fields)
dowidth(hmap)
// The size of hmap should be 48 bytes on 64 bit
@@ -285,9 +283,8 @@ func hiter(t *types.Type) *types.Type {
}
// build iterator struct holding the above fields
- hiter := types.New(types.TSTRUCT)
+ hiter := types.NewStruct(types.NoPkg, fields)
hiter.SetNoalg(true)
- hiter.SetFields(fields)
dowidth(hiter)
if hiter.Width != int64(12*Widthptr) {
base.Fatalf("hash_iter size not correct %d %d", hiter.Width, 12*Widthptr)
@@ -304,7 +301,7 @@ func deferstruct(stksize int64) *types.Type {
// Unlike the global makefield function, this one needs to set Pkg
// because these types might be compared (in SSA CSE sorting).
// TODO: unify this makefield and the global one above.
- sym := &types.Sym{Name: name, Pkg: ir.LocalPkg}
+ sym := &types.Sym{Name: name, Pkg: types.LocalPkg}
return types.NewField(src.NoXPos, sym, typ)
}
argtype := types.NewArray(types.Types[types.TUINT8], stksize)
@@ -332,9 +329,8 @@ func deferstruct(stksize int64) *types.Type {
}
// build struct holding the above fields
- s := types.New(types.TSTRUCT)
+ s := types.NewStruct(types.NoPkg, fields)
s.SetNoalg(true)
- s.SetFields(fields)
s.Width = widstruct(s, s, 0, 1)
s.Align = uint8(Widthptr)
return s
@@ -347,7 +343,7 @@ func methodfunc(f *types.Type, receiver *types.Type) *types.Type {
if receiver != nil {
inLen++
}
- in := make([]ir.Node, 0, inLen)
+ in := make([]*ir.Field, 0, inLen)
if receiver != nil {
d := anonfield(receiver)
@@ -356,12 +352,12 @@ func methodfunc(f *types.Type, receiver *types.Type) *types.Type {
for _, t := range f.Params().Fields().Slice() {
d := anonfield(t.Type)
- d.SetIsDDD(t.IsDDD())
+ d.IsDDD = t.IsDDD()
in = append(in, d)
}
outLen := f.Results().Fields().Len()
- out := make([]ir.Node, 0, outLen)
+ out := make([]*ir.Field, 0, outLen)
for _, t := range f.Results().Fields().Slice() {
d := anonfield(t.Type)
out = append(out, d)
@@ -448,7 +444,7 @@ func methods(t *types.Type) []*Sig {
func imethods(t *types.Type) []*Sig {
var methods []*Sig
for _, f := range t.Fields().Slice() {
- if f.Type.Etype != types.TFUNC || f.Sym == nil {
+ if f.Type.Kind() != types.TFUNC || f.Sym == nil {
continue
}
if f.Sym.IsBlank() {
@@ -495,7 +491,7 @@ func dimportpath(p *types.Pkg) {
}
str := p.Path
- if p == ir.LocalPkg {
+ if p == types.LocalPkg {
// Note: myimportpath != "", or else dgopkgpath won't call dimportpath.
str = base.Ctxt.Pkgpath
}
@@ -512,7 +508,7 @@ func dgopkgpath(s *obj.LSym, ot int, pkg *types.Pkg) int {
return duintptr(s, ot, 0)
}
- if pkg == ir.LocalPkg && base.Ctxt.Pkgpath == "" {
+ if pkg == types.LocalPkg && base.Ctxt.Pkgpath == "" {
// If we don't know the full import path of the package being compiled
// (i.e. -p was not passed on the compiler command line), emit a reference to
// type..importpath.""., which the linker will rewrite using the correct import path.
@@ -531,7 +527,7 @@ func dgopkgpathOff(s *obj.LSym, ot int, pkg *types.Pkg) int {
if pkg == nil {
return duint32(s, ot, 0)
}
- if pkg == ir.LocalPkg && base.Ctxt.Pkgpath == "" {
+ if pkg == types.LocalPkg && base.Ctxt.Pkgpath == "" {
// If we don't know the full import path of the package being compiled
// (i.e. -p was not passed on the compiler command line), emit a reference to
// type..importpath.""., which the linker will rewrite using the correct import path.
@@ -640,7 +636,7 @@ func dname(name, tag string, pkg *types.Pkg, exported bool) *obj.LSym {
// backing array of the []method field is written (by dextratypeData).
func dextratype(lsym *obj.LSym, ot int, t *types.Type, dataAdd int) int {
m := methods(t)
- if t.Sym == nil && len(m) == 0 {
+ if t.Sym() == nil && len(m) == 0 {
return ot
}
noff := int(Rnd(int64(ot), int64(Widthptr)))
@@ -672,16 +668,16 @@ func dextratype(lsym *obj.LSym, ot int, t *types.Type, dataAdd int) int {
}
func typePkg(t *types.Type) *types.Pkg {
- tsym := t.Sym
+ tsym := t.Sym()
if tsym == nil {
- switch t.Etype {
+ switch t.Kind() {
case types.TARRAY, types.TSLICE, types.TPTR, types.TCHAN:
if t.Elem() != nil {
- tsym = t.Elem().Sym
+ tsym = t.Elem().Sym()
}
}
}
- if tsym != nil && t != types.Types[t.Etype] && t != types.Errortype {
+ if tsym != nil && t != types.Types[t.Kind()] && t != types.ErrorType {
return tsym.Pkg
}
return nil
@@ -753,7 +749,7 @@ func typeptrdata(t *types.Type) int64 {
return 0
}
- switch t.Etype {
+ switch t.Kind() {
case types.TPTR,
types.TUNSAFEPTR,
types.TFUNC,
@@ -823,7 +819,7 @@ func dcommontype(lsym *obj.LSym, t *types.Type) int {
var sptr *obj.LSym
if !t.IsPtr() || t.IsPtrElem() {
tptr := types.NewPtr(t)
- if t.Sym != nil || methods(tptr) != nil {
+ if t.Sym() != nil || methods(tptr) != nil {
sptrWeak = false
}
sptr = dtypesym(tptr)
@@ -855,7 +851,7 @@ func dcommontype(lsym *obj.LSym, t *types.Type) int {
if uncommonSize(t) != 0 {
tflag |= tflagUncommon
}
- if t.Sym != nil && t.Sym.Name != "" {
+ if t.Sym() != nil && t.Sym().Name != "" {
tflag |= tflagNamed
}
if IsRegularMemory(t) {
@@ -872,12 +868,12 @@ func dcommontype(lsym *obj.LSym, t *types.Type) int {
if !strings.HasPrefix(p, "*") {
p = "*" + p
tflag |= tflagExtraStar
- if t.Sym != nil {
- exported = types.IsExported(t.Sym.Name)
+ if t.Sym() != nil {
+ exported = types.IsExported(t.Sym().Name)
}
} else {
- if t.Elem() != nil && t.Elem().Sym != nil {
- exported = types.IsExported(t.Elem().Sym.Name)
+ if t.Elem() != nil && t.Elem().Sym() != nil {
+ exported = types.IsExported(t.Elem().Sym().Name)
}
}
@@ -895,7 +891,7 @@ func dcommontype(lsym *obj.LSym, t *types.Type) int {
ot = duint8(lsym, ot, t.Align) // align
ot = duint8(lsym, ot, t.Align) // fieldAlign
- i = kinds[t.Etype]
+ i = kinds[t.Kind()]
if isdirectiface(t) {
i |= objabi.KindDirectIface
}
@@ -1001,7 +997,7 @@ func typename(t *types.Type) ir.Node {
}
n := ir.Nod(ir.OADDR, ir.AsNode(s.Def), nil)
- n.SetType(types.NewPtr(ir.AsNode(s.Def).Type()))
+ n.SetType(types.NewPtr(s.Def.Type()))
n.SetTypecheck(1)
return n
}
@@ -1021,7 +1017,7 @@ func itabname(t, itype *types.Type) ir.Node {
}
n := ir.Nod(ir.OADDR, ir.AsNode(s.Def), nil)
- n.SetType(types.NewPtr(ir.AsNode(s.Def).Type()))
+ n.SetType(types.NewPtr(s.Def.Type()))
n.SetTypecheck(1)
return n
}
@@ -1029,7 +1025,7 @@ func itabname(t, itype *types.Type) ir.Node {
// isreflexive reports whether t has a reflexive equality operator.
// That is, if x==x for all x of type t.
func isreflexive(t *types.Type) bool {
- switch t.Etype {
+ switch t.Kind() {
case types.TBOOL,
types.TINT,
types.TUINT,
@@ -1075,7 +1071,7 @@ func isreflexive(t *types.Type) bool {
// needkeyupdate reports whether map updates with t as a key
// need the key to be updated.
func needkeyupdate(t *types.Type) bool {
- switch t.Etype {
+ switch t.Kind() {
case types.TBOOL, types.TINT, types.TUINT, types.TINT8, types.TUINT8, types.TINT16, types.TUINT16, types.TINT32, types.TUINT32,
types.TINT64, types.TUINT64, types.TUINTPTR, types.TPTR, types.TUNSAFEPTR, types.TCHAN:
return false
@@ -1104,7 +1100,7 @@ func needkeyupdate(t *types.Type) bool {
// hashMightPanic reports whether the hash of a map key of type t might panic.
func hashMightPanic(t *types.Type) bool {
- switch t.Etype {
+ switch t.Kind() {
case types.TINTER:
return true
@@ -1128,8 +1124,8 @@ func hashMightPanic(t *types.Type) bool {
// They've been separate internally to make error messages
// better, but we have to merge them in the reflect tables.
func formalType(t *types.Type) *types.Type {
- if t == types.Bytetype || t == types.Runetype {
- return types.Types[t.Etype]
+ if t == types.ByteType || t == types.RuneType {
+ return types.Types[t.Kind()]
}
return t
}
@@ -1152,19 +1148,19 @@ func dtypesym(t *types.Type) *obj.LSym {
// emit the type structures for int, float, etc.
tbase := t
- if t.IsPtr() && t.Sym == nil && t.Elem().Sym != nil {
+ if t.IsPtr() && t.Sym() == nil && t.Elem().Sym() != nil {
tbase = t.Elem()
}
dupok := 0
- if tbase.Sym == nil {
+ if tbase.Sym() == nil {
dupok = obj.DUPOK
}
- if base.Ctxt.Pkgpath != "runtime" || (tbase != types.Types[tbase.Etype] && tbase != types.Bytetype && tbase != types.Runetype && tbase != types.Errortype) { // int, float, etc
+ if base.Ctxt.Pkgpath != "runtime" || (tbase != types.Types[tbase.Kind()] && tbase != types.ByteType && tbase != types.RuneType && tbase != types.ErrorType) { // int, float, etc
// named types from other files are defined only by those files
- if tbase.Sym != nil && tbase.Sym.Pkg != ir.LocalPkg {
+ if tbase.Sym() != nil && tbase.Sym().Pkg != types.LocalPkg {
if i, ok := typeSymIdx[tbase]; ok {
- lsym.Pkg = tbase.Sym.Pkg.Prefix
+ lsym.Pkg = tbase.Sym().Pkg.Prefix
if t != tbase {
lsym.SymIdx = int32(i[1])
} else {
@@ -1175,13 +1171,13 @@ func dtypesym(t *types.Type) *obj.LSym {
return lsym
}
// TODO(mdempsky): Investigate whether this can happen.
- if tbase.Etype == types.TFORW {
+ if tbase.Kind() == types.TFORW {
return lsym
}
}
ot := 0
- switch t.Etype {
+ switch t.Kind() {
default:
ot = dcommontype(lsym, t)
ot = dextratype(lsym, ot, t, 0)
@@ -1262,8 +1258,8 @@ func dtypesym(t *types.Type) *obj.LSym {
ot = dcommontype(lsym, t)
var tpkg *types.Pkg
- if t.Sym != nil && t != types.Types[t.Etype] && t != types.Errortype {
- tpkg = t.Sym.Pkg
+ if t.Sym() != nil && t != types.Types[t.Kind()] && t != types.ErrorType {
+ tpkg = t.Sym().Pkg
}
ot = dgopkgpath(lsym, ot, tpkg)
@@ -1328,7 +1324,7 @@ func dtypesym(t *types.Type) *obj.LSym {
ot = dextratype(lsym, ot, t, 0)
case types.TPTR:
- if t.Elem().Etype == types.TANY {
+ if t.Elem().Kind() == types.TANY {
// ../../../../runtime/type.go:/UnsafePointerType
ot = dcommontype(lsym, t)
ot = dextratype(lsym, ot, t, 0)
@@ -1397,13 +1393,13 @@ func dtypesym(t *types.Type) *obj.LSym {
// When buildmode=shared, all types are in typelinks so the
// runtime can deduplicate type pointers.
keep := base.Ctxt.Flag_dynlink
- if !keep && t.Sym == nil {
+ if !keep && t.Sym() == nil {
// For an unnamed type, we only need the link if the type can
// be created at run time by reflect.PtrTo and similar
// functions. If the type exists in the program, those
// functions must return the existing type structure rather
// than creating a new one.
- switch t.Etype {
+ switch t.Kind() {
case types.TPTR, types.TARRAY, types.TCHAN, types.TFUNC, types.TMAP, types.TSLICE, types.TSTRUCT:
keep = true
}
@@ -1541,7 +1537,7 @@ func dumpsignats() {
for _, ts := range signats {
t := ts.t
dtypesym(t)
- if t.Sym != nil {
+ if t.Sym() != nil {
dtypesym(types.NewPtr(t))
}
}
@@ -1572,7 +1568,7 @@ func dumptabs() {
}
// process ptabs
- if ir.LocalPkg.Name == "main" && len(ptabs) > 0 {
+ if types.LocalPkg.Name == "main" && len(ptabs) > 0 {
ot := 0
s := base.Ctxt.Lookup("go.plugin.tabs")
for _, p := range ptabs {
@@ -1616,7 +1612,7 @@ func dumpbasictypes() {
// another possible choice would be package main,
// but using runtime means fewer copies in object files.
if base.Ctxt.Pkgpath == "runtime" {
- for i := types.EType(1); i <= types.TBOOL; i++ {
+ for i := types.Kind(1); i <= types.TBOOL; i++ {
dtypesym(types.NewPtr(types.Types[i]))
}
dtypesym(types.NewPtr(types.Types[types.TSTRING]))
@@ -1624,9 +1620,9 @@ func dumpbasictypes() {
// emit type structs for error and func(error) string.
// The latter is the type of an auto-generated wrapper.
- dtypesym(types.NewPtr(types.Errortype))
+ dtypesym(types.NewPtr(types.ErrorType))
- dtypesym(functype(nil, []ir.Node{anonfield(types.Errortype)}, []ir.Node{anonfield(types.Types[types.TSTRING])}))
+ dtypesym(functype(nil, []*ir.Field{anonfield(types.ErrorType)}, []*ir.Field{anonfield(types.Types[types.TSTRING])}))
// add paths for runtime and main, which 6l imports implicitly.
dimportpath(Runtimepkg)
@@ -1665,7 +1661,7 @@ func (a typesByString) Less(i, j int) bool {
// will be equal for the above checks, but different in DWARF output.
// Sort by source position to ensure deterministic order.
// See issues 27013 and 30202.
- if a[i].t.Etype == types.TINTER && a[i].t.Methods().Len() > 0 {
+ if a[i].t.Kind() == types.TINTER && a[i].t.Methods().Len() > 0 {
return a[i].t.Methods().Index(0).Pos.Before(a[j].t.Methods().Index(0).Pos)
}
return false
@@ -1821,7 +1817,7 @@ func (p *GCProg) emit(t *types.Type, offset int64) {
p.w.Ptr(offset / int64(Widthptr))
return
}
- switch t.Etype {
+ switch t.Kind() {
default:
base.Fatalf("GCProg.emit: unexpected type %v", t)
diff --git a/src/cmd/compile/internal/gc/scc.go b/src/cmd/compile/internal/gc/scc.go
index fe7956d5d5..063aaa09bd 100644
--- a/src/cmd/compile/internal/gc/scc.go
+++ b/src/cmd/compile/internal/gc/scc.go
@@ -32,10 +32,10 @@ import "cmd/compile/internal/ir"
// when analyzing a set of mutually recursive functions.
type bottomUpVisitor struct {
- analyze func([]ir.Node, bool)
+ analyze func([]*ir.Func, bool)
visitgen uint32
- nodeID map[ir.Node]uint32
- stack []ir.Node
+ nodeID map[*ir.Func]uint32
+ stack []*ir.Func
}
// visitBottomUp invokes analyze on the ODCLFUNC nodes listed in list.
@@ -51,18 +51,18 @@ type bottomUpVisitor struct {
// If recursive is false, the list consists of only a single function and its closures.
// If recursive is true, the list may still contain only a single function,
// if that function is itself recursive.
-func visitBottomUp(list []ir.Node, analyze func(list []ir.Node, recursive bool)) {
+func visitBottomUp(list []ir.Node, analyze func(list []*ir.Func, recursive bool)) {
var v bottomUpVisitor
v.analyze = analyze
- v.nodeID = make(map[ir.Node]uint32)
+ v.nodeID = make(map[*ir.Func]uint32)
for _, n := range list {
if n.Op() == ir.ODCLFUNC && !n.Func().IsHiddenClosure() {
- v.visit(n)
+ v.visit(n.(*ir.Func))
}
}
}
-func (v *bottomUpVisitor) visit(n ir.Node) uint32 {
+func (v *bottomUpVisitor) visit(n *ir.Func) uint32 {
if id := v.nodeID[n]; id > 0 {
// already visited
return id
@@ -80,41 +80,41 @@ func (v *bottomUpVisitor) visit(n ir.Node) uint32 {
case ir.ONAME:
if n.Class() == ir.PFUNC {
if n != nil && n.Name().Defn != nil {
- if m := v.visit(n.Name().Defn); m < min {
+ if m := v.visit(n.Name().Defn.(*ir.Func)); m < min {
min = m
}
}
}
case ir.OMETHEXPR:
fn := methodExprName(n)
- if fn != nil && fn.Name().Defn != nil {
- if m := v.visit(fn.Name().Defn); m < min {
+ if fn != nil && fn.Defn != nil {
+ if m := v.visit(fn.Defn.(*ir.Func)); m < min {
min = m
}
}
case ir.ODOTMETH:
fn := methodExprName(n)
- if fn != nil && fn.Op() == ir.ONAME && fn.Class() == ir.PFUNC && fn.Name().Defn != nil {
- if m := v.visit(fn.Name().Defn); m < min {
+ if fn != nil && fn.Op() == ir.ONAME && fn.Class() == ir.PFUNC && fn.Defn != nil {
+ if m := v.visit(fn.Defn.(*ir.Func)); m < min {
min = m
}
}
case ir.OCALLPART:
fn := ir.AsNode(callpartMethod(n).Nname)
if fn != nil && fn.Op() == ir.ONAME && fn.Class() == ir.PFUNC && fn.Name().Defn != nil {
- if m := v.visit(fn.Name().Defn); m < min {
+ if m := v.visit(fn.Name().Defn.(*ir.Func)); m < min {
min = m
}
}
case ir.OCLOSURE:
- if m := v.visit(n.Func().Decl); m < min {
+ if m := v.visit(n.Func()); m < min {
min = m
}
}
return true
})
- if (min == id || min == id+1) && !n.Func().IsHiddenClosure() {
+ if (min == id || min == id+1) && !n.IsHiddenClosure() {
// This node is the root of a strongly connected component.
// The original min passed to visitcodelist was v.nodeID[n]+1.
diff --git a/src/cmd/compile/internal/gc/select.go b/src/cmd/compile/internal/gc/select.go
index 116b6f5b6e..3afcef69f8 100644
--- a/src/cmd/compile/internal/gc/select.go
+++ b/src/cmd/compile/internal/gc/select.go
@@ -47,36 +47,30 @@ func typecheckselect(sel ir.Node) {
}
base.ErrorfAt(pos, "select case must be receive, send or assign recv")
- // convert x = <-c into OSELRECV(x, <-c).
- // remove implicit conversions; the eventual assignment
- // will reintroduce them.
case ir.OAS:
+ // convert x = <-c into OSELRECV(x, <-c).
+ // remove implicit conversions; the eventual assignment
+ // will reintroduce them.
if (n.Right().Op() == ir.OCONVNOP || n.Right().Op() == ir.OCONVIFACE) && n.Right().Implicit() {
n.SetRight(n.Right().Left())
}
-
if n.Right().Op() != ir.ORECV {
base.ErrorfAt(n.Pos(), "select assignment must have receive on right hand side")
break
}
-
n.SetOp(ir.OSELRECV)
- // convert x, ok = <-c into OSELRECV2(x, <-c) with ntest=ok
case ir.OAS2RECV:
- if n.Right().Op() != ir.ORECV {
+ // convert x, ok = <-c into OSELRECV2(x, <-c) with ntest=ok
+ if n.Rlist().First().Op() != ir.ORECV {
base.ErrorfAt(n.Pos(), "select assignment must have receive on right hand side")
break
}
-
n.SetOp(ir.OSELRECV2)
- n.SetLeft(n.List().First())
- n.PtrList().Set1(n.List().Second())
- // convert <-c into OSELRECV(N, <-c)
case ir.ORECV:
- n = ir.NodAt(n.Pos(), ir.OSELRECV, nil, n)
-
+ // convert <-c into OSELRECV(_, <-c)
+ n = ir.NodAt(n.Pos(), ir.OSELRECV, ir.BlankNode, n)
n.SetTypecheck(1)
ncase.SetLeft(n)
@@ -134,28 +128,19 @@ func walkselectcases(cases *ir.Nodes) []ir.Node {
case ir.OSEND:
// already ok
- case ir.OSELRECV, ir.OSELRECV2:
- if n.Op() == ir.OSELRECV || n.List().Len() == 0 {
- if n.Left() == nil {
- n = n.Right()
- } else {
- n.SetOp(ir.OAS)
- }
+ case ir.OSELRECV:
+ if ir.IsBlank(n.Left()) {
+ n = n.Right()
break
}
+ n.SetOp(ir.OAS)
- if n.Left() == nil {
- ir.BlankNode = typecheck(ir.BlankNode, ctxExpr|ctxAssign)
- n.SetLeft(ir.BlankNode)
+ case ir.OSELRECV2:
+ if ir.IsBlank(n.List().First()) && ir.IsBlank(n.List().Second()) {
+ n = n.Rlist().First()
+ break
}
-
- n.SetOp(ir.OAS2)
- n.PtrList().Prepend(n.Left())
- n.PtrRlist().Set1(n.Right())
- n.SetRight(nil)
- n.SetLeft(nil)
- n.SetTypecheck(0)
- n = typecheck(n, ctxStmt)
+ n.SetOp(ir.OAS2RECV)
}
l = append(l, n)
@@ -176,20 +161,30 @@ func walkselectcases(cases *ir.Nodes) []ir.Node {
dflt = cas
continue
}
+
+ // Lower x, _ = <-c to x = <-c.
+ if n.Op() == ir.OSELRECV2 && ir.IsBlank(n.List().Second()) {
+ n = ir.NodAt(n.Pos(), ir.OSELRECV, n.List().First(), n.Rlist().First())
+ n.SetTypecheck(1)
+ cas.SetLeft(n)
+ }
+
switch n.Op() {
case ir.OSEND:
n.SetRight(ir.Nod(ir.OADDR, n.Right(), nil))
n.SetRight(typecheck(n.Right(), ctxExpr))
- case ir.OSELRECV, ir.OSELRECV2:
- if n.Op() == ir.OSELRECV2 && n.List().Len() == 0 {
- n.SetOp(ir.OSELRECV)
- }
-
- if n.Left() != nil {
+ case ir.OSELRECV:
+ if !ir.IsBlank(n.Left()) {
n.SetLeft(ir.Nod(ir.OADDR, n.Left(), nil))
n.SetLeft(typecheck(n.Left(), ctxExpr))
}
+
+ case ir.OSELRECV2:
+ if !ir.IsBlank(n.List().First()) {
+ n.List().SetIndex(0, ir.Nod(ir.OADDR, n.List().First(), nil))
+ n.List().SetIndex(0, typecheck(n.List().First(), ctxExpr))
+ }
}
}
@@ -204,6 +199,7 @@ func walkselectcases(cases *ir.Nodes) []ir.Node {
setlineno(n)
r := ir.Nod(ir.OIF, nil, nil)
r.PtrInit().Set(cas.Init().Slice())
+ var call ir.Node
switch n.Op() {
default:
base.Fatalf("select %v", n.Op())
@@ -211,30 +207,30 @@ func walkselectcases(cases *ir.Nodes) []ir.Node {
case ir.OSEND:
// if selectnbsend(c, v) { body } else { default body }
ch := n.Left()
- r.SetLeft(mkcall1(chanfn("selectnbsend", 2, ch.Type()), types.Types[types.TBOOL], r.PtrInit(), ch, n.Right()))
+ call = mkcall1(chanfn("selectnbsend", 2, ch.Type()), types.Types[types.TBOOL], r.PtrInit(), ch, n.Right())
case ir.OSELRECV:
// if selectnbrecv(&v, c) { body } else { default body }
ch := n.Right().Left()
elem := n.Left()
- if elem == nil {
+ if ir.IsBlank(elem) {
elem = nodnil()
}
- r.SetLeft(mkcall1(chanfn("selectnbrecv", 2, ch.Type()), types.Types[types.TBOOL], r.PtrInit(), elem, ch))
+ call = mkcall1(chanfn("selectnbrecv", 2, ch.Type()), types.Types[types.TBOOL], r.PtrInit(), elem, ch)
case ir.OSELRECV2:
// if selectnbrecv2(&v, &received, c) { body } else { default body }
- ch := n.Right().Left()
- elem := n.Left()
- if elem == nil {
+ ch := n.Rlist().First().Left()
+ elem := n.List().First()
+ if ir.IsBlank(elem) {
elem = nodnil()
}
- receivedp := ir.Nod(ir.OADDR, n.List().First(), nil)
+ receivedp := ir.Nod(ir.OADDR, n.List().Second(), nil)
receivedp = typecheck(receivedp, ctxExpr)
- r.SetLeft(mkcall1(chanfn("selectnbrecv2", 2, ch.Type()), types.Types[types.TBOOL], r.PtrInit(), elem, receivedp, ch))
+ call = mkcall1(chanfn("selectnbrecv2", 2, ch.Type()), types.Types[types.TBOOL], r.PtrInit(), elem, receivedp, ch)
}
- r.SetLeft(typecheck(r.Left(), ctxExpr))
+ r.SetLeft(typecheck(call, ctxExpr))
r.PtrBody().Set(cas.Body().Slice())
r.PtrRlist().Set(append(dflt.Init().Slice(), dflt.Body().Slice()...))
return []ir.Node{r, ir.Nod(ir.OBREAK, nil, nil)}
@@ -288,11 +284,16 @@ func walkselectcases(cases *ir.Nodes) []ir.Node {
nsends++
c = n.Left()
elem = n.Right()
- case ir.OSELRECV, ir.OSELRECV2:
+ case ir.OSELRECV:
nrecvs++
i = ncas - nrecvs
c = n.Right().Left()
elem = n.Left()
+ case ir.OSELRECV2:
+ nrecvs++
+ i = ncas - nrecvs
+ c = n.Rlist().First().Left()
+ elem = n.List().First()
}
casorder[i] = cas
@@ -305,7 +306,7 @@ func walkselectcases(cases *ir.Nodes) []ir.Node {
c = convnop(c, types.Types[types.TUNSAFEPTR])
setField("c", c)
- if elem != nil {
+ if !ir.IsBlank(elem) {
elem = convnop(elem, types.Types[types.TUNSAFEPTR])
setField("elem", elem)
}
@@ -347,7 +348,7 @@ func walkselectcases(cases *ir.Nodes) []ir.Node {
r := ir.Nod(ir.OIF, cond, nil)
if n := cas.Left(); n != nil && n.Op() == ir.OSELRECV2 {
- x := ir.Nod(ir.OAS, n.List().First(), recvOK)
+ x := ir.Nod(ir.OAS, n.List().Second(), recvOK)
x = typecheck(x, ctxStmt)
r.PtrBody().Append(x)
}
@@ -381,7 +382,7 @@ var scase *types.Type
// Keep in sync with src/runtime/select.go.
func scasetype() *types.Type {
if scase == nil {
- scase = tostruct([]ir.Node{
+ scase = tostruct([]*ir.Field{
namedfield("c", types.Types[types.TUNSAFEPTR]),
namedfield("elem", types.Types[types.TUNSAFEPTR]),
})
diff --git a/src/cmd/compile/internal/gc/sinit.go b/src/cmd/compile/internal/gc/sinit.go
index e30663cfbb..3c5f11c5ab 100644
--- a/src/cmd/compile/internal/gc/sinit.go
+++ b/src/cmd/compile/internal/gc/sinit.go
@@ -60,7 +60,8 @@ func (s *InitSchedule) tryStaticInit(n ir.Node) bool {
if n.Op() != ir.OAS {
return false
}
- if ir.IsBlank(n.Left()) && candiscard(n.Right()) {
+ if ir.IsBlank(n.Left()) && !hasSideEffects(n.Right()) {
+ // Discard.
return true
}
lno := setlineno(n)
@@ -78,7 +79,7 @@ func (s *InitSchedule) staticcopy(l ir.Node, r ir.Node) bool {
pfuncsym(l, r)
return true
}
- if r.Class() != ir.PEXTERN || r.Sym().Pkg != ir.LocalPkg {
+ if r.Class() != ir.PEXTERN || r.Sym().Pkg != types.LocalPkg {
return false
}
if r.Name().Defn == nil { // probably zeroed but perhaps supplied externally and of unknown value
@@ -134,7 +135,7 @@ func (s *InitSchedule) staticcopy(l ir.Node, r ir.Node) bool {
case ir.OSLICELIT:
// copy slice
a := s.inittemps[r]
- slicesym(l, a, r.Right().Int64Val())
+ slicesym(l, a, ir.Int64Val(r.Right()))
return true
case ir.OARRAYLIT, ir.OSTRUCTLIT:
@@ -213,7 +214,7 @@ func (s *InitSchedule) staticassign(l ir.Node, r ir.Node) bool {
case ir.OSTR2BYTES:
if l.Class() == ir.PEXTERN && r.Left().Op() == ir.OLITERAL {
- sval := r.Left().StringVal()
+ sval := ir.StringVal(r.Left())
slicebytes(l, sval)
return true
}
@@ -221,7 +222,7 @@ func (s *InitSchedule) staticassign(l ir.Node, r ir.Node) bool {
case ir.OSLICELIT:
s.initplan(r)
// Init slice.
- bound := r.Right().Int64Val()
+ bound := ir.Int64Val(r.Right())
ta := types.NewArray(r.Type().Elem(), bound)
ta.SetNoalg(true)
a := staticname(ta)
@@ -371,7 +372,8 @@ func staticname(t *types.Type) ir.Node {
// Don't use lookupN; it interns the resulting string, but these are all unique.
n := NewName(lookup(fmt.Sprintf("%s%d", obj.StaticNamePref, statuniqgen)))
statuniqgen++
- addvar(n, t, ir.PEXTERN)
+ declare(n, ir.PEXTERN)
+ n.SetType(t)
n.Sym().Linksym().Set(obj.AttrLocal, true)
return n
}
@@ -417,7 +419,7 @@ func getdyn(n ir.Node, top bool) initGenType {
if !top {
return initDynamic
}
- if n.Right().Int64Val()/4 > int64(n.List().Len()) {
+ if ir.Int64Val(n.Right())/4 > int64(n.List().Len()) {
// <25% of entries have explicit values.
// Very rough estimation, it takes 4 bytes of instructions
// to initialize 1 byte of result. So don't use a static
@@ -547,7 +549,8 @@ func fixedlit(ctxt initContext, kind initKind, n ir.Node, var_ ir.Node, init *ir
for _, r := range n.List().Slice() {
a, value := splitnode(r)
- if a == ir.BlankNode && candiscard(value) {
+ if a == ir.BlankNode && !hasSideEffects(value) {
+ // Discard.
continue
}
@@ -576,7 +579,7 @@ func fixedlit(ctxt initContext, kind initKind, n ir.Node, var_ ir.Node, init *ir
case initKindStatic:
genAsStatic(a)
case initKindDynamic, initKindLocalCode:
- a = orderStmtInPlace(a, map[string][]ir.Node{})
+ a = orderStmtInPlace(a, map[string][]*ir.Name{})
a = walkstmt(a)
init.Append(a)
default:
@@ -593,12 +596,12 @@ func isSmallSliceLit(n ir.Node) bool {
r := n.Right()
- return smallintconst(r) && (n.Type().Elem().Width == 0 || r.Int64Val() <= smallArrayBytes/n.Type().Elem().Width)
+ return smallintconst(r) && (n.Type().Elem().Width == 0 || ir.Int64Val(r) <= smallArrayBytes/n.Type().Elem().Width)
}
func slicelit(ctxt initContext, n ir.Node, var_ ir.Node, init *ir.Nodes) {
// make an array type corresponding the number of elements we have
- t := types.NewArray(n.Type().Elem(), n.Right().Int64Val())
+ t := types.NewArray(n.Type().Elem(), ir.Int64Val(n.Right()))
dowidth(t)
if ctxt == inNonInitFunction {
@@ -686,8 +689,7 @@ func slicelit(ctxt initContext, n ir.Node, var_ ir.Node, init *ir.Nodes) {
a = ir.Nod(ir.OADDR, a, nil)
} else {
- a = ir.Nod(ir.ONEW, nil, nil)
- a.PtrList().Set1(typenod(t))
+ a = ir.Nod(ir.ONEW, ir.TypeNode(t), nil)
}
a = ir.Nod(ir.OAS, vauto, a)
@@ -745,7 +747,7 @@ func slicelit(ctxt initContext, n ir.Node, var_ ir.Node, init *ir.Nodes) {
a = ir.Nod(ir.OAS, a, value)
a = typecheck(a, ctxStmt)
- a = orderStmtInPlace(a, map[string][]ir.Node{})
+ a = orderStmtInPlace(a, map[string][]*ir.Name{})
a = walkstmt(a)
init.Append(a)
}
@@ -754,7 +756,7 @@ func slicelit(ctxt initContext, n ir.Node, var_ ir.Node, init *ir.Nodes) {
a = ir.Nod(ir.OAS, var_, ir.Nod(ir.OSLICE, vauto, nil))
a = typecheck(a, ctxStmt)
- a = orderStmtInPlace(a, map[string][]ir.Node{})
+ a = orderStmtInPlace(a, map[string][]*ir.Name{})
a = walkstmt(a)
init.Append(a)
}
@@ -763,7 +765,7 @@ func maplit(n ir.Node, m ir.Node, init *ir.Nodes) {
// make the map var
a := ir.Nod(ir.OMAKE, nil, nil)
a.SetEsc(n.Esc())
- a.PtrList().Set2(typenod(n.Type()), nodintconst(int64(n.List().Len())))
+ a.PtrList().Set2(ir.TypeNode(n.Type()), nodintconst(int64(n.List().Len())))
litas(m, a, init)
entries := n.List().Slice()
@@ -889,9 +891,8 @@ func anylit(n ir.Node, var_ ir.Node, init *ir.Nodes) {
r = ir.Nod(ir.OADDR, n.Right(), nil)
r = typecheck(r, ctxExpr)
} else {
- r = ir.Nod(ir.ONEW, nil, nil)
- r.SetTypecheck(1)
- r.SetType(t)
+ r = ir.Nod(ir.ONEW, ir.TypeNode(n.Left().Type()), nil)
+ r = typecheck(r, ctxExpr)
r.SetEsc(n.Esc())
}
@@ -959,6 +960,9 @@ func anylit(n ir.Node, var_ ir.Node, init *ir.Nodes) {
}
}
+// oaslit handles special composite literal assignments.
+// It returns true if n's effects have been added to init,
+// in which case n should be dropped from the program by the caller.
func oaslit(n ir.Node, init *ir.Nodes) bool {
if n.Left() == nil || n.Right() == nil {
// not a special composite literal assignment
@@ -990,14 +994,12 @@ func oaslit(n ir.Node, init *ir.Nodes) bool {
anylit(n.Right(), n.Left(), init)
}
- n.SetOp(ir.OEMPTY)
- n.SetRight(nil)
return true
}
func getlit(lit ir.Node) int {
if smallintconst(lit) {
- return int(lit.Int64Val())
+ return int(ir.Int64Val(lit))
}
return -1
}
diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go
index cb73532b48..f13c45c2a6 100644
--- a/src/cmd/compile/internal/gc/ssa.go
+++ b/src/cmd/compile/internal/gc/ssa.go
@@ -40,7 +40,7 @@ const ssaDumpFile = "ssa.html"
const maxOpenDefers = 8
// ssaDumpInlined holds all inlined functions when ssaDump contains a function name.
-var ssaDumpInlined []ir.Node
+var ssaDumpInlined []*ir.Func
func initssaconfig() {
types_ := ssa.NewTypes()
@@ -54,13 +54,13 @@ func initssaconfig() {
_ = types.NewPtr(types.Types[types.TINTER]) // *interface{}
_ = types.NewPtr(types.NewPtr(types.Types[types.TSTRING])) // **string
_ = types.NewPtr(types.NewSlice(types.Types[types.TINTER])) // *[]interface{}
- _ = types.NewPtr(types.NewPtr(types.Bytetype)) // **byte
- _ = types.NewPtr(types.NewSlice(types.Bytetype)) // *[]byte
+ _ = types.NewPtr(types.NewPtr(types.ByteType)) // **byte
+ _ = types.NewPtr(types.NewSlice(types.ByteType)) // *[]byte
_ = types.NewPtr(types.NewSlice(types.Types[types.TSTRING])) // *[]string
_ = types.NewPtr(types.NewPtr(types.NewPtr(types.Types[types.TUINT8]))) // ***uint8
_ = types.NewPtr(types.Types[types.TINT16]) // *int16
_ = types.NewPtr(types.Types[types.TINT64]) // *int64
- _ = types.NewPtr(types.Errortype) // *error
+ _ = types.NewPtr(types.ErrorType) // *error
types.NewPtrCacheEnabled = false
ssaConfig = ssa.NewConfig(thearch.LinkArch.Name, *types_, base.Ctxt, base.Flag.N == 0)
ssaConfig.SoftFloat = thearch.SoftFloat
@@ -82,6 +82,7 @@ func initssaconfig() {
growslice = sysfunc("growslice")
msanread = sysfunc("msanread")
msanwrite = sysfunc("msanwrite")
+ msanmove = sysfunc("msanmove")
newobject = sysfunc("newobject")
newproc = sysfunc("newproc")
panicdivide = sysfunc("panicdivide")
@@ -242,8 +243,8 @@ func dvarint(x *obj.LSym, off int, v int64) int {
// - Size of the argument
// - Offset of where argument should be placed in the args frame when making call
func (s *state) emitOpenDeferInfo() {
- x := base.Ctxt.Lookup(s.curfn.Func().LSym.Name + ".opendefer")
- s.curfn.Func().LSym.Func().OpenCodedDeferInfo = x
+ x := base.Ctxt.Lookup(s.curfn.LSym.Name + ".opendefer")
+ s.curfn.LSym.Func().OpenCodedDeferInfo = x
off := 0
// Compute maxargsize (max size of arguments for all defers)
@@ -289,7 +290,7 @@ func (s *state) emitOpenDeferInfo() {
// buildssa builds an SSA function for fn.
// worker indicates which of the backend workers is doing the processing.
-func buildssa(fn ir.Node, worker int) *ssa.Func {
+func buildssa(fn *ir.Func, worker int) *ssa.Func {
name := ir.FuncName(fn)
printssa := false
if ssaDump != "" { // match either a simple name e.g. "(*Reader).Reset", or a package.name e.g. "compress/gzip.(*Reader).Reset"
@@ -298,9 +299,9 @@ func buildssa(fn ir.Node, worker int) *ssa.Func {
var astBuf *bytes.Buffer
if printssa {
astBuf = &bytes.Buffer{}
- ir.FDumpList(astBuf, "buildssa-enter", fn.Func().Enter)
+ ir.FDumpList(astBuf, "buildssa-enter", fn.Enter)
ir.FDumpList(astBuf, "buildssa-body", fn.Body())
- ir.FDumpList(astBuf, "buildssa-exit", fn.Func().Exit)
+ ir.FDumpList(astBuf, "buildssa-exit", fn.Exit)
if ssaDumpStdout {
fmt.Println("generating SSA for", name)
fmt.Print(astBuf.String())
@@ -311,8 +312,8 @@ func buildssa(fn ir.Node, worker int) *ssa.Func {
s.pushLine(fn.Pos())
defer s.popLine()
- s.hasdefer = fn.Func().HasDefer()
- if fn.Func().Pragma&ir.CgoUnsafeArgs != 0 {
+ s.hasdefer = fn.HasDefer()
+ if fn.Pragma&ir.CgoUnsafeArgs != 0 {
s.cgoUnsafeArgs = true
}
@@ -331,7 +332,7 @@ func buildssa(fn ir.Node, worker int) *ssa.Func {
s.f.Name = name
s.f.DebugTest = s.f.DebugHashMatch("GOSSAHASH")
s.f.PrintOrHtmlSSA = printssa
- if fn.Func().Pragma&ir.Nosplit != 0 {
+ if fn.Pragma&ir.Nosplit != 0 {
s.f.NoSplit = true
}
s.panics = map[funcLine]*ssa.Block{}
@@ -356,11 +357,10 @@ func buildssa(fn ir.Node, worker int) *ssa.Func {
// Allocate starting values
s.labels = map[string]*ssaLabel{}
- s.labeledNodes = map[ir.Node]*ssaLabel{}
s.fwdVars = map[ir.Node]*ssa.Value{}
s.startmem = s.entryNewValue0(ssa.OpInitMem, types.TypeMem)
- s.hasOpenDefers = base.Flag.N == 0 && s.hasdefer && !s.curfn.Func().OpenCodedDeferDisallowed()
+ s.hasOpenDefers = base.Flag.N == 0 && s.hasdefer && !s.curfn.OpenCodedDeferDisallowed()
switch {
case s.hasOpenDefers && (base.Ctxt.Flag_shared || base.Ctxt.Flag_dynlink) && thearch.LinkArch.Name == "386":
// Don't support open-coded defers for 386 ONLY when using shared
@@ -369,7 +369,7 @@ func buildssa(fn ir.Node, worker int) *ssa.Func {
// that we don't track correctly.
s.hasOpenDefers = false
}
- if s.hasOpenDefers && s.curfn.Func().Exit.Len() > 0 {
+ if s.hasOpenDefers && s.curfn.Exit.Len() > 0 {
// Skip doing open defers if there is any extra exit code (likely
// copying heap-allocated return values or race detection), since
// we will not generate that code in the case of the extra
@@ -377,7 +377,7 @@ func buildssa(fn ir.Node, worker int) *ssa.Func {
s.hasOpenDefers = false
}
if s.hasOpenDefers &&
- s.curfn.Func().NumReturns*s.curfn.Func().NumDefers > 15 {
+ s.curfn.NumReturns*s.curfn.NumDefers > 15 {
// Since we are generating defer calls at every exit for
// open-coded defers, skip doing open-coded defers if there are
// too many returns (especially if there are multiple defers).
@@ -411,10 +411,10 @@ func buildssa(fn ir.Node, worker int) *ssa.Func {
}
// Generate addresses of local declarations
- s.decladdrs = map[ir.Node]*ssa.Value{}
+ s.decladdrs = map[*ir.Name]*ssa.Value{}
var args []ssa.Param
var results []ssa.Param
- for _, n := range fn.Func().Dcl {
+ for _, n := range fn.Dcl {
switch n.Class() {
case ir.PPARAM:
s.decladdrs[n] = s.entryNewValue2A(ssa.OpLocalAddr, types.NewPtr(n.Type()), n, s.sp, s.startmem)
@@ -441,7 +441,7 @@ func buildssa(fn ir.Node, worker int) *ssa.Func {
}
// Populate SSAable arguments.
- for _, n := range fn.Func().Dcl {
+ for _, n := range fn.Dcl {
if n.Class() == ir.PPARAM && s.canSSA(n) {
v := s.newValue0A(ssa.OpArg, n.Type(), n)
s.vars[n] = v
@@ -450,12 +450,12 @@ func buildssa(fn ir.Node, worker int) *ssa.Func {
}
// Convert the AST-based IR to the SSA-based IR
- s.stmtList(fn.Func().Enter)
+ s.stmtList(fn.Enter)
s.stmtList(fn.Body())
// fallthrough to exit
if s.curBlock != nil {
- s.pushLine(fn.Func().Endlineno)
+ s.pushLine(fn.Endlineno)
s.exit()
s.popLine()
}
@@ -478,10 +478,10 @@ func buildssa(fn ir.Node, worker int) *ssa.Func {
return s.f
}
-func dumpSourcesColumn(writer *ssa.HTMLWriter, fn ir.Node) {
+func dumpSourcesColumn(writer *ssa.HTMLWriter, fn *ir.Func) {
// Read sources of target function fn.
fname := base.Ctxt.PosTable.Pos(fn.Pos()).Filename()
- targetFn, err := readFuncLines(fname, fn.Pos().Line(), fn.Func().Endlineno.Line())
+ targetFn, err := readFuncLines(fname, fn.Pos().Line(), fn.Endlineno.Line())
if err != nil {
writer.Logf("cannot read sources for function %v: %v", fn, err)
}
@@ -489,13 +489,7 @@ func dumpSourcesColumn(writer *ssa.HTMLWriter, fn ir.Node) {
// Read sources of inlined functions.
var inlFns []*ssa.FuncLines
for _, fi := range ssaDumpInlined {
- var elno src.XPos
- if fi.Name().Defn == nil {
- // Endlineno is filled from exported data.
- elno = fi.Func().Endlineno
- } else {
- elno = fi.Name().Defn.Func().Endlineno
- }
+ elno := fi.Endlineno
fname := base.Ctxt.PosTable.Pos(fi.Pos()).Filename()
fnLines, err := readFuncLines(fname, fi.Pos().Line(), elno.Line())
if err != nil {
@@ -583,7 +577,7 @@ type openDeferInfo struct {
// function call are stored.
argVals []*ssa.Value
// The nodes representing the argtmps where the args of the defer are stored
- argNodes []ir.Node
+ argNodes []*ir.Name
}
type state struct {
@@ -594,11 +588,10 @@ type state struct {
f *ssa.Func
// Node for function
- curfn ir.Node
+ curfn *ir.Func
- // labels and labeled control flow nodes (OFOR, OFORUNTIL, OSWITCH, OSELECT) in f
- labels map[string]*ssaLabel
- labeledNodes map[ir.Node]*ssaLabel
+ // labels in f
+ labels map[string]*ssaLabel
// unlabeled break and continue statement tracking
breakTo *ssa.Block // current target for plain break statement
@@ -621,7 +614,7 @@ type state struct {
defvars []map[ir.Node]*ssa.Value
// addresses of PPARAM and PPARAMOUT variables.
- decladdrs map[ir.Node]*ssa.Value
+ decladdrs map[*ir.Name]*ssa.Value
// starting values. Memory, stack pointer, and globals pointer
startmem *ssa.Value
@@ -641,7 +634,7 @@ type state struct {
panics map[funcLine]*ssa.Block
// list of PPARAMOUT (return) variables.
- returns []ir.Node
+ returns []*ir.Name
cgoUnsafeArgs bool
hasdefer bool // whether the function contains a defer statement
@@ -693,7 +686,7 @@ func (s *state) Fatalf(msg string, args ...interface{}) {
func (s *state) Warnl(pos src.XPos, msg string, args ...interface{}) { s.f.Warnl(pos, msg, args...) }
func (s *state) Debug_checknil() bool { return s.f.Frontend().Debug_checknil() }
-func ssaMarker(name string) ir.Node {
+func ssaMarker(name string) *ir.Name {
return NewName(&types.Sym{Name: name})
}
@@ -780,7 +773,7 @@ func (s *state) newValue0(op ssa.Op, t *types.Type) *ssa.Value {
}
// newValue0A adds a new value with no arguments and an aux value to the current block.
-func (s *state) newValue0A(op ssa.Op, t *types.Type, aux interface{}) *ssa.Value {
+func (s *state) newValue0A(op ssa.Op, t *types.Type, aux ssa.Aux) *ssa.Value {
return s.curBlock.NewValue0A(s.peekPos(), op, t, aux)
}
@@ -795,14 +788,14 @@ func (s *state) newValue1(op ssa.Op, t *types.Type, arg *ssa.Value) *ssa.Value {
}
// newValue1A adds a new value with one argument and an aux value to the current block.
-func (s *state) newValue1A(op ssa.Op, t *types.Type, aux interface{}, arg *ssa.Value) *ssa.Value {
+func (s *state) newValue1A(op ssa.Op, t *types.Type, aux ssa.Aux, arg *ssa.Value) *ssa.Value {
return s.curBlock.NewValue1A(s.peekPos(), op, t, aux, arg)
}
// newValue1Apos adds a new value with one argument and an aux value to the current block.
// isStmt determines whether the created values may be a statement or not
// (i.e., false means never, yes means maybe).
-func (s *state) newValue1Apos(op ssa.Op, t *types.Type, aux interface{}, arg *ssa.Value, isStmt bool) *ssa.Value {
+func (s *state) newValue1Apos(op ssa.Op, t *types.Type, aux ssa.Aux, arg *ssa.Value, isStmt bool) *ssa.Value {
if isStmt {
return s.curBlock.NewValue1A(s.peekPos(), op, t, aux, arg)
}
@@ -820,14 +813,14 @@ func (s *state) newValue2(op ssa.Op, t *types.Type, arg0, arg1 *ssa.Value) *ssa.
}
// newValue2A adds a new value with two arguments and an aux value to the current block.
-func (s *state) newValue2A(op ssa.Op, t *types.Type, aux interface{}, arg0, arg1 *ssa.Value) *ssa.Value {
+func (s *state) newValue2A(op ssa.Op, t *types.Type, aux ssa.Aux, arg0, arg1 *ssa.Value) *ssa.Value {
return s.curBlock.NewValue2A(s.peekPos(), op, t, aux, arg0, arg1)
}
// newValue2Apos adds a new value with two arguments and an aux value to the current block.
// isStmt determines whether the created values may be a statement or not
// (i.e., false means never, yes means maybe).
-func (s *state) newValue2Apos(op ssa.Op, t *types.Type, aux interface{}, arg0, arg1 *ssa.Value, isStmt bool) *ssa.Value {
+func (s *state) newValue2Apos(op ssa.Op, t *types.Type, aux ssa.Aux, arg0, arg1 *ssa.Value, isStmt bool) *ssa.Value {
if isStmt {
return s.curBlock.NewValue2A(s.peekPos(), op, t, aux, arg0, arg1)
}
@@ -850,14 +843,14 @@ func (s *state) newValue3I(op ssa.Op, t *types.Type, aux int64, arg0, arg1, arg2
}
// newValue3A adds a new value with three arguments and an aux value to the current block.
-func (s *state) newValue3A(op ssa.Op, t *types.Type, aux interface{}, arg0, arg1, arg2 *ssa.Value) *ssa.Value {
+func (s *state) newValue3A(op ssa.Op, t *types.Type, aux ssa.Aux, arg0, arg1, arg2 *ssa.Value) *ssa.Value {
return s.curBlock.NewValue3A(s.peekPos(), op, t, aux, arg0, arg1, arg2)
}
// newValue3Apos adds a new value with three arguments and an aux value to the current block.
// isStmt determines whether the created values may be a statement or not
// (i.e., false means never, yes means maybe).
-func (s *state) newValue3Apos(op ssa.Op, t *types.Type, aux interface{}, arg0, arg1, arg2 *ssa.Value, isStmt bool) *ssa.Value {
+func (s *state) newValue3Apos(op ssa.Op, t *types.Type, aux ssa.Aux, arg0, arg1, arg2 *ssa.Value, isStmt bool) *ssa.Value {
if isStmt {
return s.curBlock.NewValue3A(s.peekPos(), op, t, aux, arg0, arg1, arg2)
}
@@ -880,7 +873,7 @@ func (s *state) entryNewValue0(op ssa.Op, t *types.Type) *ssa.Value {
}
// entryNewValue0A adds a new value with no arguments and an aux value to the entry block.
-func (s *state) entryNewValue0A(op ssa.Op, t *types.Type, aux interface{}) *ssa.Value {
+func (s *state) entryNewValue0A(op ssa.Op, t *types.Type, aux ssa.Aux) *ssa.Value {
return s.f.Entry.NewValue0A(src.NoXPos, op, t, aux)
}
@@ -895,7 +888,7 @@ func (s *state) entryNewValue1I(op ssa.Op, t *types.Type, auxint int64, arg *ssa
}
// entryNewValue1A adds a new value with one argument and an aux value to the entry block.
-func (s *state) entryNewValue1A(op ssa.Op, t *types.Type, aux interface{}, arg *ssa.Value) *ssa.Value {
+func (s *state) entryNewValue1A(op ssa.Op, t *types.Type, aux ssa.Aux, arg *ssa.Value) *ssa.Value {
return s.f.Entry.NewValue1A(src.NoXPos, op, t, aux, arg)
}
@@ -905,7 +898,7 @@ func (s *state) entryNewValue2(op ssa.Op, t *types.Type, arg0, arg1 *ssa.Value)
}
// entryNewValue2A adds a new value with two arguments and an aux value to the entry block.
-func (s *state) entryNewValue2A(op ssa.Op, t *types.Type, aux interface{}, arg0, arg1 *ssa.Value) *ssa.Value {
+func (s *state) entryNewValue2A(op ssa.Op, t *types.Type, aux ssa.Aux, arg0, arg1 *ssa.Value) *ssa.Value {
return s.f.Entry.NewValue2A(src.NoXPos, op, t, aux, arg0, arg1)
}
@@ -973,7 +966,45 @@ func (s *state) newValueOrSfCall2(op ssa.Op, t *types.Type, arg0, arg1 *ssa.Valu
return s.newValue2(op, t, arg0, arg1)
}
-func (s *state) instrument(t *types.Type, addr *ssa.Value, wr bool) {
+type instrumentKind uint8
+
+const (
+ instrumentRead = iota
+ instrumentWrite
+ instrumentMove
+)
+
+func (s *state) instrument(t *types.Type, addr *ssa.Value, kind instrumentKind) {
+ s.instrument2(t, addr, nil, kind)
+}
+
+// instrumentFields instruments a read/write operation on addr.
+// If it is instrumenting for MSAN and t is a struct type, it instruments
+// operation for each field, instead of for the whole struct.
+func (s *state) instrumentFields(t *types.Type, addr *ssa.Value, kind instrumentKind) {
+ if !base.Flag.MSan || !t.IsStruct() {
+ s.instrument(t, addr, kind)
+ return
+ }
+ for _, f := range t.Fields().Slice() {
+ if f.Sym.IsBlank() {
+ continue
+ }
+ offptr := s.newValue1I(ssa.OpOffPtr, types.NewPtr(f.Type), f.Offset, addr)
+ s.instrumentFields(f.Type, offptr, kind)
+ }
+}
+
+func (s *state) instrumentMove(t *types.Type, dst, src *ssa.Value) {
+ if base.Flag.MSan {
+ s.instrument2(t, dst, src, instrumentMove)
+ } else {
+ s.instrument(t, src, instrumentRead)
+ s.instrument(t, dst, instrumentWrite)
+ }
+}
+
+func (s *state) instrument2(t *types.Type, addr, addr2 *ssa.Value, kind instrumentKind) {
if !s.curfn.Func().InstrumentBody() {
return
}
@@ -990,33 +1021,54 @@ func (s *state) instrument(t *types.Type, addr *ssa.Value, wr bool) {
var fn *obj.LSym
needWidth := false
+ if addr2 != nil && kind != instrumentMove {
+ panic("instrument2: non-nil addr2 for non-move instrumentation")
+ }
+
if base.Flag.MSan {
- fn = msanread
- if wr {
+ switch kind {
+ case instrumentRead:
+ fn = msanread
+ case instrumentWrite:
fn = msanwrite
+ case instrumentMove:
+ fn = msanmove
+ default:
+ panic("unreachable")
}
needWidth = true
} else if base.Flag.Race && t.NumComponents(types.CountBlankFields) > 1 {
// for composite objects we have to write every address
// because a write might happen to any subobject.
// composites with only one element don't have subobjects, though.
- fn = racereadrange
- if wr {
+ switch kind {
+ case instrumentRead:
+ fn = racereadrange
+ case instrumentWrite:
fn = racewriterange
+ default:
+ panic("unreachable")
}
needWidth = true
} else if base.Flag.Race {
// for non-composite objects we can write just the start
// address, as any write must write the first byte.
- fn = raceread
- if wr {
+ switch kind {
+ case instrumentRead:
+ fn = raceread
+ case instrumentWrite:
fn = racewrite
+ default:
+ panic("unreachable")
}
} else {
panic("unreachable")
}
args := []*ssa.Value{addr}
+ if addr2 != nil {
+ args = append(args, addr2)
+ }
if needWidth {
args = append(args, s.constInt(types.Types[types.TUINTPTR], w))
}
@@ -1024,7 +1076,7 @@ func (s *state) instrument(t *types.Type, addr *ssa.Value, wr bool) {
}
func (s *state) load(t *types.Type, src *ssa.Value) *ssa.Value {
- s.instrument(t, src, false)
+ s.instrumentFields(t, src, instrumentRead)
return s.rawLoad(t, src)
}
@@ -1037,15 +1089,14 @@ func (s *state) store(t *types.Type, dst, val *ssa.Value) {
}
func (s *state) zero(t *types.Type, dst *ssa.Value) {
- s.instrument(t, dst, true)
+ s.instrument(t, dst, instrumentWrite)
store := s.newValue2I(ssa.OpZero, types.TypeMem, t.Size(), dst, s.mem())
store.Aux = t
s.vars[memVar] = store
}
func (s *state) move(t *types.Type, dst, src *ssa.Value) {
- s.instrument(t, src, false)
- s.instrument(t, dst, true)
+ s.instrumentMove(t, dst, src)
store := s.newValue3I(ssa.OpMove, types.TypeMem, t.Size(), dst, src, s.mem())
store.Aux = t
s.vars[memVar] = store
@@ -1079,7 +1130,7 @@ func (s *state) stmt(n ir.Node) {
s.stmtList(n.List())
// No-ops
- case ir.OEMPTY, ir.ODCLCONST, ir.ODCLTYPE, ir.OFALL:
+ case ir.ODCLCONST, ir.ODCLTYPE, ir.OFALL:
// Expression statements
case ir.OCALLFUNC:
@@ -1128,9 +1179,9 @@ func (s *state) stmt(n ir.Node) {
s.callResult(n.Left(), callGo)
case ir.OAS2DOTTYPE:
- res, resok := s.dottype(n.Right(), true)
+ res, resok := s.dottype(n.Rlist().First(), true)
deref := false
- if !canSSAType(n.Right().Type()) {
+ if !canSSAType(n.Rlist().First().Type()) {
if res.Op != ssa.OpLoad {
s.Fatalf("dottype of non-load")
}
@@ -1150,10 +1201,10 @@ func (s *state) stmt(n ir.Node) {
case ir.OAS2FUNC:
// We come here only when it is an intrinsic call returning two values.
- if !isIntrinsicCall(n.Right()) {
- s.Fatalf("non-intrinsic AS2FUNC not expanded %v", n.Right())
+ if !isIntrinsicCall(n.Rlist().First()) {
+ s.Fatalf("non-intrinsic AS2FUNC not expanded %v", n.Rlist().First())
}
- v := s.intrinsicCall(n.Right())
+ v := s.intrinsicCall(n.Rlist().First())
v1 := s.newValue1(ssa.OpSelect0, n.List().First().Type(), v)
v2 := s.newValue1(ssa.OpSelect1, n.List().Second().Type(), v)
s.assign(n.List().First(), v1, false, 0)
@@ -1169,11 +1220,6 @@ func (s *state) stmt(n ir.Node) {
sym := n.Sym()
lab := s.label(sym)
- // Associate label with its control flow node, if any
- if ctl := labeledControl(n); ctl != nil {
- s.labeledNodes[ctl] = lab
- }
-
// The label might already have a target block via a goto.
if lab.target == nil {
lab.target = s.f.NewBlock(ssa.BlockPlain)
@@ -1284,7 +1330,7 @@ func (s *state) stmt(n ir.Node) {
// We're assigning a slicing operation back to its source.
// Don't write back fields we aren't changing. See issue #14855.
i, j, k := rhs.SliceBounds()
- if i != nil && (i.Op() == ir.OLITERAL && i.Val().Kind() == constant.Int && i.Int64Val() == 0) {
+ if i != nil && (i.Op() == ir.OLITERAL && i.Val().Kind() == constant.Int && ir.Int64Val(i) == 0) {
// [0:...] is the same as [:...]
i = nil
}
@@ -1314,7 +1360,7 @@ func (s *state) stmt(n ir.Node) {
case ir.OIF:
if ir.IsConst(n.Left(), constant.Bool) {
s.stmtList(n.Left().Init())
- if n.Left().BoolVal() {
+ if ir.BoolVal(n.Left()) {
s.stmtList(n.Body())
} else {
s.stmtList(n.Rlist())
@@ -1431,9 +1477,10 @@ func (s *state) stmt(n ir.Node) {
prevBreak := s.breakTo
s.continueTo = bIncr
s.breakTo = bEnd
- lab := s.labeledNodes[n]
- if lab != nil {
+ var lab *ssaLabel
+ if sym := n.Sym(); sym != nil {
// labeled for loop
+ lab = s.label(sym)
lab.continueTarget = bIncr
lab.breakTarget = bEnd
}
@@ -1489,9 +1536,10 @@ func (s *state) stmt(n ir.Node) {
prevBreak := s.breakTo
s.breakTo = bEnd
- lab := s.labeledNodes[n]
- if lab != nil {
+ var lab *ssaLabel
+ if sym := n.Sym(); sym != nil {
// labeled
+ lab = s.label(sym)
lab.breakTarget = bEnd
}
@@ -1515,7 +1563,7 @@ func (s *state) stmt(n ir.Node) {
case ir.OVARDEF:
if !s.canSSA(n.Left()) {
- s.vars[memVar] = s.newValue1Apos(ssa.OpVarDef, types.TypeMem, n.Left(), s.mem(), false)
+ s.vars[memVar] = s.newValue1Apos(ssa.OpVarDef, types.TypeMem, n.Left().(*ir.Name), s.mem(), false)
}
case ir.OVARKILL:
// Insert a varkill op to record that a variable is no longer live.
@@ -1523,7 +1571,7 @@ func (s *state) stmt(n ir.Node) {
// varkill in the store chain is enough to keep it correctly ordered
// with respect to call ops.
if !s.canSSA(n.Left()) {
- s.vars[memVar] = s.newValue1Apos(ssa.OpVarKill, types.TypeMem, n.Left(), s.mem(), false)
+ s.vars[memVar] = s.newValue1Apos(ssa.OpVarKill, types.TypeMem, n.Left().(*ir.Name), s.mem(), false)
}
case ir.OVARLIVE:
@@ -1536,7 +1584,7 @@ func (s *state) stmt(n ir.Node) {
default:
s.Fatalf("VARLIVE variable %v must be Auto or Arg", n.Left())
}
- s.vars[memVar] = s.newValue1A(ssa.OpVarLive, types.TypeMem, n.Left(), s.mem())
+ s.vars[memVar] = s.newValue1A(ssa.OpVarLive, types.TypeMem, n.Left().(*ir.Name), s.mem())
case ir.OCHECKNIL:
p := s.expr(n.Left())
@@ -1576,7 +1624,7 @@ func (s *state) exit() *ssa.Block {
// Run exit code. Typically, this code copies heap-allocated PPARAMOUT
// variables back to the stack.
- s.stmtList(s.curfn.Func().Exit)
+ s.stmtList(s.curfn.Exit)
// Store SSAable PPARAMOUT variables back to stack locations.
for _, n := range s.returns {
@@ -1602,7 +1650,7 @@ func (s *state) exit() *ssa.Block {
type opAndType struct {
op ir.Op
- etype types.EType
+ etype types.Kind
}
var opToSSA = map[opAndType]ssa.Op{
@@ -1777,8 +1825,8 @@ var opToSSA = map[opAndType]ssa.Op{
opAndType{ir.OLE, types.TFLOAT32}: ssa.OpLeq32F,
}
-func (s *state) concreteEtype(t *types.Type) types.EType {
- e := t.Etype
+func (s *state) concreteEtype(t *types.Type) types.Kind {
+ e := t.Kind()
switch e {
default:
return e
@@ -1810,7 +1858,7 @@ func (s *state) ssaOp(op ir.Op, t *types.Type) ssa.Op {
}
func floatForComplex(t *types.Type) *types.Type {
- switch t.Etype {
+ switch t.Kind() {
case types.TCOMPLEX64:
return types.Types[types.TFLOAT32]
case types.TCOMPLEX128:
@@ -1821,7 +1869,7 @@ func floatForComplex(t *types.Type) *types.Type {
}
func complexForFloat(t *types.Type) *types.Type {
- switch t.Etype {
+ switch t.Kind() {
case types.TFLOAT32:
return types.Types[types.TCOMPLEX64]
case types.TFLOAT64:
@@ -1833,19 +1881,19 @@ func complexForFloat(t *types.Type) *types.Type {
type opAndTwoTypes struct {
op ir.Op
- etype1 types.EType
- etype2 types.EType
+ etype1 types.Kind
+ etype2 types.Kind
}
type twoTypes struct {
- etype1 types.EType
- etype2 types.EType
+ etype1 types.Kind
+ etype2 types.Kind
}
type twoOpsAndType struct {
op1 ssa.Op
op2 ssa.Op
- intermediateType types.EType
+ intermediateType types.Kind
}
var fpConvOpToSSA = map[twoTypes]twoOpsAndType{
@@ -2036,7 +2084,7 @@ func (s *state) expr(n ir.Node) *ssa.Value {
}
addr := s.addr(n)
return s.load(n.Type(), addr)
- case ir.OCLOSUREVAR:
+ case ir.OCLOSUREREAD:
addr := s.addr(n)
return s.load(n.Type(), addr)
case ir.ONIL:
@@ -2052,7 +2100,7 @@ func (s *state) expr(n ir.Node) *ssa.Value {
case ir.OLITERAL:
switch u := n.Val(); u.Kind() {
case constant.Int:
- i := ir.Int64Val(n.Type(), u)
+ i := ir.IntVal(n.Type(), u)
switch n.Type().Size() {
case 1:
return s.constInt8(n.Type(), int8(i))
@@ -2071,7 +2119,7 @@ func (s *state) expr(n ir.Node) *ssa.Value {
if i == "" {
return s.constEmptyString(n.Type())
}
- return s.entryNewValue0A(ssa.OpConstString, n.Type(), i)
+ return s.entryNewValue0A(ssa.OpConstString, n.Type(), ssa.StringToAux(i))
case constant.Bool:
return s.constBool(constant.BoolVal(u))
case constant.Float:
@@ -2114,6 +2162,9 @@ func (s *state) expr(n ir.Node) *ssa.Value {
// Assume everything will work out, so set up our return value.
// Anything interesting that happens from here is a fatal.
x := s.expr(n.Left())
+ if to == from {
+ return x
+ }
// Special case for not confusing GC and liveness.
// We don't want pointers accidentally classified
@@ -2126,12 +2177,12 @@ func (s *state) expr(n ir.Node) *ssa.Value {
v := s.newValue1(ssa.OpCopy, to, x) // ensure that v has the right type
// CONVNOP closure
- if to.Etype == types.TFUNC && from.IsPtrShaped() {
+ if to.Kind() == types.TFUNC && from.IsPtrShaped() {
return v
}
// named <--> unnamed type or typed <--> untyped const
- if from.Etype == to.Etype {
+ if from.Kind() == to.Kind() {
return v
}
@@ -2141,7 +2192,7 @@ func (s *state) expr(n ir.Node) *ssa.Value {
}
// map <--> *hmap
- if to.Etype == types.TMAP && from.IsPtr() &&
+ if to.Kind() == types.TMAP && from.IsPtr() &&
to.MapType().Hmap == from.Elem() {
return v
}
@@ -2152,8 +2203,8 @@ func (s *state) expr(n ir.Node) *ssa.Value {
s.Fatalf("CONVNOP width mismatch %v (%d) -> %v (%d)\n", from, from.Width, to, to.Width)
return nil
}
- if etypesign(from.Etype) != etypesign(to.Etype) {
- s.Fatalf("CONVNOP sign mismatch %v (%s) -> %v (%s)\n", from, from.Etype, to, to.Etype)
+ if etypesign(from.Kind()) != etypesign(to.Kind()) {
+ s.Fatalf("CONVNOP sign mismatch %v (%s) -> %v (%s)\n", from, from.Kind(), to, to.Kind())
return nil
}
@@ -2164,7 +2215,7 @@ func (s *state) expr(n ir.Node) *ssa.Value {
return v
}
- if etypesign(from.Etype) == 0 {
+ if etypesign(from.Kind()) == 0 {
s.Fatalf("CONVNOP unrecognized non-integer %v -> %v\n", from, to)
return nil
}
@@ -2340,7 +2391,7 @@ func (s *state) expr(n ir.Node) *ssa.Value {
s.newValueOrSfCall1(op, ttp, s.newValue1(ssa.OpComplexImag, ftp, x)))
}
- s.Fatalf("unhandled OCONV %s -> %s", n.Left().Type().Etype, n.Type().Etype)
+ s.Fatalf("unhandled OCONV %s -> %s", n.Left().Type().Kind(), n.Type().Kind())
return nil
case ir.ODOTTYPE:
@@ -2632,7 +2683,7 @@ func (s *state) expr(n ir.Node) *ssa.Value {
// Replace "abc"[1] with 'b'.
// Delayed until now because "abc"[1] is not an ideal constant.
// See test/fixedbugs/issue11370.go.
- return s.newValue0I(ssa.OpConst8, types.Types[types.TUINT8], int64(int8(n.Left().StringVal()[n.Right().Int64Val()])))
+ return s.newValue0I(ssa.OpConst8, types.Types[types.TUINT8], int64(int8(ir.StringVal(n.Left())[ir.Int64Val(n.Right())])))
}
a := s.expr(n.Left())
i := s.expr(n.Right())
@@ -2641,7 +2692,7 @@ func (s *state) expr(n ir.Node) *ssa.Value {
ptrtyp := s.f.Config.Types.BytePtr
ptr := s.newValue1(ssa.OpStringPtr, ptrtyp, a)
if ir.IsConst(n.Right(), constant.Int) {
- ptr = s.newValue1I(ssa.OpOffPtr, ptrtyp, n.Right().Int64Val(), ptr)
+ ptr = s.newValue1I(ssa.OpOffPtr, ptrtyp, ir.Int64Val(n.Right()), ptr)
} else {
ptr = s.newValue2(ssa.OpAddPtr, ptrtyp, ptr, i)
}
@@ -2874,7 +2925,7 @@ func (s *state) append(n ir.Node, inplace bool) *ssa.Value {
if inplace {
if sn.Op() == ir.ONAME && sn.Class() != ir.PEXTERN {
// Tell liveness we're about to build a new slice
- s.vars[memVar] = s.newValue1A(ssa.OpVarDef, types.TypeMem, sn, s.mem())
+ s.vars[memVar] = s.newValue1A(ssa.OpVarDef, types.TypeMem, sn.(*ir.Name), s.mem())
}
capaddr := s.newValue1I(ssa.OpOffPtr, s.f.Config.Types.IntPtr, sliceCapOffset, addr)
s.store(types.Types[types.TINT], capaddr, r[2])
@@ -2977,6 +3028,10 @@ func (s *state) condBranch(cond ir.Node, yes, no *ssa.Block, likely int8) {
s.stmtList(cond.Init())
s.condBranch(cond.Left(), no, yes, -likely)
return
+ case ir.OCONVNOP:
+ s.stmtList(cond.Init())
+ s.condBranch(cond.Left(), yes, no, likely)
+ return
}
c := s.expr(cond)
b := s.endBlock()
@@ -3080,7 +3135,7 @@ func (s *state) assign(left ir.Node, right *ssa.Value, deref bool, skip skipMask
// If this assignment clobbers an entire local variable, then emit
// OpVarDef so liveness analysis knows the variable is redefined.
if base := clobberBase(left); base.Op() == ir.ONAME && base.Class() != ir.PEXTERN && skip == 0 {
- s.vars[memVar] = s.newValue1Apos(ssa.OpVarDef, types.TypeMem, base, s.mem(), !ir.IsAutoTmp(base))
+ s.vars[memVar] = s.newValue1Apos(ssa.OpVarDef, types.TypeMem, base.(*ir.Name), s.mem(), !ir.IsAutoTmp(base))
}
// Left is not ssa-able. Compute its address.
@@ -3183,7 +3238,7 @@ const (
type sfRtCallDef struct {
rtfn *obj.LSym
- rtype types.EType
+ rtype types.Kind
}
var softFloatOps map[ssa.Op]sfRtCallDef
@@ -3478,9 +3533,9 @@ func init() {
},
sys.AMD64, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X)
- type atomicOpEmitter func(s *state, n ir.Node, args []*ssa.Value, op ssa.Op, typ types.EType)
+ type atomicOpEmitter func(s *state, n ir.Node, args []*ssa.Value, op ssa.Op, typ types.Kind)
- makeAtomicGuardedIntrinsicARM64 := func(op0, op1 ssa.Op, typ, rtyp types.EType, emit atomicOpEmitter) intrinsicBuilder {
+ makeAtomicGuardedIntrinsicARM64 := func(op0, op1 ssa.Op, typ, rtyp types.Kind, emit atomicOpEmitter) intrinsicBuilder {
return func(s *state, n ir.Node, args []*ssa.Value) *ssa.Value {
// Target Atomic feature is identified by dynamic detection
@@ -3516,7 +3571,7 @@ func init() {
}
}
- atomicXchgXaddEmitterARM64 := func(s *state, n ir.Node, args []*ssa.Value, op ssa.Op, typ types.EType) {
+ atomicXchgXaddEmitterARM64 := func(s *state, n ir.Node, args []*ssa.Value, op ssa.Op, typ types.Kind) {
v := s.newValue3(op, types.NewTuple(types.Types[typ], types.TypeMem), args[0], args[1], s.mem())
s.vars[memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v)
s.vars[n] = s.newValue1(ssa.OpSelect0, types.Types[typ], v)
@@ -3572,7 +3627,7 @@ func init() {
},
sys.PPC64)
- atomicCasEmitterARM64 := func(s *state, n ir.Node, args []*ssa.Value, op ssa.Op, typ types.EType) {
+ atomicCasEmitterARM64 := func(s *state, n ir.Node, args []*ssa.Value, op ssa.Op, typ types.Kind) {
v := s.newValue4(op, types.NewTuple(types.Types[types.TBOOL], types.TypeMem), args[0], args[1], args[2], s.mem())
s.vars[memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v)
s.vars[n] = s.newValue1(ssa.OpSelect0, types.Types[typ], v)
@@ -3610,7 +3665,7 @@ func init() {
},
sys.AMD64, sys.MIPS, sys.PPC64, sys.S390X)
- atomicAndOrEmitterARM64 := func(s *state, n ir.Node, args []*ssa.Value, op ssa.Op, typ types.EType) {
+ atomicAndOrEmitterARM64 := func(s *state, n ir.Node, args []*ssa.Value, op ssa.Op, typ types.Kind) {
s.vars[memVar] = s.newValue3(op, types.TypeMem, args[0], args[1], s.mem())
}
@@ -4131,7 +4186,7 @@ func findIntrinsic(sym *types.Sym) intrinsicBuilder {
return nil
}
pkg := sym.Pkg.Path
- if sym.Pkg == ir.LocalPkg {
+ if sym.Pkg == types.LocalPkg {
pkg = base.Ctxt.Pkgpath
}
if base.Flag.Race && pkg == "sync/atomic" {
@@ -4157,10 +4212,14 @@ func findIntrinsic(sym *types.Sym) intrinsicBuilder {
}
func isIntrinsicCall(n ir.Node) bool {
- if n == nil || n.Left() == nil {
+ if n == nil {
return false
}
- return findIntrinsic(n.Left().Sym()) != nil
+ name, ok := n.Left().(*ir.Name)
+ if !ok {
+ return false
+ }
+ return findIntrinsic(name.Sym()) != nil
}
// intrinsicCall converts a call to a recognized intrinsic function into the intrinsic SSA operation.
@@ -4224,7 +4283,7 @@ func (s *state) openDeferRecord(n ir.Node) {
s.stmtList(n.List())
var args []*ssa.Value
- var argNodes []ir.Node
+ var argNodes []*ir.Name
opendefer := &openDeferInfo{
n: n,
@@ -4236,7 +4295,7 @@ func (s *state) openDeferRecord(n ir.Node) {
// call the function directly if it is a static function.
closureVal := s.expr(fn)
closure := s.openDeferSave(nil, fn.Type(), closureVal)
- opendefer.closureNode = closure.Aux.(ir.Node)
+ opendefer.closureNode = closure.Aux.(*ir.Name)
if !(fn.Op() == ir.ONAME && fn.Class() == ir.PFUNC) {
opendefer.closure = closure
}
@@ -4249,7 +4308,7 @@ func (s *state) openDeferRecord(n ir.Node) {
// runtime panic code to use. But in the defer exit code, we will
// call the method directly.
closure := s.openDeferSave(nil, fn.Type(), closureVal)
- opendefer.closureNode = closure.Aux.(ir.Node)
+ opendefer.closureNode = closure.Aux.(*ir.Name)
} else {
if fn.Op() != ir.ODOTINTER {
base.Fatalf("OCALLINTER: n.Left not an ODOTINTER: %v", fn.Op())
@@ -4259,8 +4318,8 @@ func (s *state) openDeferRecord(n ir.Node) {
// Important to get the receiver type correct, so it is recognized
// as a pointer for GC purposes.
opendefer.rcvr = s.openDeferSave(nil, fn.Type().Recv().Type, rcvr)
- opendefer.closureNode = opendefer.closure.Aux.(ir.Node)
- opendefer.rcvrNode = opendefer.rcvr.Aux.(ir.Node)
+ opendefer.closureNode = opendefer.closure.Aux.(*ir.Name)
+ opendefer.rcvrNode = opendefer.rcvr.Aux.(*ir.Name)
}
for _, argn := range n.Rlist().Slice() {
var v *ssa.Value
@@ -4270,7 +4329,7 @@ func (s *state) openDeferRecord(n ir.Node) {
v = s.openDeferSave(argn, argn.Type(), nil)
}
args = append(args, v)
- argNodes = append(argNodes, v.Aux.(ir.Node))
+ argNodes = append(argNodes, v.Aux.(*ir.Name))
}
opendefer.argVals = args
opendefer.argNodes = argNodes
@@ -4301,7 +4360,7 @@ func (s *state) openDeferSave(n ir.Node, t *types.Type, val *ssa.Value) *ssa.Val
pos = n.Pos()
}
argTemp := tempAt(pos.WithNotStmt(), s.curfn, t)
- argTemp.Name().SetOpenDeferSlot(true)
+ argTemp.SetOpenDeferSlot(true)
var addrArgTemp *ssa.Value
// Use OpVarLive to make sure stack slots for the args, etc. are not
// removed by dead-store elimination
@@ -4327,7 +4386,7 @@ func (s *state) openDeferSave(n ir.Node, t *types.Type, val *ssa.Value) *ssa.Val
// Therefore, we must make sure it is zeroed out in the entry
// block if it contains pointers, else GC may wrongly follow an
// uninitialized pointer value.
- argTemp.Name().SetNeedzero(true)
+ argTemp.SetNeedzero(true)
}
if !canSSA {
a := s.addr(n)
@@ -4458,11 +4517,11 @@ func (s *state) openDeferExit() {
// use the first call of the last defer exit to compute liveness
// for the deferreturn, so we want all stack slots to be live.
if r.closureNode != nil {
- s.vars[memVar] = s.newValue1Apos(ssa.OpVarLive, types.TypeMem, r.closureNode, s.mem(), false)
+ s.vars[memVar] = s.newValue1Apos(ssa.OpVarLive, types.TypeMem, r.closureNode.(*ir.Name), s.mem(), false)
}
if r.rcvrNode != nil {
if r.rcvrNode.Type().HasPointers() {
- s.vars[memVar] = s.newValue1Apos(ssa.OpVarLive, types.TypeMem, r.rcvrNode, s.mem(), false)
+ s.vars[memVar] = s.newValue1Apos(ssa.OpVarLive, types.TypeMem, r.rcvrNode.(*ir.Name), s.mem(), false)
}
}
for _, argNode := range r.argNodes {
@@ -4795,7 +4854,7 @@ func (s *state) getMethodClosure(fn ir.Node) *ssa.Value {
// We get back an SSA value representing &sync.(*Mutex).Unlock·f.
// We can then pass that to defer or go.
n2 := ir.NewNameAt(fn.Pos(), fn.Sym())
- n2.Name().Curfn = s.curfn
+ n2.Curfn = s.curfn
n2.SetClass(ir.PFUNC)
// n2.Sym already existed, so it's already marked as a function.
n2.SetPos(fn.Pos())
@@ -4817,7 +4876,7 @@ func (s *state) getClosureAndRcvr(fn ir.Node) (*ssa.Value, *ssa.Value) {
// etypesign returns the signed-ness of e, for integer/pointer etypes.
// -1 means signed, +1 means unsigned, 0 means non-integer/non-pointer.
-func etypesign(e types.EType) int8 {
+func etypesign(e types.Kind) int8 {
switch e {
case types.TINT8, types.TINT16, types.TINT32, types.TINT64, types.TINT:
return -1
@@ -4838,6 +4897,7 @@ func (s *state) addr(n ir.Node) *ssa.Value {
t := types.NewPtr(n.Type())
switch n.Op() {
case ir.ONAME:
+ n := n.(*ir.Name)
switch n.Class() {
case ir.PEXTERN:
// global variable
@@ -4906,10 +4966,13 @@ func (s *state) addr(n ir.Node) *ssa.Value {
case ir.ODOTPTR:
p := s.exprPtr(n.Left(), n.Bounded(), n.Pos())
return s.newValue1I(ssa.OpOffPtr, t, n.Offset(), p)
- case ir.OCLOSUREVAR:
+ case ir.OCLOSUREREAD:
return s.newValue1I(ssa.OpOffPtr, t, n.Offset(),
s.entryNewValue0(ssa.OpGetClosurePtr, s.f.Config.Types.BytePtr))
case ir.OCONVNOP:
+ if n.Type() == n.Left().Type() {
+ return s.addr(n.Left())
+ }
addr := s.addr(n.Left())
return s.newValue1(ssa.OpCopy, t, addr) // ensure that addr has the right type
case ir.OCALLFUNC, ir.OCALLINTER, ir.OCALLMETH:
@@ -4987,7 +5050,7 @@ func canSSAType(t *types.Type) bool {
// Too big and we'll introduce too much register pressure.
return false
}
- switch t.Etype {
+ switch t.Kind() {
case types.TARRAY:
// We can't do larger arrays because dynamic indexing is
// not supported on SSA variables.
@@ -5028,7 +5091,7 @@ func (s *state) exprPtr(n ir.Node, bounded bool, lineno src.XPos) *ssa.Value {
// Used only for automatically inserted nil checks,
// not for user code like 'x != nil'.
func (s *state) nilCheck(ptr *ssa.Value) {
- if base.Debug.DisableNil != 0 || s.curfn.Func().NilCheckDisabled() {
+ if base.Debug.DisableNil != 0 || s.curfn.NilCheckDisabled() {
return
}
s.newValue2(ssa.OpNilCheck, types.TypeVoid, ptr, s.mem())
@@ -5259,7 +5322,7 @@ func (s *state) rtcall(fn *obj.LSym, returns bool, results []*types.Type, args .
// do *left = right for type t.
func (s *state) storeType(t *types.Type, left, right *ssa.Value, skip skipMask, leftIsStmt bool) {
- s.instrument(t, left, true)
+ s.instrument(t, left, instrumentWrite)
if skip == 0 && (!t.HasPointers() || ssa.IsStackAddr(left)) {
// Known to not have write barrier. Store the whole type.
@@ -5948,7 +6011,7 @@ func (s *state) dottype(n ir.Node, commaok bool) (res, resok *ssa.Value) {
// unSSAable type, use temporary.
// TODO: get rid of some of these temporaries.
tmp = tempAt(n.Pos(), s.curfn, n.Type())
- s.vars[memVar] = s.newValue1A(ssa.OpVarDef, types.TypeMem, tmp, s.mem())
+ s.vars[memVar] = s.newValue1A(ssa.OpVarDef, types.TypeMem, tmp.(*ir.Name), s.mem())
addr = s.addr(tmp)
}
@@ -6024,7 +6087,7 @@ func (s *state) dottype(n ir.Node, commaok bool) (res, resok *ssa.Value) {
delete(s.vars, valVar)
} else {
res = s.load(n.Type(), addr)
- s.vars[memVar] = s.newValue1A(ssa.OpVarKill, types.TypeMem, tmp, s.mem())
+ s.vars[memVar] = s.newValue1A(ssa.OpVarKill, types.TypeMem, tmp.(*ir.Name), s.mem())
}
resok = s.variable(okVar, types.Types[types.TBOOL])
delete(s.vars, okVar)
@@ -6048,7 +6111,7 @@ func (s *state) variable(name ir.Node, t *types.Type) *ssa.Value {
}
// Make a FwdRef, which records a value that's live on block input.
// We'll find the matching definition as part of insertPhis.
- v = s.newValue0A(ssa.OpFwdRef, t, name)
+ v = s.newValue0A(ssa.OpFwdRef, t, FwdRefAux{N: name})
s.fwdVars[name] = v
s.addNamedValue(name, v)
return v
@@ -6075,7 +6138,7 @@ func (s *state) addNamedValue(n ir.Node, v *ssa.Value) {
if n.Class() == ir.PAUTO && n.Offset() != 0 {
s.Fatalf("AUTO var with offset %v %d", n, n.Offset())
}
- loc := ssa.LocalSlot{N: n, Type: n.Type(), Off: 0}
+ loc := ssa.LocalSlot{N: n.Name(), Type: n.Type(), Off: 0}
values, ok := s.f.NamedValues[loc]
if !ok {
s.f.Names = append(s.f.Names, loc)
@@ -6193,17 +6256,17 @@ func (s *SSAGenState) DebugFriendlySetPosFrom(v *ssa.Value) {
}
}
-// byXoffset implements sort.Interface for []*Node using Xoffset as the ordering.
-type byXoffset []ir.Node
+// byXoffset implements sort.Interface for []*ir.Name using Xoffset as the ordering.
+type byXoffset []*ir.Name
func (s byXoffset) Len() int { return len(s) }
func (s byXoffset) Less(i, j int) bool { return s[i].Offset() < s[j].Offset() }
func (s byXoffset) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func emitStackObjects(e *ssafn, pp *Progs) {
- var vars []ir.Node
- for _, n := range e.curfn.Func().Dcl {
- if livenessShouldTrack(n) && n.Name().Addrtaken() {
+ var vars []*ir.Name
+ for _, n := range e.curfn.Dcl {
+ if livenessShouldTrack(n) && n.Addrtaken() {
vars = append(vars, n)
}
}
@@ -6216,7 +6279,7 @@ func emitStackObjects(e *ssafn, pp *Progs) {
// Populate the stack object data.
// Format must match runtime/stack.go:stackObjectRecord.
- x := e.curfn.Func().LSym.Func().StackObjects
+ x := e.curfn.LSym.Func().StackObjects
off := 0
off = duintptr(x, off, uint64(len(vars)))
for _, v := range vars {
@@ -6253,7 +6316,7 @@ func genssa(f *ssa.Func, pp *Progs) {
s.livenessMap = liveness(e, f, pp)
emitStackObjects(e, pp)
- openDeferInfo := e.curfn.Func().LSym.Func().OpenCodedDeferInfo
+ openDeferInfo := e.curfn.LSym.Func().OpenCodedDeferInfo
if openDeferInfo != nil {
// This function uses open-coded defers -- write out the funcdata
// info that we computed at the end of genssa.
@@ -6458,7 +6521,7 @@ func genssa(f *ssa.Func, pp *Progs) {
// some of the inline marks.
// Use this instruction instead.
p.Pos = p.Pos.WithIsStmt() // promote position to a statement
- pp.curfn.Func().LSym.Func().AddInlMark(p, inlMarks[m])
+ pp.curfn.LSym.Func().AddInlMark(p, inlMarks[m])
// Make the inline mark a real nop, so it doesn't generate any code.
m.As = obj.ANOP
m.Pos = src.NoXPos
@@ -6470,14 +6533,14 @@ func genssa(f *ssa.Func, pp *Progs) {
// Any unmatched inline marks now need to be added to the inlining tree (and will generate a nop instruction).
for _, p := range inlMarkList {
if p.As != obj.ANOP {
- pp.curfn.Func().LSym.Func().AddInlMark(p, inlMarks[p])
+ pp.curfn.LSym.Func().AddInlMark(p, inlMarks[p])
}
}
}
if base.Ctxt.Flag_locationlists {
debugInfo := ssa.BuildFuncDebug(base.Ctxt, f, base.Debug.LocationLists > 1, stackOffset)
- e.curfn.Func().DebugInfo = debugInfo
+ e.curfn.DebugInfo = debugInfo
bstart := s.bstart
// Note that at this moment, Prog.Pc is a sequence number; it's
// not a real PC until after assembly, so this mapping has to
@@ -6491,7 +6554,7 @@ func genssa(f *ssa.Func, pp *Progs) {
}
return bstart[b].Pc
case ssa.BlockEnd.ID:
- return e.curfn.Func().LSym.Size
+ return e.curfn.LSym.Size
default:
return valueToProgAfter[v].Pc
}
@@ -6589,8 +6652,8 @@ func defframe(s *SSAGenState, e *ssafn) {
var state uint32
// Iterate through declarations. They are sorted in decreasing Xoffset order.
- for _, n := range e.curfn.Func().Dcl {
- if !n.Name().Needzero() {
+ for _, n := range e.curfn.Dcl {
+ if !n.Needzero() {
continue
}
if n.Class() != ir.PAUTO {
@@ -6677,10 +6740,10 @@ func AddAux2(a *obj.Addr, v *ssa.Value, offset int64) {
case *obj.LSym:
a.Name = obj.NAME_EXTERN
a.Sym = n
- case ir.Node:
+ case *ir.Name:
if n.Class() == ir.PPARAM || n.Class() == ir.PPARAMOUT {
a.Name = obj.NAME_PARAM
- a.Sym = n.Orig().Sym().Linksym()
+ a.Sym = ir.Orig(n).Sym().Linksym()
a.Offset += n.Offset()
break
}
@@ -6954,7 +7017,7 @@ func fieldIdx(n ir.Node) int {
// ssafn holds frontend information about a function that the backend is processing.
// It also exports a bunch of compiler services for the ssa backend.
type ssafn struct {
- curfn ir.Node
+ curfn *ir.Func
strings map[string]*obj.LSym // map from constant string to data symbols
scratchFpMem ir.Node // temp for floating point register / memory moves on some architectures
stksize int64 // stack size for current frame
@@ -6976,9 +7039,8 @@ func (e *ssafn) StringData(s string) *obj.LSym {
return data
}
-func (e *ssafn) Auto(pos src.XPos, t *types.Type) ir.Node {
- n := tempAt(pos, e.curfn, t) // Note: adds new auto to e.curfn.Func.Dcl list
- return n
+func (e *ssafn) Auto(pos src.XPos, t *types.Type) *ir.Name {
+ return tempAt(pos, e.curfn, t) // Note: adds new auto to e.curfn.Func.Dcl list
}
func (e *ssafn) SplitString(name ssa.LocalSlot) (ssa.LocalSlot, ssa.LocalSlot) {
@@ -7070,15 +7132,15 @@ func (e *ssafn) SplitSlot(parent *ssa.LocalSlot, suffix string, offset int64, t
return ssa.LocalSlot{N: node, Type: t, Off: parent.Off + offset}
}
- s := &types.Sym{Name: node.Sym().Name + suffix, Pkg: ir.LocalPkg}
+ s := &types.Sym{Name: node.Sym().Name + suffix, Pkg: types.LocalPkg}
n := ir.NewNameAt(parent.N.Pos(), s)
s.Def = n
ir.AsNode(s.Def).Name().SetUsed(true)
n.SetType(t)
n.SetClass(ir.PAUTO)
n.SetEsc(EscNever)
- n.Name().Curfn = e.curfn
- e.curfn.Func().Dcl = append(e.curfn.Func().Dcl, n)
+ n.Curfn = e.curfn
+ e.curfn.Dcl = append(e.curfn.Dcl, n)
dowidth(t)
return ssa.LocalSlot{N: n, Type: t, Off: 0, SplitOf: parent, SplitOffset: offset}
}
@@ -7141,7 +7203,7 @@ func (e *ssafn) Syslook(name string) *obj.LSym {
}
func (e *ssafn) SetWBPos(pos src.XPos) {
- e.curfn.Func().SetWBPos(pos)
+ e.curfn.SetWBPos(pos)
}
func (e *ssafn) MyImportPath() string {
diff --git a/src/cmd/compile/internal/gc/subr.go b/src/cmd/compile/internal/gc/subr.go
index fcda219737..e05a124b29 100644
--- a/src/cmd/compile/internal/gc/subr.go
+++ b/src/cmd/compile/internal/gc/subr.go
@@ -69,7 +69,7 @@ func setlineno(n ir.Node) src.XPos {
}
func lookup(name string) *types.Sym {
- return ir.LocalPkg.Lookup(name)
+ return types.LocalPkg.Lookup(name)
}
// lookupN looks up the symbol starting with prefix and ending with
@@ -78,7 +78,7 @@ func lookupN(prefix string, n int) *types.Sym {
var buf [20]byte // plenty long enough for all current users
copy(buf[:], prefix)
b := strconv.AppendInt(buf[:len(prefix)], int64(n), 10)
- return ir.LocalPkg.LookupBytes(b)
+ return types.LocalPkg.LookupBytes(b)
}
// autolabel generates a new Name node for use with
@@ -95,14 +95,14 @@ func autolabel(prefix string) *types.Sym {
if Curfn == nil {
base.Fatalf("autolabel outside function")
}
- n := fn.Func().Label
- fn.Func().Label++
+ n := fn.Label
+ fn.Label++
return lookupN(prefix, int(n))
}
// find all the exported symbols in package opkg
// and make them available in the current package
-func importdot(opkg *types.Pkg, pack ir.Node) {
+func importdot(opkg *types.Pkg, pack *ir.PkgName) {
n := 0
for _, s := range opkg.Syms {
if s.Def == nil {
@@ -124,7 +124,7 @@ func importdot(opkg *types.Pkg, pack ir.Node) {
ir.Dump("s1def", ir.AsNode(s1.Def))
base.Fatalf("missing Name")
}
- ir.AsNode(s1.Def).Name().Pack = pack
+ ir.AsNode(s1.Def).Name().PkgName = pack
s1.Origpkg = opkg
n++
}
@@ -136,9 +136,9 @@ func importdot(opkg *types.Pkg, pack ir.Node) {
}
// newname returns a new ONAME Node associated with symbol s.
-func NewName(s *types.Sym) ir.Node {
+func NewName(s *types.Sym) *ir.Name {
n := ir.NewNameAt(base.Pos, s)
- n.Name().Curfn = Curfn
+ n.Curfn = Curfn
return n
}
@@ -181,43 +181,7 @@ func nodstr(s string) ir.Node {
return ir.NewLiteral(constant.MakeString(s))
}
-// treecopy recursively copies n, with the exception of
-// ONAME, OLITERAL, OTYPE, and ONONAME leaves.
-// If pos.IsKnown(), it sets the source position of newly
-// allocated nodes to pos.
-func treecopy(n ir.Node, pos src.XPos) ir.Node {
- if n == nil {
- return nil
- }
-
- switch n.Op() {
- default:
- m := ir.SepCopy(n)
- m.SetLeft(treecopy(n.Left(), pos))
- m.SetRight(treecopy(n.Right(), pos))
- m.PtrList().Set(listtreecopy(n.List().Slice(), pos))
- if pos.IsKnown() {
- m.SetPos(pos)
- }
- if m.Name() != nil && n.Op() != ir.ODCLFIELD {
- ir.Dump("treecopy", n)
- base.Fatalf("treecopy Name")
- }
- return m
-
- case ir.OPACK:
- // OPACK nodes are never valid in const value declarations,
- // but allow them like any other declared symbol to avoid
- // crashing (golang.org/issue/11361).
- fallthrough
-
- case ir.ONAME, ir.ONONAME, ir.OLITERAL, ir.ONIL, ir.OTYPE:
- return n
-
- }
-}
-
-func isptrto(t *types.Type, et types.EType) bool {
+func isptrto(t *types.Type, et types.Kind) bool {
if t == nil {
return false
}
@@ -228,7 +192,7 @@ func isptrto(t *types.Type, et types.EType) bool {
if t == nil {
return false
}
- if t.Etype != et {
+ if t.Kind() != et {
return false
}
return true
@@ -244,7 +208,7 @@ func methtype(t *types.Type) *types.Type {
// Strip away pointer if it's there.
if t.IsPtr() {
- if t.Sym != nil {
+ if t.Sym() != nil {
return nil
}
t = t.Elem()
@@ -254,15 +218,15 @@ func methtype(t *types.Type) *types.Type {
}
// Must be a named type or anonymous struct.
- if t.Sym == nil && !t.IsStruct() {
+ if t.Sym() == nil && !t.IsStruct() {
return nil
}
// Check types.
- if issimple[t.Etype] {
+ if issimple[t.Kind()] {
return t
}
- switch t.Etype {
+ switch t.Kind() {
case types.TARRAY, types.TCHAN, types.TFUNC, types.TMAP, types.TSLICE, types.TSTRING, types.TSTRUCT:
return t
}
@@ -277,7 +241,7 @@ func assignop(src, dst *types.Type) (ir.Op, string) {
if src == dst {
return ir.OCONVNOP, ""
}
- if src == nil || dst == nil || src.Etype == types.TFORW || dst.Etype == types.TFORW || src.Orig == nil || dst.Orig == nil {
+ if src == nil || dst == nil || src.Kind() == types.TFORW || dst.Kind() == types.TFORW || src.Underlying() == nil || dst.Underlying() == nil {
return ir.OXXX, ""
}
@@ -293,13 +257,13 @@ func assignop(src, dst *types.Type) (ir.Op, string) {
// we want to recompute the itab. Recomputing the itab ensures
// that itabs are unique (thus an interface with a compile-time
// type I has an itab with interface type I).
- if types.Identical(src.Orig, dst.Orig) {
+ if types.Identical(src.Underlying(), dst.Underlying()) {
if src.IsEmptyInterface() {
// Conversion between two empty interfaces
// requires no code.
return ir.OCONVNOP, ""
}
- if (src.Sym == nil || dst.Sym == nil) && !src.IsInterface() {
+ if (src.Sym() == nil || dst.Sym() == nil) && !src.IsInterface() {
// Conversion between two types, at least one unnamed,
// needs no conversion. The exception is nonempty interfaces
// which need to have their itab updated.
@@ -308,7 +272,7 @@ func assignop(src, dst *types.Type) (ir.Op, string) {
}
// 3. dst is an interface type and src implements dst.
- if dst.IsInterface() && src.Etype != types.TNIL {
+ if dst.IsInterface() && src.Kind() != types.TNIL {
var missing, have *types.Field
var ptr int
if implements(src, dst, &missing, &have, &ptr) {
@@ -327,12 +291,12 @@ func assignop(src, dst *types.Type) (ir.Op, string) {
why = fmt.Sprintf(":\n\t%v does not implement %v (%v method is marked 'nointerface')", src, dst, missing.Sym)
} else if have != nil && have.Sym == missing.Sym {
why = fmt.Sprintf(":\n\t%v does not implement %v (wrong type for %v method)\n"+
- "\t\thave %v%0S\n\t\twant %v%0S", src, dst, missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type)
+ "\t\thave %v%S\n\t\twant %v%S", src, dst, missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type)
} else if ptr != 0 {
why = fmt.Sprintf(":\n\t%v does not implement %v (%v method has pointer receiver)", src, dst, missing.Sym)
} else if have != nil {
why = fmt.Sprintf(":\n\t%v does not implement %v (missing %v method)\n"+
- "\t\thave %v%0S\n\t\twant %v%0S", src, dst, missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type)
+ "\t\thave %v%S\n\t\twant %v%S", src, dst, missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type)
} else {
why = fmt.Sprintf(":\n\t%v does not implement %v (missing %v method)", src, dst, missing.Sym)
}
@@ -345,7 +309,7 @@ func assignop(src, dst *types.Type) (ir.Op, string) {
return ir.OXXX, why
}
- if src.IsInterface() && dst.Etype != types.TBLANK {
+ if src.IsInterface() && dst.Kind() != types.TBLANK {
var missing, have *types.Field
var ptr int
var why string
@@ -359,14 +323,14 @@ func assignop(src, dst *types.Type) (ir.Op, string) {
// src and dst have identical element types, and
// either src or dst is not a named type.
if src.IsChan() && src.ChanDir() == types.Cboth && dst.IsChan() {
- if types.Identical(src.Elem(), dst.Elem()) && (src.Sym == nil || dst.Sym == nil) {
+ if types.Identical(src.Elem(), dst.Elem()) && (src.Sym() == nil || dst.Sym() == nil) {
return ir.OCONVNOP, ""
}
}
// 5. src is the predeclared identifier nil and dst is a nillable type.
- if src.Etype == types.TNIL {
- switch dst.Etype {
+ if src.Kind() == types.TNIL {
+ switch dst.Kind() {
case types.TPTR,
types.TFUNC,
types.TMAP,
@@ -380,7 +344,7 @@ func assignop(src, dst *types.Type) (ir.Op, string) {
// 6. rule about untyped constants - already converted by defaultlit.
// 7. Any typed value can be assigned to the blank identifier.
- if dst.Etype == types.TBLANK {
+ if dst.Kind() == types.TBLANK {
return ir.OCONVNOP, ""
}
@@ -409,7 +373,7 @@ func convertop(srcConstant bool, src, dst *types.Type) (ir.Op, string) {
return ir.OXXX, why
}
// (b) Disallow string to []T where T is go:notinheap.
- if src.IsString() && dst.IsSlice() && dst.Elem().NotInHeap() && (dst.Elem().Etype == types.Bytetype.Etype || dst.Elem().Etype == types.Runetype.Etype) {
+ if src.IsString() && dst.IsSlice() && dst.Elem().NotInHeap() && (dst.Elem().Kind() == types.ByteType.Kind() || dst.Elem().Kind() == types.RuneType.Kind()) {
why := fmt.Sprintf(":\n\t%v is incomplete (or unallocatable)", dst.Elem())
return ir.OXXX, why
}
@@ -429,21 +393,21 @@ func convertop(srcConstant bool, src, dst *types.Type) (ir.Op, string) {
}
// 2. Ignoring struct tags, src and dst have identical underlying types.
- if types.IdenticalIgnoreTags(src.Orig, dst.Orig) {
+ if types.IdenticalIgnoreTags(src.Underlying(), dst.Underlying()) {
return ir.OCONVNOP, ""
}
// 3. src and dst are unnamed pointer types and, ignoring struct tags,
// their base types have identical underlying types.
- if src.IsPtr() && dst.IsPtr() && src.Sym == nil && dst.Sym == nil {
- if types.IdenticalIgnoreTags(src.Elem().Orig, dst.Elem().Orig) {
+ if src.IsPtr() && dst.IsPtr() && src.Sym() == nil && dst.Sym() == nil {
+ if types.IdenticalIgnoreTags(src.Elem().Underlying(), dst.Elem().Underlying()) {
return ir.OCONVNOP, ""
}
}
// 4. src and dst are both integer or floating point types.
if (src.IsInteger() || src.IsFloat()) && (dst.IsInteger() || dst.IsFloat()) {
- if simtype[src.Etype] == simtype[dst.Etype] {
+ if simtype[src.Kind()] == simtype[dst.Kind()] {
return ir.OCONVNOP, ""
}
return ir.OCONV, ""
@@ -451,7 +415,7 @@ func convertop(srcConstant bool, src, dst *types.Type) (ir.Op, string) {
// 5. src and dst are both complex types.
if src.IsComplex() && dst.IsComplex() {
- if simtype[src.Etype] == simtype[dst.Etype] {
+ if simtype[src.Kind()] == simtype[dst.Kind()] {
return ir.OCONVNOP, ""
}
return ir.OCONV, ""
@@ -471,10 +435,10 @@ func convertop(srcConstant bool, src, dst *types.Type) (ir.Op, string) {
}
if src.IsSlice() && dst.IsString() {
- if src.Elem().Etype == types.Bytetype.Etype {
+ if src.Elem().Kind() == types.ByteType.Kind() {
return ir.OBYTES2STR, ""
}
- if src.Elem().Etype == types.Runetype.Etype {
+ if src.Elem().Kind() == types.RuneType.Kind() {
return ir.ORUNES2STR, ""
}
}
@@ -482,10 +446,10 @@ func convertop(srcConstant bool, src, dst *types.Type) (ir.Op, string) {
// 7. src is a string and dst is []byte or []rune.
// String to slice.
if src.IsString() && dst.IsSlice() {
- if dst.Elem().Etype == types.Bytetype.Etype {
+ if dst.Elem().Kind() == types.ByteType.Kind() {
return ir.OSTR2BYTES, ""
}
- if dst.Elem().Etype == types.Runetype.Etype {
+ if dst.Elem().Kind() == types.RuneType.Kind() {
return ir.OSTR2RUNES, ""
}
}
@@ -503,7 +467,7 @@ func convertop(srcConstant bool, src, dst *types.Type) (ir.Op, string) {
// src is map and dst is a pointer to corresponding hmap.
// This rule is needed for the implementation detail that
// go gc maps are implemented as a pointer to a hmap struct.
- if src.Etype == types.TMAP && dst.IsPtr() &&
+ if src.Kind() == types.TMAP && dst.IsPtr() &&
src.MapType().Hmap == dst.Elem() {
return ir.OCONVNOP, ""
}
@@ -521,7 +485,7 @@ func assignconvfn(n ir.Node, t *types.Type, context func() string) ir.Node {
return n
}
- if t.Etype == types.TBLANK && n.Type().Etype == types.TNIL {
+ if t.Kind() == types.TBLANK && n.Type().Kind() == types.TNIL {
base.Errorf("use of untyped nil")
}
@@ -529,7 +493,7 @@ func assignconvfn(n ir.Node, t *types.Type, context func() string) ir.Node {
if n.Type() == nil {
return n
}
- if t.Etype == types.TBLANK {
+ if t.Kind() == types.TBLANK {
return n
}
@@ -559,7 +523,6 @@ func assignconvfn(n ir.Node, t *types.Type, context func() string) ir.Node {
r.SetType(t)
r.SetTypecheck(1)
r.SetImplicit(true)
- r.SetOrig(n.Orig())
return r
}
@@ -582,23 +545,6 @@ func backingArrayPtrLen(n ir.Node) (ptr, len ir.Node) {
return ptr, len
}
-// labeledControl returns the control flow Node (for, switch, select)
-// associated with the label n, if any.
-func labeledControl(n ir.Node) ir.Node {
- if n.Op() != ir.OLABEL {
- base.Fatalf("labeledControl %v", n.Op())
- }
- ctl := n.Name().Defn
- if ctl == nil {
- return nil
- }
- switch ctl.Op() {
- case ir.OFOR, ir.OFORUNTIL, ir.OSWITCH, ir.OSELECT:
- return ctl
- }
- return nil
-}
-
func syslook(name string) ir.Node {
s := Runtimepkg.Lookup(name)
if s == nil || s.Def == nil {
@@ -653,15 +599,15 @@ func calcHasCall(n ir.Node) bool {
// When using soft-float, these ops might be rewritten to function calls
// so we ensure they are evaluated first.
case ir.OADD, ir.OSUB, ir.ONEG, ir.OMUL:
- if thearch.SoftFloat && (isFloat[n.Type().Etype] || isComplex[n.Type().Etype]) {
+ if thearch.SoftFloat && (isFloat[n.Type().Kind()] || isComplex[n.Type().Kind()]) {
return true
}
case ir.OLT, ir.OEQ, ir.ONE, ir.OLE, ir.OGE, ir.OGT:
- if thearch.SoftFloat && (isFloat[n.Left().Type().Etype] || isComplex[n.Left().Type().Etype]) {
+ if thearch.SoftFloat && (isFloat[n.Left().Type().Kind()] || isComplex[n.Left().Type().Kind()]) {
return true
}
case ir.OCONV:
- if thearch.SoftFloat && ((isFloat[n.Type().Etype] || isComplex[n.Type().Etype]) || (isFloat[n.Left().Type().Etype] || isComplex[n.Left().Type().Etype])) {
+ if thearch.SoftFloat && ((isFloat[n.Type().Kind()] || isComplex[n.Type().Kind()]) || (isFloat[n.Left().Type().Kind()] || isComplex[n.Left().Type().Kind()])) {
return true
}
}
@@ -855,7 +801,7 @@ func lookdot0(s *types.Sym, t *types.Type, save **types.Field, ignorecase bool)
}
u = t
- if t.Sym != nil && t.IsPtr() && !t.Elem().IsPtr() {
+ if t.Sym() != nil && t.IsPtr() && !t.Elem().IsPtr() {
// If t is a defined pointer type, then x.m is shorthand for (*x).m.
u = t.Elem()
}
@@ -1115,9 +1061,9 @@ func expandmeth(t *types.Type) {
t.AllMethods().Set(ms)
}
-// Given funarg struct list, return list of ODCLFIELD Node fn args.
-func structargs(tl *types.Type, mustname bool) []ir.Node {
- var args []ir.Node
+// Given funarg struct list, return list of fn args.
+func structargs(tl *types.Type, mustname bool) []*ir.Field {
+ var args []*ir.Field
gen := 0
for _, t := range tl.Fields().Slice() {
s := t.Sym
@@ -1127,8 +1073,8 @@ func structargs(tl *types.Type, mustname bool) []ir.Node {
gen++
}
a := symfield(s, t.Type)
- a.SetPos(t.Pos)
- a.SetIsDDD(t.IsDDD())
+ a.Pos = t.Pos
+ a.IsDDD = t.IsDDD()
args = append(args, a)
}
@@ -1163,26 +1109,26 @@ func genwrapper(rcvr *types.Type, method *types.Field, newnam *types.Sym) {
// Only generate (*T).M wrappers for T.M in T's own package.
if rcvr.IsPtr() && rcvr.Elem() == method.Type.Recv().Type &&
- rcvr.Elem().Sym != nil && rcvr.Elem().Sym.Pkg != ir.LocalPkg {
+ rcvr.Elem().Sym() != nil && rcvr.Elem().Sym().Pkg != types.LocalPkg {
return
}
// Only generate I.M wrappers for I in I's own package
// but keep doing it for error.Error (was issue #29304).
- if rcvr.IsInterface() && rcvr.Sym != nil && rcvr.Sym.Pkg != ir.LocalPkg && rcvr != types.Errortype {
+ if rcvr.IsInterface() && rcvr.Sym() != nil && rcvr.Sym().Pkg != types.LocalPkg && rcvr != types.ErrorType {
return
}
base.Pos = autogeneratedPos
dclcontext = ir.PEXTERN
- tfn := ir.Nod(ir.OTFUNC, nil, nil)
- tfn.SetLeft(namedfield(".this", rcvr))
- tfn.PtrList().Set(structargs(method.Type.Params(), true))
- tfn.PtrRlist().Set(structargs(method.Type.Results(), false))
+ tfn := ir.NewFuncType(base.Pos,
+ namedfield(".this", rcvr),
+ structargs(method.Type.Params(), true),
+ structargs(method.Type.Results(), false))
fn := dclfunc(newnam, tfn)
- fn.Func().SetDupok(true)
+ fn.SetDupok(true)
nthis := ir.AsNode(tfn.Type().Recv().Nname)
@@ -1218,7 +1164,7 @@ func genwrapper(rcvr *types.Type, method *types.Field, newnam *types.Sym) {
fn.PtrBody().Append(as)
fn.PtrBody().Append(nodSym(ir.ORETJMP, nil, methodSym(methodrcvr, method.Sym)))
} else {
- fn.Func().SetWrapper(true) // ignore frame for panic+recover matching
+ fn.SetWrapper(true) // ignore frame for panic+recover matching
call := ir.Nod(ir.OCALL, dot, nil)
call.PtrList().Set(paramNnames(tfn.Type()))
call.SetIsDDD(tfn.Type().IsVariadic())
@@ -1239,18 +1185,17 @@ func genwrapper(rcvr *types.Type, method *types.Field, newnam *types.Sym) {
testdclstack()
}
- fn = typecheck(fn, ctxStmt)
-
+ typecheckFunc(fn)
Curfn = fn
typecheckslice(fn.Body().Slice(), ctxStmt)
// Inline calls within (*T).M wrappers. This is safe because we only
// generate those wrappers within the same compilation unit as (T).M.
// TODO(mdempsky): Investigate why we can't enable this more generally.
- if rcvr.IsPtr() && rcvr.Elem() == method.Type.Recv().Type && rcvr.Elem().Sym != nil {
+ if rcvr.IsPtr() && rcvr.Elem() == method.Type.Recv().Type && rcvr.Elem().Sym() != nil {
inlcalls(fn)
}
- escapeFuncs([]ir.Node{fn}, false)
+ escapeFuncs([]*ir.Func{fn}, false)
Curfn = nil
xtop = append(xtop, fn)
@@ -1269,11 +1214,11 @@ func hashmem(t *types.Type) ir.Node {
n := NewName(sym)
setNodeNameFunc(n)
- n.SetType(functype(nil, []ir.Node{
+ n.SetType(functype(nil, []*ir.Field{
anonfield(types.NewPtr(t)),
anonfield(types.Types[types.TUINTPTR]),
anonfield(types.Types[types.TUINTPTR]),
- }, []ir.Node{
+ }, []*ir.Field{
anonfield(types.Types[types.TUINTPTR]),
}))
return n
@@ -1393,14 +1338,6 @@ func implements(t, iface *types.Type, m, samename **types.Field, ptr *int) bool
return true
}
-func listtreecopy(l []ir.Node, pos src.XPos) []ir.Node {
- var out []ir.Node
- for _, n := range l {
- out = append(out, treecopy(n, pos))
- }
- return out
-}
-
func liststmt(l []ir.Node) ir.Node {
n := ir.Nod(ir.OBLOCK, nil, nil)
n.PtrList().Set(l)
@@ -1417,9 +1354,9 @@ func ngotype(n ir.Node) *types.Sym {
return nil
}
-// The result of addinit MUST be assigned back to n, e.g.
-// n.Left = addinit(n.Left, init)
-func addinit(n ir.Node, init []ir.Node) ir.Node {
+// The result of initExpr MUST be assigned back to n, e.g.
+// n.Left = initExpr(init, n.Left)
+func initExpr(init []ir.Node, n ir.Node) ir.Node {
if len(init) == 0 {
return n
}
@@ -1495,7 +1432,7 @@ func isdirectiface(t *types.Type) bool {
return false
}
- switch t.Etype {
+ switch t.Kind() {
case types.TPTR:
// Pointers to notinheap types must be stored indirectly. See issue 42076.
return !t.Elem().NotInHeap()
@@ -1534,7 +1471,7 @@ func ifaceData(pos src.XPos, n ir.Node, t *types.Type) ir.Node {
if t.IsInterface() {
base.Fatalf("ifaceData interface: %v", t)
}
- ptr := nodlSym(pos, ir.OIDATA, n, nil)
+ ptr := ir.NodAt(pos, ir.OIDATA, n, nil)
if isdirectiface(t) {
ptr.SetType(t)
ptr.SetTypecheck(1)
@@ -1552,9 +1489,9 @@ func ifaceData(pos src.XPos, n ir.Node, t *types.Type) ir.Node {
// typePos returns the position associated with t.
// This is where t was declared or where it appeared as a type expression.
func typePos(t *types.Type) src.XPos {
- n := ir.AsNode(t.Nod)
- if n == nil || !n.Pos().IsKnown() {
- base.Fatalf("bad type: %v", t)
+ if pos := t.Pos(); pos.IsKnown() {
+ return pos
}
- return n.Pos()
+ base.Fatalf("bad type: %v", t)
+ panic("unreachable")
}
diff --git a/src/cmd/compile/internal/gc/swt.go b/src/cmd/compile/internal/gc/swt.go
index 02d38ac4b1..e241721588 100644
--- a/src/cmd/compile/internal/gc/swt.go
+++ b/src/cmd/compile/internal/gc/swt.go
@@ -157,7 +157,7 @@ func typecheckExprSwitch(n ir.Node) {
switch {
case t.IsMap():
nilonly = "map"
- case t.Etype == types.TFUNC:
+ case t.Kind() == types.TFUNC:
nilonly = "func"
case t.IsSlice():
nilonly = "slice"
@@ -332,7 +332,7 @@ type exprClause struct {
func (s *exprSwitch) Add(pos src.XPos, expr, jmp ir.Node) {
c := exprClause{pos: pos, lo: expr, hi: expr, jmp: jmp}
- if okforcmp[s.exprname.Type().Etype] && expr.Op() == ir.OLITERAL {
+ if okforcmp[s.exprname.Type().Kind()] && expr.Op() == ir.OLITERAL {
s.clauses = append(s.clauses, c)
return
}
@@ -365,8 +365,8 @@ func (s *exprSwitch) flush() {
// all we need here is consistency. We respect this
// sorting below.
sort.Slice(cc, func(i, j int) bool {
- si := cc[i].lo.StringVal()
- sj := cc[j].lo.StringVal()
+ si := ir.StringVal(cc[i].lo)
+ sj := ir.StringVal(cc[j].lo)
if len(si) != len(sj) {
return len(si) < len(sj)
}
@@ -375,7 +375,7 @@ func (s *exprSwitch) flush() {
// runLen returns the string length associated with a
// particular run of exprClauses.
- runLen := func(run []exprClause) int64 { return int64(len(run[0].lo.StringVal())) }
+ runLen := func(run []exprClause) int64 { return int64(len(ir.StringVal(run[0].lo))) }
// Collapse runs of consecutive strings with the same length.
var runs [][]exprClause
@@ -411,7 +411,7 @@ func (s *exprSwitch) flush() {
merged := cc[:1]
for _, c := range cc[1:] {
last := &merged[len(merged)-1]
- if last.jmp == c.jmp && last.hi.Int64Val()+1 == c.lo.Int64Val() {
+ if last.jmp == c.jmp && ir.Int64Val(last.hi)+1 == ir.Int64Val(c.lo) {
last.hi = c.lo
} else {
merged = append(merged, c)
@@ -446,7 +446,7 @@ func (c *exprClause) test(exprname ir.Node) ir.Node {
// Optimize "switch true { ...}" and "switch false { ... }".
if ir.IsConst(exprname, constant.Bool) && !c.lo.Type().IsInterface() {
- if exprname.BoolVal() {
+ if ir.BoolVal(exprname) {
return c.lo
} else {
return ir.NodAt(c.pos, ir.ONOT, c.lo, nil)
diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go
index 4e2f205312..f187880e28 100644
--- a/src/cmd/compile/internal/gc/typecheck.go
+++ b/src/cmd/compile/internal/gc/typecheck.go
@@ -58,7 +58,7 @@ func tracePrint(title string, n ir.Node) func(np *ir.Node) {
skipDowidthForTracing = true
defer func() { skipDowidthForTracing = false }()
- fmt.Printf("%s: %s=> %p %s %v tc=%d type=%#L\n", pos, indent, n, op, n, tc, typ)
+ fmt.Printf("%s: %s=> %p %s %v tc=%d type=%L\n", pos, indent, n, op, n, tc, typ)
}
}
@@ -90,7 +90,11 @@ func resolve(n ir.Node) (res ir.Node) {
defer tracePrint("resolve", n)(&res)
}
- if n.Sym().Pkg != ir.LocalPkg {
+ // Stub ir.Name left for us by iimport.
+ if n, ok := n.(*ir.Name); ok {
+ if n.Sym().Pkg == types.LocalPkg {
+ base.Fatalf("unexpected Name: %+v", n)
+ }
if inimport {
base.Fatalf("recursive inimport")
}
@@ -156,7 +160,7 @@ func typekind(t *types.Type) string {
if t.IsUntyped() {
return fmt.Sprintf("%v", t)
}
- et := t.Etype
+ et := t.Kind()
if int(et) < len(_typekind) {
s := _typekind[et]
if s != "" {
@@ -199,6 +203,17 @@ func cycleTrace(cycle []ir.Node) string {
var typecheck_tcstack []ir.Node
+func typecheckFunc(fn *ir.Func) {
+ new := typecheck(fn, ctxStmt)
+ if new != fn {
+ base.Fatalf("typecheck changed func")
+ }
+}
+
+func typecheckNtype(n ir.Ntype) ir.Ntype {
+ return typecheck(n, ctxType).(ir.Ntype)
+}
+
// typecheck type checks node n.
// The result of typecheck MUST be assigned back to n, e.g.
// n.Left = typecheck(n.Left, top)
@@ -259,12 +274,12 @@ func typecheck(n ir.Node, top int) (res ir.Node) {
// are substituted.
cycle := cycleFor(n)
for _, n1 := range cycle {
- if n1.Name() != nil && !n1.Name().Param.Alias() {
+ if n1.Name() != nil && !n1.Name().Alias() {
// Cycle is ok. But if n is an alias type and doesn't
// have a type yet, we have a recursive type declaration
// with aliases that we can't handle properly yet.
// Report an error rather than crashing later.
- if n.Name() != nil && n.Name().Param.Alias() && n.Type() == nil {
+ if n.Name() != nil && n.Name().Alias() && n.Type() == nil {
base.Pos = n.Pos()
base.Fatalf("cannot handle alias type declaration (issue #25838): %v", n)
}
@@ -296,17 +311,91 @@ func typecheck(n ir.Node, top int) (res ir.Node) {
return n
}
- n.SetTypecheck(2)
-
typecheck_tcstack = append(typecheck_tcstack, n)
- n = typecheck1(n, top)
+ n.SetTypecheck(2)
+ n = typecheck1(n, top)
n.SetTypecheck(1)
last := len(typecheck_tcstack) - 1
typecheck_tcstack[last] = nil
typecheck_tcstack = typecheck_tcstack[:last]
+ _, isExpr := n.(ir.Expr)
+ _, isStmt := n.(ir.Stmt)
+ isMulti := false
+ switch n.Op() {
+ case ir.OCALLFUNC, ir.OCALLINTER, ir.OCALLMETH:
+ if t := n.Left().Type(); t != nil && t.Kind() == types.TFUNC {
+ nr := t.NumResults()
+ isMulti = nr > 1
+ if nr == 0 {
+ isExpr = false
+ }
+ }
+ case ir.OAPPEND:
+ // Must be used (and not BinaryExpr/UnaryExpr).
+ isStmt = false
+ case ir.OCLOSE, ir.ODELETE, ir.OPANIC, ir.OPRINT, ir.OPRINTN, ir.OVARKILL, ir.OVARLIVE:
+ // Must not be used.
+ isExpr = false
+ isStmt = true
+ case ir.OCOPY, ir.ORECOVER, ir.ORECV:
+ // Can be used or not.
+ isStmt = true
+ }
+
+ t := n.Type()
+ if t != nil && !t.IsFuncArgStruct() && n.Op() != ir.OTYPE {
+ switch t.Kind() {
+ case types.TFUNC, // might have TANY; wait until it's called
+ types.TANY, types.TFORW, types.TIDEAL, types.TNIL, types.TBLANK:
+ break
+
+ default:
+ checkwidth(t)
+ }
+ }
+ if t != nil {
+ n = evalConst(n)
+ t = n.Type()
+ }
+
+ // TODO(rsc): Lots of the complexity here is because typecheck can
+ // see OTYPE, ONAME, and OLITERAL nodes multiple times.
+ // Once we make the IR a proper tree, we should be able to simplify
+ // this code a bit, especially the final case.
+ switch {
+ case top&(ctxStmt|ctxExpr) == ctxExpr && !isExpr && n.Op() != ir.OTYPE && !isMulti:
+ if !n.Diag() {
+ base.Errorf("%v used as value", n)
+ n.SetDiag(true)
+ }
+ if t != nil {
+ n.SetType(nil)
+ }
+
+ case top&ctxType == 0 && n.Op() == ir.OTYPE && t != nil:
+ if !n.Type().Broke() {
+ base.Errorf("type %v is not an expression", n.Type())
+ }
+ n.SetType(nil)
+
+ case top&(ctxStmt|ctxExpr) == ctxStmt && !isStmt && t != nil:
+ if !n.Diag() {
+ base.Errorf("%v evaluated but not used", n)
+ n.SetDiag(true)
+ }
+ n.SetType(nil)
+
+ case top&(ctxType|ctxExpr) == ctxType && n.Op() != ir.OTYPE && n.Op() != ir.ONONAME && (t != nil || n.Op() == ir.ONAME):
+ base.Errorf("%v is not a type", n)
+ if t != nil {
+ n.SetType(nil)
+ }
+
+ }
+
base.Pos = lno
return n
}
@@ -318,14 +407,13 @@ func typecheck(n ir.Node, top int) (res ir.Node) {
// The result of indexlit MUST be assigned back to n, e.g.
// n.Left = indexlit(n.Left)
func indexlit(n ir.Node) ir.Node {
- if n != nil && n.Type() != nil && n.Type().Etype == types.TIDEAL {
+ if n != nil && n.Type() != nil && n.Type().Kind() == types.TIDEAL {
return defaultlit(n, types.Types[types.TINT])
}
return n
}
-// The result of typecheck1 MUST be assigned back to n, e.g.
-// n.Left = typecheck1(n.Left, top)
+// typecheck1 should ONLY be called from typecheck.
func typecheck1(n ir.Node, top int) (res ir.Node) {
if enableTrace && base.Flag.LowerT {
defer tracePrint("typecheck1", n)(&res)
@@ -334,7 +422,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
switch n.Op() {
case ir.OLITERAL, ir.ONAME, ir.ONONAME, ir.OTYPE:
if n.Sym() == nil {
- break
+ return n
}
if n.Op() == ir.ONAME && n.SubOp() != 0 && top&ctxCallee == 0 {
@@ -350,34 +438,29 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
}
}
- ok := 0
switch n.Op() {
- // until typecheck is complete, do nothing.
default:
ir.Dump("typecheck", n)
-
base.Fatalf("typecheck %v", n.Op())
+ panic("unreachable")
// names
case ir.OLITERAL:
- ok |= ctxExpr
-
if n.Type() == nil && n.Val().Kind() == constant.String {
base.Fatalf("string literal missing type")
}
+ return n
case ir.ONIL, ir.ONONAME:
- ok |= ctxExpr
+ return n
case ir.ONAME:
if n.Name().Decldepth == 0 {
n.Name().Decldepth = decldepth
}
if n.SubOp() != 0 {
- ok |= ctxCallee
- break
+ return n
}
-
if top&ctxAssign == 0 {
// not a write to the variable
if ir.IsBlank(n) {
@@ -385,92 +468,84 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
n.SetType(nil)
return n
}
-
n.Name().SetUsed(true)
}
-
- ok |= ctxExpr
+ return n
case ir.OPACK:
base.Errorf("use of package %v without selector", n.Sym())
n.SetType(nil)
return n
- case ir.ODDD:
- break
-
// types (ODEREF is with exprs)
case ir.OTYPE:
- ok |= ctxType
-
if n.Type() == nil {
return n
}
+ return n
- case ir.OTARRAY:
- ok |= ctxType
- r := typecheck(n.Right(), ctxType)
- if r.Type() == nil {
- n.SetType(nil)
+ case ir.OTSLICE:
+ n := n.(*ir.SliceType)
+ n.Elem = typecheck(n.Elem, ctxType)
+ if n.Elem.Type() == nil {
return n
}
+ t := types.NewSlice(n.Elem.Type())
+ n.SetOTYPE(t)
+ checkwidth(t)
+ return n
- var t *types.Type
- if n.Left() == nil {
- t = types.NewSlice(r.Type())
- } else if n.Left().Op() == ir.ODDD {
+ case ir.OTARRAY:
+ n := n.(*ir.ArrayType)
+ n.Elem = typecheck(n.Elem, ctxType)
+ if n.Elem.Type() == nil {
+ return n
+ }
+ if n.Len == nil { // [...]T
if !n.Diag() {
n.SetDiag(true)
base.Errorf("use of [...] array outside of array literal")
}
- n.SetType(nil)
return n
- } else {
- n.SetLeft(indexlit(typecheck(n.Left(), ctxExpr)))
- l := n.Left()
- if ir.ConstType(l) != constant.Int {
- switch {
- case l.Type() == nil:
- // Error already reported elsewhere.
- case l.Type().IsInteger() && l.Op() != ir.OLITERAL:
- base.Errorf("non-constant array bound %v", l)
- default:
- base.Errorf("invalid array bound %v", l)
- }
- n.SetType(nil)
- return n
+ }
+ n.Len = indexlit(typecheck(n.Len, ctxExpr))
+ size := n.Len
+ if ir.ConstType(size) != constant.Int {
+ switch {
+ case size.Type() == nil:
+ // Error already reported elsewhere.
+ case size.Type().IsInteger() && size.Op() != ir.OLITERAL:
+ base.Errorf("non-constant array bound %v", size)
+ default:
+ base.Errorf("invalid array bound %v", size)
}
-
- v := l.Val()
- if doesoverflow(v, types.Types[types.TINT]) {
- base.Errorf("array bound is too large")
- n.SetType(nil)
- return n
- }
-
- if constant.Sign(v) < 0 {
- base.Errorf("array bound must be non-negative")
- n.SetType(nil)
- return n
- }
-
- bound, _ := constant.Int64Val(v)
- t = types.NewArray(r.Type(), bound)
+ return n
}
- setTypeNode(n, t)
- n.SetLeft(nil)
- n.SetRight(nil)
+ v := size.Val()
+ if doesoverflow(v, types.Types[types.TINT]) {
+ base.Errorf("array bound is too large")
+ return n
+ }
+
+ if constant.Sign(v) < 0 {
+ base.Errorf("array bound must be non-negative")
+ return n
+ }
+
+ bound, _ := constant.Int64Val(v)
+ t := types.NewArray(n.Elem.Type(), bound)
+ n.SetOTYPE(t)
checkwidth(t)
+ return n
case ir.OTMAP:
- ok |= ctxType
- n.SetLeft(typecheck(n.Left(), ctxType))
- n.SetRight(typecheck(n.Right(), ctxType))
- l := n.Left()
- r := n.Right()
+ n := n.(*ir.MapType)
+ n.Key = typecheck(n.Key, ctxType)
+ n.Elem = typecheck(n.Elem, ctxType)
+ l := n.Key
+ r := n.Elem
if l.Type() == nil || r.Type() == nil {
- n.SetType(nil)
return n
}
if l.Type().NotInHeap() {
@@ -479,60 +554,53 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
if r.Type().NotInHeap() {
base.Errorf("incomplete (or unallocatable) map value not allowed")
}
-
- setTypeNode(n, types.NewMap(l.Type(), r.Type()))
+ n.SetOTYPE(types.NewMap(l.Type(), r.Type()))
mapqueue = append(mapqueue, n) // check map keys when all types are settled
- n.SetLeft(nil)
- n.SetRight(nil)
+ return n
case ir.OTCHAN:
- ok |= ctxType
- n.SetLeft(typecheck(n.Left(), ctxType))
- l := n.Left()
+ n := n.(*ir.ChanType)
+ n.Elem = typecheck(n.Elem, ctxType)
+ l := n.Elem
if l.Type() == nil {
- n.SetType(nil)
return n
}
if l.Type().NotInHeap() {
base.Errorf("chan of incomplete (or unallocatable) type not allowed")
}
-
- setTypeNode(n, types.NewChan(l.Type(), n.TChanDir()))
- n.SetLeft(nil)
- n.ResetAux()
+ n.SetOTYPE(types.NewChan(l.Type(), n.Dir))
+ return n
case ir.OTSTRUCT:
- ok |= ctxType
- setTypeNode(n, tostruct(n.List().Slice()))
- n.PtrList().Set(nil)
+ n := n.(*ir.StructType)
+ n.SetOTYPE(tostruct(n.Fields))
+ return n
case ir.OTINTER:
- ok |= ctxType
- setTypeNode(n, tointerface(n.List().Slice()))
+ n := n.(*ir.InterfaceType)
+ n.SetOTYPE(tointerface(n.Methods))
+ return n
case ir.OTFUNC:
- ok |= ctxType
- setTypeNode(n, functype(n.Left(), n.List().Slice(), n.Rlist().Slice()))
- n.SetLeft(nil)
- n.PtrList().Set(nil)
- n.PtrRlist().Set(nil)
+ n := n.(*ir.FuncType)
+ n.SetOTYPE(functype(n.Recv, n.Params, n.Results))
+ return n
// type or expr
case ir.ODEREF:
- n.SetLeft(typecheck(n.Left(), ctxExpr|ctxType))
- l := n.Left()
+ n := n.(*ir.StarExpr)
+ n.X = typecheck(n.X, ctxExpr|ctxType)
+ l := n.X
t := l.Type()
if t == nil {
n.SetType(nil)
return n
}
if l.Op() == ir.OTYPE {
- ok |= ctxType
- setTypeNode(n, types.NewPtr(l.Type()))
- n.SetLeft(nil)
+ n.SetOTYPE(types.NewPtr(l.Type()))
// Ensure l.Type gets dowidth'd for the backend. Issue 20174.
checkwidth(l.Type())
- break
+ return n
}
if !t.IsPtr() {
@@ -541,12 +609,12 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
n.SetType(nil)
return n
}
-
- break
+ base.Errorf("%v is not a type", l)
+ return n
}
- ok |= ctxExpr
n.SetType(t.Elem())
+ return n
// arithmetic exprs
case ir.OASOP,
@@ -573,7 +641,6 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
var op ir.Op
var r ir.Node
if n.Op() == ir.OASOP {
- ok |= ctxStmt
n.SetLeft(typecheck(n.Left(), ctxExpr))
n.SetRight(typecheck(n.Right(), ctxExpr))
l = n.Left()
@@ -583,7 +650,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
n.SetType(nil)
return n
}
- if n.Implicit() && !okforarith[l.Type().Etype] {
+ if n.Implicit() && !okforarith[l.Type().Kind()] {
base.Errorf("invalid operation: %v (non-numeric type %v)", n, l.Type())
n.SetType(nil)
return n
@@ -591,7 +658,6 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
// TODO(marvin): Fix Node.EType type union.
op = n.SubOp()
} else {
- ok |= ctxExpr
n.SetLeft(typecheck(n.Left(), ctxExpr))
n.SetRight(typecheck(n.Right(), ctxExpr))
l = n.Left()
@@ -617,7 +683,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
return n
}
t = l.Type()
- if t != nil && t.Etype != types.TIDEAL && !t.IsInteger() {
+ if t != nil && t.Kind() != types.TIDEAL && !t.IsInteger() {
base.Errorf("invalid operation: %v (shift of type %v)", n, t)
n.SetType(nil)
return n
@@ -629,8 +695,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
if (l.Type() == types.UntypedFloat || l.Type() == types.UntypedComplex) && r.Op() == ir.OLITERAL {
n.SetType(types.UntypedInt)
}
-
- break
+ return n
}
// For "x == x && len(s)", it's better to report that "len(s)" (type int)
@@ -659,15 +724,15 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
return n
}
t := l.Type()
- if t.Etype == types.TIDEAL {
+ if t.Kind() == types.TIDEAL {
t = r.Type()
}
- et := t.Etype
+ et := t.Kind()
if et == types.TIDEAL {
et = types.TINT
}
aop := ir.OXXX
- if iscmp[n.Op()] && t.Etype != types.TIDEAL && !types.Identical(l.Type(), r.Type()) {
+ if iscmp[n.Op()] && t.Kind() != types.TIDEAL && !types.Identical(l.Type(), r.Type()) {
// comparison is okay as long as one side is
// assignable to the other. convert so they have
// the same type.
@@ -676,7 +741,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
// in that case, check comparability of the concrete type.
// The conversion allocates, so only do it if the concrete type is huge.
converted := false
- if r.Type().Etype != types.TBLANK {
+ if r.Type().Kind() != types.TBLANK {
aop, _ = assignop(l.Type(), r.Type())
if aop != ir.OXXX {
if r.Type().IsInterface() && !l.Type().IsInterface() && !IsComparable(l.Type()) {
@@ -698,7 +763,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
}
}
- if !converted && l.Type().Etype != types.TBLANK {
+ if !converted && l.Type().Kind() != types.TBLANK {
aop, _ = assignop(r.Type(), l.Type())
if aop != ir.OXXX {
if l.Type().IsInterface() && !r.Type().IsInterface() && !IsComparable(r.Type()) {
@@ -719,10 +784,10 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
}
}
- et = t.Etype
+ et = t.Kind()
}
- if t.Etype != types.TIDEAL && !types.Identical(l.Type(), r.Type()) {
+ if t.Kind() != types.TIDEAL && !types.Identical(l.Type(), r.Type()) {
l, r = defaultlit2(l, r, true)
if l.Type() == nil || r.Type() == nil {
n.SetType(nil)
@@ -735,10 +800,10 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
}
}
- if t.Etype == types.TIDEAL {
+ if t.Kind() == types.TIDEAL {
t = mixUntyped(l.Type(), r.Type())
}
- if dt := defaultType(t); !okfor[op][dt.Etype] {
+ if dt := defaultType(t); !okfor[op][dt.Kind()] {
base.Errorf("invalid operation: %v (operator %v not defined on %s)", n, op, typekind(t))
n.SetType(nil)
return n
@@ -764,7 +829,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
return n
}
- if l.Type().Etype == types.TFUNC && !ir.IsNil(l) && !ir.IsNil(r) {
+ if l.Type().Kind() == types.TFUNC && !ir.IsNil(l) && !ir.IsNil(r) {
base.Errorf("invalid operation: %v (func can only be compared to nil)", n)
n.SetType(nil)
return n
@@ -815,9 +880,9 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
}
n.SetType(t)
+ return n
case ir.OBITNOT, ir.ONEG, ir.ONOT, ir.OPLUS:
- ok |= ctxExpr
n.SetLeft(typecheck(n.Left(), ctxExpr))
l := n.Left()
t := l.Type()
@@ -825,18 +890,17 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
n.SetType(nil)
return n
}
- if !okfor[n.Op()][defaultType(t).Etype] {
+ if !okfor[n.Op()][defaultType(t).Kind()] {
base.Errorf("invalid operation: %v (operator %v not defined on %s)", n, n.Op(), typekind(t))
n.SetType(nil)
return n
}
n.SetType(t)
+ return n
// exprs
case ir.OADDR:
- ok |= ctxExpr
-
n.SetLeft(typecheck(n.Left(), ctxExpr))
if n.Left().Type() == nil {
n.SetType(nil)
@@ -851,7 +915,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
checklvalue(n.Left(), "take the address of")
r := outervalue(n.Left())
if r.Op() == ir.ONAME {
- if r.Orig() != r {
+ if ir.Orig(r) != r {
base.Fatalf("found non-orig name node %v", r) // TODO(mdempsky): What does this mean?
}
r.Name().SetAddrtaken(true)
@@ -871,13 +935,10 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
}
n.SetType(types.NewPtr(n.Left().Type()))
+ return n
case ir.OCOMPLIT:
- ok |= ctxExpr
- n = typecheckcomplit(n)
- if n.Type() == nil {
- return n
- }
+ return typecheckcomplit(n)
case ir.OXDOT, ir.ODOT:
if n.Op() == ir.OXDOT {
@@ -895,7 +956,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
t := n.Left().Type()
if t == nil {
- base.UpdateErrorDot(ir.Line(n), n.Left().String(), n.String())
+ base.UpdateErrorDot(ir.Line(n), fmt.Sprint(n.Left()), fmt.Sprint(n))
n.SetType(nil)
return n
}
@@ -903,12 +964,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
s := n.Sym()
if n.Left().Op() == ir.OTYPE {
- n = typecheckMethodExpr(n)
- if n.Type() == nil {
- return n
- }
- ok = ctxExpr
- break
+ return typecheckMethodExpr(n)
}
if t.IsPtr() && !t.Elem().IsInterface() {
@@ -952,21 +1008,12 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
return n
}
- switch n.Op() {
- case ir.ODOTINTER, ir.ODOTMETH:
- if top&ctxCallee != 0 {
- ok |= ctxCallee
- } else {
- typecheckpartialcall(n, s)
- ok |= ctxExpr
- }
-
- default:
- ok |= ctxExpr
+ if (n.Op() == ir.ODOTINTER || n.Op() == ir.ODOTMETH) && top&ctxCallee == 0 {
+ n = typecheckpartialcall(n, s)
}
+ return n
case ir.ODOTTYPE:
- ok |= ctxExpr
n.SetLeft(typecheck(n.Left(), ctxExpr))
n.SetLeft(defaultlit(n.Left(), nil))
l := n.Left()
@@ -996,12 +1043,12 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
if !implements(n.Type(), t, &missing, &have, &ptr) {
if have != nil && have.Sym == missing.Sym {
base.Errorf("impossible type assertion:\n\t%v does not implement %v (wrong type for %v method)\n"+
- "\t\thave %v%0S\n\t\twant %v%0S", n.Type(), t, missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type)
+ "\t\thave %v%S\n\t\twant %v%S", n.Type(), t, missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type)
} else if ptr != 0 {
base.Errorf("impossible type assertion:\n\t%v does not implement %v (%v method has pointer receiver)", n.Type(), t, missing.Sym)
} else if have != nil {
base.Errorf("impossible type assertion:\n\t%v does not implement %v (missing %v method)\n"+
- "\t\thave %v%0S\n\t\twant %v%0S", n.Type(), t, missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type)
+ "\t\thave %v%S\n\t\twant %v%S", n.Type(), t, missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type)
} else {
base.Errorf("impossible type assertion:\n\t%v does not implement %v (missing %v method)", n.Type(), t, missing.Sym)
}
@@ -1009,9 +1056,9 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
return n
}
}
+ return n
case ir.OINDEX:
- ok |= ctxExpr
n.SetLeft(typecheck(n.Left(), ctxExpr))
n.SetLeft(defaultlit(n.Left(), nil))
n.SetLeft(implicitstar(n.Left()))
@@ -1023,7 +1070,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
n.SetType(nil)
return n
}
- switch t.Etype {
+ switch t.Kind() {
default:
base.Errorf("invalid operation: %v (type %v does not support indexing)", n, t)
n.SetType(nil)
@@ -1032,7 +1079,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
case types.TSTRING, types.TARRAY, types.TSLICE:
n.SetRight(indexlit(n.Right()))
if t.IsString() {
- n.SetType(types.Bytetype)
+ n.SetType(types.ByteType)
} else {
n.SetType(t.Elem())
}
@@ -1045,7 +1092,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
if n.Right().Type() != nil && !n.Right().Type().IsInteger() {
base.Errorf("non-integer %s index %v", why, n.Right())
- break
+ return n
}
if !n.Bounded() && ir.IsConst(n.Right(), constant.Int) {
@@ -1054,8 +1101,8 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
base.Errorf("invalid %s index %v (index must be non-negative)", why, n.Right())
} else if t.IsArray() && constant.Compare(x, token.GEQ, constant.MakeInt64(t.NumElem())) {
base.Errorf("invalid array index %v (out of bounds for %d-element array)", n.Right(), t.NumElem())
- } else if ir.IsConst(n.Left(), constant.String) && constant.Compare(x, token.GEQ, constant.MakeInt64(int64(len(n.Left().StringVal())))) {
- base.Errorf("invalid string index %v (out of bounds for %d-byte string)", n.Right(), len(n.Left().StringVal()))
+ } else if ir.IsConst(n.Left(), constant.String) && constant.Compare(x, token.GEQ, constant.MakeInt64(int64(len(ir.StringVal(n.Left()))))) {
+ base.Errorf("invalid string index %v (out of bounds for %d-byte string)", n.Right(), len(ir.StringVal(n.Left())))
} else if doesoverflow(x, types.Types[types.TINT]) {
base.Errorf("invalid %s index %v (index too large)", why, n.Right())
}
@@ -1065,11 +1112,11 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
n.SetRight(assignconv(n.Right(), t.Key(), "map index"))
n.SetType(t.Elem())
n.SetOp(ir.OINDEXMAP)
- n.ResetAux()
+ n.SetIndexMapLValue(false)
}
+ return n
case ir.ORECV:
- ok |= ctxStmt | ctxExpr
n.SetLeft(typecheck(n.Left(), ctxExpr))
n.SetLeft(defaultlit(n.Left(), nil))
l := n.Left()
@@ -1091,43 +1138,37 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
}
n.SetType(t.Elem())
+ return n
case ir.OSEND:
- ok |= ctxStmt
n.SetLeft(typecheck(n.Left(), ctxExpr))
n.SetRight(typecheck(n.Right(), ctxExpr))
n.SetLeft(defaultlit(n.Left(), nil))
t := n.Left().Type()
if t == nil {
- n.SetType(nil)
return n
}
if !t.IsChan() {
base.Errorf("invalid operation: %v (send to non-chan type %v)", n, t)
- n.SetType(nil)
return n
}
if !t.ChanDir().CanSend() {
base.Errorf("invalid operation: %v (send to receive-only type %v)", n, t)
- n.SetType(nil)
return n
}
n.SetRight(assignconv(n.Right(), t.Elem(), "send"))
if n.Right().Type() == nil {
- n.SetType(nil)
return n
}
- n.SetType(nil)
+ return n
case ir.OSLICEHEADER:
// Errors here are Fatalf instead of Errorf because only the compiler
// can construct an OSLICEHEADER node.
// Components used in OSLICEHEADER that are supplied by parsed source code
// have already been typechecked in e.g. OMAKESLICE earlier.
- ok |= ctxExpr
-
t := n.Type()
if t == nil {
base.Fatalf("no type specified for OSLICEHEADER")
@@ -1151,11 +1192,11 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
l = defaultlit(l, types.Types[types.TINT])
c = defaultlit(c, types.Types[types.TINT])
- if ir.IsConst(l, constant.Int) && l.Int64Val() < 0 {
+ if ir.IsConst(l, constant.Int) && ir.Int64Val(l) < 0 {
base.Fatalf("len for OSLICEHEADER must be non-negative")
}
- if ir.IsConst(c, constant.Int) && c.Int64Val() < 0 {
+ if ir.IsConst(c, constant.Int) && ir.Int64Val(c) < 0 {
base.Fatalf("cap for OSLICEHEADER must be non-negative")
}
@@ -1165,14 +1206,13 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
n.List().SetFirst(l)
n.List().SetSecond(c)
+ return n
case ir.OMAKESLICECOPY:
// Errors here are Fatalf instead of Errorf because only the compiler
// can construct an OMAKESLICECOPY node.
// Components used in OMAKESCLICECOPY that are supplied by parsed source code
// have already been typechecked in OMAKE and OCOPY earlier.
- ok |= ctxExpr
-
t := n.Type()
if t == nil {
@@ -1196,7 +1236,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
n.SetLeft(defaultlit(n.Left(), types.Types[types.TINT]))
- if !n.Left().Type().IsInteger() && n.Type().Etype != types.TIDEAL {
+ if !n.Left().Type().IsInteger() && n.Type().Kind() != types.TIDEAL {
base.Errorf("non-integer len argument in OMAKESLICECOPY")
}
@@ -1208,9 +1248,9 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
base.Fatalf("len for OMAKESLICECOPY must be non-negative")
}
}
+ return n
case ir.OSLICE, ir.OSLICE3:
- ok |= ctxExpr
n.SetLeft(typecheck(n.Left(), ctxExpr))
low, high, max := n.SliceBounds()
hasmax := n.Op().IsSlice3()
@@ -1282,9 +1322,14 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
n.SetType(nil)
return n
}
+ return n
// call and call like
case ir.OCALL:
+ n.(*ir.CallExpr).Use = ir.CallUseExpr
+ if top == ctxStmt {
+ n.(*ir.CallExpr).Use = ir.CallUseStmt
+ }
typecheckslice(n.Init().Slice(), ctxStmt) // imported rewritten f(g()) calls (#30907)
n.SetLeft(typecheck(n.Left(), ctxExpr|ctxType|ctxCallee))
if n.Left().Diag() {
@@ -1299,11 +1344,41 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
}
// builtin: OLEN, OCAP, etc.
- n.SetOp(l.SubOp())
- n.SetLeft(n.Right())
- n.SetRight(nil)
- n = typecheck1(n, top)
- return n
+ switch l.SubOp() {
+ default:
+ base.Fatalf("unknown builtin %v", l)
+ return n
+
+ case ir.OAPPEND, ir.ODELETE, ir.OMAKE, ir.OPRINT, ir.OPRINTN, ir.ORECOVER:
+ n.SetOp(l.SubOp())
+ n.SetLeft(nil)
+ n.SetTypecheck(0) // re-typechecking new op is OK, not a loop
+
+ case ir.OCAP, ir.OCLOSE, ir.OIMAG, ir.OLEN, ir.OPANIC, ir.OREAL:
+ typecheckargs(n)
+ fallthrough
+ case ir.ONEW, ir.OALIGNOF, ir.OOFFSETOF, ir.OSIZEOF:
+ arg, ok := needOneArg(n, "%v", n.Op())
+ if !ok {
+ n.SetType(nil)
+ return n
+ }
+ old := n
+ n = ir.NodAt(n.Pos(), l.SubOp(), arg, nil)
+ n = initExpr(old.Init().Slice(), n) // typecheckargs can add to old.Init
+
+ case ir.OCOMPLEX, ir.OCOPY:
+ typecheckargs(n)
+ arg1, arg2, ok := needTwoArgs(n)
+ if !ok {
+ n.SetType(nil)
+ return n
+ }
+ old := n
+ n = ir.NodAt(n.Pos(), l.SubOp(), arg1, arg2)
+ n = initExpr(old.Init().Slice(), n) // typecheckargs can add to old.Init
+ }
+ return typecheck(n, top)
}
n.SetLeft(defaultlit(n.Left(), nil))
@@ -1317,19 +1392,15 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
}
// pick off before type-checking arguments
- ok |= ctxExpr
-
- // turn CALL(type, arg) into CONV(arg) w/ type
- n.SetLeft(nil)
-
- n.SetOp(ir.OCONV)
- n.SetType(l.Type())
- if !onearg(n, "conversion to %v", l.Type()) {
+ arg, ok := needOneArg(n, "conversion to %v", l.Type())
+ if !ok {
n.SetType(nil)
return n
}
- n = typecheck1(n, top)
- return n
+
+ n = ir.NodAt(n.Pos(), ir.OCONV, arg, nil)
+ n.SetType(l.Type())
+ return typecheck1(n, top)
}
typecheckargs(n)
@@ -1359,15 +1430,16 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
default:
n.SetOp(ir.OCALLFUNC)
- if t.Etype != types.TFUNC {
- name := l.String()
- if isBuiltinFuncName(name) && l.Name().Defn != nil {
- // be more specific when the function
+ if t.Kind() != types.TFUNC {
+ // TODO(mdempsky): Remove "o.Sym() != nil" once we stop
+ // using ir.Name for numeric literals.
+ if o := ir.Orig(l); o.Name() != nil && o.Sym() != nil && types.BuiltinPkg.Lookup(o.Sym().Name).Def != nil {
+ // be more specific when the non-function
// name matches a predeclared function
- base.Errorf("cannot call non-function %s (type %v), declared at %s",
- name, t, base.FmtPos(l.Name().Defn.Pos()))
+ base.Errorf("cannot call non-function %L, declared at %s",
+ l, base.FmtPos(o.Name().Pos()))
} else {
- base.Errorf("cannot call non-function %s (type %v)", name, t)
+ base.Errorf("cannot call non-function %L", l)
}
n.SetType(nil)
return n
@@ -1375,11 +1447,9 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
}
typecheckaste(ir.OCALL, n.Left(), n.IsDDD(), t.Params(), n.List(), func() string { return fmt.Sprintf("argument to %v", n.Left()) })
- ok |= ctxStmt
if t.NumResults() == 0 {
- break
+ return n
}
- ok |= ctxExpr
if t.NumResults() == 1 {
n.SetType(l.Type().Results().Field(0).Type)
@@ -1392,33 +1462,23 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
// and we want to avoid the temporaries, so we do the rewrite earlier than is typical.
n.SetOp(ir.OGETG)
}
-
- break
+ return n
}
// multiple return
if top&(ctxMultiOK|ctxStmt) == 0 {
base.Errorf("multiple-value %v() in single-value context", l)
- break
+ return n
}
n.SetType(l.Type().Results())
+ return n
case ir.OALIGNOF, ir.OOFFSETOF, ir.OSIZEOF:
- ok |= ctxExpr
- if !onearg(n, "%v", n.Op()) {
- n.SetType(nil)
- return n
- }
n.SetType(types.Types[types.TUINTPTR])
+ return n
case ir.OCAP, ir.OLEN:
- ok |= ctxExpr
- if !onearg(n, "%v", n.Op()) {
- n.SetType(nil)
- return n
- }
-
n.SetLeft(typecheck(n.Left(), ctxExpr))
n.SetLeft(defaultlit(n.Left(), nil))
n.SetLeft(implicitstar(n.Left()))
@@ -1431,9 +1491,9 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
var ok bool
if n.Op() == ir.OLEN {
- ok = okforlen[t.Etype]
+ ok = okforlen[t.Kind()]
} else {
- ok = okforcap[t.Etype]
+ ok = okforcap[t.Kind()]
}
if !ok {
base.Errorf("invalid argument %L for %v", l, n.Op())
@@ -1442,14 +1502,9 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
}
n.SetType(types.Types[types.TINT])
+ return n
case ir.OREAL, ir.OIMAG:
- ok |= ctxExpr
- if !onearg(n, "%v", n.Op()) {
- n.SetType(nil)
- return n
- }
-
n.SetLeft(typecheck(n.Left(), ctxExpr))
l := n.Left()
t := l.Type()
@@ -1459,7 +1514,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
}
// Determine result type.
- switch t.Etype {
+ switch t.Kind() {
case types.TIDEAL:
n.SetType(types.UntypedFloat)
case types.TCOMPLEX64:
@@ -1471,16 +1526,11 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
n.SetType(nil)
return n
}
+ return n
case ir.OCOMPLEX:
- ok |= ctxExpr
- typecheckargs(n)
- if !twoarg(n) {
- n.SetType(nil)
- return n
- }
- l := n.Left()
- r := n.Right()
+ l := typecheck(n.Left(), ctxExpr)
+ r := typecheck(n.Right(), ctxExpr)
if l.Type() == nil || r.Type() == nil {
n.SetType(nil)
return n
@@ -1500,7 +1550,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
}
var t *types.Type
- switch l.Type().Etype {
+ switch l.Type().Kind() {
default:
base.Errorf("invalid operation: %v (arguments have type %v, expected floating-point)", n, l.Type())
n.SetType(nil)
@@ -1516,12 +1566,9 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
t = types.Types[types.TCOMPLEX128]
}
n.SetType(t)
+ return n
case ir.OCLOSE:
- if !onearg(n, "%v", n.Op()) {
- n.SetType(nil)
- return n
- }
n.SetLeft(typecheck(n.Left(), ctxExpr))
n.SetLeft(defaultlit(n.Left(), nil))
l := n.Left()
@@ -1541,11 +1588,9 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
n.SetType(nil)
return n
}
-
- ok |= ctxStmt
+ return n
case ir.ODELETE:
- ok |= ctxStmt
typecheckargs(n)
args := n.List()
if args.Len() == 0 {
@@ -1575,9 +1620,9 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
}
args.SetSecond(assignconv(r, l.Type().Key(), "delete"))
+ return n
case ir.OAPPEND:
- ok |= ctxExpr
typecheckargs(n)
args := n.List()
if args.Len() == 0 {
@@ -1620,11 +1665,11 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
if t.Elem().IsKind(types.TUINT8) && args.Second().Type().IsString() {
args.SetSecond(defaultlit(args.Second(), types.Types[types.TSTRING]))
- break
+ return n
}
- args.SetSecond(assignconv(args.Second(), t.Orig, "append"))
- break
+ args.SetSecond(assignconv(args.Second(), t.Underlying(), "append"))
+ return n
}
as := args.Slice()[1:]
@@ -1635,20 +1680,13 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
as[i] = assignconv(n, t.Elem(), "append")
checkwidth(as[i].Type()) // ensure width is calculated for backend
}
+ return n
case ir.OCOPY:
- ok |= ctxStmt | ctxExpr
- typecheckargs(n)
- if !twoarg(n) {
- n.SetType(nil)
- return n
- }
n.SetType(types.Types[types.TINT])
- if n.Left().Type() == nil || n.Right().Type() == nil {
- n.SetType(nil)
- return n
- }
+ n.SetLeft(typecheck(n.Left(), ctxExpr))
n.SetLeft(defaultlit(n.Left(), nil))
+ n.SetRight(typecheck(n.Right(), ctxExpr))
n.SetRight(defaultlit(n.Right(), nil))
if n.Left().Type() == nil || n.Right().Type() == nil {
n.SetType(nil)
@@ -1657,8 +1695,8 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
// copy([]byte, string)
if n.Left().Type().IsSlice() && n.Right().Type().IsString() {
- if types.Identical(n.Left().Type().Elem(), types.Bytetype) {
- break
+ if types.Identical(n.Left().Type().Elem(), types.ByteType) {
+ return n
}
base.Errorf("arguments to copy have different element types: %L and string", n.Left().Type())
n.SetType(nil)
@@ -1682,9 +1720,9 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
n.SetType(nil)
return n
}
+ return n
case ir.OCONV:
- ok |= ctxExpr
checkwidth(n.Type()) // ensure width is calculated for backend
n.SetLeft(typecheck(n.Left(), ctxExpr))
n.SetLeft(convlit1(n.Left(), n.Type(), true, nil))
@@ -1694,8 +1732,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
return n
}
op, why := convertop(n.Left().Op() == ir.OLITERAL, t, n.Type())
- n.SetOp(op)
- if n.Op() == ir.OXXX {
+ if op == ir.OXXX {
if !n.Diag() && !n.Type().Broke() && !n.Left().Diag() {
base.Errorf("cannot convert %L to type %v%s", n.Left(), n.Type(), why)
n.SetDiag(true)
@@ -1705,10 +1742,11 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
return n
}
+ n.SetOp(op)
switch n.Op() {
case ir.OCONVNOP:
- if t.Etype == n.Type().Etype {
- switch t.Etype {
+ if t.Kind() == n.Type().Kind() {
+ switch t.Kind() {
case types.TFLOAT32, types.TFLOAT64, types.TCOMPLEX64, types.TCOMPLEX128:
// Floating point casts imply rounding and
// so the conversion must be kept.
@@ -1719,16 +1757,16 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
// do not convert to []byte literal. See CL 125796.
// generated code and compiler memory footprint is better without it.
case ir.OSTR2BYTES:
- break
+ // ok
case ir.OSTR2RUNES:
if n.Left().Op() == ir.OLITERAL {
n = stringtoruneslit(n)
}
}
+ return n
case ir.OMAKE:
- ok |= ctxExpr
args := n.List().Slice()
if len(args) == 0 {
base.Errorf("missing argument to make")
@@ -1746,7 +1784,8 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
}
i := 1
- switch t.Etype {
+ var nn ir.Node
+ switch t.Kind() {
default:
base.Errorf("cannot make type %v", t)
n.SetType(nil)
@@ -1782,10 +1821,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
n.SetType(nil)
return n
}
-
- n.SetLeft(l)
- n.SetRight(r)
- n.SetOp(ir.OMAKESLICE)
+ nn = ir.NodAt(n.Pos(), ir.OMAKESLICE, l, r)
case types.TMAP:
if i < len(args) {
@@ -1801,11 +1837,11 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
n.SetType(nil)
return n
}
- n.SetLeft(l)
} else {
- n.SetLeft(nodintconst(0))
+ l = nodintconst(0)
}
- n.SetOp(ir.OMAKEMAP)
+ nn = ir.NodAt(n.Pos(), ir.OMAKEMAP, l, nil)
+ nn.SetEsc(n.Esc())
case types.TCHAN:
l = nil
@@ -1822,49 +1858,40 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
n.SetType(nil)
return n
}
- n.SetLeft(l)
} else {
- n.SetLeft(nodintconst(0))
+ l = nodintconst(0)
}
- n.SetOp(ir.OMAKECHAN)
+ nn = ir.NodAt(n.Pos(), ir.OMAKECHAN, l, nil)
}
if i < len(args) {
base.Errorf("too many arguments to make(%v)", t)
- n.SetOp(ir.OMAKE)
n.SetType(nil)
return n
}
- n.SetType(t)
+ nn.SetType(t)
+ n = nn
+ return n
case ir.ONEW:
- ok |= ctxExpr
- args := n.List()
- if args.Len() == 0 {
- base.Errorf("missing argument to new")
- n.SetType(nil)
- return n
+ if n.Left() == nil {
+ // Fatalf because the OCALL above checked for us,
+ // so this must be an internally-generated mistake.
+ base.Fatalf("missing argument to new")
}
-
- l := args.First()
+ l := n.Left()
l = typecheck(l, ctxType)
t := l.Type()
if t == nil {
n.SetType(nil)
return n
}
- if args.Len() > 1 {
- base.Errorf("too many arguments to new(%v)", t)
- n.SetType(nil)
- return n
- }
-
n.SetLeft(l)
n.SetType(types.NewPtr(t))
+ return n
case ir.OPRINT, ir.OPRINTN:
- ok |= ctxStmt
typecheckargs(n)
ls := n.List().Slice()
for i1, n1 := range ls {
@@ -1875,22 +1902,18 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
ls[i1] = defaultlit(ls[i1], nil)
}
}
+ return n
case ir.OPANIC:
- ok |= ctxStmt
- if !onearg(n, "panic") {
- n.SetType(nil)
- return n
- }
n.SetLeft(typecheck(n.Left(), ctxExpr))
n.SetLeft(defaultlit(n.Left(), types.Types[types.TINTER]))
if n.Left().Type() == nil {
n.SetType(nil)
return n
}
+ return n
case ir.ORECOVER:
- ok |= ctxExpr | ctxStmt
if n.List().Len() != 0 {
base.Errorf("too many arguments to recover")
n.SetType(nil)
@@ -1898,16 +1921,16 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
}
n.SetType(types.Types[types.TINTER])
+ return n
case ir.OCLOSURE:
- ok |= ctxExpr
typecheckclosure(n, top)
if n.Type() == nil {
return n
}
+ return n
case ir.OITAB:
- ok |= ctxExpr
n.SetLeft(typecheck(n.Left(), ctxExpr))
t := n.Left().Type()
if t == nil {
@@ -1918,14 +1941,15 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
base.Fatalf("OITAB of %v", t)
}
n.SetType(types.NewPtr(types.Types[types.TUINTPTR]))
+ return n
case ir.OIDATA:
// Whoever creates the OIDATA node must know a priori the concrete type at that moment,
// usually by just having checked the OITAB.
base.Fatalf("cannot typecheck interface data %v", n)
+ panic("unreachable")
case ir.OSPTR:
- ok |= ctxExpr
n.SetLeft(typecheck(n.Left(), ctxExpr))
t := n.Left().Type()
if t == nil {
@@ -1940,69 +1964,65 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
} else {
n.SetType(types.NewPtr(t.Elem()))
}
+ return n
- case ir.OCLOSUREVAR:
- ok |= ctxExpr
+ case ir.OCLOSUREREAD:
+ return n
case ir.OCFUNC:
- ok |= ctxExpr
n.SetLeft(typecheck(n.Left(), ctxExpr))
n.SetType(types.Types[types.TUINTPTR])
+ return n
case ir.OCONVNOP:
- ok |= ctxExpr
n.SetLeft(typecheck(n.Left(), ctxExpr))
+ return n
// statements
case ir.OAS:
- ok |= ctxStmt
-
typecheckas(n)
// Code that creates temps does not bother to set defn, so do it here.
if n.Left().Op() == ir.ONAME && ir.IsAutoTmp(n.Left()) {
n.Left().Name().Defn = n
}
+ return n
case ir.OAS2:
- ok |= ctxStmt
typecheckas2(n)
+ return n
case ir.OBREAK,
ir.OCONTINUE,
ir.ODCL,
- ir.OEMPTY,
ir.OGOTO,
ir.OFALL,
ir.OVARKILL,
ir.OVARLIVE:
- ok |= ctxStmt
+ return n
+
+ case ir.OBLOCK:
+ typecheckslice(n.List().Slice(), ctxStmt)
+ return n
case ir.OLABEL:
- ok |= ctxStmt
decldepth++
if n.Sym().IsBlank() {
// Empty identifier is valid but useless.
// Eliminate now to simplify life later.
// See issues 7538, 11589, 11593.
- n.SetOp(ir.OEMPTY)
- n.SetLeft(nil)
+ n = ir.NodAt(n.Pos(), ir.OBLOCK, nil, nil)
}
+ return n
- case ir.ODEFER:
- ok |= ctxStmt
+ case ir.ODEFER, ir.OGO:
n.SetLeft(typecheck(n.Left(), ctxStmt|ctxExpr))
if !n.Left().Diag() {
checkdefergo(n)
}
-
- case ir.OGO:
- ok |= ctxStmt
- n.SetLeft(typecheck(n.Left(), ctxStmt|ctxExpr))
- checkdefergo(n)
+ return n
case ir.OFOR, ir.OFORUNTIL:
- ok |= ctxStmt
typecheckslice(n.Init().Slice(), ctxStmt)
decldepth++
n.SetLeft(typecheck(n.Left(), ctxExpr))
@@ -2019,9 +2039,9 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
}
typecheckslice(n.Body().Slice(), ctxStmt)
decldepth--
+ return n
case ir.OIF:
- ok |= ctxStmt
typecheckslice(n.Init().Slice(), ctxStmt)
n.SetLeft(typecheck(n.Left(), ctxExpr))
n.SetLeft(defaultlit(n.Left(), nil))
@@ -2033,9 +2053,9 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
}
typecheckslice(n.Body().Slice(), ctxStmt)
typecheckslice(n.Rlist().Slice(), ctxStmt)
+ return n
case ir.ORETURN:
- ok |= ctxStmt
typecheckargs(n)
if Curfn == nil {
base.Errorf("return outside function")
@@ -2043,25 +2063,26 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
return n
}
- if Curfn.Type().FuncType().Outnamed && n.List().Len() == 0 {
- break
+ if hasNamedResults(Curfn) && n.List().Len() == 0 {
+ return n
}
typecheckaste(ir.ORETURN, nil, false, Curfn.Type().Results(), n.List(), func() string { return "return argument" })
+ return n
case ir.ORETJMP:
- ok |= ctxStmt
+ return n
case ir.OSELECT:
- ok |= ctxStmt
typecheckselect(n)
+ return n
case ir.OSWITCH:
- ok |= ctxStmt
typecheckswitch(n)
+ return n
case ir.ORANGE:
- ok |= ctxStmt
typecheckrange(n)
+ return n
case ir.OTYPESW:
base.Errorf("use of .(type) outside type switch")
@@ -2069,64 +2090,22 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
return n
case ir.ODCLFUNC:
- ok |= ctxStmt
- typecheckfunc(n)
+ typecheckfunc(n.(*ir.Func))
+ return n
case ir.ODCLCONST:
- ok |= ctxStmt
n.SetLeft(typecheck(n.Left(), ctxExpr))
+ return n
case ir.ODCLTYPE:
- ok |= ctxStmt
n.SetLeft(typecheck(n.Left(), ctxType))
checkwidth(n.Left().Type())
- }
-
- t := n.Type()
- if t != nil && !t.IsFuncArgStruct() && n.Op() != ir.OTYPE {
- switch t.Etype {
- case types.TFUNC, // might have TANY; wait until it's called
- types.TANY, types.TFORW, types.TIDEAL, types.TNIL, types.TBLANK:
- break
-
- default:
- checkwidth(t)
- }
- }
-
- n = evalConst(n)
- if n.Op() == ir.OTYPE && top&ctxType == 0 {
- if !n.Type().Broke() {
- base.Errorf("type %v is not an expression", n.Type())
- }
- n.SetType(nil)
return n
}
- if top&(ctxExpr|ctxType) == ctxType && n.Op() != ir.OTYPE {
- base.Errorf("%v is not a type", n)
- n.SetType(nil)
- return n
- }
-
- // TODO(rsc): simplify
- if (top&(ctxCallee|ctxExpr|ctxType) != 0) && top&ctxStmt == 0 && ok&(ctxExpr|ctxType|ctxCallee) == 0 {
- base.Errorf("%v used as value", n)
- n.SetType(nil)
- return n
- }
-
- if (top&ctxStmt != 0) && top&(ctxCallee|ctxExpr|ctxType) == 0 && ok&ctxStmt == 0 {
- if !n.Diag() {
- base.Errorf("%v evaluated but not used", n)
- n.SetDiag(true)
- }
-
- n.SetType(nil)
- return n
- }
-
- return n
+ // No return n here!
+ // Individual cases can type-assert n, introducing a new one.
+ // Each must execute its own return n.
}
func typecheckargs(n ir.Node) {
@@ -2144,8 +2123,8 @@ func typecheckargs(n ir.Node) {
// Rewrite f(g()) into t1, t2, ... = g(); f(t1, t2, ...).
// Save n as n.Orig for fmt.go.
- if n.Orig() == n {
- n.SetOrig(ir.SepCopy(n))
+ if ir.Orig(n) == n {
+ n.(ir.OrigNode).SetOrig(ir.SepCopy(n))
}
as := ir.Nod(ir.OAS2, nil, nil)
@@ -2192,8 +2171,8 @@ func checksliceindex(l ir.Node, r ir.Node, tp *types.Type) bool {
} else if tp != nil && tp.NumElem() >= 0 && constant.Compare(x, token.GTR, constant.MakeInt64(tp.NumElem())) {
base.Errorf("invalid slice index %v (out of bounds for %d-element array)", r, tp.NumElem())
return false
- } else if ir.IsConst(l, constant.String) && constant.Compare(x, token.GTR, constant.MakeInt64(int64(len(l.StringVal())))) {
- base.Errorf("invalid slice index %v (out of bounds for %d-byte string)", r, len(l.StringVal()))
+ } else if ir.IsConst(l, constant.String) && constant.Compare(x, token.GTR, constant.MakeInt64(int64(len(ir.StringVal(l))))) {
+ base.Errorf("invalid slice index %v (out of bounds for %d-byte string)", r, len(ir.StringVal(l)))
return false
} else if doesoverflow(x, types.Types[types.TINT]) {
base.Errorf("invalid slice index %v (index too large)", r)
@@ -2245,7 +2224,7 @@ func checkdefergo(n ir.Node) {
ir.ONEW,
ir.OREAL,
ir.OLITERAL: // conversion or unsafe.Alignof, Offsetof, Sizeof
- if n.Left().Orig() != nil && n.Left().Orig().Op() == ir.OCONV {
+ if orig := ir.Orig(n.Left()); orig.Op() == ir.OCONV {
break
}
base.ErrorfAt(n.Pos(), "%s discards result of %v", what, n.Left())
@@ -2287,45 +2266,32 @@ func implicitstar(n ir.Node) ir.Node {
return n
}
-func onearg(n ir.Node, f string, args ...interface{}) bool {
- if n.Left() != nil {
- return true
- }
+func needOneArg(n ir.Node, f string, args ...interface{}) (ir.Node, bool) {
if n.List().Len() == 0 {
p := fmt.Sprintf(f, args...)
base.Errorf("missing argument to %s: %v", p, n)
- return false
+ return nil, false
}
if n.List().Len() > 1 {
p := fmt.Sprintf(f, args...)
base.Errorf("too many arguments to %s: %v", p, n)
- n.SetLeft(n.List().First())
- n.PtrList().Set(nil)
- return false
+ return n.List().First(), false
}
- n.SetLeft(n.List().First())
- n.PtrList().Set(nil)
- return true
+ return n.List().First(), true
}
-func twoarg(n ir.Node) bool {
- if n.Left() != nil {
- return true
- }
+func needTwoArgs(n ir.Node) (ir.Node, ir.Node, bool) {
if n.List().Len() != 2 {
if n.List().Len() < 2 {
base.Errorf("not enough arguments in call to %v", n)
} else {
base.Errorf("too many arguments in call to %v", n)
}
- return false
+ return nil, nil, false
}
- n.SetLeft(n.List().First())
- n.SetRight(n.List().Second())
- n.PtrList().Set(nil)
- return true
+ return n.List().First(), n.List().Second(), true
}
func lookdot1(errnode ir.Node, s *types.Sym, t *types.Type, fs *types.Fields, dostrcmp int) *types.Field {
@@ -2387,7 +2353,7 @@ func typecheckMethodExpr(n ir.Node) (res ir.Node) {
// types declared at package scope. However, we need
// to make sure to generate wrappers for anonymous
// receiver types too.
- if mt.Sym == nil {
+ if mt.Sym() == nil {
addsignat(t)
}
}
@@ -2412,24 +2378,19 @@ func typecheckMethodExpr(n ir.Node) (res ir.Node) {
return n
}
- n.SetOp(ir.OMETHEXPR)
- if n.Name() == nil {
- n.SetName(new(ir.Name))
- }
- n.SetRight(NewName(n.Sym()))
- n.SetSym(methodSym(t, n.Sym()))
- n.SetType(methodfunc(m.Type, n.Left().Type()))
- n.SetOffset(0)
- n.SetClass(ir.PFUNC)
- n.SetOpt(m)
- // methodSym already marked n.Sym as a function.
+ me := ir.NodAt(n.Pos(), ir.OMETHEXPR, n.Left(), NewName(n.Sym()))
+ me.SetSym(methodSym(t, n.Sym()))
+ me.SetType(methodfunc(m.Type, n.Left().Type()))
+ me.SetOffset(0)
+ me.SetClass(ir.PFUNC)
+ me.(*ir.MethodExpr).Method = m
// Issue 25065. Make sure that we emit the symbol for a local method.
- if base.Ctxt.Flag_dynlink && !inimport && (t.Sym == nil || t.Sym.Pkg == ir.LocalPkg) {
- makefuncsym(n.Sym())
+ if base.Ctxt.Flag_dynlink && !inimport && (t.Sym() == nil || t.Sym().Pkg == types.LocalPkg) {
+ makefuncsym(me.Sym())
}
- return n
+ return me
}
// isMethodApplicable reports whether method m can be called on a
@@ -2457,7 +2418,7 @@ func lookdot(n ir.Node, t *types.Type, dostrcmp int) *types.Field {
}
var f2 *types.Field
- if n.Left().Type() == t || n.Left().Type().Sym == nil {
+ if n.Left().Type() == t || n.Left().Type().Sym() == nil {
mt := methtype(t)
if mt != nil {
f2 = lookdot1(n, s, mt, mt.Methods(), dostrcmp)
@@ -2485,10 +2446,8 @@ func lookdot(n ir.Node, t *types.Type, dostrcmp int) *types.Field {
}
n.SetOp(ir.ODOTINTER)
- } else {
- n.SetOpt(f1)
}
-
+ n.(*ir.SelectorExpr).Selection = f1
return f1
}
@@ -2533,7 +2492,7 @@ func lookdot(n ir.Node, t *types.Type, dostrcmp int) *types.Field {
pll = ll
ll = ll.Left()
}
- if pll.Implicit() && ll.Type().IsPtr() && ll.Type().Sym != nil && ir.AsNode(ll.Type().Sym.Def) != nil && ir.AsNode(ll.Type().Sym.Def).Op() == ir.OTYPE {
+ if pll.Implicit() && ll.Type().IsPtr() && ll.Type().Sym() != nil && ll.Type().Sym().Def != nil && ir.AsNode(ll.Type().Sym().Def).Op() == ir.OTYPE {
// It is invalid to automatically dereference a named pointer type when selecting a method.
// Make n.Left == ll to clarify error message.
n.SetLeft(ll)
@@ -2544,7 +2503,7 @@ func lookdot(n ir.Node, t *types.Type, dostrcmp int) *types.Field {
n.SetOffset(f2.Offset)
n.SetType(f2.Type)
n.SetOp(ir.ODOTMETH)
- n.SetOpt(f2)
+ n.(*ir.SelectorExpr).Selection = f2
return f2
}
@@ -2721,7 +2680,7 @@ func sigrepr(t *types.Type, isddd bool) string {
return "bool"
}
- if t.Etype == types.TIDEAL {
+ if t.Kind() == types.TIDEAL {
// "untyped number" is not commonly used
// outside of the compiler, so let's use "number".
// TODO(mdempsky): Revisit this.
@@ -2764,7 +2723,7 @@ func fielddup(name string, hash map[string]bool) {
// iscomptype reports whether type t is a composite literal type.
func iscomptype(t *types.Type) bool {
- switch t.Etype {
+ switch t.Kind() {
case types.TARRAY, types.TSLICE, types.TSTRUCT, types.TMAP:
return true
default:
@@ -2782,11 +2741,11 @@ func pushtype(n ir.Node, t *types.Type) ir.Node {
switch {
case iscomptype(t):
// For T, return T{...}.
- n.SetRight(typenod(t))
+ n.SetRight(ir.TypeNode(t))
case t.IsPtr() && iscomptype(t.Elem()):
// For *T, return &T{...}.
- n.SetRight(typenod(t.Elem()))
+ n.SetRight(ir.TypeNode(t.Elem()))
n = ir.NodAt(n.Pos(), ir.OADDR, n, nil)
n.SetImplicit(true)
@@ -2814,21 +2773,19 @@ func typecheckcomplit(n ir.Node) (res ir.Node) {
}
// Save original node (including n.Right)
- n.SetOrig(ir.Copy(n))
+ n.(ir.OrigNode).SetOrig(ir.Copy(n))
setlineno(n.Right())
// Need to handle [...]T arrays specially.
- if n.Right().Op() == ir.OTARRAY && n.Right().Left() != nil && n.Right().Left().Op() == ir.ODDD {
- n.Right().SetRight(typecheck(n.Right().Right(), ctxType))
- if n.Right().Right().Type() == nil {
+ if array, ok := n.Right().(*ir.ArrayType); ok && array.Elem != nil && array.Len == nil {
+ array.Elem = typecheck(array.Elem, ctxType)
+ elemType := array.Elem.Type()
+ if elemType == nil {
n.SetType(nil)
return n
}
- elemType := n.Right().Right().Type()
-
length := typecheckarraylit(elemType, -1, n.List().Slice(), "array literal")
-
n.SetOp(ir.OARRAYLIT)
n.SetType(types.NewArray(elemType, length))
n.SetRight(nil)
@@ -2843,7 +2800,7 @@ func typecheckcomplit(n ir.Node) (res ir.Node) {
}
n.SetType(t)
- switch t.Etype {
+ switch t.Kind() {
default:
base.Errorf("invalid composite literal type %v", t)
n.SetType(nil)
@@ -2905,7 +2862,7 @@ func typecheckcomplit(n ir.Node) (res ir.Node) {
f := t.Field(i)
s := f.Sym
- if s != nil && !types.IsExported(s.Name) && s.Pkg != ir.LocalPkg {
+ if s != nil && !types.IsExported(s.Name) && s.Pkg != types.LocalPkg {
base.Errorf("implicit assignment of unexported field '%s' in %v literal", s.Name, t)
}
// No pushtype allowed here. Must name fields for that.
@@ -2928,9 +2885,9 @@ func typecheckcomplit(n ir.Node) (res ir.Node) {
if l.Op() == ir.OKEY {
key := l.Left()
- l.SetOp(ir.OSTRUCTKEY)
- l.SetLeft(l.Right())
- l.SetRight(nil)
+ sk := ir.NewStructKeyExpr(l.Pos(), nil, l.Right())
+ ls[i] = sk
+ l = sk
// An OXDOT uses the Sym field to hold
// the field to the right of the dot,
@@ -2938,7 +2895,7 @@ func typecheckcomplit(n ir.Node) (res ir.Node) {
// is never a valid struct literal key.
if key.Sym() == nil || key.Op() == ir.OXDOT || key.Sym().IsBlank() {
base.Errorf("invalid field name %v in struct initializer", key)
- l.SetLeft(typecheck(l.Left(), ctxExpr))
+ sk.SetLeft(typecheck(sk.Left(), ctxExpr))
continue
}
@@ -2946,13 +2903,13 @@ func typecheckcomplit(n ir.Node) (res ir.Node) {
// package, because of import dot. Redirect to correct sym
// before we do the lookup.
s := key.Sym()
- if s.Pkg != ir.LocalPkg && types.IsExported(s.Name) {
+ if s.Pkg != types.LocalPkg && types.IsExported(s.Name) {
s1 := lookup(s.Name)
if s1.Origpkg == s.Pkg {
s = s1
}
}
- l.SetSym(s)
+ sk.SetSym(s)
}
if l.Op() != ir.OSTRUCTKEY {
@@ -3077,7 +3034,7 @@ func typecheckarraylit(elemType *types.Type, bound int64, elts []ir.Node, ctx st
// visible reports whether sym is exported or locally defined.
func visible(sym *types.Sym) bool {
- return sym != nil && (types.IsExported(sym.Name) || sym.Pkg == ir.LocalPkg)
+ return sym != nil && (types.IsExported(sym.Name) || sym.Pkg == types.LocalPkg)
}
// nonexported reports whether sym is an unexported field.
@@ -3096,7 +3053,7 @@ func islvalue(n ir.Node) bool {
return false
}
fallthrough
- case ir.ODEREF, ir.ODOTPTR, ir.OCLOSUREVAR:
+ case ir.ODEREF, ir.ODOTPTR, ir.OCLOSUREREAD:
return true
case ir.ODOT:
@@ -3120,7 +3077,7 @@ func checklvalue(n ir.Node, verb string) {
func checkassign(stmt ir.Node, n ir.Node) {
// Variables declared in ORANGE are assigned on every iteration.
- if n.Name() == nil || n.Name().Defn != stmt || stmt.Op() == ir.ORANGE {
+ if !ir.DeclaredBy(n, stmt) || stmt.Op() == ir.ORANGE {
r := outervalue(n)
if r.Op() == ir.ONAME {
r.Name().SetAssigned(true)
@@ -3183,7 +3140,7 @@ func samesafeexpr(l ir.Node, r ir.Node) bool {
}
switch l.Op() {
- case ir.ONAME, ir.OCLOSUREVAR:
+ case ir.ONAME, ir.OCLOSUREREAD:
return l == r
case ir.ODOT, ir.ODOTPTR:
@@ -3196,7 +3153,7 @@ func samesafeexpr(l ir.Node, r ir.Node) bool {
case ir.OCONV:
// Some conversions can't be reused, such as []byte(str).
// Allow only numeric-ish types. This is a bit conservative.
- return issimple[l.Type().Etype] && samesafeexpr(l.Left(), r.Left())
+ return issimple[l.Type().Kind()] && samesafeexpr(l.Left(), r.Left())
case ir.OINDEX, ir.OINDEXMAP,
ir.OADD, ir.OSUB, ir.OOR, ir.OXOR, ir.OMUL, ir.OLSH, ir.ORSH, ir.OAND, ir.OANDNOT, ir.ODIV, ir.OMOD:
@@ -3229,7 +3186,7 @@ func typecheckas(n ir.Node) {
// so that the conversion below happens).
n.SetLeft(resolve(n.Left()))
- if n.Left().Name() == nil || n.Left().Name().Defn != n || n.Left().Name().Param.Ntype != nil {
+ if !ir.DeclaredBy(n.Left(), n) || n.Left().Name().Ntype != nil {
n.SetLeft(typecheck(n.Left(), ctxExpr|ctxAssign))
}
@@ -3248,7 +3205,7 @@ func typecheckas(n ir.Node) {
}
}
- if n.Left().Name() != nil && n.Left().Name().Defn == n && n.Left().Name().Param.Ntype == nil {
+ if ir.DeclaredBy(n.Left(), n) && n.Left().Name().Ntype == nil {
n.SetRight(defaultlit(n.Right(), nil))
n.Left().SetType(n.Right().Type())
}
@@ -3284,7 +3241,7 @@ func typecheckas2(n ir.Node) {
n1 = resolve(n1)
ls[i1] = n1
- if n1.Name() == nil || n1.Name().Defn != n || n1.Name().Param.Ntype != nil {
+ if !ir.DeclaredBy(n1, n) || n1.Name().Ntype != nil {
ls[i1] = typecheck(ls[i1], ctxExpr|ctxAssign)
}
}
@@ -3309,7 +3266,7 @@ func typecheckas2(n ir.Node) {
if nl.Type() != nil && nr.Type() != nil {
rs[il] = assignconv(nr, nl.Type(), "assignment")
}
- if nl.Name() != nil && nl.Name().Defn == n && nl.Name().Param.Ntype == nil {
+ if ir.DeclaredBy(nl, n) && nl.Name().Ntype == nil {
rs[il] = defaultlit(rs[il], nil)
nl.SetType(rs[il].Type())
}
@@ -3335,15 +3292,14 @@ func typecheckas2(n ir.Node) {
if cr != cl {
goto mismatch
}
+ r.(*ir.CallExpr).Use = ir.CallUseList
n.SetOp(ir.OAS2FUNC)
- n.SetRight(r)
- n.PtrRlist().Set(nil)
for i, l := range n.List().Slice() {
f := r.Type().Field(i)
if f.Type != nil && l.Type() != nil {
checkassignto(f.Type, l)
}
- if l.Name() != nil && l.Name().Defn == n && l.Name().Param.Ntype == nil {
+ if ir.DeclaredBy(l, n) && l.Name().Ntype == nil {
l.SetType(f.Type)
}
}
@@ -3367,19 +3323,17 @@ func typecheckas2(n ir.Node) {
n.SetOp(ir.OAS2DOTTYPE)
r.SetOp(ir.ODOTTYPE2)
}
- n.SetRight(r)
- n.PtrRlist().Set(nil)
if l.Type() != nil {
checkassignto(r.Type(), l)
}
- if l.Name() != nil && l.Name().Defn == n {
+ if ir.DeclaredBy(l, n) {
l.SetType(r.Type())
}
l := n.List().Second()
if l.Type() != nil && !l.Type().IsBoolean() {
checkassignto(types.Types[types.TBOOL], l)
}
- if l.Name() != nil && l.Name().Defn == n && l.Name().Param.Ntype == nil {
+ if ir.DeclaredBy(l, n) && l.Name().Ntype == nil {
l.SetType(types.Types[types.TBOOL])
}
goto out
@@ -3406,36 +3360,38 @@ out:
}
// type check function definition
-func typecheckfunc(n ir.Node) {
+// To be called by typecheck, not directly.
+// (Call typecheckFunc instead.)
+func typecheckfunc(n *ir.Func) {
if enableTrace && base.Flag.LowerT {
defer tracePrint("typecheckfunc", n)(nil)
}
- for _, ln := range n.Func().Dcl {
+ for _, ln := range n.Dcl {
if ln.Op() == ir.ONAME && (ln.Class() == ir.PPARAM || ln.Class() == ir.PPARAMOUT) {
- ln.Name().Decldepth = 1
+ ln.Decldepth = 1
}
}
- n.Func().Nname = typecheck(n.Func().Nname, ctxExpr|ctxAssign)
- t := n.Func().Nname.Type()
+ n.Nname = typecheck(n.Nname, ctxExpr|ctxAssign).(*ir.Name)
+ t := n.Nname.Type()
if t == nil {
return
}
n.SetType(t)
rcvr := t.Recv()
- if rcvr != nil && n.Func().Shortname != nil {
- m := addmethod(n, n.Func().Shortname, t, true, n.Func().Pragma&ir.Nointerface != 0)
+ if rcvr != nil && n.Shortname != nil {
+ m := addmethod(n, n.Shortname, t, true, n.Pragma&ir.Nointerface != 0)
if m == nil {
return
}
- n.Func().Nname.SetSym(methodSym(rcvr.Type, n.Func().Shortname))
- declare(n.Func().Nname, ir.PFUNC)
+ n.Nname.SetSym(methodSym(rcvr.Type, n.Shortname))
+ declare(n.Nname, ir.PFUNC)
}
- if base.Ctxt.Flag_dynlink && !inimport && n.Func().Nname != nil {
- makefuncsym(n.Func().Nname.Sym())
+ if base.Ctxt.Flag_dynlink && !inimport && n.Nname != nil {
+ makefuncsym(n.Sym())
}
}
@@ -3448,18 +3404,18 @@ func stringtoruneslit(n ir.Node) ir.Node {
var l []ir.Node
i := 0
- for _, r := range n.Left().StringVal() {
+ for _, r := range ir.StringVal(n.Left()) {
l = append(l, ir.Nod(ir.OKEY, nodintconst(int64(i)), nodintconst(int64(r))))
i++
}
- nn := ir.Nod(ir.OCOMPLIT, nil, typenod(n.Type()))
+ nn := ir.Nod(ir.OCOMPLIT, nil, ir.TypeNode(n.Type()))
nn.PtrList().Set(l)
nn = typecheck(nn, ctxExpr)
return nn
}
-var mapqueue []ir.Node
+var mapqueue []*ir.MapType
func checkMapKeys() {
for _, n := range mapqueue {
@@ -3471,73 +3427,36 @@ func checkMapKeys() {
mapqueue = nil
}
-func setUnderlying(t, underlying *types.Type) {
- if underlying.Etype == types.TFORW {
- // This type isn't computed yet; when it is, update n.
- underlying.ForwardType().Copyto = append(underlying.ForwardType().Copyto, t)
- return
- }
-
- n := ir.AsNode(t.Nod)
- ft := t.ForwardType()
- cache := t.Cache
-
- // TODO(mdempsky): Fix Type rekinding.
- *t = *underlying
-
- // Restore unnecessarily clobbered attributes.
- t.Nod = n
- t.Sym = n.Sym()
- if n.Name() != nil {
- t.Vargen = n.Name().Vargen
- }
- t.Cache = cache
- t.SetDeferwidth(false)
-
- // spec: "The declared type does not inherit any methods bound
- // to the existing type, but the method set of an interface
- // type [...] remains unchanged."
- if !t.IsInterface() {
- *t.Methods() = types.Fields{}
- *t.AllMethods() = types.Fields{}
- }
-
- // Propagate go:notinheap pragma from the Name to the Type.
- if n.Name() != nil && n.Name().Param != nil && n.Name().Param.Pragma()&ir.NotInHeap != 0 {
- t.SetNotInHeap(true)
- }
-
- // Update types waiting on this type.
- for _, w := range ft.Copyto {
- setUnderlying(w, t)
- }
-
- // Double-check use of type as embedded type.
- if ft.Embedlineno.IsKnown() {
- if t.IsPtr() || t.IsUnsafePtr() {
- base.ErrorfAt(ft.Embedlineno, "embedded type cannot be a pointer")
- }
- }
-}
-
-func typecheckdeftype(n ir.Node) {
+func typecheckdeftype(n *ir.Name) {
if enableTrace && base.Flag.LowerT {
defer tracePrint("typecheckdeftype", n)(nil)
}
+ t := types.NewNamed(n)
+ t.Vargen = n.Vargen
+ if n.Pragma()&ir.NotInHeap != 0 {
+ t.SetNotInHeap(true)
+ }
+
+ n.SetType(t)
n.SetTypecheck(1)
- n.Name().Param.Ntype = typecheck(n.Name().Param.Ntype, ctxType)
- t := n.Name().Param.Ntype.Type()
- if t == nil {
+ n.SetWalkdef(1)
+
+ defercheckwidth()
+ errorsBefore := base.Errors()
+ n.Ntype = typecheckNtype(n.Ntype)
+ if underlying := n.Ntype.Type(); underlying != nil {
+ t.SetUnderlying(underlying)
+ } else {
n.SetDiag(true)
n.SetType(nil)
- } else if n.Type() == nil {
- n.SetDiag(true)
- } else {
- // copy new type and clear fields
- // that don't come along.
- setUnderlying(n.Type(), t)
}
+ if t.Kind() == types.TFORW && base.Errors() > errorsBefore {
+ // Something went wrong during type-checking,
+ // but it was reported. Silence future errors.
+ t.SetBroke(true)
+ }
+ resumecheckwidth()
}
func typecheckdef(n ir.Node) {
@@ -3587,10 +3506,10 @@ func typecheckdef(n ir.Node) {
base.Fatalf("typecheckdef %v", n.Op())
case ir.OLITERAL:
- if n.Name().Param.Ntype != nil {
- n.Name().Param.Ntype = typecheck(n.Name().Param.Ntype, ctxType)
- n.SetType(n.Name().Param.Ntype.Type())
- n.Name().Param.Ntype = nil
+ if n.Name().Ntype != nil {
+ n.Name().Ntype = typecheckNtype(n.Name().Ntype)
+ n.SetType(n.Name().Ntype.Type())
+ n.Name().Ntype = nil
if n.Type() == nil {
n.SetDiag(true)
goto ret
@@ -3622,7 +3541,7 @@ func typecheckdef(n ir.Node) {
t := n.Type()
if t != nil {
- if !ir.OKForConst[t.Etype] {
+ if !ir.OKForConst[t.Kind()] {
base.ErrorfAt(n.Pos(), "invalid constant type %v", t)
goto ret
}
@@ -3641,9 +3560,9 @@ func typecheckdef(n ir.Node) {
}
case ir.ONAME:
- if n.Name().Param.Ntype != nil {
- n.Name().Param.Ntype = typecheck(n.Name().Param.Ntype, ctxType)
- n.SetType(n.Name().Param.Ntype.Type())
+ if n.Name().Ntype != nil {
+ n.Name().Ntype = typecheckNtype(n.Name().Ntype)
+ n.SetType(n.Name().Ntype.Type())
if n.Type() == nil {
n.SetDiag(true)
goto ret
@@ -3677,39 +3596,29 @@ func typecheckdef(n ir.Node) {
n.Name().Defn = typecheck(n.Name().Defn, ctxStmt) // fills in n.Type
case ir.OTYPE:
- if p := n.Name().Param; p.Alias() {
+ n := n.(*ir.Name)
+ if n.Alias() {
// Type alias declaration: Simply use the rhs type - no need
// to create a new type.
- // If we have a syntax error, p.Ntype may be nil.
- if p.Ntype != nil {
- p.Ntype = typecheck(p.Ntype, ctxType)
- n.SetType(p.Ntype.Type())
+ // If we have a syntax error, name.Ntype may be nil.
+ if n.Ntype != nil {
+ n.Ntype = typecheckNtype(n.Ntype)
+ n.SetType(n.Ntype.Type())
if n.Type() == nil {
n.SetDiag(true)
goto ret
}
// For package-level type aliases, set n.Sym.Def so we can identify
// it as a type alias during export. See also #31959.
- if n.Name().Curfn == nil {
- n.Sym().Def = p.Ntype
+ if n.Curfn == nil {
+ n.Sym().Def = n.Ntype
}
}
break
}
// regular type declaration
- defercheckwidth()
- n.SetWalkdef(1)
- setTypeNode(n, types.New(types.TFORW))
- n.Type().Sym = n.Sym()
- errorsBefore := base.Errors()
typecheckdeftype(n)
- if n.Type().Etype == types.TFORW && base.Errors() > errorsBefore {
- // Something went wrong during type-checking,
- // but it was reported. Silence future errors.
- n.Type().SetBroke(true)
- }
- resumecheckwidth()
}
ret:
@@ -3729,7 +3638,7 @@ ret:
func checkmake(t *types.Type, arg string, np *ir.Node) bool {
n := *np
- if !n.Type().IsInteger() && n.Type().Etype != types.TIDEAL {
+ if !n.Type().IsInteger() && n.Type().Kind() != types.TIDEAL {
base.Errorf("non-integer %s argument in make(%v) - %v", arg, t, n.Type())
return false
}
@@ -3759,59 +3668,52 @@ func checkmake(t *types.Type, arg string, np *ir.Node) bool {
return true
}
-func markbreak(n ir.Node, implicit ir.Node) {
- if n == nil {
- return
+// markBreak marks control statements containing break statements with SetHasBreak(true).
+func markBreak(fn *ir.Func) {
+ var labels map[*types.Sym]ir.Node
+ var implicit ir.Node
+
+ var mark func(ir.Node) error
+ mark = func(n ir.Node) error {
+ switch n.Op() {
+ default:
+ ir.DoChildren(n, mark)
+
+ case ir.OBREAK:
+ if n.Sym() == nil {
+ if implicit != nil {
+ implicit.SetHasBreak(true)
+ }
+ } else {
+ if lab := labels[n.Sym()]; lab != nil {
+ lab.SetHasBreak(true)
+ }
+ }
+
+ case ir.OFOR, ir.OFORUNTIL, ir.OSWITCH, ir.OTYPESW, ir.OSELECT, ir.ORANGE:
+ old := implicit
+ implicit = n
+ sym := n.Sym()
+ if sym != nil {
+ if labels == nil {
+ // Map creation delayed until we need it - most functions don't.
+ labels = make(map[*types.Sym]ir.Node)
+ }
+ labels[sym] = n
+ }
+ ir.DoChildren(n, mark)
+ if sym != nil {
+ delete(labels, sym)
+ }
+ implicit = old
+ }
+ return nil
}
- switch n.Op() {
- case ir.OBREAK:
- if n.Sym() == nil {
- if implicit != nil {
- implicit.SetHasBreak(true)
- }
- } else {
- lab := ir.AsNode(n.Sym().Label)
- if lab != nil {
- lab.SetHasBreak(true)
- }
- }
- case ir.OFOR, ir.OFORUNTIL, ir.OSWITCH, ir.OTYPESW, ir.OSELECT, ir.ORANGE:
- implicit = n
- fallthrough
- default:
- markbreak(n.Left(), implicit)
- markbreak(n.Right(), implicit)
- markbreaklist(n.Init(), implicit)
- markbreaklist(n.Body(), implicit)
- markbreaklist(n.List(), implicit)
- markbreaklist(n.Rlist(), implicit)
- }
+ mark(fn)
}
-func markbreaklist(l ir.Nodes, implicit ir.Node) {
- s := l.Slice()
- for i := 0; i < len(s); i++ {
- n := s[i]
- if n == nil {
- continue
- }
- if n.Op() == ir.OLABEL && i+1 < len(s) && n.Name().Defn == s[i+1] {
- switch n.Name().Defn.Op() {
- case ir.OFOR, ir.OFORUNTIL, ir.OSWITCH, ir.OTYPESW, ir.OSELECT, ir.ORANGE:
- n.Sym().Label = n.Name().Defn
- markbreak(n.Name().Defn, n.Name().Defn)
- n.Sym().Label = nil
- i++
- continue
- }
- }
-
- markbreak(n, implicit)
- }
-}
-
-// isterminating reports whether the Nodes list ends with a terminating statement.
+// isTermNodes reports whether the Nodes list ends with a terminating statement.
func isTermNodes(l ir.Nodes) bool {
s := l.Slice()
c := len(s)
@@ -3821,7 +3723,7 @@ func isTermNodes(l ir.Nodes) bool {
return isTermNode(s[c-1])
}
-// Isterminating reports whether the node n, the last one in a
+// isTermNode reports whether the node n, the last one in a
// statement list, is a terminating statement.
func isTermNode(n ir.Node) bool {
switch n.Op() {
@@ -3872,21 +3774,18 @@ func isTermNode(n ir.Node) bool {
}
// checkreturn makes sure that fn terminates appropriately.
-func checkreturn(fn ir.Node) {
+func checkreturn(fn *ir.Func) {
if fn.Type().NumResults() != 0 && fn.Body().Len() != 0 {
- markbreaklist(fn.Body(), nil)
+ markBreak(fn)
if !isTermNodes(fn.Body()) {
- base.ErrorfAt(fn.Func().Endlineno, "missing return at end of function")
+ base.ErrorfAt(fn.Endlineno, "missing return at end of function")
}
}
}
-func deadcode(fn ir.Node) {
+func deadcode(fn *ir.Func) {
deadcodeslice(fn.PtrBody())
- deadcodefn(fn)
-}
-func deadcodefn(fn ir.Node) {
if fn.Body().Len() == 0 {
return
}
@@ -3901,7 +3800,7 @@ func deadcodefn(fn ir.Node) {
return
}
case ir.OFOR:
- if !ir.IsConst(n.Left(), constant.Bool) || n.Left().BoolVal() {
+ if !ir.IsConst(n.Left(), constant.Bool) || ir.BoolVal(n.Left()) {
return
}
default:
@@ -3909,7 +3808,7 @@ func deadcodefn(fn ir.Node) {
}
}
- fn.PtrBody().Set([]ir.Node{ir.Nod(ir.OEMPTY, nil, nil)})
+ fn.PtrBody().Set([]ir.Node{ir.Nod(ir.OBLOCK, nil, nil)})
}
func deadcodeslice(nn *ir.Nodes) {
@@ -3931,7 +3830,7 @@ func deadcodeslice(nn *ir.Nodes) {
n.SetLeft(deadcodeexpr(n.Left()))
if ir.IsConst(n.Left(), constant.Bool) {
var body ir.Nodes
- if n.Left().BoolVal() {
+ if ir.BoolVal(n.Left()) {
n.SetRlist(ir.Nodes{})
body = n.Body()
} else {
@@ -3955,9 +3854,24 @@ func deadcodeslice(nn *ir.Nodes) {
}
deadcodeslice(n.PtrInit())
- deadcodeslice(n.PtrBody())
- deadcodeslice(n.PtrList())
- deadcodeslice(n.PtrRlist())
+ switch n.Op() {
+ case ir.OBLOCK:
+ deadcodeslice(n.PtrList())
+ case ir.OCASE:
+ deadcodeslice(n.PtrBody())
+ case ir.OFOR:
+ deadcodeslice(n.PtrBody())
+ case ir.OIF:
+ deadcodeslice(n.PtrBody())
+ deadcodeslice(n.PtrRlist())
+ case ir.ORANGE:
+ deadcodeslice(n.PtrBody())
+ case ir.OSELECT:
+ deadcodeslice(n.PtrList())
+ case ir.OSWITCH:
+ deadcodeslice(n.PtrList())
+ }
+
if cut {
nn.Set(nn.Slice()[:i+1])
break
@@ -3974,7 +3888,7 @@ func deadcodeexpr(n ir.Node) ir.Node {
n.SetLeft(deadcodeexpr(n.Left()))
n.SetRight(deadcodeexpr(n.Right()))
if ir.IsConst(n.Left(), constant.Bool) {
- if n.Left().BoolVal() {
+ if ir.BoolVal(n.Left()) {
return n.Right() // true && x => x
} else {
return n.Left() // false && x => false
@@ -3984,7 +3898,7 @@ func deadcodeexpr(n ir.Node) ir.Node {
n.SetLeft(deadcodeexpr(n.Left()))
n.SetRight(deadcodeexpr(n.Right()))
if ir.IsConst(n.Left(), constant.Bool) {
- if n.Left().BoolVal() {
+ if ir.BoolVal(n.Left()) {
return n.Left() // true || x => true
} else {
return n.Right() // false || x => x
@@ -3994,13 +3908,6 @@ func deadcodeexpr(n ir.Node) ir.Node {
return n
}
-// setTypeNode sets n to an OTYPE node representing t.
-func setTypeNode(n ir.Node, t *types.Type) {
- n.SetOp(ir.OTYPE)
- n.SetType(t)
- n.Type().Nod = n
-}
-
// getIotaValue returns the current value for "iota",
// or -1 if not within a ConstSpec.
func getIotaValue() int64 {
@@ -4022,30 +3929,26 @@ func curpkg() *types.Pkg {
fn := Curfn
if fn == nil {
// Initialization expressions for package-scope variables.
- return ir.LocalPkg
+ return types.LocalPkg
}
-
- // TODO(mdempsky): Standardize on either ODCLFUNC or ONAME for
- // Curfn, rather than mixing them.
- if fn.Op() == ir.ODCLFUNC {
- fn = fn.Func().Nname
- }
-
- return fnpkg(fn)
+ return fnpkg(fn.Nname)
}
// MethodName returns the ONAME representing the method
// referenced by expression n, which must be a method selector,
// method expression, or method value.
-func methodExprName(n ir.Node) ir.Node {
- return ir.AsNode(methodExprFunc(n).Nname)
+func methodExprName(n ir.Node) *ir.Name {
+ name, _ := methodExprFunc(n).Nname.(*ir.Name)
+ return name
}
// MethodFunc is like MethodName, but returns the types.Field instead.
func methodExprFunc(n ir.Node) *types.Field {
switch n.Op() {
- case ir.ODOTMETH, ir.OMETHEXPR:
- return n.Opt().(*types.Field)
+ case ir.ODOTMETH:
+ return n.(*ir.SelectorExpr).Selection
+ case ir.OMETHEXPR:
+ return n.(*ir.MethodExpr).Method
case ir.OCALLPART:
return callpartMethod(n)
}
diff --git a/src/cmd/compile/internal/gc/universe.go b/src/cmd/compile/internal/gc/universe.go
index 978e53ac15..66ca0d01b3 100644
--- a/src/cmd/compile/internal/gc/universe.go
+++ b/src/cmd/compile/internal/gc/universe.go
@@ -15,7 +15,7 @@ import (
var basicTypes = [...]struct {
name string
- etype types.EType
+ etype types.Kind
}{
{"int8", types.TINT8},
{"int16", types.TINT16},
@@ -35,9 +35,9 @@ var basicTypes = [...]struct {
var typedefs = [...]struct {
name string
- etype types.EType
- sameas32 types.EType
- sameas64 types.EType
+ etype types.Kind
+ sameas32 types.Kind
+ sameas64 types.Kind
}{
{"int", types.TINT, types.TINT32, types.TINT64},
{"uint", types.TUINT, types.TUINT32, types.TUINT64},
@@ -65,17 +65,6 @@ var builtinFuncs = [...]struct {
{"recover", ir.ORECOVER},
}
-// isBuiltinFuncName reports whether name matches a builtin function
-// name.
-func isBuiltinFuncName(name string) bool {
- for _, fn := range &builtinFuncs {
- if fn.name == name {
- return true
- }
- }
- return false
-}
-
var unsafeFuncs = [...]struct {
name string
op ir.Op
@@ -87,34 +76,82 @@ var unsafeFuncs = [...]struct {
// initUniverse initializes the universe block.
func initUniverse() {
- lexinit()
- typeinit()
- lexinit1()
-}
-
-// lexinit initializes known symbols and the basic types.
-func lexinit() {
- for _, s := range &basicTypes {
- etype := s.etype
- if int(etype) >= len(types.Types) {
- base.Fatalf("lexinit: %s bad etype", s.name)
- }
- s2 := ir.BuiltinPkg.Lookup(s.name)
- t := types.Types[etype]
- if t == nil {
- t = types.New(etype)
- t.Sym = s2
- if etype != types.TANY && etype != types.TSTRING {
- dowidth(t)
- }
- types.Types[etype] = t
- }
- s2.Def = typenod(t)
- ir.AsNode(s2.Def).SetName(new(ir.Name))
+ if Widthptr == 0 {
+ base.Fatalf("typeinit before betypeinit")
}
+ slicePtrOffset = 0
+ sliceLenOffset = Rnd(slicePtrOffset+int64(Widthptr), int64(Widthptr))
+ sliceCapOffset = Rnd(sliceLenOffset+int64(Widthptr), int64(Widthptr))
+ sizeofSlice = Rnd(sliceCapOffset+int64(Widthptr), int64(Widthptr))
+
+ // string is same as slice wo the cap
+ sizeofString = Rnd(sliceLenOffset+int64(Widthptr), int64(Widthptr))
+
+ for et := types.Kind(0); et < types.NTYPE; et++ {
+ simtype[et] = et
+ }
+
+ types.Types[types.TANY] = types.New(types.TANY)
+ types.Types[types.TINTER] = types.NewInterface(types.LocalPkg, nil)
+
+ defBasic := func(kind types.Kind, pkg *types.Pkg, name string) *types.Type {
+ sym := pkg.Lookup(name)
+ n := ir.NewDeclNameAt(src.NoXPos, sym)
+ n.SetOp(ir.OTYPE)
+ t := types.NewBasic(kind, n)
+ n.SetType(t)
+ sym.Def = n
+ if kind != types.TANY {
+ dowidth(t)
+ }
+ return t
+ }
+
+ for _, s := range &basicTypes {
+ types.Types[s.etype] = defBasic(s.etype, types.BuiltinPkg, s.name)
+ }
+
+ for _, s := range &typedefs {
+ sameas := s.sameas32
+ if Widthptr == 8 {
+ sameas = s.sameas64
+ }
+ simtype[s.etype] = sameas
+
+ types.Types[s.etype] = defBasic(s.etype, types.BuiltinPkg, s.name)
+ }
+
+ // We create separate byte and rune types for better error messages
+ // rather than just creating type alias *types.Sym's for the uint8 and
+ // int32 types. Hence, (bytetype|runtype).Sym.isAlias() is false.
+ // TODO(gri) Should we get rid of this special case (at the cost
+ // of less informative error messages involving bytes and runes)?
+ // (Alternatively, we could introduce an OTALIAS node representing
+ // type aliases, albeit at the cost of having to deal with it everywhere).
+ types.ByteType = defBasic(types.TUINT8, types.BuiltinPkg, "byte")
+ types.RuneType = defBasic(types.TINT32, types.BuiltinPkg, "rune")
+
+ // error type
+ s := types.BuiltinPkg.Lookup("error")
+ n := ir.NewDeclNameAt(src.NoXPos, s)
+ n.SetOp(ir.OTYPE)
+ types.ErrorType = types.NewNamed(n)
+ types.ErrorType.SetUnderlying(makeErrorInterface())
+ n.SetType(types.ErrorType)
+ s.Def = n
+ dowidth(types.ErrorType)
+
+ types.Types[types.TUNSAFEPTR] = defBasic(types.TUNSAFEPTR, unsafepkg, "Pointer")
+
+ // simple aliases
+ simtype[types.TMAP] = types.TPTR
+ simtype[types.TCHAN] = types.TPTR
+ simtype[types.TFUNC] = types.TPTR
+ simtype[types.TUNSAFEPTR] = types.TPTR
+
for _, s := range &builtinFuncs {
- s2 := ir.BuiltinPkg.Lookup(s.name)
+ s2 := types.BuiltinPkg.Lookup(s.name)
s2.Def = NewName(s2)
ir.AsNode(s2.Def).SetSubOp(s.op)
}
@@ -125,65 +162,36 @@ func lexinit() {
ir.AsNode(s2.Def).SetSubOp(s.op)
}
- types.UntypedString = types.New(types.TSTRING)
- types.UntypedBool = types.New(types.TBOOL)
- types.Types[types.TANY] = types.New(types.TANY)
-
- s := ir.BuiltinPkg.Lookup("true")
+ s = types.BuiltinPkg.Lookup("true")
s.Def = nodbool(true)
ir.AsNode(s.Def).SetSym(lookup("true"))
- ir.AsNode(s.Def).SetName(new(ir.Name))
- ir.AsNode(s.Def).SetType(types.UntypedBool)
- s = ir.BuiltinPkg.Lookup("false")
+ s = types.BuiltinPkg.Lookup("false")
s.Def = nodbool(false)
ir.AsNode(s.Def).SetSym(lookup("false"))
- ir.AsNode(s.Def).SetName(new(ir.Name))
- ir.AsNode(s.Def).SetType(types.UntypedBool)
s = lookup("_")
+ types.BlankSym = s
s.Block = -100
s.Def = NewName(s)
types.Types[types.TBLANK] = types.New(types.TBLANK)
ir.AsNode(s.Def).SetType(types.Types[types.TBLANK])
ir.BlankNode = ir.AsNode(s.Def)
+ ir.BlankNode.SetTypecheck(1)
- s = ir.BuiltinPkg.Lookup("_")
+ s = types.BuiltinPkg.Lookup("_")
s.Block = -100
s.Def = NewName(s)
types.Types[types.TBLANK] = types.New(types.TBLANK)
ir.AsNode(s.Def).SetType(types.Types[types.TBLANK])
types.Types[types.TNIL] = types.New(types.TNIL)
- s = ir.BuiltinPkg.Lookup("nil")
+ s = types.BuiltinPkg.Lookup("nil")
s.Def = nodnil()
ir.AsNode(s.Def).SetSym(s)
- ir.AsNode(s.Def).SetName(new(ir.Name))
- s = ir.BuiltinPkg.Lookup("iota")
- s.Def = ir.Nod(ir.OIOTA, nil, nil)
- ir.AsNode(s.Def).SetSym(s)
- ir.AsNode(s.Def).SetName(new(ir.Name))
-}
-
-func typeinit() {
- if Widthptr == 0 {
- base.Fatalf("typeinit before betypeinit")
- }
-
- for et := types.EType(0); et < types.NTYPE; et++ {
- simtype[et] = et
- }
-
- types.Types[types.TPTR] = types.New(types.TPTR)
- dowidth(types.Types[types.TPTR])
-
- t := types.New(types.TUNSAFEPTR)
- types.Types[types.TUNSAFEPTR] = t
- t.Sym = unsafepkg.Lookup("Pointer")
- t.Sym.Def = typenod(t)
- ir.AsNode(t.Sym.Def).SetName(new(ir.Name))
- dowidth(types.Types[types.TUNSAFEPTR])
+ s = types.BuiltinPkg.Lookup("iota")
+ s.Def = ir.NewIota(base.Pos, s)
for et := types.TINT8; et <= types.TUINT64; et++ {
isInt[et] = true
@@ -199,7 +207,7 @@ func typeinit() {
isComplex[types.TCOMPLEX128] = true
// initialize okfor
- for et := types.EType(0); et < types.NTYPE; et++ {
+ for et := types.Kind(0); et < types.NTYPE; et++ {
if isInt[et] || et == types.TIDEAL {
okforeq[et] = true
okforcmp[et] = true
@@ -261,8 +269,7 @@ func typeinit() {
okforcmp[types.TSTRING] = true
- var i int
- for i = 0; i < len(okfor); i++ {
+ for i := range okfor {
okfor[i] = okfornone[:]
}
@@ -304,92 +311,14 @@ func typeinit() {
iscmp[ir.OLE] = true
iscmp[ir.OEQ] = true
iscmp[ir.ONE] = true
-
- types.Types[types.TINTER] = types.New(types.TINTER) // empty interface
-
- // simple aliases
- simtype[types.TMAP] = types.TPTR
- simtype[types.TCHAN] = types.TPTR
- simtype[types.TFUNC] = types.TPTR
- simtype[types.TUNSAFEPTR] = types.TPTR
-
- slicePtrOffset = 0
- sliceLenOffset = Rnd(slicePtrOffset+int64(Widthptr), int64(Widthptr))
- sliceCapOffset = Rnd(sliceLenOffset+int64(Widthptr), int64(Widthptr))
- sizeofSlice = Rnd(sliceCapOffset+int64(Widthptr), int64(Widthptr))
-
- // string is same as slice wo the cap
- sizeofString = Rnd(sliceLenOffset+int64(Widthptr), int64(Widthptr))
-
- dowidth(types.Types[types.TSTRING])
- dowidth(types.UntypedString)
}
func makeErrorInterface() *types.Type {
- sig := functypefield(fakeRecvField(), nil, []*types.Field{
+ sig := types.NewSignature(types.NoPkg, fakeRecvField(), nil, []*types.Field{
types.NewField(src.NoXPos, nil, types.Types[types.TSTRING]),
})
-
method := types.NewField(src.NoXPos, lookup("Error"), sig)
-
- t := types.New(types.TINTER)
- t.SetInterface([]*types.Field{method})
- return t
-}
-
-func lexinit1() {
- // error type
- s := ir.BuiltinPkg.Lookup("error")
- types.Errortype = makeErrorInterface()
- types.Errortype.Sym = s
- types.Errortype.Orig = makeErrorInterface()
- s.Def = typenod(types.Errortype)
- dowidth(types.Errortype)
-
- // We create separate byte and rune types for better error messages
- // rather than just creating type alias *types.Sym's for the uint8 and
- // int32 types. Hence, (bytetype|runtype).Sym.isAlias() is false.
- // TODO(gri) Should we get rid of this special case (at the cost
- // of less informative error messages involving bytes and runes)?
- // (Alternatively, we could introduce an OTALIAS node representing
- // type aliases, albeit at the cost of having to deal with it everywhere).
-
- // byte alias
- s = ir.BuiltinPkg.Lookup("byte")
- types.Bytetype = types.New(types.TUINT8)
- types.Bytetype.Sym = s
- s.Def = typenod(types.Bytetype)
- ir.AsNode(s.Def).SetName(new(ir.Name))
- dowidth(types.Bytetype)
-
- // rune alias
- s = ir.BuiltinPkg.Lookup("rune")
- types.Runetype = types.New(types.TINT32)
- types.Runetype.Sym = s
- s.Def = typenod(types.Runetype)
- ir.AsNode(s.Def).SetName(new(ir.Name))
- dowidth(types.Runetype)
-
- // backend-dependent builtin types (e.g. int).
- for _, s := range &typedefs {
- s1 := ir.BuiltinPkg.Lookup(s.name)
-
- sameas := s.sameas32
- if Widthptr == 8 {
- sameas = s.sameas64
- }
-
- simtype[s.etype] = sameas
-
- t := types.New(s.etype)
- t.Sym = s1
- types.Types[s.etype] = t
- s1.Def = typenod(t)
- ir.AsNode(s1.Def).SetName(new(ir.Name))
- s1.Origpkg = ir.BuiltinPkg
-
- dowidth(t)
- }
+ return types.NewInterface(types.NoPkg, []*types.Field{method})
}
// finishUniverse makes the universe block visible within the current package.
@@ -398,7 +327,7 @@ func finishUniverse() {
// that we silently skip symbols that are already declared in the
// package block rather than emitting a redeclared symbol error.
- for _, s := range ir.BuiltinPkg.Syms {
+ for _, s := range types.BuiltinPkg.Syms {
if s.Def == nil {
continue
}
@@ -414,5 +343,5 @@ func finishUniverse() {
nodfp = NewName(lookup(".fp"))
nodfp.SetType(types.Types[types.TINT32])
nodfp.SetClass(ir.PPARAM)
- nodfp.Name().SetUsed(true)
+ nodfp.SetUsed(true)
}
diff --git a/src/cmd/compile/internal/gc/unsafe.go b/src/cmd/compile/internal/gc/unsafe.go
index 678924b229..d7ae5d7aaa 100644
--- a/src/cmd/compile/internal/gc/unsafe.go
+++ b/src/cmd/compile/internal/gc/unsafe.go
@@ -70,7 +70,7 @@ func evalunsafe(n ir.Node) int64 {
v += r.Offset()
default:
ir.Dump("unsafenmagic", n.Left())
- base.Fatalf("impossible %#v node after dot insertion", r.Op())
+ base.Fatalf("impossible %v node after dot insertion", r.Op())
}
}
return v
diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go
index db8791ee05..390719e441 100644
--- a/src/cmd/compile/internal/gc/walk.go
+++ b/src/cmd/compile/internal/gc/walk.go
@@ -22,42 +22,42 @@ import (
const tmpstringbufsize = 32
const zeroValSize = 1024 // must match value of runtime/map.go:maxZero
-func walk(fn ir.Node) {
+func walk(fn *ir.Func) {
Curfn = fn
errorsBefore := base.Errors()
if base.Flag.W != 0 {
- s := fmt.Sprintf("\nbefore walk %v", Curfn.Func().Nname.Sym())
+ s := fmt.Sprintf("\nbefore walk %v", Curfn.Sym())
ir.DumpList(s, Curfn.Body())
}
lno := base.Pos
// Final typecheck for any unused variables.
- for i, ln := range fn.Func().Dcl {
+ for i, ln := range fn.Dcl {
if ln.Op() == ir.ONAME && (ln.Class() == ir.PAUTO || ln.Class() == ir.PAUTOHEAP) {
- ln = typecheck(ln, ctxExpr|ctxAssign)
- fn.Func().Dcl[i] = ln
+ ln = typecheck(ln, ctxExpr|ctxAssign).(*ir.Name)
+ fn.Dcl[i] = ln
}
}
// Propagate the used flag for typeswitch variables up to the NONAME in its definition.
- for _, ln := range fn.Func().Dcl {
- if ln.Op() == ir.ONAME && (ln.Class() == ir.PAUTO || ln.Class() == ir.PAUTOHEAP) && ln.Name().Defn != nil && ln.Name().Defn.Op() == ir.OTYPESW && ln.Name().Used() {
- ln.Name().Defn.Left().Name().SetUsed(true)
+ for _, ln := range fn.Dcl {
+ if ln.Op() == ir.ONAME && (ln.Class() == ir.PAUTO || ln.Class() == ir.PAUTOHEAP) && ln.Defn != nil && ln.Defn.Op() == ir.OTYPESW && ln.Used() {
+ ln.Defn.(*ir.TypeSwitchGuard).Used = true
}
}
- for _, ln := range fn.Func().Dcl {
- if ln.Op() != ir.ONAME || (ln.Class() != ir.PAUTO && ln.Class() != ir.PAUTOHEAP) || ln.Sym().Name[0] == '&' || ln.Name().Used() {
+ for _, ln := range fn.Dcl {
+ if ln.Op() != ir.ONAME || (ln.Class() != ir.PAUTO && ln.Class() != ir.PAUTOHEAP) || ln.Sym().Name[0] == '&' || ln.Used() {
continue
}
- if defn := ln.Name().Defn; defn != nil && defn.Op() == ir.OTYPESW {
- if defn.Left().Name().Used() {
+ if defn, ok := ln.Defn.(*ir.TypeSwitchGuard); ok {
+ if defn.Used {
continue
}
- base.ErrorfAt(defn.Left().Pos(), "%v declared but not used", ln.Sym())
- defn.Left().Name().SetUsed(true) // suppress repeats
+ base.ErrorfAt(defn.Tag.Pos(), "%v declared but not used", ln.Sym())
+ defn.Used = true // suppress repeats
} else {
base.ErrorfAt(ln.Pos(), "%v declared but not used", ln.Sym())
}
@@ -69,15 +69,15 @@ func walk(fn ir.Node) {
}
walkstmtlist(Curfn.Body().Slice())
if base.Flag.W != 0 {
- s := fmt.Sprintf("after walk %v", Curfn.Func().Nname.Sym())
+ s := fmt.Sprintf("after walk %v", Curfn.Sym())
ir.DumpList(s, Curfn.Body())
}
zeroResults()
heapmoves()
- if base.Flag.W != 0 && Curfn.Func().Enter.Len() > 0 {
- s := fmt.Sprintf("enter %v", Curfn.Func().Nname.Sym())
- ir.DumpList(s, Curfn.Func().Enter)
+ if base.Flag.W != 0 && Curfn.Enter.Len() > 0 {
+ s := fmt.Sprintf("enter %v", Curfn.Sym())
+ ir.DumpList(s, Curfn.Enter)
}
}
@@ -87,11 +87,11 @@ func walkstmtlist(s []ir.Node) {
}
}
-func paramoutheap(fn ir.Node) bool {
- for _, ln := range fn.Func().Dcl {
+func paramoutheap(fn *ir.Func) bool {
+ for _, ln := range fn.Dcl {
switch ln.Class() {
case ir.PPARAMOUT:
- if isParamStackCopy(ln) || ln.Name().Addrtaken() {
+ if isParamStackCopy(ln) || ln.Addrtaken() {
return true
}
@@ -123,6 +123,7 @@ func walkstmt(n ir.Node) ir.Node {
base.Errorf("%v is not a top level statement", n.Op())
}
ir.Dump("nottop", n)
+ return n
case ir.OAS,
ir.OASOP,
@@ -142,20 +143,31 @@ func walkstmt(n ir.Node) ir.Node {
ir.OPRINT,
ir.OPRINTN,
ir.OPANIC,
- ir.OEMPTY,
ir.ORECOVER,
ir.OGETG:
if n.Typecheck() == 0 {
base.Fatalf("missing typecheck: %+v", n)
}
- wascopy := n.Op() == ir.OCOPY
init := n.Init()
n.PtrInit().Set(nil)
n = walkexpr(n, &init)
- n = addinit(n, init.Slice())
- if wascopy && n.Op() == ir.OCONVNOP {
- n.SetOp(ir.OEMPTY) // don't leave plain values as statements.
+ if n.Op() == ir.ONAME {
+ // copy rewrote to a statement list and a temp for the length.
+ // Throw away the temp to avoid plain values as statements.
+ n = ir.NewBlockStmt(n.Pos(), init.Slice())
+ init.Set(nil)
}
+ if init.Len() > 0 {
+ switch n.Op() {
+ case ir.OAS, ir.OAS2, ir.OBLOCK:
+ n.PtrInit().Prepend(init.Slice()...)
+
+ default:
+ init.Append(n)
+ n = ir.NewBlockStmt(n.Pos(), init.Slice())
+ }
+ }
+ return n
// special case for a receive where we throw away
// the value received.
@@ -169,8 +181,7 @@ func walkstmt(n ir.Node) ir.Node {
n.SetLeft(walkexpr(n.Left(), &init))
n = mkcall1(chanfn("chanrecv1", 2, n.Left().Type()), nil, &init, n.Left(), nodnil())
n = walkexpr(n, &init)
-
- n = addinit(n, init.Slice())
+ return initExpr(init.Slice(), n)
case ir.OBREAK,
ir.OCONTINUE,
@@ -183,7 +194,7 @@ func walkstmt(n ir.Node) ir.Node {
ir.OVARDEF,
ir.OVARKILL,
ir.OVARLIVE:
- break
+ return n
case ir.ODCL:
v := n.Left()
@@ -194,58 +205,67 @@ func walkstmt(n ir.Node) ir.Node {
if prealloc[v] == nil {
prealloc[v] = callnew(v.Type())
}
- nn := ir.Nod(ir.OAS, v.Name().Param.Heapaddr, prealloc[v])
+ nn := ir.Nod(ir.OAS, v.Name().Heapaddr, prealloc[v])
nn.SetColas(true)
nn = typecheck(nn, ctxStmt)
return walkstmt(nn)
}
+ return n
case ir.OBLOCK:
walkstmtlist(n.List().Slice())
+ return n
case ir.OCASE:
base.Errorf("case statement out of place")
+ panic("unreachable")
case ir.ODEFER:
- Curfn.Func().SetHasDefer(true)
- Curfn.Func().NumDefers++
- if Curfn.Func().NumDefers > maxOpenDefers {
+ Curfn.SetHasDefer(true)
+ Curfn.NumDefers++
+ if Curfn.NumDefers > maxOpenDefers {
// Don't allow open-coded defers if there are more than
// 8 defers in the function, since we use a single
// byte to record active defers.
- Curfn.Func().SetOpenCodedDeferDisallowed(true)
+ Curfn.SetOpenCodedDeferDisallowed(true)
}
if n.Esc() != EscNever {
// If n.Esc is not EscNever, then this defer occurs in a loop,
// so open-coded defers cannot be used in this function.
- Curfn.Func().SetOpenCodedDeferDisallowed(true)
+ Curfn.SetOpenCodedDeferDisallowed(true)
}
fallthrough
case ir.OGO:
+ var init ir.Nodes
switch n.Left().Op() {
case ir.OPRINT, ir.OPRINTN:
- n.SetLeft(wrapCall(n.Left(), n.PtrInit()))
+ n.SetLeft(wrapCall(n.Left(), &init))
case ir.ODELETE:
if mapfast(n.Left().List().First().Type()) == mapslow {
- n.SetLeft(wrapCall(n.Left(), n.PtrInit()))
+ n.SetLeft(wrapCall(n.Left(), &init))
} else {
- n.SetLeft(walkexpr(n.Left(), n.PtrInit()))
+ n.SetLeft(walkexpr(n.Left(), &init))
}
case ir.OCOPY:
- n.SetLeft(copyany(n.Left(), n.PtrInit(), true))
+ n.SetLeft(copyany(n.Left(), &init, true))
case ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER:
if n.Left().Body().Len() > 0 {
- n.SetLeft(wrapCall(n.Left(), n.PtrInit()))
+ n.SetLeft(wrapCall(n.Left(), &init))
} else {
- n.SetLeft(walkexpr(n.Left(), n.PtrInit()))
+ n.SetLeft(walkexpr(n.Left(), &init))
}
default:
- n.SetLeft(walkexpr(n.Left(), n.PtrInit()))
+ n.SetLeft(walkexpr(n.Left(), &init))
}
+ if init.Len() > 0 {
+ init.Append(n)
+ n = ir.NewBlockStmt(n.Pos(), init.Slice())
+ }
+ return n
case ir.OFOR, ir.OFORUNTIL:
if n.Left() != nil {
@@ -253,7 +273,7 @@ func walkstmt(n ir.Node) ir.Node {
init := n.Left().Init()
n.Left().PtrInit().Set(nil)
n.SetLeft(walkexpr(n.Left(), &init))
- n.SetLeft(addinit(n.Left(), init.Slice()))
+ n.SetLeft(initExpr(init.Slice(), n.Left()))
}
n.SetRight(walkstmt(n.Right()))
@@ -261,30 +281,33 @@ func walkstmt(n ir.Node) ir.Node {
walkstmtlist(n.List().Slice())
}
walkstmtlist(n.Body().Slice())
+ return n
case ir.OIF:
n.SetLeft(walkexpr(n.Left(), n.PtrInit()))
walkstmtlist(n.Body().Slice())
walkstmtlist(n.Rlist().Slice())
+ return n
case ir.ORETURN:
- Curfn.Func().NumReturns++
+ Curfn.NumReturns++
if n.List().Len() == 0 {
- break
+ return n
}
- if (Curfn.Type().FuncType().Outnamed && n.List().Len() > 1) || paramoutheap(Curfn) {
+ if (hasNamedResults(Curfn) && n.List().Len() > 1) || paramoutheap(Curfn) {
// assign to the function out parameters,
// so that reorder3 can fix up conflicts
var rl []ir.Node
- for _, ln := range Curfn.Func().Dcl {
+ for _, ln := range Curfn.Dcl {
cl := ln.Class()
if cl == ir.PAUTO || cl == ir.PAUTOHEAP {
break
}
if cl == ir.PPARAMOUT {
+ var ln ir.Node = ln
if isParamStackCopy(ln) {
- ln = walkexpr(typecheck(ir.Nod(ir.ODEREF, ln.Name().Param.Heapaddr, nil), ctxExpr), nil)
+ ln = walkexpr(typecheck(ir.Nod(ir.ODEREF, ln.Name().Heapaddr, nil), ctxExpr), nil)
}
rl = append(rl, ln)
}
@@ -301,7 +324,7 @@ func walkstmt(n ir.Node) ir.Node {
ll := ascompatee(n.Op(), rl, n.List().Slice(), n.PtrInit())
n.PtrList().Set(reorder3(ll))
- break
+ return n
}
walkexprlist(n.List().Slice(), n.PtrInit())
@@ -312,33 +335,35 @@ func walkstmt(n ir.Node) ir.Node {
for i, nl := range lhs.FieldSlice() {
nname := ir.AsNode(nl.Nname)
if isParamHeapCopy(nname) {
- nname = nname.Name().Param.Stackcopy
+ nname = nname.Name().Stackcopy
}
a := ir.Nod(ir.OAS, nname, rhs[i])
res[i] = convas(a, n.PtrInit())
}
n.PtrList().Set(res)
+ return n
case ir.ORETJMP:
- break
+ return n
case ir.OINLMARK:
- break
+ return n
case ir.OSELECT:
walkselect(n)
+ return n
case ir.OSWITCH:
walkswitch(n)
+ return n
case ir.ORANGE:
- n = walkrange(n)
+ return walkrange(n)
}
- if n.Op() == ir.ONAME {
- base.Fatalf("walkstmt ended up with name: %+v", n)
- }
- return n
+ // No return! Each case must return (or panic),
+ // to avoid confusion about what gets returned
+ // in the presence of type assertions.
}
// walk the whole tree of the body of an
@@ -420,7 +445,7 @@ func walkexpr(n ir.Node, init *ir.Nodes) ir.Node {
// Eagerly checkwidth all expressions for the back end.
if n.Type() != nil && !n.Type().WidthCalculated() {
- switch n.Type().Etype {
+ switch n.Type().Kind() {
case types.TBLANK, types.TNIL, types.TIDEAL:
default:
checkwidth(n.Type())
@@ -454,38 +479,75 @@ func walkexpr(n ir.Node, init *ir.Nodes) ir.Node {
}
if n.Op() == ir.ONAME && n.Class() == ir.PAUTOHEAP {
- nn := ir.Nod(ir.ODEREF, n.Name().Param.Heapaddr, nil)
+ nn := ir.Nod(ir.ODEREF, n.Name().Heapaddr, nil)
nn = typecheck(nn, ctxExpr)
nn = walkexpr(nn, init)
nn.Left().MarkNonNil()
return nn
}
-opswitch:
+ n = walkexpr1(n, init)
+
+ // Expressions that are constant at run time but not
+ // considered const by the language spec are not turned into
+ // constants until walk. For example, if n is y%1 == 0, the
+ // walk of y%1 may have replaced it by 0.
+ // Check whether n with its updated args is itself now a constant.
+ t := n.Type()
+ n = evalConst(n)
+ if n.Type() != t {
+ base.Fatalf("evconst changed Type: %v had type %v, now %v", n, t, n.Type())
+ }
+ if n.Op() == ir.OLITERAL {
+ n = typecheck(n, ctxExpr)
+ // Emit string symbol now to avoid emitting
+ // any concurrently during the backend.
+ if v := n.Val(); v.Kind() == constant.String {
+ _ = stringsym(n.Pos(), constant.StringVal(v))
+ }
+ }
+
+ updateHasCall(n)
+
+ if base.Flag.LowerW != 0 && n != nil {
+ ir.Dump("after walk expr", n)
+ }
+
+ base.Pos = lno
+ return n
+}
+
+func walkexpr1(n ir.Node, init *ir.Nodes) ir.Node {
switch n.Op() {
default:
ir.Dump("walk", n)
- base.Fatalf("walkexpr: switch 1 unknown op %+S", n)
+ base.Fatalf("walkexpr: switch 1 unknown op %+v", n.Op())
+ panic("unreachable")
- case ir.ONONAME, ir.OEMPTY, ir.OGETG, ir.ONEWOBJ, ir.OMETHEXPR:
+ case ir.ONONAME, ir.OGETG, ir.ONEWOBJ, ir.OMETHEXPR:
+ return n
case ir.OTYPE, ir.ONAME, ir.OLITERAL, ir.ONIL:
// TODO(mdempsky): Just return n; see discussion on CL 38655.
// Perhaps refactor to use Node.mayBeShared for these instead.
// If these return early, make sure to still call
// stringsym for constant strings.
+ return n
case ir.ONOT, ir.ONEG, ir.OPLUS, ir.OBITNOT, ir.OREAL, ir.OIMAG, ir.ODOTMETH, ir.ODOTINTER,
ir.ODEREF, ir.OSPTR, ir.OITAB, ir.OIDATA, ir.OADDR:
n.SetLeft(walkexpr(n.Left(), init))
+ return n
case ir.OEFACE, ir.OAND, ir.OANDNOT, ir.OSUB, ir.OMUL, ir.OADD, ir.OOR, ir.OXOR, ir.OLSH, ir.ORSH:
n.SetLeft(walkexpr(n.Left(), init))
n.SetRight(walkexpr(n.Right(), init))
+ return n
case ir.ODOT, ir.ODOTPTR:
usefield(n)
n.SetLeft(walkexpr(n.Left(), init))
+ return n
case ir.ODOTTYPE, ir.ODOTTYPE2:
n.SetLeft(walkexpr(n.Left(), init))
@@ -497,12 +559,12 @@ opswitch:
if !n.Type().IsInterface() && !n.Left().Type().IsEmptyInterface() {
n.PtrList().Set1(itabname(n.Type(), n.Left().Type()))
}
+ return n
case ir.OLEN, ir.OCAP:
if isRuneCount(n) {
// Replace len([]rune(string)) with runtime.countrunes(string).
- n = mkcall("countrunes", n.Type(), init, conv(n.Left().Left(), types.Types[types.TSTRING]))
- break
+ return mkcall("countrunes", n.Type(), init, conv(n.Left().Left(), types.Types[types.TSTRING]))
}
n.SetLeft(walkexpr(n.Left(), init))
@@ -519,6 +581,7 @@ opswitch:
n = origIntConst(n, t.NumElem())
n.SetTypecheck(1)
}
+ return n
case ir.OCOMPLEX:
// Use results from call expression as arguments for complex.
@@ -528,9 +591,10 @@ opswitch:
}
n.SetLeft(walkexpr(n.Left(), init))
n.SetRight(walkexpr(n.Right(), init))
+ return n
case ir.OEQ, ir.ONE, ir.OLT, ir.OLE, ir.OGT, ir.OGE:
- n = walkcompare(n, init)
+ return walkcompare(n, init)
case ir.OANDAND, ir.OOROR:
n.SetLeft(walkexpr(n.Left(), init))
@@ -541,18 +605,20 @@ opswitch:
var ll ir.Nodes
n.SetRight(walkexpr(n.Right(), &ll))
- n.SetRight(addinit(n.Right(), ll.Slice()))
+ n.SetRight(initExpr(ll.Slice(), n.Right()))
+ return n
case ir.OPRINT, ir.OPRINTN:
- n = walkprint(n, init)
+ return walkprint(n, init)
case ir.OPANIC:
- n = mkcall("gopanic", nil, init, n.Left())
+ return mkcall("gopanic", nil, init, n.Left())
case ir.ORECOVER:
- n = mkcall("gorecover", n.Type(), init, ir.Nod(ir.OADDR, nodfp, nil))
+ return mkcall("gorecover", n.Type(), init, ir.Nod(ir.OADDR, nodfp, nil))
- case ir.OCLOSUREVAR, ir.OCFUNC:
+ case ir.OCLOSUREREAD, ir.OCFUNC:
+ return n
case ir.OCALLINTER, ir.OCALLFUNC, ir.OCALLMETH:
if n.Op() == ir.OCALLINTER {
@@ -581,6 +647,7 @@ opswitch:
}
walkCall(n, init)
+ return n
case ir.OAS, ir.OASOP:
init.AppendNodes(n.PtrInit())
@@ -601,24 +668,21 @@ opswitch:
if n.Op() == ir.OASOP {
// Rewrite x op= y into x = x op y.
- n.SetRight(ir.Nod(n.SubOp(), n.Left(), n.Right()))
- n.SetRight(typecheck(n.Right(), ctxExpr))
-
- n.SetOp(ir.OAS)
- n.ResetAux()
+ n = ir.Nod(ir.OAS, n.Left(),
+ typecheck(ir.Nod(n.SubOp(), n.Left(), n.Right()), ctxExpr))
}
if oaslit(n, init) {
- break
+ return ir.NodAt(n.Pos(), ir.OBLOCK, nil, nil)
}
if n.Right() == nil {
// TODO(austin): Check all "implicit zeroing"
- break
+ return n
}
if !instrumenting && isZero(n.Right()) {
- break
+ return n
}
switch n.Right().Op() {
@@ -632,9 +696,7 @@ opswitch:
n1 := ir.Nod(ir.OADDR, n.Left(), nil)
r := n.Right().Left() // the channel
- n = mkcall1(chanfn("chanrecv1", 2, r.Type()), nil, init, r, n1)
- n = walkexpr(n, init)
- break opswitch
+ return mkcall1(chanfn("chanrecv1", 2, r.Type()), nil, init, r, n1)
case ir.OAPPEND:
// x = append(...)
@@ -657,7 +719,7 @@ opswitch:
// Do not add a new write barrier.
// Set up address of type for back end.
r.SetLeft(typename(r.Type().Elem()))
- break opswitch
+ return n
}
// Otherwise, lowered for race detector.
// Treat as ordinary assignment.
@@ -666,6 +728,7 @@ opswitch:
if n.Left() != nil && n.Right() != nil {
n = convas(n, init)
}
+ return n
case ir.OAS2:
init.AppendNodes(n.PtrInit())
@@ -673,31 +736,31 @@ opswitch:
walkexprlistsafe(n.Rlist().Slice(), init)
ll := ascompatee(ir.OAS, n.List().Slice(), n.Rlist().Slice(), init)
ll = reorder3(ll)
- n = liststmt(ll)
+ return liststmt(ll)
// a,b,... = fn()
case ir.OAS2FUNC:
init.AppendNodes(n.PtrInit())
- r := n.Right()
+ r := n.Rlist().First()
walkexprlistsafe(n.List().Slice(), init)
r = walkexpr(r, init)
if isIntrinsicCall(r) {
- n.SetRight(r)
- break
+ n.PtrRlist().Set1(r)
+ return n
}
init.Append(r)
ll := ascompatet(n.List(), r.Type())
- n = liststmt(ll)
+ return liststmt(ll)
// x, y = <-c
// order.stmt made sure x is addressable or blank.
case ir.OAS2RECV:
init.AppendNodes(n.PtrInit())
- r := n.Right()
+ r := n.Rlist().First()
walkexprlistsafe(n.List().Slice(), init)
r.SetLeft(walkexpr(r.Left(), init))
var n1 ir.Node
@@ -710,13 +773,13 @@ opswitch:
ok := n.List().Second()
call := mkcall1(fn, types.Types[types.TBOOL], init, r.Left(), n1)
n = ir.Nod(ir.OAS, ok, call)
- n = typecheck(n, ctxStmt)
+ return typecheck(n, ctxStmt)
// a,b = m[i]
case ir.OAS2MAPR:
init.AppendNodes(n.PtrInit())
- r := n.Right()
+ r := n.Rlist().First()
walkexprlistsafe(n.List().Slice(), init)
r.SetLeft(walkexpr(r.Left(), init))
r.SetRight(walkexpr(r.Right(), init))
@@ -755,7 +818,7 @@ opswitch:
if ok := n.List().Second(); !ir.IsBlank(ok) && ok.Type().IsBoolean() {
r.Type().Field(1).Type = ok.Type()
}
- n.SetRight(r)
+ n.PtrRlist().Set1(r)
n.SetOp(ir.OAS2FUNC)
// don't generate a = *var if a is _
@@ -770,7 +833,7 @@ opswitch:
}
n = typecheck(n, ctxStmt)
- n = walkexpr(n, init)
+ return walkexpr(n, init)
case ir.ODELETE:
init.AppendNodes(n.PtrInit())
@@ -785,11 +848,12 @@ opswitch:
// order.stmt made sure key is addressable.
key = ir.Nod(ir.OADDR, key, nil)
}
- n = mkcall1(mapfndel(mapdelete[fast], t), nil, init, typename(t), map_, key)
+ return mkcall1(mapfndel(mapdelete[fast], t), nil, init, typename(t), map_, key)
case ir.OAS2DOTTYPE:
walkexprlistsafe(n.List().Slice(), init)
- n.SetRight(walkexpr(n.Right(), init))
+ n.PtrRlist().SetIndex(0, walkexpr(n.Rlist().First(), init))
+ return n
case ir.OCONVIFACE:
n.SetLeft(walkexpr(n.Left(), init))
@@ -797,8 +861,8 @@ opswitch:
fromType := n.Left().Type()
toType := n.Type()
- if !fromType.IsInterface() && !ir.IsBlank(Curfn.Func().Nname) { // skip unnamed functions (func _())
- markTypeUsedInInterface(fromType, Curfn.Func().LSym)
+ if !fromType.IsInterface() && !ir.IsBlank(Curfn.Nname) { // skip unnamed functions (func _())
+ markTypeUsedInInterface(fromType, Curfn.LSym)
}
// typeword generates the type word of the interface value.
@@ -814,8 +878,7 @@ opswitch:
l := ir.Nod(ir.OEFACE, typeword(), n.Left())
l.SetType(toType)
l.SetTypecheck(n.Typecheck())
- n = l
- break
+ return l
}
if staticuint64s == nil {
@@ -849,7 +912,7 @@ opswitch:
}
value = ir.Nod(ir.OINDEX, staticuint64s, index)
value.SetBounded(true)
- case n.Left().Class() == ir.PEXTERN && n.Left().Name() != nil && n.Left().Name().Readonly():
+ case n.Left().Name() != nil && n.Left().Class() == ir.PEXTERN && n.Left().Name().Readonly():
// n.Left is a readonly global; use it directly.
value = n.Left()
case !fromType.IsInterface() && n.Esc() == EscNone && fromType.Width <= 1024:
@@ -864,8 +927,7 @@ opswitch:
l := ir.Nod(ir.OEFACE, typeword(), typecheck(ir.Nod(ir.OADDR, value, nil), ctxExpr))
l.SetType(toType)
l.SetTypecheck(n.Typecheck())
- n = l
- break
+ return l
}
// Implement interface to empty interface conversion.
@@ -892,8 +954,7 @@ opswitch:
e := ir.Nod(ir.OEFACE, tmp, ifaceData(n.Pos(), c, types.NewPtr(types.Types[types.TUINT8])))
e.SetType(toType) // assign type manually, typecheck doesn't understand OEFACE.
e.SetTypecheck(1)
- n = e
- break
+ return e
}
fnname, needsaddr := convFuncName(fromType, toType)
@@ -914,8 +975,7 @@ opswitch:
e := ir.Nod(ir.OEFACE, typeword(), call)
e.SetType(toType)
e.SetTypecheck(1)
- n = e
- break
+ return e
}
var tab ir.Node
@@ -948,44 +1008,44 @@ opswitch:
n = ir.Nod(ir.OCALL, fn, nil)
n.PtrList().Set2(tab, v)
n = typecheck(n, ctxExpr)
- n = walkexpr(n, init)
+ return walkexpr(n, init)
case ir.OCONV, ir.OCONVNOP:
n.SetLeft(walkexpr(n.Left(), init))
+ if n.Op() == ir.OCONVNOP && n.Type() == n.Left().Type() {
+ return n.Left()
+ }
if n.Op() == ir.OCONVNOP && checkPtr(Curfn, 1) {
if n.Type().IsPtr() && n.Left().Type().IsUnsafePtr() { // unsafe.Pointer to *T
- n = walkCheckPtrAlignment(n, init, nil)
- break
+ return walkCheckPtrAlignment(n, init, nil)
}
if n.Type().IsUnsafePtr() && n.Left().Type().IsUintptr() { // uintptr to unsafe.Pointer
- n = walkCheckPtrArithmetic(n, init)
- break
+ return walkCheckPtrArithmetic(n, init)
}
}
param, result := rtconvfn(n.Left().Type(), n.Type())
if param == types.Txxx {
- break
+ return n
}
- fn := ir.BasicTypeNames[param] + "to" + ir.BasicTypeNames[result]
- n = conv(mkcall(fn, types.Types[result], init, conv(n.Left(), types.Types[param])), n.Type())
+ fn := types.BasicTypeNames[param] + "to" + types.BasicTypeNames[result]
+ return conv(mkcall(fn, types.Types[result], init, conv(n.Left(), types.Types[param])), n.Type())
case ir.ODIV, ir.OMOD:
n.SetLeft(walkexpr(n.Left(), init))
n.SetRight(walkexpr(n.Right(), init))
// rewrite complex div into function call.
- et := n.Left().Type().Etype
+ et := n.Left().Type().Kind()
if isComplex[et] && n.Op() == ir.ODIV {
t := n.Type()
n = mkcall("complex128div", types.Types[types.TCOMPLEX128], init, conv(n.Left(), types.Types[types.TCOMPLEX128]), conv(n.Right(), types.Types[types.TCOMPLEX128]))
- n = conv(n, t)
- break
+ return conv(n, t)
}
// Nothing to do for float divisions.
if isFloat[et] {
- break
+ return n
}
// rewrite 64-bit div and mod on 32-bit architectures.
@@ -997,20 +1057,20 @@ opswitch:
// The SSA backend will handle those.
switch et {
case types.TINT64:
- c := n.Right().Int64Val()
+ c := ir.Int64Val(n.Right())
if c < 0 {
c = -c
}
if c != 0 && c&(c-1) == 0 {
- break opswitch
+ return n
}
case types.TUINT64:
- c := n.Right().Uint64Val()
+ c := ir.Uint64Val(n.Right())
if c < 1<<16 {
- break opswitch
+ return n
}
if c != 0 && c&(c-1) == 0 {
- break opswitch
+ return n
}
}
}
@@ -1025,8 +1085,9 @@ opswitch:
} else {
fn += "mod"
}
- n = mkcall(fn, n.Type(), init, conv(n.Left(), types.Types[et]), conv(n.Right(), types.Types[et]))
+ return mkcall(fn, n.Type(), init, conv(n.Left(), types.Types[et]), conv(n.Right(), types.Types[et]))
}
+ return n
case ir.OINDEX:
n.SetLeft(walkexpr(n.Left(), init))
@@ -1040,7 +1101,7 @@ opswitch:
// if range of type cannot exceed static array bound,
// disable bounds check.
if n.Bounded() {
- break
+ return n
}
t := n.Left().Type()
if t != nil && t.IsPtr() {
@@ -1055,7 +1116,7 @@ opswitch:
base.Errorf("index out of bounds")
}
} else if ir.IsConst(n.Left(), constant.String) {
- n.SetBounded(bounded(r, int64(len(n.Left().StringVal()))))
+ n.SetBounded(bounded(r, int64(len(ir.StringVal(n.Left())))))
if base.Flag.LowerM != 0 && n.Bounded() && !ir.IsConst(n.Right(), constant.Int) {
base.Warn("index bounds check elided")
}
@@ -1069,6 +1130,7 @@ opswitch:
base.Errorf("index out of bounds")
}
}
+ return n
case ir.OINDEXMAP:
// Replace m[k] with *map{access1,assign}(maptype, m, &k)
@@ -1107,14 +1169,17 @@ opswitch:
n = ir.Nod(ir.ODEREF, n, nil)
n.SetType(t.Elem())
n.SetTypecheck(1)
+ return n
case ir.ORECV:
base.Fatalf("walkexpr ORECV") // should see inside OAS only
+ panic("unreachable")
case ir.OSLICEHEADER:
n.SetLeft(walkexpr(n.Left(), init))
n.List().SetFirst(walkexpr(n.List().First(), init))
n.List().SetSecond(walkexpr(n.List().Second(), init))
+ return n
case ir.OSLICE, ir.OSLICEARR, ir.OSLICESTR, ir.OSLICE3, ir.OSLICE3ARR:
checkSlice := checkPtr(Curfn, 1) && n.Op() == ir.OSLICE3ARR && n.Left().Op() == ir.OCONVNOP && n.Left().Left().Type().IsUnsafePtr()
@@ -1143,11 +1208,11 @@ opswitch:
} else {
n.SetOp(ir.OSLICEARR)
}
- n = reduceSlice(n)
+ return reduceSlice(n)
}
- } else {
- n = reduceSlice(n)
+ return n
}
+ return reduceSlice(n)
case ir.ONEW:
if n.Type().Elem().NotInHeap() {
@@ -1157,33 +1222,31 @@ opswitch:
if n.Type().Elem().Width >= maxImplicitStackVarSize {
base.Fatalf("large ONEW with EscNone: %v", n)
}
- r := temp(n.Type().Elem())
+ r := ir.Node(temp(n.Type().Elem()))
r = ir.Nod(ir.OAS, r, nil) // zero temp
r = typecheck(r, ctxStmt)
init.Append(r)
r = ir.Nod(ir.OADDR, r.Left(), nil)
- r = typecheck(r, ctxExpr)
- n = r
- } else {
- n = callnew(n.Type().Elem())
+ return typecheck(r, ctxExpr)
}
+ return callnew(n.Type().Elem())
case ir.OADDSTR:
- n = addstr(n, init)
+ return addstr(n, init)
case ir.OAPPEND:
// order should make sure we only see OAS(node, OAPPEND), which we handle above.
base.Fatalf("append outside assignment")
+ panic("unreachable")
case ir.OCOPY:
- n = copyany(n, init, instrumenting && !base.Flag.CompilingRuntime)
+ return copyany(n, init, instrumenting && !base.Flag.CompilingRuntime)
- // cannot use chanfn - closechan takes any, not chan any
case ir.OCLOSE:
+ // cannot use chanfn - closechan takes any, not chan any
fn := syslook("closechan")
-
fn = substArgTypes(fn, n.Left().Type())
- n = mkcall1(fn, nil, init, n.Left())
+ return mkcall1(fn, nil, init, n.Left())
case ir.OMAKECHAN:
// When size fits into int, use makechan instead of
@@ -1200,7 +1263,7 @@ opswitch:
argtype = types.Types[types.TINT]
}
- n = mkcall1(chanfn(fnname, 1, n.Type()), n.Type(), init, typename(n.Type()), conv(size, argtype))
+ return mkcall1(chanfn(fnname, 1, n.Type()), n.Type(), init, typename(n.Type()), conv(size, argtype))
case ir.OMAKEMAP:
t := n.Type()
@@ -1277,42 +1340,41 @@ opswitch:
a = typecheck(a, ctxStmt)
a = walkexpr(a, init)
init.Append(a)
- n = convnop(h, t)
- } else {
- // Call runtime.makehmap to allocate an
- // hmap on the heap and initialize hmap's hash0 field.
- fn := syslook("makemap_small")
- fn = substArgTypes(fn, t.Key(), t.Elem())
- n = mkcall1(fn, n.Type(), init)
+ return convnop(h, t)
}
- } else {
- if n.Esc() != EscNone {
- h = nodnil()
- }
- // Map initialization with a variable or large hint is
- // more complicated. We therefore generate a call to
- // runtime.makemap to initialize hmap and allocate the
- // map buckets.
-
- // When hint fits into int, use makemap instead of
- // makemap64, which is faster and shorter on 32 bit platforms.
- fnname := "makemap64"
- argtype := types.Types[types.TINT64]
-
- // Type checking guarantees that TIDEAL hint is positive and fits in an int.
- // See checkmake call in TMAP case of OMAKE case in OpSwitch in typecheck1 function.
- // The case of hint overflow when converting TUINT or TUINTPTR to TINT
- // will be handled by the negative range checks in makemap during runtime.
- if hint.Type().IsKind(types.TIDEAL) || hint.Type().Size() <= types.Types[types.TUINT].Size() {
- fnname = "makemap"
- argtype = types.Types[types.TINT]
- }
-
- fn := syslook(fnname)
- fn = substArgTypes(fn, hmapType, t.Key(), t.Elem())
- n = mkcall1(fn, n.Type(), init, typename(n.Type()), conv(hint, argtype), h)
+ // Call runtime.makehmap to allocate an
+ // hmap on the heap and initialize hmap's hash0 field.
+ fn := syslook("makemap_small")
+ fn = substArgTypes(fn, t.Key(), t.Elem())
+ return mkcall1(fn, n.Type(), init)
}
+ if n.Esc() != EscNone {
+ h = nodnil()
+ }
+ // Map initialization with a variable or large hint is
+ // more complicated. We therefore generate a call to
+ // runtime.makemap to initialize hmap and allocate the
+ // map buckets.
+
+ // When hint fits into int, use makemap instead of
+ // makemap64, which is faster and shorter on 32 bit platforms.
+ fnname := "makemap64"
+ argtype := types.Types[types.TINT64]
+
+ // Type checking guarantees that TIDEAL hint is positive and fits in an int.
+ // See checkmake call in TMAP case of OMAKE case in OpSwitch in typecheck1 function.
+ // The case of hint overflow when converting TUINT or TUINTPTR to TINT
+ // will be handled by the negative range checks in makemap during runtime.
+ if hint.Type().IsKind(types.TIDEAL) || hint.Type().Size() <= types.Types[types.TUINT].Size() {
+ fnname = "makemap"
+ argtype = types.Types[types.TINT]
+ }
+
+ fn := syslook(fnname)
+ fn = substArgTypes(fn, hmapType, t.Key(), t.Elem())
+ return mkcall1(fn, n.Type(), init, typename(n.Type()), conv(hint, argtype), h)
+
case ir.OMAKESLICE:
l := n.Left()
r := n.Right()
@@ -1359,39 +1421,39 @@ opswitch:
r = conv(r, n.Type()) // in case n.Type is named.
r = typecheck(r, ctxExpr)
r = walkexpr(r, init)
- n = r
- } else {
- // n escapes; set up a call to makeslice.
- // When len and cap can fit into int, use makeslice instead of
- // makeslice64, which is faster and shorter on 32 bit platforms.
-
- len, cap := l, r
-
- fnname := "makeslice64"
- argtype := types.Types[types.TINT64]
-
- // Type checking guarantees that TIDEAL len/cap are positive and fit in an int.
- // The case of len or cap overflow when converting TUINT or TUINTPTR to TINT
- // will be handled by the negative range checks in makeslice during runtime.
- if (len.Type().IsKind(types.TIDEAL) || len.Type().Size() <= types.Types[types.TUINT].Size()) &&
- (cap.Type().IsKind(types.TIDEAL) || cap.Type().Size() <= types.Types[types.TUINT].Size()) {
- fnname = "makeslice"
- argtype = types.Types[types.TINT]
- }
-
- m := ir.Nod(ir.OSLICEHEADER, nil, nil)
- m.SetType(t)
-
- fn := syslook(fnname)
- m.SetLeft(mkcall1(fn, types.Types[types.TUNSAFEPTR], init, typename(t.Elem()), conv(len, argtype), conv(cap, argtype)))
- m.Left().MarkNonNil()
- m.PtrList().Set2(conv(len, types.Types[types.TINT]), conv(cap, types.Types[types.TINT]))
-
- m = typecheck(m, ctxExpr)
- m = walkexpr(m, init)
- n = m
+ return r
}
+ // n escapes; set up a call to makeslice.
+ // When len and cap can fit into int, use makeslice instead of
+ // makeslice64, which is faster and shorter on 32 bit platforms.
+
+ len, cap := l, r
+
+ fnname := "makeslice64"
+ argtype := types.Types[types.TINT64]
+
+ // Type checking guarantees that TIDEAL len/cap are positive and fit in an int.
+ // The case of len or cap overflow when converting TUINT or TUINTPTR to TINT
+ // will be handled by the negative range checks in makeslice during runtime.
+ if (len.Type().IsKind(types.TIDEAL) || len.Type().Size() <= types.Types[types.TUINT].Size()) &&
+ (cap.Type().IsKind(types.TIDEAL) || cap.Type().Size() <= types.Types[types.TUINT].Size()) {
+ fnname = "makeslice"
+ argtype = types.Types[types.TINT]
+ }
+
+ m := ir.Nod(ir.OSLICEHEADER, nil, nil)
+ m.SetType(t)
+
+ fn := syslook(fnname)
+ m.SetLeft(mkcall1(fn, types.Types[types.TUNSAFEPTR], init, typename(t.Elem()), conv(len, argtype), conv(cap, argtype)))
+ m.Left().MarkNonNil()
+ m.PtrList().Set2(conv(len, types.Types[types.TINT]), conv(cap, types.Types[types.TINT]))
+
+ m = typecheck(m, ctxExpr)
+ m = walkexpr(m, init)
+ return m
+
case ir.OMAKESLICECOPY:
if n.Esc() == EscNone {
base.Fatalf("OMAKESLICECOPY with EscNone: %v", n)
@@ -1436,18 +1498,18 @@ opswitch:
ncopy = walkexpr(ncopy, init)
init.Append(ncopy)
- n = s
- } else { // Replace make+copy with runtime.makeslicecopy.
- // instantiate makeslicecopy(typ *byte, tolen int, fromlen int, from unsafe.Pointer) unsafe.Pointer
- fn := syslook("makeslicecopy")
- s := ir.Nod(ir.OSLICEHEADER, nil, nil)
- s.SetLeft(mkcall1(fn, types.Types[types.TUNSAFEPTR], init, typename(t.Elem()), length, copylen, conv(copyptr, types.Types[types.TUNSAFEPTR])))
- s.Left().MarkNonNil()
- s.PtrList().Set2(length, length)
- s.SetType(t)
- n = typecheck(s, ctxExpr)
- n = walkexpr(n, init)
+ return s
}
+ // Replace make+copy with runtime.makeslicecopy.
+ // instantiate makeslicecopy(typ *byte, tolen int, fromlen int, from unsafe.Pointer) unsafe.Pointer
+ fn := syslook("makeslicecopy")
+ s := ir.Nod(ir.OSLICEHEADER, nil, nil)
+ s.SetLeft(mkcall1(fn, types.Types[types.TUNSAFEPTR], init, typename(t.Elem()), length, copylen, conv(copyptr, types.Types[types.TUNSAFEPTR])))
+ s.Left().MarkNonNil()
+ s.PtrList().Set2(length, length)
+ s.SetType(t)
+ n = typecheck(s, ctxExpr)
+ return walkexpr(n, init)
case ir.ORUNESTR:
a := nodnil()
@@ -1456,7 +1518,7 @@ opswitch:
a = ir.Nod(ir.OADDR, temp(t), nil)
}
// intstring(*[4]byte, rune)
- n = mkcall("intstring", n.Type(), init, a, conv(n.Left(), types.Types[types.TINT64]))
+ return mkcall("intstring", n.Type(), init, a, conv(n.Left(), types.Types[types.TINT64]))
case ir.OBYTES2STR, ir.ORUNES2STR:
a := nodnil()
@@ -1467,30 +1529,29 @@ opswitch:
}
if n.Op() == ir.ORUNES2STR {
// slicerunetostring(*[32]byte, []rune) string
- n = mkcall("slicerunetostring", n.Type(), init, a, n.Left())
- } else {
- // slicebytetostring(*[32]byte, ptr *byte, n int) string
- n.SetLeft(cheapexpr(n.Left(), init))
- ptr, len := backingArrayPtrLen(n.Left())
- n = mkcall("slicebytetostring", n.Type(), init, a, ptr, len)
+ return mkcall("slicerunetostring", n.Type(), init, a, n.Left())
}
+ // slicebytetostring(*[32]byte, ptr *byte, n int) string
+ n.SetLeft(cheapexpr(n.Left(), init))
+ ptr, len := backingArrayPtrLen(n.Left())
+ return mkcall("slicebytetostring", n.Type(), init, a, ptr, len)
case ir.OBYTES2STRTMP:
n.SetLeft(walkexpr(n.Left(), init))
if !instrumenting {
// Let the backend handle OBYTES2STRTMP directly
// to avoid a function call to slicebytetostringtmp.
- break
+ return n
}
// slicebytetostringtmp(ptr *byte, n int) string
n.SetLeft(cheapexpr(n.Left(), init))
ptr, len := backingArrayPtrLen(n.Left())
- n = mkcall("slicebytetostringtmp", n.Type(), init, ptr, len)
+ return mkcall("slicebytetostringtmp", n.Type(), init, ptr, len)
case ir.OSTR2BYTES:
s := n.Left()
if ir.IsConst(s, constant.String) {
- sc := s.StringVal()
+ sc := ir.StringVal(s)
// Allocate a [n]byte of the right size.
t := types.NewArray(types.Types[types.TUINT8], int64(len(sc)))
@@ -1514,10 +1575,10 @@ opswitch:
}
// Slice the [n]byte to a []byte.
- n.SetOp(ir.OSLICEARR)
- n.SetLeft(p)
- n = walkexpr(n, init)
- break
+ slice := ir.NodAt(n.Pos(), ir.OSLICEARR, p, nil)
+ slice.SetType(n.Type())
+ slice.SetTypecheck(1)
+ return walkexpr(slice, init)
}
a := nodnil()
@@ -1527,7 +1588,7 @@ opswitch:
a = ir.Nod(ir.OADDR, temp(t), nil)
}
// stringtoslicebyte(*32[byte], string) []byte
- n = mkcall("stringtoslicebyte", n.Type(), init, a, conv(s, types.Types[types.TSTRING]))
+ return mkcall("stringtoslicebyte", n.Type(), init, a, conv(s, types.Types[types.TSTRING]))
case ir.OSTR2BYTESTMP:
// []byte(string) conversion that creates a slice
@@ -1538,6 +1599,7 @@ opswitch:
// The only such case today is:
// for i, c := range []byte(string)
n.SetLeft(walkexpr(n.Left(), init))
+ return n
case ir.OSTR2RUNES:
a := nodnil()
@@ -1547,7 +1609,7 @@ opswitch:
a = ir.Nod(ir.OADDR, temp(t), nil)
}
// stringtoslicerune(*[32]rune, string) []rune
- n = mkcall("stringtoslicerune", n.Type(), init, a, conv(n.Left(), types.Types[types.TSTRING]))
+ return mkcall("stringtoslicerune", n.Type(), init, a, conv(n.Left(), types.Types[types.TSTRING]))
case ir.OARRAYLIT, ir.OSLICELIT, ir.OMAPLIT, ir.OSTRUCTLIT, ir.OPTRLIT:
if isStaticCompositeLiteral(n) && !canSSAType(n.Type()) {
@@ -1555,55 +1617,29 @@ opswitch:
// Make direct reference to the static data. See issue 12841.
vstat := readonlystaticname(n.Type())
fixedlit(inInitFunction, initKindStatic, n, vstat, init)
- n = vstat
- n = typecheck(n, ctxExpr)
- break
+ return typecheck(vstat, ctxExpr)
}
var_ := temp(n.Type())
anylit(n, var_, init)
- n = var_
+ return var_
case ir.OSEND:
n1 := n.Right()
n1 = assignconv(n1, n.Left().Type().Elem(), "chan send")
n1 = walkexpr(n1, init)
n1 = ir.Nod(ir.OADDR, n1, nil)
- n = mkcall1(chanfn("chansend1", 2, n.Left().Type()), nil, init, n.Left(), n1)
+ return mkcall1(chanfn("chansend1", 2, n.Left().Type()), nil, init, n.Left(), n1)
case ir.OCLOSURE:
- n = walkclosure(n, init)
+ return walkclosure(n, init)
case ir.OCALLPART:
- n = walkpartialcall(n, init)
+ return walkpartialcall(n.(*ir.CallPartExpr), init)
}
- // Expressions that are constant at run time but not
- // considered const by the language spec are not turned into
- // constants until walk. For example, if n is y%1 == 0, the
- // walk of y%1 may have replaced it by 0.
- // Check whether n with its updated args is itself now a constant.
- t := n.Type()
- n = evalConst(n)
- if n.Type() != t {
- base.Fatalf("evconst changed Type: %v had type %v, now %v", n, t, n.Type())
- }
- if n.Op() == ir.OLITERAL {
- n = typecheck(n, ctxExpr)
- // Emit string symbol now to avoid emitting
- // any concurrently during the backend.
- if v := n.Val(); v.Kind() == constant.String {
- _ = stringsym(n.Pos(), constant.StringVal(v))
- }
- }
-
- updateHasCall(n)
-
- if base.Flag.LowerW != 0 && n != nil {
- ir.Dump("after walk expr", n)
- }
-
- base.Pos = lno
- return n
+ // No return! Each case must return (or panic),
+ // to avoid confusion about what gets returned
+ // in the presence of type assertions.
}
// markTypeUsedInInterface marks that type t is converted to an interface.
@@ -1622,7 +1658,7 @@ func markTypeUsedInInterface(t *types.Type, from *obj.LSym) {
func markUsedIfaceMethod(n ir.Node) {
ityp := n.Left().Left().Type()
tsym := typenamesym(ityp).Linksym()
- r := obj.Addrel(Curfn.Func().LSym)
+ r := obj.Addrel(Curfn.LSym)
r.Sym = tsym
// n.Left.Xoffset is the method index * Widthptr (the offset of code pointer
// in itab).
@@ -1636,7 +1672,7 @@ func markUsedIfaceMethod(n ir.Node) {
// name can be derived from the names of the returned types.
//
// If no such function is necessary, it returns (Txxx, Txxx).
-func rtconvfn(src, dst *types.Type) (param, result types.EType) {
+func rtconvfn(src, dst *types.Type) (param, result types.Kind) {
if thearch.SoftFloat {
return types.Txxx, types.Txxx
}
@@ -1644,31 +1680,31 @@ func rtconvfn(src, dst *types.Type) (param, result types.EType) {
switch thearch.LinkArch.Family {
case sys.ARM, sys.MIPS:
if src.IsFloat() {
- switch dst.Etype {
+ switch dst.Kind() {
case types.TINT64, types.TUINT64:
- return types.TFLOAT64, dst.Etype
+ return types.TFLOAT64, dst.Kind()
}
}
if dst.IsFloat() {
- switch src.Etype {
+ switch src.Kind() {
case types.TINT64, types.TUINT64:
- return src.Etype, types.TFLOAT64
+ return src.Kind(), types.TFLOAT64
}
}
case sys.I386:
if src.IsFloat() {
- switch dst.Etype {
+ switch dst.Kind() {
case types.TINT64, types.TUINT64:
- return types.TFLOAT64, dst.Etype
+ return types.TFLOAT64, dst.Kind()
case types.TUINT32, types.TUINT, types.TUINTPTR:
return types.TFLOAT64, types.TUINT32
}
}
if dst.IsFloat() {
- switch src.Etype {
+ switch src.Kind() {
case types.TINT64, types.TUINT64:
- return src.Etype, types.TFLOAT64
+ return src.Kind(), types.TFLOAT64
case types.TUINT32, types.TUINT, types.TUINTPTR:
return types.TUINT32, types.TFLOAT64
}
@@ -1773,7 +1809,7 @@ func ascompatet(nl ir.Nodes, nr *types.Type) []ir.Node {
// Any assignment to an lvalue that might cause a function call must be
// deferred until all the returned values have been read.
if fncall(l, r.Type) {
- tmp := temp(r.Type)
+ tmp := ir.Node(temp(r.Type))
tmp = typecheck(tmp, ctxExpr)
a := ir.Nod(ir.OAS, l, tmp)
a = convas(a, &mm)
@@ -1806,7 +1842,7 @@ func mkdotargslice(typ *types.Type, args []ir.Node) ir.Node {
n = nodnil()
n.SetType(typ)
} else {
- n = ir.Nod(ir.OCOMPLIT, nil, typenod(typ))
+ n = ir.Nod(ir.OCOMPLIT, nil, ir.TypeNode(typ))
n.PtrList().Append(args...)
n.SetImplicit(true)
}
@@ -1918,7 +1954,7 @@ func walkprint(nn ir.Node, init *ir.Nodes) ir.Node {
for i := 0; i < len(s); {
var strs []string
for i < len(s) && ir.IsConst(s[i], constant.String) {
- strs = append(strs, s[i].StringVal())
+ strs = append(strs, ir.StringVal(s[i]))
i++
}
if len(strs) > 0 {
@@ -1935,7 +1971,7 @@ func walkprint(nn ir.Node, init *ir.Nodes) ir.Node {
for i, n := range nn.List().Slice() {
if n.Op() == ir.OLITERAL {
if n.Type() == types.UntypedRune {
- n = defaultlit(n, types.Runetype)
+ n = defaultlit(n, types.RuneType)
}
switch n.Val().Kind() {
@@ -1947,17 +1983,17 @@ func walkprint(nn ir.Node, init *ir.Nodes) ir.Node {
}
}
- if n.Op() != ir.OLITERAL && n.Type() != nil && n.Type().Etype == types.TIDEAL {
+ if n.Op() != ir.OLITERAL && n.Type() != nil && n.Type().Kind() == types.TIDEAL {
n = defaultlit(n, types.Types[types.TINT64])
}
n = defaultlit(n, nil)
nn.List().SetIndex(i, n)
- if n.Type() == nil || n.Type().Etype == types.TFORW {
+ if n.Type() == nil || n.Type().Kind() == types.TFORW {
continue
}
var on ir.Node
- switch n.Type().Etype {
+ switch n.Type().Kind() {
case types.TINTER:
if n.Type().IsEmptyInterface() {
on = syslook("printeface")
@@ -1982,7 +2018,7 @@ func walkprint(nn ir.Node, init *ir.Nodes) ir.Node {
on = syslook("printslice")
on = substArgTypes(on, n.Type()) // any-1
case types.TUINT, types.TUINT8, types.TUINT16, types.TUINT32, types.TUINT64, types.TUINTPTR:
- if isRuntimePkg(n.Type().Sym.Pkg) && n.Type().Sym.Name == "hex" {
+ if isRuntimePkg(n.Type().Sym().Pkg) && n.Type().Sym().Name == "hex" {
on = syslook("printhex")
} else {
on = syslook("printuint")
@@ -1998,7 +2034,7 @@ func walkprint(nn ir.Node, init *ir.Nodes) ir.Node {
case types.TSTRING:
cs := ""
if ir.IsConst(n, constant.String) {
- cs = n.StringVal()
+ cs = ir.StringVal(n)
}
switch cs {
case " ":
@@ -2030,10 +2066,10 @@ func walkprint(nn ir.Node, init *ir.Nodes) ir.Node {
typecheckslice(calls, ctxStmt)
walkexprlist(calls, init)
- r := ir.Nod(ir.OEMPTY, nil, nil)
+ r := ir.Nod(ir.OBLOCK, nil, nil)
r = typecheck(r, ctxStmt)
- r = walkexpr(r, init)
- r.PtrInit().Set(calls)
+ r = walkstmt(r)
+ r.PtrList().Set(calls)
return r
}
@@ -2056,9 +2092,9 @@ func isReflectHeaderDataField(l ir.Node) bool {
var tsym *types.Sym
switch l.Op() {
case ir.ODOT:
- tsym = l.Left().Type().Sym
+ tsym = l.Left().Type().Sym()
case ir.ODOTPTR:
- tsym = l.Left().Type().Elem().Sym
+ tsym = l.Left().Type().Elem().Sym()
default:
return false
}
@@ -2136,7 +2172,7 @@ func reorder3(all []ir.Node) []ir.Node {
switch l.Op() {
default:
- base.Fatalf("reorder3 unexpected lvalue %#v", l.Op())
+ base.Fatalf("reorder3 unexpected lvalue %v", l.Op())
case ir.ONAME:
break
@@ -2171,7 +2207,7 @@ func reorder3save(n ir.Node, all []ir.Node, i int, early *[]ir.Node) ir.Node {
return n
}
- q := temp(n.Type())
+ q := ir.Node(temp(n.Type()))
q = ir.Nod(ir.OAS, q, n)
q = typecheck(q, ctxStmt)
*early = append(*early, q)
@@ -2408,7 +2444,7 @@ func paramstoheap(params *types.Type) []ir.Node {
continue
}
- if stackcopy := v.Name().Param.Stackcopy; stackcopy != nil {
+ if stackcopy := v.Name().Stackcopy; stackcopy != nil {
nn = append(nn, walkstmt(ir.Nod(ir.ODCL, v, nil)))
if stackcopy.Class() == ir.PPARAM {
nn = append(nn, walkstmt(typecheck(ir.Nod(ir.OAS, v, stackcopy), ctxStmt)))
@@ -2429,7 +2465,7 @@ func paramstoheap(params *types.Type) []ir.Node {
func zeroResults() {
for _, f := range Curfn.Type().Results().Fields().Slice() {
v := ir.AsNode(f.Nname)
- if v != nil && v.Name().Param.Heapaddr != nil {
+ if v != nil && v.Name().Heapaddr != nil {
// The local which points to the return value is the
// thing that needs zeroing. This is already handled
// by a Needzero annotation in plive.go:livenessepilogue.
@@ -2442,10 +2478,10 @@ func zeroResults() {
// I don't think the zeroing below matters.
// The stack return value will never be marked as live anywhere in the function.
// It is not written to until deferreturn returns.
- v = v.Name().Param.Stackcopy
+ v = v.Name().Stackcopy
}
// Zero the stack location containing f.
- Curfn.Func().Enter.Append(ir.NodAt(Curfn.Pos(), ir.OAS, v, nil))
+ Curfn.Enter.Append(ir.NodAt(Curfn.Pos(), ir.OAS, v, nil))
}
}
@@ -2458,7 +2494,7 @@ func returnsfromheap(params *types.Type) []ir.Node {
if v == nil {
continue
}
- if stackcopy := v.Name().Param.Stackcopy; stackcopy != nil && stackcopy.Class() == ir.PPARAMOUT {
+ if stackcopy := v.Name().Stackcopy; stackcopy != nil && stackcopy.Class() == ir.PPARAMOUT {
nn = append(nn, walkstmt(typecheck(ir.Nod(ir.OAS, stackcopy, v), ctxStmt)))
}
}
@@ -2475,14 +2511,14 @@ func heapmoves() {
nn := paramstoheap(Curfn.Type().Recvs())
nn = append(nn, paramstoheap(Curfn.Type().Params())...)
nn = append(nn, paramstoheap(Curfn.Type().Results())...)
- Curfn.Func().Enter.Append(nn...)
- base.Pos = Curfn.Func().Endlineno
- Curfn.Func().Exit.Append(returnsfromheap(Curfn.Type().Results())...)
+ Curfn.Enter.Append(nn...)
+ base.Pos = Curfn.Endlineno
+ Curfn.Exit.Append(returnsfromheap(Curfn.Type().Results())...)
base.Pos = lno
}
func vmkcall(fn ir.Node, t *types.Type, init *ir.Nodes, va []ir.Node) ir.Node {
- if fn.Type() == nil || fn.Type().Etype != types.TFUNC {
+ if fn.Type() == nil || fn.Type().Kind() != types.TFUNC {
base.Fatalf("mkcall %v %v", fn, fn.Type())
}
@@ -2655,7 +2691,7 @@ func addstr(n ir.Node, init *ir.Nodes) ir.Node {
sz := int64(0)
for _, n1 := range n.List().Slice() {
if n1.Op() == ir.OLITERAL {
- sz += int64(len(n1.StringVal()))
+ sz += int64(len(ir.StringVal(n1)))
}
}
@@ -2683,7 +2719,7 @@ func addstr(n ir.Node, init *ir.Nodes) ir.Node {
fn = "concatstrings"
t := types.NewSlice(types.Types[types.TSTRING])
- slice := ir.Nod(ir.OCOMPLIT, nil, typenod(t))
+ slice := ir.Nod(ir.OCOMPLIT, nil, ir.TypeNode(t))
if prealloc[n] != nil {
prealloc[slice] = prealloc[n]
}
@@ -2778,7 +2814,7 @@ func appendslice(n ir.Node, init *ir.Nodes) ir.Node {
nptr2 := l2
- Curfn.Func().SetWBPos(n.Pos())
+ Curfn.SetWBPos(n.Pos())
// instantiate typedslicecopy(typ *type, dstPtr *any, dstLen int, srcPtr *any, srcLen int) int
fn := syslook("typedslicecopy")
@@ -2963,7 +2999,7 @@ func extendslice(n ir.Node, init *ir.Nodes) ir.Node {
hasPointers := elemtype.HasPointers()
if hasPointers {
clrname = "memclrHasPointers"
- Curfn.Func().SetWBPos(n.Pos())
+ Curfn.SetWBPos(n.Pos())
}
var clr ir.Nodes
@@ -3097,7 +3133,7 @@ func walkappend(n ir.Node, init *ir.Nodes, dst ir.Node) ir.Node {
//
func copyany(n ir.Node, init *ir.Nodes, runtimecall bool) ir.Node {
if n.Left().Type().Elem().HasPointers() {
- Curfn.Func().SetWBPos(n.Pos())
+ Curfn.SetWBPos(n.Pos())
fn := writebarrierfn("typedslicecopy", n.Left().Type().Elem(), n.Right().Type().Elem())
n.SetLeft(cheapexpr(n.Left(), init))
ptrL, lenL := backingArrayPtrLen(n.Left())
@@ -3152,7 +3188,7 @@ func copyany(n ir.Node, init *ir.Nodes, runtimecall bool) ir.Node {
fn := syslook("memmove")
fn = substArgTypes(fn, nl.Type().Elem(), nl.Type().Elem())
- nwid := temp(types.Types[types.TUINTPTR])
+ nwid := ir.Node(temp(types.Types[types.TUINTPTR]))
setwid := ir.Nod(ir.OAS, nwid, conv(nlen, types.Types[types.TUINTPTR]))
ne.PtrBody().Append(setwid)
nwid = ir.Nod(ir.OMUL, nwid, nodintconst(nl.Type().Elem().Width))
@@ -3179,10 +3215,10 @@ func eqfor(t *types.Type) (n ir.Node, needsize bool) {
sym := typesymprefix(".eq", t)
n := NewName(sym)
setNodeNameFunc(n)
- n.SetType(functype(nil, []ir.Node{
+ n.SetType(functype(nil, []*ir.Field{
anonfield(types.NewPtr(t)),
anonfield(types.NewPtr(t)),
- }, []ir.Node{
+ }, []*ir.Field{
anonfield(types.Types[types.TBOOL]),
}))
return n, false
@@ -3262,7 +3298,7 @@ func walkcompare(n ir.Node, init *ir.Nodes) ir.Node {
maxcmpsize = 2 * int64(thearch.LinkArch.RegSize)
}
- switch t.Etype {
+ switch t.Kind() {
default:
if base.Debug.Libfuzzer != 0 && t.IsInteger() {
n.SetLeft(cheapexpr(n.Left(), init))
@@ -3313,7 +3349,7 @@ func walkcompare(n ir.Node, init *ir.Nodes) ir.Node {
return n
case types.TARRAY:
// We can compare several elements at once with 2/4/8 byte integer compares
- inline = t.NumElem() <= 1 || (issimple[t.Elem().Etype] && (t.NumElem() <= 4 || t.Elem().Width*t.NumElem() <= maxcmpsize))
+ inline = t.NumElem() <= 1 || (issimple[t.Elem().Kind()] && (t.NumElem() <= 4 || t.Elem().Width*t.NumElem() <= maxcmpsize))
case types.TSTRUCT:
inline = t.NumComponents(types.IgnoreBlankFields) <= 4
}
@@ -3449,7 +3485,7 @@ func walkcompare(n ir.Node, init *ir.Nodes) ir.Node {
func tracecmpArg(n ir.Node, t *types.Type, init *ir.Nodes) ir.Node {
// Ugly hack to avoid "constant -1 overflows uintptr" errors, etc.
- if n.Op() == ir.OLITERAL && n.Type().IsSigned() && n.Int64Val() < 0 {
+ if n.Op() == ir.OLITERAL && n.Type().IsSigned() && ir.Int64Val(n) < 0 {
n = copyexpr(n, n.Type(), init)
}
@@ -3519,7 +3555,7 @@ func walkcompareString(n ir.Node, init *ir.Nodes) ir.Node {
// Length-only checks are ok, though.
maxRewriteLen = 0
}
- if s := cs.StringVal(); len(s) <= maxRewriteLen {
+ if s := ir.StringVal(cs); len(s) <= maxRewriteLen {
if len(s) > 0 {
ncs = safeexpr(ncs, init)
}
@@ -3614,7 +3650,7 @@ func bounded(n ir.Node, max int64) bool {
bits := int32(8 * n.Type().Width)
if smallintconst(n) {
- v := n.Int64Val()
+ v := ir.Int64Val(n)
return 0 <= v && v < max
}
@@ -3623,9 +3659,9 @@ func bounded(n ir.Node, max int64) bool {
v := int64(-1)
switch {
case smallintconst(n.Left()):
- v = n.Left().Int64Val()
+ v = ir.Int64Val(n.Left())
case smallintconst(n.Right()):
- v = n.Right().Int64Val()
+ v = ir.Int64Val(n.Right())
if n.Op() == ir.OANDNOT {
v = ^v
if !sign {
@@ -3639,7 +3675,7 @@ func bounded(n ir.Node, max int64) bool {
case ir.OMOD:
if !sign && smallintconst(n.Right()) {
- v := n.Right().Int64Val()
+ v := ir.Int64Val(n.Right())
if 0 <= v && v <= max {
return true
}
@@ -3647,7 +3683,7 @@ func bounded(n ir.Node, max int64) bool {
case ir.ODIV:
if !sign && smallintconst(n.Right()) {
- v := n.Right().Int64Val()
+ v := ir.Int64Val(n.Right())
for bits > 0 && v >= 2 {
bits--
v >>= 1
@@ -3656,7 +3692,7 @@ func bounded(n ir.Node, max int64) bool {
case ir.ORSH:
if !sign && smallintconst(n.Right()) {
- v := n.Right().Int64Val()
+ v := ir.Int64Val(n.Right())
if v > int64(bits) {
return true
}
@@ -3695,7 +3731,7 @@ func usemethod(n ir.Node) {
}
if res1 == nil {
- if p0.Type.Etype != types.TINT {
+ if p0.Type.Kind() != types.TINT {
return
}
} else {
@@ -3710,10 +3746,10 @@ func usemethod(n ir.Node) {
// Note: Don't rely on res0.Type.String() since its formatting depends on multiple factors
// (including global variables such as numImports - was issue #19028).
// Also need to check for reflect package itself (see Issue #38515).
- if s := res0.Type.Sym; s != nil && s.Name == "Method" && isReflectPkg(s.Pkg) {
- Curfn.Func().SetReflectMethod(true)
+ if s := res0.Type.Sym(); s != nil && s.Name == "Method" && isReflectPkg(s.Pkg) {
+ Curfn.SetReflectMethod(true)
// The LSym is initialized at this point. We need to set the attribute on the LSym.
- Curfn.Func().LSym.Set(obj.AttrReflectMethod, true)
+ Curfn.LSym.Set(obj.AttrReflectMethod, true)
}
}
@@ -3739,7 +3775,7 @@ func usefield(n ir.Node) {
if t.IsPtr() {
t = t.Elem()
}
- field := n.Opt().(*types.Field)
+ field := n.(*ir.SelectorExpr).Selection
if field == nil {
base.Fatalf("usefield %v %v without paramfld", n.Left().Type(), n.Sym())
}
@@ -3754,7 +3790,7 @@ func usefield(n ir.Node) {
if outer.IsPtr() {
outer = outer.Elem()
}
- if outer.Sym == nil {
+ if outer.Sym() == nil {
base.Errorf("tracked field must be in named struct type")
}
if !types.IsExported(field.Sym.Name) {
@@ -3762,113 +3798,97 @@ func usefield(n ir.Node) {
}
sym := tracksym(outer, field)
- if Curfn.Func().FieldTrack == nil {
- Curfn.Func().FieldTrack = make(map[*types.Sym]struct{})
+ if Curfn.FieldTrack == nil {
+ Curfn.FieldTrack = make(map[*types.Sym]struct{})
}
- Curfn.Func().FieldTrack[sym] = struct{}{}
+ Curfn.FieldTrack[sym] = struct{}{}
}
-func candiscardlist(l ir.Nodes) bool {
- for _, n := range l.Slice() {
- if !candiscard(n) {
- return false
+// hasSideEffects reports whether n contains any operations that could have observable side effects.
+func hasSideEffects(n ir.Node) bool {
+ found := ir.Find(n, func(n ir.Node) interface{} {
+ switch n.Op() {
+ // Assume side effects unless we know otherwise.
+ default:
+ return n
+
+ // No side effects here (arguments are checked separately).
+ case ir.ONAME,
+ ir.ONONAME,
+ ir.OTYPE,
+ ir.OPACK,
+ ir.OLITERAL,
+ ir.ONIL,
+ ir.OADD,
+ ir.OSUB,
+ ir.OOR,
+ ir.OXOR,
+ ir.OADDSTR,
+ ir.OADDR,
+ ir.OANDAND,
+ ir.OBYTES2STR,
+ ir.ORUNES2STR,
+ ir.OSTR2BYTES,
+ ir.OSTR2RUNES,
+ ir.OCAP,
+ ir.OCOMPLIT,
+ ir.OMAPLIT,
+ ir.OSTRUCTLIT,
+ ir.OARRAYLIT,
+ ir.OSLICELIT,
+ ir.OPTRLIT,
+ ir.OCONV,
+ ir.OCONVIFACE,
+ ir.OCONVNOP,
+ ir.ODOT,
+ ir.OEQ,
+ ir.ONE,
+ ir.OLT,
+ ir.OLE,
+ ir.OGT,
+ ir.OGE,
+ ir.OKEY,
+ ir.OSTRUCTKEY,
+ ir.OLEN,
+ ir.OMUL,
+ ir.OLSH,
+ ir.ORSH,
+ ir.OAND,
+ ir.OANDNOT,
+ ir.ONEW,
+ ir.ONOT,
+ ir.OBITNOT,
+ ir.OPLUS,
+ ir.ONEG,
+ ir.OOROR,
+ ir.OPAREN,
+ ir.ORUNESTR,
+ ir.OREAL,
+ ir.OIMAG,
+ ir.OCOMPLEX:
+ return nil
+
+ // Only possible side effect is division by zero.
+ case ir.ODIV, ir.OMOD:
+ if n.Right().Op() != ir.OLITERAL || constant.Sign(n.Right().Val()) == 0 {
+ return n
+ }
+
+ // Only possible side effect is panic on invalid size,
+ // but many makechan and makemap use size zero, which is definitely OK.
+ case ir.OMAKECHAN, ir.OMAKEMAP:
+ if !ir.IsConst(n.Left(), constant.Int) || constant.Sign(n.Left().Val()) != 0 {
+ return n
+ }
+
+ // Only possible side effect is panic on invalid size.
+ // TODO(rsc): Merge with previous case (probably breaks toolstash -cmp).
+ case ir.OMAKESLICE, ir.OMAKESLICECOPY:
+ return n
}
- }
- return true
-}
-
-func candiscard(n ir.Node) bool {
- if n == nil {
- return true
- }
-
- switch n.Op() {
- default:
- return false
-
- // Discardable as long as the subpieces are.
- case ir.ONAME,
- ir.ONONAME,
- ir.OTYPE,
- ir.OPACK,
- ir.OLITERAL,
- ir.ONIL,
- ir.OADD,
- ir.OSUB,
- ir.OOR,
- ir.OXOR,
- ir.OADDSTR,
- ir.OADDR,
- ir.OANDAND,
- ir.OBYTES2STR,
- ir.ORUNES2STR,
- ir.OSTR2BYTES,
- ir.OSTR2RUNES,
- ir.OCAP,
- ir.OCOMPLIT,
- ir.OMAPLIT,
- ir.OSTRUCTLIT,
- ir.OARRAYLIT,
- ir.OSLICELIT,
- ir.OPTRLIT,
- ir.OCONV,
- ir.OCONVIFACE,
- ir.OCONVNOP,
- ir.ODOT,
- ir.OEQ,
- ir.ONE,
- ir.OLT,
- ir.OLE,
- ir.OGT,
- ir.OGE,
- ir.OKEY,
- ir.OSTRUCTKEY,
- ir.OLEN,
- ir.OMUL,
- ir.OLSH,
- ir.ORSH,
- ir.OAND,
- ir.OANDNOT,
- ir.ONEW,
- ir.ONOT,
- ir.OBITNOT,
- ir.OPLUS,
- ir.ONEG,
- ir.OOROR,
- ir.OPAREN,
- ir.ORUNESTR,
- ir.OREAL,
- ir.OIMAG,
- ir.OCOMPLEX:
- break
-
- // Discardable as long as we know it's not division by zero.
- case ir.ODIV, ir.OMOD:
- if n.Right().Op() == ir.OLITERAL && constant.Sign(n.Right().Val()) != 0 {
- break
- }
- return false
-
- // Discardable as long as we know it won't fail because of a bad size.
- case ir.OMAKECHAN, ir.OMAKEMAP:
- if ir.IsConst(n.Left(), constant.Int) && constant.Sign(n.Left().Val()) == 0 {
- break
- }
- return false
-
- // Difficult to tell what sizes are okay.
- case ir.OMAKESLICE:
- return false
-
- case ir.OMAKESLICECOPY:
- return false
- }
-
- if !candiscard(n.Left()) || !candiscard(n.Right()) || !candiscardlist(n.Init()) || !candiscardlist(n.Body()) || !candiscardlist(n.List()) || !candiscardlist(n.Rlist()) {
- return false
- }
-
- return true
+ return nil
+ })
+ return found != nil
}
// Rewrite
@@ -3910,7 +3930,7 @@ func wrapCall(n ir.Node, init *ir.Nodes) ir.Node {
// origArgs keeps track of what argument is uintptr-unsafe/unsafe-uintptr conversion.
origArgs := make([]ir.Node, n.List().Len())
- t := ir.Nod(ir.OTFUNC, nil, nil)
+ var funcArgs []*ir.Field
for i, arg := range n.List().Slice() {
s := lookupN("a", i)
if !isBuiltinCall && arg.Op() == ir.OCONVNOP && arg.Type().IsUintptr() && arg.Left().Type().IsUnsafePtr() {
@@ -3918,8 +3938,9 @@ func wrapCall(n ir.Node, init *ir.Nodes) ir.Node {
arg = arg.Left()
n.List().SetIndex(i, arg)
}
- t.PtrList().Append(symfield(s, arg.Type()))
+ funcArgs = append(funcArgs, symfield(s, arg.Type()))
}
+ t := ir.NewFuncType(base.Pos, nil, funcArgs, nil)
wrapCall_prgen++
sym := lookupN("wrap·", wrapCall_prgen)
@@ -3945,12 +3966,12 @@ func wrapCall(n ir.Node, init *ir.Nodes) ir.Node {
funcbody()
- fn = typecheck(fn, ctxStmt)
+ typecheckFunc(fn)
typecheckslice(fn.Body().Slice(), ctxStmt)
xtop = append(xtop, fn)
call = ir.Nod(ir.OCALL, nil, nil)
- call.SetLeft(fn.Func().Nname)
+ call.SetLeft(fn.Nname)
call.PtrList().Set(n.List().Slice())
call = typecheck(call, ctxStmt)
call = walkexpr(call, init)
@@ -4088,6 +4109,6 @@ func walkCheckPtrArithmetic(n ir.Node, init *ir.Nodes) ir.Node {
// checkPtr reports whether pointer checking should be enabled for
// function fn at a given level. See debugHelpFooter for defined
// levels.
-func checkPtr(fn ir.Node, level int) bool {
- return base.Debug.Checkptr >= level && fn.Func().Pragma&ir.NoCheckPtr == 0
+func checkPtr(fn *ir.Func, level int) bool {
+ return base.Debug.Checkptr >= level && fn.Pragma&ir.NoCheckPtr == 0
}
diff --git a/src/cmd/compile/internal/ir/bitset.go b/src/cmd/compile/internal/ir/bitset.go
index 29f136296f..0c7bd542f6 100644
--- a/src/cmd/compile/internal/ir/bitset.go
+++ b/src/cmd/compile/internal/ir/bitset.go
@@ -14,6 +14,18 @@ func (f *bitset8) set(mask uint8, b bool) {
}
}
+func (f bitset8) get2(shift uint8) uint8 {
+ return uint8(f>>shift) & 3
+}
+
+// set2 sets two bits in f using the bottom two bits of b.
+func (f *bitset8) set2(shift uint8, b uint8) {
+ // Clear old bits.
+ *(*uint8)(f) &^= 3 << shift
+ // Set new bits.
+ *(*uint8)(f) |= uint8(b&3) << shift
+}
+
type bitset16 uint16
func (f *bitset16) set(mask uint16, b bool) {
diff --git a/src/cmd/compile/internal/ir/copy.go b/src/cmd/compile/internal/ir/copy.go
new file mode 100644
index 0000000000..7f5d313513
--- /dev/null
+++ b/src/cmd/compile/internal/ir/copy.go
@@ -0,0 +1,100 @@
+// Copyright 2020 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 ir
+
+import (
+ "cmd/compile/internal/base"
+ "cmd/internal/src"
+)
+
+// A Node may implement the Orig and SetOrig method to
+// maintain a pointer to the "unrewritten" form of a Node.
+// If a Node does not implement OrigNode, it is its own Orig.
+//
+// Note that both SepCopy and Copy have definitions compatible
+// with a Node that does not implement OrigNode: such a Node
+// is its own Orig, and in that case, that's what both want to return
+// anyway (SepCopy unconditionally, and Copy only when the input
+// is its own Orig as well, but if the output does not implement
+// OrigNode, then neither does the input, making the condition true).
+type OrigNode interface {
+ Node
+ Orig() Node
+ SetOrig(Node)
+}
+
+// Orig returns the “original” node for n.
+// If n implements OrigNode, Orig returns n.Orig().
+// Otherwise Orig returns n itself.
+func Orig(n Node) Node {
+ if n, ok := n.(OrigNode); ok {
+ o := n.Orig()
+ if o == nil {
+ Dump("Orig nil", n)
+ base.Fatalf("Orig returned nil")
+ }
+ return o
+ }
+ return n
+}
+
+// SepCopy returns a separate shallow copy of n,
+// breaking any Orig link to any other nodes.
+func SepCopy(n Node) Node {
+ n = n.copy()
+ if n, ok := n.(OrigNode); ok {
+ n.SetOrig(n)
+ }
+ return n
+}
+
+// Copy returns a shallow copy of n.
+// If Orig(n) == n, then Orig(Copy(n)) == the copy.
+// Otherwise the Orig link is preserved as well.
+//
+// The specific semantics surrounding Orig are subtle but right for most uses.
+// See issues #26855 and #27765 for pitfalls.
+func Copy(n Node) Node {
+ c := n.copy()
+ if n, ok := n.(OrigNode); ok && n.Orig() == n {
+ c.(OrigNode).SetOrig(c)
+ }
+ return c
+}
+
+func copyList(x Nodes) Nodes {
+ c := make([]Node, x.Len())
+ copy(c, x.Slice())
+ return AsNodes(c)
+}
+
+// DeepCopy returns a “deep” copy of n, with its entire structure copied
+// (except for shared nodes like ONAME, ONONAME, OLITERAL, and OTYPE).
+// If pos.IsKnown(), it sets the source position of newly allocated Nodes to pos.
+func DeepCopy(pos src.XPos, n Node) Node {
+ var edit func(Node) Node
+ edit = func(x Node) Node {
+ switch x.Op() {
+ case OPACK, ONAME, ONONAME, OLITERAL, ONIL, OTYPE:
+ return x
+ }
+ x = Copy(x)
+ if pos.IsKnown() {
+ x.SetPos(pos)
+ }
+ EditChildren(x, edit)
+ return x
+ }
+ return edit(n)
+}
+
+// DeepCopyList returns a list of deep copies (using DeepCopy) of the nodes in list.
+func DeepCopyList(pos src.XPos, list []Node) []Node {
+ var out []Node
+ for _, n := range list {
+ out = append(out, DeepCopy(pos, n))
+ }
+ return out
+}
diff --git a/src/cmd/compile/internal/ir/dump.go b/src/cmd/compile/internal/ir/dump.go
index fe1410969f..bff3a40855 100644
--- a/src/cmd/compile/internal/ir/dump.go
+++ b/src/cmd/compile/internal/ir/dump.go
@@ -200,9 +200,9 @@ func (p *dumper) dump(x reflect.Value, depth int) {
typ := x.Type()
isNode := false
- if n, ok := x.Interface().(node); ok {
+ if n, ok := x.Interface().(Node); ok {
isNode = true
- p.printf("%s %s {", n.op.String(), p.addr(x))
+ p.printf("%s %s {", n.Op().String(), p.addr(x))
} else {
p.printf("%s {", typ)
}
diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go
new file mode 100644
index 0000000000..8ea31c1929
--- /dev/null
+++ b/src/cmd/compile/internal/ir/expr.go
@@ -0,0 +1,860 @@
+// Copyright 2020 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 ir
+
+import (
+ "cmd/compile/internal/base"
+ "cmd/compile/internal/types"
+ "cmd/internal/src"
+ "go/constant"
+)
+
+func maybeDo(x Node, err error, do func(Node) error) error {
+ if x != nil && err == nil {
+ err = do(x)
+ }
+ return err
+}
+
+func maybeDoList(x Nodes, err error, do func(Node) error) error {
+ if err == nil {
+ err = DoList(x, do)
+ }
+ return err
+}
+
+func maybeEdit(x Node, edit func(Node) Node) Node {
+ if x == nil {
+ return x
+ }
+ return edit(x)
+}
+
+// An Expr is a Node that can appear as an expression.
+type Expr interface {
+ Node
+ isExpr()
+}
+
+// A miniExpr is a miniNode with extra fields common to expressions.
+// TODO(rsc): Once we are sure about the contents, compact the bools
+// into a bit field and leave extra bits available for implementations
+// embedding miniExpr. Right now there are ~60 unused bits sitting here.
+type miniExpr struct {
+ miniNode
+ typ *types.Type
+ init Nodes // TODO(rsc): Don't require every Node to have an init
+ opt interface{} // TODO(rsc): Don't require every Node to have an opt?
+ flags bitset8
+}
+
+const (
+ miniExprHasCall = 1 << iota
+ miniExprImplicit
+ miniExprNonNil
+ miniExprTransient
+ miniExprBounded
+)
+
+func (*miniExpr) isExpr() {}
+
+func (n *miniExpr) Type() *types.Type { return n.typ }
+func (n *miniExpr) SetType(x *types.Type) { n.typ = x }
+func (n *miniExpr) Opt() interface{} { return n.opt }
+func (n *miniExpr) SetOpt(x interface{}) { n.opt = x }
+func (n *miniExpr) HasCall() bool { return n.flags&miniExprHasCall != 0 }
+func (n *miniExpr) SetHasCall(b bool) { n.flags.set(miniExprHasCall, b) }
+func (n *miniExpr) Implicit() bool { return n.flags&miniExprImplicit != 0 }
+func (n *miniExpr) SetImplicit(b bool) { n.flags.set(miniExprImplicit, b) }
+func (n *miniExpr) NonNil() bool { return n.flags&miniExprNonNil != 0 }
+func (n *miniExpr) MarkNonNil() { n.flags |= miniExprNonNil }
+func (n *miniExpr) Transient() bool { return n.flags&miniExprTransient != 0 }
+func (n *miniExpr) SetTransient(b bool) { n.flags.set(miniExprTransient, b) }
+func (n *miniExpr) Bounded() bool { return n.flags&miniExprBounded != 0 }
+func (n *miniExpr) SetBounded(b bool) { n.flags.set(miniExprBounded, b) }
+func (n *miniExpr) Init() Nodes { return n.init }
+func (n *miniExpr) PtrInit() *Nodes { return &n.init }
+func (n *miniExpr) SetInit(x Nodes) { n.init = x }
+
+func toNtype(x Node) Ntype {
+ if x == nil {
+ return nil
+ }
+ if _, ok := x.(Ntype); !ok {
+ Dump("not Ntype", x)
+ }
+ return x.(Ntype)
+}
+
+// An AddStringExpr is a string concatenation Expr[0] + Exprs[1] + ... + Expr[len(Expr)-1].
+type AddStringExpr struct {
+ miniExpr
+ List_ Nodes
+}
+
+func NewAddStringExpr(pos src.XPos, list []Node) *AddStringExpr {
+ n := &AddStringExpr{}
+ n.pos = pos
+ n.op = OADDSTR
+ n.List_.Set(list)
+ return n
+}
+
+func (n *AddStringExpr) List() Nodes { return n.List_ }
+func (n *AddStringExpr) PtrList() *Nodes { return &n.List_ }
+func (n *AddStringExpr) SetList(x Nodes) { n.List_ = x }
+
+// An AddrExpr is an address-of expression &X.
+// It may end up being a normal address-of or an allocation of a composite literal.
+type AddrExpr struct {
+ miniExpr
+ X Node
+ Alloc Node // preallocated storage if any
+}
+
+func NewAddrExpr(pos src.XPos, x Node) *AddrExpr {
+ n := &AddrExpr{X: x}
+ n.op = OADDR
+ n.pos = pos
+ return n
+}
+
+func (n *AddrExpr) Left() Node { return n.X }
+func (n *AddrExpr) SetLeft(x Node) { n.X = x }
+func (n *AddrExpr) Right() Node { return n.Alloc }
+func (n *AddrExpr) SetRight(x Node) { n.Alloc = x }
+
+func (n *AddrExpr) SetOp(op Op) {
+ switch op {
+ default:
+ panic(n.no("SetOp " + op.String()))
+ case OADDR, OPTRLIT:
+ n.op = op
+ }
+}
+
+// A BinaryExpr is a binary expression X Op Y,
+// or Op(X, Y) for builtin functions that do not become calls.
+type BinaryExpr struct {
+ miniExpr
+ X Node
+ Y Node
+}
+
+func NewBinaryExpr(pos src.XPos, op Op, x, y Node) *BinaryExpr {
+ n := &BinaryExpr{X: x, Y: y}
+ n.pos = pos
+ n.SetOp(op)
+ return n
+}
+
+func (n *BinaryExpr) Left() Node { return n.X }
+func (n *BinaryExpr) SetLeft(x Node) { n.X = x }
+func (n *BinaryExpr) Right() Node { return n.Y }
+func (n *BinaryExpr) SetRight(y Node) { n.Y = y }
+
+func (n *BinaryExpr) SetOp(op Op) {
+ switch op {
+ default:
+ panic(n.no("SetOp " + op.String()))
+ case OADD, OADDSTR, OAND, OANDNOT, ODIV, OEQ, OGE, OGT, OLE,
+ OLSH, OLT, OMOD, OMUL, ONE, OOR, ORSH, OSUB, OXOR,
+ OCOPY, OCOMPLEX,
+ OEFACE:
+ n.op = op
+ }
+}
+
+// A CallUse records how the result of the call is used:
+type CallUse int
+
+const (
+ _ CallUse = iota
+
+ CallUseExpr // single expression result is used
+ CallUseList // list of results are used
+ CallUseStmt // results not used - call is a statement
+)
+
+// A CallExpr is a function call X(Args).
+type CallExpr struct {
+ miniExpr
+ orig Node
+ X Node
+ Args Nodes
+ Rargs Nodes // TODO(rsc): Delete.
+ Body_ Nodes // TODO(rsc): Delete.
+ DDD bool
+ Use CallUse
+ NoInline_ bool
+}
+
+func NewCallExpr(pos src.XPos, op Op, fun Node, args []Node) *CallExpr {
+ n := &CallExpr{X: fun}
+ n.pos = pos
+ n.orig = n
+ n.SetOp(op)
+ n.Args.Set(args)
+ return n
+}
+
+func (*CallExpr) isStmt() {}
+
+func (n *CallExpr) Orig() Node { return n.orig }
+func (n *CallExpr) SetOrig(x Node) { n.orig = x }
+func (n *CallExpr) Left() Node { return n.X }
+func (n *CallExpr) SetLeft(x Node) { n.X = x }
+func (n *CallExpr) List() Nodes { return n.Args }
+func (n *CallExpr) PtrList() *Nodes { return &n.Args }
+func (n *CallExpr) SetList(x Nodes) { n.Args = x }
+func (n *CallExpr) Rlist() Nodes { return n.Rargs }
+func (n *CallExpr) PtrRlist() *Nodes { return &n.Rargs }
+func (n *CallExpr) SetRlist(x Nodes) { n.Rargs = x }
+func (n *CallExpr) IsDDD() bool { return n.DDD }
+func (n *CallExpr) SetIsDDD(x bool) { n.DDD = x }
+func (n *CallExpr) NoInline() bool { return n.NoInline_ }
+func (n *CallExpr) SetNoInline(x bool) { n.NoInline_ = x }
+func (n *CallExpr) Body() Nodes { return n.Body_ }
+func (n *CallExpr) PtrBody() *Nodes { return &n.Body_ }
+func (n *CallExpr) SetBody(x Nodes) { n.Body_ = x }
+
+func (n *CallExpr) SetOp(op Op) {
+ switch op {
+ default:
+ panic(n.no("SetOp " + op.String()))
+ case OCALL, OCALLFUNC, OCALLINTER, OCALLMETH,
+ OAPPEND, ODELETE, OGETG, OMAKE, OPRINT, OPRINTN, ORECOVER:
+ n.op = op
+ }
+}
+
+// A CallPartExpr is a method expression X.Method (uncalled).
+type CallPartExpr struct {
+ miniExpr
+ Func_ *Func
+ X Node
+ Method *types.Field
+}
+
+func NewCallPartExpr(pos src.XPos, x Node, method *types.Field, fn *Func) *CallPartExpr {
+ n := &CallPartExpr{Func_: fn, X: x, Method: method}
+ n.op = OCALLPART
+ n.pos = pos
+ n.typ = fn.Type()
+ n.Func_ = fn
+ return n
+}
+
+func (n *CallPartExpr) Func() *Func { return n.Func_ }
+func (n *CallPartExpr) Left() Node { return n.X }
+func (n *CallPartExpr) Sym() *types.Sym { return n.Method.Sym }
+func (n *CallPartExpr) SetLeft(x Node) { n.X = x }
+
+// A ClosureExpr is a function literal expression.
+type ClosureExpr struct {
+ miniExpr
+ Func_ *Func
+}
+
+func NewClosureExpr(pos src.XPos, fn *Func) *ClosureExpr {
+ n := &ClosureExpr{Func_: fn}
+ n.op = OCLOSURE
+ n.pos = pos
+ return n
+}
+
+func (n *ClosureExpr) Func() *Func { return n.Func_ }
+
+// A ClosureRead denotes reading a variable stored within a closure struct.
+type ClosureReadExpr struct {
+ miniExpr
+ Offset_ int64
+}
+
+func NewClosureRead(typ *types.Type, offset int64) *ClosureReadExpr {
+ n := &ClosureReadExpr{Offset_: offset}
+ n.typ = typ
+ n.op = OCLOSUREREAD
+ return n
+}
+
+func (n *ClosureReadExpr) Type() *types.Type { return n.typ }
+func (n *ClosureReadExpr) Offset() int64 { return n.Offset_ }
+
+// A CompLitExpr is a composite literal Type{Vals}.
+// Before type-checking, the type is Ntype.
+type CompLitExpr struct {
+ miniExpr
+ orig Node
+ Ntype Ntype
+ List_ Nodes // initialized values
+}
+
+func NewCompLitExpr(pos src.XPos, op Op, typ Ntype, list []Node) *CompLitExpr {
+ n := &CompLitExpr{Ntype: typ}
+ n.pos = pos
+ n.SetOp(op)
+ n.List_.Set(list)
+ n.orig = n
+ return n
+}
+
+func (n *CompLitExpr) Orig() Node { return n.orig }
+func (n *CompLitExpr) SetOrig(x Node) { n.orig = x }
+func (n *CompLitExpr) Right() Node { return n.Ntype }
+func (n *CompLitExpr) SetRight(x Node) { n.Ntype = toNtype(x) }
+func (n *CompLitExpr) List() Nodes { return n.List_ }
+func (n *CompLitExpr) PtrList() *Nodes { return &n.List_ }
+func (n *CompLitExpr) SetList(x Nodes) { n.List_ = x }
+
+func (n *CompLitExpr) SetOp(op Op) {
+ switch op {
+ default:
+ panic(n.no("SetOp " + op.String()))
+ case OARRAYLIT, OCOMPLIT, OMAPLIT, OSTRUCTLIT, OSLICELIT:
+ n.op = op
+ }
+}
+
+type ConstExpr struct {
+ miniExpr
+ val constant.Value
+ orig Node
+}
+
+func NewConstExpr(val constant.Value, orig Node) Node {
+ n := &ConstExpr{orig: orig, val: val}
+ n.op = OLITERAL
+ n.pos = orig.Pos()
+ n.SetType(orig.Type())
+ n.SetTypecheck(orig.Typecheck())
+ n.SetDiag(orig.Diag())
+ return n
+}
+
+func (n *ConstExpr) Sym() *types.Sym { return n.orig.Sym() }
+func (n *ConstExpr) Orig() Node { return n.orig }
+func (n *ConstExpr) SetOrig(orig Node) { panic(n.no("SetOrig")) }
+func (n *ConstExpr) Val() constant.Value { return n.val }
+
+// A ConvExpr is a conversion Type(X).
+// It may end up being a value or a type.
+type ConvExpr struct {
+ miniExpr
+ X Node
+}
+
+func NewConvExpr(pos src.XPos, op Op, typ *types.Type, x Node) *ConvExpr {
+ n := &ConvExpr{X: x}
+ n.pos = pos
+ n.typ = typ
+ n.SetOp(op)
+ return n
+}
+
+func (n *ConvExpr) Left() Node { return n.X }
+func (n *ConvExpr) SetLeft(x Node) { n.X = x }
+
+func (n *ConvExpr) SetOp(op Op) {
+ switch op {
+ default:
+ panic(n.no("SetOp " + op.String()))
+ case OCONV, OCONVIFACE, OCONVNOP, OBYTES2STR, OBYTES2STRTMP, ORUNES2STR, OSTR2BYTES, OSTR2BYTESTMP, OSTR2RUNES, ORUNESTR:
+ n.op = op
+ }
+}
+
+// An IndexExpr is an index expression X[Y].
+type IndexExpr struct {
+ miniExpr
+ X Node
+ Index Node
+ Assigned bool
+}
+
+func NewIndexExpr(pos src.XPos, x, index Node) *IndexExpr {
+ n := &IndexExpr{X: x, Index: index}
+ n.pos = pos
+ n.op = OINDEX
+ return n
+}
+
+func (n *IndexExpr) Left() Node { return n.X }
+func (n *IndexExpr) SetLeft(x Node) { n.X = x }
+func (n *IndexExpr) Right() Node { return n.Index }
+func (n *IndexExpr) SetRight(y Node) { n.Index = y }
+func (n *IndexExpr) IndexMapLValue() bool { return n.Assigned }
+func (n *IndexExpr) SetIndexMapLValue(x bool) { n.Assigned = x }
+
+func (n *IndexExpr) SetOp(op Op) {
+ switch op {
+ default:
+ panic(n.no("SetOp " + op.String()))
+ case OINDEX, OINDEXMAP:
+ n.op = op
+ }
+}
+
+// A KeyExpr is a Key: Value composite literal key.
+type KeyExpr struct {
+ miniExpr
+ Key Node
+ Value Node
+}
+
+func NewKeyExpr(pos src.XPos, key, value Node) *KeyExpr {
+ n := &KeyExpr{Key: key, Value: value}
+ n.pos = pos
+ n.op = OKEY
+ return n
+}
+
+func (n *KeyExpr) Left() Node { return n.Key }
+func (n *KeyExpr) SetLeft(x Node) { n.Key = x }
+func (n *KeyExpr) Right() Node { return n.Value }
+func (n *KeyExpr) SetRight(y Node) { n.Value = y }
+
+// A StructKeyExpr is an Field: Value composite literal key.
+type StructKeyExpr struct {
+ miniExpr
+ Field *types.Sym
+ Value Node
+ Offset_ int64
+}
+
+func NewStructKeyExpr(pos src.XPos, field *types.Sym, value Node) *StructKeyExpr {
+ n := &StructKeyExpr{Field: field, Value: value}
+ n.pos = pos
+ n.op = OSTRUCTKEY
+ n.Offset_ = types.BADWIDTH
+ return n
+}
+
+func (n *StructKeyExpr) Sym() *types.Sym { return n.Field }
+func (n *StructKeyExpr) SetSym(x *types.Sym) { n.Field = x }
+func (n *StructKeyExpr) Left() Node { return n.Value }
+func (n *StructKeyExpr) SetLeft(x Node) { n.Value = x }
+func (n *StructKeyExpr) Offset() int64 { return n.Offset_ }
+func (n *StructKeyExpr) SetOffset(x int64) { n.Offset_ = x }
+
+// An InlinedCallExpr is an inlined function call.
+type InlinedCallExpr struct {
+ miniExpr
+ Body_ Nodes
+ ReturnVars Nodes
+}
+
+func NewInlinedCallExpr(pos src.XPos, body, retvars []Node) *InlinedCallExpr {
+ n := &InlinedCallExpr{}
+ n.pos = pos
+ n.op = OINLCALL
+ n.Body_.Set(body)
+ n.ReturnVars.Set(retvars)
+ return n
+}
+
+func (n *InlinedCallExpr) Body() Nodes { return n.Body_ }
+func (n *InlinedCallExpr) PtrBody() *Nodes { return &n.Body_ }
+func (n *InlinedCallExpr) SetBody(x Nodes) { n.Body_ = x }
+func (n *InlinedCallExpr) Rlist() Nodes { return n.ReturnVars }
+func (n *InlinedCallExpr) PtrRlist() *Nodes { return &n.ReturnVars }
+func (n *InlinedCallExpr) SetRlist(x Nodes) { n.ReturnVars = x }
+
+// A LogicalExpr is a expression X Op Y where Op is && or ||.
+// It is separate from BinaryExpr to make room for statements
+// that must be executed before Y but after X.
+type LogicalExpr struct {
+ miniExpr
+ X Node
+ Y Node
+}
+
+func NewLogicalExpr(pos src.XPos, op Op, x, y Node) *LogicalExpr {
+ n := &LogicalExpr{X: x, Y: y}
+ n.pos = pos
+ n.SetOp(op)
+ return n
+}
+
+func (n *LogicalExpr) Left() Node { return n.X }
+func (n *LogicalExpr) SetLeft(x Node) { n.X = x }
+func (n *LogicalExpr) Right() Node { return n.Y }
+func (n *LogicalExpr) SetRight(y Node) { n.Y = y }
+
+func (n *LogicalExpr) SetOp(op Op) {
+ switch op {
+ default:
+ panic(n.no("SetOp " + op.String()))
+ case OANDAND, OOROR:
+ n.op = op
+ }
+}
+
+// A MakeExpr is a make expression: make(Type[, Len[, Cap]]).
+// Op is OMAKECHAN, OMAKEMAP, OMAKESLICE, or OMAKESLICECOPY,
+// but *not* OMAKE (that's a pre-typechecking CallExpr).
+type MakeExpr struct {
+ miniExpr
+ Len Node
+ Cap Node
+}
+
+func NewMakeExpr(pos src.XPos, op Op, len, cap Node) *MakeExpr {
+ n := &MakeExpr{Len: len, Cap: cap}
+ n.pos = pos
+ n.SetOp(op)
+ return n
+}
+
+func (n *MakeExpr) Left() Node { return n.Len }
+func (n *MakeExpr) SetLeft(x Node) { n.Len = x }
+func (n *MakeExpr) Right() Node { return n.Cap }
+func (n *MakeExpr) SetRight(x Node) { n.Cap = x }
+
+func (n *MakeExpr) SetOp(op Op) {
+ switch op {
+ default:
+ panic(n.no("SetOp " + op.String()))
+ case OMAKECHAN, OMAKEMAP, OMAKESLICE, OMAKESLICECOPY:
+ n.op = op
+ }
+}
+
+// A MethodExpr is a method value X.M (where X is an expression, not a type).
+type MethodExpr struct {
+ miniExpr
+ X Node
+ M Node
+ Sym_ *types.Sym
+ Offset_ int64
+ Class_ Class
+ Method *types.Field
+}
+
+func NewMethodExpr(pos src.XPos, x, m Node) *MethodExpr {
+ n := &MethodExpr{X: x, M: m}
+ n.pos = pos
+ n.op = OMETHEXPR
+ n.Offset_ = types.BADWIDTH
+ return n
+}
+
+func (n *MethodExpr) Left() Node { return n.X }
+func (n *MethodExpr) SetLeft(x Node) { n.X = x }
+func (n *MethodExpr) Right() Node { return n.M }
+func (n *MethodExpr) SetRight(y Node) { n.M = y }
+func (n *MethodExpr) Sym() *types.Sym { return n.Sym_ }
+func (n *MethodExpr) SetSym(x *types.Sym) { n.Sym_ = x }
+func (n *MethodExpr) Offset() int64 { return n.Offset_ }
+func (n *MethodExpr) SetOffset(x int64) { n.Offset_ = x }
+func (n *MethodExpr) Class() Class { return n.Class_ }
+func (n *MethodExpr) SetClass(x Class) { n.Class_ = x }
+
+// A NilExpr represents the predefined untyped constant nil.
+// (It may be copied and assigned a type, though.)
+type NilExpr struct {
+ miniExpr
+ Sym_ *types.Sym // TODO: Remove
+}
+
+func NewNilExpr(pos src.XPos) *NilExpr {
+ n := &NilExpr{}
+ n.pos = pos
+ n.op = ONIL
+ return n
+}
+
+func (n *NilExpr) Sym() *types.Sym { return n.Sym_ }
+func (n *NilExpr) SetSym(x *types.Sym) { n.Sym_ = x }
+
+// A ParenExpr is a parenthesized expression (X).
+// It may end up being a value or a type.
+type ParenExpr struct {
+ miniExpr
+ X Node
+}
+
+func NewParenExpr(pos src.XPos, x Node) *ParenExpr {
+ n := &ParenExpr{X: x}
+ n.op = OPAREN
+ n.pos = pos
+ return n
+}
+
+func (n *ParenExpr) Left() Node { return n.X }
+func (n *ParenExpr) SetLeft(x Node) { n.X = x }
+
+func (*ParenExpr) CanBeNtype() {}
+
+// SetOTYPE changes n to be an OTYPE node returning t,
+// like all the type nodes in type.go.
+func (n *ParenExpr) SetOTYPE(t *types.Type) {
+ n.op = OTYPE
+ n.typ = t
+ t.SetNod(n)
+}
+
+// A ResultExpr represents a direct access to a result slot on the stack frame.
+type ResultExpr struct {
+ miniExpr
+ Offset_ int64
+}
+
+func NewResultExpr(pos src.XPos, typ *types.Type, offset int64) *ResultExpr {
+ n := &ResultExpr{Offset_: offset}
+ n.pos = pos
+ n.op = ORESULT
+ n.typ = typ
+ return n
+}
+
+func (n *ResultExpr) Offset() int64 { return n.Offset_ }
+func (n *ResultExpr) SetOffset(x int64) { n.Offset_ = x }
+
+// A SelectorExpr is a selector expression X.Sym.
+type SelectorExpr struct {
+ miniExpr
+ X Node
+ Sel *types.Sym
+ Offset_ int64
+ Selection *types.Field
+}
+
+func NewSelectorExpr(pos src.XPos, op Op, x Node, sel *types.Sym) *SelectorExpr {
+ n := &SelectorExpr{X: x, Sel: sel}
+ n.pos = pos
+ n.Offset_ = types.BADWIDTH
+ n.SetOp(op)
+ return n
+}
+
+func (n *SelectorExpr) SetOp(op Op) {
+ switch op {
+ default:
+ panic(n.no("SetOp " + op.String()))
+ case ODOT, ODOTPTR, ODOTMETH, ODOTINTER, OXDOT:
+ n.op = op
+ }
+}
+
+func (n *SelectorExpr) Left() Node { return n.X }
+func (n *SelectorExpr) SetLeft(x Node) { n.X = x }
+func (n *SelectorExpr) Sym() *types.Sym { return n.Sel }
+func (n *SelectorExpr) SetSym(x *types.Sym) { n.Sel = x }
+func (n *SelectorExpr) Offset() int64 { return n.Offset_ }
+func (n *SelectorExpr) SetOffset(x int64) { n.Offset_ = x }
+
+// Before type-checking, bytes.Buffer is a SelectorExpr.
+// After type-checking it becomes a Name.
+func (*SelectorExpr) CanBeNtype() {}
+
+// A SliceExpr is a slice expression X[Low:High] or X[Low:High:Max].
+type SliceExpr struct {
+ miniExpr
+ X Node
+ List_ Nodes // TODO(rsc): Use separate Nodes
+}
+
+func NewSliceExpr(pos src.XPos, op Op, x Node) *SliceExpr {
+ n := &SliceExpr{X: x}
+ n.pos = pos
+ n.op = op
+ return n
+}
+
+func (n *SliceExpr) Left() Node { return n.X }
+func (n *SliceExpr) SetLeft(x Node) { n.X = x }
+func (n *SliceExpr) List() Nodes { return n.List_ }
+func (n *SliceExpr) PtrList() *Nodes { return &n.List_ }
+func (n *SliceExpr) SetList(x Nodes) { n.List_ = x }
+
+func (n *SliceExpr) SetOp(op Op) {
+ switch op {
+ default:
+ panic(n.no("SetOp " + op.String()))
+ case OSLICE, OSLICEARR, OSLICESTR, OSLICE3, OSLICE3ARR:
+ n.op = op
+ }
+}
+
+// SliceBounds returns n's slice bounds: low, high, and max in expr[low:high:max].
+// n must be a slice expression. max is nil if n is a simple slice expression.
+func (n *SliceExpr) SliceBounds() (low, high, max Node) {
+ if n.List_.Len() == 0 {
+ return nil, nil, nil
+ }
+
+ switch n.Op() {
+ case OSLICE, OSLICEARR, OSLICESTR:
+ s := n.List_.Slice()
+ return s[0], s[1], nil
+ case OSLICE3, OSLICE3ARR:
+ s := n.List_.Slice()
+ return s[0], s[1], s[2]
+ }
+ base.Fatalf("SliceBounds op %v: %v", n.Op(), n)
+ return nil, nil, nil
+}
+
+// SetSliceBounds sets n's slice bounds, where n is a slice expression.
+// n must be a slice expression. If max is non-nil, n must be a full slice expression.
+func (n *SliceExpr) SetSliceBounds(low, high, max Node) {
+ switch n.Op() {
+ case OSLICE, OSLICEARR, OSLICESTR:
+ if max != nil {
+ base.Fatalf("SetSliceBounds %v given three bounds", n.Op())
+ }
+ s := n.List_.Slice()
+ if s == nil {
+ if low == nil && high == nil {
+ return
+ }
+ n.List_.Set2(low, high)
+ return
+ }
+ s[0] = low
+ s[1] = high
+ return
+ case OSLICE3, OSLICE3ARR:
+ s := n.List_.Slice()
+ if s == nil {
+ if low == nil && high == nil && max == nil {
+ return
+ }
+ n.List_.Set3(low, high, max)
+ return
+ }
+ s[0] = low
+ s[1] = high
+ s[2] = max
+ return
+ }
+ base.Fatalf("SetSliceBounds op %v: %v", n.Op(), n)
+}
+
+// IsSlice3 reports whether o is a slice3 op (OSLICE3, OSLICE3ARR).
+// o must be a slicing op.
+func (o Op) IsSlice3() bool {
+ switch o {
+ case OSLICE, OSLICEARR, OSLICESTR:
+ return false
+ case OSLICE3, OSLICE3ARR:
+ return true
+ }
+ base.Fatalf("IsSlice3 op %v", o)
+ return false
+}
+
+// A SliceHeader expression constructs a slice header from its parts.
+type SliceHeaderExpr struct {
+ miniExpr
+ Ptr Node
+ LenCap_ Nodes // TODO(rsc): Split into two Node fields
+}
+
+func NewSliceHeaderExpr(pos src.XPos, typ *types.Type, ptr, len, cap Node) *SliceHeaderExpr {
+ n := &SliceHeaderExpr{Ptr: ptr}
+ n.pos = pos
+ n.op = OSLICEHEADER
+ n.typ = typ
+ n.LenCap_.Set2(len, cap)
+ return n
+}
+
+func (n *SliceHeaderExpr) Left() Node { return n.Ptr }
+func (n *SliceHeaderExpr) SetLeft(x Node) { n.Ptr = x }
+func (n *SliceHeaderExpr) List() Nodes { return n.LenCap_ }
+func (n *SliceHeaderExpr) PtrList() *Nodes { return &n.LenCap_ }
+func (n *SliceHeaderExpr) SetList(x Nodes) { n.LenCap_ = x }
+
+// A StarExpr is a dereference expression *X.
+// It may end up being a value or a type.
+type StarExpr struct {
+ miniExpr
+ X Node
+}
+
+func NewStarExpr(pos src.XPos, x Node) *StarExpr {
+ n := &StarExpr{X: x}
+ n.op = ODEREF
+ n.pos = pos
+ return n
+}
+
+func (n *StarExpr) Left() Node { return n.X }
+func (n *StarExpr) SetLeft(x Node) { n.X = x }
+
+func (*StarExpr) CanBeNtype() {}
+
+// SetOTYPE changes n to be an OTYPE node returning t,
+// like all the type nodes in type.go.
+func (n *StarExpr) SetOTYPE(t *types.Type) {
+ n.op = OTYPE
+ n.X = nil
+ n.typ = t
+ t.SetNod(n)
+}
+
+// A TypeAssertionExpr is a selector expression X.(Type).
+// Before type-checking, the type is Ntype.
+type TypeAssertExpr struct {
+ miniExpr
+ X Node
+ Ntype Node // TODO: Should be Ntype, but reused as address of type structure
+ Itab Nodes // Itab[0] is itab
+}
+
+func NewTypeAssertExpr(pos src.XPos, x Node, typ Ntype) *TypeAssertExpr {
+ n := &TypeAssertExpr{X: x, Ntype: typ}
+ n.pos = pos
+ n.op = ODOTTYPE
+ return n
+}
+
+func (n *TypeAssertExpr) Left() Node { return n.X }
+func (n *TypeAssertExpr) SetLeft(x Node) { n.X = x }
+func (n *TypeAssertExpr) Right() Node { return n.Ntype }
+func (n *TypeAssertExpr) SetRight(x Node) { n.Ntype = x } // TODO: toNtype(x)
+func (n *TypeAssertExpr) List() Nodes { return n.Itab }
+func (n *TypeAssertExpr) PtrList() *Nodes { return &n.Itab }
+func (n *TypeAssertExpr) SetList(x Nodes) { n.Itab = x }
+
+func (n *TypeAssertExpr) SetOp(op Op) {
+ switch op {
+ default:
+ panic(n.no("SetOp " + op.String()))
+ case ODOTTYPE, ODOTTYPE2:
+ n.op = op
+ }
+}
+
+// A UnaryExpr is a unary expression Op X,
+// or Op(X) for a builtin function that does not end up being a call.
+type UnaryExpr struct {
+ miniExpr
+ X Node
+}
+
+func NewUnaryExpr(pos src.XPos, op Op, x Node) *UnaryExpr {
+ n := &UnaryExpr{X: x}
+ n.pos = pos
+ n.SetOp(op)
+ return n
+}
+
+func (n *UnaryExpr) Left() Node { return n.X }
+func (n *UnaryExpr) SetLeft(x Node) { n.X = x }
+
+func (n *UnaryExpr) SetOp(op Op) {
+ switch op {
+ default:
+ panic(n.no("SetOp " + op.String()))
+ case OBITNOT, ONEG, ONOT, OPLUS, ORECV,
+ OALIGNOF, OCAP, OCLOSE, OIMAG, OLEN, ONEW,
+ OOFFSETOF, OPANIC, OREAL, OSIZEOF,
+ OCHECKNIL, OCFUNC, OIDATA, OITAB, ONEWOBJ, OSPTR, OVARDEF, OVARKILL, OVARLIVE:
+ n.op = op
+ }
+}
diff --git a/src/cmd/compile/internal/ir/fmt.go b/src/cmd/compile/internal/ir/fmt.go
index f394219c05..4bea6e2ae0 100644
--- a/src/cmd/compile/internal/ir/fmt.go
+++ b/src/cmd/compile/internal/ir/fmt.go
@@ -9,9 +9,11 @@ import (
"fmt"
"go/constant"
"io"
- "strconv"
+ "os"
+ "path/filepath"
+ "reflect"
"strings"
- "sync"
+
"unicode/utf8"
"cmd/compile/internal/base"
@@ -19,134 +21,7 @@ import (
"cmd/internal/src"
)
-// A FmtFlag value is a set of flags (or 0).
-// They control how the Xconv functions format their values.
-// See the respective function's documentation for details.
-type FmtFlag int
-
-const ( // fmt.Format flag/prec or verb
- FmtLeft FmtFlag = 1 << iota // '-'
- FmtSharp // '#'
- FmtSign // '+'
- FmtUnsigned // internal use only (historic: u flag)
- FmtShort // verb == 'S' (historic: h flag)
- FmtLong // verb == 'L' (historic: l flag)
- FmtComma // '.' (== hasPrec) (historic: , flag)
- FmtByte // '0' (historic: hh flag)
-)
-
-// fmtFlag computes the (internal) FmtFlag
-// value given the fmt.State and format verb.
-func fmtFlag(s fmt.State, verb rune) FmtFlag {
- var flag FmtFlag
- if s.Flag('-') {
- flag |= FmtLeft
- }
- if s.Flag('#') {
- flag |= FmtSharp
- }
- if s.Flag('+') {
- flag |= FmtSign
- }
- if s.Flag(' ') {
- base.Fatalf("FmtUnsigned in format string")
- }
- if _, ok := s.Precision(); ok {
- flag |= FmtComma
- }
- if s.Flag('0') {
- flag |= FmtByte
- }
- switch verb {
- case 'S':
- flag |= FmtShort
- case 'L':
- flag |= FmtLong
- }
- return flag
-}
-
-// Format conversions:
-// TODO(gri) verify these; eliminate those not used anymore
-//
-// %v Op Node opcodes
-// Flags: #: print Go syntax (automatic unless mode == FDbg)
-//
-// %j *Node Node details
-// Flags: 0: suppresses things not relevant until walk
-//
-// %v *Val Constant values
-//
-// %v *types.Sym Symbols
-// %S unqualified identifier in any mode
-// Flags: +,- #: mode (see below)
-// 0: in export mode: unqualified identifier if exported, qualified if not
-//
-// %v *types.Type Types
-// %S omit "func" and receiver in function types
-// %L definition instead of name.
-// Flags: +,- #: mode (see below)
-// ' ' (only in -/Sym mode) print type identifiers wit package name instead of prefix.
-//
-// %v *Node Nodes
-// %S (only in +/debug mode) suppress recursion
-// %L (only in Error mode) print "foo (type Bar)"
-// Flags: +,- #: mode (see below)
-//
-// %v Nodes Node lists
-// Flags: those of *Node
-// .: separate items with ',' instead of ';'
-
-// *types.Sym, *types.Type, and *Node types use the flags below to set the format mode
-const (
- FErr FmtMode = iota
- FDbg
- FTypeId
- FTypeIdName // same as FTypeId, but use package name instead of prefix
-)
-
-// The mode flags '+', '-', and '#' are sticky; they persist through
-// recursions of *Node, *types.Type, and *types.Sym values. The ' ' flag is
-// sticky only on *types.Type recursions and only used in %-/*types.Sym mode.
-//
-// Example: given a *types.Sym: %+v %#v %-v print an identifier properly qualified for debug/export/internal mode
-
-// Useful format combinations:
-// TODO(gri): verify these
-//
-// *Node, Nodes:
-// %+v multiline recursive debug dump of *Node/Nodes
-// %+S non-recursive debug dump
-//
-// *Node:
-// %#v Go format
-// %L "foo (type Bar)" for error messages
-//
-// *types.Type:
-// %#v Go format
-// %#L type definition instead of name
-// %#S omit "func" and receiver in function signature
-//
-// %-v type identifiers
-// %-S type identifiers without "func" and arg names in type signatures (methodsym)
-// %- v type identifiers with package name instead of prefix (typesym, dcommontype, typehash)
-
-// update returns the results of applying f to mode.
-func (f FmtFlag) update(mode FmtMode) (FmtFlag, FmtMode) {
- switch {
- case f&FmtSign != 0:
- mode = FDbg
- case f&FmtSharp != 0:
- // ignore (textual export format no longer supported)
- case f&FmtUnsigned != 0:
- mode = FTypeIdName
- case f&FmtLeft != 0:
- mode = FTypeId
- }
-
- f &^= FmtSharp | FmtLeft | FmtSign
- return f, mode
-}
+// Op
var OpNames = []string{
OADDR: "&",
@@ -214,864 +89,82 @@ var OpNames = []string{
OXOR: "^",
}
+// GoString returns the Go syntax for the Op, or else its name.
func (o Op) GoString() string {
- return fmt.Sprintf("%#v", o)
+ if int(o) < len(OpNames) && OpNames[o] != "" {
+ return OpNames[o]
+ }
+ return o.String()
}
-func (o Op) format(s fmt.State, verb rune, mode FmtMode) {
+// Format implements formatting for an Op.
+// The valid formats are:
+//
+// %v Go syntax ("+", "<-", "print")
+// %+v Debug syntax ("ADD", "RECV", "PRINT")
+//
+func (o Op) Format(s fmt.State, verb rune) {
switch verb {
- case 'v':
- o.oconv(s, fmtFlag(s, verb), mode)
-
default:
fmt.Fprintf(s, "%%!%c(Op=%d)", verb, int(o))
- }
-}
-
-func (o Op) oconv(s fmt.State, flag FmtFlag, mode FmtMode) {
- if flag&FmtSharp != 0 || mode != FDbg {
- if int(o) < len(OpNames) && OpNames[o] != "" {
- fmt.Fprint(s, OpNames[o])
+ case 'v':
+ if s.Flag('+') {
+ // %+v is OMUL instead of "*"
+ io.WriteString(s, o.String())
return
}
+ io.WriteString(s, o.GoString())
}
-
- // 'o.String()' instead of just 'o' to avoid infinite recursion
- fmt.Fprint(s, o.String())
}
-type FmtMode int
-
-type fmtNode struct {
- x Node
- m FmtMode
-}
-
-func (f *fmtNode) Format(s fmt.State, verb rune) { nodeFormat(f.x, s, verb, f.m) }
-
-type fmtOp struct {
- x Op
- m FmtMode
-}
-
-func (f *fmtOp) Format(s fmt.State, verb rune) { f.x.format(s, verb, f.m) }
-
-type fmtType struct {
- x *types.Type
- m FmtMode
-}
-
-func (f *fmtType) Format(s fmt.State, verb rune) { typeFormat(f.x, s, verb, f.m) }
-
-type fmtSym struct {
- x *types.Sym
- m FmtMode
-}
-
-func (f *fmtSym) Format(s fmt.State, verb rune) { symFormat(f.x, s, verb, f.m) }
-
-type fmtNodes struct {
- x Nodes
- m FmtMode
-}
-
-func (f *fmtNodes) Format(s fmt.State, verb rune) { f.x.format(s, verb, f.m) }
-
-func (n *node) Format(s fmt.State, verb rune) {
- FmtNode(n, s, verb)
-}
+// Node
+// FmtNode implements formatting for a Node n.
+// Every Node implementation must define a Format method that calls FmtNode.
+// The valid formats are:
+//
+// %v Go syntax
+// %L Go syntax followed by " (type T)" if type is known.
+// %+v Debug syntax, as in Dump.
+//
func FmtNode(n Node, s fmt.State, verb rune) {
- nodeFormat(n, s, verb, FErr)
-}
-
-func (o Op) Format(s fmt.State, verb rune) { o.format(s, verb, FErr) }
-
-// func (t *types.Type) Format(s fmt.State, verb rune) // in package types
-// func (y *types.Sym) Format(s fmt.State, verb rune) // in package types { y.format(s, verb, FErr) }
-func (n Nodes) Format(s fmt.State, verb rune) { n.format(s, verb, FErr) }
-
-func (m FmtMode) Fprintf(s fmt.State, format string, args ...interface{}) {
- m.prepareArgs(args)
- fmt.Fprintf(s, format, args...)
-}
-
-func (m FmtMode) Sprintf(format string, args ...interface{}) string {
- m.prepareArgs(args)
- return fmt.Sprintf(format, args...)
-}
-
-func (m FmtMode) Sprint(args ...interface{}) string {
- m.prepareArgs(args)
- return fmt.Sprint(args...)
-}
-
-func (m FmtMode) prepareArgs(args []interface{}) {
- for i, arg := range args {
- switch arg := arg.(type) {
- case Op:
- args[i] = &fmtOp{arg, m}
- case Node:
- args[i] = &fmtNode{arg, m}
- case nil:
- args[i] = &fmtNode{nil, m} // assume this was a node interface
- case *types.Type:
- args[i] = &fmtType{arg, m}
- case *types.Sym:
- args[i] = &fmtSym{arg, m}
- case Nodes:
- args[i] = &fmtNodes{arg, m}
- case int32, int64, string, types.EType, constant.Value:
- // OK: printing these types doesn't depend on mode
- default:
- base.Fatalf("mode.prepareArgs type %T", arg)
- }
+ // %+v prints Dump.
+ // Otherwise we print Go syntax.
+ if s.Flag('+') && verb == 'v' {
+ dumpNode(s, n, 1)
+ return
}
-}
-func nodeFormat(n Node, s fmt.State, verb rune, mode FmtMode) {
- switch verb {
- case 'v', 'S', 'L':
- nconvFmt(n, s, fmtFlag(s, verb), mode)
-
- case 'j':
- jconvFmt(n, s, fmtFlag(s, verb))
-
- default:
+ if verb != 'v' && verb != 'S' && verb != 'L' {
fmt.Fprintf(s, "%%!%c(*Node=%p)", verb, n)
- }
-}
-
-// EscFmt is set by the escape analysis code to add escape analysis details to the node print.
-var EscFmt func(n Node, short bool) string
-
-// *Node details
-func jconvFmt(n Node, s fmt.State, flag FmtFlag) {
- short := flag&FmtShort != 0
-
- // Useful to see which nodes in an AST printout are actually identical
- if base.Debug.DumpPtrs != 0 {
- fmt.Fprintf(s, " p(%p)", n)
- }
- if !short && n.Name() != nil && n.Name().Vargen != 0 {
- fmt.Fprintf(s, " g(%d)", n.Name().Vargen)
- }
-
- if base.Debug.DumpPtrs != 0 && !short && n.Name() != nil && n.Name().Defn != nil {
- // Useful to see where Defn is set and what node it points to
- fmt.Fprintf(s, " defn(%p)", n.Name().Defn)
- }
-
- if n.Pos().IsKnown() {
- pfx := ""
- switch n.Pos().IsStmt() {
- case src.PosNotStmt:
- pfx = "_" // "-" would be confusing
- case src.PosIsStmt:
- pfx = "+"
- }
- fmt.Fprintf(s, " l(%s%d)", pfx, n.Pos().Line())
- }
-
- if !short && n.Offset() != types.BADWIDTH {
- fmt.Fprintf(s, " x(%d)", n.Offset())
- }
-
- if n.Class() != 0 {
- fmt.Fprintf(s, " class(%v)", n.Class())
- }
-
- if n.Colas() {
- fmt.Fprintf(s, " colas(%v)", n.Colas())
- }
-
- if EscFmt != nil {
- if esc := EscFmt(n, short); esc != "" {
- fmt.Fprintf(s, " %s", esc)
- }
- }
-
- if !short && n.Typecheck() != 0 {
- fmt.Fprintf(s, " tc(%d)", n.Typecheck())
- }
-
- if n.IsDDD() {
- fmt.Fprintf(s, " isddd(%v)", n.IsDDD())
- }
-
- if n.Implicit() {
- fmt.Fprintf(s, " implicit(%v)", n.Implicit())
- }
-
- if n.Embedded() {
- fmt.Fprintf(s, " embedded")
- }
-
- if n.Op() == ONAME {
- if n.Name().Addrtaken() {
- fmt.Fprint(s, " addrtaken")
- }
- if n.Name().Assigned() {
- fmt.Fprint(s, " assigned")
- }
- if n.Name().IsClosureVar() {
- fmt.Fprint(s, " closurevar")
- }
- if n.Name().Captured() {
- fmt.Fprint(s, " captured")
- }
- if n.Name().IsOutputParamHeapAddr() {
- fmt.Fprint(s, " outputparamheapaddr")
- }
- }
- if n.Bounded() {
- fmt.Fprint(s, " bounded")
- }
- if n.NonNil() {
- fmt.Fprint(s, " nonnil")
- }
-
- if !short && n.HasCall() {
- fmt.Fprint(s, " hascall")
- }
-
- if !short && n.Name() != nil && n.Name().Used() {
- fmt.Fprint(s, " used")
- }
-}
-
-func FmtConst(v constant.Value, flag FmtFlag) string {
- if flag&FmtSharp == 0 && v.Kind() == constant.Complex {
- real, imag := constant.Real(v), constant.Imag(v)
-
- var re string
- sre := constant.Sign(real)
- if sre != 0 {
- re = real.String()
- }
-
- var im string
- sim := constant.Sign(imag)
- if sim != 0 {
- im = imag.String()
- }
-
- switch {
- case sre == 0 && sim == 0:
- return "0"
- case sre == 0:
- return im + "i"
- case sim == 0:
- return re
- case sim < 0:
- return fmt.Sprintf("(%s%si)", re, im)
- default:
- return fmt.Sprintf("(%s+%si)", re, im)
- }
- }
-
- return v.String()
-}
-
-/*
-s%,%,\n%g
-s%\n+%\n%g
-s%^[ ]*T%%g
-s%,.*%%g
-s%.+% [T&] = "&",%g
-s%^ ........*\]%&~%g
-s%~ %%g
-*/
-
-func symfmt(b *bytes.Buffer, s *types.Sym, flag FmtFlag, mode FmtMode) {
- if flag&FmtShort == 0 {
- switch mode {
- case FErr: // This is for the user
- if s.Pkg == BuiltinPkg || s.Pkg == LocalPkg {
- b.WriteString(s.Name)
- return
- }
-
- // If the name was used by multiple packages, display the full path,
- if s.Pkg.Name != "" && NumImport[s.Pkg.Name] > 1 {
- fmt.Fprintf(b, "%q.%s", s.Pkg.Path, s.Name)
- return
- }
- b.WriteString(s.Pkg.Name)
- b.WriteByte('.')
- b.WriteString(s.Name)
- return
-
- case FDbg:
- b.WriteString(s.Pkg.Name)
- b.WriteByte('.')
- b.WriteString(s.Name)
- return
-
- case FTypeIdName:
- // dcommontype, typehash
- b.WriteString(s.Pkg.Name)
- b.WriteByte('.')
- b.WriteString(s.Name)
- return
-
- case FTypeId:
- // (methodsym), typesym, weaksym
- b.WriteString(s.Pkg.Prefix)
- b.WriteByte('.')
- b.WriteString(s.Name)
- return
- }
- }
-
- if flag&FmtByte != 0 {
- // FmtByte (hh) implies FmtShort (h)
- // skip leading "type." in method name
- name := s.Name
- if i := strings.LastIndex(name, "."); i >= 0 {
- name = name[i+1:]
- }
-
- if mode == FDbg {
- fmt.Fprintf(b, "@%q.%s", s.Pkg.Path, name)
- return
- }
-
- b.WriteString(name)
return
}
- b.WriteString(s.Name)
-}
-
-var BasicTypeNames = []string{
- types.TINT: "int",
- types.TUINT: "uint",
- types.TINT8: "int8",
- types.TUINT8: "uint8",
- types.TINT16: "int16",
- types.TUINT16: "uint16",
- types.TINT32: "int32",
- types.TUINT32: "uint32",
- types.TINT64: "int64",
- types.TUINT64: "uint64",
- types.TUINTPTR: "uintptr",
- types.TFLOAT32: "float32",
- types.TFLOAT64: "float64",
- types.TCOMPLEX64: "complex64",
- types.TCOMPLEX128: "complex128",
- types.TBOOL: "bool",
- types.TANY: "any",
- types.TSTRING: "string",
- types.TNIL: "nil",
- types.TIDEAL: "untyped number",
- types.TBLANK: "blank",
-}
-
-var fmtBufferPool = sync.Pool{
- New: func() interface{} {
- return new(bytes.Buffer)
- },
-}
-
-func tconv(t *types.Type, flag FmtFlag, mode FmtMode) string {
- buf := fmtBufferPool.Get().(*bytes.Buffer)
- buf.Reset()
- defer fmtBufferPool.Put(buf)
-
- tconv2(buf, t, flag, mode, nil)
- return types.InternString(buf.Bytes())
-}
-
-// tconv2 writes a string representation of t to b.
-// flag and mode control exactly what is printed.
-// Any types x that are already in the visited map get printed as @%d where %d=visited[x].
-// See #16897 before changing the implementation of tconv.
-func tconv2(b *bytes.Buffer, t *types.Type, flag FmtFlag, mode FmtMode, visited map[*types.Type]int) {
- if off, ok := visited[t]; ok {
- // We've seen this type before, so we're trying to print it recursively.
- // Print a reference to it instead.
- fmt.Fprintf(b, "@%d", off)
- return
- }
- if t == nil {
- b.WriteString("")
- return
- }
- if t.Etype == types.TSSA {
- b.WriteString(t.Extra.(string))
- return
- }
- if t.Etype == types.TTUPLE {
- b.WriteString(t.FieldType(0).String())
- b.WriteByte(',')
- b.WriteString(t.FieldType(1).String())
+ if n == nil {
+ fmt.Fprint(s, "")
return
}
- if t.Etype == types.TRESULTS {
- tys := t.Extra.(*types.Results).Types
- for i, et := range tys {
- if i > 0 {
- b.WriteByte(',')
- }
- b.WriteString(et.String())
- }
- return
- }
-
- flag, mode = flag.update(mode)
- if mode == FTypeIdName {
- flag |= FmtUnsigned
- }
- if t == types.Bytetype || t == types.Runetype {
- // in %-T mode collapse rune and byte with their originals.
- switch mode {
- case FTypeIdName, FTypeId:
- t = types.Types[t.Etype]
- default:
- sconv2(b, t.Sym, FmtShort, mode)
- return
- }
- }
- if t == types.Errortype {
- b.WriteString("error")
- return
- }
-
- // Unless the 'L' flag was specified, if the type has a name, just print that name.
- if flag&FmtLong == 0 && t.Sym != nil && t != types.Types[t.Etype] {
- switch mode {
- case FTypeId, FTypeIdName:
- if flag&FmtShort != 0 {
- if t.Vargen != 0 {
- sconv2(b, t.Sym, FmtShort, mode)
- fmt.Fprintf(b, "·%d", t.Vargen)
- return
- }
- sconv2(b, t.Sym, FmtShort, mode)
- return
- }
-
- if mode == FTypeIdName {
- sconv2(b, t.Sym, FmtUnsigned, mode)
- return
- }
-
- if t.Sym.Pkg == LocalPkg && t.Vargen != 0 {
- b.WriteString(mode.Sprintf("%v·%d", t.Sym, t.Vargen))
- return
- }
- }
-
- sconv2(b, t.Sym, 0, mode)
- return
- }
-
- if int(t.Etype) < len(BasicTypeNames) && BasicTypeNames[t.Etype] != "" {
- var name string
- switch t {
- case types.UntypedBool:
- name = "untyped bool"
- case types.UntypedString:
- name = "untyped string"
- case types.UntypedInt:
- name = "untyped int"
- case types.UntypedRune:
- name = "untyped rune"
- case types.UntypedFloat:
- name = "untyped float"
- case types.UntypedComplex:
- name = "untyped complex"
- default:
- name = BasicTypeNames[t.Etype]
- }
- b.WriteString(name)
- return
- }
-
- if mode == FDbg {
- b.WriteString(t.Etype.String())
- b.WriteByte('-')
- tconv2(b, t, flag, FErr, visited)
- return
- }
-
- // At this point, we might call tconv2 recursively. Add the current type to the visited list so we don't
- // try to print it recursively.
- // We record the offset in the result buffer where the type's text starts. This offset serves as a reference
- // point for any later references to the same type.
- // Note that we remove the type from the visited map as soon as the recursive call is done.
- // This prevents encoding types like map[*int]*int as map[*int]@4. (That encoding would work,
- // but I'd like to use the @ notation only when strictly necessary.)
- if visited == nil {
- visited = map[*types.Type]int{}
- }
- visited[t] = b.Len()
- defer delete(visited, t)
-
- switch t.Etype {
- case types.TPTR:
- b.WriteByte('*')
- switch mode {
- case FTypeId, FTypeIdName:
- if flag&FmtShort != 0 {
- tconv2(b, t.Elem(), FmtShort, mode, visited)
- return
- }
- }
- tconv2(b, t.Elem(), 0, mode, visited)
-
- case types.TARRAY:
- b.WriteByte('[')
- b.WriteString(strconv.FormatInt(t.NumElem(), 10))
- b.WriteByte(']')
- tconv2(b, t.Elem(), 0, mode, visited)
-
- case types.TSLICE:
- b.WriteString("[]")
- tconv2(b, t.Elem(), 0, mode, visited)
-
- case types.TCHAN:
- switch t.ChanDir() {
- case types.Crecv:
- b.WriteString("<-chan ")
- tconv2(b, t.Elem(), 0, mode, visited)
- case types.Csend:
- b.WriteString("chan<- ")
- tconv2(b, t.Elem(), 0, mode, visited)
- default:
- b.WriteString("chan ")
- if t.Elem() != nil && t.Elem().IsChan() && t.Elem().Sym == nil && t.Elem().ChanDir() == types.Crecv {
- b.WriteByte('(')
- tconv2(b, t.Elem(), 0, mode, visited)
- b.WriteByte(')')
- } else {
- tconv2(b, t.Elem(), 0, mode, visited)
- }
- }
-
- case types.TMAP:
- b.WriteString("map[")
- tconv2(b, t.Key(), 0, mode, visited)
- b.WriteByte(']')
- tconv2(b, t.Elem(), 0, mode, visited)
-
- case types.TINTER:
- if t.IsEmptyInterface() {
- b.WriteString("interface {}")
- break
- }
- b.WriteString("interface {")
- for i, f := range t.Fields().Slice() {
- if i != 0 {
- b.WriteByte(';')
- }
- b.WriteByte(' ')
- switch {
- case f.Sym == nil:
- // Check first that a symbol is defined for this type.
- // Wrong interface definitions may have types lacking a symbol.
- break
- case types.IsExported(f.Sym.Name):
- sconv2(b, f.Sym, FmtShort, mode)
- default:
- flag1 := FmtLeft
- if flag&FmtUnsigned != 0 {
- flag1 = FmtUnsigned
- }
- sconv2(b, f.Sym, flag1, mode)
- }
- tconv2(b, f.Type, FmtShort, mode, visited)
- }
- if t.NumFields() != 0 {
- b.WriteByte(' ')
- }
- b.WriteByte('}')
-
- case types.TFUNC:
- if flag&FmtShort != 0 {
- // no leading func
+ t := n.Type()
+ if verb == 'L' && t != nil {
+ if t.Kind() == types.TNIL {
+ fmt.Fprint(s, "nil")
+ } else if n.Op() == ONAME && n.Name().AutoTemp() {
+ fmt.Fprintf(s, "%v value", t)
} else {
- if t.Recv() != nil {
- b.WriteString("method")
- tconv2(b, t.Recvs(), 0, mode, visited)
- b.WriteByte(' ')
- }
- b.WriteString("func")
+ fmt.Fprintf(s, "%v (type %v)", n, t)
}
- tconv2(b, t.Params(), 0, mode, visited)
-
- switch t.NumResults() {
- case 0:
- // nothing to do
-
- case 1:
- b.WriteByte(' ')
- tconv2(b, t.Results().Field(0).Type, 0, mode, visited) // struct->field->field's type
-
- default:
- b.WriteByte(' ')
- tconv2(b, t.Results(), 0, mode, visited)
- }
-
- case types.TSTRUCT:
- if m := t.StructType().Map; m != nil {
- mt := m.MapType()
- // Format the bucket struct for map[x]y as map.bucket[x]y.
- // This avoids a recursive print that generates very long names.
- switch t {
- case mt.Bucket:
- b.WriteString("map.bucket[")
- case mt.Hmap:
- b.WriteString("map.hdr[")
- case mt.Hiter:
- b.WriteString("map.iter[")
- default:
- base.Fatalf("unknown internal map type")
- }
- tconv2(b, m.Key(), 0, mode, visited)
- b.WriteByte(']')
- tconv2(b, m.Elem(), 0, mode, visited)
- break
- }
-
- if funarg := t.StructType().Funarg; funarg != types.FunargNone {
- b.WriteByte('(')
- var flag1 FmtFlag
- switch mode {
- case FTypeId, FTypeIdName, FErr:
- // no argument names on function signature, and no "noescape"/"nosplit" tags
- flag1 = FmtShort
- }
- for i, f := range t.Fields().Slice() {
- if i != 0 {
- b.WriteString(", ")
- }
- fldconv(b, f, flag1, mode, visited, funarg)
- }
- b.WriteByte(')')
- } else {
- b.WriteString("struct {")
- for i, f := range t.Fields().Slice() {
- if i != 0 {
- b.WriteByte(';')
- }
- b.WriteByte(' ')
- fldconv(b, f, FmtLong, mode, visited, funarg)
- }
- if t.NumFields() != 0 {
- b.WriteByte(' ')
- }
- b.WriteByte('}')
- }
-
- case types.TFORW:
- b.WriteString("undefined")
- if t.Sym != nil {
- b.WriteByte(' ')
- sconv2(b, t.Sym, 0, mode)
- }
-
- case types.TUNSAFEPTR:
- b.WriteString("unsafe.Pointer")
-
- case types.Txxx:
- b.WriteString("Txxx")
- default:
- // Don't know how to handle - fall back to detailed prints.
- b.WriteString(mode.Sprintf("%v <%v>", t.Etype, t.Sym))
- }
-}
-
-// Statements which may be rendered with a simplestmt as init.
-func StmtWithInit(op Op) bool {
- switch op {
- case OIF, OFOR, OFORUNTIL, OSWITCH:
- return true
+ return
}
- return false
-}
+ // TODO inlining produces expressions with ninits. we can't print these yet.
-func stmtFmt(n Node, s fmt.State, mode FmtMode) {
- // some statements allow for an init, but at most one,
- // but we may have an arbitrary number added, eg by typecheck
- // and inlining. If it doesn't fit the syntax, emit an enclosing
- // block starting with the init statements.
-
- // if we can just say "for" n->ninit; ... then do so
- simpleinit := n.Init().Len() == 1 && n.Init().First().Init().Len() == 0 && StmtWithInit(n.Op())
-
- // otherwise, print the inits as separate statements
- complexinit := n.Init().Len() != 0 && !simpleinit && (mode != FErr)
-
- // but if it was for if/for/switch, put in an extra surrounding block to limit the scope
- extrablock := complexinit && StmtWithInit(n.Op())
-
- if extrablock {
- fmt.Fprint(s, "{")
+ if OpPrec[n.Op()] < 0 {
+ stmtFmt(n, s)
+ return
}
- if complexinit {
- mode.Fprintf(s, " %v; ", n.Init())
- }
-
- switch n.Op() {
- case ODCL:
- mode.Fprintf(s, "var %v %v", n.Left().Sym(), n.Left().Type())
-
- case ODCLFIELD:
- if n.Sym() != nil {
- mode.Fprintf(s, "%v %v", n.Sym(), n.Left())
- } else {
- mode.Fprintf(s, "%v", n.Left())
- }
-
- // Don't export "v = " initializing statements, hope they're always
- // preceded by the DCL which will be re-parsed and typechecked to reproduce
- // the "v = " again.
- case OAS:
- if n.Colas() && !complexinit {
- mode.Fprintf(s, "%v := %v", n.Left(), n.Right())
- } else {
- mode.Fprintf(s, "%v = %v", n.Left(), n.Right())
- }
-
- case OASOP:
- if n.Implicit() {
- if n.SubOp() == OADD {
- mode.Fprintf(s, "%v++", n.Left())
- } else {
- mode.Fprintf(s, "%v--", n.Left())
- }
- break
- }
-
- mode.Fprintf(s, "%v %#v= %v", n.Left(), n.SubOp(), n.Right())
-
- case OAS2:
- if n.Colas() && !complexinit {
- mode.Fprintf(s, "%.v := %.v", n.List(), n.Rlist())
- break
- }
- fallthrough
-
- case OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV:
- mode.Fprintf(s, "%.v = %v", n.List(), n.Right())
-
- case ORETURN:
- mode.Fprintf(s, "return %.v", n.List())
-
- case ORETJMP:
- mode.Fprintf(s, "retjmp %v", n.Sym())
-
- case OINLMARK:
- mode.Fprintf(s, "inlmark %d", n.Offset())
-
- case OGO:
- mode.Fprintf(s, "go %v", n.Left())
-
- case ODEFER:
- mode.Fprintf(s, "defer %v", n.Left())
-
- case OIF:
- if simpleinit {
- mode.Fprintf(s, "if %v; %v { %v }", n.Init().First(), n.Left(), n.Body())
- } else {
- mode.Fprintf(s, "if %v { %v }", n.Left(), n.Body())
- }
- if n.Rlist().Len() != 0 {
- mode.Fprintf(s, " else { %v }", n.Rlist())
- }
-
- case OFOR, OFORUNTIL:
- opname := "for"
- if n.Op() == OFORUNTIL {
- opname = "foruntil"
- }
- if mode == FErr { // TODO maybe only if FmtShort, same below
- fmt.Fprintf(s, "%s loop", opname)
- break
- }
-
- fmt.Fprint(s, opname)
- if simpleinit {
- mode.Fprintf(s, " %v;", n.Init().First())
- } else if n.Right() != nil {
- fmt.Fprint(s, " ;")
- }
-
- if n.Left() != nil {
- mode.Fprintf(s, " %v", n.Left())
- }
-
- if n.Right() != nil {
- mode.Fprintf(s, "; %v", n.Right())
- } else if simpleinit {
- fmt.Fprint(s, ";")
- }
-
- if n.Op() == OFORUNTIL && n.List().Len() != 0 {
- mode.Fprintf(s, "; %v", n.List())
- }
-
- mode.Fprintf(s, " { %v }", n.Body())
-
- case ORANGE:
- if mode == FErr {
- fmt.Fprint(s, "for loop")
- break
- }
-
- if n.List().Len() == 0 {
- mode.Fprintf(s, "for range %v { %v }", n.Right(), n.Body())
- break
- }
-
- mode.Fprintf(s, "for %.v = range %v { %v }", n.List(), n.Right(), n.Body())
-
- case OSELECT, OSWITCH:
- if mode == FErr {
- mode.Fprintf(s, "%v statement", n.Op())
- break
- }
-
- mode.Fprintf(s, "%#v", n.Op())
- if simpleinit {
- mode.Fprintf(s, " %v;", n.Init().First())
- }
- if n.Left() != nil {
- mode.Fprintf(s, " %v ", n.Left())
- }
-
- mode.Fprintf(s, " { %v }", n.List())
-
- case OCASE:
- if n.List().Len() != 0 {
- mode.Fprintf(s, "case %.v", n.List())
- } else {
- fmt.Fprint(s, "default")
- }
- mode.Fprintf(s, ": %v", n.Body())
-
- case OBREAK, OCONTINUE, OGOTO, OFALL:
- if n.Sym() != nil {
- mode.Fprintf(s, "%#v %v", n.Op(), n.Sym())
- } else {
- mode.Fprintf(s, "%#v", n.Op())
- }
-
- case OEMPTY:
- break
-
- case OLABEL:
- mode.Fprintf(s, "%v: ", n.Sym())
- }
-
- if extrablock {
- fmt.Fprint(s, "}")
- }
+ exprFmt(n, s, 0)
}
var OpPrec = []int{
@@ -1087,6 +180,7 @@ var OpPrec = []int{
OCALL: 8,
OCAP: 8,
OCLOSE: 8,
+ OCOMPLIT: 8,
OCONVIFACE: 8,
OCONVNOP: 8,
OCONV: 8,
@@ -1115,6 +209,7 @@ var OpPrec = []int{
OSTR2RUNES: 8,
OSTRUCTLIT: 8,
OTARRAY: 8,
+ OTSLICE: 8,
OTCHAN: 8,
OTFUNC: 8,
OTINTER: 8,
@@ -1172,13 +267,12 @@ var OpPrec = []int{
OAS2MAPR: -1,
OAS2RECV: -1,
OASOP: -1,
+ OBLOCK: -1,
OBREAK: -1,
OCASE: -1,
OCONTINUE: -1,
ODCL: -1,
- ODCLFIELD: -1,
ODEFER: -1,
- OEMPTY: -1,
OFALL: -1,
OFOR: -1,
OFORUNTIL: -1,
@@ -1194,14 +288,226 @@ var OpPrec = []int{
OEND: 0,
}
-func exprFmt(n Node, s fmt.State, prec int, mode FmtMode) {
- for n != nil && n.Implicit() && (n.Op() == ODEREF || n.Op() == OADDR) {
- n = n.Left()
+// StmtWithInit reports whether op is a statement with an explicit init list.
+func StmtWithInit(op Op) bool {
+ switch op {
+ case OIF, OFOR, OFORUNTIL, OSWITCH:
+ return true
+ }
+ return false
+}
+
+func stmtFmt(n Node, s fmt.State) {
+ // NOTE(rsc): This code used to support the text-based
+ // which was more aggressive about printing full Go syntax
+ // (for example, an actual loop instead of "for loop").
+ // The code is preserved for now in case we want to expand
+ // any of those shortenings later. Or maybe we will delete
+ // the code. But for now, keep it.
+ const exportFormat = false
+
+ // some statements allow for an init, but at most one,
+ // but we may have an arbitrary number added, eg by typecheck
+ // and inlining. If it doesn't fit the syntax, emit an enclosing
+ // block starting with the init statements.
+
+ // if we can just say "for" n->ninit; ... then do so
+ simpleinit := n.Init().Len() == 1 && n.Init().First().Init().Len() == 0 && StmtWithInit(n.Op())
+
+ // otherwise, print the inits as separate statements
+ complexinit := n.Init().Len() != 0 && !simpleinit && exportFormat
+
+ // but if it was for if/for/switch, put in an extra surrounding block to limit the scope
+ extrablock := complexinit && StmtWithInit(n.Op())
+
+ if extrablock {
+ fmt.Fprint(s, "{")
}
- if n == nil {
- fmt.Fprint(s, "")
- return
+ if complexinit {
+ fmt.Fprintf(s, " %v; ", n.Init())
+ }
+
+ switch n.Op() {
+ case ODCL:
+ fmt.Fprintf(s, "var %v %v", n.Left().Sym(), n.Left().Type())
+
+ // Don't export "v = " initializing statements, hope they're always
+ // preceded by the DCL which will be re-parsed and typechecked to reproduce
+ // the "v = " again.
+ case OAS:
+ if n.Colas() && !complexinit {
+ fmt.Fprintf(s, "%v := %v", n.Left(), n.Right())
+ } else {
+ fmt.Fprintf(s, "%v = %v", n.Left(), n.Right())
+ }
+
+ case OASOP:
+ if n.Implicit() {
+ if n.SubOp() == OADD {
+ fmt.Fprintf(s, "%v++", n.Left())
+ } else {
+ fmt.Fprintf(s, "%v--", n.Left())
+ }
+ break
+ }
+
+ fmt.Fprintf(s, "%v %v= %v", n.Left(), n.SubOp(), n.Right())
+
+ case OAS2, OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV:
+ if n.Colas() && !complexinit {
+ fmt.Fprintf(s, "%.v := %.v", n.List(), n.Rlist())
+ } else {
+ fmt.Fprintf(s, "%.v = %.v", n.List(), n.Rlist())
+ }
+
+ case OBLOCK:
+ if n.List().Len() != 0 {
+ fmt.Fprintf(s, "%v", n.List())
+ }
+
+ case ORETURN:
+ fmt.Fprintf(s, "return %.v", n.List())
+
+ case ORETJMP:
+ fmt.Fprintf(s, "retjmp %v", n.Sym())
+
+ case OINLMARK:
+ fmt.Fprintf(s, "inlmark %d", n.Offset())
+
+ case OGO:
+ fmt.Fprintf(s, "go %v", n.Left())
+
+ case ODEFER:
+ fmt.Fprintf(s, "defer %v", n.Left())
+
+ case OIF:
+ if simpleinit {
+ fmt.Fprintf(s, "if %v; %v { %v }", n.Init().First(), n.Left(), n.Body())
+ } else {
+ fmt.Fprintf(s, "if %v { %v }", n.Left(), n.Body())
+ }
+ if n.Rlist().Len() != 0 {
+ fmt.Fprintf(s, " else { %v }", n.Rlist())
+ }
+
+ case OFOR, OFORUNTIL:
+ opname := "for"
+ if n.Op() == OFORUNTIL {
+ opname = "foruntil"
+ }
+ if !exportFormat { // TODO maybe only if FmtShort, same below
+ fmt.Fprintf(s, "%s loop", opname)
+ break
+ }
+
+ fmt.Fprint(s, opname)
+ if simpleinit {
+ fmt.Fprintf(s, " %v;", n.Init().First())
+ } else if n.Right() != nil {
+ fmt.Fprint(s, " ;")
+ }
+
+ if n.Left() != nil {
+ fmt.Fprintf(s, " %v", n.Left())
+ }
+
+ if n.Right() != nil {
+ fmt.Fprintf(s, "; %v", n.Right())
+ } else if simpleinit {
+ fmt.Fprint(s, ";")
+ }
+
+ if n.Op() == OFORUNTIL && n.List().Len() != 0 {
+ fmt.Fprintf(s, "; %v", n.List())
+ }
+
+ fmt.Fprintf(s, " { %v }", n.Body())
+
+ case ORANGE:
+ if !exportFormat {
+ fmt.Fprint(s, "for loop")
+ break
+ }
+
+ if n.List().Len() == 0 {
+ fmt.Fprintf(s, "for range %v { %v }", n.Right(), n.Body())
+ break
+ }
+
+ fmt.Fprintf(s, "for %.v = range %v { %v }", n.List(), n.Right(), n.Body())
+
+ case OSELECT, OSWITCH:
+ if !exportFormat {
+ fmt.Fprintf(s, "%v statement", n.Op())
+ break
+ }
+
+ fmt.Fprintf(s, "%v", n.Op())
+ if simpleinit {
+ fmt.Fprintf(s, " %v;", n.Init().First())
+ }
+ if n.Left() != nil {
+ fmt.Fprintf(s, " %v ", n.Left())
+ }
+
+ fmt.Fprintf(s, " { %v }", n.List())
+
+ case OCASE:
+ if n.List().Len() != 0 {
+ fmt.Fprintf(s, "case %.v", n.List())
+ } else {
+ fmt.Fprint(s, "default")
+ }
+ fmt.Fprintf(s, ": %v", n.Body())
+
+ case OBREAK, OCONTINUE, OGOTO, OFALL:
+ if n.Sym() != nil {
+ fmt.Fprintf(s, "%v %v", n.Op(), n.Sym())
+ } else {
+ fmt.Fprintf(s, "%v", n.Op())
+ }
+
+ case OLABEL:
+ fmt.Fprintf(s, "%v: ", n.Sym())
+ }
+
+ if extrablock {
+ fmt.Fprint(s, "}")
+ }
+}
+
+func exprFmt(n Node, s fmt.State, prec int) {
+ // NOTE(rsc): This code used to support the text-based
+ // which was more aggressive about printing full Go syntax
+ // (for example, an actual loop instead of "for loop").
+ // The code is preserved for now in case we want to expand
+ // any of those shortenings later. Or maybe we will delete
+ // the code. But for now, keep it.
+ const exportFormat = false
+
+ for {
+ if n == nil {
+ fmt.Fprint(s, "")
+ return
+ }
+
+ // We always want the original, if any.
+ if o := Orig(n); o != n {
+ n = o
+ continue
+ }
+
+ // Skip implicit operations introduced during typechecking.
+ switch n.Op() {
+ case OADDR, ODEREF, OCONV, OCONVNOP, OCONVIFACE:
+ if n.Implicit() {
+ n = n.Left()
+ continue
+ }
+ }
+
+ break
}
nprec := OpPrec[n.Op()]
@@ -1210,27 +516,21 @@ func exprFmt(n Node, s fmt.State, prec int, mode FmtMode) {
}
if prec > nprec {
- mode.Fprintf(s, "(%v)", n)
+ fmt.Fprintf(s, "(%v)", n)
return
}
switch n.Op() {
case OPAREN:
- mode.Fprintf(s, "(%v)", n.Left())
+ fmt.Fprintf(s, "(%v)", n.Left())
case ONIL:
fmt.Fprint(s, "nil")
case OLITERAL: // this is a bit of a mess
- if mode == FErr {
- if n.Orig() != nil && n.Orig() != n {
- exprFmt(n.Orig(), s, prec, mode)
- return
- }
- if n.Sym() != nil {
- fmt.Fprint(s, smodeString(n.Sym(), mode))
- return
- }
+ if !exportFormat && n.Sym() != nil {
+ fmt.Fprint(s, n.Sym())
+ return
}
needUnparen := false
@@ -1238,9 +538,9 @@ func exprFmt(n Node, s fmt.State, prec int, mode FmtMode) {
// Need parens when type begins with what might
// be misinterpreted as a unary operator: * or <-.
if n.Type().IsPtr() || (n.Type().IsChan() && n.Type().ChanDir() == types.Crecv) {
- mode.Fprintf(s, "(%v)(", n.Type())
+ fmt.Fprintf(s, "(%v)(", n.Type())
} else {
- mode.Fprintf(s, "%v(", n.Type())
+ fmt.Fprintf(s, "%v(", n.Type())
}
needUnparen = true
}
@@ -1262,54 +562,72 @@ func exprFmt(n Node, s fmt.State, prec int, mode FmtMode) {
fmt.Fprintf(s, "'\\U%08x'", uint64(x))
}
} else {
- fmt.Fprint(s, FmtConst(n.Val(), fmtFlag(s, 'v')))
+ fmt.Fprint(s, types.FmtConst(n.Val(), s.Flag('#')))
}
if needUnparen {
- mode.Fprintf(s, ")")
+ fmt.Fprintf(s, ")")
}
+ case ODCLFUNC:
+ if sym := n.Sym(); sym != nil {
+ fmt.Fprint(s, sym)
+ return
+ }
+ fmt.Fprintf(s, "")
+
case ONAME:
// Special case: name used as local variable in export.
// _ becomes ~b%d internally; print as _ for export
- if mode == FErr && n.Sym() != nil && n.Sym().Name[0] == '~' && n.Sym().Name[1] == 'b' {
+ if !exportFormat && n.Sym() != nil && n.Sym().Name[0] == '~' && n.Sym().Name[1] == 'b' {
fmt.Fprint(s, "_")
return
}
fallthrough
case OPACK, ONONAME, OMETHEXPR:
- fmt.Fprint(s, smodeString(n.Sym(), mode))
+ fmt.Fprint(s, n.Sym())
case OTYPE:
if n.Type() == nil && n.Sym() != nil {
- fmt.Fprint(s, smodeString(n.Sym(), mode))
+ fmt.Fprint(s, n.Sym())
return
}
- mode.Fprintf(s, "%v", n.Type())
+ fmt.Fprintf(s, "%v", n.Type())
+
+ case OTSLICE:
+ n := n.(*SliceType)
+ if n.DDD {
+ fmt.Fprintf(s, "...%v", n.Elem)
+ } else {
+ fmt.Fprintf(s, "[]%v", n.Elem) // happens before typecheck
+ }
case OTARRAY:
- if n.Left() != nil {
- mode.Fprintf(s, "[%v]%v", n.Left(), n.Right())
- return
+ n := n.(*ArrayType)
+ if n.Len == nil {
+ fmt.Fprintf(s, "[...]%v", n.Elem)
+ } else {
+ fmt.Fprintf(s, "[%v]%v", n.Len, n.Elem)
}
- mode.Fprintf(s, "[]%v", n.Right()) // happens before typecheck
case OTMAP:
- mode.Fprintf(s, "map[%v]%v", n.Left(), n.Right())
+ n := n.(*MapType)
+ fmt.Fprintf(s, "map[%v]%v", n.Key, n.Elem)
case OTCHAN:
- switch n.TChanDir() {
+ n := n.(*ChanType)
+ switch n.Dir {
case types.Crecv:
- mode.Fprintf(s, "<-chan %v", n.Left())
+ fmt.Fprintf(s, "<-chan %v", n.Elem)
case types.Csend:
- mode.Fprintf(s, "chan<- %v", n.Left())
+ fmt.Fprintf(s, "chan<- %v", n.Elem)
default:
- if n.Left() != nil && n.Left().Op() == OTCHAN && n.Left().Sym() == nil && n.Left().TChanDir() == types.Crecv {
- mode.Fprintf(s, "chan (%v)", n.Left())
+ if n.Elem != nil && n.Elem.Op() == OTCHAN && n.Elem.(*ChanType).Dir == types.Crecv {
+ fmt.Fprintf(s, "chan (%v)", n.Elem)
} else {
- mode.Fprintf(s, "chan %v", n.Left())
+ fmt.Fprintf(s, "chan %v", n.Elem)
}
}
@@ -1323,104 +641,104 @@ func exprFmt(n Node, s fmt.State, prec int, mode FmtMode) {
fmt.Fprint(s, "")
case OCLOSURE:
- if mode == FErr {
+ if !exportFormat {
fmt.Fprint(s, "func literal")
return
}
if n.Body().Len() != 0 {
- mode.Fprintf(s, "%v { %v }", n.Type(), n.Body())
+ fmt.Fprintf(s, "%v { %v }", n.Type(), n.Body())
return
}
- mode.Fprintf(s, "%v { %v }", n.Type(), n.Func().Decl.Body())
+ fmt.Fprintf(s, "%v { %v }", n.Type(), n.Func().Body())
case OCOMPLIT:
- if mode == FErr {
+ if !exportFormat {
if n.Implicit() {
- mode.Fprintf(s, "... argument")
+ fmt.Fprintf(s, "... argument")
return
}
if n.Right() != nil {
- mode.Fprintf(s, "%v{%s}", n.Right(), ellipsisIf(n.List().Len() != 0))
+ fmt.Fprintf(s, "%v{%s}", n.Right(), ellipsisIf(n.List().Len() != 0))
return
}
fmt.Fprint(s, "composite literal")
return
}
- mode.Fprintf(s, "(%v{ %.v })", n.Right(), n.List())
+ fmt.Fprintf(s, "(%v{ %.v })", n.Right(), n.List())
case OPTRLIT:
- mode.Fprintf(s, "&%v", n.Left())
+ fmt.Fprintf(s, "&%v", n.Left())
case OSTRUCTLIT, OARRAYLIT, OSLICELIT, OMAPLIT:
- if mode == FErr {
- mode.Fprintf(s, "%v{%s}", n.Type(), ellipsisIf(n.List().Len() != 0))
+ if !exportFormat {
+ fmt.Fprintf(s, "%v{%s}", n.Type(), ellipsisIf(n.List().Len() != 0))
return
}
- mode.Fprintf(s, "(%v{ %.v })", n.Type(), n.List())
+ fmt.Fprintf(s, "(%v{ %.v })", n.Type(), n.List())
case OKEY:
if n.Left() != nil && n.Right() != nil {
- mode.Fprintf(s, "%v:%v", n.Left(), n.Right())
+ fmt.Fprintf(s, "%v:%v", n.Left(), n.Right())
return
}
if n.Left() == nil && n.Right() != nil {
- mode.Fprintf(s, ":%v", n.Right())
+ fmt.Fprintf(s, ":%v", n.Right())
return
}
if n.Left() != nil && n.Right() == nil {
- mode.Fprintf(s, "%v:", n.Left())
+ fmt.Fprintf(s, "%v:", n.Left())
return
}
fmt.Fprint(s, ":")
case OSTRUCTKEY:
- mode.Fprintf(s, "%v:%v", n.Sym(), n.Left())
+ fmt.Fprintf(s, "%v:%v", n.Sym(), n.Left())
case OCALLPART:
- exprFmt(n.Left(), s, nprec, mode)
- if n.Right() == nil || n.Right().Sym() == nil {
- fmt.Fprint(s, ".")
- return
- }
- mode.Fprintf(s, ".%0S", n.Right().Sym())
-
- case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH:
- exprFmt(n.Left(), s, nprec, mode)
+ exprFmt(n.Left(), s, nprec)
if n.Sym() == nil {
fmt.Fprint(s, ".")
return
}
- mode.Fprintf(s, ".%0S", n.Sym())
+ fmt.Fprintf(s, ".%s", types.SymMethodName(n.Sym()))
- case ODOTTYPE, ODOTTYPE2:
- exprFmt(n.Left(), s, nprec, mode)
- if n.Right() != nil {
- mode.Fprintf(s, ".(%v)", n.Right())
+ case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH:
+ exprFmt(n.Left(), s, nprec)
+ if n.Sym() == nil {
+ fmt.Fprint(s, ".")
return
}
- mode.Fprintf(s, ".(%v)", n.Type())
+ fmt.Fprintf(s, ".%s", types.SymMethodName(n.Sym()))
+
+ case ODOTTYPE, ODOTTYPE2:
+ exprFmt(n.Left(), s, nprec)
+ if n.Right() != nil {
+ fmt.Fprintf(s, ".(%v)", n.Right())
+ return
+ }
+ fmt.Fprintf(s, ".(%v)", n.Type())
case OINDEX, OINDEXMAP:
- exprFmt(n.Left(), s, nprec, mode)
- mode.Fprintf(s, "[%v]", n.Right())
+ exprFmt(n.Left(), s, nprec)
+ fmt.Fprintf(s, "[%v]", n.Right())
case OSLICE, OSLICESTR, OSLICEARR, OSLICE3, OSLICE3ARR:
- exprFmt(n.Left(), s, nprec, mode)
+ exprFmt(n.Left(), s, nprec)
fmt.Fprint(s, "[")
low, high, max := n.SliceBounds()
if low != nil {
- fmt.Fprint(s, modeString(low, mode))
+ fmt.Fprint(s, low)
}
fmt.Fprint(s, ":")
if high != nil {
- fmt.Fprint(s, modeString(high, mode))
+ fmt.Fprint(s, high)
}
if n.Op().IsSlice3() {
fmt.Fprint(s, ":")
if max != nil {
- fmt.Fprint(s, modeString(max, mode))
+ fmt.Fprint(s, max)
}
}
fmt.Fprint(s, "]")
@@ -1429,13 +747,13 @@ func exprFmt(n Node, s fmt.State, prec int, mode FmtMode) {
if n.List().Len() != 2 {
base.Fatalf("bad OSLICEHEADER list length %d", n.List().Len())
}
- mode.Fprintf(s, "sliceheader{%v,%v,%v}", n.Left(), n.List().First(), n.List().Second())
+ fmt.Fprintf(s, "sliceheader{%v,%v,%v}", n.Left(), n.List().First(), n.List().Second())
case OCOMPLEX, OCOPY:
if n.Left() != nil {
- mode.Fprintf(s, "%#v(%v, %v)", n.Op(), n.Left(), n.Right())
+ fmt.Fprintf(s, "%v(%v, %v)", n.Op(), n.Left(), n.Right())
} else {
- mode.Fprintf(s, "%#v(%.v)", n.Op(), n.List())
+ fmt.Fprintf(s, "%v(%.v)", n.Op(), n.List())
}
case OCONV,
@@ -1446,15 +764,15 @@ func exprFmt(n Node, s fmt.State, prec int, mode FmtMode) {
OSTR2BYTES,
OSTR2RUNES,
ORUNESTR:
- if n.Type() == nil || n.Type().Sym == nil {
- mode.Fprintf(s, "(%v)", n.Type())
+ if n.Type() == nil || n.Type().Sym() == nil {
+ fmt.Fprintf(s, "(%v)", n.Type())
} else {
- mode.Fprintf(s, "%v", n.Type())
+ fmt.Fprintf(s, "%v", n.Type())
}
if n.Left() != nil {
- mode.Fprintf(s, "(%v)", n.Left())
+ fmt.Fprintf(s, "(%v)", n.Left())
} else {
- mode.Fprintf(s, "(%.v)", n.List())
+ fmt.Fprintf(s, "(%.v)", n.List())
}
case OREAL,
@@ -1474,48 +792,48 @@ func exprFmt(n Node, s fmt.State, prec int, mode FmtMode) {
OPRINT,
OPRINTN:
if n.Left() != nil {
- mode.Fprintf(s, "%#v(%v)", n.Op(), n.Left())
+ fmt.Fprintf(s, "%v(%v)", n.Op(), n.Left())
return
}
if n.IsDDD() {
- mode.Fprintf(s, "%#v(%.v...)", n.Op(), n.List())
+ fmt.Fprintf(s, "%v(%.v...)", n.Op(), n.List())
return
}
- mode.Fprintf(s, "%#v(%.v)", n.Op(), n.List())
+ fmt.Fprintf(s, "%v(%.v)", n.Op(), n.List())
case OCALL, OCALLFUNC, OCALLINTER, OCALLMETH, OGETG:
- exprFmt(n.Left(), s, nprec, mode)
+ exprFmt(n.Left(), s, nprec)
if n.IsDDD() {
- mode.Fprintf(s, "(%.v...)", n.List())
+ fmt.Fprintf(s, "(%.v...)", n.List())
return
}
- mode.Fprintf(s, "(%.v)", n.List())
+ fmt.Fprintf(s, "(%.v)", n.List())
case OMAKEMAP, OMAKECHAN, OMAKESLICE:
if n.List().Len() != 0 { // pre-typecheck
- mode.Fprintf(s, "make(%v, %.v)", n.Type(), n.List())
+ fmt.Fprintf(s, "make(%v, %.v)", n.Type(), n.List())
return
}
if n.Right() != nil {
- mode.Fprintf(s, "make(%v, %v, %v)", n.Type(), n.Left(), n.Right())
+ fmt.Fprintf(s, "make(%v, %v, %v)", n.Type(), n.Left(), n.Right())
return
}
if n.Left() != nil && (n.Op() == OMAKESLICE || !n.Left().Type().IsUntyped()) {
- mode.Fprintf(s, "make(%v, %v)", n.Type(), n.Left())
+ fmt.Fprintf(s, "make(%v, %v)", n.Type(), n.Left())
return
}
- mode.Fprintf(s, "make(%v)", n.Type())
+ fmt.Fprintf(s, "make(%v)", n.Type())
case OMAKESLICECOPY:
- mode.Fprintf(s, "makeslicecopy(%v, %v, %v)", n.Type(), n.Left(), n.Right())
+ fmt.Fprintf(s, "makeslicecopy(%v, %v, %v)", n.Type(), n.Left(), n.Right())
case OPLUS, ONEG, OADDR, OBITNOT, ODEREF, ONOT, ORECV:
// Unary
- mode.Fprintf(s, "%#v", n.Op())
+ fmt.Fprintf(s, "%v", n.Op())
if n.Left() != nil && n.Left().Op() == n.Op() {
fmt.Fprint(s, " ")
}
- exprFmt(n.Left(), s, nprec+1, mode)
+ exprFmt(n.Left(), s, nprec+1)
// Binary
case OADD,
@@ -1538,346 +856,19 @@ func exprFmt(n Node, s fmt.State, prec int, mode FmtMode) {
OSEND,
OSUB,
OXOR:
- exprFmt(n.Left(), s, nprec, mode)
- mode.Fprintf(s, " %#v ", n.Op())
- exprFmt(n.Right(), s, nprec+1, mode)
+ exprFmt(n.Left(), s, nprec)
+ fmt.Fprintf(s, " %v ", n.Op())
+ exprFmt(n.Right(), s, nprec+1)
case OADDSTR:
for i, n1 := range n.List().Slice() {
if i != 0 {
fmt.Fprint(s, " + ")
}
- exprFmt(n1, s, nprec, mode)
+ exprFmt(n1, s, nprec)
}
- case ODDD:
- mode.Fprintf(s, "...")
default:
- mode.Fprintf(s, "", n.Op())
- }
-}
-
-func nodeFmt(n Node, s fmt.State, flag FmtFlag, mode FmtMode) {
- t := n.Type()
-
- // We almost always want the original.
- // TODO(gri) Why the special case for OLITERAL?
- if n.Op() != OLITERAL && n.Orig() != nil {
- n = n.Orig()
- }
-
- if flag&FmtLong != 0 && t != nil {
- if t.Etype == types.TNIL {
- fmt.Fprint(s, "nil")
- } else if n.Op() == ONAME && n.Name().AutoTemp() {
- mode.Fprintf(s, "%v value", t)
- } else {
- mode.Fprintf(s, "%v (type %v)", n, t)
- }
- return
- }
-
- // TODO inlining produces expressions with ninits. we can't print these yet.
-
- if OpPrec[n.Op()] < 0 {
- stmtFmt(n, s, mode)
- return
- }
-
- exprFmt(n, s, 0, mode)
-}
-
-func nodeDumpFmt(n Node, s fmt.State, flag FmtFlag, mode FmtMode) {
- recur := flag&FmtShort == 0
-
- if recur {
- indent(s)
- if dumpdepth > 40 {
- fmt.Fprint(s, "...")
- return
- }
-
- if n.Init().Len() != 0 {
- mode.Fprintf(s, "%v-init%v", n.Op(), n.Init())
- indent(s)
- }
- }
-
- switch n.Op() {
- default:
- mode.Fprintf(s, "%v%j", n.Op(), n)
-
- case OLITERAL:
- mode.Fprintf(s, "%v-%v%j", n.Op(), n.Val(), n)
-
- case ONAME, ONONAME, OMETHEXPR:
- if n.Sym() != nil {
- mode.Fprintf(s, "%v-%v%j", n.Op(), n.Sym(), n)
- } else {
- mode.Fprintf(s, "%v%j", n.Op(), n)
- }
- if recur && n.Type() == nil && n.Name() != nil && n.Name().Param != nil && n.Name().Param.Ntype != nil {
- indent(s)
- mode.Fprintf(s, "%v-ntype%v", n.Op(), n.Name().Param.Ntype)
- }
-
- case OASOP:
- mode.Fprintf(s, "%v-%v%j", n.Op(), n.SubOp(), n)
-
- case OTYPE:
- mode.Fprintf(s, "%v %v%j type=%v", n.Op(), n.Sym(), n, n.Type())
- if recur && n.Type() == nil && n.Name() != nil && n.Name().Param != nil && n.Name().Param.Ntype != nil {
- indent(s)
- mode.Fprintf(s, "%v-ntype%v", n.Op(), n.Name().Param.Ntype)
- }
- }
-
- if n.Op() == OCLOSURE && n.Func().Decl != nil && n.Func().Nname.Sym() != nil {
- mode.Fprintf(s, " fnName %v", n.Func().Nname.Sym())
- }
- if n.Sym() != nil && n.Op() != ONAME {
- mode.Fprintf(s, " %v", n.Sym())
- }
-
- if n.Type() != nil {
- mode.Fprintf(s, " %v", n.Type())
- }
-
- if recur {
- if n.Left() != nil {
- mode.Fprintf(s, "%v", n.Left())
- }
- if n.Right() != nil {
- mode.Fprintf(s, "%v", n.Right())
- }
- if n.Op() == OCLOSURE && n.Func() != nil && n.Func().Decl != nil && n.Func().Decl.Body().Len() != 0 {
- indent(s)
- // The function associated with a closure
- mode.Fprintf(s, "%v-clofunc%v", n.Op(), n.Func().Decl)
- }
- if n.Op() == ODCLFUNC && n.Func() != nil && n.Func().Dcl != nil && len(n.Func().Dcl) != 0 {
- indent(s)
- // The dcls for a func or closure
- mode.Fprintf(s, "%v-dcl%v", n.Op(), AsNodes(n.Func().Dcl))
- }
- if n.List().Len() != 0 {
- indent(s)
- mode.Fprintf(s, "%v-list%v", n.Op(), n.List())
- }
-
- if n.Rlist().Len() != 0 {
- indent(s)
- mode.Fprintf(s, "%v-rlist%v", n.Op(), n.Rlist())
- }
-
- if n.Body().Len() != 0 {
- indent(s)
- mode.Fprintf(s, "%v-body%v", n.Op(), n.Body())
- }
- }
-}
-
-// "%S" suppresses qualifying with package
-func symFormat(s *types.Sym, f fmt.State, verb rune, mode FmtMode) {
- switch verb {
- case 'v', 'S':
- fmt.Fprint(f, sconv(s, fmtFlag(f, verb), mode))
-
- default:
- fmt.Fprintf(f, "%%!%c(*types.Sym=%p)", verb, s)
- }
-}
-
-func smodeString(s *types.Sym, mode FmtMode) string { return sconv(s, 0, mode) }
-
-// See #16897 before changing the implementation of sconv.
-func sconv(s *types.Sym, flag FmtFlag, mode FmtMode) string {
- if flag&FmtLong != 0 {
- panic("linksymfmt")
- }
-
- if s == nil {
- return ""
- }
-
- if s.Name == "_" {
- return "_"
- }
- buf := fmtBufferPool.Get().(*bytes.Buffer)
- buf.Reset()
- defer fmtBufferPool.Put(buf)
-
- flag, mode = flag.update(mode)
- symfmt(buf, s, flag, mode)
- return types.InternString(buf.Bytes())
-}
-
-func sconv2(b *bytes.Buffer, s *types.Sym, flag FmtFlag, mode FmtMode) {
- if flag&FmtLong != 0 {
- panic("linksymfmt")
- }
- if s == nil {
- b.WriteString("")
- return
- }
- if s.Name == "_" {
- b.WriteString("_")
- return
- }
-
- flag, mode = flag.update(mode)
- symfmt(b, s, flag, mode)
-}
-
-func fldconv(b *bytes.Buffer, f *types.Field, flag FmtFlag, mode FmtMode, visited map[*types.Type]int, funarg types.Funarg) {
- if f == nil {
- b.WriteString("")
- return
- }
- flag, mode = flag.update(mode)
- if mode == FTypeIdName {
- flag |= FmtUnsigned
- }
-
- var name string
- if flag&FmtShort == 0 {
- s := f.Sym
-
- // Take the name from the original.
- if mode == FErr {
- s = OrigSym(s)
- }
-
- if s != nil && f.Embedded == 0 {
- if funarg != types.FunargNone {
- name = modeString(AsNode(f.Nname), mode)
- } else if flag&FmtLong != 0 {
- name = mode.Sprintf("%0S", s)
- if !types.IsExported(name) && flag&FmtUnsigned == 0 {
- name = smodeString(s, mode) // qualify non-exported names (used on structs, not on funarg)
- }
- } else {
- name = smodeString(s, mode)
- }
- }
- }
-
- if name != "" {
- b.WriteString(name)
- b.WriteString(" ")
- }
-
- if f.IsDDD() {
- var et *types.Type
- if f.Type != nil {
- et = f.Type.Elem()
- }
- b.WriteString("...")
- tconv2(b, et, 0, mode, visited)
- } else {
- tconv2(b, f.Type, 0, mode, visited)
- }
-
- if flag&FmtShort == 0 && funarg == types.FunargNone && f.Note != "" {
- b.WriteString(" ")
- b.WriteString(strconv.Quote(f.Note))
- }
-}
-
-// "%L" print definition, not name
-// "%S" omit 'func' and receiver from function types, short type names
-func typeFormat(t *types.Type, s fmt.State, verb rune, mode FmtMode) {
- switch verb {
- case 'v', 'S', 'L':
- fmt.Fprint(s, tconv(t, fmtFlag(s, verb), mode))
- default:
- fmt.Fprintf(s, "%%!%c(*Type=%p)", verb, t)
- }
-}
-
-func (n *node) String() string { return fmt.Sprint(n) }
-func modeString(n Node, mode FmtMode) string { return mode.Sprint(n) }
-
-// "%L" suffix with "(type %T)" where possible
-// "%+S" in debug mode, don't recurse, no multiline output
-func nconvFmt(n Node, s fmt.State, flag FmtFlag, mode FmtMode) {
- if n == nil {
- fmt.Fprint(s, "")
- return
- }
-
- flag, mode = flag.update(mode)
-
- switch mode {
- case FErr:
- nodeFmt(n, s, flag, mode)
-
- case FDbg:
- dumpdepth++
- nodeDumpFmt(n, s, flag, mode)
- dumpdepth--
-
- default:
- base.Fatalf("unhandled %%N mode: %d", mode)
- }
-}
-
-func (l Nodes) format(s fmt.State, verb rune, mode FmtMode) {
- switch verb {
- case 'v':
- l.hconv(s, fmtFlag(s, verb), mode)
-
- default:
- fmt.Fprintf(s, "%%!%c(Nodes)", verb)
- }
-}
-
-func (n Nodes) String() string {
- return fmt.Sprint(n)
-}
-
-// Flags: all those of %N plus '.': separate with comma's instead of semicolons.
-func (l Nodes) hconv(s fmt.State, flag FmtFlag, mode FmtMode) {
- if l.Len() == 0 && mode == FDbg {
- fmt.Fprint(s, "")
- return
- }
-
- flag, mode = flag.update(mode)
- sep := "; "
- if mode == FDbg {
- sep = "\n"
- } else if flag&FmtComma != 0 {
- sep = ", "
- }
-
- for i, n := range l.Slice() {
- fmt.Fprint(s, modeString(n, mode))
- if i+1 < l.Len() {
- fmt.Fprint(s, sep)
- }
- }
-}
-
-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)
-}
-
-// TODO(gri) make variable local somehow
-var dumpdepth int
-
-// indent prints indentation to s.
-func indent(s fmt.State) {
- fmt.Fprint(s, "\n")
- for i := 0; i < dumpdepth; i++ {
- fmt.Fprint(s, ". ")
+ fmt.Fprintf(s, "", n.Op())
}
}
@@ -1888,29 +879,310 @@ func ellipsisIf(b bool) string {
return ""
}
-// numImport tracks how often a package with a given name is imported.
-// It is used to provide a better error message (by using the package
-// path to disambiguate) if a package that appears multiple times with
-// the same name appears in an error message.
-var NumImport = make(map[string]int)
+// Nodes
-func InstallTypeFormats() {
- types.Sconv = func(s *types.Sym, flag, mode int) string {
- return sconv(s, FmtFlag(flag), FmtMode(mode))
+// Format implements formatting for a Nodes.
+// The valid formats are:
+//
+// %v Go syntax, semicolon-separated
+// %.v Go syntax, comma-separated
+// %+v Debug syntax, as in DumpList.
+//
+func (l Nodes) Format(s fmt.State, verb rune) {
+ if s.Flag('+') && verb == 'v' {
+ // %+v is DumpList output
+ dumpNodes(s, l, 1)
+ return
}
- types.Tconv = func(t *types.Type, flag, mode int) string {
- return tconv(t, FmtFlag(flag), FmtMode(mode))
+
+ if verb != 'v' {
+ fmt.Fprintf(s, "%%!%c(Nodes)", verb)
+ return
}
- types.FormatSym = func(sym *types.Sym, s fmt.State, verb rune, mode int) {
- symFormat(sym, s, verb, FmtMode(mode))
+
+ sep := "; "
+ if _, ok := s.Precision(); ok { // %.v is expr list
+ sep = ", "
}
- types.FormatType = func(t *types.Type, s fmt.State, verb rune, mode int) {
- typeFormat(t, s, verb, FmtMode(mode))
+
+ for i, n := range l.Slice() {
+ fmt.Fprint(s, n)
+ if i+1 < l.Len() {
+ fmt.Fprint(s, sep)
+ }
}
}
-// Line returns n's position as a string. If n has been inlined,
-// it uses the outermost position where n has been inlined.
-func Line(n Node) string {
- return base.FmtPos(n.Pos())
+// Dump
+
+// Dump prints the message s followed by a debug dump of n.
+func Dump(s string, n Node) {
+ fmt.Printf("%s [%p]%+v", s, n, n)
+}
+
+// DumpList prints the message s followed by a debug dump of each node in the list.
+func DumpList(s string, list Nodes) {
+ var buf bytes.Buffer
+ FDumpList(&buf, s, list)
+ os.Stdout.Write(buf.Bytes())
+}
+
+// FDumpList prints to w the message s followed by a debug dump of each node in the list.
+func FDumpList(w io.Writer, s string, list Nodes) {
+ io.WriteString(w, s)
+ dumpNodes(w, list, 1)
+ io.WriteString(w, "\n")
+}
+
+// indent prints indentation to w.
+func indent(w io.Writer, depth int) {
+ fmt.Fprint(w, "\n")
+ for i := 0; i < depth; i++ {
+ fmt.Fprint(w, ". ")
+ }
+}
+
+// EscFmt is set by the escape analysis code to add escape analysis details to the node print.
+var EscFmt func(n Node) string
+
+// dumpNodeHeader prints the debug-format node header line to w.
+func dumpNodeHeader(w io.Writer, n Node) {
+ // Useful to see which nodes in an AST printout are actually identical
+ if base.Debug.DumpPtrs != 0 {
+ fmt.Fprintf(w, " p(%p)", n)
+ }
+ if n.Name() != nil && n.Name().Vargen != 0 {
+ fmt.Fprintf(w, " g(%d)", n.Name().Vargen)
+ }
+
+ if base.Debug.DumpPtrs != 0 && n.Name() != nil && n.Name().Defn != nil {
+ // Useful to see where Defn is set and what node it points to
+ fmt.Fprintf(w, " defn(%p)", n.Name().Defn)
+ }
+
+ if n.Offset() != types.BADWIDTH {
+ fmt.Fprintf(w, " x(%d)", n.Offset())
+ }
+
+ if n.Class() != 0 {
+ fmt.Fprintf(w, " class(%v)", n.Class())
+ }
+
+ if n.Colas() {
+ fmt.Fprintf(w, " colas(%v)", n.Colas())
+ }
+
+ if EscFmt != nil {
+ if esc := EscFmt(n); esc != "" {
+ fmt.Fprintf(w, " %s", esc)
+ }
+ }
+
+ if n.Typecheck() != 0 {
+ fmt.Fprintf(w, " tc(%d)", n.Typecheck())
+ }
+
+ if n.IsDDD() {
+ fmt.Fprintf(w, " isddd(%v)", n.IsDDD())
+ }
+
+ if n.Implicit() {
+ fmt.Fprintf(w, " implicit(%v)", n.Implicit())
+ }
+
+ if n.Op() == ONAME {
+ if n.Name().Addrtaken() {
+ fmt.Fprint(w, " addrtaken")
+ }
+ if n.Name().Assigned() {
+ fmt.Fprint(w, " assigned")
+ }
+ if n.Name().IsClosureVar() {
+ fmt.Fprint(w, " closurevar")
+ }
+ if n.Name().Captured() {
+ fmt.Fprint(w, " captured")
+ }
+ if n.Name().IsOutputParamHeapAddr() {
+ fmt.Fprint(w, " outputparamheapaddr")
+ }
+ }
+ if n.Bounded() {
+ fmt.Fprint(w, " bounded")
+ }
+ if n.NonNil() {
+ fmt.Fprint(w, " nonnil")
+ }
+
+ if n.HasCall() {
+ fmt.Fprint(w, " hascall")
+ }
+
+ if n.Name() != nil && n.Name().Used() {
+ fmt.Fprint(w, " used")
+ }
+
+ if n.Op() == OCLOSURE {
+ if fn := n.Func(); fn != nil && fn.Nname.Sym() != nil {
+ fmt.Fprintf(w, " fnName(%+v)", fn.Nname.Sym())
+ }
+ }
+
+ if n.Type() != nil {
+ if n.Op() == OTYPE {
+ fmt.Fprintf(w, " type")
+ }
+ fmt.Fprintf(w, " %+v", n.Type())
+ }
+
+ if n.Pos().IsKnown() {
+ pfx := ""
+ switch n.Pos().IsStmt() {
+ case src.PosNotStmt:
+ pfx = "_" // "-" would be confusing
+ case src.PosIsStmt:
+ pfx = "+"
+ }
+ pos := base.Ctxt.PosTable.Pos(n.Pos())
+ file := filepath.Base(pos.Filename())
+ fmt.Fprintf(w, " # %s%s:%d", pfx, file, pos.Line())
+ }
+}
+
+func dumpNode(w io.Writer, n Node, depth int) {
+ indent(w, depth)
+ if depth > 40 {
+ fmt.Fprint(w, "...")
+ return
+ }
+
+ if n.Init().Len() != 0 {
+ fmt.Fprintf(w, "%+v-init", n.Op())
+ dumpNodes(w, n.Init(), depth+1)
+ indent(w, depth)
+ }
+
+ switch n.Op() {
+ default:
+ fmt.Fprintf(w, "%+v", n.Op())
+ dumpNodeHeader(w, n)
+
+ case OLITERAL:
+ fmt.Fprintf(w, "%+v-%v", n.Op(), n.Val())
+ dumpNodeHeader(w, n)
+ return
+
+ case ONAME, ONONAME, OMETHEXPR:
+ if n.Sym() != nil {
+ fmt.Fprintf(w, "%+v-%+v", n.Op(), n.Sym())
+ } else {
+ fmt.Fprintf(w, "%+v", n.Op())
+ }
+ dumpNodeHeader(w, n)
+ if n.Type() == nil && n.Name() != nil && n.Name().Ntype != nil {
+ indent(w, depth)
+ fmt.Fprintf(w, "%+v-ntype", n.Op())
+ dumpNode(w, n.Name().Ntype, depth+1)
+ }
+ return
+
+ case OASOP:
+ fmt.Fprintf(w, "%+v-%+v", n.Op(), n.SubOp())
+ dumpNodeHeader(w, n)
+
+ case OTYPE:
+ fmt.Fprintf(w, "%+v %+v", n.Op(), n.Sym())
+ dumpNodeHeader(w, n)
+ if n.Type() == nil && n.Name() != nil && n.Name().Ntype != nil {
+ indent(w, depth)
+ fmt.Fprintf(w, "%+v-ntype", n.Op())
+ dumpNode(w, n.Name().Ntype, depth+1)
+ }
+ return
+
+ case OCLOSURE:
+ fmt.Fprintf(w, "%+v", n.Op())
+ dumpNodeHeader(w, n)
+
+ case ODCLFUNC:
+ // Func has many fields we don't want to print.
+ // Bypass reflection and just print what we want.
+ fmt.Fprintf(w, "%+v", n.Op())
+ dumpNodeHeader(w, n)
+ fn := n.Func()
+ if len(fn.Dcl) > 0 {
+ indent(w, depth)
+ fmt.Fprintf(w, "%+v-Dcl", n.Op())
+ for _, dcl := range n.Func().Dcl {
+ dumpNode(w, dcl, depth+1)
+ }
+ }
+ if fn.Body().Len() > 0 {
+ indent(w, depth)
+ fmt.Fprintf(w, "%+v-body", n.Op())
+ dumpNodes(w, n.Body(), depth+1)
+ }
+ return
+ }
+
+ if n.Sym() != nil {
+ fmt.Fprintf(w, " %+v", n.Sym())
+ }
+ if n.Type() != nil {
+ fmt.Fprintf(w, " %+v", n.Type())
+ }
+
+ v := reflect.ValueOf(n).Elem()
+ t := reflect.TypeOf(n).Elem()
+ nf := t.NumField()
+ for i := 0; i < nf; i++ {
+ tf := t.Field(i)
+ vf := v.Field(i)
+ if tf.PkgPath != "" {
+ // skip unexported field - Interface will fail
+ continue
+ }
+ switch tf.Type.Kind() {
+ case reflect.Interface, reflect.Ptr, reflect.Slice:
+ if vf.IsNil() {
+ continue
+ }
+ }
+ name := strings.TrimSuffix(tf.Name, "_")
+ // Do not bother with field name header lines for the
+ // most common positional arguments: unary, binary expr,
+ // index expr, send stmt, go and defer call expression.
+ switch name {
+ case "X", "Y", "Index", "Chan", "Value", "Call":
+ name = ""
+ }
+ switch val := vf.Interface().(type) {
+ case Node:
+ if name != "" {
+ indent(w, depth)
+ fmt.Fprintf(w, "%+v-%s", n.Op(), name)
+ }
+ dumpNode(w, val, depth+1)
+ case Nodes:
+ if val.Len() == 0 {
+ continue
+ }
+ if name != "" {
+ indent(w, depth)
+ fmt.Fprintf(w, "%+v-%s", n.Op(), name)
+ }
+ dumpNodes(w, val, depth+1)
+ }
+ }
+}
+
+func dumpNodes(w io.Writer, list Nodes, depth int) {
+ if list.Len() == 0 {
+ fmt.Fprintf(w, " ")
+ return
+ }
+
+ for _, n := range list.Slice() {
+ dumpNode(w, n, depth)
+ }
}
diff --git a/src/cmd/compile/internal/ir/func.go b/src/cmd/compile/internal/ir/func.go
new file mode 100644
index 0000000000..8aa6daed6f
--- /dev/null
+++ b/src/cmd/compile/internal/ir/func.go
@@ -0,0 +1,249 @@
+// Copyright 2020 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 ir
+
+import (
+ "cmd/compile/internal/base"
+ "cmd/compile/internal/types"
+ "cmd/internal/obj"
+ "cmd/internal/src"
+)
+
+// A Func corresponds to a single function in a Go program
+// (and vice versa: each function is denoted by exactly one *Func).
+//
+// There are multiple nodes that represent a Func in the IR.
+//
+// The ONAME node (Func.Nname) is used for plain references to it.
+// The ODCLFUNC node (the Func itself) is used for its declaration code.
+// The OCLOSURE node (Func.OClosure) is used for a reference to a
+// function literal.
+//
+// An imported function will have an ONAME node which points to a Func
+// with an empty body.
+// A declared function or method has an ODCLFUNC (the Func itself) and an ONAME.
+// A function literal is represented directly by an OCLOSURE, but it also
+// has an ODCLFUNC (and a matching ONAME) representing the compiled
+// underlying form of the closure, which accesses the captured variables
+// using a special data structure passed in a register.
+//
+// A method declaration is represented like functions, except f.Sym
+// will be the qualified method name (e.g., "T.m") and
+// f.Func.Shortname is the bare method name (e.g., "m").
+//
+// A method expression (T.M) is represented as an OMETHEXPR node,
+// in which n.Left and n.Right point to the type and method, respectively.
+// Each distinct mention of a method expression in the source code
+// constructs a fresh node.
+//
+// A method value (t.M) is represented by ODOTMETH/ODOTINTER
+// when it is called directly and by OCALLPART otherwise.
+// These are like method expressions, except that for ODOTMETH/ODOTINTER,
+// the method name is stored in Sym instead of Right.
+// Each OCALLPART ends up being implemented as a new
+// function, a bit like a closure, with its own ODCLFUNC.
+// The OCALLPART uses n.Func to record the linkage to
+// the generated ODCLFUNC, but there is no
+// pointer from the Func back to the OCALLPART.
+type Func struct {
+ miniNode
+ typ *types.Type
+ Body_ Nodes
+ iota int64
+
+ Nname *Name // ONAME node
+ OClosure *ClosureExpr // OCLOSURE node
+
+ Shortname *types.Sym
+
+ // Extra entry code for the function. For example, allocate and initialize
+ // memory for escaping parameters.
+ Enter Nodes
+ Exit Nodes
+ // ONAME nodes for all params/locals for this func/closure, does NOT
+ // include closurevars until transformclosure runs.
+ Dcl []*Name
+
+ ClosureEnter Nodes // list of ONAME nodes (or OADDR-of-ONAME nodes, for output parameters) of captured variables
+ ClosureType Node // closure representation type
+ ClosureVars []*Name // closure params; each has closurevar set
+
+ // Parents records the parent scope of each scope within a
+ // function. The root scope (0) has no parent, so the i'th
+ // scope's parent is stored at Parents[i-1].
+ Parents []ScopeID
+
+ // Marks records scope boundary changes.
+ Marks []Mark
+
+ FieldTrack map[*types.Sym]struct{}
+ DebugInfo interface{}
+ LSym *obj.LSym
+
+ Inl *Inline
+
+ // Closgen tracks how many closures have been generated within
+ // this function. Used by closurename for creating unique
+ // function names.
+ Closgen int32
+
+ Label int32 // largest auto-generated label in this function
+
+ Endlineno src.XPos
+ WBPos src.XPos // position of first write barrier; see SetWBPos
+
+ Pragma PragmaFlag // go:xxx function annotations
+
+ flags bitset16
+ NumDefers int32 // number of defer calls in the function
+ NumReturns int32 // number of explicit returns in the function
+
+ // nwbrCalls records the LSyms of functions called by this
+ // function for go:nowritebarrierrec analysis. Only filled in
+ // if nowritebarrierrecCheck != nil.
+ NWBRCalls *[]SymAndPos
+}
+
+func NewFunc(pos src.XPos) *Func {
+ f := new(Func)
+ f.pos = pos
+ f.op = ODCLFUNC
+ f.iota = -1
+ return f
+}
+
+func (f *Func) isStmt() {}
+
+func (f *Func) Func() *Func { return f }
+func (f *Func) Body() Nodes { return f.Body_ }
+func (f *Func) PtrBody() *Nodes { return &f.Body_ }
+func (f *Func) SetBody(x Nodes) { f.Body_ = x }
+func (f *Func) Type() *types.Type { return f.typ }
+func (f *Func) SetType(x *types.Type) { f.typ = x }
+func (f *Func) Iota() int64 { return f.iota }
+func (f *Func) SetIota(x int64) { f.iota = x }
+
+func (f *Func) Sym() *types.Sym {
+ if f.Nname != nil {
+ return f.Nname.Sym()
+ }
+ return nil
+}
+
+// An Inline holds fields used for function bodies that can be inlined.
+type Inline struct {
+ Cost int32 // heuristic cost of inlining this function
+
+ // Copies of Func.Dcl and Nbody for use during inlining.
+ Dcl []*Name
+ Body []Node
+}
+
+// A Mark represents a scope boundary.
+type Mark struct {
+ // Pos is the position of the token that marks the scope
+ // change.
+ Pos src.XPos
+
+ // Scope identifies the innermost scope to the right of Pos.
+ Scope ScopeID
+}
+
+// A ScopeID represents a lexical scope within a function.
+type ScopeID int32
+
+const (
+ funcDupok = 1 << iota // duplicate definitions ok
+ funcWrapper // is method wrapper
+ funcNeedctxt // function uses context register (has closure variables)
+ funcReflectMethod // function calls reflect.Type.Method or MethodByName
+ // true if closure inside a function; false if a simple function or a
+ // closure in a global variable initialization
+ funcIsHiddenClosure
+ funcHasDefer // contains a defer statement
+ funcNilCheckDisabled // disable nil checks when compiling this function
+ funcInlinabilityChecked // inliner has already determined whether the function is inlinable
+ funcExportInline // include inline body in export data
+ funcInstrumentBody // add race/msan instrumentation during SSA construction
+ funcOpenCodedDeferDisallowed // can't do open-coded defers
+ funcClosureCalled // closure is only immediately called
+)
+
+type SymAndPos struct {
+ Sym *obj.LSym // LSym of callee
+ Pos src.XPos // line of call
+}
+
+func (f *Func) Dupok() bool { return f.flags&funcDupok != 0 }
+func (f *Func) Wrapper() bool { return f.flags&funcWrapper != 0 }
+func (f *Func) Needctxt() bool { return f.flags&funcNeedctxt != 0 }
+func (f *Func) ReflectMethod() bool { return f.flags&funcReflectMethod != 0 }
+func (f *Func) IsHiddenClosure() bool { return f.flags&funcIsHiddenClosure != 0 }
+func (f *Func) HasDefer() bool { return f.flags&funcHasDefer != 0 }
+func (f *Func) NilCheckDisabled() bool { return f.flags&funcNilCheckDisabled != 0 }
+func (f *Func) InlinabilityChecked() bool { return f.flags&funcInlinabilityChecked != 0 }
+func (f *Func) ExportInline() bool { return f.flags&funcExportInline != 0 }
+func (f *Func) InstrumentBody() bool { return f.flags&funcInstrumentBody != 0 }
+func (f *Func) OpenCodedDeferDisallowed() bool { return f.flags&funcOpenCodedDeferDisallowed != 0 }
+func (f *Func) ClosureCalled() bool { return f.flags&funcClosureCalled != 0 }
+
+func (f *Func) SetDupok(b bool) { f.flags.set(funcDupok, b) }
+func (f *Func) SetWrapper(b bool) { f.flags.set(funcWrapper, b) }
+func (f *Func) SetNeedctxt(b bool) { f.flags.set(funcNeedctxt, b) }
+func (f *Func) SetReflectMethod(b bool) { f.flags.set(funcReflectMethod, b) }
+func (f *Func) SetIsHiddenClosure(b bool) { f.flags.set(funcIsHiddenClosure, b) }
+func (f *Func) SetHasDefer(b bool) { f.flags.set(funcHasDefer, b) }
+func (f *Func) SetNilCheckDisabled(b bool) { f.flags.set(funcNilCheckDisabled, b) }
+func (f *Func) SetInlinabilityChecked(b bool) { f.flags.set(funcInlinabilityChecked, b) }
+func (f *Func) SetExportInline(b bool) { f.flags.set(funcExportInline, b) }
+func (f *Func) SetInstrumentBody(b bool) { f.flags.set(funcInstrumentBody, b) }
+func (f *Func) SetOpenCodedDeferDisallowed(b bool) { f.flags.set(funcOpenCodedDeferDisallowed, b) }
+func (f *Func) SetClosureCalled(b bool) { f.flags.set(funcClosureCalled, b) }
+
+func (f *Func) SetWBPos(pos src.XPos) {
+ if base.Debug.WB != 0 {
+ base.WarnfAt(pos, "write barrier")
+ }
+ if !f.WBPos.IsKnown() {
+ f.WBPos = pos
+ }
+}
+
+// funcname returns the name (without the package) of the function n.
+func FuncName(n Node) string {
+ if n == nil || n.Func() == nil || n.Func().Nname == nil {
+ return ""
+ }
+ return n.Func().Nname.Sym().Name
+}
+
+// pkgFuncName returns the name of the function referenced by n, with package prepended.
+// This differs from the compiler's internal convention where local functions lack a package
+// because the ultimate consumer of this is a human looking at an IDE; package is only empty
+// if the compilation package is actually the empty string.
+func PkgFuncName(n Node) string {
+ var s *types.Sym
+ if n == nil {
+ return ""
+ }
+ if n.Op() == ONAME {
+ s = n.Sym()
+ } else {
+ if n.Func() == nil || n.Func().Nname == nil {
+ return ""
+ }
+ s = n.Func().Nname.Sym()
+ }
+ pkg := s.Pkg
+
+ p := base.Ctxt.Pkgpath
+ if pkg != nil && pkg.Path != "" {
+ p = pkg.Path
+ }
+ if p == "" {
+ return s.Name
+ }
+ return p + "." + s.Name
+}
diff --git a/src/cmd/compile/internal/ir/ir.go b/src/cmd/compile/internal/ir/ir.go
index ad7f692b07..82224ca2ed 100644
--- a/src/cmd/compile/internal/ir/ir.go
+++ b/src/cmd/compile/internal/ir/ir.go
@@ -3,10 +3,3 @@
// license that can be found in the LICENSE file.
package ir
-
-import "cmd/compile/internal/types"
-
-var LocalPkg *types.Pkg // package being compiled
-
-// builtinpkg is a fake package that declares the universe block.
-var BuiltinPkg *types.Pkg
diff --git a/src/cmd/compile/internal/ir/mini.go b/src/cmd/compile/internal/ir/mini.go
new file mode 100644
index 0000000000..bf221f75ed
--- /dev/null
+++ b/src/cmd/compile/internal/ir/mini.go
@@ -0,0 +1,198 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:generate go run -mod=mod mknode.go
+
+package ir
+
+import (
+ "cmd/compile/internal/types"
+ "cmd/internal/src"
+ "fmt"
+ "go/constant"
+)
+
+// A miniNode is a minimal node implementation,
+// meant to be embedded as the first field in a larger node implementation,
+// at a cost of 8 bytes.
+//
+// A miniNode is NOT a valid Node by itself: the embedding struct
+// must at the least provide:
+//
+// func (n *MyNode) String() string { return fmt.Sprint(n) }
+// func (n *MyNode) rawCopy() Node { c := *n; return &c }
+// func (n *MyNode) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+//
+// The embedding struct should also fill in n.op in its constructor,
+// for more useful panic messages when invalid methods are called,
+// instead of implementing Op itself.
+//
+type miniNode struct {
+ pos src.XPos // uint32
+ op Op // uint8
+ bits bitset8
+ esc uint16
+}
+
+func (n *miniNode) Format(s fmt.State, verb rune) { panic(1) }
+func (n *miniNode) copy() Node { panic(1) }
+func (n *miniNode) doChildren(do func(Node) error) error { panic(1) }
+func (n *miniNode) editChildren(edit func(Node) Node) { panic(1) }
+
+// posOr returns pos if known, or else n.pos.
+// For use in DeepCopy.
+func (n *miniNode) posOr(pos src.XPos) src.XPos {
+ if pos.IsKnown() {
+ return pos
+ }
+ return n.pos
+}
+
+// op can be read, but not written.
+// An embedding implementation can provide a SetOp if desired.
+// (The panicking SetOp is with the other panics below.)
+func (n *miniNode) Op() Op { return n.op }
+func (n *miniNode) Pos() src.XPos { return n.pos }
+func (n *miniNode) SetPos(x src.XPos) { n.pos = x }
+func (n *miniNode) Esc() uint16 { return n.esc }
+func (n *miniNode) SetEsc(x uint16) { n.esc = x }
+
+const (
+ miniWalkdefShift = 0
+ miniTypecheckShift = 2
+ miniInitorderShift = 4
+ miniDiag = 1 << 6
+ miniHasCall = 1 << 7 // for miniStmt
+)
+
+func (n *miniNode) Walkdef() uint8 { return n.bits.get2(miniWalkdefShift) }
+func (n *miniNode) Typecheck() uint8 { return n.bits.get2(miniTypecheckShift) }
+func (n *miniNode) Initorder() uint8 { return n.bits.get2(miniInitorderShift) }
+func (n *miniNode) SetWalkdef(x uint8) {
+ if x > 3 {
+ panic(fmt.Sprintf("cannot SetWalkdef %d", x))
+ }
+ n.bits.set2(miniWalkdefShift, x)
+}
+func (n *miniNode) SetTypecheck(x uint8) {
+ if x > 3 {
+ panic(fmt.Sprintf("cannot SetTypecheck %d", x))
+ }
+ n.bits.set2(miniTypecheckShift, x)
+}
+func (n *miniNode) SetInitorder(x uint8) {
+ if x > 3 {
+ panic(fmt.Sprintf("cannot SetInitorder %d", x))
+ }
+ n.bits.set2(miniInitorderShift, x)
+}
+
+func (n *miniNode) Diag() bool { return n.bits&miniDiag != 0 }
+func (n *miniNode) SetDiag(x bool) { n.bits.set(miniDiag, x) }
+
+// Empty, immutable graph structure.
+
+func (n *miniNode) Left() Node { return nil }
+func (n *miniNode) Right() Node { return nil }
+func (n *miniNode) Init() Nodes { return Nodes{} }
+func (n *miniNode) PtrInit() *Nodes { return &immutableEmptyNodes }
+func (n *miniNode) Body() Nodes { return Nodes{} }
+func (n *miniNode) PtrBody() *Nodes { return &immutableEmptyNodes }
+func (n *miniNode) List() Nodes { return Nodes{} }
+func (n *miniNode) PtrList() *Nodes { return &immutableEmptyNodes }
+func (n *miniNode) Rlist() Nodes { return Nodes{} }
+func (n *miniNode) PtrRlist() *Nodes { return &immutableEmptyNodes }
+func (n *miniNode) SetLeft(x Node) {
+ if x != nil {
+ panic(n.no("SetLeft"))
+ }
+}
+func (n *miniNode) SetRight(x Node) {
+ if x != nil {
+ panic(n.no("SetRight"))
+ }
+}
+func (n *miniNode) SetInit(x Nodes) {
+ if x != (Nodes{}) {
+ panic(n.no("SetInit"))
+ }
+}
+func (n *miniNode) SetBody(x Nodes) {
+ if x != (Nodes{}) {
+ panic(n.no("SetBody"))
+ }
+}
+func (n *miniNode) SetList(x Nodes) {
+ if x != (Nodes{}) {
+ panic(n.no("SetList"))
+ }
+}
+func (n *miniNode) SetRlist(x Nodes) {
+ if x != (Nodes{}) {
+ panic(n.no("SetRlist"))
+ }
+}
+
+// Additional functionality unavailable.
+
+func (n *miniNode) no(name string) string { return "cannot " + name + " on " + n.op.String() }
+
+func (n *miniNode) SetOp(Op) { panic(n.no("SetOp")) }
+func (n *miniNode) SubOp() Op { panic(n.no("SubOp")) }
+func (n *miniNode) SetSubOp(Op) { panic(n.no("SetSubOp")) }
+func (n *miniNode) Type() *types.Type { return nil }
+func (n *miniNode) SetType(*types.Type) { panic(n.no("SetType")) }
+func (n *miniNode) Func() *Func { return nil }
+func (n *miniNode) Name() *Name { return nil }
+func (n *miniNode) Sym() *types.Sym { return nil }
+func (n *miniNode) SetSym(*types.Sym) { panic(n.no("SetSym")) }
+func (n *miniNode) Offset() int64 { return types.BADWIDTH }
+func (n *miniNode) SetOffset(x int64) { panic(n.no("SetOffset")) }
+func (n *miniNode) Class() Class { return Pxxx }
+func (n *miniNode) SetClass(Class) { panic(n.no("SetClass")) }
+func (n *miniNode) Likely() bool { panic(n.no("Likely")) }
+func (n *miniNode) SetLikely(bool) { panic(n.no("SetLikely")) }
+func (n *miniNode) SliceBounds() (low, high, max Node) {
+ panic(n.no("SliceBounds"))
+}
+func (n *miniNode) SetSliceBounds(low, high, max Node) {
+ panic(n.no("SetSliceBounds"))
+}
+func (n *miniNode) Iota() int64 { panic(n.no("Iota")) }
+func (n *miniNode) SetIota(int64) { panic(n.no("SetIota")) }
+func (n *miniNode) Colas() bool { return false }
+func (n *miniNode) SetColas(bool) { panic(n.no("SetColas")) }
+func (n *miniNode) NoInline() bool { panic(n.no("NoInline")) }
+func (n *miniNode) SetNoInline(bool) { panic(n.no("SetNoInline")) }
+func (n *miniNode) Transient() bool { panic(n.no("Transient")) }
+func (n *miniNode) SetTransient(bool) { panic(n.no("SetTransient")) }
+func (n *miniNode) Implicit() bool { return false }
+func (n *miniNode) SetImplicit(bool) { panic(n.no("SetImplicit")) }
+func (n *miniNode) IsDDD() bool { return false }
+func (n *miniNode) SetIsDDD(bool) { panic(n.no("SetIsDDD")) }
+func (n *miniNode) Embedded() bool { return false }
+func (n *miniNode) SetEmbedded(bool) { panic(n.no("SetEmbedded")) }
+func (n *miniNode) IndexMapLValue() bool { panic(n.no("IndexMapLValue")) }
+func (n *miniNode) SetIndexMapLValue(bool) { panic(n.no("SetIndexMapLValue")) }
+func (n *miniNode) ResetAux() { panic(n.no("ResetAux")) }
+func (n *miniNode) HasBreak() bool { panic(n.no("HasBreak")) }
+func (n *miniNode) SetHasBreak(bool) { panic(n.no("SetHasBreak")) }
+func (n *miniNode) Val() constant.Value { panic(n.no("Val")) }
+func (n *miniNode) SetVal(v constant.Value) { panic(n.no("SetVal")) }
+func (n *miniNode) Int64Val() int64 { panic(n.no("Int64Val")) }
+func (n *miniNode) Uint64Val() uint64 { panic(n.no("Uint64Val")) }
+func (n *miniNode) CanInt64() bool { panic(n.no("CanInt64")) }
+func (n *miniNode) BoolVal() bool { panic(n.no("BoolVal")) }
+func (n *miniNode) StringVal() string { panic(n.no("StringVal")) }
+func (n *miniNode) HasCall() bool { return false }
+func (n *miniNode) SetHasCall(bool) { panic(n.no("SetHasCall")) }
+func (n *miniNode) NonNil() bool { return false }
+func (n *miniNode) MarkNonNil() { panic(n.no("MarkNonNil")) }
+func (n *miniNode) Bounded() bool { return false }
+func (n *miniNode) SetBounded(bool) { panic(n.no("SetBounded")) }
+func (n *miniNode) Opt() interface{} { return nil }
+func (n *miniNode) SetOpt(interface{}) { panic(n.no("SetOpt")) }
+func (n *miniNode) MarkReadonly() { panic(n.no("MarkReadonly")) }
+func (n *miniNode) TChanDir() types.ChanDir { panic(n.no("TChanDir")) }
+func (n *miniNode) SetTChanDir(types.ChanDir) { panic(n.no("SetTChanDir")) }
diff --git a/src/cmd/compile/internal/ir/mknode.go b/src/cmd/compile/internal/ir/mknode.go
new file mode 100644
index 0000000000..f9b398fe28
--- /dev/null
+++ b/src/cmd/compile/internal/ir/mknode.go
@@ -0,0 +1,174 @@
+// Copyright 2020 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 ignore
+
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "go/format"
+ "go/types"
+ "io/ioutil"
+ "log"
+ "strings"
+
+ "golang.org/x/tools/go/packages"
+)
+
+func main() {
+ cfg := &packages.Config{
+ Mode: packages.NeedSyntax | packages.NeedTypes,
+ }
+ pkgs, err := packages.Load(cfg, "cmd/compile/internal/ir")
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ pkg := pkgs[0].Types
+ scope := pkg.Scope()
+
+ lookup := func(name string) *types.Named {
+ return scope.Lookup(name).(*types.TypeName).Type().(*types.Named)
+ }
+
+ nodeType := lookup("Node")
+ ntypeType := lookup("Ntype")
+ nodesType := lookup("Nodes")
+ ptrFieldType := types.NewPointer(lookup("Field"))
+ slicePtrFieldType := types.NewSlice(ptrFieldType)
+ ptrIdentType := types.NewPointer(lookup("Ident"))
+
+ var buf bytes.Buffer
+ fmt.Fprintln(&buf, "// Code generated by mknode.go. DO NOT EDIT.")
+ fmt.Fprintln(&buf)
+ fmt.Fprintln(&buf, "package ir")
+ fmt.Fprintln(&buf)
+ fmt.Fprintln(&buf, `import "fmt"`)
+
+ for _, name := range scope.Names() {
+ obj, ok := scope.Lookup(name).(*types.TypeName)
+ if !ok {
+ continue
+ }
+
+ typName := obj.Name()
+ typ, ok := obj.Type().(*types.Named).Underlying().(*types.Struct)
+ if !ok {
+ continue
+ }
+
+ if strings.HasPrefix(typName, "mini") || !hasMiniNode(typ) {
+ continue
+ }
+
+ fmt.Fprintf(&buf, "\n")
+ fmt.Fprintf(&buf, "func (n *%s) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }\n", name)
+
+ fmt.Fprintf(&buf, "func (n *%s) copy() Node { c := *n\n", name)
+ forNodeFields(typName, typ, func(name string, is func(types.Type) bool) {
+ switch {
+ case is(nodesType):
+ fmt.Fprintf(&buf, "c.%s = c.%s.Copy()\n", name, name)
+ case is(ptrFieldType):
+ fmt.Fprintf(&buf, "if c.%s != nil { c.%s = c.%s.copy() }\n", name, name, name)
+ case is(slicePtrFieldType):
+ fmt.Fprintf(&buf, "c.%s = copyFields(c.%s)\n", name, name)
+ }
+ })
+ fmt.Fprintf(&buf, "return &c }\n")
+
+ fmt.Fprintf(&buf, "func (n *%s) doChildren(do func(Node) error) error { var err error\n", name)
+ forNodeFields(typName, typ, func(name string, is func(types.Type) bool) {
+ switch {
+ case is(ptrIdentType):
+ fmt.Fprintf(&buf, "if n.%s != nil { err = maybeDo(n.%s, err, do) }\n", name, name)
+ case is(nodeType), is(ntypeType):
+ fmt.Fprintf(&buf, "err = maybeDo(n.%s, err, do)\n", name)
+ case is(nodesType):
+ fmt.Fprintf(&buf, "err = maybeDoList(n.%s, err, do)\n", name)
+ case is(ptrFieldType):
+ fmt.Fprintf(&buf, "err = maybeDoField(n.%s, err, do)\n", name)
+ case is(slicePtrFieldType):
+ fmt.Fprintf(&buf, "err = maybeDoFields(n.%s, err, do)\n", name)
+ }
+ })
+ fmt.Fprintf(&buf, "return err }\n")
+
+ fmt.Fprintf(&buf, "func (n *%s) editChildren(edit func(Node) Node) {\n", name)
+ forNodeFields(typName, typ, func(name string, is func(types.Type) bool) {
+ switch {
+ case is(ptrIdentType):
+ fmt.Fprintf(&buf, "if n.%s != nil { n.%s = edit(n.%s).(*Ident) }\n", name, name, name)
+ case is(nodeType):
+ fmt.Fprintf(&buf, "n.%s = maybeEdit(n.%s, edit)\n", name, name)
+ case is(ntypeType):
+ fmt.Fprintf(&buf, "n.%s = toNtype(maybeEdit(n.%s, edit))\n", name, name)
+ case is(nodesType):
+ fmt.Fprintf(&buf, "editList(n.%s, edit)\n", name)
+ case is(ptrFieldType):
+ fmt.Fprintf(&buf, "editField(n.%s, edit)\n", name)
+ case is(slicePtrFieldType):
+ fmt.Fprintf(&buf, "editFields(n.%s, edit)\n", name)
+ }
+ })
+ fmt.Fprintf(&buf, "}\n")
+ }
+
+ out, err := format.Source(buf.Bytes())
+ if err != nil {
+ // write out mangled source so we can see the bug.
+ out = buf.Bytes()
+ }
+
+ err = ioutil.WriteFile("node_gen.go", out, 0666)
+ if err != nil {
+ log.Fatal(err)
+ }
+}
+
+func forNodeFields(typName string, typ *types.Struct, f func(name string, is func(types.Type) bool)) {
+ for i, n := 0, typ.NumFields(); i < n; i++ {
+ v := typ.Field(i)
+ if v.Embedded() {
+ if typ, ok := v.Type().Underlying().(*types.Struct); ok {
+ forNodeFields(typName, typ, f)
+ continue
+ }
+ }
+ switch typName {
+ case "Func":
+ if strings.ToLower(strings.TrimSuffix(v.Name(), "_")) != "body" {
+ continue
+ }
+ case "Name":
+ continue
+ }
+ switch v.Name() {
+ case "orig":
+ continue
+ }
+ switch typName + "." + v.Name() {
+ case "AddStringExpr.Alloc":
+ continue
+ }
+ f(v.Name(), func(t types.Type) bool { return types.Identical(t, v.Type()) })
+ }
+}
+
+func hasMiniNode(typ *types.Struct) bool {
+ for i, n := 0, typ.NumFields(); i < n; i++ {
+ v := typ.Field(i)
+ if v.Name() == "miniNode" {
+ return true
+ }
+ if v.Embedded() {
+ if typ, ok := v.Type().Underlying().(*types.Struct); ok && hasMiniNode(typ) {
+ return true
+ }
+ }
+ }
+ return false
+}
diff --git a/src/cmd/compile/internal/ir/name.go b/src/cmd/compile/internal/ir/name.go
new file mode 100644
index 0000000000..2330838f1c
--- /dev/null
+++ b/src/cmd/compile/internal/ir/name.go
@@ -0,0 +1,398 @@
+// Copyright 2020 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 ir
+
+import (
+ "cmd/compile/internal/base"
+ "cmd/compile/internal/types"
+ "cmd/internal/objabi"
+ "cmd/internal/src"
+
+ "go/constant"
+)
+
+// An Ident is an identifier, possibly qualified.
+type Ident struct {
+ miniExpr
+ sym *types.Sym
+ Used bool
+}
+
+func NewIdent(pos src.XPos, sym *types.Sym) *Ident {
+ n := new(Ident)
+ n.op = ONONAME
+ n.pos = pos
+ n.sym = sym
+ return n
+}
+
+func (n *Ident) Sym() *types.Sym { return n.sym }
+
+func (*Ident) CanBeNtype() {}
+
+// Name holds Node fields used only by named nodes (ONAME, OTYPE, some OLITERAL).
+type Name struct {
+ miniExpr
+ subOp Op // uint8
+ class Class // uint8
+ flags bitset16
+ pragma PragmaFlag // int16
+ sym *types.Sym
+ fn *Func
+ offset int64
+ val constant.Value
+ orig Node
+ embedFiles *[]string // list of embedded files, for ONAME var
+
+ PkgName *PkgName // real package for import . names
+ // For a local variable (not param) or extern, the initializing assignment (OAS or OAS2).
+ // For a closure var, the ONAME node of the outer captured variable
+ Defn Node
+
+ // The function, method, or closure in which local variable or param is declared.
+ Curfn *Func
+
+ // Unique number for ONAME nodes within a function. Function outputs
+ // (results) are numbered starting at one, followed by function inputs
+ // (parameters), and then local variables. Vargen is used to distinguish
+ // local variables/params with the same name.
+ Vargen int32
+ Decldepth int32 // declaration loop depth, increased for every loop or label
+
+ Ntype Ntype
+ Heapaddr *Name // temp holding heap address of param
+
+ // ONAME PAUTOHEAP
+ Stackcopy *Name // the PPARAM/PPARAMOUT on-stack slot (moved func params only)
+
+ // ONAME closure linkage
+ // Consider:
+ //
+ // func f() {
+ // x := 1 // x1
+ // func() {
+ // use(x) // x2
+ // func() {
+ // use(x) // x3
+ // --- parser is here ---
+ // }()
+ // }()
+ // }
+ //
+ // There is an original declaration of x and then a chain of mentions of x
+ // leading into the current function. Each time x is mentioned in a new closure,
+ // we create a variable representing x for use in that specific closure,
+ // since the way you get to x is different in each closure.
+ //
+ // Let's number the specific variables as shown in the code:
+ // x1 is the original x, x2 is when mentioned in the closure,
+ // and x3 is when mentioned in the closure in the closure.
+ //
+ // We keep these linked (assume N > 1):
+ //
+ // - x1.Defn = original declaration statement for x (like most variables)
+ // - x1.Innermost = current innermost closure x (in this case x3), or nil for none
+ // - x1.IsClosureVar() = false
+ //
+ // - xN.Defn = x1, N > 1
+ // - xN.IsClosureVar() = true, N > 1
+ // - x2.Outer = nil
+ // - xN.Outer = x(N-1), N > 2
+ //
+ //
+ // When we look up x in the symbol table, we always get x1.
+ // Then we can use x1.Innermost (if not nil) to get the x
+ // for the innermost known closure function,
+ // but the first reference in a closure will find either no x1.Innermost
+ // or an x1.Innermost with .Funcdepth < Funcdepth.
+ // In that case, a new xN must be created, linked in with:
+ //
+ // xN.Defn = x1
+ // xN.Outer = x1.Innermost
+ // x1.Innermost = xN
+ //
+ // When we finish the function, we'll process its closure variables
+ // and find xN and pop it off the list using:
+ //
+ // x1 := xN.Defn
+ // x1.Innermost = xN.Outer
+ //
+ // We leave x1.Innermost set so that we can still get to the original
+ // variable quickly. Not shown here, but once we're
+ // done parsing a function and no longer need xN.Outer for the
+ // lexical x reference links as described above, funcLit
+ // recomputes xN.Outer as the semantic x reference link tree,
+ // even filling in x in intermediate closures that might not
+ // have mentioned it along the way to inner closures that did.
+ // See funcLit for details.
+ //
+ // During the eventual compilation, then, for closure variables we have:
+ //
+ // xN.Defn = original variable
+ // xN.Outer = variable captured in next outward scope
+ // to make closure where xN appears
+ //
+ // Because of the sharding of pieces of the node, x.Defn means x.Name.Defn
+ // and x.Innermost/Outer means x.Name.Param.Innermost/Outer.
+ Innermost *Name
+ Outer *Name
+}
+
+func (n *Name) isExpr() {}
+
+// NewNameAt returns a new ONAME Node associated with symbol s at position pos.
+// The caller is responsible for setting Curfn.
+func NewNameAt(pos src.XPos, sym *types.Sym) *Name {
+ if sym == nil {
+ base.Fatalf("NewNameAt nil")
+ }
+ return newNameAt(pos, ONAME, sym)
+}
+
+// NewIota returns a new OIOTA Node.
+func NewIota(pos src.XPos, sym *types.Sym) *Name {
+ if sym == nil {
+ base.Fatalf("NewIota nil")
+ }
+ return newNameAt(pos, OIOTA, sym)
+}
+
+// NewDeclNameAt returns a new ONONAME Node associated with symbol s at position pos.
+// The caller is responsible for setting Curfn.
+func NewDeclNameAt(pos src.XPos, sym *types.Sym) *Name {
+ if sym == nil {
+ base.Fatalf("NewDeclNameAt nil")
+ }
+ return newNameAt(pos, ONONAME, sym)
+}
+
+// newNameAt is like NewNameAt but allows sym == nil.
+func newNameAt(pos src.XPos, op Op, sym *types.Sym) *Name {
+ n := new(Name)
+ n.op = op
+ n.pos = pos
+ n.orig = n
+ n.sym = sym
+ return n
+}
+
+func (n *Name) Name() *Name { return n }
+func (n *Name) Sym() *types.Sym { return n.sym }
+func (n *Name) SetSym(x *types.Sym) { n.sym = x }
+func (n *Name) SubOp() Op { return n.subOp }
+func (n *Name) SetSubOp(x Op) { n.subOp = x }
+func (n *Name) Class() Class { return n.class }
+func (n *Name) SetClass(x Class) { n.class = x }
+func (n *Name) Func() *Func { return n.fn }
+func (n *Name) SetFunc(x *Func) { n.fn = x }
+func (n *Name) Offset() int64 { return n.offset }
+func (n *Name) SetOffset(x int64) { n.offset = x }
+func (n *Name) Iota() int64 { return n.offset }
+func (n *Name) SetIota(x int64) { n.offset = x }
+
+func (*Name) CanBeNtype() {}
+func (*Name) CanBeAnSSASym() {}
+func (*Name) CanBeAnSSAAux() {}
+
+func (n *Name) SetOp(op Op) {
+ if n.op != ONONAME {
+ base.Fatalf("%v already has Op %v", n, n.op)
+ }
+ switch op {
+ default:
+ panic(n.no("SetOp " + op.String()))
+ case OLITERAL, ONAME, OTYPE, OIOTA:
+ n.op = op
+ }
+}
+
+// Pragma returns the PragmaFlag for p, which must be for an OTYPE.
+func (n *Name) Pragma() PragmaFlag { return n.pragma }
+
+// SetPragma sets the PragmaFlag for p, which must be for an OTYPE.
+func (n *Name) SetPragma(flag PragmaFlag) { n.pragma = flag }
+
+// Alias reports whether p, which must be for an OTYPE, is a type alias.
+func (n *Name) Alias() bool { return n.flags&nameAlias != 0 }
+
+// SetAlias sets whether p, which must be for an OTYPE, is a type alias.
+func (n *Name) SetAlias(alias bool) { n.flags.set(nameAlias, alias) }
+
+// EmbedFiles returns the list of embedded files for p,
+// which must be for an ONAME var.
+func (n *Name) EmbedFiles() []string {
+ if n.embedFiles == nil {
+ return nil
+ }
+ return *n.embedFiles
+}
+
+// SetEmbedFiles sets the list of embedded files for p,
+// which must be for an ONAME var.
+func (n *Name) SetEmbedFiles(list []string) {
+ if n.embedFiles == nil && list == nil {
+ return
+ }
+ if n.embedFiles == nil {
+ n.embedFiles = new([]string)
+ }
+ *n.embedFiles = list
+}
+
+const (
+ nameCaptured = 1 << iota // is the variable captured by a closure
+ nameReadonly
+ nameByval // is the variable captured by value or by reference
+ nameNeedzero // if it contains pointers, needs to be zeroed on function entry
+ nameAutoTemp // is the variable a temporary (implies no dwarf info. reset if escapes to heap)
+ nameUsed // for variable declared and not used error
+ nameIsClosureVar // PAUTOHEAP closure pseudo-variable; original at n.Name.Defn
+ nameIsOutputParamHeapAddr // pointer to a result parameter's heap copy
+ nameAssigned // is the variable ever assigned to
+ nameAddrtaken // address taken, even if not moved to heap
+ nameInlFormal // PAUTO created by inliner, derived from callee formal
+ nameInlLocal // PAUTO created by inliner, derived from callee local
+ nameOpenDeferSlot // if temporary var storing info for open-coded defers
+ nameLibfuzzerExtraCounter // if PEXTERN should be assigned to __libfuzzer_extra_counters section
+ nameIsDDD // is function argument a ...
+ nameAlias // is type name an alias
+)
+
+func (n *Name) Captured() bool { return n.flags&nameCaptured != 0 }
+func (n *Name) Readonly() bool { return n.flags&nameReadonly != 0 }
+func (n *Name) Byval() bool { return n.flags&nameByval != 0 }
+func (n *Name) Needzero() bool { return n.flags&nameNeedzero != 0 }
+func (n *Name) AutoTemp() bool { return n.flags&nameAutoTemp != 0 }
+func (n *Name) Used() bool { return n.flags&nameUsed != 0 }
+func (n *Name) IsClosureVar() bool { return n.flags&nameIsClosureVar != 0 }
+func (n *Name) IsOutputParamHeapAddr() bool { return n.flags&nameIsOutputParamHeapAddr != 0 }
+func (n *Name) Assigned() bool { return n.flags&nameAssigned != 0 }
+func (n *Name) Addrtaken() bool { return n.flags&nameAddrtaken != 0 }
+func (n *Name) InlFormal() bool { return n.flags&nameInlFormal != 0 }
+func (n *Name) InlLocal() bool { return n.flags&nameInlLocal != 0 }
+func (n *Name) OpenDeferSlot() bool { return n.flags&nameOpenDeferSlot != 0 }
+func (n *Name) LibfuzzerExtraCounter() bool { return n.flags&nameLibfuzzerExtraCounter != 0 }
+func (n *Name) IsDDD() bool { return n.flags&nameIsDDD != 0 }
+
+func (n *Name) SetCaptured(b bool) { n.flags.set(nameCaptured, b) }
+func (n *Name) setReadonly(b bool) { n.flags.set(nameReadonly, b) }
+func (n *Name) SetByval(b bool) { n.flags.set(nameByval, b) }
+func (n *Name) SetNeedzero(b bool) { n.flags.set(nameNeedzero, b) }
+func (n *Name) SetAutoTemp(b bool) { n.flags.set(nameAutoTemp, b) }
+func (n *Name) SetUsed(b bool) { n.flags.set(nameUsed, b) }
+func (n *Name) SetIsClosureVar(b bool) { n.flags.set(nameIsClosureVar, b) }
+func (n *Name) SetIsOutputParamHeapAddr(b bool) { n.flags.set(nameIsOutputParamHeapAddr, b) }
+func (n *Name) SetAssigned(b bool) { n.flags.set(nameAssigned, b) }
+func (n *Name) SetAddrtaken(b bool) { n.flags.set(nameAddrtaken, b) }
+func (n *Name) SetInlFormal(b bool) { n.flags.set(nameInlFormal, b) }
+func (n *Name) SetInlLocal(b bool) { n.flags.set(nameInlLocal, b) }
+func (n *Name) SetOpenDeferSlot(b bool) { n.flags.set(nameOpenDeferSlot, b) }
+func (n *Name) SetLibfuzzerExtraCounter(b bool) { n.flags.set(nameLibfuzzerExtraCounter, b) }
+func (n *Name) SetIsDDD(b bool) { n.flags.set(nameIsDDD, b) }
+
+// MarkReadonly indicates that n is an ONAME with readonly contents.
+func (n *Name) MarkReadonly() {
+ if n.Op() != ONAME {
+ base.Fatalf("Node.MarkReadonly %v", n.Op())
+ }
+ n.Name().setReadonly(true)
+ // Mark the linksym as readonly immediately
+ // so that the SSA backend can use this information.
+ // It will be overridden later during dumpglobls.
+ n.Sym().Linksym().Type = objabi.SRODATA
+}
+
+// Val returns the constant.Value for the node.
+func (n *Name) Val() constant.Value {
+ if n.val == nil {
+ return constant.MakeUnknown()
+ }
+ return n.val
+}
+
+// SetVal sets the constant.Value for the node,
+// which must not have been used with SetOpt.
+func (n *Name) SetVal(v constant.Value) {
+ if n.op != OLITERAL {
+ panic(n.no("SetVal"))
+ }
+ AssertValidTypeForConst(n.Type(), v)
+ n.val = v
+}
+
+// SameSource reports whether two nodes refer to the same source
+// element.
+//
+// It exists to help incrementally migrate the compiler towards
+// allowing the introduction of IdentExpr (#42990). Once we have
+// IdentExpr, it will no longer be safe to directly compare Node
+// values to tell if they refer to the same Name. Instead, code will
+// need to explicitly get references to the underlying Name object(s),
+// and compare those instead.
+//
+// It will still be safe to compare Nodes directly for checking if two
+// nodes are syntactically the same. The SameSource function exists to
+// indicate code that intentionally compares Nodes for syntactic
+// equality as opposed to code that has yet to be updated in
+// preparation for IdentExpr.
+func SameSource(n1, n2 Node) bool {
+ return n1 == n2
+}
+
+// Uses reports whether expression x is a (direct) use of the given
+// variable.
+func Uses(x Node, v *Name) bool {
+ if v == nil || v.Op() != ONAME {
+ base.Fatalf("RefersTo bad Name: %v", v)
+ }
+ return x.Op() == ONAME && x.Name() == v
+}
+
+// DeclaredBy reports whether expression x refers (directly) to a
+// variable that was declared by the given statement.
+func DeclaredBy(x, stmt Node) bool {
+ if stmt == nil {
+ base.Fatalf("DeclaredBy nil")
+ }
+ return x.Op() == ONAME && SameSource(x.Name().Defn, stmt)
+}
+
+// The Class of a variable/function describes the "storage class"
+// of a variable or function. During parsing, storage classes are
+// called declaration contexts.
+type Class uint8
+
+//go:generate stringer -type=Class
+const (
+ Pxxx Class = iota // no class; used during ssa conversion to indicate pseudo-variables
+ PEXTERN // global variables
+ PAUTO // local variables
+ PAUTOHEAP // local variables or parameters moved to heap
+ PPARAM // input arguments
+ PPARAMOUT // output results
+ PFUNC // global functions
+
+ // Careful: Class is stored in three bits in Node.flags.
+ _ = uint((1 << 3) - iota) // static assert for iota <= (1 << 3)
+)
+
+// A Pack is an identifier referring to an imported package.
+type PkgName struct {
+ miniNode
+ sym *types.Sym
+ Pkg *types.Pkg
+ Used bool
+}
+
+func (p *PkgName) Sym() *types.Sym { return p.sym }
+
+func (*PkgName) CanBeNtype() {}
+
+func NewPkgName(pos src.XPos, sym *types.Sym, pkg *types.Pkg) *PkgName {
+ p := &PkgName{sym: sym, Pkg: pkg}
+ p.op = OPACK
+ p.pos = pos
+ return p
+}
diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go
index 477d07f502..dc86b6c683 100644
--- a/src/cmd/compile/internal/ir/node.go
+++ b/src/cmd/compile/internal/ir/node.go
@@ -10,12 +10,9 @@ import (
"fmt"
"go/constant"
"sort"
- "strings"
"cmd/compile/internal/base"
"cmd/compile/internal/types"
- "cmd/internal/obj"
- "cmd/internal/objabi"
"cmd/internal/src"
)
@@ -23,20 +20,20 @@ import (
type Node interface {
// Formatting
Format(s fmt.State, verb rune)
- String() string
// Source position.
Pos() src.XPos
SetPos(x src.XPos)
- // For making copies. Mainly used by Copy and SepCopy.
- RawCopy() Node
+ // For making copies. For Copy and SepCopy.
+ copy() Node
+
+ doChildren(func(Node) error) error
+ editChildren(func(Node) Node)
// Abstract graph structure, for generic traversals.
Op() Op
SetOp(x Op)
- Orig() Node
- SetOrig(x Node)
SubOp() Op
SetSubOp(x Op)
Left() Node
@@ -60,9 +57,7 @@ type Node interface {
Type() *types.Type
SetType(t *types.Type)
Func() *Func
- SetFunc(x *Func)
Name() *Name
- SetName(x *Name)
Sym() *types.Sym
SetSym(x *types.Sym)
Offset() int64
@@ -85,24 +80,14 @@ type Node interface {
SetImplicit(x bool)
IsDDD() bool
SetIsDDD(x bool)
- Embedded() bool
- SetEmbedded(x bool)
IndexMapLValue() bool
SetIndexMapLValue(x bool)
- TChanDir() types.ChanDir
- SetTChanDir(x types.ChanDir)
ResetAux()
HasBreak() bool
SetHasBreak(x bool)
MarkReadonly()
Val() constant.Value
- HasVal() bool
SetVal(v constant.Value)
- Int64Val() int64
- Uint64Val() uint64
- CanInt64() bool
- BoolVal() bool
- StringVal() string
// Storage for analysis passes.
Esc() uint16
@@ -111,7 +96,6 @@ type Node interface {
SetWalkdef(x uint8)
Opt() interface{}
SetOpt(x interface{})
- HasOpt() bool
Diag() bool
SetDiag(x bool)
Bounded() bool
@@ -124,148 +108,12 @@ type Node interface {
MarkNonNil()
HasCall() bool
SetHasCall(x bool)
-
- // Only for SSA and should be removed when SSA starts
- // using a more specific type than Node.
- CanBeAnSSASym()
}
-var _ Node = (*node)(nil)
-
-// A Node is a single node in the syntax tree.
-// Actually the syntax tree is a syntax DAG, because there is only one
-// node with Op=ONAME for a given instance of a variable x.
-// The same is true for Op=OTYPE and Op=OLITERAL. See Node.mayBeShared.
-type node struct {
- // Tree structure.
- // Generic recursive walks should follow these fields.
- left Node
- right Node
- init Nodes
- body Nodes
- list Nodes
- rlist Nodes
-
- // most nodes
- typ *types.Type
- orig Node // original form, for printing, and tracking copies of ONAMEs
-
- // func
- fn *Func
-
- // ONAME, OTYPE, OPACK, OLABEL, some OLITERAL
- name *Name
-
- sym *types.Sym // various
- e interface{} // Opt or Val, see methods below
-
- // Various. Usually an offset into a struct. For example:
- // - ONAME nodes that refer to local variables use it to identify their stack frame position.
- // - ODOT, ODOTPTR, and ORESULT use it to indicate offset relative to their base address.
- // - OSTRUCTKEY uses it to store the named field's offset.
- // - Named OLITERALs use it to store their ambient iota value.
- // - OINLMARK stores an index into the inlTree data structure.
- // - OCLOSURE uses it to store ambient iota value, if any.
- // Possibly still more uses. If you find any, document them.
- offset int64
-
- pos src.XPos
-
- flags bitset32
-
- esc uint16 // EscXXX
-
- op Op
- aux uint8
-}
-
-func (n *node) Left() Node { return n.left }
-func (n *node) SetLeft(x Node) { n.left = x }
-func (n *node) Right() Node { return n.right }
-func (n *node) SetRight(x Node) { n.right = x }
-func (n *node) Orig() Node { return n.orig }
-func (n *node) SetOrig(x Node) { n.orig = x }
-func (n *node) Type() *types.Type { return n.typ }
-func (n *node) SetType(x *types.Type) { n.typ = x }
-func (n *node) Func() *Func { return n.fn }
-func (n *node) SetFunc(x *Func) { n.fn = x }
-func (n *node) Name() *Name { return n.name }
-func (n *node) SetName(x *Name) { n.name = x }
-func (n *node) Sym() *types.Sym { return n.sym }
-func (n *node) SetSym(x *types.Sym) { n.sym = x }
-func (n *node) Pos() src.XPos { return n.pos }
-func (n *node) SetPos(x src.XPos) { n.pos = x }
-func (n *node) Offset() int64 { return n.offset }
-func (n *node) SetOffset(x int64) { n.offset = x }
-func (n *node) Esc() uint16 { return n.esc }
-func (n *node) SetEsc(x uint16) { n.esc = x }
-func (n *node) Op() Op { return n.op }
-func (n *node) SetOp(x Op) { n.op = x }
-func (n *node) Init() Nodes { return n.init }
-func (n *node) SetInit(x Nodes) { n.init = x }
-func (n *node) PtrInit() *Nodes { return &n.init }
-func (n *node) Body() Nodes { return n.body }
-func (n *node) SetBody(x Nodes) { n.body = x }
-func (n *node) PtrBody() *Nodes { return &n.body }
-func (n *node) List() Nodes { return n.list }
-func (n *node) SetList(x Nodes) { n.list = x }
-func (n *node) PtrList() *Nodes { return &n.list }
-func (n *node) Rlist() Nodes { return n.rlist }
-func (n *node) SetRlist(x Nodes) { n.rlist = x }
-func (n *node) PtrRlist() *Nodes { return &n.rlist }
-
-func (n *node) ResetAux() {
- n.aux = 0
-}
-
-func (n *node) SubOp() Op {
- switch n.Op() {
- case OASOP, ONAME:
- default:
- base.Fatalf("unexpected op: %v", n.Op())
- }
- return Op(n.aux)
-}
-
-func (n *node) SetSubOp(op Op) {
- switch n.Op() {
- case OASOP, ONAME:
- default:
- base.Fatalf("unexpected op: %v", n.Op())
- }
- n.aux = uint8(op)
-}
-
-func (n *node) IndexMapLValue() bool {
- if n.Op() != OINDEXMAP {
- base.Fatalf("unexpected op: %v", n.Op())
- }
- return n.aux != 0
-}
-
-func (n *node) SetIndexMapLValue(b bool) {
- if n.Op() != OINDEXMAP {
- base.Fatalf("unexpected op: %v", n.Op())
- }
- if b {
- n.aux = 1
- } else {
- n.aux = 0
- }
-}
-
-func (n *node) TChanDir() types.ChanDir {
- if n.Op() != OTCHAN {
- base.Fatalf("unexpected op: %v", n.Op())
- }
- return types.ChanDir(n.aux)
-}
-
-func (n *node) SetTChanDir(dir types.ChanDir) {
- if n.Op() != OTCHAN {
- base.Fatalf("unexpected op: %v", n.Op())
- }
- n.aux = uint8(dir)
+// Line returns n's position as a string. If n has been inlined,
+// it uses the outermost position where n has been inlined.
+func Line(n Node) string {
+ return base.FmtPos(n.Pos())
}
func IsSynthetic(n Node) bool {
@@ -282,170 +130,6 @@ func IsAutoTmp(n Node) bool {
return n.Name().AutoTemp()
}
-const (
- nodeClass, _ = iota, 1 << iota // PPARAM, PAUTO, PEXTERN, etc; three bits; first in the list because frequently accessed
- _, _ // second nodeClass bit
- _, _ // third nodeClass bit
- nodeWalkdef, _ // tracks state during typecheckdef; 2 == loop detected; two bits
- _, _ // second nodeWalkdef bit
- nodeTypecheck, _ // tracks state during typechecking; 2 == loop detected; two bits
- _, _ // second nodeTypecheck bit
- nodeInitorder, _ // tracks state during init1; two bits
- _, _ // second nodeInitorder bit
- _, nodeHasBreak
- _, nodeNoInline // used internally by inliner to indicate that a function call should not be inlined; set for OCALLFUNC and OCALLMETH only
- _, nodeImplicit // implicit OADDR or ODEREF; ++/-- statement represented as OASOP
- _, nodeIsDDD // is the argument variadic
- _, nodeDiag // already printed error about this
- _, nodeColas // OAS resulting from :=
- _, nodeNonNil // guaranteed to be non-nil
- _, nodeTransient // storage can be reused immediately after this statement
- _, nodeBounded // bounds check unnecessary
- _, nodeHasCall // expression contains a function call
- _, nodeLikely // if statement condition likely
- _, nodeHasVal // node.E contains a Val
- _, nodeHasOpt // node.E contains an Opt
- _, nodeEmbedded // ODCLFIELD embedded type
-)
-
-func (n *node) Class() Class { return Class(n.flags.get3(nodeClass)) }
-func (n *node) Walkdef() uint8 { return n.flags.get2(nodeWalkdef) }
-func (n *node) Typecheck() uint8 { return n.flags.get2(nodeTypecheck) }
-func (n *node) Initorder() uint8 { return n.flags.get2(nodeInitorder) }
-
-func (n *node) HasBreak() bool { return n.flags&nodeHasBreak != 0 }
-func (n *node) NoInline() bool { return n.flags&nodeNoInline != 0 }
-func (n *node) Implicit() bool { return n.flags&nodeImplicit != 0 }
-func (n *node) IsDDD() bool { return n.flags&nodeIsDDD != 0 }
-func (n *node) Diag() bool { return n.flags&nodeDiag != 0 }
-func (n *node) Colas() bool { return n.flags&nodeColas != 0 }
-func (n *node) NonNil() bool { return n.flags&nodeNonNil != 0 }
-func (n *node) Transient() bool { return n.flags&nodeTransient != 0 }
-func (n *node) Bounded() bool { return n.flags&nodeBounded != 0 }
-func (n *node) HasCall() bool { return n.flags&nodeHasCall != 0 }
-func (n *node) Likely() bool { return n.flags&nodeLikely != 0 }
-func (n *node) HasVal() bool { return n.flags&nodeHasVal != 0 }
-func (n *node) HasOpt() bool { return n.flags&nodeHasOpt != 0 }
-func (n *node) Embedded() bool { return n.flags&nodeEmbedded != 0 }
-
-func (n *node) SetClass(b Class) { n.flags.set3(nodeClass, uint8(b)) }
-func (n *node) SetWalkdef(b uint8) { n.flags.set2(nodeWalkdef, b) }
-func (n *node) SetTypecheck(b uint8) { n.flags.set2(nodeTypecheck, b) }
-func (n *node) SetInitorder(b uint8) { n.flags.set2(nodeInitorder, b) }
-
-func (n *node) SetHasBreak(b bool) { n.flags.set(nodeHasBreak, b) }
-func (n *node) SetNoInline(b bool) { n.flags.set(nodeNoInline, b) }
-func (n *node) SetImplicit(b bool) { n.flags.set(nodeImplicit, b) }
-func (n *node) SetIsDDD(b bool) { n.flags.set(nodeIsDDD, b) }
-func (n *node) SetDiag(b bool) { n.flags.set(nodeDiag, b) }
-func (n *node) SetColas(b bool) { n.flags.set(nodeColas, b) }
-func (n *node) SetTransient(b bool) { n.flags.set(nodeTransient, b) }
-func (n *node) SetHasCall(b bool) { n.flags.set(nodeHasCall, b) }
-func (n *node) SetLikely(b bool) { n.flags.set(nodeLikely, b) }
-func (n *node) setHasVal(b bool) { n.flags.set(nodeHasVal, b) }
-func (n *node) setHasOpt(b bool) { n.flags.set(nodeHasOpt, b) }
-func (n *node) SetEmbedded(b bool) { n.flags.set(nodeEmbedded, b) }
-
-// MarkNonNil marks a pointer n as being guaranteed non-nil,
-// on all code paths, at all times.
-// During conversion to SSA, non-nil pointers won't have nil checks
-// inserted before dereferencing. See state.exprPtr.
-func (n *node) MarkNonNil() {
- if !n.Type().IsPtr() && !n.Type().IsUnsafePtr() {
- base.Fatalf("MarkNonNil(%v), type %v", n, n.Type())
- }
- n.flags.set(nodeNonNil, true)
-}
-
-// SetBounded indicates whether operation n does not need safety checks.
-// When n is an index or slice operation, n does not need bounds checks.
-// When n is a dereferencing operation, n does not need nil checks.
-// When n is a makeslice+copy operation, n does not need length and cap checks.
-func (n *node) SetBounded(b bool) {
- switch n.Op() {
- case OINDEX, OSLICE, OSLICEARR, OSLICE3, OSLICE3ARR, OSLICESTR:
- // No bounds checks needed.
- case ODOTPTR, ODEREF:
- // No nil check needed.
- case OMAKESLICECOPY:
- // No length and cap checks needed
- // since new slice and copied over slice data have same length.
- default:
- base.Fatalf("SetBounded(%v)", n)
- }
- n.flags.set(nodeBounded, b)
-}
-
-// MarkReadonly indicates that n is an ONAME with readonly contents.
-func (n *node) MarkReadonly() {
- if n.Op() != ONAME {
- base.Fatalf("Node.MarkReadonly %v", n.Op())
- }
- n.Name().SetReadonly(true)
- // Mark the linksym as readonly immediately
- // so that the SSA backend can use this information.
- // It will be overridden later during dumpglobls.
- n.Sym().Linksym().Type = objabi.SRODATA
-}
-
-// Val returns the constant.Value for the node.
-func (n *node) Val() constant.Value {
- if !n.HasVal() {
- return constant.MakeUnknown()
- }
- return *n.e.(*constant.Value)
-}
-
-// SetVal sets the constant.Value for the node,
-// which must not have been used with SetOpt.
-func (n *node) SetVal(v constant.Value) {
- if n.HasOpt() {
- base.Flag.LowerH = 1
- Dump("have Opt", n)
- base.Fatalf("have Opt")
- }
- if n.Op() == OLITERAL {
- AssertValidTypeForConst(n.Type(), v)
- }
- n.setHasVal(true)
- n.e = &v
-}
-
-// Opt returns the optimizer data for the node.
-func (n *node) Opt() interface{} {
- if !n.HasOpt() {
- return nil
- }
- return n.e
-}
-
-// SetOpt sets the optimizer data for the node, which must not have been used with SetVal.
-// SetOpt(nil) is ignored for Vals to simplify call sites that are clearing Opts.
-func (n *node) SetOpt(x interface{}) {
- if x == nil {
- if n.HasOpt() {
- n.setHasOpt(false)
- n.e = nil
- }
- return
- }
- if n.HasVal() {
- base.Flag.LowerH = 1
- Dump("have Val", n)
- base.Fatalf("have Val")
- }
- n.setHasOpt(true)
- n.e = x
-}
-
-func (n *node) Iota() int64 {
- return n.Offset()
-}
-
-func (n *node) SetIota(x int64) {
- n.SetOffset(x)
-}
-
// mayBeShared reports whether n may occur in multiple places in the AST.
// Extra care must be taken when mutating such a node.
func MayBeShared(n Node) bool {
@@ -456,438 +140,6 @@ func MayBeShared(n Node) bool {
return false
}
-// funcname returns the name (without the package) of the function n.
-func FuncName(n Node) string {
- if n == nil || n.Func() == nil || n.Func().Nname == nil {
- return ""
- }
- return n.Func().Nname.Sym().Name
-}
-
-// pkgFuncName returns the name of the function referenced by n, with package prepended.
-// This differs from the compiler's internal convention where local functions lack a package
-// because the ultimate consumer of this is a human looking at an IDE; package is only empty
-// if the compilation package is actually the empty string.
-func PkgFuncName(n Node) string {
- var s *types.Sym
- if n == nil {
- return ""
- }
- if n.Op() == ONAME {
- s = n.Sym()
- } else {
- if n.Func() == nil || n.Func().Nname == nil {
- return ""
- }
- s = n.Func().Nname.Sym()
- }
- pkg := s.Pkg
-
- p := base.Ctxt.Pkgpath
- if pkg != nil && pkg.Path != "" {
- p = pkg.Path
- }
- if p == "" {
- return s.Name
- }
- return p + "." + s.Name
-}
-
-// The compiler needs *Node to be assignable to cmd/compile/internal/ssa.Sym.
-func (n *node) CanBeAnSSASym() {
-}
-
-// Name holds Node fields used only by named nodes (ONAME, OTYPE, OPACK, OLABEL, some OLITERAL).
-type Name struct {
- Pack Node // real package for import . names
- Pkg *types.Pkg // pkg for OPACK nodes
- // For a local variable (not param) or extern, the initializing assignment (OAS or OAS2).
- // For a closure var, the ONAME node of the outer captured variable
- Defn Node
- // The ODCLFUNC node (for a static function/method or a closure) in which
- // local variable or param is declared.
- Curfn Node
- Param *Param // additional fields for ONAME, OTYPE
- Decldepth int32 // declaration loop depth, increased for every loop or label
- // Unique number for ONAME nodes within a function. Function outputs
- // (results) are numbered starting at one, followed by function inputs
- // (parameters), and then local variables. Vargen is used to distinguish
- // local variables/params with the same name.
- Vargen int32
- flags bitset16
-}
-
-const (
- nameCaptured = 1 << iota // is the variable captured by a closure
- nameReadonly
- nameByval // is the variable captured by value or by reference
- nameNeedzero // if it contains pointers, needs to be zeroed on function entry
- nameAutoTemp // is the variable a temporary (implies no dwarf info. reset if escapes to heap)
- nameUsed // for variable declared and not used error
- nameIsClosureVar // PAUTOHEAP closure pseudo-variable; original at n.Name.Defn
- nameIsOutputParamHeapAddr // pointer to a result parameter's heap copy
- nameAssigned // is the variable ever assigned to
- nameAddrtaken // address taken, even if not moved to heap
- nameInlFormal // PAUTO created by inliner, derived from callee formal
- nameInlLocal // PAUTO created by inliner, derived from callee local
- nameOpenDeferSlot // if temporary var storing info for open-coded defers
- nameLibfuzzerExtraCounter // if PEXTERN should be assigned to __libfuzzer_extra_counters section
-)
-
-func (n *Name) Captured() bool { return n.flags&nameCaptured != 0 }
-func (n *Name) Readonly() bool { return n.flags&nameReadonly != 0 }
-func (n *Name) Byval() bool { return n.flags&nameByval != 0 }
-func (n *Name) Needzero() bool { return n.flags&nameNeedzero != 0 }
-func (n *Name) AutoTemp() bool { return n.flags&nameAutoTemp != 0 }
-func (n *Name) Used() bool { return n.flags&nameUsed != 0 }
-func (n *Name) IsClosureVar() bool { return n.flags&nameIsClosureVar != 0 }
-func (n *Name) IsOutputParamHeapAddr() bool { return n.flags&nameIsOutputParamHeapAddr != 0 }
-func (n *Name) Assigned() bool { return n.flags&nameAssigned != 0 }
-func (n *Name) Addrtaken() bool { return n.flags&nameAddrtaken != 0 }
-func (n *Name) InlFormal() bool { return n.flags&nameInlFormal != 0 }
-func (n *Name) InlLocal() bool { return n.flags&nameInlLocal != 0 }
-func (n *Name) OpenDeferSlot() bool { return n.flags&nameOpenDeferSlot != 0 }
-func (n *Name) LibfuzzerExtraCounter() bool { return n.flags&nameLibfuzzerExtraCounter != 0 }
-
-func (n *Name) SetCaptured(b bool) { n.flags.set(nameCaptured, b) }
-func (n *Name) SetReadonly(b bool) { n.flags.set(nameReadonly, b) }
-func (n *Name) SetByval(b bool) { n.flags.set(nameByval, b) }
-func (n *Name) SetNeedzero(b bool) { n.flags.set(nameNeedzero, b) }
-func (n *Name) SetAutoTemp(b bool) { n.flags.set(nameAutoTemp, b) }
-func (n *Name) SetUsed(b bool) { n.flags.set(nameUsed, b) }
-func (n *Name) SetIsClosureVar(b bool) { n.flags.set(nameIsClosureVar, b) }
-func (n *Name) SetIsOutputParamHeapAddr(b bool) { n.flags.set(nameIsOutputParamHeapAddr, b) }
-func (n *Name) SetAssigned(b bool) { n.flags.set(nameAssigned, b) }
-func (n *Name) SetAddrtaken(b bool) { n.flags.set(nameAddrtaken, b) }
-func (n *Name) SetInlFormal(b bool) { n.flags.set(nameInlFormal, b) }
-func (n *Name) SetInlLocal(b bool) { n.flags.set(nameInlLocal, b) }
-func (n *Name) SetOpenDeferSlot(b bool) { n.flags.set(nameOpenDeferSlot, b) }
-func (n *Name) SetLibfuzzerExtraCounter(b bool) { n.flags.set(nameLibfuzzerExtraCounter, b) }
-
-type Param struct {
- Ntype Node
- Heapaddr Node // temp holding heap address of param
-
- // ONAME PAUTOHEAP
- Stackcopy Node // the PPARAM/PPARAMOUT on-stack slot (moved func params only)
-
- // ONAME closure linkage
- // Consider:
- //
- // func f() {
- // x := 1 // x1
- // func() {
- // use(x) // x2
- // func() {
- // use(x) // x3
- // --- parser is here ---
- // }()
- // }()
- // }
- //
- // There is an original declaration of x and then a chain of mentions of x
- // leading into the current function. Each time x is mentioned in a new closure,
- // we create a variable representing x for use in that specific closure,
- // since the way you get to x is different in each closure.
- //
- // Let's number the specific variables as shown in the code:
- // x1 is the original x, x2 is when mentioned in the closure,
- // and x3 is when mentioned in the closure in the closure.
- //
- // We keep these linked (assume N > 1):
- //
- // - x1.Defn = original declaration statement for x (like most variables)
- // - x1.Innermost = current innermost closure x (in this case x3), or nil for none
- // - x1.IsClosureVar() = false
- //
- // - xN.Defn = x1, N > 1
- // - xN.IsClosureVar() = true, N > 1
- // - x2.Outer = nil
- // - xN.Outer = x(N-1), N > 2
- //
- //
- // When we look up x in the symbol table, we always get x1.
- // Then we can use x1.Innermost (if not nil) to get the x
- // for the innermost known closure function,
- // but the first reference in a closure will find either no x1.Innermost
- // or an x1.Innermost with .Funcdepth < Funcdepth.
- // In that case, a new xN must be created, linked in with:
- //
- // xN.Defn = x1
- // xN.Outer = x1.Innermost
- // x1.Innermost = xN
- //
- // When we finish the function, we'll process its closure variables
- // and find xN and pop it off the list using:
- //
- // x1 := xN.Defn
- // x1.Innermost = xN.Outer
- //
- // We leave x1.Innermost set so that we can still get to the original
- // variable quickly. Not shown here, but once we're
- // done parsing a function and no longer need xN.Outer for the
- // lexical x reference links as described above, funcLit
- // recomputes xN.Outer as the semantic x reference link tree,
- // even filling in x in intermediate closures that might not
- // have mentioned it along the way to inner closures that did.
- // See funcLit for details.
- //
- // During the eventual compilation, then, for closure variables we have:
- //
- // xN.Defn = original variable
- // xN.Outer = variable captured in next outward scope
- // to make closure where xN appears
- //
- // Because of the sharding of pieces of the node, x.Defn means x.Name.Defn
- // and x.Innermost/Outer means x.Name.Param.Innermost/Outer.
- Innermost Node
- Outer Node
-
- // OTYPE & ONAME //go:embed info,
- // sharing storage to reduce gc.Param size.
- // Extra is nil, or else *Extra is a *paramType or an *embedFileList.
- Extra *interface{}
-}
-
-type paramType struct {
- flag PragmaFlag
- alias bool
-}
-
-type embedFileList []string
-
-// Pragma returns the PragmaFlag for p, which must be for an OTYPE.
-func (p *Param) Pragma() PragmaFlag {
- if p.Extra == nil {
- return 0
- }
- return (*p.Extra).(*paramType).flag
-}
-
-// SetPragma sets the PragmaFlag for p, which must be for an OTYPE.
-func (p *Param) SetPragma(flag PragmaFlag) {
- if p.Extra == nil {
- if flag == 0 {
- return
- }
- p.Extra = new(interface{})
- *p.Extra = ¶mType{flag: flag}
- return
- }
- (*p.Extra).(*paramType).flag = flag
-}
-
-// Alias reports whether p, which must be for an OTYPE, is a type alias.
-func (p *Param) Alias() bool {
- if p.Extra == nil {
- return false
- }
- t, ok := (*p.Extra).(*paramType)
- if !ok {
- return false
- }
- return t.alias
-}
-
-// SetAlias sets whether p, which must be for an OTYPE, is a type alias.
-func (p *Param) SetAlias(alias bool) {
- if p.Extra == nil {
- if !alias {
- return
- }
- p.Extra = new(interface{})
- *p.Extra = ¶mType{alias: alias}
- return
- }
- (*p.Extra).(*paramType).alias = alias
-}
-
-// EmbedFiles returns the list of embedded files for p,
-// which must be for an ONAME var.
-func (p *Param) EmbedFiles() []string {
- if p.Extra == nil {
- return nil
- }
- return *(*p.Extra).(*embedFileList)
-}
-
-// SetEmbedFiles sets the list of embedded files for p,
-// which must be for an ONAME var.
-func (p *Param) SetEmbedFiles(list []string) {
- if p.Extra == nil {
- if len(list) == 0 {
- return
- }
- f := embedFileList(list)
- p.Extra = new(interface{})
- *p.Extra = &f
- return
- }
- *(*p.Extra).(*embedFileList) = list
-}
-
-// A Func corresponds to a single function in a Go program
-// (and vice versa: each function is denoted by exactly one *Func).
-//
-// There are multiple nodes that represent a Func in the IR.
-//
-// The ONAME node (Func.Name) is used for plain references to it.
-// The ODCLFUNC node (Func.Decl) is used for its declaration code.
-// The OCLOSURE node (Func.Closure) is used for a reference to a
-// function literal.
-//
-// A Func for an imported function will have only an ONAME node.
-// A declared function or method has an ONAME and an ODCLFUNC.
-// A function literal is represented directly by an OCLOSURE, but it also
-// has an ODCLFUNC (and a matching ONAME) representing the compiled
-// underlying form of the closure, which accesses the captured variables
-// using a special data structure passed in a register.
-//
-// A method declaration is represented like functions, except f.Sym
-// will be the qualified method name (e.g., "T.m") and
-// f.Func.Shortname is the bare method name (e.g., "m").
-//
-// A method expression (T.M) is represented as an OMETHEXPR node,
-// in which n.Left and n.Right point to the type and method, respectively.
-// Each distinct mention of a method expression in the source code
-// constructs a fresh node.
-//
-// A method value (t.M) is represented by ODOTMETH/ODOTINTER
-// when it is called directly and by OCALLPART otherwise.
-// These are like method expressions, except that for ODOTMETH/ODOTINTER,
-// the method name is stored in Sym instead of Right.
-// Each OCALLPART ends up being implemented as a new
-// function, a bit like a closure, with its own ODCLFUNC.
-// The OCALLPART has uses n.Func to record the linkage to
-// the generated ODCLFUNC (as n.Func.Decl), but there is no
-// pointer from the Func back to the OCALLPART.
-type Func struct {
- Nname Node // ONAME node
- Decl Node // ODCLFUNC node
- OClosure Node // OCLOSURE node
-
- Shortname *types.Sym
-
- // Extra entry code for the function. For example, allocate and initialize
- // memory for escaping parameters.
- Enter Nodes
- Exit Nodes
- // ONAME nodes for all params/locals for this func/closure, does NOT
- // include closurevars until transformclosure runs.
- Dcl []Node
-
- ClosureEnter Nodes // list of ONAME nodes of captured variables
- ClosureType Node // closure representation type
- ClosureCalled bool // closure is only immediately called
- ClosureVars Nodes // closure params; each has closurevar set
-
- // Parents records the parent scope of each scope within a
- // function. The root scope (0) has no parent, so the i'th
- // scope's parent is stored at Parents[i-1].
- Parents []ScopeID
-
- // Marks records scope boundary changes.
- Marks []Mark
-
- // Closgen tracks how many closures have been generated within
- // this function. Used by closurename for creating unique
- // function names.
- Closgen int
-
- FieldTrack map[*types.Sym]struct{}
- DebugInfo interface{}
- LSym *obj.LSym
-
- Inl *Inline
-
- Label int32 // largest auto-generated label in this function
-
- Endlineno src.XPos
- WBPos src.XPos // position of first write barrier; see SetWBPos
-
- Pragma PragmaFlag // go:xxx function annotations
-
- flags bitset16
- NumDefers int // number of defer calls in the function
- NumReturns int // number of explicit returns in the function
-
- // nwbrCalls records the LSyms of functions called by this
- // function for go:nowritebarrierrec analysis. Only filled in
- // if nowritebarrierrecCheck != nil.
- NWBRCalls *[]SymAndPos
-}
-
-// An Inline holds fields used for function bodies that can be inlined.
-type Inline struct {
- Cost int32 // heuristic cost of inlining this function
-
- // Copies of Func.Dcl and Nbody for use during inlining.
- Dcl []Node
- Body []Node
-}
-
-// A Mark represents a scope boundary.
-type Mark struct {
- // Pos is the position of the token that marks the scope
- // change.
- Pos src.XPos
-
- // Scope identifies the innermost scope to the right of Pos.
- Scope ScopeID
-}
-
-// A ScopeID represents a lexical scope within a function.
-type ScopeID int32
-
-const (
- funcDupok = 1 << iota // duplicate definitions ok
- funcWrapper // is method wrapper
- funcNeedctxt // function uses context register (has closure variables)
- funcReflectMethod // function calls reflect.Type.Method or MethodByName
- // true if closure inside a function; false if a simple function or a
- // closure in a global variable initialization
- funcIsHiddenClosure
- funcHasDefer // contains a defer statement
- funcNilCheckDisabled // disable nil checks when compiling this function
- funcInlinabilityChecked // inliner has already determined whether the function is inlinable
- funcExportInline // include inline body in export data
- funcInstrumentBody // add race/msan instrumentation during SSA construction
- funcOpenCodedDeferDisallowed // can't do open-coded defers
-)
-
-func (f *Func) Dupok() bool { return f.flags&funcDupok != 0 }
-func (f *Func) Wrapper() bool { return f.flags&funcWrapper != 0 }
-func (f *Func) Needctxt() bool { return f.flags&funcNeedctxt != 0 }
-func (f *Func) ReflectMethod() bool { return f.flags&funcReflectMethod != 0 }
-func (f *Func) IsHiddenClosure() bool { return f.flags&funcIsHiddenClosure != 0 }
-func (f *Func) HasDefer() bool { return f.flags&funcHasDefer != 0 }
-func (f *Func) NilCheckDisabled() bool { return f.flags&funcNilCheckDisabled != 0 }
-func (f *Func) InlinabilityChecked() bool { return f.flags&funcInlinabilityChecked != 0 }
-func (f *Func) ExportInline() bool { return f.flags&funcExportInline != 0 }
-func (f *Func) InstrumentBody() bool { return f.flags&funcInstrumentBody != 0 }
-func (f *Func) OpenCodedDeferDisallowed() bool { return f.flags&funcOpenCodedDeferDisallowed != 0 }
-
-func (f *Func) SetDupok(b bool) { f.flags.set(funcDupok, b) }
-func (f *Func) SetWrapper(b bool) { f.flags.set(funcWrapper, b) }
-func (f *Func) SetNeedctxt(b bool) { f.flags.set(funcNeedctxt, b) }
-func (f *Func) SetReflectMethod(b bool) { f.flags.set(funcReflectMethod, b) }
-func (f *Func) SetIsHiddenClosure(b bool) { f.flags.set(funcIsHiddenClosure, b) }
-func (f *Func) SetHasDefer(b bool) { f.flags.set(funcHasDefer, b) }
-func (f *Func) SetNilCheckDisabled(b bool) { f.flags.set(funcNilCheckDisabled, b) }
-func (f *Func) SetInlinabilityChecked(b bool) { f.flags.set(funcInlinabilityChecked, b) }
-func (f *Func) SetExportInline(b bool) { f.flags.set(funcExportInline, b) }
-func (f *Func) SetInstrumentBody(b bool) { f.flags.set(funcInstrumentBody, b) }
-func (f *Func) SetOpenCodedDeferDisallowed(b bool) { f.flags.set(funcOpenCodedDeferDisallowed, b) }
-
-func (f *Func) SetWBPos(pos src.XPos) {
- if base.Debug.WB != 0 {
- base.WarnfAt(pos, "write barrier")
- }
- if !f.WBPos.IsKnown() {
- f.WBPos = pos
- }
-}
-
//go:generate stringer -type=Op -trimprefix=O
type Op uint8
@@ -961,7 +213,6 @@ const (
// Used during parsing but don't last.
ODCLFUNC // func f() or func (r) f()
- ODCLFIELD // struct field, interface field, or func/method argument/return value.
ODCLCONST // const pi = 3.14
ODCLTYPE // type Int int or type Int = int
@@ -1025,8 +276,8 @@ const (
ORECOVER // recover()
ORECV // <-Left
ORUNESTR // Type(Left) (Type is string, Left is rune)
- OSELRECV // Left = <-Right.Left: (appears as .Left of OCASE; Right.Op == ORECV)
- OSELRECV2 // List = <-Right.Left: (appears as .Left of OCASE; count(List) == 2, Right.Op == ORECV)
+ OSELRECV // like OAS: Left = Right where Right.Op = ORECV (appears as .Left of OCASE)
+ OSELRECV2 // like OAS2: List = Rlist where len(List)=2, len(Rlist)=1, Rlist[0].Op = ORECV (appears as .Left of OCASE)
OIOTA // iota
OREAL // real(Left)
OIMAG // imag(Left)
@@ -1035,6 +286,7 @@ const (
OOFFSETOF // unsafe.Offsetof(Left)
OSIZEOF // unsafe.Sizeof(Left)
OMETHEXPR // method expression
+ OSTMTEXPR // statement expression (Init; Left)
// statements
OBLOCK // { List } (block of code)
@@ -1047,7 +299,6 @@ const (
OCASE
OCONTINUE // continue [Sym]
ODEFER // defer Left (Left must be call)
- OEMPTY // no-op (empty statement)
OFALL // fallthrough
OFOR // for Ninit; Left; Right { Nbody }
// OFORUNTIL is like OFOR, but the test (Left) is applied after the body:
@@ -1080,23 +331,23 @@ const (
// OTFUNC: func() - Left is receiver field, List is list of param fields, Rlist is
// list of result fields.
OTFUNC
- OTARRAY // []int, [8]int, [N]int or [...]int
+ OTARRAY // [8]int or [...]int
+ OTSLICE // []int
// misc
- ODDD // func f(args ...int) or f(l...) or var a = [...]int{0, 1, 2}.
- OINLCALL // intermediary representation of an inlined call.
- OEFACE // itable and data words of an empty-interface value.
- OITAB // itable word of an interface value.
- OIDATA // data word of an interface value in Left
- OSPTR // base pointer of a slice or string.
- OCLOSUREVAR // variable reference at beginning of closure function
- OCFUNC // reference to c function pointer (not go func value)
- OCHECKNIL // emit code to ensure pointer/interface not nil
- OVARDEF // variable is about to be fully initialized
- OVARKILL // variable is dead
- OVARLIVE // variable is alive
- ORESULT // result of a function call; Xoffset is stack offset
- OINLMARK // start of an inlined body, with file/line of caller. Xoffset is an index into the inline tree.
+ OINLCALL // intermediary representation of an inlined call.
+ OEFACE // itable and data words of an empty-interface value.
+ OITAB // itable word of an interface value.
+ OIDATA // data word of an interface value in Left
+ OSPTR // base pointer of a slice or string.
+ OCLOSUREREAD // read from inside closure struct at beginning of closure function
+ OCFUNC // reference to c function pointer (not go func value)
+ OCHECKNIL // emit code to ensure pointer/interface not nil
+ OVARDEF // variable is about to be fully initialized
+ OVARKILL // variable is dead
+ OVARLIVE // variable is alive
+ ORESULT // result of a function call; Xoffset is stack offset
+ OINLMARK // start of an inlined body, with file/line of caller. Xoffset is an index into the inline tree.
// arch-specific opcodes
ORETJMP // return to other function
@@ -1110,6 +361,10 @@ const (
// a slice to save space.
type Nodes struct{ slice *[]Node }
+// immutableEmptyNodes is an immutable, empty Nodes list.
+// The methods that would modify it panic instead.
+var immutableEmptyNodes = Nodes{}
+
// asNodes returns a slice of *Node as a Nodes value.
func AsNodes(s []Node) Nodes {
return Nodes{&s}
@@ -1151,9 +406,22 @@ func (n Nodes) Second() Node {
return (*n.slice)[1]
}
+func (n *Nodes) mutate() {
+ if n == &immutableEmptyNodes {
+ panic("immutable Nodes.Set")
+ }
+}
+
// Set sets n to a slice.
// This takes ownership of the slice.
func (n *Nodes) Set(s []Node) {
+ if n == &immutableEmptyNodes {
+ if len(s) == 0 {
+ // Allow immutableEmptyNodes.Set(nil) (a no-op).
+ return
+ }
+ n.mutate()
+ }
if len(s) == 0 {
n.slice = nil
} else {
@@ -1167,21 +435,25 @@ func (n *Nodes) Set(s []Node) {
// Set1 sets n to a slice containing a single node.
func (n *Nodes) Set1(n1 Node) {
+ n.mutate()
n.slice = &[]Node{n1}
}
// Set2 sets n to a slice containing two nodes.
func (n *Nodes) Set2(n1, n2 Node) {
+ n.mutate()
n.slice = &[]Node{n1, n2}
}
// Set3 sets n to a slice containing three nodes.
func (n *Nodes) Set3(n1, n2, n3 Node) {
+ n.mutate()
n.slice = &[]Node{n1, n2, n3}
}
// MoveNodes sets n to the contents of n2, then clears n2.
func (n *Nodes) MoveNodes(n2 *Nodes) {
+ n.mutate()
n.slice = n2.slice
n2.slice = nil
}
@@ -1215,6 +487,7 @@ func (n *Nodes) Append(a ...Node) {
if len(a) == 0 {
return
}
+ n.mutate()
if n.slice == nil {
s := make([]Node, len(a))
copy(s, a)
@@ -1230,6 +503,7 @@ func (n *Nodes) Prepend(a ...Node) {
if len(a) == 0 {
return
}
+ n.mutate()
if n.slice == nil {
n.slice = &a
} else {
@@ -1239,6 +513,7 @@ func (n *Nodes) Prepend(a ...Node) {
// AppendNodes appends the contents of *n2 to n, then clears n2.
func (n *Nodes) AppendNodes(n2 *Nodes) {
+ n.mutate()
switch {
case n2.slice == nil:
case n.slice == nil:
@@ -1249,45 +524,40 @@ func (n *Nodes) AppendNodes(n2 *Nodes) {
n2.slice = nil
}
-// inspect invokes f on each node in an AST in depth-first order.
-// If f(n) returns false, inspect skips visiting n's children.
-func Inspect(n Node, f func(Node) bool) {
- if n == nil || !f(n) {
- return
+// Copy returns a copy of the content of the slice.
+func (n Nodes) Copy() Nodes {
+ var c Nodes
+ if n.slice == nil {
+ return c
}
- InspectList(n.Init(), f)
- Inspect(n.Left(), f)
- Inspect(n.Right(), f)
- InspectList(n.List(), f)
- InspectList(n.Body(), f)
- InspectList(n.Rlist(), f)
+ c.slice = new([]Node)
+ if *n.slice == nil {
+ return c
+ }
+ *c.slice = make([]Node, n.Len())
+ copy(*c.slice, n.Slice())
+ return c
}
-func InspectList(l Nodes, f func(Node) bool) {
- for _, n := range l.Slice() {
- Inspect(n, f)
- }
-}
-
-// nodeQueue is a FIFO queue of *Node. The zero value of nodeQueue is
+// NameQueue is a FIFO queue of *Name. The zero value of NameQueue is
// a ready-to-use empty queue.
-type NodeQueue struct {
- ring []Node
+type NameQueue struct {
+ ring []*Name
head, tail int
}
-// empty reports whether q contains no Nodes.
-func (q *NodeQueue) Empty() bool {
+// Empty reports whether q contains no Names.
+func (q *NameQueue) Empty() bool {
return q.head == q.tail
}
-// pushRight appends n to the right of the queue.
-func (q *NodeQueue) PushRight(n Node) {
+// PushRight appends n to the right of the queue.
+func (q *NameQueue) PushRight(n *Name) {
if len(q.ring) == 0 {
- q.ring = make([]Node, 16)
+ q.ring = make([]*Name, 16)
} else if q.head+len(q.ring) == q.tail {
// Grow the ring.
- nring := make([]Node, len(q.ring)*2)
+ nring := make([]*Name, len(q.ring)*2)
// Copy the old elements.
part := q.ring[q.head%len(q.ring):]
if q.tail-q.head <= len(part) {
@@ -1304,9 +574,9 @@ func (q *NodeQueue) PushRight(n Node) {
q.tail++
}
-// popLeft pops a node from the left of the queue. It panics if q is
+// PopLeft pops a Name from the left of the queue. It panics if q is
// empty.
-func (q *NodeQueue) PopLeft() Node {
+func (q *NameQueue) PopLeft() *Name {
if q.Empty() {
panic("dequeue empty")
}
@@ -1315,26 +585,26 @@ func (q *NodeQueue) PopLeft() Node {
return n
}
-// NodeSet is a set of Nodes.
-type NodeSet map[Node]struct{}
+// NameSet is a set of Names.
+type NameSet map[*Name]struct{}
// Has reports whether s contains n.
-func (s NodeSet) Has(n Node) bool {
+func (s NameSet) Has(n *Name) bool {
_, isPresent := s[n]
return isPresent
}
// Add adds n to s.
-func (s *NodeSet) Add(n Node) {
+func (s *NameSet) Add(n *Name) {
if *s == nil {
- *s = make(map[Node]struct{})
+ *s = make(map[*Name]struct{})
}
(*s)[n] = struct{}{}
}
// Sorted returns s sorted according to less.
-func (s NodeSet) Sorted(less func(Node, Node) bool) []Node {
- var res []Node
+func (s NameSet) Sorted(less func(*Name, *Name) bool) []*Name {
+ var res []*Name
for n := range s {
res = append(res, n)
}
@@ -1342,85 +612,6 @@ func (s NodeSet) Sorted(less func(Node, Node) bool) []Node {
return res
}
-func Nod(op Op, nleft, nright Node) Node {
- return NodAt(base.Pos, op, nleft, nright)
-}
-
-func NodAt(pos src.XPos, op Op, nleft, nright Node) Node {
- var n Node
- switch op {
- case ODCLFUNC:
- var x struct {
- n node
- f Func
- }
- n = &x.n
- n.SetFunc(&x.f)
- n.Func().Decl = n
- case ONAME:
- base.Fatalf("use newname instead")
- case OLABEL, OPACK:
- var x struct {
- n node
- m Name
- }
- n = &x.n
- n.SetName(&x.m)
- default:
- n = new(node)
- }
- n.SetOp(op)
- n.SetLeft(nleft)
- n.SetRight(nright)
- n.SetPos(pos)
- n.SetOffset(types.BADWIDTH)
- n.SetOrig(n)
- return n
-}
-
-// newnamel returns a new ONAME Node associated with symbol s at position pos.
-// The caller is responsible for setting n.Name.Curfn.
-func NewNameAt(pos src.XPos, s *types.Sym) Node {
- if s == nil {
- base.Fatalf("newnamel nil")
- }
-
- var x struct {
- n node
- m Name
- p Param
- }
- n := &x.n
- n.SetName(&x.m)
- n.Name().Param = &x.p
-
- n.SetOp(ONAME)
- n.SetPos(pos)
- n.SetOrig(n)
-
- n.SetSym(s)
- return n
-}
-
-// The Class of a variable/function describes the "storage class"
-// of a variable or function. During parsing, storage classes are
-// called declaration contexts.
-type Class uint8
-
-//go:generate stringer -type=Class
-const (
- Pxxx Class = iota // no class; used during ssa conversion to indicate pseudo-variables
- PEXTERN // global variables
- PAUTO // local variables
- PAUTOHEAP // local variables or parameters moved to heap
- PPARAM // input arguments
- PPARAMOUT // output results
- PFUNC // global functions
-
- // Careful: Class is stored in three bits in Node.flags.
- _ = uint((1 << 3) - iota) // static assert for iota <= (1 << 3)
-)
-
type PragmaFlag int16
const (
@@ -1448,12 +639,7 @@ const (
GoBuildPragma
)
-type SymAndPos struct {
- Sym *obj.LSym // LSym of callee
- Pos src.XPos // line of call
-}
-
-func AsNode(n types.IRNode) Node {
+func AsNode(n types.Object) Node {
if n == nil {
return nil
}
@@ -1462,195 +648,15 @@ func AsNode(n types.IRNode) Node {
var BlankNode Node
-// origSym returns the original symbol written by the user.
-func OrigSym(s *types.Sym) *types.Sym {
- if s == nil {
- return nil
- }
-
- if len(s.Name) > 1 && s.Name[0] == '~' {
- switch s.Name[1] {
- case 'r': // originally an unnamed result
- return nil
- case 'b': // originally the blank identifier _
- // TODO(mdempsky): Does s.Pkg matter here?
- return BlankNode.Sym()
- }
- return s
- }
-
- if strings.HasPrefix(s.Name, ".anon") {
- // originally an unnamed or _ name (see subr.go: structargs)
- return nil
- }
-
- return s
-}
-
-// SliceBounds returns n's slice bounds: low, high, and max in expr[low:high:max].
-// n must be a slice expression. max is nil if n is a simple slice expression.
-func (n *node) SliceBounds() (low, high, max Node) {
- if n.List().Len() == 0 {
- return nil, nil, nil
- }
-
- switch n.Op() {
- case OSLICE, OSLICEARR, OSLICESTR:
- s := n.List().Slice()
- return s[0], s[1], nil
- case OSLICE3, OSLICE3ARR:
- s := n.List().Slice()
- return s[0], s[1], s[2]
- }
- base.Fatalf("SliceBounds op %v: %v", n.Op(), n)
- return nil, nil, nil
-}
-
-// SetSliceBounds sets n's slice bounds, where n is a slice expression.
-// n must be a slice expression. If max is non-nil, n must be a full slice expression.
-func (n *node) SetSliceBounds(low, high, max Node) {
- switch n.Op() {
- case OSLICE, OSLICEARR, OSLICESTR:
- if max != nil {
- base.Fatalf("SetSliceBounds %v given three bounds", n.Op())
- }
- s := n.List().Slice()
- if s == nil {
- if low == nil && high == nil {
- return
- }
- n.PtrList().Set2(low, high)
- return
- }
- s[0] = low
- s[1] = high
- return
- case OSLICE3, OSLICE3ARR:
- s := n.List().Slice()
- if s == nil {
- if low == nil && high == nil && max == nil {
- return
- }
- n.PtrList().Set3(low, high, max)
- return
- }
- s[0] = low
- s[1] = high
- s[2] = max
- return
- }
- base.Fatalf("SetSliceBounds op %v: %v", n.Op(), n)
-}
-
-// IsSlice3 reports whether o is a slice3 op (OSLICE3, OSLICE3ARR).
-// o must be a slicing op.
-func (o Op) IsSlice3() bool {
- switch o {
- case OSLICE, OSLICEARR, OSLICESTR:
- return false
- case OSLICE3, OSLICE3ARR:
- return true
- }
- base.Fatalf("IsSlice3 op %v", o)
- return false
-}
-
func IsConst(n Node, ct constant.Kind) bool {
return ConstType(n) == ct
}
-// Int64Val returns n as an int64.
-// n must be an integer or rune constant.
-func (n *node) Int64Val() int64 {
- if !IsConst(n, constant.Int) {
- base.Fatalf("Int64Val(%v)", n)
- }
- x, ok := constant.Int64Val(n.Val())
- if !ok {
- base.Fatalf("Int64Val(%v)", n)
- }
- return x
-}
-
-// CanInt64 reports whether it is safe to call Int64Val() on n.
-func (n *node) CanInt64() bool {
- if !IsConst(n, constant.Int) {
- return false
- }
-
- // if the value inside n cannot be represented as an int64, the
- // return value of Int64 is undefined
- _, ok := constant.Int64Val(n.Val())
- return ok
-}
-
-// Uint64Val returns n as an uint64.
-// n must be an integer or rune constant.
-func (n *node) Uint64Val() uint64 {
- if !IsConst(n, constant.Int) {
- base.Fatalf("Uint64Val(%v)", n)
- }
- x, ok := constant.Uint64Val(n.Val())
- if !ok {
- base.Fatalf("Uint64Val(%v)", n)
- }
- return x
-}
-
-// BoolVal returns n as a bool.
-// n must be a boolean constant.
-func (n *node) BoolVal() bool {
- if !IsConst(n, constant.Bool) {
- base.Fatalf("BoolVal(%v)", n)
- }
- return constant.BoolVal(n.Val())
-}
-
-// StringVal returns the value of a literal string Node as a string.
-// n must be a string constant.
-func (n *node) StringVal() string {
- if !IsConst(n, constant.String) {
- base.Fatalf("StringVal(%v)", n)
- }
- return constant.StringVal(n.Val())
-}
-
-// rawcopy returns a shallow copy of n.
-// Note: copy or sepcopy (rather than rawcopy) is usually the
-// correct choice (see comment with Node.copy, below).
-func (n *node) RawCopy() Node {
- copy := *n
- return ©
-}
-
-// sepcopy returns a separate shallow copy of n, with the copy's
-// Orig pointing to itself.
-func SepCopy(n Node) Node {
- n = n.RawCopy()
- n.SetOrig(n)
- return n
-}
-
-// copy returns shallow copy of n and adjusts the copy's Orig if
-// necessary: In general, if n.Orig points to itself, the copy's
-// Orig should point to itself as well. Otherwise, if n is modified,
-// the copy's Orig node appears modified, too, and then doesn't
-// represent the original node anymore.
-// (This caused the wrong complit Op to be used when printing error
-// messages; see issues #26855, #27765).
-func Copy(n Node) Node {
- copy := n.RawCopy()
- if n.Orig() == n {
- copy.SetOrig(copy)
- }
- return copy
-}
-
// isNil reports whether n represents the universal untyped zero value "nil".
func IsNil(n Node) bool {
// Check n.Orig because constant propagation may produce typed nil constants,
// which don't exist in the Go spec.
- return n.Orig().Op() == ONIL
+ return n != nil && Orig(n).Op() == ONIL
}
func IsBlank(n Node) bool {
@@ -1665,3 +671,129 @@ func IsBlank(n Node) bool {
func IsMethod(n Node) bool {
return n.Type().Recv() != nil
}
+
+func Nod(op Op, nleft, nright Node) Node {
+ return NodAt(base.Pos, op, nleft, nright)
+}
+
+func NodAt(pos src.XPos, op Op, nleft, nright Node) Node {
+ switch op {
+ default:
+ panic("NodAt " + op.String())
+ case OADD, OAND, OANDNOT, ODIV, OEQ, OGE, OGT, OLE,
+ OLSH, OLT, OMOD, OMUL, ONE, OOR, ORSH, OSUB, OXOR,
+ OCOPY, OCOMPLEX,
+ OEFACE:
+ return NewBinaryExpr(pos, op, nleft, nright)
+ case OADDR:
+ return NewAddrExpr(pos, nleft)
+ case OADDSTR:
+ return NewAddStringExpr(pos, nil)
+ case OANDAND, OOROR:
+ return NewLogicalExpr(pos, op, nleft, nright)
+ case OARRAYLIT, OCOMPLIT, OMAPLIT, OSTRUCTLIT, OSLICELIT:
+ var typ Ntype
+ if nright != nil {
+ typ = nright.(Ntype)
+ }
+ return NewCompLitExpr(pos, op, typ, nil)
+ case OAS, OSELRECV:
+ n := NewAssignStmt(pos, nleft, nright)
+ if op != OAS {
+ n.SetOp(op)
+ }
+ return n
+ case OAS2, OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV, OSELRECV2:
+ n := NewAssignListStmt(pos, op, nil, nil)
+ return n
+ case OASOP:
+ return NewAssignOpStmt(pos, OXXX, nleft, nright)
+ case OBITNOT, ONEG, ONOT, OPLUS, ORECV,
+ OALIGNOF, OCAP, OCLOSE, OIMAG, OLEN, ONEW, ONEWOBJ,
+ OOFFSETOF, OPANIC, OREAL, OSIZEOF,
+ OCHECKNIL, OCFUNC, OIDATA, OITAB, OSPTR, OVARDEF, OVARKILL, OVARLIVE:
+ if nright != nil {
+ panic("unary nright")
+ }
+ return NewUnaryExpr(pos, op, nleft)
+ case OBLOCK:
+ return NewBlockStmt(pos, nil)
+ case OBREAK, OCONTINUE, OFALL, OGOTO, ORETJMP:
+ return NewBranchStmt(pos, op, nil)
+ case OCALL, OCALLFUNC, OCALLINTER, OCALLMETH,
+ OAPPEND, ODELETE, OGETG, OMAKE, OPRINT, OPRINTN, ORECOVER:
+ return NewCallExpr(pos, op, nleft, nil)
+ case OCASE:
+ return NewCaseStmt(pos, nil, nil)
+ case OCONV, OCONVIFACE, OCONVNOP, ORUNESTR:
+ return NewConvExpr(pos, op, nil, nleft)
+ case ODCL, ODCLCONST, ODCLTYPE:
+ return NewDecl(pos, op, nleft)
+ case ODCLFUNC:
+ return NewFunc(pos)
+ case ODEFER, OGO:
+ return NewGoDeferStmt(pos, op, nleft)
+ case ODEREF:
+ return NewStarExpr(pos, nleft)
+ case ODOT, ODOTPTR, ODOTMETH, ODOTINTER, OXDOT:
+ return NewSelectorExpr(pos, op, nleft, nil)
+ case ODOTTYPE, ODOTTYPE2:
+ var typ Ntype
+ if nright != nil {
+ typ = nright.(Ntype)
+ }
+ n := NewTypeAssertExpr(pos, nleft, typ)
+ if op != ODOTTYPE {
+ n.SetOp(op)
+ }
+ return n
+ case OFOR:
+ return NewForStmt(pos, nil, nleft, nright, nil)
+ case OIF:
+ return NewIfStmt(pos, nleft, nil, nil)
+ case OINDEX, OINDEXMAP:
+ n := NewIndexExpr(pos, nleft, nright)
+ if op != OINDEX {
+ n.SetOp(op)
+ }
+ return n
+ case OINLMARK:
+ return NewInlineMarkStmt(pos, types.BADWIDTH)
+ case OKEY:
+ return NewKeyExpr(pos, nleft, nright)
+ case OSTRUCTKEY:
+ return NewStructKeyExpr(pos, nil, nleft)
+ case OLABEL:
+ return NewLabelStmt(pos, nil)
+ case OLITERAL, OTYPE, OIOTA:
+ return newNameAt(pos, op, nil)
+ case OMAKECHAN, OMAKEMAP, OMAKESLICE, OMAKESLICECOPY:
+ return NewMakeExpr(pos, op, nleft, nright)
+ case OMETHEXPR:
+ return NewMethodExpr(pos, nleft, nright)
+ case ONIL:
+ return NewNilExpr(pos)
+ case OPACK:
+ return NewPkgName(pos, nil, nil)
+ case OPAREN:
+ return NewParenExpr(pos, nleft)
+ case ORANGE:
+ return NewRangeStmt(pos, nil, nright, nil)
+ case ORESULT:
+ return NewResultExpr(pos, nil, types.BADWIDTH)
+ case ORETURN:
+ return NewReturnStmt(pos, nil)
+ case OSELECT:
+ return NewSelectStmt(pos, nil)
+ case OSEND:
+ return NewSendStmt(pos, nleft, nright)
+ case OSLICE, OSLICEARR, OSLICESTR, OSLICE3, OSLICE3ARR:
+ return NewSliceExpr(pos, op, nleft)
+ case OSLICEHEADER:
+ return NewSliceHeaderExpr(pos, nil, nleft, nil, nil)
+ case OSWITCH:
+ return NewSwitchStmt(pos, nleft, nil)
+ case OINLCALL:
+ return NewInlinedCallExpr(pos, nil, nil)
+ }
+}
diff --git a/src/cmd/compile/internal/ir/node_gen.go b/src/cmd/compile/internal/ir/node_gen.go
new file mode 100644
index 0000000000..39d8f03ddc
--- /dev/null
+++ b/src/cmd/compile/internal/ir/node_gen.go
@@ -0,0 +1,1009 @@
+// Code generated by mknode.go. DO NOT EDIT.
+
+package ir
+
+import "fmt"
+
+func (n *AddStringExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *AddStringExpr) copy() Node {
+ c := *n
+ c.init = c.init.Copy()
+ c.List_ = c.List_.Copy()
+ return &c
+}
+func (n *AddStringExpr) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.init, err, do)
+ err = maybeDoList(n.List_, err, do)
+ return err
+}
+func (n *AddStringExpr) editChildren(edit func(Node) Node) {
+ editList(n.init, edit)
+ editList(n.List_, edit)
+}
+
+func (n *AddrExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *AddrExpr) copy() Node {
+ c := *n
+ c.init = c.init.Copy()
+ return &c
+}
+func (n *AddrExpr) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.init, err, do)
+ err = maybeDo(n.X, err, do)
+ err = maybeDo(n.Alloc, err, do)
+ return err
+}
+func (n *AddrExpr) editChildren(edit func(Node) Node) {
+ editList(n.init, edit)
+ n.X = maybeEdit(n.X, edit)
+ n.Alloc = maybeEdit(n.Alloc, edit)
+}
+
+func (n *ArrayType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *ArrayType) copy() Node {
+ c := *n
+ return &c
+}
+func (n *ArrayType) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDo(n.Len, err, do)
+ err = maybeDo(n.Elem, err, do)
+ return err
+}
+func (n *ArrayType) editChildren(edit func(Node) Node) {
+ n.Len = maybeEdit(n.Len, edit)
+ n.Elem = maybeEdit(n.Elem, edit)
+}
+
+func (n *AssignListStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *AssignListStmt) copy() Node {
+ c := *n
+ c.init = c.init.Copy()
+ c.Lhs = c.Lhs.Copy()
+ c.Rhs = c.Rhs.Copy()
+ return &c
+}
+func (n *AssignListStmt) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.init, err, do)
+ err = maybeDoList(n.Lhs, err, do)
+ err = maybeDoList(n.Rhs, err, do)
+ return err
+}
+func (n *AssignListStmt) editChildren(edit func(Node) Node) {
+ editList(n.init, edit)
+ editList(n.Lhs, edit)
+ editList(n.Rhs, edit)
+}
+
+func (n *AssignOpStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *AssignOpStmt) copy() Node {
+ c := *n
+ c.init = c.init.Copy()
+ return &c
+}
+func (n *AssignOpStmt) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.init, err, do)
+ err = maybeDo(n.X, err, do)
+ err = maybeDo(n.Y, err, do)
+ return err
+}
+func (n *AssignOpStmt) editChildren(edit func(Node) Node) {
+ editList(n.init, edit)
+ n.X = maybeEdit(n.X, edit)
+ n.Y = maybeEdit(n.Y, edit)
+}
+
+func (n *AssignStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *AssignStmt) copy() Node {
+ c := *n
+ c.init = c.init.Copy()
+ return &c
+}
+func (n *AssignStmt) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.init, err, do)
+ err = maybeDo(n.X, err, do)
+ err = maybeDo(n.Y, err, do)
+ return err
+}
+func (n *AssignStmt) editChildren(edit func(Node) Node) {
+ editList(n.init, edit)
+ n.X = maybeEdit(n.X, edit)
+ n.Y = maybeEdit(n.Y, edit)
+}
+
+func (n *BinaryExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *BinaryExpr) copy() Node {
+ c := *n
+ c.init = c.init.Copy()
+ return &c
+}
+func (n *BinaryExpr) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.init, err, do)
+ err = maybeDo(n.X, err, do)
+ err = maybeDo(n.Y, err, do)
+ return err
+}
+func (n *BinaryExpr) editChildren(edit func(Node) Node) {
+ editList(n.init, edit)
+ n.X = maybeEdit(n.X, edit)
+ n.Y = maybeEdit(n.Y, edit)
+}
+
+func (n *BlockStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *BlockStmt) copy() Node {
+ c := *n
+ c.init = c.init.Copy()
+ c.List_ = c.List_.Copy()
+ return &c
+}
+func (n *BlockStmt) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.init, err, do)
+ err = maybeDoList(n.List_, err, do)
+ return err
+}
+func (n *BlockStmt) editChildren(edit func(Node) Node) {
+ editList(n.init, edit)
+ editList(n.List_, edit)
+}
+
+func (n *BranchStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *BranchStmt) copy() Node {
+ c := *n
+ c.init = c.init.Copy()
+ return &c
+}
+func (n *BranchStmt) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.init, err, do)
+ return err
+}
+func (n *BranchStmt) editChildren(edit func(Node) Node) {
+ editList(n.init, edit)
+}
+
+func (n *CallExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *CallExpr) copy() Node {
+ c := *n
+ c.init = c.init.Copy()
+ c.Args = c.Args.Copy()
+ c.Rargs = c.Rargs.Copy()
+ c.Body_ = c.Body_.Copy()
+ return &c
+}
+func (n *CallExpr) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.init, err, do)
+ err = maybeDo(n.X, err, do)
+ err = maybeDoList(n.Args, err, do)
+ err = maybeDoList(n.Rargs, err, do)
+ err = maybeDoList(n.Body_, err, do)
+ return err
+}
+func (n *CallExpr) editChildren(edit func(Node) Node) {
+ editList(n.init, edit)
+ n.X = maybeEdit(n.X, edit)
+ editList(n.Args, edit)
+ editList(n.Rargs, edit)
+ editList(n.Body_, edit)
+}
+
+func (n *CallPartExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *CallPartExpr) copy() Node {
+ c := *n
+ c.init = c.init.Copy()
+ return &c
+}
+func (n *CallPartExpr) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.init, err, do)
+ err = maybeDo(n.X, err, do)
+ return err
+}
+func (n *CallPartExpr) editChildren(edit func(Node) Node) {
+ editList(n.init, edit)
+ n.X = maybeEdit(n.X, edit)
+}
+
+func (n *CaseStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *CaseStmt) copy() Node {
+ c := *n
+ c.init = c.init.Copy()
+ c.Vars = c.Vars.Copy()
+ c.List_ = c.List_.Copy()
+ c.Body_ = c.Body_.Copy()
+ return &c
+}
+func (n *CaseStmt) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.init, err, do)
+ err = maybeDoList(n.Vars, err, do)
+ err = maybeDoList(n.List_, err, do)
+ err = maybeDo(n.Comm, err, do)
+ err = maybeDoList(n.Body_, err, do)
+ return err
+}
+func (n *CaseStmt) editChildren(edit func(Node) Node) {
+ editList(n.init, edit)
+ editList(n.Vars, edit)
+ editList(n.List_, edit)
+ n.Comm = maybeEdit(n.Comm, edit)
+ editList(n.Body_, edit)
+}
+
+func (n *ChanType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *ChanType) copy() Node {
+ c := *n
+ return &c
+}
+func (n *ChanType) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDo(n.Elem, err, do)
+ return err
+}
+func (n *ChanType) editChildren(edit func(Node) Node) {
+ n.Elem = maybeEdit(n.Elem, edit)
+}
+
+func (n *ClosureExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *ClosureExpr) copy() Node {
+ c := *n
+ c.init = c.init.Copy()
+ return &c
+}
+func (n *ClosureExpr) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.init, err, do)
+ return err
+}
+func (n *ClosureExpr) editChildren(edit func(Node) Node) {
+ editList(n.init, edit)
+}
+
+func (n *ClosureReadExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *ClosureReadExpr) copy() Node {
+ c := *n
+ c.init = c.init.Copy()
+ return &c
+}
+func (n *ClosureReadExpr) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.init, err, do)
+ return err
+}
+func (n *ClosureReadExpr) editChildren(edit func(Node) Node) {
+ editList(n.init, edit)
+}
+
+func (n *CompLitExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *CompLitExpr) copy() Node {
+ c := *n
+ c.init = c.init.Copy()
+ c.List_ = c.List_.Copy()
+ return &c
+}
+func (n *CompLitExpr) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.init, err, do)
+ err = maybeDo(n.Ntype, err, do)
+ err = maybeDoList(n.List_, err, do)
+ return err
+}
+func (n *CompLitExpr) editChildren(edit func(Node) Node) {
+ editList(n.init, edit)
+ n.Ntype = toNtype(maybeEdit(n.Ntype, edit))
+ editList(n.List_, edit)
+}
+
+func (n *ConstExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *ConstExpr) copy() Node {
+ c := *n
+ c.init = c.init.Copy()
+ return &c
+}
+func (n *ConstExpr) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.init, err, do)
+ return err
+}
+func (n *ConstExpr) editChildren(edit func(Node) Node) {
+ editList(n.init, edit)
+}
+
+func (n *ConvExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *ConvExpr) copy() Node {
+ c := *n
+ c.init = c.init.Copy()
+ return &c
+}
+func (n *ConvExpr) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.init, err, do)
+ err = maybeDo(n.X, err, do)
+ return err
+}
+func (n *ConvExpr) editChildren(edit func(Node) Node) {
+ editList(n.init, edit)
+ n.X = maybeEdit(n.X, edit)
+}
+
+func (n *Decl) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *Decl) copy() Node {
+ c := *n
+ return &c
+}
+func (n *Decl) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDo(n.X, err, do)
+ return err
+}
+func (n *Decl) editChildren(edit func(Node) Node) {
+ n.X = maybeEdit(n.X, edit)
+}
+
+func (n *ForStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *ForStmt) copy() Node {
+ c := *n
+ c.init = c.init.Copy()
+ c.Late = c.Late.Copy()
+ c.Body_ = c.Body_.Copy()
+ return &c
+}
+func (n *ForStmt) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.init, err, do)
+ err = maybeDo(n.Cond, err, do)
+ err = maybeDoList(n.Late, err, do)
+ err = maybeDo(n.Post, err, do)
+ err = maybeDoList(n.Body_, err, do)
+ return err
+}
+func (n *ForStmt) editChildren(edit func(Node) Node) {
+ editList(n.init, edit)
+ n.Cond = maybeEdit(n.Cond, edit)
+ editList(n.Late, edit)
+ n.Post = maybeEdit(n.Post, edit)
+ editList(n.Body_, edit)
+}
+
+func (n *Func) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *Func) copy() Node {
+ c := *n
+ c.Body_ = c.Body_.Copy()
+ return &c
+}
+func (n *Func) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.Body_, err, do)
+ return err
+}
+func (n *Func) editChildren(edit func(Node) Node) {
+ editList(n.Body_, edit)
+}
+
+func (n *FuncType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *FuncType) copy() Node {
+ c := *n
+ if c.Recv != nil {
+ c.Recv = c.Recv.copy()
+ }
+ c.Params = copyFields(c.Params)
+ c.Results = copyFields(c.Results)
+ return &c
+}
+func (n *FuncType) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoField(n.Recv, err, do)
+ err = maybeDoFields(n.Params, err, do)
+ err = maybeDoFields(n.Results, err, do)
+ return err
+}
+func (n *FuncType) editChildren(edit func(Node) Node) {
+ editField(n.Recv, edit)
+ editFields(n.Params, edit)
+ editFields(n.Results, edit)
+}
+
+func (n *GoDeferStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *GoDeferStmt) copy() Node {
+ c := *n
+ c.init = c.init.Copy()
+ return &c
+}
+func (n *GoDeferStmt) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.init, err, do)
+ err = maybeDo(n.Call, err, do)
+ return err
+}
+func (n *GoDeferStmt) editChildren(edit func(Node) Node) {
+ editList(n.init, edit)
+ n.Call = maybeEdit(n.Call, edit)
+}
+
+func (n *Ident) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *Ident) copy() Node {
+ c := *n
+ c.init = c.init.Copy()
+ return &c
+}
+func (n *Ident) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.init, err, do)
+ return err
+}
+func (n *Ident) editChildren(edit func(Node) Node) {
+ editList(n.init, edit)
+}
+
+func (n *IfStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *IfStmt) copy() Node {
+ c := *n
+ c.init = c.init.Copy()
+ c.Body_ = c.Body_.Copy()
+ c.Else = c.Else.Copy()
+ return &c
+}
+func (n *IfStmt) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.init, err, do)
+ err = maybeDo(n.Cond, err, do)
+ err = maybeDoList(n.Body_, err, do)
+ err = maybeDoList(n.Else, err, do)
+ return err
+}
+func (n *IfStmt) editChildren(edit func(Node) Node) {
+ editList(n.init, edit)
+ n.Cond = maybeEdit(n.Cond, edit)
+ editList(n.Body_, edit)
+ editList(n.Else, edit)
+}
+
+func (n *IndexExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *IndexExpr) copy() Node {
+ c := *n
+ c.init = c.init.Copy()
+ return &c
+}
+func (n *IndexExpr) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.init, err, do)
+ err = maybeDo(n.X, err, do)
+ err = maybeDo(n.Index, err, do)
+ return err
+}
+func (n *IndexExpr) editChildren(edit func(Node) Node) {
+ editList(n.init, edit)
+ n.X = maybeEdit(n.X, edit)
+ n.Index = maybeEdit(n.Index, edit)
+}
+
+func (n *InlineMarkStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *InlineMarkStmt) copy() Node {
+ c := *n
+ c.init = c.init.Copy()
+ return &c
+}
+func (n *InlineMarkStmt) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.init, err, do)
+ return err
+}
+func (n *InlineMarkStmt) editChildren(edit func(Node) Node) {
+ editList(n.init, edit)
+}
+
+func (n *InlinedCallExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *InlinedCallExpr) copy() Node {
+ c := *n
+ c.init = c.init.Copy()
+ c.Body_ = c.Body_.Copy()
+ c.ReturnVars = c.ReturnVars.Copy()
+ return &c
+}
+func (n *InlinedCallExpr) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.init, err, do)
+ err = maybeDoList(n.Body_, err, do)
+ err = maybeDoList(n.ReturnVars, err, do)
+ return err
+}
+func (n *InlinedCallExpr) editChildren(edit func(Node) Node) {
+ editList(n.init, edit)
+ editList(n.Body_, edit)
+ editList(n.ReturnVars, edit)
+}
+
+func (n *InterfaceType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *InterfaceType) copy() Node {
+ c := *n
+ c.Methods = copyFields(c.Methods)
+ return &c
+}
+func (n *InterfaceType) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoFields(n.Methods, err, do)
+ return err
+}
+func (n *InterfaceType) editChildren(edit func(Node) Node) {
+ editFields(n.Methods, edit)
+}
+
+func (n *KeyExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *KeyExpr) copy() Node {
+ c := *n
+ c.init = c.init.Copy()
+ return &c
+}
+func (n *KeyExpr) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.init, err, do)
+ err = maybeDo(n.Key, err, do)
+ err = maybeDo(n.Value, err, do)
+ return err
+}
+func (n *KeyExpr) editChildren(edit func(Node) Node) {
+ editList(n.init, edit)
+ n.Key = maybeEdit(n.Key, edit)
+ n.Value = maybeEdit(n.Value, edit)
+}
+
+func (n *LabelStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *LabelStmt) copy() Node {
+ c := *n
+ c.init = c.init.Copy()
+ return &c
+}
+func (n *LabelStmt) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.init, err, do)
+ return err
+}
+func (n *LabelStmt) editChildren(edit func(Node) Node) {
+ editList(n.init, edit)
+}
+
+func (n *LogicalExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *LogicalExpr) copy() Node {
+ c := *n
+ c.init = c.init.Copy()
+ return &c
+}
+func (n *LogicalExpr) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.init, err, do)
+ err = maybeDo(n.X, err, do)
+ err = maybeDo(n.Y, err, do)
+ return err
+}
+func (n *LogicalExpr) editChildren(edit func(Node) Node) {
+ editList(n.init, edit)
+ n.X = maybeEdit(n.X, edit)
+ n.Y = maybeEdit(n.Y, edit)
+}
+
+func (n *MakeExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *MakeExpr) copy() Node {
+ c := *n
+ c.init = c.init.Copy()
+ return &c
+}
+func (n *MakeExpr) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.init, err, do)
+ err = maybeDo(n.Len, err, do)
+ err = maybeDo(n.Cap, err, do)
+ return err
+}
+func (n *MakeExpr) editChildren(edit func(Node) Node) {
+ editList(n.init, edit)
+ n.Len = maybeEdit(n.Len, edit)
+ n.Cap = maybeEdit(n.Cap, edit)
+}
+
+func (n *MapType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *MapType) copy() Node {
+ c := *n
+ return &c
+}
+func (n *MapType) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDo(n.Key, err, do)
+ err = maybeDo(n.Elem, err, do)
+ return err
+}
+func (n *MapType) editChildren(edit func(Node) Node) {
+ n.Key = maybeEdit(n.Key, edit)
+ n.Elem = maybeEdit(n.Elem, edit)
+}
+
+func (n *MethodExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *MethodExpr) copy() Node {
+ c := *n
+ c.init = c.init.Copy()
+ return &c
+}
+func (n *MethodExpr) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.init, err, do)
+ err = maybeDo(n.X, err, do)
+ err = maybeDo(n.M, err, do)
+ return err
+}
+func (n *MethodExpr) editChildren(edit func(Node) Node) {
+ editList(n.init, edit)
+ n.X = maybeEdit(n.X, edit)
+ n.M = maybeEdit(n.M, edit)
+}
+
+func (n *Name) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *Name) copy() Node {
+ c := *n
+ return &c
+}
+func (n *Name) doChildren(do func(Node) error) error {
+ var err error
+ return err
+}
+func (n *Name) editChildren(edit func(Node) Node) {
+}
+
+func (n *NilExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *NilExpr) copy() Node {
+ c := *n
+ c.init = c.init.Copy()
+ return &c
+}
+func (n *NilExpr) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.init, err, do)
+ return err
+}
+func (n *NilExpr) editChildren(edit func(Node) Node) {
+ editList(n.init, edit)
+}
+
+func (n *ParenExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *ParenExpr) copy() Node {
+ c := *n
+ c.init = c.init.Copy()
+ return &c
+}
+func (n *ParenExpr) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.init, err, do)
+ err = maybeDo(n.X, err, do)
+ return err
+}
+func (n *ParenExpr) editChildren(edit func(Node) Node) {
+ editList(n.init, edit)
+ n.X = maybeEdit(n.X, edit)
+}
+
+func (n *PkgName) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *PkgName) copy() Node {
+ c := *n
+ return &c
+}
+func (n *PkgName) doChildren(do func(Node) error) error {
+ var err error
+ return err
+}
+func (n *PkgName) editChildren(edit func(Node) Node) {
+}
+
+func (n *RangeStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *RangeStmt) copy() Node {
+ c := *n
+ c.init = c.init.Copy()
+ c.Vars = c.Vars.Copy()
+ c.Body_ = c.Body_.Copy()
+ return &c
+}
+func (n *RangeStmt) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.init, err, do)
+ err = maybeDoList(n.Vars, err, do)
+ err = maybeDo(n.X, err, do)
+ err = maybeDoList(n.Body_, err, do)
+ return err
+}
+func (n *RangeStmt) editChildren(edit func(Node) Node) {
+ editList(n.init, edit)
+ editList(n.Vars, edit)
+ n.X = maybeEdit(n.X, edit)
+ editList(n.Body_, edit)
+}
+
+func (n *ResultExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *ResultExpr) copy() Node {
+ c := *n
+ c.init = c.init.Copy()
+ return &c
+}
+func (n *ResultExpr) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.init, err, do)
+ return err
+}
+func (n *ResultExpr) editChildren(edit func(Node) Node) {
+ editList(n.init, edit)
+}
+
+func (n *ReturnStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *ReturnStmt) copy() Node {
+ c := *n
+ c.init = c.init.Copy()
+ c.Results = c.Results.Copy()
+ return &c
+}
+func (n *ReturnStmt) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.init, err, do)
+ err = maybeDoList(n.Results, err, do)
+ return err
+}
+func (n *ReturnStmt) editChildren(edit func(Node) Node) {
+ editList(n.init, edit)
+ editList(n.Results, edit)
+}
+
+func (n *SelectStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *SelectStmt) copy() Node {
+ c := *n
+ c.init = c.init.Copy()
+ c.Cases = c.Cases.Copy()
+ c.Compiled = c.Compiled.Copy()
+ return &c
+}
+func (n *SelectStmt) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.init, err, do)
+ err = maybeDoList(n.Cases, err, do)
+ err = maybeDoList(n.Compiled, err, do)
+ return err
+}
+func (n *SelectStmt) editChildren(edit func(Node) Node) {
+ editList(n.init, edit)
+ editList(n.Cases, edit)
+ editList(n.Compiled, edit)
+}
+
+func (n *SelectorExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *SelectorExpr) copy() Node {
+ c := *n
+ c.init = c.init.Copy()
+ return &c
+}
+func (n *SelectorExpr) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.init, err, do)
+ err = maybeDo(n.X, err, do)
+ return err
+}
+func (n *SelectorExpr) editChildren(edit func(Node) Node) {
+ editList(n.init, edit)
+ n.X = maybeEdit(n.X, edit)
+}
+
+func (n *SendStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *SendStmt) copy() Node {
+ c := *n
+ c.init = c.init.Copy()
+ return &c
+}
+func (n *SendStmt) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.init, err, do)
+ err = maybeDo(n.Chan, err, do)
+ err = maybeDo(n.Value, err, do)
+ return err
+}
+func (n *SendStmt) editChildren(edit func(Node) Node) {
+ editList(n.init, edit)
+ n.Chan = maybeEdit(n.Chan, edit)
+ n.Value = maybeEdit(n.Value, edit)
+}
+
+func (n *SliceExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *SliceExpr) copy() Node {
+ c := *n
+ c.init = c.init.Copy()
+ c.List_ = c.List_.Copy()
+ return &c
+}
+func (n *SliceExpr) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.init, err, do)
+ err = maybeDo(n.X, err, do)
+ err = maybeDoList(n.List_, err, do)
+ return err
+}
+func (n *SliceExpr) editChildren(edit func(Node) Node) {
+ editList(n.init, edit)
+ n.X = maybeEdit(n.X, edit)
+ editList(n.List_, edit)
+}
+
+func (n *SliceHeaderExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *SliceHeaderExpr) copy() Node {
+ c := *n
+ c.init = c.init.Copy()
+ c.LenCap_ = c.LenCap_.Copy()
+ return &c
+}
+func (n *SliceHeaderExpr) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.init, err, do)
+ err = maybeDo(n.Ptr, err, do)
+ err = maybeDoList(n.LenCap_, err, do)
+ return err
+}
+func (n *SliceHeaderExpr) editChildren(edit func(Node) Node) {
+ editList(n.init, edit)
+ n.Ptr = maybeEdit(n.Ptr, edit)
+ editList(n.LenCap_, edit)
+}
+
+func (n *SliceType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *SliceType) copy() Node {
+ c := *n
+ return &c
+}
+func (n *SliceType) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDo(n.Elem, err, do)
+ return err
+}
+func (n *SliceType) editChildren(edit func(Node) Node) {
+ n.Elem = maybeEdit(n.Elem, edit)
+}
+
+func (n *StarExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *StarExpr) copy() Node {
+ c := *n
+ c.init = c.init.Copy()
+ return &c
+}
+func (n *StarExpr) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.init, err, do)
+ err = maybeDo(n.X, err, do)
+ return err
+}
+func (n *StarExpr) editChildren(edit func(Node) Node) {
+ editList(n.init, edit)
+ n.X = maybeEdit(n.X, edit)
+}
+
+func (n *StructKeyExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *StructKeyExpr) copy() Node {
+ c := *n
+ c.init = c.init.Copy()
+ return &c
+}
+func (n *StructKeyExpr) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.init, err, do)
+ err = maybeDo(n.Value, err, do)
+ return err
+}
+func (n *StructKeyExpr) editChildren(edit func(Node) Node) {
+ editList(n.init, edit)
+ n.Value = maybeEdit(n.Value, edit)
+}
+
+func (n *StructType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *StructType) copy() Node {
+ c := *n
+ c.Fields = copyFields(c.Fields)
+ return &c
+}
+func (n *StructType) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoFields(n.Fields, err, do)
+ return err
+}
+func (n *StructType) editChildren(edit func(Node) Node) {
+ editFields(n.Fields, edit)
+}
+
+func (n *SwitchStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *SwitchStmt) copy() Node {
+ c := *n
+ c.init = c.init.Copy()
+ c.Cases = c.Cases.Copy()
+ c.Compiled = c.Compiled.Copy()
+ return &c
+}
+func (n *SwitchStmt) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.init, err, do)
+ err = maybeDo(n.Tag, err, do)
+ err = maybeDoList(n.Cases, err, do)
+ err = maybeDoList(n.Compiled, err, do)
+ return err
+}
+func (n *SwitchStmt) editChildren(edit func(Node) Node) {
+ editList(n.init, edit)
+ n.Tag = maybeEdit(n.Tag, edit)
+ editList(n.Cases, edit)
+ editList(n.Compiled, edit)
+}
+
+func (n *TypeAssertExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *TypeAssertExpr) copy() Node {
+ c := *n
+ c.init = c.init.Copy()
+ c.Itab = c.Itab.Copy()
+ return &c
+}
+func (n *TypeAssertExpr) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.init, err, do)
+ err = maybeDo(n.X, err, do)
+ err = maybeDo(n.Ntype, err, do)
+ err = maybeDoList(n.Itab, err, do)
+ return err
+}
+func (n *TypeAssertExpr) editChildren(edit func(Node) Node) {
+ editList(n.init, edit)
+ n.X = maybeEdit(n.X, edit)
+ n.Ntype = maybeEdit(n.Ntype, edit)
+ editList(n.Itab, edit)
+}
+
+func (n *TypeSwitchGuard) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *TypeSwitchGuard) copy() Node {
+ c := *n
+ return &c
+}
+func (n *TypeSwitchGuard) doChildren(do func(Node) error) error {
+ var err error
+ if n.Tag != nil {
+ err = maybeDo(n.Tag, err, do)
+ }
+ err = maybeDo(n.X, err, do)
+ return err
+}
+func (n *TypeSwitchGuard) editChildren(edit func(Node) Node) {
+ if n.Tag != nil {
+ n.Tag = edit(n.Tag).(*Ident)
+ }
+ n.X = maybeEdit(n.X, edit)
+}
+
+func (n *UnaryExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *UnaryExpr) copy() Node {
+ c := *n
+ c.init = c.init.Copy()
+ return &c
+}
+func (n *UnaryExpr) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.init, err, do)
+ err = maybeDo(n.X, err, do)
+ return err
+}
+func (n *UnaryExpr) editChildren(edit func(Node) Node) {
+ editList(n.init, edit)
+ n.X = maybeEdit(n.X, edit)
+}
+
+func (n *typeNode) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *typeNode) copy() Node {
+ c := *n
+ return &c
+}
+func (n *typeNode) doChildren(do func(Node) error) error {
+ var err error
+ return err
+}
+func (n *typeNode) editChildren(edit func(Node) Node) {
+}
diff --git a/src/cmd/compile/internal/ir/op_string.go b/src/cmd/compile/internal/ir/op_string.go
index d0d3778357..bb5e16fbbc 100644
--- a/src/cmd/compile/internal/ir/op_string.go
+++ b/src/cmd/compile/internal/ir/op_string.go
@@ -56,118 +56,117 @@ func _() {
_ = x[OCOPY-45]
_ = x[ODCL-46]
_ = x[ODCLFUNC-47]
- _ = x[ODCLFIELD-48]
- _ = x[ODCLCONST-49]
- _ = x[ODCLTYPE-50]
- _ = x[ODELETE-51]
- _ = x[ODOT-52]
- _ = x[ODOTPTR-53]
- _ = x[ODOTMETH-54]
- _ = x[ODOTINTER-55]
- _ = x[OXDOT-56]
- _ = x[ODOTTYPE-57]
- _ = x[ODOTTYPE2-58]
- _ = x[OEQ-59]
- _ = x[ONE-60]
- _ = x[OLT-61]
- _ = x[OLE-62]
- _ = x[OGE-63]
- _ = x[OGT-64]
- _ = x[ODEREF-65]
- _ = x[OINDEX-66]
- _ = x[OINDEXMAP-67]
- _ = x[OKEY-68]
- _ = x[OSTRUCTKEY-69]
- _ = x[OLEN-70]
- _ = x[OMAKE-71]
- _ = x[OMAKECHAN-72]
- _ = x[OMAKEMAP-73]
- _ = x[OMAKESLICE-74]
- _ = x[OMAKESLICECOPY-75]
- _ = x[OMUL-76]
- _ = x[ODIV-77]
- _ = x[OMOD-78]
- _ = x[OLSH-79]
- _ = x[ORSH-80]
- _ = x[OAND-81]
- _ = x[OANDNOT-82]
- _ = x[ONEW-83]
- _ = x[ONEWOBJ-84]
- _ = x[ONOT-85]
- _ = x[OBITNOT-86]
- _ = x[OPLUS-87]
- _ = x[ONEG-88]
- _ = x[OOROR-89]
- _ = x[OPANIC-90]
- _ = x[OPRINT-91]
- _ = x[OPRINTN-92]
- _ = x[OPAREN-93]
- _ = x[OSEND-94]
- _ = x[OSLICE-95]
- _ = x[OSLICEARR-96]
- _ = x[OSLICESTR-97]
- _ = x[OSLICE3-98]
- _ = x[OSLICE3ARR-99]
- _ = x[OSLICEHEADER-100]
- _ = x[ORECOVER-101]
- _ = x[ORECV-102]
- _ = x[ORUNESTR-103]
- _ = x[OSELRECV-104]
- _ = x[OSELRECV2-105]
- _ = x[OIOTA-106]
- _ = x[OREAL-107]
- _ = x[OIMAG-108]
- _ = x[OCOMPLEX-109]
- _ = x[OALIGNOF-110]
- _ = x[OOFFSETOF-111]
- _ = x[OSIZEOF-112]
- _ = x[OMETHEXPR-113]
+ _ = x[ODCLCONST-48]
+ _ = x[ODCLTYPE-49]
+ _ = x[ODELETE-50]
+ _ = x[ODOT-51]
+ _ = x[ODOTPTR-52]
+ _ = x[ODOTMETH-53]
+ _ = x[ODOTINTER-54]
+ _ = x[OXDOT-55]
+ _ = x[ODOTTYPE-56]
+ _ = x[ODOTTYPE2-57]
+ _ = x[OEQ-58]
+ _ = x[ONE-59]
+ _ = x[OLT-60]
+ _ = x[OLE-61]
+ _ = x[OGE-62]
+ _ = x[OGT-63]
+ _ = x[ODEREF-64]
+ _ = x[OINDEX-65]
+ _ = x[OINDEXMAP-66]
+ _ = x[OKEY-67]
+ _ = x[OSTRUCTKEY-68]
+ _ = x[OLEN-69]
+ _ = x[OMAKE-70]
+ _ = x[OMAKECHAN-71]
+ _ = x[OMAKEMAP-72]
+ _ = x[OMAKESLICE-73]
+ _ = x[OMAKESLICECOPY-74]
+ _ = x[OMUL-75]
+ _ = x[ODIV-76]
+ _ = x[OMOD-77]
+ _ = x[OLSH-78]
+ _ = x[ORSH-79]
+ _ = x[OAND-80]
+ _ = x[OANDNOT-81]
+ _ = x[ONEW-82]
+ _ = x[ONEWOBJ-83]
+ _ = x[ONOT-84]
+ _ = x[OBITNOT-85]
+ _ = x[OPLUS-86]
+ _ = x[ONEG-87]
+ _ = x[OOROR-88]
+ _ = x[OPANIC-89]
+ _ = x[OPRINT-90]
+ _ = x[OPRINTN-91]
+ _ = x[OPAREN-92]
+ _ = x[OSEND-93]
+ _ = x[OSLICE-94]
+ _ = x[OSLICEARR-95]
+ _ = x[OSLICESTR-96]
+ _ = x[OSLICE3-97]
+ _ = x[OSLICE3ARR-98]
+ _ = x[OSLICEHEADER-99]
+ _ = x[ORECOVER-100]
+ _ = x[ORECV-101]
+ _ = x[ORUNESTR-102]
+ _ = x[OSELRECV-103]
+ _ = x[OSELRECV2-104]
+ _ = x[OIOTA-105]
+ _ = x[OREAL-106]
+ _ = x[OIMAG-107]
+ _ = x[OCOMPLEX-108]
+ _ = x[OALIGNOF-109]
+ _ = x[OOFFSETOF-110]
+ _ = x[OSIZEOF-111]
+ _ = x[OMETHEXPR-112]
+ _ = x[OSTMTEXPR-113]
_ = x[OBLOCK-114]
_ = x[OBREAK-115]
_ = x[OCASE-116]
_ = x[OCONTINUE-117]
_ = x[ODEFER-118]
- _ = x[OEMPTY-119]
- _ = x[OFALL-120]
- _ = x[OFOR-121]
- _ = x[OFORUNTIL-122]
- _ = x[OGOTO-123]
- _ = x[OIF-124]
- _ = x[OLABEL-125]
- _ = x[OGO-126]
- _ = x[ORANGE-127]
- _ = x[ORETURN-128]
- _ = x[OSELECT-129]
- _ = x[OSWITCH-130]
- _ = x[OTYPESW-131]
- _ = x[OTCHAN-132]
- _ = x[OTMAP-133]
- _ = x[OTSTRUCT-134]
- _ = x[OTINTER-135]
- _ = x[OTFUNC-136]
- _ = x[OTARRAY-137]
- _ = x[ODDD-138]
- _ = x[OINLCALL-139]
- _ = x[OEFACE-140]
- _ = x[OITAB-141]
- _ = x[OIDATA-142]
- _ = x[OSPTR-143]
- _ = x[OCLOSUREVAR-144]
- _ = x[OCFUNC-145]
- _ = x[OCHECKNIL-146]
- _ = x[OVARDEF-147]
- _ = x[OVARKILL-148]
- _ = x[OVARLIVE-149]
- _ = x[ORESULT-150]
- _ = x[OINLMARK-151]
- _ = x[ORETJMP-152]
- _ = x[OGETG-153]
- _ = x[OEND-154]
+ _ = x[OFALL-119]
+ _ = x[OFOR-120]
+ _ = x[OFORUNTIL-121]
+ _ = x[OGOTO-122]
+ _ = x[OIF-123]
+ _ = x[OLABEL-124]
+ _ = x[OGO-125]
+ _ = x[ORANGE-126]
+ _ = x[ORETURN-127]
+ _ = x[OSELECT-128]
+ _ = x[OSWITCH-129]
+ _ = x[OTYPESW-130]
+ _ = x[OTCHAN-131]
+ _ = x[OTMAP-132]
+ _ = x[OTSTRUCT-133]
+ _ = x[OTINTER-134]
+ _ = x[OTFUNC-135]
+ _ = x[OTARRAY-136]
+ _ = x[OTSLICE-137]
+ _ = x[OINLCALL-138]
+ _ = x[OEFACE-139]
+ _ = x[OITAB-140]
+ _ = x[OIDATA-141]
+ _ = x[OSPTR-142]
+ _ = x[OCLOSUREREAD-143]
+ _ = x[OCFUNC-144]
+ _ = x[OCHECKNIL-145]
+ _ = x[OVARDEF-146]
+ _ = x[OVARKILL-147]
+ _ = x[OVARLIVE-148]
+ _ = x[ORESULT-149]
+ _ = x[OINLMARK-150]
+ _ = x[ORETJMP-151]
+ _ = x[OGETG-152]
+ _ = x[OEND-153]
}
-const _Op_name = "XXXNAMENONAMETYPEPACKLITERALNILADDSUBORXORADDSTRADDRANDANDAPPENDBYTES2STRBYTES2STRTMPRUNES2STRSTR2BYTESSTR2BYTESTMPSTR2RUNESASAS2AS2DOTTYPEAS2FUNCAS2MAPRAS2RECVASOPCALLCALLFUNCCALLMETHCALLINTERCALLPARTCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVNOPCOPYDCLDCLFUNCDCLFIELDDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTDEREFINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMAKESLICECOPYMULDIVMODLSHRSHANDANDNOTNEWNEWOBJNOTBITNOTPLUSNEGORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICE3SLICE3ARRSLICEHEADERRECOVERRECVRUNESTRSELRECVSELRECV2IOTAREALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFMETHEXPRBLOCKBREAKCASECONTINUEDEFEREMPTYFALLFORFORUNTILGOTOIFLABELGORANGERETURNSELECTSWITCHTYPESWTCHANTMAPTSTRUCTTINTERTFUNCTARRAYDDDINLCALLEFACEITABIDATASPTRCLOSUREVARCFUNCCHECKNILVARDEFVARKILLVARLIVERESULTINLMARKRETJMPGETGEND"
+const _Op_name = "XXXNAMENONAMETYPEPACKLITERALNILADDSUBORXORADDSTRADDRANDANDAPPENDBYTES2STRBYTES2STRTMPRUNES2STRSTR2BYTESSTR2BYTESTMPSTR2RUNESASAS2AS2DOTTYPEAS2FUNCAS2MAPRAS2RECVASOPCALLCALLFUNCCALLMETHCALLINTERCALLPARTCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVNOPCOPYDCLDCLFUNCDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTDEREFINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMAKESLICECOPYMULDIVMODLSHRSHANDANDNOTNEWNEWOBJNOTBITNOTPLUSNEGORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICE3SLICE3ARRSLICEHEADERRECOVERRECVRUNESTRSELRECVSELRECV2IOTAREALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFMETHEXPRSTMTEXPRBLOCKBREAKCASECONTINUEDEFERFALLFORFORUNTILGOTOIFLABELGORANGERETURNSELECTSWITCHTYPESWTCHANTMAPTSTRUCTTINTERTFUNCTARRAYTSLICEINLCALLEFACEITABIDATASPTRCLOSUREREADCFUNCCHECKNILVARDEFVARKILLVARLIVERESULTINLMARKRETJMPGETGEND"
-var _Op_index = [...]uint16{0, 3, 7, 13, 17, 21, 28, 31, 34, 37, 39, 42, 48, 52, 58, 64, 73, 85, 94, 103, 115, 124, 126, 129, 139, 146, 153, 160, 164, 168, 176, 184, 193, 201, 204, 209, 216, 223, 229, 238, 246, 254, 260, 264, 273, 280, 284, 287, 294, 302, 310, 317, 323, 326, 332, 339, 347, 351, 358, 366, 368, 370, 372, 374, 376, 378, 383, 388, 396, 399, 408, 411, 415, 423, 430, 439, 452, 455, 458, 461, 464, 467, 470, 476, 479, 485, 488, 494, 498, 501, 505, 510, 515, 521, 526, 530, 535, 543, 551, 557, 566, 577, 584, 588, 595, 602, 610, 614, 618, 622, 629, 636, 644, 650, 658, 663, 668, 672, 680, 685, 690, 694, 697, 705, 709, 711, 716, 718, 723, 729, 735, 741, 747, 752, 756, 763, 769, 774, 780, 783, 790, 795, 799, 804, 808, 818, 823, 831, 837, 844, 851, 857, 864, 870, 874, 877}
+var _Op_index = [...]uint16{0, 3, 7, 13, 17, 21, 28, 31, 34, 37, 39, 42, 48, 52, 58, 64, 73, 85, 94, 103, 115, 124, 126, 129, 139, 146, 153, 160, 164, 168, 176, 184, 193, 201, 204, 209, 216, 223, 229, 238, 246, 254, 260, 264, 273, 280, 284, 287, 294, 302, 309, 315, 318, 324, 331, 339, 343, 350, 358, 360, 362, 364, 366, 368, 370, 375, 380, 388, 391, 400, 403, 407, 415, 422, 431, 444, 447, 450, 453, 456, 459, 462, 468, 471, 477, 480, 486, 490, 493, 497, 502, 507, 513, 518, 522, 527, 535, 543, 549, 558, 569, 576, 580, 587, 594, 602, 606, 610, 614, 621, 628, 636, 642, 650, 658, 663, 668, 672, 680, 685, 689, 692, 700, 704, 706, 711, 713, 718, 724, 730, 736, 742, 747, 751, 758, 764, 769, 775, 781, 788, 793, 797, 802, 806, 817, 822, 830, 836, 843, 850, 856, 863, 869, 873, 876}
func (i Op) String() string {
if i >= Op(len(_Op_index)-1) {
diff --git a/src/cmd/compile/internal/ir/sizeof_test.go b/src/cmd/compile/internal/ir/sizeof_test.go
index 0a9542fa44..181f1462fe 100644
--- a/src/cmd/compile/internal/ir/sizeof_test.go
+++ b/src/cmd/compile/internal/ir/sizeof_test.go
@@ -20,10 +20,8 @@ func TestSizeof(t *testing.T) {
_32bit uintptr // size on 32bit platforms
_64bit uintptr // size on 64bit platforms
}{
- {Func{}, 152, 280},
- {Name{}, 44, 80},
- {Param{}, 44, 88},
- {node{}, 88, 152},
+ {Func{}, 168, 288},
+ {Name{}, 124, 216},
}
for _, tt := range tests {
diff --git a/src/cmd/compile/internal/ir/stmt.go b/src/cmd/compile/internal/ir/stmt.go
new file mode 100644
index 0000000000..f41c50c92b
--- /dev/null
+++ b/src/cmd/compile/internal/ir/stmt.go
@@ -0,0 +1,541 @@
+// Copyright 2020 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 ir
+
+import (
+ "cmd/compile/internal/types"
+ "cmd/internal/src"
+)
+
+// A Decl is a declaration of a const, type, or var. (A declared func is a Func.)
+type Decl struct {
+ miniNode
+ X Node // the thing being declared
+}
+
+func NewDecl(pos src.XPos, op Op, x Node) *Decl {
+ n := &Decl{X: x}
+ n.pos = pos
+ switch op {
+ default:
+ panic("invalid Decl op " + op.String())
+ case ODCL, ODCLCONST, ODCLTYPE:
+ n.op = op
+ }
+ return n
+}
+
+func (*Decl) isStmt() {}
+
+func (n *Decl) Left() Node { return n.X }
+func (n *Decl) SetLeft(x Node) { n.X = x }
+
+// A Stmt is a Node that can appear as a statement.
+// This includes statement-like expressions such as f().
+//
+// (It's possible it should include <-c, but that would require
+// splitting ORECV out of UnaryExpr, which hasn't yet been
+// necessary. Maybe instead we will introduce ExprStmt at
+// some point.)
+type Stmt interface {
+ Node
+ isStmt()
+}
+
+// A miniStmt is a miniNode with extra fields common to statements.
+type miniStmt struct {
+ miniNode
+ init Nodes
+}
+
+func (*miniStmt) isStmt() {}
+
+func (n *miniStmt) Init() Nodes { return n.init }
+func (n *miniStmt) SetInit(x Nodes) { n.init = x }
+func (n *miniStmt) PtrInit() *Nodes { return &n.init }
+func (n *miniStmt) HasCall() bool { return n.bits&miniHasCall != 0 }
+func (n *miniStmt) SetHasCall(b bool) { n.bits.set(miniHasCall, b) }
+
+// An AssignListStmt is an assignment statement with
+// more than one item on at least one side: Lhs = Rhs.
+// If Def is true, the assignment is a :=.
+type AssignListStmt struct {
+ miniStmt
+ Lhs Nodes
+ Def bool
+ Rhs Nodes
+ Offset_ int64 // for initorder
+}
+
+func NewAssignListStmt(pos src.XPos, op Op, lhs, rhs []Node) *AssignListStmt {
+ n := &AssignListStmt{}
+ n.pos = pos
+ n.SetOp(op)
+ n.Lhs.Set(lhs)
+ n.Rhs.Set(rhs)
+ n.Offset_ = types.BADWIDTH
+ return n
+}
+
+func (n *AssignListStmt) List() Nodes { return n.Lhs }
+func (n *AssignListStmt) PtrList() *Nodes { return &n.Lhs }
+func (n *AssignListStmt) SetList(x Nodes) { n.Lhs = x }
+func (n *AssignListStmt) Rlist() Nodes { return n.Rhs }
+func (n *AssignListStmt) PtrRlist() *Nodes { return &n.Rhs }
+func (n *AssignListStmt) SetRlist(x Nodes) { n.Rhs = x }
+func (n *AssignListStmt) Colas() bool { return n.Def }
+func (n *AssignListStmt) SetColas(x bool) { n.Def = x }
+func (n *AssignListStmt) Offset() int64 { return n.Offset_ }
+func (n *AssignListStmt) SetOffset(x int64) { n.Offset_ = x }
+
+func (n *AssignListStmt) SetOp(op Op) {
+ switch op {
+ default:
+ panic(n.no("SetOp " + op.String()))
+ case OAS2, OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV, OSELRECV2:
+ n.op = op
+ }
+}
+
+// An AssignStmt is a simple assignment statement: X = Y.
+// If Def is true, the assignment is a :=.
+type AssignStmt struct {
+ miniStmt
+ X Node
+ Def bool
+ Y Node
+ Offset_ int64 // for initorder
+}
+
+func NewAssignStmt(pos src.XPos, x, y Node) *AssignStmt {
+ n := &AssignStmt{X: x, Y: y}
+ n.pos = pos
+ n.op = OAS
+ n.Offset_ = types.BADWIDTH
+ return n
+}
+
+func (n *AssignStmt) Left() Node { return n.X }
+func (n *AssignStmt) SetLeft(x Node) { n.X = x }
+func (n *AssignStmt) Right() Node { return n.Y }
+func (n *AssignStmt) SetRight(y Node) { n.Y = y }
+func (n *AssignStmt) Colas() bool { return n.Def }
+func (n *AssignStmt) SetColas(x bool) { n.Def = x }
+func (n *AssignStmt) Offset() int64 { return n.Offset_ }
+func (n *AssignStmt) SetOffset(x int64) { n.Offset_ = x }
+
+func (n *AssignStmt) SetOp(op Op) {
+ switch op {
+ default:
+ panic(n.no("SetOp " + op.String()))
+ case OAS, OSELRECV:
+ n.op = op
+ }
+}
+
+// An AssignOpStmt is an AsOp= assignment statement: X AsOp= Y.
+type AssignOpStmt struct {
+ miniStmt
+ typ *types.Type
+ X Node
+ AsOp Op // OADD etc
+ Y Node
+ IncDec bool // actually ++ or --
+}
+
+func NewAssignOpStmt(pos src.XPos, op Op, x, y Node) *AssignOpStmt {
+ n := &AssignOpStmt{AsOp: op, X: x, Y: y}
+ n.pos = pos
+ n.op = OASOP
+ return n
+}
+
+func (n *AssignOpStmt) Left() Node { return n.X }
+func (n *AssignOpStmt) SetLeft(x Node) { n.X = x }
+func (n *AssignOpStmt) Right() Node { return n.Y }
+func (n *AssignOpStmt) SetRight(y Node) { n.Y = y }
+func (n *AssignOpStmt) SubOp() Op { return n.AsOp }
+func (n *AssignOpStmt) SetSubOp(x Op) { n.AsOp = x }
+func (n *AssignOpStmt) Implicit() bool { return n.IncDec }
+func (n *AssignOpStmt) SetImplicit(b bool) { n.IncDec = b }
+func (n *AssignOpStmt) Type() *types.Type { return n.typ }
+func (n *AssignOpStmt) SetType(x *types.Type) { n.typ = x }
+
+// A BlockStmt is a block: { List }.
+type BlockStmt struct {
+ miniStmt
+ List_ Nodes
+}
+
+func NewBlockStmt(pos src.XPos, list []Node) *BlockStmt {
+ n := &BlockStmt{}
+ n.pos = pos
+ n.op = OBLOCK
+ n.List_.Set(list)
+ return n
+}
+
+func (n *BlockStmt) List() Nodes { return n.List_ }
+func (n *BlockStmt) PtrList() *Nodes { return &n.List_ }
+func (n *BlockStmt) SetList(x Nodes) { n.List_ = x }
+
+// A BranchStmt is a break, continue, fallthrough, or goto statement.
+//
+// For back-end code generation, Op may also be RETJMP (return+jump),
+// in which case the label names another function entirely.
+type BranchStmt struct {
+ miniStmt
+ Label *types.Sym // label if present
+}
+
+func NewBranchStmt(pos src.XPos, op Op, label *types.Sym) *BranchStmt {
+ switch op {
+ case OBREAK, OCONTINUE, OFALL, OGOTO, ORETJMP:
+ // ok
+ default:
+ panic("NewBranch " + op.String())
+ }
+ n := &BranchStmt{Label: label}
+ n.pos = pos
+ n.op = op
+ return n
+}
+
+func (n *BranchStmt) Sym() *types.Sym { return n.Label }
+func (n *BranchStmt) SetSym(sym *types.Sym) { n.Label = sym }
+
+// A CaseStmt is a case statement in a switch or select: case List: Body.
+type CaseStmt struct {
+ miniStmt
+ Vars Nodes // declared variable for this case in type switch
+ List_ Nodes // list of expressions for switch, early select
+ Comm Node // communication case (Exprs[0]) after select is type-checked
+ Body_ Nodes
+}
+
+func NewCaseStmt(pos src.XPos, list, body []Node) *CaseStmt {
+ n := &CaseStmt{}
+ n.pos = pos
+ n.op = OCASE
+ n.List_.Set(list)
+ n.Body_.Set(body)
+ return n
+}
+
+func (n *CaseStmt) List() Nodes { return n.List_ }
+func (n *CaseStmt) PtrList() *Nodes { return &n.List_ }
+func (n *CaseStmt) SetList(x Nodes) { n.List_ = x }
+func (n *CaseStmt) Body() Nodes { return n.Body_ }
+func (n *CaseStmt) PtrBody() *Nodes { return &n.Body_ }
+func (n *CaseStmt) SetBody(x Nodes) { n.Body_ = x }
+func (n *CaseStmt) Rlist() Nodes { return n.Vars }
+func (n *CaseStmt) PtrRlist() *Nodes { return &n.Vars }
+func (n *CaseStmt) SetRlist(x Nodes) { n.Vars = x }
+func (n *CaseStmt) Left() Node { return n.Comm }
+func (n *CaseStmt) SetLeft(x Node) { n.Comm = x }
+
+// A ForStmt is a non-range for loop: for Init; Cond; Post { Body }
+// Op can be OFOR or OFORUNTIL (!Cond).
+type ForStmt struct {
+ miniStmt
+ Label *types.Sym
+ Cond Node
+ Late Nodes
+ Post Node
+ Body_ Nodes
+ HasBreak_ bool
+}
+
+func NewForStmt(pos src.XPos, init []Node, cond, post Node, body []Node) *ForStmt {
+ n := &ForStmt{Cond: cond, Post: post}
+ n.pos = pos
+ n.op = OFOR
+ n.init.Set(init)
+ n.Body_.Set(body)
+ return n
+}
+
+func (n *ForStmt) Sym() *types.Sym { return n.Label }
+func (n *ForStmt) SetSym(x *types.Sym) { n.Label = x }
+func (n *ForStmt) Left() Node { return n.Cond }
+func (n *ForStmt) SetLeft(x Node) { n.Cond = x }
+func (n *ForStmt) Right() Node { return n.Post }
+func (n *ForStmt) SetRight(x Node) { n.Post = x }
+func (n *ForStmt) Body() Nodes { return n.Body_ }
+func (n *ForStmt) PtrBody() *Nodes { return &n.Body_ }
+func (n *ForStmt) SetBody(x Nodes) { n.Body_ = x }
+func (n *ForStmt) List() Nodes { return n.Late }
+func (n *ForStmt) PtrList() *Nodes { return &n.Late }
+func (n *ForStmt) SetList(x Nodes) { n.Late = x }
+func (n *ForStmt) HasBreak() bool { return n.HasBreak_ }
+func (n *ForStmt) SetHasBreak(b bool) { n.HasBreak_ = b }
+
+func (n *ForStmt) SetOp(op Op) {
+ if op != OFOR && op != OFORUNTIL {
+ panic(n.no("SetOp " + op.String()))
+ }
+ n.op = op
+}
+
+// A GoDeferStmt is a go or defer statement: go Call / defer Call.
+//
+// The two opcodes use a signle syntax because the implementations
+// are very similar: both are concerned with saving Call and running it
+// in a different context (a separate goroutine or a later time).
+type GoDeferStmt struct {
+ miniStmt
+ Call Node
+}
+
+func NewGoDeferStmt(pos src.XPos, op Op, call Node) *GoDeferStmt {
+ n := &GoDeferStmt{Call: call}
+ n.pos = pos
+ switch op {
+ case ODEFER, OGO:
+ n.op = op
+ default:
+ panic("NewGoDeferStmt " + op.String())
+ }
+ return n
+}
+
+func (n *GoDeferStmt) Left() Node { return n.Call }
+func (n *GoDeferStmt) SetLeft(x Node) { n.Call = x }
+
+// A IfStmt is a return statement: if Init; Cond { Then } else { Else }.
+type IfStmt struct {
+ miniStmt
+ Cond Node
+ Body_ Nodes
+ Else Nodes
+ Likely_ bool // code layout hint
+}
+
+func NewIfStmt(pos src.XPos, cond Node, body, els []Node) *IfStmt {
+ n := &IfStmt{Cond: cond}
+ n.pos = pos
+ n.op = OIF
+ n.Body_.Set(body)
+ n.Else.Set(els)
+ return n
+}
+
+func (n *IfStmt) Left() Node { return n.Cond }
+func (n *IfStmt) SetLeft(x Node) { n.Cond = x }
+func (n *IfStmt) Body() Nodes { return n.Body_ }
+func (n *IfStmt) PtrBody() *Nodes { return &n.Body_ }
+func (n *IfStmt) SetBody(x Nodes) { n.Body_ = x }
+func (n *IfStmt) Rlist() Nodes { return n.Else }
+func (n *IfStmt) PtrRlist() *Nodes { return &n.Else }
+func (n *IfStmt) SetRlist(x Nodes) { n.Else = x }
+func (n *IfStmt) Likely() bool { return n.Likely_ }
+func (n *IfStmt) SetLikely(x bool) { n.Likely_ = x }
+
+// An InlineMarkStmt is a marker placed just before an inlined body.
+type InlineMarkStmt struct {
+ miniStmt
+ Index int64
+}
+
+func NewInlineMarkStmt(pos src.XPos, index int64) *InlineMarkStmt {
+ n := &InlineMarkStmt{Index: index}
+ n.pos = pos
+ n.op = OINLMARK
+ return n
+}
+
+func (n *InlineMarkStmt) Offset() int64 { return n.Index }
+func (n *InlineMarkStmt) SetOffset(x int64) { n.Index = x }
+
+// A LabelStmt is a label statement (just the label, not including the statement it labels).
+type LabelStmt struct {
+ miniStmt
+ Label *types.Sym // "Label:"
+}
+
+func NewLabelStmt(pos src.XPos, label *types.Sym) *LabelStmt {
+ n := &LabelStmt{Label: label}
+ n.pos = pos
+ n.op = OLABEL
+ return n
+}
+
+func (n *LabelStmt) Sym() *types.Sym { return n.Label }
+func (n *LabelStmt) SetSym(x *types.Sym) { n.Label = x }
+
+// A RangeStmt is a range loop: for Vars = range X { Stmts }
+// Op can be OFOR or OFORUNTIL (!Cond).
+type RangeStmt struct {
+ miniStmt
+ Label *types.Sym
+ Vars Nodes // TODO(rsc): Replace with Key, Value Node
+ Def bool
+ X Node
+ Body_ Nodes
+ HasBreak_ bool
+ typ *types.Type // TODO(rsc): Remove - use X.Type() instead
+}
+
+func NewRangeStmt(pos src.XPos, vars []Node, x Node, body []Node) *RangeStmt {
+ n := &RangeStmt{X: x}
+ n.pos = pos
+ n.op = ORANGE
+ n.Vars.Set(vars)
+ n.Body_.Set(body)
+ return n
+}
+
+func (n *RangeStmt) Sym() *types.Sym { return n.Label }
+func (n *RangeStmt) SetSym(x *types.Sym) { n.Label = x }
+func (n *RangeStmt) Right() Node { return n.X }
+func (n *RangeStmt) SetRight(x Node) { n.X = x }
+func (n *RangeStmt) Body() Nodes { return n.Body_ }
+func (n *RangeStmt) PtrBody() *Nodes { return &n.Body_ }
+func (n *RangeStmt) SetBody(x Nodes) { n.Body_ = x }
+func (n *RangeStmt) List() Nodes { return n.Vars }
+func (n *RangeStmt) PtrList() *Nodes { return &n.Vars }
+func (n *RangeStmt) SetList(x Nodes) { n.Vars = x }
+func (n *RangeStmt) HasBreak() bool { return n.HasBreak_ }
+func (n *RangeStmt) SetHasBreak(b bool) { n.HasBreak_ = b }
+func (n *RangeStmt) Colas() bool { return n.Def }
+func (n *RangeStmt) SetColas(b bool) { n.Def = b }
+func (n *RangeStmt) Type() *types.Type { return n.typ }
+func (n *RangeStmt) SetType(x *types.Type) { n.typ = x }
+
+// A ReturnStmt is a return statement.
+type ReturnStmt struct {
+ miniStmt
+ orig Node // for typecheckargs rewrite
+ Results Nodes // return list
+}
+
+func NewReturnStmt(pos src.XPos, results []Node) *ReturnStmt {
+ n := &ReturnStmt{}
+ n.pos = pos
+ n.op = ORETURN
+ n.orig = n
+ n.Results.Set(results)
+ return n
+}
+
+func (n *ReturnStmt) Orig() Node { return n.orig }
+func (n *ReturnStmt) SetOrig(x Node) { n.orig = x }
+func (n *ReturnStmt) List() Nodes { return n.Results }
+func (n *ReturnStmt) PtrList() *Nodes { return &n.Results }
+func (n *ReturnStmt) SetList(x Nodes) { n.Results = x }
+func (n *ReturnStmt) IsDDD() bool { return false } // typecheckargs asks
+
+// A SelectStmt is a block: { Cases }.
+type SelectStmt struct {
+ miniStmt
+ Label *types.Sym
+ Cases Nodes
+ HasBreak_ bool
+
+ // TODO(rsc): Instead of recording here, replace with a block?
+ Compiled Nodes // compiled form, after walkswitch
+}
+
+func NewSelectStmt(pos src.XPos, cases []Node) *SelectStmt {
+ n := &SelectStmt{}
+ n.pos = pos
+ n.op = OSELECT
+ n.Cases.Set(cases)
+ return n
+}
+
+func (n *SelectStmt) List() Nodes { return n.Cases }
+func (n *SelectStmt) PtrList() *Nodes { return &n.Cases }
+func (n *SelectStmt) SetList(x Nodes) { n.Cases = x }
+func (n *SelectStmt) Sym() *types.Sym { return n.Label }
+func (n *SelectStmt) SetSym(x *types.Sym) { n.Label = x }
+func (n *SelectStmt) HasBreak() bool { return n.HasBreak_ }
+func (n *SelectStmt) SetHasBreak(x bool) { n.HasBreak_ = x }
+func (n *SelectStmt) Body() Nodes { return n.Compiled }
+func (n *SelectStmt) PtrBody() *Nodes { return &n.Compiled }
+func (n *SelectStmt) SetBody(x Nodes) { n.Compiled = x }
+
+// A SendStmt is a send statement: X <- Y.
+type SendStmt struct {
+ miniStmt
+ Chan Node
+ Value Node
+}
+
+func NewSendStmt(pos src.XPos, ch, value Node) *SendStmt {
+ n := &SendStmt{Chan: ch, Value: value}
+ n.pos = pos
+ n.op = OSEND
+ return n
+}
+
+func (n *SendStmt) Left() Node { return n.Chan }
+func (n *SendStmt) SetLeft(x Node) { n.Chan = x }
+func (n *SendStmt) Right() Node { return n.Value }
+func (n *SendStmt) SetRight(y Node) { n.Value = y }
+
+// A SwitchStmt is a switch statement: switch Init; Expr { Cases }.
+type SwitchStmt struct {
+ miniStmt
+ Tag Node
+ Cases Nodes // list of *CaseStmt
+ Label *types.Sym
+ HasBreak_ bool
+
+ // TODO(rsc): Instead of recording here, replace with a block?
+ Compiled Nodes // compiled form, after walkswitch
+}
+
+func NewSwitchStmt(pos src.XPos, tag Node, cases []Node) *SwitchStmt {
+ n := &SwitchStmt{Tag: tag}
+ n.pos = pos
+ n.op = OSWITCH
+ n.Cases.Set(cases)
+ return n
+}
+
+func (n *SwitchStmt) Left() Node { return n.Tag }
+func (n *SwitchStmt) SetLeft(x Node) { n.Tag = x }
+func (n *SwitchStmt) List() Nodes { return n.Cases }
+func (n *SwitchStmt) PtrList() *Nodes { return &n.Cases }
+func (n *SwitchStmt) SetList(x Nodes) { n.Cases = x }
+func (n *SwitchStmt) Body() Nodes { return n.Compiled }
+func (n *SwitchStmt) PtrBody() *Nodes { return &n.Compiled }
+func (n *SwitchStmt) SetBody(x Nodes) { n.Compiled = x }
+func (n *SwitchStmt) Sym() *types.Sym { return n.Label }
+func (n *SwitchStmt) SetSym(x *types.Sym) { n.Label = x }
+func (n *SwitchStmt) HasBreak() bool { return n.HasBreak_ }
+func (n *SwitchStmt) SetHasBreak(x bool) { n.HasBreak_ = x }
+
+// A TypeSwitchGuard is the [Name :=] X.(type) in a type switch.
+type TypeSwitchGuard struct {
+ miniNode
+ Tag *Ident
+ X Node
+ Used bool
+}
+
+func NewTypeSwitchGuard(pos src.XPos, tag *Ident, x Node) *TypeSwitchGuard {
+ n := &TypeSwitchGuard{Tag: tag, X: x}
+ n.pos = pos
+ n.op = OTYPESW
+ return n
+}
+
+func (n *TypeSwitchGuard) Left() Node {
+ if n.Tag == nil {
+ return nil
+ }
+ return n.Tag
+}
+func (n *TypeSwitchGuard) SetLeft(x Node) {
+ if x == nil {
+ n.Tag = nil
+ return
+ }
+ n.Tag = x.(*Ident)
+}
+func (n *TypeSwitchGuard) Right() Node { return n.X }
+func (n *TypeSwitchGuard) SetRight(x Node) { n.X = x }
diff --git a/src/cmd/compile/internal/ir/type.go b/src/cmd/compile/internal/ir/type.go
new file mode 100644
index 0000000000..5e6d76229d
--- /dev/null
+++ b/src/cmd/compile/internal/ir/type.go
@@ -0,0 +1,340 @@
+// Copyright 2009 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 ir
+
+import (
+ "cmd/compile/internal/base"
+ "cmd/compile/internal/types"
+ "cmd/internal/src"
+ "fmt"
+)
+
+// Nodes that represent the syntax of a type before type-checking.
+// After type-checking, they serve only as shells around a *types.Type.
+// Calling TypeNode converts a *types.Type to a Node shell.
+
+// An Ntype is a Node that syntactically looks like a type.
+// It can be the raw syntax for a type before typechecking,
+// or it can be an OTYPE with Type() set to a *types.Type.
+// Note that syntax doesn't guarantee it's a type: an expression
+// like *fmt is an Ntype (we don't know whether names are types yet),
+// but at least 1+1 is not an Ntype.
+type Ntype interface {
+ Node
+ CanBeNtype()
+}
+
+// A miniType is a minimal type syntax Node implementation,
+// to be embedded as the first field in a larger node implementation.
+type miniType struct {
+ miniNode
+ typ *types.Type
+}
+
+func (*miniType) CanBeNtype() {}
+
+func (n *miniType) Type() *types.Type { return n.typ }
+
+// setOTYPE changes n to be an OTYPE node returning t.
+// Rewriting the node in place this way should not be strictly
+// necessary (we should be able to update the uses with
+// proper OTYPE nodes), but it's mostly harmless and easy
+// to keep doing for now.
+//
+// setOTYPE also records t.Nod = self if t.Nod is not already set.
+// (Some types are shared by multiple OTYPE nodes, so only
+// the first such node is used as t.Nod.)
+func (n *miniType) setOTYPE(t *types.Type, self Node) {
+ if n.typ != nil {
+ panic(n.op.String() + " SetType: type already set")
+ }
+ n.op = OTYPE
+ n.typ = t
+ t.SetNod(self)
+}
+
+func (n *miniType) Sym() *types.Sym { return nil } // for Format OTYPE
+func (n *miniType) Implicit() bool { return false } // for Format OTYPE
+
+// A ChanType represents a chan Elem syntax with the direction Dir.
+type ChanType struct {
+ miniType
+ Elem Node
+ Dir types.ChanDir
+}
+
+func NewChanType(pos src.XPos, elem Node, dir types.ChanDir) *ChanType {
+ n := &ChanType{Elem: elem, Dir: dir}
+ n.op = OTCHAN
+ n.pos = pos
+ return n
+}
+
+func (n *ChanType) SetOTYPE(t *types.Type) {
+ n.setOTYPE(t, n)
+ n.Elem = nil
+}
+
+// A MapType represents a map[Key]Value type syntax.
+type MapType struct {
+ miniType
+ Key Node
+ Elem Node
+}
+
+func NewMapType(pos src.XPos, key, elem Node) *MapType {
+ n := &MapType{Key: key, Elem: elem}
+ n.op = OTMAP
+ n.pos = pos
+ return n
+}
+
+func (n *MapType) SetOTYPE(t *types.Type) {
+ n.setOTYPE(t, n)
+ n.Key = nil
+ n.Elem = nil
+}
+
+// A StructType represents a struct { ... } type syntax.
+type StructType struct {
+ miniType
+ Fields []*Field
+}
+
+func NewStructType(pos src.XPos, fields []*Field) *StructType {
+ n := &StructType{Fields: fields}
+ n.op = OTSTRUCT
+ n.pos = pos
+ return n
+}
+
+func (n *StructType) SetOTYPE(t *types.Type) {
+ n.setOTYPE(t, n)
+ n.Fields = nil
+}
+
+func deepCopyFields(pos src.XPos, fields []*Field) []*Field {
+ var out []*Field
+ for _, f := range fields {
+ out = append(out, f.deepCopy(pos))
+ }
+ return out
+}
+
+// An InterfaceType represents a struct { ... } type syntax.
+type InterfaceType struct {
+ miniType
+ Methods []*Field
+}
+
+func NewInterfaceType(pos src.XPos, methods []*Field) *InterfaceType {
+ n := &InterfaceType{Methods: methods}
+ n.op = OTINTER
+ n.pos = pos
+ return n
+}
+
+func (n *InterfaceType) SetOTYPE(t *types.Type) {
+ n.setOTYPE(t, n)
+ n.Methods = nil
+}
+
+// A FuncType represents a func(Args) Results type syntax.
+type FuncType struct {
+ miniType
+ Recv *Field
+ Params []*Field
+ Results []*Field
+}
+
+func NewFuncType(pos src.XPos, rcvr *Field, args, results []*Field) *FuncType {
+ n := &FuncType{Recv: rcvr, Params: args, Results: results}
+ n.op = OTFUNC
+ n.pos = pos
+ return n
+}
+
+func (n *FuncType) SetOTYPE(t *types.Type) {
+ n.setOTYPE(t, n)
+ n.Recv = nil
+ n.Params = nil
+ n.Results = nil
+}
+
+// A Field is a declared struct field, interface method, or function argument.
+// It is not a Node.
+type Field struct {
+ Pos src.XPos
+ Sym *types.Sym
+ Ntype Ntype
+ Type *types.Type
+ Embedded bool
+ IsDDD bool
+ Note string
+ Decl *Name
+}
+
+func NewField(pos src.XPos, sym *types.Sym, ntyp Ntype, typ *types.Type) *Field {
+ return &Field{Pos: pos, Sym: sym, Ntype: ntyp, Type: typ}
+}
+
+func (f *Field) String() string {
+ var typ string
+ if f.Type != nil {
+ typ = fmt.Sprint(f.Type)
+ } else {
+ typ = fmt.Sprint(f.Ntype)
+ }
+ if f.Sym != nil {
+ return fmt.Sprintf("%v %v", f.Sym, typ)
+ }
+ return typ
+}
+
+func (f *Field) copy() *Field {
+ c := *f
+ return &c
+}
+
+func copyFields(list []*Field) []*Field {
+ out := make([]*Field, len(list))
+ copy(out, list)
+ for i, f := range out {
+ out[i] = f.copy()
+ }
+ return out
+}
+
+func maybeDoField(f *Field, err error, do func(Node) error) error {
+ if f != nil {
+ if err == nil && f.Decl != nil {
+ err = do(f.Decl)
+ }
+ if err == nil && f.Ntype != nil {
+ err = do(f.Ntype)
+ }
+ }
+ return err
+}
+
+func maybeDoFields(list []*Field, err error, do func(Node) error) error {
+ if err != nil {
+ return err
+ }
+ for _, f := range list {
+ err = maybeDoField(f, err, do)
+ if err != nil {
+ return err
+ }
+ }
+ return err
+}
+
+func editField(f *Field, edit func(Node) Node) {
+ if f == nil {
+ return
+ }
+ if f.Decl != nil {
+ f.Decl = edit(f.Decl).(*Name)
+ }
+ if f.Ntype != nil {
+ f.Ntype = toNtype(edit(f.Ntype))
+ }
+}
+
+func editFields(list []*Field, edit func(Node) Node) {
+ for _, f := range list {
+ editField(f, edit)
+ }
+}
+
+func (f *Field) deepCopy(pos src.XPos) *Field {
+ if f == nil {
+ return nil
+ }
+ fpos := pos
+ if !pos.IsKnown() {
+ fpos = f.Pos
+ }
+ decl := f.Decl
+ if decl != nil {
+ decl = DeepCopy(pos, decl).(*Name)
+ }
+ ntype := f.Ntype
+ if ntype != nil {
+ ntype = DeepCopy(pos, ntype).(Ntype)
+ }
+ // No keyed literal here: if a new struct field is added, we want this to stop compiling.
+ return &Field{fpos, f.Sym, ntype, f.Type, f.Embedded, f.IsDDD, f.Note, decl}
+}
+
+// A SliceType represents a []Elem type syntax.
+// If DDD is true, it's the ...Elem at the end of a function list.
+type SliceType struct {
+ miniType
+ Elem Node
+ DDD bool
+}
+
+func NewSliceType(pos src.XPos, elem Node) *SliceType {
+ n := &SliceType{Elem: elem}
+ n.op = OTSLICE
+ n.pos = pos
+ return n
+}
+
+func (n *SliceType) SetOTYPE(t *types.Type) {
+ n.setOTYPE(t, n)
+ n.Elem = nil
+}
+
+// An ArrayType represents a [Len]Elem type syntax.
+// If Len is nil, the type is a [...]Elem in an array literal.
+type ArrayType struct {
+ miniType
+ Len Node
+ Elem Node
+}
+
+func NewArrayType(pos src.XPos, size Node, elem Node) *ArrayType {
+ n := &ArrayType{Len: size, Elem: elem}
+ n.op = OTARRAY
+ n.pos = pos
+ return n
+}
+
+func (n *ArrayType) SetOTYPE(t *types.Type) {
+ n.setOTYPE(t, n)
+ n.Len = nil
+ n.Elem = nil
+}
+
+// A typeNode is a Node wrapper for type t.
+type typeNode struct {
+ miniNode
+ typ *types.Type
+}
+
+func newTypeNode(pos src.XPos, typ *types.Type) *typeNode {
+ n := &typeNode{typ: typ}
+ n.pos = pos
+ n.op = OTYPE
+ return n
+}
+
+func (n *typeNode) Type() *types.Type { return n.typ }
+func (n *typeNode) Sym() *types.Sym { return n.typ.Sym() }
+func (n *typeNode) CanBeNtype() {}
+
+// TypeNode returns the Node representing the type t.
+func TypeNode(t *types.Type) Ntype {
+ if n := t.Obj(); n != nil {
+ if n.Type() != t {
+ base.Fatalf("type skew: %v has type %v, but expected %v", n, n.Type(), t)
+ }
+ return n.(Ntype)
+ }
+ return newTypeNode(src.NoXPos, t)
+}
diff --git a/src/cmd/compile/internal/ir/val.go b/src/cmd/compile/internal/ir/val.go
index 9035e90084..5b0506c0d0 100644
--- a/src/cmd/compile/internal/ir/val.go
+++ b/src/cmd/compile/internal/ir/val.go
@@ -32,7 +32,7 @@ func ConstValue(n Node) interface{} {
case constant.String:
return constant.StringVal(v)
case constant.Int:
- return Int64Val(n.Type(), v)
+ return IntVal(n.Type(), v)
case constant.Float:
return Float64Val(v)
case constant.Complex:
@@ -42,7 +42,7 @@ func ConstValue(n Node) interface{} {
// int64Val returns v converted to int64.
// Note: if t is uint64, very large values will be converted to negative int64.
-func Int64Val(t *types.Type, v constant.Value) int64 {
+func IntVal(t *types.Type, v constant.Value) int64 {
if t.IsUnsigned() {
if x, ok := constant.Uint64Val(v); ok {
return int64(x)
@@ -73,7 +73,7 @@ func AssertValidTypeForConst(t *types.Type, v constant.Value) {
func ValidTypeForConst(t *types.Type, v constant.Value) bool {
switch v.Kind() {
case constant.Unknown:
- return OKForConst[t.Etype]
+ return OKForConst[t.Kind()]
case constant.Bool:
return t.IsBoolean()
case constant.String:
@@ -92,7 +92,7 @@ func ValidTypeForConst(t *types.Type, v constant.Value) bool {
// nodlit returns a new untyped constant with value v.
func NewLiteral(v constant.Value) Node {
- n := Nod(OLITERAL, nil, nil)
+ n := newNameAt(base.Pos, OLITERAL, nil)
if k := v.Kind(); k != constant.Unknown {
n.SetType(idealType(k))
n.SetVal(v)
@@ -118,3 +118,59 @@ func idealType(ct constant.Kind) *types.Type {
}
var OKForConst [types.NTYPE]bool
+
+// CanInt64 reports whether it is safe to call Int64Val() on n.
+func CanInt64(n Node) bool {
+ if !IsConst(n, constant.Int) {
+ return false
+ }
+
+ // if the value inside n cannot be represented as an int64, the
+ // return value of Int64 is undefined
+ _, ok := constant.Int64Val(n.Val())
+ return ok
+}
+
+// Int64Val returns n as an int64.
+// n must be an integer or rune constant.
+func Int64Val(n Node) int64 {
+ if !IsConst(n, constant.Int) {
+ base.Fatalf("Int64Val(%v)", n)
+ }
+ x, ok := constant.Int64Val(n.Val())
+ if !ok {
+ base.Fatalf("Int64Val(%v)", n)
+ }
+ return x
+}
+
+// Uint64Val returns n as an uint64.
+// n must be an integer or rune constant.
+func Uint64Val(n Node) uint64 {
+ if !IsConst(n, constant.Int) {
+ base.Fatalf("Uint64Val(%v)", n)
+ }
+ x, ok := constant.Uint64Val(n.Val())
+ if !ok {
+ base.Fatalf("Uint64Val(%v)", n)
+ }
+ return x
+}
+
+// BoolVal returns n as a bool.
+// n must be a boolean constant.
+func BoolVal(n Node) bool {
+ if !IsConst(n, constant.Bool) {
+ base.Fatalf("BoolVal(%v)", n)
+ }
+ return constant.BoolVal(n.Val())
+}
+
+// StringVal returns the value of a literal string Node as a string.
+// n must be a string constant.
+func StringVal(n Node) string {
+ if !IsConst(n, constant.String) {
+ base.Fatalf("StringVal(%v)", n)
+ }
+ return constant.StringVal(n.Val())
+}
diff --git a/src/cmd/compile/internal/ir/visit.go b/src/cmd/compile/internal/ir/visit.go
new file mode 100644
index 0000000000..4f3575614d
--- /dev/null
+++ b/src/cmd/compile/internal/ir/visit.go
@@ -0,0 +1,244 @@
+// Copyright 2020 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.
+
+// IR visitors for walking the IR tree.
+//
+// The lowest level helpers are DoChildren and EditChildren,
+// which nodes help implement (TODO(rsc): eventually) and
+// provide control over whether and when recursion happens
+// during the walk of the IR.
+//
+// Although these are both useful directly, two simpler patterns
+// are fairly common and also provided: Inspect and Scan.
+
+package ir
+
+import (
+ "errors"
+)
+
+// DoChildren calls do(x) on each of n's non-nil child nodes x.
+// If any call returns a non-nil error, DoChildren stops and returns that error.
+// Otherwise, DoChildren returns nil.
+//
+// Note that DoChildren(n, do) only calls do(x) for n's immediate children.
+// If x's children should be processed, then do(x) must call DoChildren(x, do).
+//
+// DoChildren allows constructing general traversals of the IR graph
+// that can stop early if needed. The most general usage is:
+//
+// var do func(ir.Node) error
+// do = func(x ir.Node) error {
+// ... processing BEFORE visting children ...
+// if ... should visit children ... {
+// ir.DoChildren(x, do)
+// ... processing AFTER visting children ...
+// }
+// if ... should stop parent DoChildren call from visiting siblings ... {
+// return non-nil error
+// }
+// return nil
+// }
+// do(root)
+//
+// Since DoChildren does not generate any errors itself, if the do function
+// never wants to stop the traversal, it can assume that DoChildren itself
+// will always return nil, simplifying to:
+//
+// var do func(ir.Node) error
+// do = func(x ir.Node) error {
+// ... processing BEFORE visting children ...
+// if ... should visit children ... {
+// ir.DoChildren(x, do)
+// }
+// ... processing AFTER visting children ...
+// return nil
+// }
+// do(root)
+//
+// The Inspect function illustrates a further simplification of the pattern,
+// only considering processing before visiting children, and letting
+// that processing decide whether children are visited at all:
+//
+// func Inspect(n ir.Node, inspect func(ir.Node) bool) {
+// var do func(ir.Node) error
+// do = func(x ir.Node) error {
+// if inspect(x) {
+// ir.DoChildren(x, do)
+// }
+// return nil
+// }
+// if n != nil {
+// do(n)
+// }
+// }
+//
+// The Find function illustrates a different simplification of the pattern,
+// visiting each node and then its children, recursively, until finding
+// a node x such that find(x) returns a non-nil result,
+// at which point the entire traversal stops:
+//
+// func Find(n ir.Node, find func(ir.Node) interface{}) interface{} {
+// stop := errors.New("stop")
+// var found interface{}
+// var do func(ir.Node) error
+// do = func(x ir.Node) error {
+// if v := find(x); v != nil {
+// found = v
+// return stop
+// }
+// return ir.DoChildren(x, do)
+// }
+// do(n)
+// return found
+// }
+//
+// Inspect and Find are presented above as examples of how to use
+// DoChildren effectively, but of course, usage that fits within the
+// simplifications captured by Inspect or Find will be best served
+// by directly calling the ones provided by this package.
+func DoChildren(n Node, do func(Node) error) error {
+ if n == nil {
+ return nil
+ }
+ return n.doChildren(do)
+}
+
+// DoList calls f on each non-nil node x in the list, in list order.
+// If any call returns a non-nil error, DoList stops and returns that error.
+// Otherwise DoList returns nil.
+//
+// Note that DoList only calls do on the nodes in the list, not their children.
+// If x's children should be processed, do(x) must call DoChildren(x, do) itself.
+func DoList(list Nodes, do func(Node) error) error {
+ for _, x := range list.Slice() {
+ if x != nil {
+ if err := do(x); err != nil {
+ return err
+ }
+ }
+ }
+ return nil
+}
+
+// Inspect visits each node x in the IR tree rooted at n
+// in a depth-first preorder traversal, calling inspect on each node visited.
+// If inspect(x) returns false, then Inspect skips over x's children.
+//
+// Note that the meaning of the boolean result in the callback function
+// passed to Inspect differs from that of Scan.
+// During Scan, if scan(x) returns false, then Scan stops the scan.
+// During Inspect, if inspect(x) returns false, then Inspect skips x's children
+// but continues with the remainder of the tree (x's siblings and so on).
+func Inspect(n Node, inspect func(Node) bool) {
+ var do func(Node) error
+ do = func(x Node) error {
+ if inspect(x) {
+ DoChildren(x, do)
+ }
+ return nil
+ }
+ if n != nil {
+ do(n)
+ }
+}
+
+// InspectList calls Inspect(x, inspect) for each node x in the list.
+func InspectList(list Nodes, inspect func(Node) bool) {
+ for _, x := range list.Slice() {
+ Inspect(x, inspect)
+ }
+}
+
+var stop = errors.New("stop")
+
+// Find looks for a non-nil node x in the IR tree rooted at n
+// for which find(x) returns a non-nil value.
+// Find considers nodes in a depth-first, preorder traversal.
+// When Find finds a node x such that find(x) != nil,
+// Find ends the traversal and returns the value of find(x) immediately.
+// Otherwise Find returns nil.
+func Find(n Node, find func(Node) interface{}) interface{} {
+ if n == nil {
+ return nil
+ }
+ var found interface{}
+ var do func(Node) error
+ do = func(x Node) error {
+ if v := find(x); v != nil {
+ found = v
+ return stop
+ }
+ return DoChildren(x, do)
+ }
+ do(n)
+ return found
+}
+
+// FindList calls Find(x, ok) for each node x in the list, in order.
+// If any call find(x) returns a non-nil result, FindList stops and
+// returns that result, skipping the remainder of the list.
+// Otherwise FindList returns nil.
+func FindList(list Nodes, find func(Node) interface{}) interface{} {
+ for _, x := range list.Slice() {
+ if v := Find(x, find); v != nil {
+ return v
+ }
+ }
+ return nil
+}
+
+// EditChildren edits the child nodes of n, replacing each child x with edit(x).
+//
+// Note that EditChildren(n, edit) only calls edit(x) for n's immediate children.
+// If x's children should be processed, then edit(x) must call EditChildren(x, edit).
+//
+// EditChildren allows constructing general editing passes of the IR graph.
+// The most general usage is:
+//
+// var edit func(ir.Node) ir.Node
+// edit = func(x ir.Node) ir.Node {
+// ... processing BEFORE editing children ...
+// if ... should edit children ... {
+// EditChildren(x, edit)
+// ... processing AFTER editing children ...
+// }
+// ... return x ...
+// }
+// n = edit(n)
+//
+// EditChildren edits the node in place. To edit a copy, call Copy first.
+// As an example, a simple deep copy implementation would be:
+//
+// func deepCopy(n ir.Node) ir.Node {
+// var edit func(ir.Node) ir.Node
+// edit = func(x ir.Node) ir.Node {
+// x = ir.Copy(x)
+// ir.EditChildren(x, edit)
+// return x
+// }
+// return edit(n)
+// }
+//
+// Of course, in this case it is better to call ir.DeepCopy than to build one anew.
+func EditChildren(n Node, edit func(Node) Node) {
+ if n == nil {
+ return
+ }
+ n.editChildren(edit)
+}
+
+// editList calls edit on each non-nil node x in the list,
+// saving the result of edit back into the list.
+//
+// Note that editList only calls edit on the nodes in the list, not their children.
+// If x's children should be processed, edit(x) must call EditChildren(x, edit) itself.
+func editList(list Nodes, edit func(Node) Node) {
+ s := list.Slice()
+ for i, x := range list.Slice() {
+ if x != nil {
+ s[i] = edit(x)
+ }
+ }
+}
diff --git a/src/cmd/compile/internal/logopt/logopt_test.go b/src/cmd/compile/internal/logopt/logopt_test.go
index 51bab49518..71976174b0 100644
--- a/src/cmd/compile/internal/logopt/logopt_test.go
+++ b/src/cmd/compile/internal/logopt/logopt_test.go
@@ -51,7 +51,7 @@ func want(t *testing.T, out string, desired string) {
func wantN(t *testing.T, out string, desired string, n int) {
if strings.Count(out, desired) != n {
- t.Errorf("expected exactly %d occurences of %s in \n%s", n, desired, out)
+ t.Errorf("expected exactly %d occurrences of %s in \n%s", n, desired, out)
}
}
@@ -132,7 +132,7 @@ func TestLogOpt(t *testing.T) {
// Check at both 1 and 8-byte alignments.
t.Run("Copy", func(t *testing.T) {
const copyCode = `package x
-func s128a1(x *[128]int8) [128]int8 {
+func s128a1(x *[128]int8) [128]int8 {
return *x
}
func s127a1(x *[127]int8) [127]int8 {
@@ -219,7 +219,7 @@ func s15a8(x *[15]int64) [15]int64 {
`{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":4,"character":11},"end":{"line":4,"character":11}}},"message":"inlineLoc"},`+
`{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}}},"message":"escflow: from \u0026y.b (address-of)"},`+
`{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":4,"character":9},"end":{"line":4,"character":9}}},"message":"inlineLoc"},`+
- `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}}},"message":"escflow: from ~R0 = \u003cN\u003e (assign-pair)"},`+
+ `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}}},"message":"escflow: from ~R0 = \u0026y.b (assign-pair)"},`+
`{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":3},"end":{"line":9,"character":3}}},"message":"escflow: flow: ~r2 = ~R0:"},`+
`{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":3},"end":{"line":9,"character":3}}},"message":"escflow: from return (*int)(~R0) (return)"}]}`)
})
diff --git a/src/cmd/compile/internal/mips/ssa.go b/src/cmd/compile/internal/mips/ssa.go
index bd71b2fcd8..10453c27d5 100644
--- a/src/cmd/compile/internal/mips/ssa.go
+++ b/src/cmd/compile/internal/mips/ssa.go
@@ -289,7 +289,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
case *obj.LSym:
wantreg = "SB"
gc.AddAux(&p.From, v)
- case ir.Node:
+ case *ir.Name:
wantreg = "SP"
gc.AddAux(&p.From, v)
case nil:
diff --git a/src/cmd/compile/internal/mips64/ssa.go b/src/cmd/compile/internal/mips64/ssa.go
index bcadebde4e..9aaf8715de 100644
--- a/src/cmd/compile/internal/mips64/ssa.go
+++ b/src/cmd/compile/internal/mips64/ssa.go
@@ -263,7 +263,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
case *obj.LSym:
wantreg = "SB"
gc.AddAux(&p.From, v)
- case ir.Node:
+ case *ir.Name:
wantreg = "SP"
gc.AddAux(&p.From, v)
case nil:
diff --git a/src/cmd/compile/internal/riscv64/ssa.go b/src/cmd/compile/internal/riscv64/ssa.go
index c81b6897a6..d382304d72 100644
--- a/src/cmd/compile/internal/riscv64/ssa.go
+++ b/src/cmd/compile/internal/riscv64/ssa.go
@@ -324,7 +324,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
case *obj.LSym:
wantreg = "SB"
gc.AddAux(&p.From, v)
- case ir.Node:
+ case *ir.Name:
wantreg = "SP"
gc.AddAux(&p.From, v)
case nil:
diff --git a/src/cmd/compile/internal/ssa/block.go b/src/cmd/compile/internal/ssa/block.go
index 519ac214ca..937c757b21 100644
--- a/src/cmd/compile/internal/ssa/block.go
+++ b/src/cmd/compile/internal/ssa/block.go
@@ -52,7 +52,7 @@ type Block struct {
Controls [2]*Value
// Auxiliary info for the block. Its value depends on the Kind.
- Aux interface{}
+ Aux Aux
AuxInt int64
// The unordered set of Values that define the operation of this block.
diff --git a/src/cmd/compile/internal/ssa/check.go b/src/cmd/compile/internal/ssa/check.go
index 5f5dfc328a..4d57eef556 100644
--- a/src/cmd/compile/internal/ssa/check.go
+++ b/src/cmd/compile/internal/ssa/check.go
@@ -161,7 +161,7 @@ func checkFunc(f *Func) {
f.Fatalf("value %v has an AuxInt that encodes a NaN", v)
}
case auxString:
- if _, ok := v.Aux.(string); !ok {
+ if _, ok := v.Aux.(stringAux); !ok {
f.Fatalf("value %v has Aux type %T, want string", v, v.Aux)
}
canHaveAux = true
diff --git a/src/cmd/compile/internal/ssa/config.go b/src/cmd/compile/internal/ssa/config.go
index eeabd81d03..8dc2ee8213 100644
--- a/src/cmd/compile/internal/ssa/config.go
+++ b/src/cmd/compile/internal/ssa/config.go
@@ -139,7 +139,7 @@ type Frontend interface {
// Auto returns a Node for an auto variable of the given type.
// The SSA compiler uses this function to allocate space for spills.
- Auto(src.XPos, *types.Type) ir.Node
+ Auto(src.XPos, *types.Type) *ir.Name
// Given the name for a compound type, returns the name we should use
// for the parts of that compound type.
diff --git a/src/cmd/compile/internal/ssa/cse.go b/src/cmd/compile/internal/ssa/cse.go
index 3b4f2be37e..f78527410c 100644
--- a/src/cmd/compile/internal/ssa/cse.go
+++ b/src/cmd/compile/internal/ssa/cse.go
@@ -275,7 +275,7 @@ func lt2Cmp(isLt bool) types.Cmp {
return types.CMPgt
}
-type auxmap map[interface{}]int32
+type auxmap map[Aux]int32
func cmpVal(v, w *Value, auxIDs auxmap) types.Cmp {
// Try to order these comparison by cost (cheaper first)
diff --git a/src/cmd/compile/internal/ssa/cse_test.go b/src/cmd/compile/internal/ssa/cse_test.go
index 9e76645f54..8052016f3a 100644
--- a/src/cmd/compile/internal/ssa/cse_test.go
+++ b/src/cmd/compile/internal/ssa/cse_test.go
@@ -14,6 +14,8 @@ type tstAux struct {
s string
}
+func (*tstAux) CanBeAnSSAAux() {}
+
// This tests for a bug found when partitioning, but not sorting by the Aux value.
func TestCSEAuxPartitionBug(t *testing.T) {
c := testConfig(t)
diff --git a/src/cmd/compile/internal/ssa/deadstore.go b/src/cmd/compile/internal/ssa/deadstore.go
index f3ef33d670..a68c82ba97 100644
--- a/src/cmd/compile/internal/ssa/deadstore.go
+++ b/src/cmd/compile/internal/ssa/deadstore.go
@@ -137,9 +137,9 @@ func dse(f *Func) {
// reaches stores then we delete all the stores. The other operations will then
// be eliminated by the dead code elimination pass.
func elimDeadAutosGeneric(f *Func) {
- addr := make(map[*Value]ir.Node) // values that the address of the auto reaches
- elim := make(map[*Value]ir.Node) // values that could be eliminated if the auto is
- used := make(map[ir.Node]bool) // used autos that must be kept
+ addr := make(map[*Value]*ir.Name) // values that the address of the auto reaches
+ elim := make(map[*Value]*ir.Name) // values that could be eliminated if the auto is
+ used := make(map[*ir.Name]bool) // used autos that must be kept
// visit the value and report whether any of the maps are updated
visit := func(v *Value) (changed bool) {
@@ -147,7 +147,7 @@ func elimDeadAutosGeneric(f *Func) {
switch v.Op {
case OpAddr, OpLocalAddr:
// Propagate the address if it points to an auto.
- n, ok := v.Aux.(ir.Node)
+ n, ok := v.Aux.(*ir.Name)
if !ok || n.Class() != ir.PAUTO {
return
}
@@ -158,7 +158,7 @@ func elimDeadAutosGeneric(f *Func) {
return
case OpVarDef, OpVarKill:
// v should be eliminated if we eliminate the auto.
- n, ok := v.Aux.(ir.Node)
+ n, ok := v.Aux.(*ir.Name)
if !ok || n.Class() != ir.PAUTO {
return
}
@@ -174,7 +174,7 @@ func elimDeadAutosGeneric(f *Func) {
// for open-coded defers from being removed (since they
// may not be used by the inline code, but will be used by
// panic processing).
- n, ok := v.Aux.(ir.Node)
+ n, ok := v.Aux.(*ir.Name)
if !ok || n.Class() != ir.PAUTO {
return
}
@@ -222,7 +222,7 @@ func elimDeadAutosGeneric(f *Func) {
}
// Propagate any auto addresses through v.
- var node ir.Node
+ var node *ir.Name
for _, a := range args {
if n, ok := addr[a]; ok && !used[n] {
if node == nil {
@@ -299,11 +299,11 @@ func elimUnreadAutos(f *Func) {
// Loop over all ops that affect autos taking note of which
// autos we need and also stores that we might be able to
// eliminate.
- seen := make(map[ir.Node]bool)
+ seen := make(map[*ir.Name]bool)
var stores []*Value
for _, b := range f.Blocks {
for _, v := range b.Values {
- n, ok := v.Aux.(ir.Node)
+ n, ok := v.Aux.(*ir.Name)
if !ok {
continue
}
@@ -335,7 +335,7 @@ func elimUnreadAutos(f *Func) {
// Eliminate stores to unread autos.
for _, store := range stores {
- n, _ := store.Aux.(ir.Node)
+ n, _ := store.Aux.(*ir.Name)
if seen[n] {
continue
}
diff --git a/src/cmd/compile/internal/ssa/debug.go b/src/cmd/compile/internal/ssa/debug.go
index 0d660361b1..68b6ab5fe9 100644
--- a/src/cmd/compile/internal/ssa/debug.go
+++ b/src/cmd/compile/internal/ssa/debug.go
@@ -25,7 +25,7 @@ type FuncDebug struct {
// Slots is all the slots used in the debug info, indexed by their SlotID.
Slots []LocalSlot
// The user variables, indexed by VarID.
- Vars []ir.Node
+ Vars []*ir.Name
// The slots that make up each variable, indexed by VarID.
VarSlots [][]SlotID
// The location list data, indexed by VarID. Must be processed by PutLocationList.
@@ -143,13 +143,13 @@ func (loc VarLoc) absent() bool {
var BlockStart = &Value{
ID: -10000,
Op: OpInvalid,
- Aux: "BlockStart",
+ Aux: StringToAux("BlockStart"),
}
var BlockEnd = &Value{
ID: -20000,
Op: OpInvalid,
- Aux: "BlockEnd",
+ Aux: StringToAux("BlockEnd"),
}
// RegisterSet is a bitmap of registers, indexed by Register.num.
@@ -166,7 +166,7 @@ func (s *debugState) logf(msg string, args ...interface{}) {
type debugState struct {
// See FuncDebug.
slots []LocalSlot
- vars []ir.Node
+ vars []*ir.Name
varSlots [][]SlotID
lists [][]byte
@@ -190,7 +190,7 @@ type debugState struct {
// The pending location list entry for each user variable, indexed by VarID.
pendingEntries []pendingEntry
- varParts map[ir.Node][]SlotID
+ varParts map[*ir.Name][]SlotID
blockDebug []BlockDebug
pendingSlotLocs []VarLoc
liveSlots []liveSlot
@@ -347,7 +347,7 @@ func BuildFuncDebug(ctxt *obj.Link, f *Func, loggingEnabled bool, stackOffset fu
}
if state.varParts == nil {
- state.varParts = make(map[ir.Node][]SlotID)
+ state.varParts = make(map[*ir.Name][]SlotID)
} else {
for n := range state.varParts {
delete(state.varParts, n)
@@ -380,7 +380,7 @@ func BuildFuncDebug(ctxt *obj.Link, f *Func, loggingEnabled bool, stackOffset fu
for _, b := range f.Blocks {
for _, v := range b.Values {
if v.Op == OpVarDef || v.Op == OpVarKill {
- n := v.Aux.(ir.Node)
+ n := v.Aux.(*ir.Name)
if ir.IsSynthetic(n) {
continue
}
@@ -718,7 +718,7 @@ func (state *debugState) processValue(v *Value, vSlots []SlotID, vReg *Register)
switch {
case v.Op == OpVarDef, v.Op == OpVarKill:
- n := v.Aux.(ir.Node)
+ n := v.Aux.(*ir.Name)
if ir.IsSynthetic(n) {
break
}
diff --git a/src/cmd/compile/internal/ssa/expand_calls.go b/src/cmd/compile/internal/ssa/expand_calls.go
index f266e49327..0eba238d81 100644
--- a/src/cmd/compile/internal/ssa/expand_calls.go
+++ b/src/cmd/compile/internal/ssa/expand_calls.go
@@ -69,7 +69,7 @@ func expandCalls(f *Func) {
// intPairTypes returns the pair of 32-bit int types needed to encode a 64-bit integer type on a target
// that has no 64-bit integer registers.
- intPairTypes := func(et types.EType) (tHi, tLo *types.Type) {
+ intPairTypes := func(et types.Kind) (tHi, tLo *types.Type) {
tHi = typ.UInt32
if et == types.TINT64 {
tHi = typ.Int32
@@ -294,7 +294,7 @@ func expandCalls(f *Func) {
case OpStructSelect:
w := selector.Args[0]
var ls []LocalSlot
- if w.Type.Etype != types.TSTRUCT { // IData artifact
+ if w.Type.Kind() != types.TSTRUCT { // IData artifact
ls = rewriteSelect(leaf, w, offset)
} else {
ls = rewriteSelect(leaf, w, offset+w.Type.FieldOff(int(selector.AuxInt)))
@@ -383,7 +383,7 @@ func expandCalls(f *Func) {
decomposeOne func(pos src.XPos, b *Block, base, source, mem *Value, t1 *types.Type, offArg, offStore int64) *Value,
decomposeTwo func(pos src.XPos, b *Block, base, source, mem *Value, t1, t2 *types.Type, offArg, offStore int64) *Value) *Value {
u := source.Type
- switch u.Etype {
+ switch u.Kind() {
case types.TARRAY:
elem := u.Elem()
for i := int64(0); i < u.NumElem(); i++ {
@@ -403,7 +403,7 @@ func expandCalls(f *Func) {
if t.Width == regSize {
break
}
- tHi, tLo := intPairTypes(t.Etype)
+ tHi, tLo := intPairTypes(t.Kind())
mem = decomposeOne(pos, b, base, source, mem, tHi, source.AuxInt+hiOffset, offset+hiOffset)
pos = pos.WithNotStmt()
return decomposeOne(pos, b, base, source, mem, tLo, source.AuxInt+lowOffset, offset+lowOffset)
@@ -491,7 +491,7 @@ func expandCalls(f *Func) {
return storeArgOrLoad(pos, b, base, source.Args[0], mem, t.Elem(), offset)
case OpInt64Make:
- tHi, tLo := intPairTypes(t.Etype)
+ tHi, tLo := intPairTypes(t.Kind())
mem = storeArgOrLoad(pos, b, base, source.Args[0], mem, tHi, offset+hiOffset)
pos = pos.WithNotStmt()
return storeArgOrLoad(pos, b, base, source.Args[1], mem, tLo, offset+lowOffset)
@@ -524,7 +524,7 @@ func expandCalls(f *Func) {
}
// For nodes that cannot be taken apart -- OpSelectN, other structure selectors.
- switch t.Etype {
+ switch t.Kind() {
case types.TARRAY:
elt := t.Elem()
if source.Type != t && t.NumElem() == 1 && elt.Width == t.Width && t.Width == regSize {
@@ -576,7 +576,7 @@ func expandCalls(f *Func) {
if t.Width == regSize {
break
}
- tHi, tLo := intPairTypes(t.Etype)
+ tHi, tLo := intPairTypes(t.Kind())
sel := source.Block.NewValue1(pos, OpInt64Hi, tHi, source)
mem = storeArgOrLoad(pos, b, base, sel, mem, tHi, offset+hiOffset)
pos = pos.WithNotStmt()
@@ -873,7 +873,7 @@ func expandCalls(f *Func) {
offset := int64(0)
switch v.Op {
case OpStructSelect:
- if w.Type.Etype == types.TSTRUCT {
+ if w.Type.Kind() == types.TSTRUCT {
offset = w.Type.FieldOff(int(v.AuxInt))
} else { // Immediate interface data artifact, offset is zero.
f.Fatalf("Expand calls interface data problem, func %s, v=%s, w=%s\n", f.Name, v.LongString(), w.LongString())
diff --git a/src/cmd/compile/internal/ssa/export_test.go b/src/cmd/compile/internal/ssa/export_test.go
index df83383308..644baa8548 100644
--- a/src/cmd/compile/internal/ssa/export_test.go
+++ b/src/cmd/compile/internal/ssa/export_test.go
@@ -12,7 +12,6 @@ import (
"cmd/internal/obj/s390x"
"cmd/internal/obj/x86"
"cmd/internal/src"
- "fmt"
"testing"
)
@@ -69,7 +68,7 @@ type TestFrontend struct {
func (TestFrontend) StringData(s string) *obj.LSym {
return nil
}
-func (TestFrontend) Auto(pos src.XPos, t *types.Type) ir.Node {
+func (TestFrontend) Auto(pos src.XPos, t *types.Type) *ir.Name {
n := ir.NewNameAt(pos, &types.Sym{Name: "aFakeAuto"})
n.SetClass(ir.PAUTO)
return n
@@ -138,24 +137,11 @@ func init() {
// Initialize just enough of the universe and the types package to make our tests function.
// TODO(josharian): move universe initialization to the types package,
// so this test setup can share it.
-
- types.Tconv = func(t *types.Type, flag, mode int) string {
- return t.Etype.String()
- }
- types.Sconv = func(s *types.Sym, flag, mode int) string {
- return "sym"
- }
- types.FormatSym = func(sym *types.Sym, s fmt.State, verb rune, mode int) {
- fmt.Fprintf(s, "sym")
- }
- types.FormatType = func(t *types.Type, s fmt.State, verb rune, mode int) {
- fmt.Fprintf(s, "%v", t.Etype)
- }
types.Dowidth = func(t *types.Type) {}
for _, typ := range [...]struct {
width int64
- et types.EType
+ et types.Kind
}{
{1, types.TINT8},
{1, types.TUINT8},
diff --git a/src/cmd/compile/internal/ssa/func.go b/src/cmd/compile/internal/ssa/func.go
index ec2c67c1fa..e6c4798a78 100644
--- a/src/cmd/compile/internal/ssa/func.go
+++ b/src/cmd/compile/internal/ssa/func.go
@@ -377,13 +377,7 @@ func (b *Block) NewValue0I(pos src.XPos, op Op, t *types.Type, auxint int64) *Va
}
// NewValue returns a new value in the block with no arguments and an aux value.
-func (b *Block) NewValue0A(pos src.XPos, op Op, t *types.Type, aux interface{}) *Value {
- if _, ok := aux.(int64); ok {
- // Disallow int64 aux values. They should be in the auxint field instead.
- // Maybe we want to allow this at some point, but for now we disallow it
- // to prevent errors like using NewValue1A instead of NewValue1I.
- b.Fatalf("aux field has int64 type op=%s type=%s aux=%v", op, t, aux)
- }
+func (b *Block) NewValue0A(pos src.XPos, op Op, t *types.Type, aux Aux) *Value {
v := b.Func.newValue(op, t, b, pos)
v.AuxInt = 0
v.Aux = aux
@@ -392,7 +386,7 @@ func (b *Block) NewValue0A(pos src.XPos, op Op, t *types.Type, aux interface{})
}
// NewValue returns a new value in the block with no arguments and both an auxint and aux values.
-func (b *Block) NewValue0IA(pos src.XPos, op Op, t *types.Type, auxint int64, aux interface{}) *Value {
+func (b *Block) NewValue0IA(pos src.XPos, op Op, t *types.Type, auxint int64, aux Aux) *Value {
v := b.Func.newValue(op, t, b, pos)
v.AuxInt = auxint
v.Aux = aux
@@ -421,7 +415,7 @@ func (b *Block) NewValue1I(pos src.XPos, op Op, t *types.Type, auxint int64, arg
}
// NewValue1A returns a new value in the block with one argument and an aux value.
-func (b *Block) NewValue1A(pos src.XPos, op Op, t *types.Type, aux interface{}, arg *Value) *Value {
+func (b *Block) NewValue1A(pos src.XPos, op Op, t *types.Type, aux Aux, arg *Value) *Value {
v := b.Func.newValue(op, t, b, pos)
v.AuxInt = 0
v.Aux = aux
@@ -432,7 +426,7 @@ func (b *Block) NewValue1A(pos src.XPos, op Op, t *types.Type, aux interface{},
}
// NewValue1IA returns a new value in the block with one argument and both an auxint and aux values.
-func (b *Block) NewValue1IA(pos src.XPos, op Op, t *types.Type, auxint int64, aux interface{}, arg *Value) *Value {
+func (b *Block) NewValue1IA(pos src.XPos, op Op, t *types.Type, auxint int64, aux Aux, arg *Value) *Value {
v := b.Func.newValue(op, t, b, pos)
v.AuxInt = auxint
v.Aux = aux
@@ -455,7 +449,7 @@ func (b *Block) NewValue2(pos src.XPos, op Op, t *types.Type, arg0, arg1 *Value)
}
// NewValue2A returns a new value in the block with two arguments and one aux values.
-func (b *Block) NewValue2A(pos src.XPos, op Op, t *types.Type, aux interface{}, arg0, arg1 *Value) *Value {
+func (b *Block) NewValue2A(pos src.XPos, op Op, t *types.Type, aux Aux, arg0, arg1 *Value) *Value {
v := b.Func.newValue(op, t, b, pos)
v.AuxInt = 0
v.Aux = aux
@@ -480,7 +474,7 @@ func (b *Block) NewValue2I(pos src.XPos, op Op, t *types.Type, auxint int64, arg
}
// NewValue2IA returns a new value in the block with two arguments and both an auxint and aux values.
-func (b *Block) NewValue2IA(pos src.XPos, op Op, t *types.Type, auxint int64, aux interface{}, arg0, arg1 *Value) *Value {
+func (b *Block) NewValue2IA(pos src.XPos, op Op, t *types.Type, auxint int64, aux Aux, arg0, arg1 *Value) *Value {
v := b.Func.newValue(op, t, b, pos)
v.AuxInt = auxint
v.Aux = aux
@@ -521,7 +515,7 @@ func (b *Block) NewValue3I(pos src.XPos, op Op, t *types.Type, auxint int64, arg
}
// NewValue3A returns a new value in the block with three argument and an aux value.
-func (b *Block) NewValue3A(pos src.XPos, op Op, t *types.Type, aux interface{}, arg0, arg1, arg2 *Value) *Value {
+func (b *Block) NewValue3A(pos src.XPos, op Op, t *types.Type, aux Aux, arg0, arg1, arg2 *Value) *Value {
v := b.Func.newValue(op, t, b, pos)
v.AuxInt = 0
v.Aux = aux
@@ -633,7 +627,7 @@ func (f *Func) ConstNil(t *types.Type) *Value {
}
func (f *Func) ConstEmptyString(t *types.Type) *Value {
v := f.constVal(OpConstString, t, constEmptyStringMagic, false)
- v.Aux = ""
+ v.Aux = StringToAux("")
return v
}
func (f *Func) ConstOffPtrSP(t *types.Type, c int64, sp *Value) *Value {
@@ -790,10 +784,10 @@ func (f *Func) spSb() (sp, sb *Value) {
}
}
if sb == nil {
- sb = f.Entry.NewValue0(initpos, OpSB, f.Config.Types.Uintptr)
+ sb = f.Entry.NewValue0(initpos.WithNotStmt(), OpSB, f.Config.Types.Uintptr)
}
if sp == nil {
- sp = f.Entry.NewValue0(initpos, OpSP, f.Config.Types.Uintptr)
+ sp = f.Entry.NewValue0(initpos.WithNotStmt(), OpSP, f.Config.Types.Uintptr)
}
return
}
diff --git a/src/cmd/compile/internal/ssa/func_test.go b/src/cmd/compile/internal/ssa/func_test.go
index 568c6436f5..276c444b9a 100644
--- a/src/cmd/compile/internal/ssa/func_test.go
+++ b/src/cmd/compile/internal/ssa/func_test.go
@@ -232,7 +232,7 @@ func Bloc(name string, entries ...interface{}) bloc {
}
// Valu defines a value in a block.
-func Valu(name string, op Op, t *types.Type, auxint int64, aux interface{}, args ...string) valu {
+func Valu(name string, op Op, t *types.Type, auxint int64, aux Aux, args ...string) valu {
return valu{name, op, t, auxint, aux, args}
}
@@ -277,7 +277,7 @@ type valu struct {
op Op
t *types.Type
auxint int64
- aux interface{}
+ aux Aux
args []string
}
@@ -402,12 +402,12 @@ func TestEquiv(t *testing.T) {
cfg.Fun("entry",
Bloc("entry",
Valu("mem", OpInitMem, types.TypeMem, 0, nil),
- Valu("a", OpConst64, cfg.config.Types.Int64, 0, 14),
+ Valu("a", OpConstString, cfg.config.Types.String, 0, StringToAux("foo")),
Exit("mem"))),
cfg.Fun("entry",
Bloc("entry",
Valu("mem", OpInitMem, types.TypeMem, 0, nil),
- Valu("a", OpConst64, cfg.config.Types.Int64, 0, 26),
+ Valu("a", OpConstString, cfg.config.Types.String, 0, StringToAux("bar")),
Exit("mem"))),
},
// value args different
diff --git a/src/cmd/compile/internal/ssa/gen/386.rules b/src/cmd/compile/internal/ssa/gen/386.rules
index 537705c681..fbc12fd672 100644
--- a/src/cmd/compile/internal/ssa/gen/386.rules
+++ b/src/cmd/compile/internal/ssa/gen/386.rules
@@ -531,6 +531,7 @@
// fold ADDL into LEAL
(ADDLconst [c] (LEAL [d] {s} x)) && is32Bit(int64(c)+int64(d)) => (LEAL [c+d] {s} x)
(LEAL [c] {s} (ADDLconst [d] x)) && is32Bit(int64(c)+int64(d)) => (LEAL [c+d] {s} x)
+(ADDLconst [c] x:(SP)) => (LEAL [c] x) // so it is rematerializeable
(LEAL [c] {s} (ADDL x y)) && x.Op != OpSB && y.Op != OpSB => (LEAL1 [c] {s} x y)
(ADDL x (LEAL [c] {s} y)) && x.Op != OpSB && y.Op != OpSB => (LEAL1 [c] {s} x y)
diff --git a/src/cmd/compile/internal/ssa/gen/ARM.rules b/src/cmd/compile/internal/ssa/gen/ARM.rules
index 946acd4ccc..11c36b5da3 100644
--- a/src/cmd/compile/internal/ssa/gen/ARM.rules
+++ b/src/cmd/compile/internal/ssa/gen/ARM.rules
@@ -760,8 +760,8 @@
(MUL (MOVWconst [c]) (MOVWconst [d])) => (MOVWconst [c*d])
(MULA (MOVWconst [c]) (MOVWconst [d]) a) => (ADDconst [c*d] a)
(MULS (MOVWconst [c]) (MOVWconst [d]) a) => (SUBconst [c*d] a)
-(Select0 (CALLudiv (MOVWconst [c]) (MOVWconst [d]))) => (MOVWconst [int32(uint32(c)/uint32(d))])
-(Select1 (CALLudiv (MOVWconst [c]) (MOVWconst [d]))) => (MOVWconst [int32(uint32(c)%uint32(d))])
+(Select0 (CALLudiv (MOVWconst [c]) (MOVWconst [d]))) && d != 0 => (MOVWconst [int32(uint32(c)/uint32(d))])
+(Select1 (CALLudiv (MOVWconst [c]) (MOVWconst [d]))) && d != 0 => (MOVWconst [int32(uint32(c)%uint32(d))])
(ANDconst [c] (MOVWconst [d])) => (MOVWconst [c&d])
(ANDconst [c] (ANDconst [d] x)) => (ANDconst [c&d] x)
(ORconst [c] (MOVWconst [d])) => (MOVWconst [c|d])
@@ -1369,38 +1369,38 @@
(LE (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 => (LEnoov (CMNshiftLLreg x y z) yes no)
(LE (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 => (LEnoov (CMNshiftRLreg x y z) yes no)
(LE (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 => (LEnoov (CMNshiftRAreg x y z) yes no)
-(LT (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 => (LT (TST x y) yes no)
-(LT (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 => (LT (TSTconst [c] x) yes no)
-(LT (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 => (LT (TSTshiftLL x y [c]) yes no)
-(LT (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 => (LT (TSTshiftRL x y [c]) yes no)
-(LT (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) && l.Uses==1 => (LT (TSTshiftRA x y [c]) yes no)
-(LT (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) && l.Uses==1 => (LT (TSTshiftLLreg x y z) yes no)
-(LT (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) && l.Uses==1 => (LT (TSTshiftRLreg x y z) yes no)
-(LT (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) && l.Uses==1 => (LT (TSTshiftRAreg x y z) yes no)
-(LE (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 => (LE (TST x y) yes no)
-(LE (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 => (LE (TSTconst [c] x) yes no)
-(LE (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 => (LE (TSTshiftLL x y [c]) yes no)
-(LE (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 => (LE (TSTshiftRL x y [c]) yes no)
-(LE (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) && l.Uses==1 => (LE (TSTshiftRA x y [c]) yes no)
-(LE (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) && l.Uses==1 => (LE (TSTshiftLLreg x y z) yes no)
-(LE (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) && l.Uses==1 => (LE (TSTshiftRLreg x y z) yes no)
-(LE (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) && l.Uses==1 => (LE (TSTshiftRAreg x y z) yes no)
-(LT (CMPconst [0] l:(XOR x y)) yes no) && l.Uses==1 => (LT (TEQ x y) yes no)
-(LT (CMPconst [0] l:(XORconst [c] x)) yes no) && l.Uses==1 => (LT (TEQconst [c] x) yes no)
-(LT (CMPconst [0] l:(XORshiftLL x y [c])) yes no) && l.Uses==1 => (LT (TEQshiftLL x y [c]) yes no)
-(LT (CMPconst [0] l:(XORshiftRL x y [c])) yes no) && l.Uses==1 => (LT (TEQshiftRL x y [c]) yes no)
-(LT (CMPconst [0] l:(XORshiftRA x y [c])) yes no) && l.Uses==1 => (LT (TEQshiftRA x y [c]) yes no)
-(LT (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 => (LT (TEQshiftLLreg x y z) yes no)
-(LT (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 => (LT (TEQshiftRLreg x y z) yes no)
-(LT (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 => (LT (TEQshiftRAreg x y z) yes no)
-(LE (CMPconst [0] l:(XOR x y)) yes no) && l.Uses==1 => (LE (TEQ x y) yes no)
-(LE (CMPconst [0] l:(XORconst [c] x)) yes no) && l.Uses==1 => (LE (TEQconst [c] x) yes no)
-(LE (CMPconst [0] l:(XORshiftLL x y [c])) yes no) && l.Uses==1 => (LE (TEQshiftLL x y [c]) yes no)
-(LE (CMPconst [0] l:(XORshiftRL x y [c])) yes no) && l.Uses==1 => (LE (TEQshiftRL x y [c]) yes no)
-(LE (CMPconst [0] l:(XORshiftRA x y [c])) yes no) && l.Uses==1 => (LE (TEQshiftRA x y [c]) yes no)
-(LE (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 => (LE (TEQshiftLLreg x y z) yes no)
-(LE (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 => (LE (TEQshiftRLreg x y z) yes no)
-(LE (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 => (LE (TEQshiftRAreg x y z) yes no)
+(LT (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 => (LTnoov (TST x y) yes no)
+(LT (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 => (LTnoov (TSTconst [c] x) yes no)
+(LT (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 => (LTnoov (TSTshiftLL x y [c]) yes no)
+(LT (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 => (LTnoov (TSTshiftRL x y [c]) yes no)
+(LT (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) && l.Uses==1 => (LTnoov (TSTshiftRA x y [c]) yes no)
+(LT (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) && l.Uses==1 => (LTnoov (TSTshiftLLreg x y z) yes no)
+(LT (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) && l.Uses==1 => (LTnoov (TSTshiftRLreg x y z) yes no)
+(LT (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) && l.Uses==1 => (LTnoov (TSTshiftRAreg x y z) yes no)
+(LE (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 => (LEnoov (TST x y) yes no)
+(LE (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 => (LEnoov (TSTconst [c] x) yes no)
+(LE (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 => (LEnoov (TSTshiftLL x y [c]) yes no)
+(LE (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 => (LEnoov (TSTshiftRL x y [c]) yes no)
+(LE (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) && l.Uses==1 => (LEnoov (TSTshiftRA x y [c]) yes no)
+(LE (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) && l.Uses==1 => (LEnoov (TSTshiftLLreg x y z) yes no)
+(LE (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) && l.Uses==1 => (LEnoov (TSTshiftRLreg x y z) yes no)
+(LE (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) && l.Uses==1 => (LEnoov (TSTshiftRAreg x y z) yes no)
+(LT (CMPconst [0] l:(XOR x y)) yes no) && l.Uses==1 => (LTnoov (TEQ x y) yes no)
+(LT (CMPconst [0] l:(XORconst [c] x)) yes no) && l.Uses==1 => (LTnoov (TEQconst [c] x) yes no)
+(LT (CMPconst [0] l:(XORshiftLL x y [c])) yes no) && l.Uses==1 => (LTnoov (TEQshiftLL x y [c]) yes no)
+(LT (CMPconst [0] l:(XORshiftRL x y [c])) yes no) && l.Uses==1 => (LTnoov (TEQshiftRL x y [c]) yes no)
+(LT (CMPconst [0] l:(XORshiftRA x y [c])) yes no) && l.Uses==1 => (LTnoov (TEQshiftRA x y [c]) yes no)
+(LT (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 => (LTnoov (TEQshiftLLreg x y z) yes no)
+(LT (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 => (LTnoov (TEQshiftRLreg x y z) yes no)
+(LT (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 => (LTnoov (TEQshiftRAreg x y z) yes no)
+(LE (CMPconst [0] l:(XOR x y)) yes no) && l.Uses==1 => (LEnoov (TEQ x y) yes no)
+(LE (CMPconst [0] l:(XORconst [c] x)) yes no) && l.Uses==1 => (LEnoov (TEQconst [c] x) yes no)
+(LE (CMPconst [0] l:(XORshiftLL x y [c])) yes no) && l.Uses==1 => (LEnoov (TEQshiftLL x y [c]) yes no)
+(LE (CMPconst [0] l:(XORshiftRL x y [c])) yes no) && l.Uses==1 => (LEnoov (TEQshiftRL x y [c]) yes no)
+(LE (CMPconst [0] l:(XORshiftRA x y [c])) yes no) && l.Uses==1 => (LEnoov (TEQshiftRA x y [c]) yes no)
+(LE (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 => (LEnoov (TEQshiftLLreg x y z) yes no)
+(LE (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 => (LEnoov (TEQshiftRLreg x y z) yes no)
+(LE (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 => (LEnoov (TEQshiftRAreg x y z) yes no)
(GT (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 => (GTnoov (CMP x y) yes no)
(GT (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 => (GTnoov (CMP a (MUL x y)) yes no)
(GT (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 => (GTnoov (CMPconst [c] x) yes no)
@@ -1436,39 +1436,39 @@
(GE (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 => (GEnoov (CMNshiftLLreg x y z) yes no)
(GE (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 => (GEnoov (CMNshiftRLreg x y z) yes no)
(GE (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 => (GEnoov (CMNshiftRAreg x y z) yes no)
-(GT (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 => (GT (TST x y) yes no)
(GT (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 => (GTnoov (CMN a (MUL x y)) yes no)
-(GT (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 => (GT (TSTconst [c] x) yes no)
-(GT (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 => (GT (TSTshiftLL x y [c]) yes no)
-(GT (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 => (GT (TSTshiftRL x y [c]) yes no)
-(GT (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) && l.Uses==1 => (GT (TSTshiftRA x y [c]) yes no)
-(GT (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) && l.Uses==1 => (GT (TSTshiftLLreg x y z) yes no)
-(GT (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) && l.Uses==1 => (GT (TSTshiftRLreg x y z) yes no)
-(GT (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) && l.Uses==1 => (GT (TSTshiftRAreg x y z) yes no)
-(GE (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 => (GE (TST x y) yes no)
-(GE (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 => (GE (TSTconst [c] x) yes no)
-(GE (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 => (GE (TSTshiftLL x y [c]) yes no)
-(GE (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 => (GE (TSTshiftRL x y [c]) yes no)
-(GE (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) && l.Uses==1 => (GE (TSTshiftRA x y [c]) yes no)
-(GE (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) && l.Uses==1 => (GE (TSTshiftLLreg x y z) yes no)
-(GE (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) && l.Uses==1 => (GE (TSTshiftRLreg x y z) yes no)
-(GE (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) && l.Uses==1 => (GE (TSTshiftRAreg x y z) yes no)
-(GT (CMPconst [0] l:(XOR x y)) yes no) && l.Uses==1 => (GT (TEQ x y) yes no)
-(GT (CMPconst [0] l:(XORconst [c] x)) yes no) && l.Uses==1 => (GT (TEQconst [c] x) yes no)
-(GT (CMPconst [0] l:(XORshiftLL x y [c])) yes no) && l.Uses==1 => (GT (TEQshiftLL x y [c]) yes no)
-(GT (CMPconst [0] l:(XORshiftRL x y [c])) yes no) && l.Uses==1 => (GT (TEQshiftRL x y [c]) yes no)
-(GT (CMPconst [0] l:(XORshiftRA x y [c])) yes no) && l.Uses==1 => (GT (TEQshiftRA x y [c]) yes no)
-(GT (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 => (GT (TEQshiftLLreg x y z) yes no)
-(GT (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 => (GT (TEQshiftRLreg x y z) yes no)
-(GT (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 => (GT (TEQshiftRAreg x y z) yes no)
-(GE (CMPconst [0] l:(XOR x y)) yes no) && l.Uses==1 => (GE (TEQ x y) yes no)
-(GE (CMPconst [0] l:(XORconst [c] x)) yes no) && l.Uses==1 => (GE (TEQconst [c] x) yes no)
-(GE (CMPconst [0] l:(XORshiftLL x y [c])) yes no) && l.Uses==1 => (GE (TEQshiftLL x y [c]) yes no)
-(GE (CMPconst [0] l:(XORshiftRL x y [c])) yes no) && l.Uses==1 => (GE (TEQshiftRL x y [c]) yes no)
-(GE (CMPconst [0] l:(XORshiftRA x y [c])) yes no) && l.Uses==1 => (GE (TEQshiftRA x y [c]) yes no)
-(GE (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 => (GE (TEQshiftLLreg x y z) yes no)
-(GE (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 => (GE (TEQshiftRLreg x y z) yes no)
-(GE (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 => (GE (TEQshiftRAreg x y z) yes no)
+(GT (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 => (GTnoov (TST x y) yes no)
+(GT (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 => (GTnoov (TSTconst [c] x) yes no)
+(GT (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 => (GTnoov (TSTshiftLL x y [c]) yes no)
+(GT (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 => (GTnoov (TSTshiftRL x y [c]) yes no)
+(GT (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) && l.Uses==1 => (GTnoov (TSTshiftRA x y [c]) yes no)
+(GT (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) && l.Uses==1 => (GTnoov (TSTshiftLLreg x y z) yes no)
+(GT (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) && l.Uses==1 => (GTnoov (TSTshiftRLreg x y z) yes no)
+(GT (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) && l.Uses==1 => (GTnoov (TSTshiftRAreg x y z) yes no)
+(GE (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 => (GEnoov (TST x y) yes no)
+(GE (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 => (GEnoov (TSTconst [c] x) yes no)
+(GE (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 => (GEnoov (TSTshiftLL x y [c]) yes no)
+(GE (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 => (GEnoov (TSTshiftRL x y [c]) yes no)
+(GE (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) && l.Uses==1 => (GEnoov (TSTshiftRA x y [c]) yes no)
+(GE (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) && l.Uses==1 => (GEnoov (TSTshiftLLreg x y z) yes no)
+(GE (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) && l.Uses==1 => (GEnoov (TSTshiftRLreg x y z) yes no)
+(GE (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) && l.Uses==1 => (GEnoov (TSTshiftRAreg x y z) yes no)
+(GT (CMPconst [0] l:(XOR x y)) yes no) && l.Uses==1 => (GTnoov (TEQ x y) yes no)
+(GT (CMPconst [0] l:(XORconst [c] x)) yes no) && l.Uses==1 => (GTnoov (TEQconst [c] x) yes no)
+(GT (CMPconst [0] l:(XORshiftLL x y [c])) yes no) && l.Uses==1 => (GTnoov (TEQshiftLL x y [c]) yes no)
+(GT (CMPconst [0] l:(XORshiftRL x y [c])) yes no) && l.Uses==1 => (GTnoov (TEQshiftRL x y [c]) yes no)
+(GT (CMPconst [0] l:(XORshiftRA x y [c])) yes no) && l.Uses==1 => (GTnoov (TEQshiftRA x y [c]) yes no)
+(GT (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 => (GTnoov (TEQshiftLLreg x y z) yes no)
+(GT (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 => (GTnoov (TEQshiftRLreg x y z) yes no)
+(GT (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 => (GTnoov (TEQshiftRAreg x y z) yes no)
+(GE (CMPconst [0] l:(XOR x y)) yes no) && l.Uses==1 => (GEnoov (TEQ x y) yes no)
+(GE (CMPconst [0] l:(XORconst [c] x)) yes no) && l.Uses==1 => (GEnoov (TEQconst [c] x) yes no)
+(GE (CMPconst [0] l:(XORshiftLL x y [c])) yes no) && l.Uses==1 => (GEnoov (TEQshiftLL x y [c]) yes no)
+(GE (CMPconst [0] l:(XORshiftRL x y [c])) yes no) && l.Uses==1 => (GEnoov (TEQshiftRL x y [c]) yes no)
+(GE (CMPconst [0] l:(XORshiftRA x y [c])) yes no) && l.Uses==1 => (GEnoov (TEQshiftRA x y [c]) yes no)
+(GE (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 => (GEnoov (TEQshiftLLreg x y z) yes no)
+(GE (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 => (GEnoov (TEQshiftRLreg x y z) yes no)
+(GE (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 => (GEnoov (TEQshiftRAreg x y z) yes no)
(MOVBUload [off] {sym} (SB) _) && symIsRO(sym) => (MOVWconst [int32(read8(sym, int64(off)))])
(MOVHUload [off] {sym} (SB) _) && symIsRO(sym) => (MOVWconst [int32(read16(sym, int64(off), config.ctxt.Arch.ByteOrder))])
diff --git a/src/cmd/compile/internal/ssa/gen/ARM64.rules b/src/cmd/compile/internal/ssa/gen/ARM64.rules
index 9edc0c94b0..3f4d0c1c52 100644
--- a/src/cmd/compile/internal/ssa/gen/ARM64.rules
+++ b/src/cmd/compile/internal/ssa/gen/ARM64.rules
@@ -1372,14 +1372,14 @@
(MADDW a (MOVDconst [c]) (MOVDconst [d])) => (ADDconst [int64(int32(c)*int32(d))] a)
(MSUB a (MOVDconst [c]) (MOVDconst [d])) => (SUBconst [c*d] a)
(MSUBW a (MOVDconst [c]) (MOVDconst [d])) => (SUBconst [int64(int32(c)*int32(d))] a)
-(DIV (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [c/d])
-(UDIV (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [int64(uint64(c)/uint64(d))])
-(DIVW (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [int64(int32(c)/int32(d))])
-(UDIVW (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [int64(uint32(c)/uint32(d))])
-(MOD (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [c%d])
-(UMOD (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [int64(uint64(c)%uint64(d))])
-(MODW (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [int64(int32(c)%int32(d))])
-(UMODW (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [int64(uint32(c)%uint32(d))])
+(DIV (MOVDconst [c]) (MOVDconst [d])) && d != 0 => (MOVDconst [c/d])
+(UDIV (MOVDconst [c]) (MOVDconst [d])) && d != 0 => (MOVDconst [int64(uint64(c)/uint64(d))])
+(DIVW (MOVDconst [c]) (MOVDconst [d])) && d != 0 => (MOVDconst [int64(int32(c)/int32(d))])
+(UDIVW (MOVDconst [c]) (MOVDconst [d])) && d != 0 => (MOVDconst [int64(uint32(c)/uint32(d))])
+(MOD (MOVDconst [c]) (MOVDconst [d])) && d != 0 => (MOVDconst [c%d])
+(UMOD (MOVDconst [c]) (MOVDconst [d])) && d != 0 => (MOVDconst [int64(uint64(c)%uint64(d))])
+(MODW (MOVDconst [c]) (MOVDconst [d])) && d != 0 => (MOVDconst [int64(int32(c)%int32(d))])
+(UMODW (MOVDconst [c]) (MOVDconst [d])) && d != 0 => (MOVDconst [int64(uint32(c)%uint32(d))])
(ANDconst [c] (MOVDconst [d])) => (MOVDconst [c&d])
(ANDconst [c] (ANDconst [d] x)) => (ANDconst [c&d] x)
(ANDconst [c] (MOVWUreg x)) => (ANDconst [c&(1<<32-1)] x)
diff --git a/src/cmd/compile/internal/ssa/gen/MIPS.rules b/src/cmd/compile/internal/ssa/gen/MIPS.rules
index 470cc66869..8ad2c90ac3 100644
--- a/src/cmd/compile/internal/ssa/gen/MIPS.rules
+++ b/src/cmd/compile/internal/ssa/gen/MIPS.rules
@@ -626,10 +626,10 @@
(MUL (MOVWconst [c]) (MOVWconst [d])) => (MOVWconst [c*d])
(Select1 (MULTU (MOVWconst [c]) (MOVWconst [d]))) => (MOVWconst [int32(uint32(c)*uint32(d))])
(Select0 (MULTU (MOVWconst [c]) (MOVWconst [d]))) => (MOVWconst [int32((int64(uint32(c))*int64(uint32(d)))>>32)])
-(Select1 (DIV (MOVWconst [c]) (MOVWconst [d]))) => (MOVWconst [c/d])
-(Select1 (DIVU (MOVWconst [c]) (MOVWconst [d]))) => (MOVWconst [int32(uint32(c)/uint32(d))])
-(Select0 (DIV (MOVWconst [c]) (MOVWconst [d]))) => (MOVWconst [c%d])
-(Select0 (DIVU (MOVWconst [c]) (MOVWconst [d]))) => (MOVWconst [int32(uint32(c)%uint32(d))])
+(Select1 (DIV (MOVWconst [c]) (MOVWconst [d]))) && d != 0 => (MOVWconst [c/d])
+(Select1 (DIVU (MOVWconst [c]) (MOVWconst [d]))) && d != 0 => (MOVWconst [int32(uint32(c)/uint32(d))])
+(Select0 (DIV (MOVWconst [c]) (MOVWconst [d]))) && d != 0 => (MOVWconst [c%d])
+(Select0 (DIVU (MOVWconst [c]) (MOVWconst [d]))) && d != 0 => (MOVWconst [int32(uint32(c)%uint32(d))])
(ANDconst [c] (MOVWconst [d])) => (MOVWconst [c&d])
(ANDconst [c] (ANDconst [d] x)) => (ANDconst [c&d] x)
(ORconst [c] (MOVWconst [d])) => (MOVWconst [c|d])
diff --git a/src/cmd/compile/internal/ssa/gen/MIPS64.rules b/src/cmd/compile/internal/ssa/gen/MIPS64.rules
index 9af0f93333..088c9b1ac4 100644
--- a/src/cmd/compile/internal/ssa/gen/MIPS64.rules
+++ b/src/cmd/compile/internal/ssa/gen/MIPS64.rules
@@ -617,10 +617,10 @@
(SRLVconst [c] (MOVVconst [d])) => (MOVVconst [int64(uint64(d)>>uint64(c))])
(SRAVconst [c] (MOVVconst [d])) => (MOVVconst [d>>uint64(c)])
(Select1 (MULVU (MOVVconst [c]) (MOVVconst [d]))) => (MOVVconst [c*d])
-(Select1 (DIVV (MOVVconst [c]) (MOVVconst [d]))) => (MOVVconst [c/d])
-(Select1 (DIVVU (MOVVconst [c]) (MOVVconst [d]))) => (MOVVconst [int64(uint64(c)/uint64(d))])
-(Select0 (DIVV (MOVVconst [c]) (MOVVconst [d]))) => (MOVVconst [c%d]) // mod
-(Select0 (DIVVU (MOVVconst [c]) (MOVVconst [d]))) => (MOVVconst [int64(uint64(c)%uint64(d))]) // mod
+(Select1 (DIVV (MOVVconst [c]) (MOVVconst [d]))) && d != 0 => (MOVVconst [c/d])
+(Select1 (DIVVU (MOVVconst [c]) (MOVVconst [d]))) && d != 0 => (MOVVconst [int64(uint64(c)/uint64(d))])
+(Select0 (DIVV (MOVVconst [c]) (MOVVconst [d]))) && d != 0 => (MOVVconst [c%d]) // mod
+(Select0 (DIVVU (MOVVconst [c]) (MOVVconst [d]))) && d != 0 => (MOVVconst [int64(uint64(c)%uint64(d))]) // mod
(ANDconst [c] (MOVVconst [d])) => (MOVVconst [c&d])
(ANDconst [c] (ANDconst [d] x)) => (ANDconst [c&d] x)
(ORconst [c] (MOVVconst [d])) => (MOVVconst [c|d])
diff --git a/src/cmd/compile/internal/ssa/gen/PPC64.rules b/src/cmd/compile/internal/ssa/gen/PPC64.rules
index 31b186d167..c064046172 100644
--- a/src/cmd/compile/internal/ssa/gen/PPC64.rules
+++ b/src/cmd/compile/internal/ssa/gen/PPC64.rules
@@ -845,6 +845,7 @@
(SUB x (MOVDconst [c])) && is32Bit(-c) => (ADDconst [-c] x)
(ADDconst [c] (MOVDaddr [d] {sym} x)) && is32Bit(c+int64(d)) => (MOVDaddr [int32(c+int64(d))] {sym} x)
+(ADDconst [c] x:(SP)) && is32Bit(c) => (MOVDaddr [int32(c)] x) // so it is rematerializeable
(MULL(W|D) x (MOVDconst [c])) && is16Bit(c) => (MULL(W|D)const [int32(c)] x)
diff --git a/src/cmd/compile/internal/ssa/gen/Wasm.rules b/src/cmd/compile/internal/ssa/gen/Wasm.rules
index ea12c5d617..fc45cd3ed5 100644
--- a/src/cmd/compile/internal/ssa/gen/Wasm.rules
+++ b/src/cmd/compile/internal/ssa/gen/Wasm.rules
@@ -399,6 +399,7 @@
// folding offset into address
(I64AddConst [off] (LoweredAddr {sym} [off2] base)) && isU32Bit(off+int64(off2)) =>
(LoweredAddr {sym} [int32(off)+off2] base)
+(I64AddConst [off] x:(SP)) && isU32Bit(off) => (LoweredAddr [int32(off)] x) // so it is rematerializeable
// transforming readonly globals into constants
(I64Load [off] (LoweredAddr {sym} [off2] (SB)) _) && symIsRO(sym) && isU32Bit(off+int64(off2)) => (I64Const [int64(read64(sym, off+int64(off2), config.ctxt.Arch.ByteOrder))])
diff --git a/src/cmd/compile/internal/ssa/location.go b/src/cmd/compile/internal/ssa/location.go
index 3dc3a81703..69f90d9ab4 100644
--- a/src/cmd/compile/internal/ssa/location.go
+++ b/src/cmd/compile/internal/ssa/location.go
@@ -60,7 +60,7 @@ func (r *Register) GCNum() int16 {
// { N: len, Type: int, Off: 0, SplitOf: parent, SplitOffset: 8}
// parent = &{N: s, Type: string}
type LocalSlot struct {
- N ir.Node // an ONAME *gc.Node representing a stack location.
+ N *ir.Name // an ONAME *ir.Name representing a stack location.
Type *types.Type // type of slot
Off int64 // offset of slot in N
diff --git a/src/cmd/compile/internal/ssa/nilcheck.go b/src/cmd/compile/internal/ssa/nilcheck.go
index b36f6b97e1..bae50657c9 100644
--- a/src/cmd/compile/internal/ssa/nilcheck.go
+++ b/src/cmd/compile/internal/ssa/nilcheck.go
@@ -236,7 +236,7 @@ func nilcheckelim2(f *Func) {
continue
}
if v.Type.IsMemory() || v.Type.IsTuple() && v.Type.FieldType(1).IsMemory() {
- if v.Op == OpVarKill || v.Op == OpVarLive || (v.Op == OpVarDef && !v.Aux.(ir.Node).Type().HasPointers()) {
+ if v.Op == OpVarKill || v.Op == OpVarLive || (v.Op == OpVarDef && !v.Aux.(*ir.Name).Type().HasPointers()) {
// These ops don't really change memory.
continue
// Note: OpVarDef requires that the defined variable not have pointers.
diff --git a/src/cmd/compile/internal/ssa/nilcheck_test.go b/src/cmd/compile/internal/ssa/nilcheck_test.go
index 16d94614d8..2e32afe2a6 100644
--- a/src/cmd/compile/internal/ssa/nilcheck_test.go
+++ b/src/cmd/compile/internal/ssa/nilcheck_test.go
@@ -212,7 +212,7 @@ func TestNilcheckPhi(t *testing.T) {
Valu("mem", OpInitMem, types.TypeMem, 0, nil),
Valu("sb", OpSB, c.config.Types.Uintptr, 0, nil),
Valu("sp", OpSP, c.config.Types.Uintptr, 0, nil),
- Valu("baddr", OpLocalAddr, c.config.Types.Bool, 0, "b", "sp", "mem"),
+ Valu("baddr", OpLocalAddr, c.config.Types.Bool, 0, StringToAux("b"), "sp", "mem"),
Valu("bool1", OpLoad, c.config.Types.Bool, 0, nil, "baddr", "mem"),
If("bool1", "b1", "b2")),
Bloc("b1",
diff --git a/src/cmd/compile/internal/ssa/op.go b/src/cmd/compile/internal/ssa/op.go
index 6f029a421e..9bc5aaec02 100644
--- a/src/cmd/compile/internal/ssa/op.go
+++ b/src/cmd/compile/internal/ssa/op.go
@@ -197,6 +197,8 @@ func ClosureAuxCall(args []Param, results []Param) *AuxCall {
return &AuxCall{Fn: nil, args: args, results: results}
}
+func (*AuxCall) CanBeAnSSAAux() {}
+
const (
auxNone auxType = iota
auxBool // auxInt is 0/1 for false/true
@@ -246,8 +248,8 @@ const (
// - a *obj.LSym, for an offset from SB (the global pointer)
// - nil, for no offset
type Sym interface {
- String() string
CanBeAnSSASym()
+ CanBeAnSSAAux()
}
// A ValAndOff is used by the several opcodes. It holds
diff --git a/src/cmd/compile/internal/ssa/regalloc.go b/src/cmd/compile/internal/ssa/regalloc.go
index 459a9923f7..8c25b1c81d 100644
--- a/src/cmd/compile/internal/ssa/regalloc.go
+++ b/src/cmd/compile/internal/ssa/regalloc.go
@@ -783,9 +783,9 @@ func (s *regAllocState) compatRegs(t *types.Type) regMask {
return 0
}
if t.IsFloat() || t == types.TypeInt128 {
- if t.Etype == types.TFLOAT32 && s.f.Config.fp32RegMask != 0 {
+ if t.Kind() == types.TFLOAT32 && s.f.Config.fp32RegMask != 0 {
m = s.f.Config.fp32RegMask
- } else if t.Etype == types.TFLOAT64 && s.f.Config.fp64RegMask != 0 {
+ } else if t.Kind() == types.TFLOAT64 && s.f.Config.fp64RegMask != 0 {
m = s.f.Config.fp64RegMask
} else {
m = s.f.Config.fpRegMask
@@ -1249,7 +1249,7 @@ func (s *regAllocState) regalloc(f *Func) {
// This forces later liveness analysis to make the
// value live at this point.
v.SetArg(0, s.makeSpill(a, b))
- } else if _, ok := a.Aux.(ir.Node); ok && vi.rematerializeable {
+ } else if _, ok := a.Aux.(*ir.Name); ok && vi.rematerializeable {
// Rematerializeable value with a gc.Node. This is the address of
// a stack object (e.g. an LEAQ). Keep the object live.
// Change it to VarLive, which is what plive expects for locals.
diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go
index 24efd38fb7..9abfe0938b 100644
--- a/src/cmd/compile/internal/ssa/rewrite.go
+++ b/src/cmd/compile/internal/ssa/rewrite.go
@@ -678,43 +678,53 @@ func opToAuxInt(o Op) int64 {
return int64(o)
}
-func auxToString(i interface{}) string {
- return i.(string)
+// Aux is an interface to hold miscellaneous data in Blocks and Values.
+type Aux interface {
+ CanBeAnSSAAux()
}
-func auxToSym(i interface{}) Sym {
+
+// stringAux wraps string values for use in Aux.
+type stringAux string
+
+func (stringAux) CanBeAnSSAAux() {}
+
+func auxToString(i Aux) string {
+ return string(i.(stringAux))
+}
+func auxToSym(i Aux) Sym {
// TODO: kind of a hack - allows nil interface through
s, _ := i.(Sym)
return s
}
-func auxToType(i interface{}) *types.Type {
+func auxToType(i Aux) *types.Type {
return i.(*types.Type)
}
-func auxToCall(i interface{}) *AuxCall {
+func auxToCall(i Aux) *AuxCall {
return i.(*AuxCall)
}
-func auxToS390xCCMask(i interface{}) s390x.CCMask {
+func auxToS390xCCMask(i Aux) s390x.CCMask {
return i.(s390x.CCMask)
}
-func auxToS390xRotateParams(i interface{}) s390x.RotateParams {
+func auxToS390xRotateParams(i Aux) s390x.RotateParams {
return i.(s390x.RotateParams)
}
-func stringToAux(s string) interface{} {
+func StringToAux(s string) Aux {
+ return stringAux(s)
+}
+func symToAux(s Sym) Aux {
return s
}
-func symToAux(s Sym) interface{} {
+func callToAux(s *AuxCall) Aux {
return s
}
-func callToAux(s *AuxCall) interface{} {
- return s
-}
-func typeToAux(t *types.Type) interface{} {
+func typeToAux(t *types.Type) Aux {
return t
}
-func s390xCCMaskToAux(c s390x.CCMask) interface{} {
+func s390xCCMaskToAux(c s390x.CCMask) Aux {
return c
}
-func s390xRotateParamsToAux(r s390x.RotateParams) interface{} {
+func s390xRotateParamsToAux(r s390x.RotateParams) Aux {
return r
}
@@ -725,7 +735,7 @@ func uaddOvf(a, b int64) bool {
// de-virtualize an InterCall
// 'sym' is the symbol for the itab
-func devirt(v *Value, aux interface{}, sym Sym, offset int64) *AuxCall {
+func devirt(v *Value, aux Aux, sym Sym, offset int64) *AuxCall {
f := v.Block.Func
n, ok := sym.(*obj.LSym)
if !ok {
@@ -748,7 +758,7 @@ func devirt(v *Value, aux interface{}, sym Sym, offset int64) *AuxCall {
// de-virtualize an InterLECall
// 'sym' is the symbol for the itab
-func devirtLESym(v *Value, aux interface{}, sym Sym, offset int64) *obj.LSym {
+func devirtLESym(v *Value, aux Aux, sym Sym, offset int64) *obj.LSym {
n, ok := sym.(*obj.LSym)
if !ok {
return nil
diff --git a/src/cmd/compile/internal/ssa/rewrite386.go b/src/cmd/compile/internal/ssa/rewrite386.go
index eca4817b9b..2acdccd568 100644
--- a/src/cmd/compile/internal/ssa/rewrite386.go
+++ b/src/cmd/compile/internal/ssa/rewrite386.go
@@ -1027,6 +1027,19 @@ func rewriteValue386_Op386ADDLconst(v *Value) bool {
v.AddArg(x)
return true
}
+ // match: (ADDLconst [c] x:(SP))
+ // result: (LEAL [c] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ x := v_0
+ if x.Op != OpSP {
+ break
+ }
+ v.reset(Op386LEAL)
+ v.AuxInt = int32ToAuxInt(c)
+ v.AddArg(x)
+ return true
+ }
// match: (ADDLconst [c] (LEAL1 [d] {s} x y))
// cond: is32Bit(int64(c)+int64(d))
// result: (LEAL1 [c+d] {s} x y)
diff --git a/src/cmd/compile/internal/ssa/rewriteARM.go b/src/cmd/compile/internal/ssa/rewriteARM.go
index 47fd0a94cc..d9d439fa63 100644
--- a/src/cmd/compile/internal/ssa/rewriteARM.go
+++ b/src/cmd/compile/internal/ssa/rewriteARM.go
@@ -15599,6 +15599,7 @@ func rewriteValueARM_OpSelect0(v *Value) bool {
return true
}
// match: (Select0 (CALLudiv (MOVWconst [c]) (MOVWconst [d])))
+ // cond: d != 0
// result: (MOVWconst [int32(uint32(c)/uint32(d))])
for {
if v_0.Op != OpARMCALLudiv {
@@ -15615,6 +15616,9 @@ func rewriteValueARM_OpSelect0(v *Value) bool {
break
}
d := auxIntToInt32(v_0_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
v.reset(OpARMMOVWconst)
v.AuxInt = int32ToAuxInt(int32(uint32(c) / uint32(d)))
return true
@@ -15661,6 +15665,7 @@ func rewriteValueARM_OpSelect1(v *Value) bool {
return true
}
// match: (Select1 (CALLudiv (MOVWconst [c]) (MOVWconst [d])))
+ // cond: d != 0
// result: (MOVWconst [int32(uint32(c)%uint32(d))])
for {
if v_0.Op != OpARMCALLudiv {
@@ -15677,6 +15682,9 @@ func rewriteValueARM_OpSelect1(v *Value) bool {
break
}
d := auxIntToInt32(v_0_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
v.reset(OpARMMOVWconst)
v.AuxInt = int32ToAuxInt(int32(uint32(c) % uint32(d)))
return true
@@ -17389,7 +17397,7 @@ func rewriteBlockARM(b *Block) bool {
}
// match: (GE (CMPconst [0] l:(AND x y)) yes no)
// cond: l.Uses==1
- // result: (GE (TST x y) yes no)
+ // result: (GEnoov (TST x y) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -17410,14 +17418,14 @@ func rewriteBlockARM(b *Block) bool {
}
v0 := b.NewValue0(v_0.Pos, OpARMTST, types.TypeFlags)
v0.AddArg2(x, y)
- b.resetWithControl(BlockARMGE, v0)
+ b.resetWithControl(BlockARMGEnoov, v0)
return true
}
break
}
// match: (GE (CMPconst [0] l:(ANDconst [c] x)) yes no)
// cond: l.Uses==1
- // result: (GE (TSTconst [c] x) yes no)
+ // result: (GEnoov (TSTconst [c] x) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -17435,12 +17443,12 @@ func rewriteBlockARM(b *Block) bool {
v0 := b.NewValue0(v_0.Pos, OpARMTSTconst, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(c)
v0.AddArg(x)
- b.resetWithControl(BlockARMGE, v0)
+ b.resetWithControl(BlockARMGEnoov, v0)
return true
}
// match: (GE (CMPconst [0] l:(ANDshiftLL x y [c])) yes no)
// cond: l.Uses==1
- // result: (GE (TSTshiftLL x y [c]) yes no)
+ // result: (GEnoov (TSTshiftLL x y [c]) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -17459,12 +17467,12 @@ func rewriteBlockARM(b *Block) bool {
v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftLL, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(c)
v0.AddArg2(x, y)
- b.resetWithControl(BlockARMGE, v0)
+ b.resetWithControl(BlockARMGEnoov, v0)
return true
}
// match: (GE (CMPconst [0] l:(ANDshiftRL x y [c])) yes no)
// cond: l.Uses==1
- // result: (GE (TSTshiftRL x y [c]) yes no)
+ // result: (GEnoov (TSTshiftRL x y [c]) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -17483,12 +17491,12 @@ func rewriteBlockARM(b *Block) bool {
v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRL, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(c)
v0.AddArg2(x, y)
- b.resetWithControl(BlockARMGE, v0)
+ b.resetWithControl(BlockARMGEnoov, v0)
return true
}
// match: (GE (CMPconst [0] l:(ANDshiftRA x y [c])) yes no)
// cond: l.Uses==1
- // result: (GE (TSTshiftRA x y [c]) yes no)
+ // result: (GEnoov (TSTshiftRA x y [c]) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -17507,12 +17515,12 @@ func rewriteBlockARM(b *Block) bool {
v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRA, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(c)
v0.AddArg2(x, y)
- b.resetWithControl(BlockARMGE, v0)
+ b.resetWithControl(BlockARMGEnoov, v0)
return true
}
// match: (GE (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no)
// cond: l.Uses==1
- // result: (GE (TSTshiftLLreg x y z) yes no)
+ // result: (GEnoov (TSTshiftLLreg x y z) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -17530,12 +17538,12 @@ func rewriteBlockARM(b *Block) bool {
}
v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftLLreg, types.TypeFlags)
v0.AddArg3(x, y, z)
- b.resetWithControl(BlockARMGE, v0)
+ b.resetWithControl(BlockARMGEnoov, v0)
return true
}
// match: (GE (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no)
// cond: l.Uses==1
- // result: (GE (TSTshiftRLreg x y z) yes no)
+ // result: (GEnoov (TSTshiftRLreg x y z) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -17553,12 +17561,12 @@ func rewriteBlockARM(b *Block) bool {
}
v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRLreg, types.TypeFlags)
v0.AddArg3(x, y, z)
- b.resetWithControl(BlockARMGE, v0)
+ b.resetWithControl(BlockARMGEnoov, v0)
return true
}
// match: (GE (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no)
// cond: l.Uses==1
- // result: (GE (TSTshiftRAreg x y z) yes no)
+ // result: (GEnoov (TSTshiftRAreg x y z) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -17576,12 +17584,12 @@ func rewriteBlockARM(b *Block) bool {
}
v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRAreg, types.TypeFlags)
v0.AddArg3(x, y, z)
- b.resetWithControl(BlockARMGE, v0)
+ b.resetWithControl(BlockARMGEnoov, v0)
return true
}
// match: (GE (CMPconst [0] l:(XOR x y)) yes no)
// cond: l.Uses==1
- // result: (GE (TEQ x y) yes no)
+ // result: (GEnoov (TEQ x y) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -17602,14 +17610,14 @@ func rewriteBlockARM(b *Block) bool {
}
v0 := b.NewValue0(v_0.Pos, OpARMTEQ, types.TypeFlags)
v0.AddArg2(x, y)
- b.resetWithControl(BlockARMGE, v0)
+ b.resetWithControl(BlockARMGEnoov, v0)
return true
}
break
}
// match: (GE (CMPconst [0] l:(XORconst [c] x)) yes no)
// cond: l.Uses==1
- // result: (GE (TEQconst [c] x) yes no)
+ // result: (GEnoov (TEQconst [c] x) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -17627,12 +17635,12 @@ func rewriteBlockARM(b *Block) bool {
v0 := b.NewValue0(v_0.Pos, OpARMTEQconst, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(c)
v0.AddArg(x)
- b.resetWithControl(BlockARMGE, v0)
+ b.resetWithControl(BlockARMGEnoov, v0)
return true
}
// match: (GE (CMPconst [0] l:(XORshiftLL x y [c])) yes no)
// cond: l.Uses==1
- // result: (GE (TEQshiftLL x y [c]) yes no)
+ // result: (GEnoov (TEQshiftLL x y [c]) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -17651,12 +17659,12 @@ func rewriteBlockARM(b *Block) bool {
v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftLL, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(c)
v0.AddArg2(x, y)
- b.resetWithControl(BlockARMGE, v0)
+ b.resetWithControl(BlockARMGEnoov, v0)
return true
}
// match: (GE (CMPconst [0] l:(XORshiftRL x y [c])) yes no)
// cond: l.Uses==1
- // result: (GE (TEQshiftRL x y [c]) yes no)
+ // result: (GEnoov (TEQshiftRL x y [c]) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -17675,12 +17683,12 @@ func rewriteBlockARM(b *Block) bool {
v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRL, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(c)
v0.AddArg2(x, y)
- b.resetWithControl(BlockARMGE, v0)
+ b.resetWithControl(BlockARMGEnoov, v0)
return true
}
// match: (GE (CMPconst [0] l:(XORshiftRA x y [c])) yes no)
// cond: l.Uses==1
- // result: (GE (TEQshiftRA x y [c]) yes no)
+ // result: (GEnoov (TEQshiftRA x y [c]) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -17699,12 +17707,12 @@ func rewriteBlockARM(b *Block) bool {
v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRA, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(c)
v0.AddArg2(x, y)
- b.resetWithControl(BlockARMGE, v0)
+ b.resetWithControl(BlockARMGEnoov, v0)
return true
}
// match: (GE (CMPconst [0] l:(XORshiftLLreg x y z)) yes no)
// cond: l.Uses==1
- // result: (GE (TEQshiftLLreg x y z) yes no)
+ // result: (GEnoov (TEQshiftLLreg x y z) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -17722,12 +17730,12 @@ func rewriteBlockARM(b *Block) bool {
}
v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftLLreg, types.TypeFlags)
v0.AddArg3(x, y, z)
- b.resetWithControl(BlockARMGE, v0)
+ b.resetWithControl(BlockARMGEnoov, v0)
return true
}
// match: (GE (CMPconst [0] l:(XORshiftRLreg x y z)) yes no)
// cond: l.Uses==1
- // result: (GE (TEQshiftRLreg x y z) yes no)
+ // result: (GEnoov (TEQshiftRLreg x y z) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -17745,12 +17753,12 @@ func rewriteBlockARM(b *Block) bool {
}
v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRLreg, types.TypeFlags)
v0.AddArg3(x, y, z)
- b.resetWithControl(BlockARMGE, v0)
+ b.resetWithControl(BlockARMGEnoov, v0)
return true
}
// match: (GE (CMPconst [0] l:(XORshiftRAreg x y z)) yes no)
// cond: l.Uses==1
- // result: (GE (TEQshiftRAreg x y z) yes no)
+ // result: (GEnoov (TEQshiftRAreg x y z) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -17768,7 +17776,7 @@ func rewriteBlockARM(b *Block) bool {
}
v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRAreg, types.TypeFlags)
v0.AddArg3(x, y, z)
- b.resetWithControl(BlockARMGE, v0)
+ b.resetWithControl(BlockARMGEnoov, v0)
return true
}
case BlockARMGEnoov:
@@ -18278,34 +18286,6 @@ func rewriteBlockARM(b *Block) bool {
b.resetWithControl(BlockARMGTnoov, v0)
return true
}
- // match: (GT (CMPconst [0] l:(AND x y)) yes no)
- // cond: l.Uses==1
- // result: (GT (TST x y) yes no)
- for b.Controls[0].Op == OpARMCMPconst {
- v_0 := b.Controls[0]
- if auxIntToInt32(v_0.AuxInt) != 0 {
- break
- }
- l := v_0.Args[0]
- if l.Op != OpARMAND {
- break
- }
- _ = l.Args[1]
- l_0 := l.Args[0]
- l_1 := l.Args[1]
- for _i0 := 0; _i0 <= 1; _i0, l_0, l_1 = _i0+1, l_1, l_0 {
- x := l_0
- y := l_1
- if !(l.Uses == 1) {
- continue
- }
- v0 := b.NewValue0(v_0.Pos, OpARMTST, types.TypeFlags)
- v0.AddArg2(x, y)
- b.resetWithControl(BlockARMGT, v0)
- return true
- }
- break
- }
// match: (GT (CMPconst [0] l:(MULA x y a)) yes no)
// cond: l.Uses==1
// result: (GTnoov (CMN a (MUL x y)) yes no)
@@ -18331,9 +18311,37 @@ func rewriteBlockARM(b *Block) bool {
b.resetWithControl(BlockARMGTnoov, v0)
return true
}
+ // match: (GT (CMPconst [0] l:(AND x y)) yes no)
+ // cond: l.Uses==1
+ // result: (GTnoov (TST x y) yes no)
+ for b.Controls[0].Op == OpARMCMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ l := v_0.Args[0]
+ if l.Op != OpARMAND {
+ break
+ }
+ _ = l.Args[1]
+ l_0 := l.Args[0]
+ l_1 := l.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, l_0, l_1 = _i0+1, l_1, l_0 {
+ x := l_0
+ y := l_1
+ if !(l.Uses == 1) {
+ continue
+ }
+ v0 := b.NewValue0(v_0.Pos, OpARMTST, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARMGTnoov, v0)
+ return true
+ }
+ break
+ }
// match: (GT (CMPconst [0] l:(ANDconst [c] x)) yes no)
// cond: l.Uses==1
- // result: (GT (TSTconst [c] x) yes no)
+ // result: (GTnoov (TSTconst [c] x) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -18351,12 +18359,12 @@ func rewriteBlockARM(b *Block) bool {
v0 := b.NewValue0(v_0.Pos, OpARMTSTconst, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(c)
v0.AddArg(x)
- b.resetWithControl(BlockARMGT, v0)
+ b.resetWithControl(BlockARMGTnoov, v0)
return true
}
// match: (GT (CMPconst [0] l:(ANDshiftLL x y [c])) yes no)
// cond: l.Uses==1
- // result: (GT (TSTshiftLL x y [c]) yes no)
+ // result: (GTnoov (TSTshiftLL x y [c]) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -18375,12 +18383,12 @@ func rewriteBlockARM(b *Block) bool {
v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftLL, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(c)
v0.AddArg2(x, y)
- b.resetWithControl(BlockARMGT, v0)
+ b.resetWithControl(BlockARMGTnoov, v0)
return true
}
// match: (GT (CMPconst [0] l:(ANDshiftRL x y [c])) yes no)
// cond: l.Uses==1
- // result: (GT (TSTshiftRL x y [c]) yes no)
+ // result: (GTnoov (TSTshiftRL x y [c]) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -18399,12 +18407,12 @@ func rewriteBlockARM(b *Block) bool {
v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRL, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(c)
v0.AddArg2(x, y)
- b.resetWithControl(BlockARMGT, v0)
+ b.resetWithControl(BlockARMGTnoov, v0)
return true
}
// match: (GT (CMPconst [0] l:(ANDshiftRA x y [c])) yes no)
// cond: l.Uses==1
- // result: (GT (TSTshiftRA x y [c]) yes no)
+ // result: (GTnoov (TSTshiftRA x y [c]) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -18423,12 +18431,12 @@ func rewriteBlockARM(b *Block) bool {
v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRA, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(c)
v0.AddArg2(x, y)
- b.resetWithControl(BlockARMGT, v0)
+ b.resetWithControl(BlockARMGTnoov, v0)
return true
}
// match: (GT (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no)
// cond: l.Uses==1
- // result: (GT (TSTshiftLLreg x y z) yes no)
+ // result: (GTnoov (TSTshiftLLreg x y z) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -18446,12 +18454,12 @@ func rewriteBlockARM(b *Block) bool {
}
v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftLLreg, types.TypeFlags)
v0.AddArg3(x, y, z)
- b.resetWithControl(BlockARMGT, v0)
+ b.resetWithControl(BlockARMGTnoov, v0)
return true
}
// match: (GT (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no)
// cond: l.Uses==1
- // result: (GT (TSTshiftRLreg x y z) yes no)
+ // result: (GTnoov (TSTshiftRLreg x y z) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -18469,12 +18477,12 @@ func rewriteBlockARM(b *Block) bool {
}
v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRLreg, types.TypeFlags)
v0.AddArg3(x, y, z)
- b.resetWithControl(BlockARMGT, v0)
+ b.resetWithControl(BlockARMGTnoov, v0)
return true
}
// match: (GT (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no)
// cond: l.Uses==1
- // result: (GT (TSTshiftRAreg x y z) yes no)
+ // result: (GTnoov (TSTshiftRAreg x y z) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -18492,12 +18500,12 @@ func rewriteBlockARM(b *Block) bool {
}
v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRAreg, types.TypeFlags)
v0.AddArg3(x, y, z)
- b.resetWithControl(BlockARMGT, v0)
+ b.resetWithControl(BlockARMGTnoov, v0)
return true
}
// match: (GT (CMPconst [0] l:(XOR x y)) yes no)
// cond: l.Uses==1
- // result: (GT (TEQ x y) yes no)
+ // result: (GTnoov (TEQ x y) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -18518,14 +18526,14 @@ func rewriteBlockARM(b *Block) bool {
}
v0 := b.NewValue0(v_0.Pos, OpARMTEQ, types.TypeFlags)
v0.AddArg2(x, y)
- b.resetWithControl(BlockARMGT, v0)
+ b.resetWithControl(BlockARMGTnoov, v0)
return true
}
break
}
// match: (GT (CMPconst [0] l:(XORconst [c] x)) yes no)
// cond: l.Uses==1
- // result: (GT (TEQconst [c] x) yes no)
+ // result: (GTnoov (TEQconst [c] x) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -18543,12 +18551,12 @@ func rewriteBlockARM(b *Block) bool {
v0 := b.NewValue0(v_0.Pos, OpARMTEQconst, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(c)
v0.AddArg(x)
- b.resetWithControl(BlockARMGT, v0)
+ b.resetWithControl(BlockARMGTnoov, v0)
return true
}
// match: (GT (CMPconst [0] l:(XORshiftLL x y [c])) yes no)
// cond: l.Uses==1
- // result: (GT (TEQshiftLL x y [c]) yes no)
+ // result: (GTnoov (TEQshiftLL x y [c]) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -18567,12 +18575,12 @@ func rewriteBlockARM(b *Block) bool {
v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftLL, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(c)
v0.AddArg2(x, y)
- b.resetWithControl(BlockARMGT, v0)
+ b.resetWithControl(BlockARMGTnoov, v0)
return true
}
// match: (GT (CMPconst [0] l:(XORshiftRL x y [c])) yes no)
// cond: l.Uses==1
- // result: (GT (TEQshiftRL x y [c]) yes no)
+ // result: (GTnoov (TEQshiftRL x y [c]) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -18591,12 +18599,12 @@ func rewriteBlockARM(b *Block) bool {
v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRL, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(c)
v0.AddArg2(x, y)
- b.resetWithControl(BlockARMGT, v0)
+ b.resetWithControl(BlockARMGTnoov, v0)
return true
}
// match: (GT (CMPconst [0] l:(XORshiftRA x y [c])) yes no)
// cond: l.Uses==1
- // result: (GT (TEQshiftRA x y [c]) yes no)
+ // result: (GTnoov (TEQshiftRA x y [c]) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -18615,12 +18623,12 @@ func rewriteBlockARM(b *Block) bool {
v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRA, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(c)
v0.AddArg2(x, y)
- b.resetWithControl(BlockARMGT, v0)
+ b.resetWithControl(BlockARMGTnoov, v0)
return true
}
// match: (GT (CMPconst [0] l:(XORshiftLLreg x y z)) yes no)
// cond: l.Uses==1
- // result: (GT (TEQshiftLLreg x y z) yes no)
+ // result: (GTnoov (TEQshiftLLreg x y z) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -18638,12 +18646,12 @@ func rewriteBlockARM(b *Block) bool {
}
v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftLLreg, types.TypeFlags)
v0.AddArg3(x, y, z)
- b.resetWithControl(BlockARMGT, v0)
+ b.resetWithControl(BlockARMGTnoov, v0)
return true
}
// match: (GT (CMPconst [0] l:(XORshiftRLreg x y z)) yes no)
// cond: l.Uses==1
- // result: (GT (TEQshiftRLreg x y z) yes no)
+ // result: (GTnoov (TEQshiftRLreg x y z) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -18661,12 +18669,12 @@ func rewriteBlockARM(b *Block) bool {
}
v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRLreg, types.TypeFlags)
v0.AddArg3(x, y, z)
- b.resetWithControl(BlockARMGT, v0)
+ b.resetWithControl(BlockARMGTnoov, v0)
return true
}
// match: (GT (CMPconst [0] l:(XORshiftRAreg x y z)) yes no)
// cond: l.Uses==1
- // result: (GT (TEQshiftRAreg x y z) yes no)
+ // result: (GTnoov (TEQshiftRAreg x y z) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -18684,7 +18692,7 @@ func rewriteBlockARM(b *Block) bool {
}
v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRAreg, types.TypeFlags)
v0.AddArg3(x, y, z)
- b.resetWithControl(BlockARMGT, v0)
+ b.resetWithControl(BlockARMGTnoov, v0)
return true
}
case BlockARMGTnoov:
@@ -19312,7 +19320,7 @@ func rewriteBlockARM(b *Block) bool {
}
// match: (LE (CMPconst [0] l:(AND x y)) yes no)
// cond: l.Uses==1
- // result: (LE (TST x y) yes no)
+ // result: (LEnoov (TST x y) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -19333,14 +19341,14 @@ func rewriteBlockARM(b *Block) bool {
}
v0 := b.NewValue0(v_0.Pos, OpARMTST, types.TypeFlags)
v0.AddArg2(x, y)
- b.resetWithControl(BlockARMLE, v0)
+ b.resetWithControl(BlockARMLEnoov, v0)
return true
}
break
}
// match: (LE (CMPconst [0] l:(ANDconst [c] x)) yes no)
// cond: l.Uses==1
- // result: (LE (TSTconst [c] x) yes no)
+ // result: (LEnoov (TSTconst [c] x) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -19358,12 +19366,12 @@ func rewriteBlockARM(b *Block) bool {
v0 := b.NewValue0(v_0.Pos, OpARMTSTconst, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(c)
v0.AddArg(x)
- b.resetWithControl(BlockARMLE, v0)
+ b.resetWithControl(BlockARMLEnoov, v0)
return true
}
// match: (LE (CMPconst [0] l:(ANDshiftLL x y [c])) yes no)
// cond: l.Uses==1
- // result: (LE (TSTshiftLL x y [c]) yes no)
+ // result: (LEnoov (TSTshiftLL x y [c]) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -19382,12 +19390,12 @@ func rewriteBlockARM(b *Block) bool {
v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftLL, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(c)
v0.AddArg2(x, y)
- b.resetWithControl(BlockARMLE, v0)
+ b.resetWithControl(BlockARMLEnoov, v0)
return true
}
// match: (LE (CMPconst [0] l:(ANDshiftRL x y [c])) yes no)
// cond: l.Uses==1
- // result: (LE (TSTshiftRL x y [c]) yes no)
+ // result: (LEnoov (TSTshiftRL x y [c]) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -19406,12 +19414,12 @@ func rewriteBlockARM(b *Block) bool {
v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRL, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(c)
v0.AddArg2(x, y)
- b.resetWithControl(BlockARMLE, v0)
+ b.resetWithControl(BlockARMLEnoov, v0)
return true
}
// match: (LE (CMPconst [0] l:(ANDshiftRA x y [c])) yes no)
// cond: l.Uses==1
- // result: (LE (TSTshiftRA x y [c]) yes no)
+ // result: (LEnoov (TSTshiftRA x y [c]) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -19430,12 +19438,12 @@ func rewriteBlockARM(b *Block) bool {
v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRA, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(c)
v0.AddArg2(x, y)
- b.resetWithControl(BlockARMLE, v0)
+ b.resetWithControl(BlockARMLEnoov, v0)
return true
}
// match: (LE (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no)
// cond: l.Uses==1
- // result: (LE (TSTshiftLLreg x y z) yes no)
+ // result: (LEnoov (TSTshiftLLreg x y z) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -19453,12 +19461,12 @@ func rewriteBlockARM(b *Block) bool {
}
v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftLLreg, types.TypeFlags)
v0.AddArg3(x, y, z)
- b.resetWithControl(BlockARMLE, v0)
+ b.resetWithControl(BlockARMLEnoov, v0)
return true
}
// match: (LE (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no)
// cond: l.Uses==1
- // result: (LE (TSTshiftRLreg x y z) yes no)
+ // result: (LEnoov (TSTshiftRLreg x y z) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -19476,12 +19484,12 @@ func rewriteBlockARM(b *Block) bool {
}
v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRLreg, types.TypeFlags)
v0.AddArg3(x, y, z)
- b.resetWithControl(BlockARMLE, v0)
+ b.resetWithControl(BlockARMLEnoov, v0)
return true
}
// match: (LE (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no)
// cond: l.Uses==1
- // result: (LE (TSTshiftRAreg x y z) yes no)
+ // result: (LEnoov (TSTshiftRAreg x y z) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -19499,12 +19507,12 @@ func rewriteBlockARM(b *Block) bool {
}
v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRAreg, types.TypeFlags)
v0.AddArg3(x, y, z)
- b.resetWithControl(BlockARMLE, v0)
+ b.resetWithControl(BlockARMLEnoov, v0)
return true
}
// match: (LE (CMPconst [0] l:(XOR x y)) yes no)
// cond: l.Uses==1
- // result: (LE (TEQ x y) yes no)
+ // result: (LEnoov (TEQ x y) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -19525,14 +19533,14 @@ func rewriteBlockARM(b *Block) bool {
}
v0 := b.NewValue0(v_0.Pos, OpARMTEQ, types.TypeFlags)
v0.AddArg2(x, y)
- b.resetWithControl(BlockARMLE, v0)
+ b.resetWithControl(BlockARMLEnoov, v0)
return true
}
break
}
// match: (LE (CMPconst [0] l:(XORconst [c] x)) yes no)
// cond: l.Uses==1
- // result: (LE (TEQconst [c] x) yes no)
+ // result: (LEnoov (TEQconst [c] x) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -19550,12 +19558,12 @@ func rewriteBlockARM(b *Block) bool {
v0 := b.NewValue0(v_0.Pos, OpARMTEQconst, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(c)
v0.AddArg(x)
- b.resetWithControl(BlockARMLE, v0)
+ b.resetWithControl(BlockARMLEnoov, v0)
return true
}
// match: (LE (CMPconst [0] l:(XORshiftLL x y [c])) yes no)
// cond: l.Uses==1
- // result: (LE (TEQshiftLL x y [c]) yes no)
+ // result: (LEnoov (TEQshiftLL x y [c]) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -19574,12 +19582,12 @@ func rewriteBlockARM(b *Block) bool {
v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftLL, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(c)
v0.AddArg2(x, y)
- b.resetWithControl(BlockARMLE, v0)
+ b.resetWithControl(BlockARMLEnoov, v0)
return true
}
// match: (LE (CMPconst [0] l:(XORshiftRL x y [c])) yes no)
// cond: l.Uses==1
- // result: (LE (TEQshiftRL x y [c]) yes no)
+ // result: (LEnoov (TEQshiftRL x y [c]) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -19598,12 +19606,12 @@ func rewriteBlockARM(b *Block) bool {
v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRL, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(c)
v0.AddArg2(x, y)
- b.resetWithControl(BlockARMLE, v0)
+ b.resetWithControl(BlockARMLEnoov, v0)
return true
}
// match: (LE (CMPconst [0] l:(XORshiftRA x y [c])) yes no)
// cond: l.Uses==1
- // result: (LE (TEQshiftRA x y [c]) yes no)
+ // result: (LEnoov (TEQshiftRA x y [c]) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -19622,12 +19630,12 @@ func rewriteBlockARM(b *Block) bool {
v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRA, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(c)
v0.AddArg2(x, y)
- b.resetWithControl(BlockARMLE, v0)
+ b.resetWithControl(BlockARMLEnoov, v0)
return true
}
// match: (LE (CMPconst [0] l:(XORshiftLLreg x y z)) yes no)
// cond: l.Uses==1
- // result: (LE (TEQshiftLLreg x y z) yes no)
+ // result: (LEnoov (TEQshiftLLreg x y z) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -19645,12 +19653,12 @@ func rewriteBlockARM(b *Block) bool {
}
v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftLLreg, types.TypeFlags)
v0.AddArg3(x, y, z)
- b.resetWithControl(BlockARMLE, v0)
+ b.resetWithControl(BlockARMLEnoov, v0)
return true
}
// match: (LE (CMPconst [0] l:(XORshiftRLreg x y z)) yes no)
// cond: l.Uses==1
- // result: (LE (TEQshiftRLreg x y z) yes no)
+ // result: (LEnoov (TEQshiftRLreg x y z) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -19668,12 +19676,12 @@ func rewriteBlockARM(b *Block) bool {
}
v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRLreg, types.TypeFlags)
v0.AddArg3(x, y, z)
- b.resetWithControl(BlockARMLE, v0)
+ b.resetWithControl(BlockARMLEnoov, v0)
return true
}
// match: (LE (CMPconst [0] l:(XORshiftRAreg x y z)) yes no)
// cond: l.Uses==1
- // result: (LE (TEQshiftRAreg x y z) yes no)
+ // result: (LEnoov (TEQshiftRAreg x y z) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -19691,7 +19699,7 @@ func rewriteBlockARM(b *Block) bool {
}
v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRAreg, types.TypeFlags)
v0.AddArg3(x, y, z)
- b.resetWithControl(BlockARMLE, v0)
+ b.resetWithControl(BlockARMLEnoov, v0)
return true
}
case BlockARMLEnoov:
@@ -20228,7 +20236,7 @@ func rewriteBlockARM(b *Block) bool {
}
// match: (LT (CMPconst [0] l:(AND x y)) yes no)
// cond: l.Uses==1
- // result: (LT (TST x y) yes no)
+ // result: (LTnoov (TST x y) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -20249,14 +20257,14 @@ func rewriteBlockARM(b *Block) bool {
}
v0 := b.NewValue0(v_0.Pos, OpARMTST, types.TypeFlags)
v0.AddArg2(x, y)
- b.resetWithControl(BlockARMLT, v0)
+ b.resetWithControl(BlockARMLTnoov, v0)
return true
}
break
}
// match: (LT (CMPconst [0] l:(ANDconst [c] x)) yes no)
// cond: l.Uses==1
- // result: (LT (TSTconst [c] x) yes no)
+ // result: (LTnoov (TSTconst [c] x) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -20274,12 +20282,12 @@ func rewriteBlockARM(b *Block) bool {
v0 := b.NewValue0(v_0.Pos, OpARMTSTconst, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(c)
v0.AddArg(x)
- b.resetWithControl(BlockARMLT, v0)
+ b.resetWithControl(BlockARMLTnoov, v0)
return true
}
// match: (LT (CMPconst [0] l:(ANDshiftLL x y [c])) yes no)
// cond: l.Uses==1
- // result: (LT (TSTshiftLL x y [c]) yes no)
+ // result: (LTnoov (TSTshiftLL x y [c]) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -20298,12 +20306,12 @@ func rewriteBlockARM(b *Block) bool {
v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftLL, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(c)
v0.AddArg2(x, y)
- b.resetWithControl(BlockARMLT, v0)
+ b.resetWithControl(BlockARMLTnoov, v0)
return true
}
// match: (LT (CMPconst [0] l:(ANDshiftRL x y [c])) yes no)
// cond: l.Uses==1
- // result: (LT (TSTshiftRL x y [c]) yes no)
+ // result: (LTnoov (TSTshiftRL x y [c]) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -20322,12 +20330,12 @@ func rewriteBlockARM(b *Block) bool {
v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRL, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(c)
v0.AddArg2(x, y)
- b.resetWithControl(BlockARMLT, v0)
+ b.resetWithControl(BlockARMLTnoov, v0)
return true
}
// match: (LT (CMPconst [0] l:(ANDshiftRA x y [c])) yes no)
// cond: l.Uses==1
- // result: (LT (TSTshiftRA x y [c]) yes no)
+ // result: (LTnoov (TSTshiftRA x y [c]) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -20346,12 +20354,12 @@ func rewriteBlockARM(b *Block) bool {
v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRA, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(c)
v0.AddArg2(x, y)
- b.resetWithControl(BlockARMLT, v0)
+ b.resetWithControl(BlockARMLTnoov, v0)
return true
}
// match: (LT (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no)
// cond: l.Uses==1
- // result: (LT (TSTshiftLLreg x y z) yes no)
+ // result: (LTnoov (TSTshiftLLreg x y z) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -20369,12 +20377,12 @@ func rewriteBlockARM(b *Block) bool {
}
v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftLLreg, types.TypeFlags)
v0.AddArg3(x, y, z)
- b.resetWithControl(BlockARMLT, v0)
+ b.resetWithControl(BlockARMLTnoov, v0)
return true
}
// match: (LT (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no)
// cond: l.Uses==1
- // result: (LT (TSTshiftRLreg x y z) yes no)
+ // result: (LTnoov (TSTshiftRLreg x y z) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -20392,12 +20400,12 @@ func rewriteBlockARM(b *Block) bool {
}
v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRLreg, types.TypeFlags)
v0.AddArg3(x, y, z)
- b.resetWithControl(BlockARMLT, v0)
+ b.resetWithControl(BlockARMLTnoov, v0)
return true
}
// match: (LT (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no)
// cond: l.Uses==1
- // result: (LT (TSTshiftRAreg x y z) yes no)
+ // result: (LTnoov (TSTshiftRAreg x y z) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -20415,12 +20423,12 @@ func rewriteBlockARM(b *Block) bool {
}
v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRAreg, types.TypeFlags)
v0.AddArg3(x, y, z)
- b.resetWithControl(BlockARMLT, v0)
+ b.resetWithControl(BlockARMLTnoov, v0)
return true
}
// match: (LT (CMPconst [0] l:(XOR x y)) yes no)
// cond: l.Uses==1
- // result: (LT (TEQ x y) yes no)
+ // result: (LTnoov (TEQ x y) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -20441,14 +20449,14 @@ func rewriteBlockARM(b *Block) bool {
}
v0 := b.NewValue0(v_0.Pos, OpARMTEQ, types.TypeFlags)
v0.AddArg2(x, y)
- b.resetWithControl(BlockARMLT, v0)
+ b.resetWithControl(BlockARMLTnoov, v0)
return true
}
break
}
// match: (LT (CMPconst [0] l:(XORconst [c] x)) yes no)
// cond: l.Uses==1
- // result: (LT (TEQconst [c] x) yes no)
+ // result: (LTnoov (TEQconst [c] x) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -20466,12 +20474,12 @@ func rewriteBlockARM(b *Block) bool {
v0 := b.NewValue0(v_0.Pos, OpARMTEQconst, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(c)
v0.AddArg(x)
- b.resetWithControl(BlockARMLT, v0)
+ b.resetWithControl(BlockARMLTnoov, v0)
return true
}
// match: (LT (CMPconst [0] l:(XORshiftLL x y [c])) yes no)
// cond: l.Uses==1
- // result: (LT (TEQshiftLL x y [c]) yes no)
+ // result: (LTnoov (TEQshiftLL x y [c]) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -20490,12 +20498,12 @@ func rewriteBlockARM(b *Block) bool {
v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftLL, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(c)
v0.AddArg2(x, y)
- b.resetWithControl(BlockARMLT, v0)
+ b.resetWithControl(BlockARMLTnoov, v0)
return true
}
// match: (LT (CMPconst [0] l:(XORshiftRL x y [c])) yes no)
// cond: l.Uses==1
- // result: (LT (TEQshiftRL x y [c]) yes no)
+ // result: (LTnoov (TEQshiftRL x y [c]) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -20514,12 +20522,12 @@ func rewriteBlockARM(b *Block) bool {
v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRL, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(c)
v0.AddArg2(x, y)
- b.resetWithControl(BlockARMLT, v0)
+ b.resetWithControl(BlockARMLTnoov, v0)
return true
}
// match: (LT (CMPconst [0] l:(XORshiftRA x y [c])) yes no)
// cond: l.Uses==1
- // result: (LT (TEQshiftRA x y [c]) yes no)
+ // result: (LTnoov (TEQshiftRA x y [c]) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -20538,12 +20546,12 @@ func rewriteBlockARM(b *Block) bool {
v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRA, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(c)
v0.AddArg2(x, y)
- b.resetWithControl(BlockARMLT, v0)
+ b.resetWithControl(BlockARMLTnoov, v0)
return true
}
// match: (LT (CMPconst [0] l:(XORshiftLLreg x y z)) yes no)
// cond: l.Uses==1
- // result: (LT (TEQshiftLLreg x y z) yes no)
+ // result: (LTnoov (TEQshiftLLreg x y z) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -20561,12 +20569,12 @@ func rewriteBlockARM(b *Block) bool {
}
v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftLLreg, types.TypeFlags)
v0.AddArg3(x, y, z)
- b.resetWithControl(BlockARMLT, v0)
+ b.resetWithControl(BlockARMLTnoov, v0)
return true
}
// match: (LT (CMPconst [0] l:(XORshiftRLreg x y z)) yes no)
// cond: l.Uses==1
- // result: (LT (TEQshiftRLreg x y z) yes no)
+ // result: (LTnoov (TEQshiftRLreg x y z) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -20584,12 +20592,12 @@ func rewriteBlockARM(b *Block) bool {
}
v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRLreg, types.TypeFlags)
v0.AddArg3(x, y, z)
- b.resetWithControl(BlockARMLT, v0)
+ b.resetWithControl(BlockARMLTnoov, v0)
return true
}
// match: (LT (CMPconst [0] l:(XORshiftRAreg x y z)) yes no)
// cond: l.Uses==1
- // result: (LT (TEQshiftRAreg x y z) yes no)
+ // result: (LTnoov (TEQshiftRAreg x y z) yes no)
for b.Controls[0].Op == OpARMCMPconst {
v_0 := b.Controls[0]
if auxIntToInt32(v_0.AuxInt) != 0 {
@@ -20607,7 +20615,7 @@ func rewriteBlockARM(b *Block) bool {
}
v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRAreg, types.TypeFlags)
v0.AddArg3(x, y, z)
- b.resetWithControl(BlockARMLT, v0)
+ b.resetWithControl(BlockARMLTnoov, v0)
return true
}
case BlockARMLTnoov:
diff --git a/src/cmd/compile/internal/ssa/rewriteARM64.go b/src/cmd/compile/internal/ssa/rewriteARM64.go
index 353696bf39..5d5e526add 100644
--- a/src/cmd/compile/internal/ssa/rewriteARM64.go
+++ b/src/cmd/compile/internal/ssa/rewriteARM64.go
@@ -3396,6 +3396,7 @@ func rewriteValueARM64_OpARM64DIV(v *Value) bool {
v_1 := v.Args[1]
v_0 := v.Args[0]
// match: (DIV (MOVDconst [c]) (MOVDconst [d]))
+ // cond: d != 0
// result: (MOVDconst [c/d])
for {
if v_0.Op != OpARM64MOVDconst {
@@ -3406,6 +3407,9 @@ func rewriteValueARM64_OpARM64DIV(v *Value) bool {
break
}
d := auxIntToInt64(v_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
v.reset(OpARM64MOVDconst)
v.AuxInt = int64ToAuxInt(c / d)
return true
@@ -3416,6 +3420,7 @@ func rewriteValueARM64_OpARM64DIVW(v *Value) bool {
v_1 := v.Args[1]
v_0 := v.Args[0]
// match: (DIVW (MOVDconst [c]) (MOVDconst [d]))
+ // cond: d != 0
// result: (MOVDconst [int64(int32(c)/int32(d))])
for {
if v_0.Op != OpARM64MOVDconst {
@@ -3426,6 +3431,9 @@ func rewriteValueARM64_OpARM64DIVW(v *Value) bool {
break
}
d := auxIntToInt64(v_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
v.reset(OpARM64MOVDconst)
v.AuxInt = int64ToAuxInt(int64(int32(c) / int32(d)))
return true
@@ -6165,6 +6173,7 @@ func rewriteValueARM64_OpARM64MOD(v *Value) bool {
v_1 := v.Args[1]
v_0 := v.Args[0]
// match: (MOD (MOVDconst [c]) (MOVDconst [d]))
+ // cond: d != 0
// result: (MOVDconst [c%d])
for {
if v_0.Op != OpARM64MOVDconst {
@@ -6175,6 +6184,9 @@ func rewriteValueARM64_OpARM64MOD(v *Value) bool {
break
}
d := auxIntToInt64(v_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
v.reset(OpARM64MOVDconst)
v.AuxInt = int64ToAuxInt(c % d)
return true
@@ -6185,6 +6197,7 @@ func rewriteValueARM64_OpARM64MODW(v *Value) bool {
v_1 := v.Args[1]
v_0 := v.Args[0]
// match: (MODW (MOVDconst [c]) (MOVDconst [d]))
+ // cond: d != 0
// result: (MOVDconst [int64(int32(c)%int32(d))])
for {
if v_0.Op != OpARM64MOVDconst {
@@ -6195,6 +6208,9 @@ func rewriteValueARM64_OpARM64MODW(v *Value) bool {
break
}
d := auxIntToInt64(v_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
v.reset(OpARM64MOVDconst)
v.AuxInt = int64ToAuxInt(int64(int32(c) % int32(d)))
return true
@@ -20423,6 +20439,7 @@ func rewriteValueARM64_OpARM64UDIV(v *Value) bool {
return true
}
// match: (UDIV (MOVDconst [c]) (MOVDconst [d]))
+ // cond: d != 0
// result: (MOVDconst [int64(uint64(c)/uint64(d))])
for {
if v_0.Op != OpARM64MOVDconst {
@@ -20433,6 +20450,9 @@ func rewriteValueARM64_OpARM64UDIV(v *Value) bool {
break
}
d := auxIntToInt64(v_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
v.reset(OpARM64MOVDconst)
v.AuxInt = int64ToAuxInt(int64(uint64(c) / uint64(d)))
return true
@@ -20475,6 +20495,7 @@ func rewriteValueARM64_OpARM64UDIVW(v *Value) bool {
return true
}
// match: (UDIVW (MOVDconst [c]) (MOVDconst [d]))
+ // cond: d != 0
// result: (MOVDconst [int64(uint32(c)/uint32(d))])
for {
if v_0.Op != OpARM64MOVDconst {
@@ -20485,6 +20506,9 @@ func rewriteValueARM64_OpARM64UDIVW(v *Value) bool {
break
}
d := auxIntToInt64(v_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
v.reset(OpARM64MOVDconst)
v.AuxInt = int64ToAuxInt(int64(uint32(c) / uint32(d)))
return true
@@ -20539,6 +20563,7 @@ func rewriteValueARM64_OpARM64UMOD(v *Value) bool {
return true
}
// match: (UMOD (MOVDconst [c]) (MOVDconst [d]))
+ // cond: d != 0
// result: (MOVDconst [int64(uint64(c)%uint64(d))])
for {
if v_0.Op != OpARM64MOVDconst {
@@ -20549,6 +20574,9 @@ func rewriteValueARM64_OpARM64UMOD(v *Value) bool {
break
}
d := auxIntToInt64(v_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
v.reset(OpARM64MOVDconst)
v.AuxInt = int64ToAuxInt(int64(uint64(c) % uint64(d)))
return true
@@ -20608,6 +20636,7 @@ func rewriteValueARM64_OpARM64UMODW(v *Value) bool {
return true
}
// match: (UMODW (MOVDconst [c]) (MOVDconst [d]))
+ // cond: d != 0
// result: (MOVDconst [int64(uint32(c)%uint32(d))])
for {
if v_0.Op != OpARM64MOVDconst {
@@ -20618,6 +20647,9 @@ func rewriteValueARM64_OpARM64UMODW(v *Value) bool {
break
}
d := auxIntToInt64(v_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
v.reset(OpARM64MOVDconst)
v.AuxInt = int64ToAuxInt(int64(uint32(c) % uint32(d)))
return true
diff --git a/src/cmd/compile/internal/ssa/rewriteMIPS.go b/src/cmd/compile/internal/ssa/rewriteMIPS.go
index bbc331014f..3fc5527955 100644
--- a/src/cmd/compile/internal/ssa/rewriteMIPS.go
+++ b/src/cmd/compile/internal/ssa/rewriteMIPS.go
@@ -6421,6 +6421,7 @@ func rewriteValueMIPS_OpSelect0(v *Value) bool {
break
}
// match: (Select0 (DIV (MOVWconst [c]) (MOVWconst [d])))
+ // cond: d != 0
// result: (MOVWconst [c%d])
for {
if v_0.Op != OpMIPSDIV {
@@ -6437,11 +6438,15 @@ func rewriteValueMIPS_OpSelect0(v *Value) bool {
break
}
d := auxIntToInt32(v_0_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
v.reset(OpMIPSMOVWconst)
v.AuxInt = int32ToAuxInt(c % d)
return true
}
// match: (Select0 (DIVU (MOVWconst [c]) (MOVWconst [d])))
+ // cond: d != 0
// result: (MOVWconst [int32(uint32(c)%uint32(d))])
for {
if v_0.Op != OpMIPSDIVU {
@@ -6458,6 +6463,9 @@ func rewriteValueMIPS_OpSelect0(v *Value) bool {
break
}
d := auxIntToInt32(v_0_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
v.reset(OpMIPSMOVWconst)
v.AuxInt = int32ToAuxInt(int32(uint32(c) % uint32(d)))
return true
@@ -6609,6 +6617,7 @@ func rewriteValueMIPS_OpSelect1(v *Value) bool {
break
}
// match: (Select1 (DIV (MOVWconst [c]) (MOVWconst [d])))
+ // cond: d != 0
// result: (MOVWconst [c/d])
for {
if v_0.Op != OpMIPSDIV {
@@ -6625,11 +6634,15 @@ func rewriteValueMIPS_OpSelect1(v *Value) bool {
break
}
d := auxIntToInt32(v_0_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
v.reset(OpMIPSMOVWconst)
v.AuxInt = int32ToAuxInt(c / d)
return true
}
// match: (Select1 (DIVU (MOVWconst [c]) (MOVWconst [d])))
+ // cond: d != 0
// result: (MOVWconst [int32(uint32(c)/uint32(d))])
for {
if v_0.Op != OpMIPSDIVU {
@@ -6646,6 +6659,9 @@ func rewriteValueMIPS_OpSelect1(v *Value) bool {
break
}
d := auxIntToInt32(v_0_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
v.reset(OpMIPSMOVWconst)
v.AuxInt = int32ToAuxInt(int32(uint32(c) / uint32(d)))
return true
diff --git a/src/cmd/compile/internal/ssa/rewriteMIPS64.go b/src/cmd/compile/internal/ssa/rewriteMIPS64.go
index 29e3a8a363..d78f6089af 100644
--- a/src/cmd/compile/internal/ssa/rewriteMIPS64.go
+++ b/src/cmd/compile/internal/ssa/rewriteMIPS64.go
@@ -6887,6 +6887,7 @@ func rewriteValueMIPS64_OpSelect0(v *Value) bool {
return true
}
// match: (Select0 (DIVV (MOVVconst [c]) (MOVVconst [d])))
+ // cond: d != 0
// result: (MOVVconst [c%d])
for {
if v_0.Op != OpMIPS64DIVV {
@@ -6903,11 +6904,15 @@ func rewriteValueMIPS64_OpSelect0(v *Value) bool {
break
}
d := auxIntToInt64(v_0_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
v.reset(OpMIPS64MOVVconst)
v.AuxInt = int64ToAuxInt(c % d)
return true
}
// match: (Select0 (DIVVU (MOVVconst [c]) (MOVVconst [d])))
+ // cond: d != 0
// result: (MOVVconst [int64(uint64(c)%uint64(d))])
for {
if v_0.Op != OpMIPS64DIVVU {
@@ -6924,6 +6929,9 @@ func rewriteValueMIPS64_OpSelect0(v *Value) bool {
break
}
d := auxIntToInt64(v_0_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
v.reset(OpMIPS64MOVVconst)
v.AuxInt = int64ToAuxInt(int64(uint64(c) % uint64(d)))
return true
@@ -7099,6 +7107,7 @@ func rewriteValueMIPS64_OpSelect1(v *Value) bool {
break
}
// match: (Select1 (DIVV (MOVVconst [c]) (MOVVconst [d])))
+ // cond: d != 0
// result: (MOVVconst [c/d])
for {
if v_0.Op != OpMIPS64DIVV {
@@ -7115,11 +7124,15 @@ func rewriteValueMIPS64_OpSelect1(v *Value) bool {
break
}
d := auxIntToInt64(v_0_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
v.reset(OpMIPS64MOVVconst)
v.AuxInt = int64ToAuxInt(c / d)
return true
}
// match: (Select1 (DIVVU (MOVVconst [c]) (MOVVconst [d])))
+ // cond: d != 0
// result: (MOVVconst [int64(uint64(c)/uint64(d))])
for {
if v_0.Op != OpMIPS64DIVVU {
@@ -7136,6 +7149,9 @@ func rewriteValueMIPS64_OpSelect1(v *Value) bool {
break
}
d := auxIntToInt64(v_0_1.AuxInt)
+ if !(d != 0) {
+ break
+ }
v.reset(OpMIPS64MOVVconst)
v.AuxInt = int64ToAuxInt(int64(uint64(c) / uint64(d)))
return true
diff --git a/src/cmd/compile/internal/ssa/rewritePPC64.go b/src/cmd/compile/internal/ssa/rewritePPC64.go
index 7d4cf73fd8..455f9b1388 100644
--- a/src/cmd/compile/internal/ssa/rewritePPC64.go
+++ b/src/cmd/compile/internal/ssa/rewritePPC64.go
@@ -4195,6 +4195,20 @@ func rewriteValuePPC64_OpPPC64ADDconst(v *Value) bool {
v.AddArg(x)
return true
}
+ // match: (ADDconst [c] x:(SP))
+ // cond: is32Bit(c)
+ // result: (MOVDaddr [int32(c)] x)
+ for {
+ c := auxIntToInt64(v.AuxInt)
+ x := v_0
+ if x.Op != OpSP || !(is32Bit(c)) {
+ break
+ }
+ v.reset(OpPPC64MOVDaddr)
+ v.AuxInt = int32ToAuxInt(int32(c))
+ v.AddArg(x)
+ return true
+ }
// match: (ADDconst [c] (SUBFCconst [d] x))
// cond: is32Bit(c+d)
// result: (SUBFCconst [c+d] x)
diff --git a/src/cmd/compile/internal/ssa/rewriteWasm.go b/src/cmd/compile/internal/ssa/rewriteWasm.go
index 52b6f6bfc7..c8ecefc736 100644
--- a/src/cmd/compile/internal/ssa/rewriteWasm.go
+++ b/src/cmd/compile/internal/ssa/rewriteWasm.go
@@ -3693,6 +3693,20 @@ func rewriteValueWasm_OpWasmI64AddConst(v *Value) bool {
v.AddArg(base)
return true
}
+ // match: (I64AddConst [off] x:(SP))
+ // cond: isU32Bit(off)
+ // result: (LoweredAddr [int32(off)] x)
+ for {
+ off := auxIntToInt64(v.AuxInt)
+ x := v_0
+ if x.Op != OpSP || !(isU32Bit(off)) {
+ break
+ }
+ v.reset(OpWasmLoweredAddr)
+ v.AuxInt = int32ToAuxInt(int32(off))
+ v.AddArg(x)
+ return true
+ }
return false
}
func rewriteValueWasm_OpWasmI64And(v *Value) bool {
diff --git a/src/cmd/compile/internal/ssa/sizeof_test.go b/src/cmd/compile/internal/ssa/sizeof_test.go
index 60ada011e3..a27002ee3a 100644
--- a/src/cmd/compile/internal/ssa/sizeof_test.go
+++ b/src/cmd/compile/internal/ssa/sizeof_test.go
@@ -22,7 +22,7 @@ func TestSizeof(t *testing.T) {
}{
{Value{}, 72, 112},
{Block{}, 164, 304},
- {LocalSlot{}, 32, 48},
+ {LocalSlot{}, 28, 40},
{valState{}, 28, 40},
}
diff --git a/src/cmd/compile/internal/ssa/stackalloc.go b/src/cmd/compile/internal/ssa/stackalloc.go
index 5257d44cfe..68a6f08a2a 100644
--- a/src/cmd/compile/internal/ssa/stackalloc.go
+++ b/src/cmd/compile/internal/ssa/stackalloc.go
@@ -157,7 +157,7 @@ func (s *stackAllocState) stackalloc() {
if v.Aux == nil {
f.Fatalf("%s has nil Aux\n", v.LongString())
}
- loc := LocalSlot{N: v.Aux.(ir.Node), Type: v.Type, Off: v.AuxInt}
+ loc := LocalSlot{N: v.Aux.(*ir.Name), Type: v.Type, Off: v.AuxInt}
if f.pass.debug > stackDebug {
fmt.Printf("stackalloc %s to %s\n", v, loc)
}
diff --git a/src/cmd/compile/internal/ssa/value.go b/src/cmd/compile/internal/ssa/value.go
index edc43aaae7..993c5a580f 100644
--- a/src/cmd/compile/internal/ssa/value.go
+++ b/src/cmd/compile/internal/ssa/value.go
@@ -36,7 +36,7 @@ type Value struct {
// Users of AuxInt which interpret AuxInt as unsigned (e.g. shifts) must be careful.
// Use Value.AuxUnsigned to get the zero-extended value of AuxInt.
AuxInt int64
- Aux interface{}
+ Aux Aux
// Arguments of this value
Args []*Value
@@ -492,3 +492,6 @@ func (v *Value) removeable() bool {
}
return true
}
+
+// TODO(mdempsky): Shouldn't be necessary; see discussion at golang.org/cl/275756
+func (*Value) CanBeAnSSAAux() {}
diff --git a/src/cmd/compile/internal/ssa/zcse.go b/src/cmd/compile/internal/ssa/zcse.go
index ec38b7d1ba..e08272c345 100644
--- a/src/cmd/compile/internal/ssa/zcse.go
+++ b/src/cmd/compile/internal/ssa/zcse.go
@@ -57,7 +57,7 @@ func zcse(f *Func) {
type vkey struct {
op Op
ai int64 // aux int
- ax interface{} // aux
+ ax Aux // aux
t *types.Type // type
}
diff --git a/src/cmd/compile/internal/types/etype_string.go b/src/cmd/compile/internal/types/etype_string.go
index 14fd5b71df..e7698296ab 100644
--- a/src/cmd/compile/internal/types/etype_string.go
+++ b/src/cmd/compile/internal/types/etype_string.go
@@ -52,8 +52,8 @@ const _EType_name = "xxxINT8UINT8INT16UINT16INT32UINT32INT64UINT64INTUINTUINTPTR
var _EType_index = [...]uint8{0, 3, 7, 12, 17, 23, 28, 34, 39, 45, 48, 52, 59, 68, 78, 85, 92, 96, 99, 103, 108, 113, 119, 123, 126, 131, 135, 138, 144, 153, 158, 161, 166, 174, 182, 185, 190, 197, 202}
-func (i EType) String() string {
- if i >= EType(len(_EType_index)-1) {
+func (i Kind) String() string {
+ if i >= Kind(len(_EType_index)-1) {
return "EType(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _EType_name[_EType_index[i]:_EType_index[i+1]]
diff --git a/src/cmd/compile/internal/types/fmt.go b/src/cmd/compile/internal/types/fmt.go
new file mode 100644
index 0000000000..d63f7a4f8d
--- /dev/null
+++ b/src/cmd/compile/internal/types/fmt.go
@@ -0,0 +1,661 @@
+// Copyright 2009 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 types
+
+import (
+ "bytes"
+ "fmt"
+ "go/constant"
+ "strconv"
+ "strings"
+ "sync"
+
+ "cmd/compile/internal/base"
+)
+
+// BuiltinPkg is a fake package that declares the universe block.
+var BuiltinPkg *Pkg
+
+// LocalPkg is the package being compiled.
+var LocalPkg *Pkg
+
+// BlankSym is the blank (_) symbol.
+var BlankSym *Sym
+
+// OrigSym returns the original symbol written by the user.
+func OrigSym(s *Sym) *Sym {
+ if s == nil {
+ return nil
+ }
+
+ if len(s.Name) > 1 && s.Name[0] == '~' {
+ switch s.Name[1] {
+ case 'r': // originally an unnamed result
+ return nil
+ case 'b': // originally the blank identifier _
+ // TODO(mdempsky): Does s.Pkg matter here?
+ return BlankSym
+ }
+ return s
+ }
+
+ if strings.HasPrefix(s.Name, ".anon") {
+ // originally an unnamed or _ name (see subr.go: structargs)
+ return nil
+ }
+
+ return s
+}
+
+// numImport tracks how often a package with a given name is imported.
+// It is used to provide a better error message (by using the package
+// path to disambiguate) if a package that appears multiple times with
+// the same name appears in an error message.
+var NumImport = make(map[string]int)
+
+// fmtMode represents the kind of printing being done.
+// The default is regular Go syntax (fmtGo).
+// fmtDebug is like fmtGo but for debugging dumps and prints the type kind too.
+// fmtTypeID and fmtTypeIDName are for generating various unique representations
+// of types used in hashes and the linker.
+type fmtMode int
+
+const (
+ fmtGo fmtMode = iota
+ fmtDebug
+ fmtTypeID
+ fmtTypeIDName
+)
+
+// Sym
+
+// Format implements formatting for a Sym.
+// The valid formats are:
+//
+// %v Go syntax: Name for symbols in the local package, PkgName.Name for imported symbols.
+// %+v Debug syntax: always include PkgName. prefix even for local names.
+// %S Short syntax: Name only, no matter what.
+//
+func (s *Sym) Format(f fmt.State, verb rune) {
+ mode := fmtGo
+ switch verb {
+ case 'v', 'S':
+ if verb == 'v' && f.Flag('+') {
+ mode = fmtDebug
+ }
+ fmt.Fprint(f, sconv(s, verb, mode))
+
+ default:
+ fmt.Fprintf(f, "%%!%c(*types.Sym=%p)", verb, s)
+ }
+}
+
+func (s *Sym) String() string {
+ return sconv(s, 0, fmtGo)
+}
+
+// See #16897 for details about performance implications
+// before changing the implementation of sconv.
+func sconv(s *Sym, verb rune, mode fmtMode) string {
+ if verb == 'L' {
+ panic("linksymfmt")
+ }
+
+ if s == nil {
+ return ""
+ }
+
+ if s.Name == "_" {
+ return "_"
+ }
+ buf := fmtBufferPool.Get().(*bytes.Buffer)
+ buf.Reset()
+ defer fmtBufferPool.Put(buf)
+
+ symfmt(buf, s, verb, mode)
+ return InternString(buf.Bytes())
+}
+
+func sconv2(b *bytes.Buffer, s *Sym, verb rune, mode fmtMode) {
+ if verb == 'L' {
+ panic("linksymfmt")
+ }
+ if s == nil {
+ b.WriteString("")
+ return
+ }
+ if s.Name == "_" {
+ b.WriteString("_")
+ return
+ }
+
+ symfmt(b, s, verb, mode)
+}
+
+func symfmt(b *bytes.Buffer, s *Sym, verb rune, mode fmtMode) {
+ if verb != 'S' {
+ switch mode {
+ case fmtGo: // This is for the user
+ if s.Pkg == BuiltinPkg || s.Pkg == LocalPkg {
+ b.WriteString(s.Name)
+ return
+ }
+
+ // If the name was used by multiple packages, display the full path,
+ if s.Pkg.Name != "" && NumImport[s.Pkg.Name] > 1 {
+ fmt.Fprintf(b, "%q.%s", s.Pkg.Path, s.Name)
+ return
+ }
+ b.WriteString(s.Pkg.Name)
+ b.WriteByte('.')
+ b.WriteString(s.Name)
+ return
+
+ case fmtDebug:
+ b.WriteString(s.Pkg.Name)
+ b.WriteByte('.')
+ b.WriteString(s.Name)
+ return
+
+ case fmtTypeIDName:
+ // dcommontype, typehash
+ b.WriteString(s.Pkg.Name)
+ b.WriteByte('.')
+ b.WriteString(s.Name)
+ return
+
+ case fmtTypeID:
+ // (methodsym), typesym, weaksym
+ b.WriteString(s.Pkg.Prefix)
+ b.WriteByte('.')
+ b.WriteString(s.Name)
+ return
+ }
+ }
+
+ b.WriteString(s.Name)
+}
+
+func SymMethodName(s *Sym) string {
+ // Skip leading "type." in method name
+ name := s.Name
+ if i := strings.LastIndex(name, "."); i >= 0 {
+ name = name[i+1:]
+ }
+ return name
+}
+
+// Type
+
+var BasicTypeNames = []string{
+ TINT: "int",
+ TUINT: "uint",
+ TINT8: "int8",
+ TUINT8: "uint8",
+ TINT16: "int16",
+ TUINT16: "uint16",
+ TINT32: "int32",
+ TUINT32: "uint32",
+ TINT64: "int64",
+ TUINT64: "uint64",
+ TUINTPTR: "uintptr",
+ TFLOAT32: "float32",
+ TFLOAT64: "float64",
+ TCOMPLEX64: "complex64",
+ TCOMPLEX128: "complex128",
+ TBOOL: "bool",
+ TANY: "any",
+ TSTRING: "string",
+ TNIL: "nil",
+ TIDEAL: "untyped number",
+ TBLANK: "blank",
+}
+
+var fmtBufferPool = sync.Pool{
+ New: func() interface{} {
+ return new(bytes.Buffer)
+ },
+}
+
+// Format implements formatting for a Type.
+// The valid formats are:
+//
+// %v Go syntax
+// %+v Debug syntax: Go syntax with a KIND- prefix for all but builtins.
+// %L Go syntax for underlying type if t is named
+// %S short Go syntax: drop leading "func" in function type
+// %-S special case for method receiver symbol
+//
+func (t *Type) Format(s fmt.State, verb rune) {
+ mode := fmtGo
+ switch verb {
+ case 'v', 'S', 'L':
+ if verb == 'v' && s.Flag('+') { // %+v is debug format
+ mode = fmtDebug
+ }
+ if verb == 'S' && s.Flag('-') { // %-S is special case for receiver - short typeid format
+ mode = fmtTypeID
+ }
+ fmt.Fprint(s, tconv(t, verb, mode))
+ default:
+ fmt.Fprintf(s, "%%!%c(*Type=%p)", verb, t)
+ }
+}
+
+// String returns the Go syntax for the type t.
+func (t *Type) String() string {
+ return tconv(t, 0, fmtGo)
+}
+
+// ShortString generates a short description of t.
+// It is used in autogenerated method names, reflection,
+// and itab names.
+func (t *Type) ShortString() string {
+ return tconv(t, 0, fmtTypeID)
+}
+
+// LongString generates a complete description of t.
+// It is useful for reflection,
+// or when a unique fingerprint or hash of a type is required.
+func (t *Type) LongString() string {
+ return tconv(t, 0, fmtTypeIDName)
+}
+
+func tconv(t *Type, verb rune, mode fmtMode) string {
+ buf := fmtBufferPool.Get().(*bytes.Buffer)
+ buf.Reset()
+ defer fmtBufferPool.Put(buf)
+
+ tconv2(buf, t, verb, mode, nil)
+ return InternString(buf.Bytes())
+}
+
+// tconv2 writes a string representation of t to b.
+// flag and mode control exactly what is printed.
+// Any types x that are already in the visited map get printed as @%d where %d=visited[x].
+// See #16897 before changing the implementation of tconv.
+func tconv2(b *bytes.Buffer, t *Type, verb rune, mode fmtMode, visited map[*Type]int) {
+ if off, ok := visited[t]; ok {
+ // We've seen this type before, so we're trying to print it recursively.
+ // Print a reference to it instead.
+ fmt.Fprintf(b, "@%d", off)
+ return
+ }
+ if t == nil {
+ b.WriteString("")
+ return
+ }
+ if t.Kind() == TSSA {
+ b.WriteString(t.Extra.(string))
+ return
+ }
+ if t.Kind() == TTUPLE {
+ b.WriteString(t.FieldType(0).String())
+ b.WriteByte(',')
+ b.WriteString(t.FieldType(1).String())
+ return
+ }
+
+ if t.Kind() == TRESULTS {
+ tys := t.Extra.(*Results).Types
+ for i, et := range tys {
+ if i > 0 {
+ b.WriteByte(',')
+ }
+ b.WriteString(et.String())
+ }
+ return
+ }
+
+ if t == ByteType || t == RuneType {
+ // in %-T mode collapse rune and byte with their originals.
+ switch mode {
+ case fmtTypeIDName, fmtTypeID:
+ t = Types[t.Kind()]
+ default:
+ sconv2(b, t.Sym(), 'S', mode)
+ return
+ }
+ }
+ if t == ErrorType {
+ b.WriteString("error")
+ return
+ }
+
+ // Unless the 'L' flag was specified, if the type has a name, just print that name.
+ if verb != 'L' && t.Sym() != nil && t != Types[t.Kind()] {
+ switch mode {
+ case fmtTypeID, fmtTypeIDName:
+ if verb == 'S' {
+ if t.Vargen != 0 {
+ sconv2(b, t.Sym(), 'S', mode)
+ fmt.Fprintf(b, "·%d", t.Vargen)
+ return
+ }
+ sconv2(b, t.Sym(), 'S', mode)
+ return
+ }
+
+ if mode == fmtTypeIDName {
+ sconv2(b, t.Sym(), 'v', fmtTypeIDName)
+ return
+ }
+
+ if t.Sym().Pkg == LocalPkg && t.Vargen != 0 {
+ sconv2(b, t.Sym(), 'v', mode)
+ fmt.Fprintf(b, "·%d", t.Vargen)
+ return
+ }
+ }
+
+ sconv2(b, t.Sym(), 'v', mode)
+ return
+ }
+
+ if int(t.Kind()) < len(BasicTypeNames) && BasicTypeNames[t.Kind()] != "" {
+ var name string
+ switch t {
+ case UntypedBool:
+ name = "untyped bool"
+ case UntypedString:
+ name = "untyped string"
+ case UntypedInt:
+ name = "untyped int"
+ case UntypedRune:
+ name = "untyped rune"
+ case UntypedFloat:
+ name = "untyped float"
+ case UntypedComplex:
+ name = "untyped complex"
+ default:
+ name = BasicTypeNames[t.Kind()]
+ }
+ b.WriteString(name)
+ return
+ }
+
+ if mode == fmtDebug {
+ b.WriteString(t.Kind().String())
+ b.WriteByte('-')
+ tconv2(b, t, 'v', fmtGo, visited)
+ return
+ }
+
+ // At this point, we might call tconv2 recursively. Add the current type to the visited list so we don't
+ // try to print it recursively.
+ // We record the offset in the result buffer where the type's text starts. This offset serves as a reference
+ // point for any later references to the same type.
+ // Note that we remove the type from the visited map as soon as the recursive call is done.
+ // This prevents encoding types like map[*int]*int as map[*int]@4. (That encoding would work,
+ // but I'd like to use the @ notation only when strictly necessary.)
+ if visited == nil {
+ visited = map[*Type]int{}
+ }
+ visited[t] = b.Len()
+ defer delete(visited, t)
+
+ switch t.Kind() {
+ case TPTR:
+ b.WriteByte('*')
+ switch mode {
+ case fmtTypeID, fmtTypeIDName:
+ if verb == 'S' {
+ tconv2(b, t.Elem(), 'S', mode, visited)
+ return
+ }
+ }
+ tconv2(b, t.Elem(), 'v', mode, visited)
+
+ case TARRAY:
+ b.WriteByte('[')
+ b.WriteString(strconv.FormatInt(t.NumElem(), 10))
+ b.WriteByte(']')
+ tconv2(b, t.Elem(), 0, mode, visited)
+
+ case TSLICE:
+ b.WriteString("[]")
+ tconv2(b, t.Elem(), 0, mode, visited)
+
+ case TCHAN:
+ switch t.ChanDir() {
+ case Crecv:
+ b.WriteString("<-chan ")
+ tconv2(b, t.Elem(), 0, mode, visited)
+ case Csend:
+ b.WriteString("chan<- ")
+ tconv2(b, t.Elem(), 0, mode, visited)
+ default:
+ b.WriteString("chan ")
+ if t.Elem() != nil && t.Elem().IsChan() && t.Elem().Sym() == nil && t.Elem().ChanDir() == Crecv {
+ b.WriteByte('(')
+ tconv2(b, t.Elem(), 0, mode, visited)
+ b.WriteByte(')')
+ } else {
+ tconv2(b, t.Elem(), 0, mode, visited)
+ }
+ }
+
+ case TMAP:
+ b.WriteString("map[")
+ tconv2(b, t.Key(), 0, mode, visited)
+ b.WriteByte(']')
+ tconv2(b, t.Elem(), 0, mode, visited)
+
+ case TINTER:
+ if t.IsEmptyInterface() {
+ b.WriteString("interface {}")
+ break
+ }
+ b.WriteString("interface {")
+ for i, f := range t.Fields().Slice() {
+ if i != 0 {
+ b.WriteByte(';')
+ }
+ b.WriteByte(' ')
+ switch {
+ case f.Sym == nil:
+ // Check first that a symbol is defined for this type.
+ // Wrong interface definitions may have types lacking a symbol.
+ break
+ case IsExported(f.Sym.Name):
+ sconv2(b, f.Sym, 'S', mode)
+ default:
+ if mode != fmtTypeIDName {
+ mode = fmtTypeID
+ }
+ sconv2(b, f.Sym, 'v', mode)
+ }
+ tconv2(b, f.Type, 'S', mode, visited)
+ }
+ if t.NumFields() != 0 {
+ b.WriteByte(' ')
+ }
+ b.WriteByte('}')
+
+ case TFUNC:
+ if verb == 'S' {
+ // no leading func
+ } else {
+ if t.Recv() != nil {
+ b.WriteString("method")
+ tconv2(b, t.Recvs(), 0, mode, visited)
+ b.WriteByte(' ')
+ }
+ b.WriteString("func")
+ }
+ tconv2(b, t.Params(), 0, mode, visited)
+
+ switch t.NumResults() {
+ case 0:
+ // nothing to do
+
+ case 1:
+ b.WriteByte(' ')
+ tconv2(b, t.Results().Field(0).Type, 0, mode, visited) // struct->field->field's type
+
+ default:
+ b.WriteByte(' ')
+ tconv2(b, t.Results(), 0, mode, visited)
+ }
+
+ case TSTRUCT:
+ if m := t.StructType().Map; m != nil {
+ mt := m.MapType()
+ // Format the bucket struct for map[x]y as map.bucket[x]y.
+ // This avoids a recursive print that generates very long names.
+ switch t {
+ case mt.Bucket:
+ b.WriteString("map.bucket[")
+ case mt.Hmap:
+ b.WriteString("map.hdr[")
+ case mt.Hiter:
+ b.WriteString("map.iter[")
+ default:
+ base.Fatalf("unknown internal map type")
+ }
+ tconv2(b, m.Key(), 0, mode, visited)
+ b.WriteByte(']')
+ tconv2(b, m.Elem(), 0, mode, visited)
+ break
+ }
+
+ if funarg := t.StructType().Funarg; funarg != FunargNone {
+ b.WriteByte('(')
+ fieldVerb := 'v'
+ switch mode {
+ case fmtTypeID, fmtTypeIDName, fmtGo:
+ // no argument names on function signature, and no "noescape"/"nosplit" tags
+ fieldVerb = 'S'
+ }
+ for i, f := range t.Fields().Slice() {
+ if i != 0 {
+ b.WriteString(", ")
+ }
+ fldconv(b, f, fieldVerb, mode, visited, funarg)
+ }
+ b.WriteByte(')')
+ } else {
+ b.WriteString("struct {")
+ for i, f := range t.Fields().Slice() {
+ if i != 0 {
+ b.WriteByte(';')
+ }
+ b.WriteByte(' ')
+ fldconv(b, f, 'L', mode, visited, funarg)
+ }
+ if t.NumFields() != 0 {
+ b.WriteByte(' ')
+ }
+ b.WriteByte('}')
+ }
+
+ case TFORW:
+ b.WriteString("undefined")
+ if t.Sym() != nil {
+ b.WriteByte(' ')
+ sconv2(b, t.Sym(), 'v', mode)
+ }
+
+ case TUNSAFEPTR:
+ b.WriteString("unsafe.Pointer")
+
+ case Txxx:
+ b.WriteString("Txxx")
+
+ default:
+ // Don't know how to handle - fall back to detailed prints
+ b.WriteString(t.Kind().String())
+ b.WriteString(" <")
+ sconv2(b, t.Sym(), 'v', mode)
+ b.WriteString(">")
+
+ }
+}
+
+func fldconv(b *bytes.Buffer, f *Field, verb rune, mode fmtMode, visited map[*Type]int, funarg Funarg) {
+ if f == nil {
+ b.WriteString("")
+ return
+ }
+
+ var name string
+ if verb != 'S' {
+ s := f.Sym
+
+ // Take the name from the original.
+ if mode == fmtGo {
+ s = OrigSym(s)
+ }
+
+ if s != nil && f.Embedded == 0 {
+ if funarg != FunargNone {
+ name = fmt.Sprint(f.Nname)
+ } else if verb == 'L' {
+ name = SymMethodName(s)
+ if !IsExported(name) && mode != fmtTypeIDName {
+ name = sconv(s, 0, mode) // qualify non-exported names (used on structs, not on funarg)
+ }
+ } else {
+ name = sconv(s, 0, mode)
+ }
+ }
+ }
+
+ if name != "" {
+ b.WriteString(name)
+ b.WriteString(" ")
+ }
+
+ if f.IsDDD() {
+ var et *Type
+ if f.Type != nil {
+ et = f.Type.Elem()
+ }
+ b.WriteString("...")
+ tconv2(b, et, 0, mode, visited)
+ } else {
+ tconv2(b, f.Type, 0, mode, visited)
+ }
+
+ if verb != 'S' && funarg == FunargNone && f.Note != "" {
+ b.WriteString(" ")
+ b.WriteString(strconv.Quote(f.Note))
+ }
+}
+
+// Val
+
+func FmtConst(v constant.Value, sharp bool) string {
+ if !sharp && v.Kind() == constant.Complex {
+ real, imag := constant.Real(v), constant.Imag(v)
+
+ var re string
+ sre := constant.Sign(real)
+ if sre != 0 {
+ re = real.String()
+ }
+
+ var im string
+ sim := constant.Sign(imag)
+ if sim != 0 {
+ im = imag.String()
+ }
+
+ switch {
+ case sre == 0 && sim == 0:
+ return "0"
+ case sre == 0:
+ return im + "i"
+ case sim == 0:
+ return re
+ case sim < 0:
+ return fmt.Sprintf("(%s%si)", re, im)
+ default:
+ return fmt.Sprintf("(%s+%si)", re, im)
+ }
+ }
+
+ return v.String()
+}
diff --git a/src/cmd/compile/internal/types/identity.go b/src/cmd/compile/internal/types/identity.go
index a77f514df9..9bc636d7ff 100644
--- a/src/cmd/compile/internal/types/identity.go
+++ b/src/cmd/compile/internal/types/identity.go
@@ -25,17 +25,17 @@ func identical(t1, t2 *Type, cmpTags bool, assumedEqual map[typePair]struct{}) b
if t1 == t2 {
return true
}
- if t1 == nil || t2 == nil || t1.Etype != t2.Etype || t1.Broke() || t2.Broke() {
+ if t1 == nil || t2 == nil || t1.kind != t2.kind || t1.Broke() || t2.Broke() {
return false
}
- if t1.Sym != nil || t2.Sym != nil {
+ if t1.sym != nil || t2.sym != nil {
// Special case: we keep byte/uint8 and rune/int32
// separate for error messages. Treat them as equal.
- switch t1.Etype {
+ switch t1.kind {
case TUINT8:
- return (t1 == Types[TUINT8] || t1 == Bytetype) && (t2 == Types[TUINT8] || t2 == Bytetype)
+ return (t1 == Types[TUINT8] || t1 == ByteType) && (t2 == Types[TUINT8] || t2 == ByteType)
case TINT32:
- return (t1 == Types[TINT32] || t1 == Runetype) && (t2 == Types[TINT32] || t2 == Runetype)
+ return (t1 == Types[TINT32] || t1 == RuneType) && (t2 == Types[TINT32] || t2 == RuneType)
default:
return false
}
@@ -52,7 +52,7 @@ func identical(t1, t2 *Type, cmpTags bool, assumedEqual map[typePair]struct{}) b
}
assumedEqual[typePair{t1, t2}] = struct{}{}
- switch t1.Etype {
+ switch t1.kind {
case TIDEAL:
// Historically, cmd/compile used a single "untyped
// number" type, so all untyped number types were
diff --git a/src/cmd/compile/internal/types/pkg.go b/src/cmd/compile/internal/types/pkg.go
index bcc6789509..bf90570b53 100644
--- a/src/cmd/compile/internal/types/pkg.go
+++ b/src/cmd/compile/internal/types/pkg.go
@@ -84,9 +84,6 @@ func (pkg *Pkg) Lookup(name string) *Sym {
return s
}
-// List of .inittask entries in imported packages, in source code order.
-var InitSyms []*Sym
-
// LookupOK looks up name in pkg and reports whether it previously existed.
func (pkg *Pkg) LookupOK(name string) (s *Sym, existed bool) {
// TODO(gri) remove this check in favor of specialized lookup
@@ -101,9 +98,6 @@ func (pkg *Pkg) LookupOK(name string) (s *Sym, existed bool) {
Name: name,
Pkg: pkg,
}
- if name == ".inittask" {
- InitSyms = append(InitSyms, s)
- }
pkg.Syms[name] = s
return s, false
}
diff --git a/src/cmd/compile/internal/types/scope.go b/src/cmd/compile/internal/types/scope.go
index 33a02c543d..04ea3c325f 100644
--- a/src/cmd/compile/internal/types/scope.go
+++ b/src/cmd/compile/internal/types/scope.go
@@ -4,7 +4,10 @@
package types
-import "cmd/internal/src"
+import (
+ "cmd/compile/internal/base"
+ "cmd/internal/src"
+)
// Declaration stack & operations
@@ -15,7 +18,7 @@ var Block int32 // current block number
// restored once the block scope ends.
type dsym struct {
sym *Sym // sym == nil indicates stack mark
- def IRNode
+ def Object
block int32
lastlineno src.XPos // last declaration for diagnostic
}
@@ -56,7 +59,7 @@ func Popdcl() {
d.sym = nil
d.def = nil
}
- Fatalf("popdcl: no stack mark")
+ base.Fatalf("popdcl: no stack mark")
}
// Markdcl records the start of a new block scope for declarations.
@@ -79,16 +82,16 @@ func IsDclstackValid() bool {
}
// PkgDef returns the definition associated with s at package scope.
-func (s *Sym) PkgDef() IRNode {
+func (s *Sym) PkgDef() Object {
return *s.pkgDefPtr()
}
// SetPkgDef sets the definition associated with s at package scope.
-func (s *Sym) SetPkgDef(n IRNode) {
+func (s *Sym) SetPkgDef(n Object) {
*s.pkgDefPtr() = n
}
-func (s *Sym) pkgDefPtr() *IRNode {
+func (s *Sym) pkgDefPtr() *Object {
// Look for outermost saved declaration, which must be the
// package scope definition, if present.
for _, d := range dclstack {
diff --git a/src/cmd/compile/internal/types/sizeof_test.go b/src/cmd/compile/internal/types/sizeof_test.go
index 2821d9a3c7..72a35bc7da 100644
--- a/src/cmd/compile/internal/types/sizeof_test.go
+++ b/src/cmd/compile/internal/types/sizeof_test.go
@@ -20,11 +20,11 @@ func TestSizeof(t *testing.T) {
_32bit uintptr // size on 32bit platforms
_64bit uintptr // size on 64bit platforms
}{
- {Sym{}, 60, 104},
+ {Sym{}, 52, 88},
{Type{}, 56, 96},
{Map{}, 20, 40},
{Forward{}, 20, 32},
- {Func{}, 28, 48},
+ {Func{}, 24, 40},
{Struct{}, 16, 32},
{Interface{}, 8, 16},
{Chan{}, 8, 16},
diff --git a/src/cmd/compile/internal/types/sym.go b/src/cmd/compile/internal/types/sym.go
index 046104d0dc..fcb095c53c 100644
--- a/src/cmd/compile/internal/types/sym.go
+++ b/src/cmd/compile/internal/types/sym.go
@@ -5,6 +5,7 @@
package types
import (
+ "cmd/compile/internal/base"
"cmd/internal/obj"
"cmd/internal/src"
"unicode"
@@ -33,13 +34,12 @@ type Sym struct {
Name string // object name
// saved and restored by dcopy
- Def IRNode // definition: ONAME OTYPE OPACK or OLITERAL
+ Def Object // definition: ONAME OTYPE OPACK or OLITERAL
Block int32 // blocknumber to catch redeclaration
Lastlineno src.XPos // last declaration for diagnostic
flags bitset8
- Label IRNode // corresponding label (ephemeral)
- Origpkg *Pkg // original package for . import
+ Origpkg *Pkg // original package for . import
}
const (
@@ -89,9 +89,9 @@ func (sym *Sym) Linksym() *obj.LSym {
}
if sym.Func() {
// This is a function symbol. Mark it as "internal ABI".
- return Ctxt.LookupABIInit(sym.LinksymName(), obj.ABIInternal, initPkg)
+ return base.Ctxt.LookupABIInit(sym.LinksymName(), obj.ABIInternal, initPkg)
}
- return Ctxt.LookupInit(sym.LinksymName(), initPkg)
+ return base.Ctxt.LookupInit(sym.LinksymName(), initPkg)
}
// Less reports whether symbol a is ordered before symbol b.
diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go
index 8499a36edc..4d1d30133c 100644
--- a/src/cmd/compile/internal/types/type.go
+++ b/src/cmd/compile/internal/types/type.go
@@ -5,6 +5,7 @@
package types
import (
+ "cmd/compile/internal/base"
"cmd/internal/obj"
"cmd/internal/src"
"fmt"
@@ -13,15 +14,19 @@ import (
// IRNode represents an ir.Node, but without needing to import cmd/compile/internal/ir,
// which would cause an import cycle. The uses in other packages must type assert
// values of type IRNode to ir.Node or a more specific type.
-type IRNode interface{ Type() *Type }
+type Object interface {
+ Pos() src.XPos
+ Sym() *Sym
+ Type() *Type
+}
//go:generate stringer -type EType -trimprefix T
// EType describes a kind of type.
-type EType uint8
+type Kind uint8
const (
- Txxx EType = iota
+ Txxx Kind = iota
TINT8
TUINT8
@@ -98,15 +103,15 @@ var Types [NTYPE]*Type
var (
// Predeclared alias types. Kept separate for better error messages.
- Bytetype *Type
- Runetype *Type
+ ByteType *Type
+ RuneType *Type
// Predeclared error interface type.
- Errortype *Type
+ ErrorType *Type
// Types to represent untyped string and boolean constants.
- UntypedString *Type
- UntypedBool *Type
+ UntypedString = New(TSTRING)
+ UntypedBool = New(TBOOL)
// Types to represent untyped numeric constants.
UntypedInt = New(TIDEAL)
@@ -141,24 +146,26 @@ type Type struct {
methods Fields
allMethods Fields
- Nod IRNode // canonical OTYPE node
- Orig *Type // original type (type literal or predefined type)
+ nod Object // canonical OTYPE node
+ underlying *Type // original type (type literal or predefined type)
// Cache of composite types, with this type being the element type.
- Cache struct {
+ cache struct {
ptr *Type // *T, or nil
slice *Type // []T, or nil
}
- Sym *Sym // symbol containing name, for named types
+ sym *Sym // symbol containing name, for named types
Vargen int32 // unique name for OTYPE/ONAME
- Etype EType // kind of type
+ kind Kind // kind of type
Align uint8 // the required alignment of this type, in bytes (0 means Width and Align have not yet been computed)
flags bitset8
}
+func (*Type) CanBeAnSSAAux() {}
+
const (
typeNotInHeap = 1 << iota // type cannot be heap allocated
typeBroke // broken type definition
@@ -179,6 +186,38 @@ func (t *Type) SetNoalg(b bool) { t.flags.set(typeNoalg, b) }
func (t *Type) SetDeferwidth(b bool) { t.flags.set(typeDeferwidth, b) }
func (t *Type) SetRecur(b bool) { t.flags.set(typeRecur, b) }
+// Kind returns the kind of type t.
+func (t *Type) Kind() Kind { return t.kind }
+
+// Sym returns the name of type t.
+func (t *Type) Sym() *Sym { return t.sym }
+
+// Underlying returns the underlying type of type t.
+func (t *Type) Underlying() *Type { return t.underlying }
+
+// SetNod associates t with syntax node n.
+func (t *Type) SetNod(n Object) {
+ // t.nod can be non-nil already
+ // in the case of shared *Types, like []byte or interface{}.
+ if t.nod == nil {
+ t.nod = n
+ }
+}
+
+// Pos returns a position associated with t, if any.
+// This should only be used for diagnostics.
+func (t *Type) Pos() src.XPos {
+ if t.nod != nil {
+ return t.nod.Pos()
+ }
+ return src.NoXPos
+}
+
+// NoPkg is a nil *Pkg value for clarity.
+// It's intended for use when constructing types that aren't exported
+// and thus don't need to be associated with any package.
+var NoPkg *Pkg = nil
+
// Pkg returns the package that t appeared in.
//
// Pkg is only defined for function, struct, and interface types
@@ -186,7 +225,7 @@ func (t *Type) SetRecur(b bool) { t.flags.set(typeRecur, b) }
// cmd/compile itself, but we need to track it because it's exposed by
// the go/types API.
func (t *Type) Pkg() *Pkg {
- switch t.Etype {
+ switch t.kind {
case TFUNC:
return t.Extra.(*Func).pkg
case TSTRUCT:
@@ -194,25 +233,11 @@ func (t *Type) Pkg() *Pkg {
case TINTER:
return t.Extra.(*Interface).pkg
default:
- Fatalf("Pkg: unexpected kind: %v", t)
+ base.Fatalf("Pkg: unexpected kind: %v", t)
return nil
}
}
-// SetPkg sets the package that t appeared in.
-func (t *Type) SetPkg(pkg *Pkg) {
- switch t.Etype {
- case TFUNC:
- t.Extra.(*Func).pkg = pkg
- case TSTRUCT:
- t.Extra.(*Struct).pkg = pkg
- case TINTER:
- t.Extra.(*Interface).pkg = pkg
- default:
- Fatalf("Pkg: unexpected kind: %v", t)
- }
-}
-
// Map contains Type fields specific to maps.
type Map struct {
Key *Type // Key type
@@ -253,8 +278,6 @@ type Func struct {
// It gets calculated via a temporary TFUNCARGS type.
// Note that TFUNC's Width is Widthptr.
Argwid int64
-
- Outnamed bool
}
// FuncType returns t's extra func-specific fields.
@@ -360,7 +383,7 @@ type Field struct {
// For fields that represent function parameters, Nname points
// to the associated ONAME Node.
- Nname IRNode
+ Nname Object
// Offset in bytes of this field or method within its enclosing struct
// or interface Type.
@@ -388,7 +411,7 @@ func (f *Field) End() int64 {
// IsMethod reports whether f represents a method rather than a struct field.
func (f *Field) IsMethod() bool {
- return f.Type.Etype == TFUNC && f.Type.Recv() != nil
+ return f.Type.kind == TFUNC && f.Type.Recv() != nil
}
// Fields is a pointer to a slice of *Field.
@@ -443,14 +466,14 @@ func (f *Fields) Append(s ...*Field) {
}
// New returns a new Type of the specified kind.
-func New(et EType) *Type {
+func New(et Kind) *Type {
t := &Type{
- Etype: et,
+ kind: et,
Width: BADWIDTH,
}
- t.Orig = t
+ t.underlying = t
// TODO(josharian): lazily initialize some of these?
- switch t.Etype {
+ switch t.kind {
case TMAP:
t.Extra = new(Map)
case TFORW:
@@ -480,7 +503,7 @@ func New(et EType) *Type {
// NewArray returns a new fixed-length array Type.
func NewArray(elem *Type, bound int64) *Type {
if bound < 0 {
- Fatalf("NewArray: invalid bound %v", bound)
+ base.Fatalf("NewArray: invalid bound %v", bound)
}
t := New(TARRAY)
t.Extra = &Array{Elem: elem, Bound: bound}
@@ -490,16 +513,16 @@ func NewArray(elem *Type, bound int64) *Type {
// NewSlice returns the slice Type with element type elem.
func NewSlice(elem *Type) *Type {
- if t := elem.Cache.slice; t != nil {
+ if t := elem.cache.slice; t != nil {
if t.Elem() != elem {
- Fatalf("elem mismatch")
+ base.Fatalf("elem mismatch")
}
return t
}
t := New(TSLICE)
t.Extra = Slice{Elem: elem}
- elem.Cache.slice = t
+ elem.cache.slice = t
return t
}
@@ -548,12 +571,12 @@ var NewPtrCacheEnabled = true
// NewPtr returns the pointer type pointing to t.
func NewPtr(elem *Type) *Type {
if elem == nil {
- Fatalf("NewPtr: pointer to elem Type is nil")
+ base.Fatalf("NewPtr: pointer to elem Type is nil")
}
- if t := elem.Cache.ptr; t != nil {
+ if t := elem.cache.ptr; t != nil {
if t.Elem() != elem {
- Fatalf("NewPtr: elem mismatch")
+ base.Fatalf("NewPtr: elem mismatch")
}
return t
}
@@ -563,7 +586,7 @@ func NewPtr(elem *Type) *Type {
t.Width = int64(Widthptr)
t.Align = uint8(Widthptr)
if NewPtrCacheEnabled {
- elem.Cache.ptr = t
+ elem.cache.ptr = t
}
return t
}
@@ -602,13 +625,13 @@ func SubstAny(t *Type, types *[]*Type) *Type {
return nil
}
- switch t.Etype {
+ switch t.kind {
default:
// Leave the type unchanged.
case TANY:
if len(*types) == 0 {
- Fatalf("substArgTypes: not enough argument types")
+ base.Fatalf("substArgTypes: not enough argument types")
}
t = (*types)[0]
*types = (*types)[1:]
@@ -686,7 +709,7 @@ func (t *Type) copy() *Type {
}
nt := *t
// copy any *T Extra fields, to avoid aliasing
- switch t.Etype {
+ switch t.kind {
case TMAP:
x := *t.Extra.(*Map)
nt.Extra = &x
@@ -709,11 +732,11 @@ func (t *Type) copy() *Type {
x := *t.Extra.(*Array)
nt.Extra = &x
case TTUPLE, TSSA, TRESULTS:
- Fatalf("ssa types cannot be copied")
+ base.Fatalf("ssa types cannot be copied")
}
// TODO(mdempsky): Find out why this is necessary and explain.
- if t.Orig == t {
- nt.Orig = &nt
+ if t.underlying == t {
+ nt.underlying = &nt
}
return &nt
}
@@ -723,9 +746,9 @@ func (f *Field) Copy() *Field {
return &nf
}
-func (t *Type) wantEtype(et EType) {
- if t.Etype != et {
- Fatalf("want %v, but have %v", et, t)
+func (t *Type) wantEtype(et Kind) {
+ if t.kind != et {
+ base.Fatalf("want %v, but have %v", et, t)
}
}
@@ -778,7 +801,7 @@ func (t *Type) Key() *Type {
// Elem returns the type of elements of t.
// Usable with pointers, channels, arrays, slices, and maps.
func (t *Type) Elem() *Type {
- switch t.Etype {
+ switch t.kind {
case TPTR:
return t.Extra.(Ptr).Elem
case TARRAY:
@@ -790,7 +813,7 @@ func (t *Type) Elem() *Type {
case TMAP:
return t.Extra.(*Map).Elem
}
- Fatalf("Type.Elem %s", t.Etype)
+ base.Fatalf("Type.Elem %s", t.kind)
return nil
}
@@ -808,7 +831,7 @@ func (t *Type) FuncArgs() *Type {
// IsFuncArgStruct reports whether t is a struct representing function parameters.
func (t *Type) IsFuncArgStruct() bool {
- return t.Etype == TSTRUCT && t.Extra.(*Struct).Funarg != FunargNone
+ return t.kind == TSTRUCT && t.Extra.(*Struct).Funarg != FunargNone
}
func (t *Type) Methods() *Fields {
@@ -822,14 +845,14 @@ func (t *Type) AllMethods() *Fields {
}
func (t *Type) Fields() *Fields {
- switch t.Etype {
+ switch t.kind {
case TSTRUCT:
return &t.Extra.(*Struct).fields
case TINTER:
Dowidth(t)
return &t.Extra.(*Interface).Fields
}
- Fatalf("Fields: type %v does not have fields", t)
+ base.Fatalf("Fields: type %v does not have fields", t)
return nil
}
@@ -853,7 +876,7 @@ func (t *Type) SetFields(fields []*Field) {
// enforce that SetFields cannot be called once
// t's width has been calculated.
if t.WidthCalculated() {
- Fatalf("SetFields of %v: width previously calculated", t)
+ base.Fatalf("SetFields of %v: width previously calculated", t)
}
t.wantEtype(TSTRUCT)
for _, f := range fields {
@@ -887,7 +910,7 @@ func (t *Type) ArgWidth() int64 {
}
func (t *Type) Size() int64 {
- if t.Etype == TSSA {
+ if t.kind == TSSA {
if t == TypeInt128 {
return 16
}
@@ -903,7 +926,7 @@ func (t *Type) Alignment() int64 {
}
func (t *Type) SimpleString() string {
- return t.Etype.String()
+ return t.kind.String()
}
// Cmp is a comparison between values a and b.
@@ -987,31 +1010,31 @@ func (t *Type) cmp(x *Type) Cmp {
return CMPgt
}
- if t.Etype != x.Etype {
- return cmpForNe(t.Etype < x.Etype)
+ if t.kind != x.kind {
+ return cmpForNe(t.kind < x.kind)
}
- if t.Sym != nil || x.Sym != nil {
+ if t.sym != nil || x.sym != nil {
// Special case: we keep byte and uint8 separate
// for error messages. Treat them as equal.
- switch t.Etype {
+ switch t.kind {
case TUINT8:
- if (t == Types[TUINT8] || t == Bytetype) && (x == Types[TUINT8] || x == Bytetype) {
+ if (t == Types[TUINT8] || t == ByteType) && (x == Types[TUINT8] || x == ByteType) {
return CMPeq
}
case TINT32:
- if (t == Types[Runetype.Etype] || t == Runetype) && (x == Types[Runetype.Etype] || x == Runetype) {
+ if (t == Types[RuneType.kind] || t == RuneType) && (x == Types[RuneType.kind] || x == RuneType) {
return CMPeq
}
}
}
- if c := t.Sym.cmpsym(x.Sym); c != CMPeq {
+ if c := t.sym.cmpsym(x.sym); c != CMPeq {
return c
}
- if x.Sym != nil {
+ if x.sym != nil {
// Syms non-nil, if vargens match then equal.
if t.Vargen != x.Vargen {
return cmpForNe(t.Vargen < x.Vargen)
@@ -1020,7 +1043,7 @@ func (t *Type) cmp(x *Type) Cmp {
}
// both syms nil, look at structure below.
- switch t.Etype {
+ switch t.kind {
case TBOOL, TFLOAT32, TFLOAT64, TCOMPLEX64, TCOMPLEX128, TUNSAFEPTR, TUINTPTR,
TINT8, TINT16, TINT32, TINT64, TINT, TUINT8, TUINT16, TUINT32, TUINT64, TUINT:
return CMPeq
@@ -1177,15 +1200,15 @@ func (t *Type) cmp(x *Type) Cmp {
}
// IsKind reports whether t is a Type of the specified kind.
-func (t *Type) IsKind(et EType) bool {
- return t != nil && t.Etype == et
+func (t *Type) IsKind(et Kind) bool {
+ return t != nil && t.kind == et
}
func (t *Type) IsBoolean() bool {
- return t.Etype == TBOOL
+ return t.kind == TBOOL
}
-var unsignedEType = [...]EType{
+var unsignedEType = [...]Kind{
TINT8: TUINT8,
TUINT8: TUINT8,
TINT16: TUINT16,
@@ -1202,13 +1225,13 @@ var unsignedEType = [...]EType{
// ToUnsigned returns the unsigned equivalent of integer type t.
func (t *Type) ToUnsigned() *Type {
if !t.IsInteger() {
- Fatalf("unsignedType(%v)", t)
+ base.Fatalf("unsignedType(%v)", t)
}
- return Types[unsignedEType[t.Etype]]
+ return Types[unsignedEType[t.kind]]
}
func (t *Type) IsInteger() bool {
- switch t.Etype {
+ switch t.kind {
case TINT8, TUINT8, TINT16, TUINT16, TINT32, TUINT32, TINT64, TUINT64, TINT, TUINT, TUINTPTR:
return true
}
@@ -1216,7 +1239,7 @@ func (t *Type) IsInteger() bool {
}
func (t *Type) IsSigned() bool {
- switch t.Etype {
+ switch t.kind {
case TINT8, TINT16, TINT32, TINT64, TINT:
return true
}
@@ -1224,7 +1247,7 @@ func (t *Type) IsSigned() bool {
}
func (t *Type) IsUnsigned() bool {
- switch t.Etype {
+ switch t.kind {
case TUINT8, TUINT16, TUINT32, TUINT64, TUINT, TUINTPTR:
return true
}
@@ -1232,32 +1255,32 @@ func (t *Type) IsUnsigned() bool {
}
func (t *Type) IsFloat() bool {
- return t.Etype == TFLOAT32 || t.Etype == TFLOAT64 || t == UntypedFloat
+ return t.kind == TFLOAT32 || t.kind == TFLOAT64 || t == UntypedFloat
}
func (t *Type) IsComplex() bool {
- return t.Etype == TCOMPLEX64 || t.Etype == TCOMPLEX128 || t == UntypedComplex
+ return t.kind == TCOMPLEX64 || t.kind == TCOMPLEX128 || t == UntypedComplex
}
// IsPtr reports whether t is a regular Go pointer type.
// This does not include unsafe.Pointer.
func (t *Type) IsPtr() bool {
- return t.Etype == TPTR
+ return t.kind == TPTR
}
// IsPtrElem reports whether t is the element of a pointer (to t).
func (t *Type) IsPtrElem() bool {
- return t.Cache.ptr != nil
+ return t.cache.ptr != nil
}
// IsUnsafePtr reports whether t is an unsafe pointer.
func (t *Type) IsUnsafePtr() bool {
- return t.Etype == TUNSAFEPTR
+ return t.kind == TUNSAFEPTR
}
// IsUintptr reports whether t is an uintptr.
func (t *Type) IsUintptr() bool {
- return t.Etype == TUINTPTR
+ return t.kind == TUINTPTR
}
// IsPtrShaped reports whether t is represented by a single machine pointer.
@@ -1266,13 +1289,13 @@ func (t *Type) IsUintptr() bool {
// that consist of a single pointer shaped type.
// TODO(mdempsky): Should it? See golang.org/issue/15028.
func (t *Type) IsPtrShaped() bool {
- return t.Etype == TPTR || t.Etype == TUNSAFEPTR ||
- t.Etype == TMAP || t.Etype == TCHAN || t.Etype == TFUNC
+ return t.kind == TPTR || t.kind == TUNSAFEPTR ||
+ t.kind == TMAP || t.kind == TCHAN || t.kind == TFUNC
}
// HasNil reports whether the set of values determined by t includes nil.
func (t *Type) HasNil() bool {
- switch t.Etype {
+ switch t.kind {
case TCHAN, TFUNC, TINTER, TMAP, TNIL, TPTR, TSLICE, TUNSAFEPTR:
return true
}
@@ -1280,31 +1303,31 @@ func (t *Type) HasNil() bool {
}
func (t *Type) IsString() bool {
- return t.Etype == TSTRING
+ return t.kind == TSTRING
}
func (t *Type) IsMap() bool {
- return t.Etype == TMAP
+ return t.kind == TMAP
}
func (t *Type) IsChan() bool {
- return t.Etype == TCHAN
+ return t.kind == TCHAN
}
func (t *Type) IsSlice() bool {
- return t.Etype == TSLICE
+ return t.kind == TSLICE
}
func (t *Type) IsArray() bool {
- return t.Etype == TARRAY
+ return t.kind == TARRAY
}
func (t *Type) IsStruct() bool {
- return t.Etype == TSTRUCT
+ return t.kind == TSTRUCT
}
func (t *Type) IsInterface() bool {
- return t.Etype == TINTER
+ return t.kind == TINTER
}
// IsEmptyInterface reports whether t is an empty interface type.
@@ -1312,6 +1335,20 @@ func (t *Type) IsEmptyInterface() bool {
return t.IsInterface() && t.NumFields() == 0
}
+// IsScalar reports whether 't' is a scalar Go type, e.g.
+// bool/int/float/complex. Note that struct and array types consisting
+// of a single scalar element are not considered scalar, likewise
+// pointer types are also not considered scalar.
+func (t *Type) IsScalar() bool {
+ switch t.kind {
+ case TBOOL, TINT8, TUINT8, TINT16, TUINT16, TINT32,
+ TUINT32, TINT64, TUINT64, TINT, TUINT,
+ TUINTPTR, TCOMPLEX64, TCOMPLEX128, TFLOAT32, TFLOAT64:
+ return true
+ }
+ return false
+}
+
func (t *Type) PtrTo() *Type {
return NewPtr(t)
}
@@ -1320,7 +1357,7 @@ func (t *Type) NumFields() int {
return t.Fields().Len()
}
func (t *Type) FieldType(i int) *Type {
- if t.Etype == TTUPLE {
+ if t.kind == TTUPLE {
switch i {
case 0:
return t.Extra.(*Tuple).first
@@ -1330,7 +1367,7 @@ func (t *Type) FieldType(i int) *Type {
panic("bad tuple index")
}
}
- if t.Etype == TRESULTS {
+ if t.kind == TRESULTS {
return t.Extra.(*Results).Types[i]
}
return t.Field(i).Type
@@ -1361,10 +1398,10 @@ const (
// (and their comprised elements) are excluded from the count.
// struct { x, y [3]int } has six components; [10]struct{ x, y string } has twenty.
func (t *Type) NumComponents(countBlank componentsIncludeBlankFields) int64 {
- switch t.Etype {
+ switch t.kind {
case TSTRUCT:
if t.IsFuncArgStruct() {
- Fatalf("NumComponents func arg struct")
+ base.Fatalf("NumComponents func arg struct")
}
var n int64
for _, f := range t.FieldSlice() {
@@ -1384,10 +1421,10 @@ func (t *Type) NumComponents(countBlank componentsIncludeBlankFields) int64 {
// if there is exactly one. Otherwise, it returns nil.
// Components are counted as in NumComponents, including blank fields.
func (t *Type) SoleComponent() *Type {
- switch t.Etype {
+ switch t.kind {
case TSTRUCT:
if t.IsFuncArgStruct() {
- Fatalf("SoleComponent func arg struct")
+ base.Fatalf("SoleComponent func arg struct")
}
if t.NumFields() != 1 {
return nil
@@ -1410,10 +1447,10 @@ func (t *Type) ChanDir() ChanDir {
}
func (t *Type) IsMemory() bool {
- if t == TypeMem || t.Etype == TTUPLE && t.Extra.(*Tuple).second == TypeMem {
+ if t == TypeMem || t.kind == TTUPLE && t.Extra.(*Tuple).second == TypeMem {
return true
}
- if t.Etype == TRESULTS {
+ if t.kind == TRESULTS {
if types := t.Extra.(*Results).Types; len(types) > 0 && types[len(types)-1] == TypeMem {
return true
}
@@ -1422,8 +1459,8 @@ func (t *Type) IsMemory() bool {
}
func (t *Type) IsFlags() bool { return t == TypeFlags }
func (t *Type) IsVoid() bool { return t == TypeVoid }
-func (t *Type) IsTuple() bool { return t.Etype == TTUPLE }
-func (t *Type) IsResults() bool { return t.Etype == TRESULTS }
+func (t *Type) IsTuple() bool { return t.kind == TTUPLE }
+func (t *Type) IsResults() bool { return t.kind == TRESULTS }
// IsUntyped reports whether t is an untyped type.
func (t *Type) IsUntyped() bool {
@@ -1433,7 +1470,7 @@ func (t *Type) IsUntyped() bool {
if t == UntypedString || t == UntypedBool {
return true
}
- switch t.Etype {
+ switch t.kind {
case TNIL, TIDEAL:
return true
}
@@ -1443,7 +1480,7 @@ func (t *Type) IsUntyped() bool {
// HasPointers reports whether t contains a heap pointer.
// Note that this function ignores pointers to go:notinheap types.
func (t *Type) HasPointers() bool {
- switch t.Etype {
+ switch t.kind {
case TINT, TUINT, TINT8, TUINT8, TINT16, TUINT16, TINT32, TUINT32, TINT64,
TUINT64, TUINTPTR, TFLOAT32, TFLOAT64, TCOMPLEX64, TCOMPLEX128, TBOOL, TSSA:
return false
@@ -1517,3 +1554,132 @@ var (
TypeVoid = newSSA("void")
TypeInt128 = newSSA("int128")
)
+
+// NewNamed returns a new named type for the given type name.
+func NewNamed(obj Object) *Type {
+ t := New(TFORW)
+ t.sym = obj.Sym()
+ t.nod = obj
+ return t
+}
+
+// Obj returns the type name for the named type t.
+func (t *Type) Obj() Object {
+ if t.sym != nil {
+ return t.nod
+ }
+ return nil
+}
+
+// SetUnderlying sets the underlying type.
+func (t *Type) SetUnderlying(underlying *Type) {
+ if underlying.kind == TFORW {
+ // This type isn't computed yet; when it is, update n.
+ underlying.ForwardType().Copyto = append(underlying.ForwardType().Copyto, t)
+ return
+ }
+
+ ft := t.ForwardType()
+
+ // TODO(mdempsky): Fix Type rekinding.
+ t.kind = underlying.kind
+ t.Extra = underlying.Extra
+ t.Width = underlying.Width
+ t.Align = underlying.Align
+ t.underlying = underlying.underlying
+
+ if underlying.NotInHeap() {
+ t.SetNotInHeap(true)
+ }
+ if underlying.Broke() {
+ t.SetBroke(true)
+ }
+
+ // spec: "The declared type does not inherit any methods bound
+ // to the existing type, but the method set of an interface
+ // type [...] remains unchanged."
+ if t.IsInterface() {
+ t.methods = underlying.methods
+ t.allMethods = underlying.allMethods
+ }
+
+ // Update types waiting on this type.
+ for _, w := range ft.Copyto {
+ w.SetUnderlying(t)
+ }
+
+ // Double-check use of type as embedded type.
+ if ft.Embedlineno.IsKnown() {
+ if t.IsPtr() || t.IsUnsafePtr() {
+ base.ErrorfAt(ft.Embedlineno, "embedded type cannot be a pointer")
+ }
+ }
+}
+
+// NewBasic returns a new basic type of the given kind.
+func NewBasic(kind Kind, obj Object) *Type {
+ t := New(kind)
+ t.sym = obj.Sym()
+ t.nod = obj
+ return t
+}
+
+// NewInterface returns a new interface for the given methods and
+// embedded types. Embedded types are specified as fields with no Sym.
+func NewInterface(pkg *Pkg, methods []*Field) *Type {
+ t := New(TINTER)
+ t.SetInterface(methods)
+ if anyBroke(methods) {
+ t.SetBroke(true)
+ }
+ t.Extra.(*Interface).pkg = pkg
+ return t
+}
+
+// NewSignature returns a new function type for the given receiver,
+// parameters, and results, any of which may be nil.
+func NewSignature(pkg *Pkg, recv *Field, params, results []*Field) *Type {
+ var recvs []*Field
+ if recv != nil {
+ recvs = []*Field{recv}
+ }
+
+ t := New(TFUNC)
+ ft := t.FuncType()
+
+ funargs := func(fields []*Field, funarg Funarg) *Type {
+ s := NewStruct(NoPkg, fields)
+ s.StructType().Funarg = funarg
+ if s.Broke() {
+ t.SetBroke(true)
+ }
+ return s
+ }
+
+ ft.Receiver = funargs(recvs, FunargRcvr)
+ ft.Params = funargs(params, FunargParams)
+ ft.Results = funargs(results, FunargResults)
+ ft.pkg = pkg
+
+ return t
+}
+
+// NewStruct returns a new struct with the given fields.
+func NewStruct(pkg *Pkg, fields []*Field) *Type {
+ t := New(TSTRUCT)
+ t.SetFields(fields)
+ if anyBroke(fields) {
+ t.SetBroke(true)
+ }
+ t.Extra.(*Struct).pkg = pkg
+ return t
+}
+
+func anyBroke(fields []*Field) bool {
+ for _, f := range fields {
+ if f.Broke() {
+ return true
+ }
+ }
+ return false
+}
diff --git a/src/cmd/compile/internal/types/utils.go b/src/cmd/compile/internal/types/utils.go
index e8b1073818..531f3ea1ca 100644
--- a/src/cmd/compile/internal/types/utils.go
+++ b/src/cmd/compile/internal/types/utils.go
@@ -6,7 +6,6 @@ package types
import (
"cmd/internal/obj"
- "fmt"
)
const BADWIDTH = -1000000000
@@ -17,51 +16,9 @@ const BADWIDTH = -1000000000
var (
Widthptr int
Dowidth func(*Type)
- Fatalf func(string, ...interface{})
- Sconv func(*Sym, int, int) string // orig: func sconv(s *Sym, flag FmtFlag, mode fmtMode) string
- Tconv func(*Type, int, int) string // orig: func tconv(t *Type, flag FmtFlag, mode fmtMode) string
- FormatSym func(*Sym, fmt.State, rune, int) // orig: func symFormat(sym *Sym, s fmt.State, verb rune, mode fmtMode)
- FormatType func(*Type, fmt.State, rune, int) // orig: func typeFormat(t *Type, s fmt.State, verb rune, mode fmtMode)
TypeLinkSym func(*Type) *obj.LSym
- Ctxt *obj.Link
-
- FmtLeft int
- FmtUnsigned int
- FErr int
)
-func (s *Sym) String() string {
- return Sconv(s, 0, FErr)
-}
-
-func (sym *Sym) Format(s fmt.State, verb rune) {
- FormatSym(sym, s, verb, FErr)
-}
-
-func (t *Type) String() string {
- // The implementation of tconv (including typefmt and fldconv)
- // must handle recursive types correctly.
- return Tconv(t, 0, FErr)
-}
-
-// ShortString generates a short description of t.
-// It is used in autogenerated method names, reflection,
-// and itab names.
-func (t *Type) ShortString() string {
- return Tconv(t, FmtLeft, FErr)
-}
-
-// LongString generates a complete description of t.
-// It is useful for reflection,
-// or when a unique fingerprint or hash of a type is required.
-func (t *Type) LongString() string {
- return Tconv(t, FmtLeft|FmtUnsigned, FErr)
-}
-
-func (t *Type) Format(s fmt.State, verb rune) {
- FormatType(t, s, verb, FErr)
-}
-
type bitset8 uint8
func (f *bitset8) set(mask uint8, b bool) {
diff --git a/src/cmd/compile/internal/types2/stdlib_test.go b/src/cmd/compile/internal/types2/stdlib_test.go
index 89e49d84d6..ae573a4ec8 100644
--- a/src/cmd/compile/internal/types2/stdlib_test.go
+++ b/src/cmd/compile/internal/types2/stdlib_test.go
@@ -162,6 +162,7 @@ func TestStdTest(t *testing.T) {
testTestDir(t, filepath.Join(runtime.GOROOT(), "test"),
"cmplxdivide.go", // also needs file cmplxdivide1.go - ignore
"directive.go", // tests compiler rejection of bad directive placement - ignore
+ "linkname2.go", // types2 doesn't check validity of //go:xxx directives
)
}
diff --git a/src/cmd/compile/internal/wasm/ssa.go b/src/cmd/compile/internal/wasm/ssa.go
index e7451381b4..c9a52a5f73 100644
--- a/src/cmd/compile/internal/wasm/ssa.go
+++ b/src/cmd/compile/internal/wasm/ssa.go
@@ -232,12 +232,18 @@ func ssaGenValueOnStack(s *gc.SSAGenState, v *ssa.Value, extend bool) {
}
case ssa.OpWasmLoweredAddr:
+ if v.Aux == nil { // address of off(SP), no symbol
+ getValue64(s, v.Args[0])
+ i64Const(s, v.AuxInt)
+ s.Prog(wasm.AI64Add)
+ break
+ }
p := s.Prog(wasm.AGet)
p.From.Type = obj.TYPE_ADDR
switch v.Aux.(type) {
case *obj.LSym:
gc.AddAux(&p.From, v)
- case ir.Node:
+ case *ir.Name:
p.From.Reg = v.Args[0].Reg()
gc.AddAux(&p.From, v)
default:
diff --git a/src/cmd/cover/cover.go b/src/cmd/cover/cover.go
index 360f9aeb06..7ee000861b 100644
--- a/src/cmd/cover/cover.go
+++ b/src/cmd/cover/cover.go
@@ -12,7 +12,6 @@ import (
"go/parser"
"go/token"
"io"
- "io/ioutil"
"log"
"os"
"sort"
@@ -304,7 +303,7 @@ func (f *File) Visit(node ast.Node) ast.Visitor {
func annotate(name string) {
fset := token.NewFileSet()
- content, err := ioutil.ReadFile(name)
+ content, err := os.ReadFile(name)
if err != nil {
log.Fatalf("cover: %s: %s", name, err)
}
diff --git a/src/cmd/cover/cover_test.go b/src/cmd/cover/cover_test.go
index 1c252e6e45..86c95d15c5 100644
--- a/src/cmd/cover/cover_test.go
+++ b/src/cmd/cover/cover_test.go
@@ -13,7 +13,6 @@ import (
"go/parser"
"go/token"
"internal/testenv"
- "io/ioutil"
"os"
"os/exec"
"path/filepath"
@@ -81,7 +80,7 @@ var debug = flag.Bool("debug", false, "keep rewritten files for debugging")
// We use TestMain to set up a temporary directory and remove it when
// the tests are done.
func TestMain(m *testing.M) {
- dir, err := ioutil.TempDir("", "go-testcover")
+ dir, err := os.MkdirTemp("", "go-testcover")
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
@@ -173,7 +172,7 @@ func TestCover(t *testing.T) {
buildCover(t)
// Read in the test file (testTest) and write it, with LINEs specified, to coverInput.
- file, err := ioutil.ReadFile(testTest)
+ file, err := os.ReadFile(testTest)
if err != nil {
t.Fatal(err)
}
@@ -192,7 +191,7 @@ func TestCover(t *testing.T) {
[]byte("}"))
lines = append(lines, []byte("func unFormatted2(b bool) {if b{}else{}}"))
- if err := ioutil.WriteFile(coverInput, bytes.Join(lines, []byte("\n")), 0666); err != nil {
+ if err := os.WriteFile(coverInput, bytes.Join(lines, []byte("\n")), 0666); err != nil {
t.Fatal(err)
}
@@ -208,11 +207,11 @@ func TestCover(t *testing.T) {
// Copy testmain to testTempDir, so that it is in the same directory
// as coverOutput.
- b, err := ioutil.ReadFile(testMain)
+ b, err := os.ReadFile(testMain)
if err != nil {
t.Fatal(err)
}
- if err := ioutil.WriteFile(tmpTestMain, b, 0444); err != nil {
+ if err := os.WriteFile(tmpTestMain, b, 0444); err != nil {
t.Fatal(err)
}
@@ -220,7 +219,7 @@ func TestCover(t *testing.T) {
cmd = exec.Command(testenv.GoToolPath(t), "run", tmpTestMain, coverOutput)
run(cmd, t)
- file, err = ioutil.ReadFile(coverOutput)
+ file, err = os.ReadFile(coverOutput)
if err != nil {
t.Fatal(err)
}
@@ -251,7 +250,7 @@ func TestDirectives(t *testing.T) {
// Read the source file and find all the directives. We'll keep
// track of whether each one has been seen in the output.
testDirectives := filepath.Join(testdata, "directives.go")
- source, err := ioutil.ReadFile(testDirectives)
+ source, err := os.ReadFile(testDirectives)
if err != nil {
t.Fatal(err)
}
@@ -398,7 +397,7 @@ func TestCoverHTML(t *testing.T) {
// Extract the parts of the HTML with comment markers,
// and compare against a golden file.
- entireHTML, err := ioutil.ReadFile(htmlHTML)
+ entireHTML, err := os.ReadFile(htmlHTML)
if err != nil {
t.Fatal(err)
}
@@ -420,7 +419,7 @@ func TestCoverHTML(t *testing.T) {
if scan.Err() != nil {
t.Error(scan.Err())
}
- golden, err := ioutil.ReadFile(htmlGolden)
+ golden, err := os.ReadFile(htmlGolden)
if err != nil {
t.Fatalf("reading golden file: %v", err)
}
@@ -457,7 +456,7 @@ func TestHtmlUnformatted(t *testing.T) {
t.Fatal(err)
}
- if err := ioutil.WriteFile(filepath.Join(htmlUDir, "go.mod"), []byte("module htmlunformatted\n"), 0666); err != nil {
+ if err := os.WriteFile(filepath.Join(htmlUDir, "go.mod"), []byte("module htmlunformatted\n"), 0666); err != nil {
t.Fatal(err)
}
@@ -474,10 +473,10 @@ lab:
const htmlUTestContents = `package htmlunformatted`
- if err := ioutil.WriteFile(htmlU, []byte(htmlUContents), 0444); err != nil {
+ if err := os.WriteFile(htmlU, []byte(htmlUContents), 0444); err != nil {
t.Fatal(err)
}
- if err := ioutil.WriteFile(htmlUTest, []byte(htmlUTestContents), 0444); err != nil {
+ if err := os.WriteFile(htmlUTest, []byte(htmlUTestContents), 0444); err != nil {
t.Fatal(err)
}
@@ -540,13 +539,13 @@ func TestFuncWithDuplicateLines(t *testing.T) {
t.Fatal(err)
}
- if err := ioutil.WriteFile(filepath.Join(lineDupDir, "go.mod"), []byte("module linedup\n"), 0666); err != nil {
+ if err := os.WriteFile(filepath.Join(lineDupDir, "go.mod"), []byte("module linedup\n"), 0666); err != nil {
t.Fatal(err)
}
- if err := ioutil.WriteFile(lineDupGo, []byte(lineDupContents), 0444); err != nil {
+ if err := os.WriteFile(lineDupGo, []byte(lineDupContents), 0444); err != nil {
t.Fatal(err)
}
- if err := ioutil.WriteFile(lineDupTestGo, []byte(lineDupTestContents), 0444); err != nil {
+ if err := os.WriteFile(lineDupTestGo, []byte(lineDupTestContents), 0444); err != nil {
t.Fatal(err)
}
diff --git a/src/cmd/cover/html.go b/src/cmd/cover/html.go
index f76ea03cf5..b2865c427c 100644
--- a/src/cmd/cover/html.go
+++ b/src/cmd/cover/html.go
@@ -11,7 +11,6 @@ import (
"fmt"
"html/template"
"io"
- "io/ioutil"
"math"
"os"
"path/filepath"
@@ -43,7 +42,7 @@ func htmlOutput(profile, outfile string) error {
if err != nil {
return err
}
- src, err := ioutil.ReadFile(file)
+ src, err := os.ReadFile(file)
if err != nil {
return fmt.Errorf("can't read %q: %v", fn, err)
}
@@ -62,7 +61,7 @@ func htmlOutput(profile, outfile string) error {
var out *os.File
if outfile == "" {
var dir string
- dir, err = ioutil.TempDir("", "cover")
+ dir, err = os.MkdirTemp("", "cover")
if err != nil {
return err
}
diff --git a/src/cmd/dist/buildtool.go b/src/cmd/dist/buildtool.go
index 5dfd5ee16e..4dda70d124 100644
--- a/src/cmd/dist/buildtool.go
+++ b/src/cmd/dist/buildtool.go
@@ -57,6 +57,7 @@ var bootstrapDirs = []string{
"cmd/compile/internal/x86",
"cmd/compile/internal/wasm",
"cmd/internal/bio",
+ "cmd/internal/codesign",
"cmd/internal/gcprog",
"cmd/internal/dwarf",
"cmd/internal/edit",
diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go
index 2a17ab9cae..955ce2a063 100644
--- a/src/cmd/dist/test.go
+++ b/src/cmd/dist/test.go
@@ -1509,6 +1509,7 @@ func (t *tester) makeGOROOTUnwritable() (undo func()) {
}
gocacheSubdir, _ := filepath.Rel(dir, gocache)
+ // Note: Can't use WalkDir here, because this has to compile with Go 1.4.
filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
if suffix := strings.TrimPrefix(path, dir+string(filepath.Separator)); suffix != "" {
if suffix == gocacheSubdir {
diff --git a/src/cmd/fix/main.go b/src/cmd/fix/main.go
index 1cea9a876a..d055929aac 100644
--- a/src/cmd/fix/main.go
+++ b/src/cmd/fix/main.go
@@ -15,7 +15,6 @@ import (
"go/token"
"io"
"io/fs"
- "io/ioutil"
"os"
"path/filepath"
"sort"
@@ -217,7 +216,7 @@ func processFile(filename string, useStdin bool) error {
return nil
}
- return ioutil.WriteFile(f.Name(), newSrc, 0)
+ return os.WriteFile(f.Name(), newSrc, 0)
}
func gofmt(n interface{}) string {
@@ -234,10 +233,10 @@ func report(err error) {
}
func walkDir(path string) {
- filepath.Walk(path, visitFile)
+ filepath.WalkDir(path, visitFile)
}
-func visitFile(path string, f fs.FileInfo, err error) error {
+func visitFile(path string, f fs.DirEntry, err error) error {
if err == nil && isGoFile(f) {
err = processFile(path, false)
}
@@ -247,7 +246,7 @@ func visitFile(path string, f fs.FileInfo, err error) error {
return nil
}
-func isGoFile(f fs.FileInfo) bool {
+func isGoFile(f fs.DirEntry) bool {
// ignore non-Go files
name := f.Name()
return !f.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go")
diff --git a/src/cmd/fix/typecheck.go b/src/cmd/fix/typecheck.go
index f45155b06d..40b2287f26 100644
--- a/src/cmd/fix/typecheck.go
+++ b/src/cmd/fix/typecheck.go
@@ -9,7 +9,6 @@ import (
"go/ast"
"go/parser"
"go/token"
- "io/ioutil"
"os"
"os/exec"
"path/filepath"
@@ -162,12 +161,12 @@ func typecheck(cfg *TypeConfig, f *ast.File) (typeof map[interface{}]string, ass
if err != nil {
return err
}
- dir, err := ioutil.TempDir(os.TempDir(), "fix_cgo_typecheck")
+ dir, err := os.MkdirTemp(os.TempDir(), "fix_cgo_typecheck")
if err != nil {
return err
}
defer os.RemoveAll(dir)
- err = ioutil.WriteFile(filepath.Join(dir, "in.go"), txt, 0600)
+ err = os.WriteFile(filepath.Join(dir, "in.go"), txt, 0600)
if err != nil {
return err
}
@@ -176,7 +175,7 @@ func typecheck(cfg *TypeConfig, f *ast.File) (typeof map[interface{}]string, ass
if err != nil {
return err
}
- out, err := ioutil.ReadFile(filepath.Join(dir, "_cgo_gotypes.go"))
+ out, err := os.ReadFile(filepath.Join(dir, "_cgo_gotypes.go"))
if err != nil {
return err
}
diff --git a/src/cmd/go.mod b/src/cmd/go.mod
index 6f55b2d1c8..c7d43873ef 100644
--- a/src/cmd/go.mod
+++ b/src/cmd/go.mod
@@ -3,11 +3,10 @@ module cmd
go 1.16
require (
- github.com/google/pprof v0.0.0-20201007051231-1066cbb265c7
- github.com/ianlancetaylor/demangle v0.0.0-20200414190113-039b1ae3a340 // indirect
+ github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2
golang.org/x/arch v0.0.0-20201008161808-52c3e6f60cff
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897
- golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449
- golang.org/x/sys v0.0.0-20201110211018-35f3e6cf4a65 // indirect
- golang.org/x/tools v0.0.0-20201110201400-7099162a900a
+ golang.org/x/mod v0.4.0
+ golang.org/x/sys v0.0.0-20201204225414-ed752295db88 // indirect
+ golang.org/x/tools v0.0.0-20201208211828-de58e7c01d49
)
diff --git a/src/cmd/go.sum b/src/cmd/go.sum
index 8775b754d8..30edf77282 100644
--- a/src/cmd/go.sum
+++ b/src/cmd/go.sum
@@ -1,11 +1,10 @@
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
-github.com/google/pprof v0.0.0-20201007051231-1066cbb265c7 h1:qYWTuM6SUNWgtvkhV8oH6GFHCpU+rKQOxPcepM3xKi0=
-github.com/google/pprof v0.0.0-20201007051231-1066cbb265c7/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
-github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
-github.com/ianlancetaylor/demangle v0.0.0-20200414190113-039b1ae3a340 h1:S1+yTUaFPXuDZnPDbO+TrDFIjPzQraYH8/CwSlu9Fac=
-github.com/ianlancetaylor/demangle v0.0.0-20200414190113-039b1ae3a340/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
+github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2 h1:HyOHhUtuB/Ruw/L5s5pG2D0kckkN2/IzBs9OClGHnHI=
+github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
+github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639 h1:mV02weKRL81bEnm8A0HT1/CAelMQDBuQIfLw8n+d6xI=
+github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
golang.org/x/arch v0.0.0-20201008161808-52c3e6f60cff h1:XmKBi9R6duxOB3lfc72wyrwiOY7X2Jl1wuI+RFOyMDE=
golang.org/x/arch v0.0.0-20201008161808-52c3e6f60cff/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4=
@@ -15,8 +14,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E=
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449 h1:xUIPaMhvROX9dhPvRCenIJtU78+lbEenGbgqB5hfHCQ=
-golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.4.0 h1:8pl+sMODzuvGJkmj2W4kZihvVb5mKm8pB/X44PIQHv8=
+golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
@@ -26,14 +25,14 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20201110211018-35f3e6cf4a65 h1:Qo9oJ566/Sq7N4hrGftVXs8GI2CXBCuOd4S2wHE/e0M=
-golang.org/x/sys v0.0.0-20201110211018-35f3e6cf4a65/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201204225414-ed752295db88 h1:KmZPnMocC93w341XZp26yTJg8Za7lhb2KhkYmixoeso=
+golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20201110201400-7099162a900a h1:5E6TPwSBG74zT8xSrVc8W59K4ch4NFobVTnh2BYzHyU=
-golang.org/x/tools v0.0.0-20201110201400-7099162a900a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.0.0-20201208211828-de58e7c01d49 h1:K1QAOVIWIvmQ66F1Z3AEa9Wzp0bj+xU3YzLkvROk2Ds=
+golang.org/x/tools v0.0.0-20201208211828-de58e7c01d49/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go
index a02231fa98..19764bfc60 100644
--- a/src/cmd/go/go_test.go
+++ b/src/cmd/go/go_test.go
@@ -17,7 +17,6 @@ import (
"internal/testenv"
"io"
"io/fs"
- "io/ioutil"
"log"
"os"
"os/exec"
@@ -100,7 +99,7 @@ func TestMain(m *testing.M) {
// Run with a temporary TMPDIR to check that the tests don't
// leave anything behind.
- topTmpdir, err := ioutil.TempDir("", "cmd-go-test-")
+ topTmpdir, err := os.MkdirTemp("", "cmd-go-test-")
if err != nil {
log.Fatal(err)
}
@@ -109,7 +108,7 @@ func TestMain(m *testing.M) {
}
os.Setenv(tempEnvName(), topTmpdir)
- dir, err := ioutil.TempDir(topTmpdir, "tmpdir")
+ dir, err := os.MkdirTemp(topTmpdir, "tmpdir")
if err != nil {
log.Fatal(err)
}
@@ -616,7 +615,7 @@ func (tg *testgoData) makeTempdir() {
tg.t.Helper()
if tg.tempdir == "" {
var err error
- tg.tempdir, err = ioutil.TempDir("", "gotest")
+ tg.tempdir, err = os.MkdirTemp("", "gotest")
tg.must(err)
}
}
@@ -633,7 +632,7 @@ func (tg *testgoData) tempFile(path, contents string) {
bytes = formatted
}
}
- tg.must(ioutil.WriteFile(filepath.Join(tg.tempdir, path), bytes, 0644))
+ tg.must(os.WriteFile(filepath.Join(tg.tempdir, path), bytes, 0644))
}
// tempDir adds a temporary directory for a run of testgo.
@@ -774,7 +773,7 @@ func (tg *testgoData) cleanup() {
func removeAll(dir string) error {
// module cache has 0444 directories;
// make them writable in order to remove content.
- filepath.Walk(dir, func(path string, info fs.FileInfo, err error) error {
+ filepath.WalkDir(dir, func(path string, info fs.DirEntry, err error) error {
// chmod not only directories, but also things that we couldn't even stat
// due to permission errors: they may also be unreadable directories.
if err != nil || info.IsDir() {
@@ -820,8 +819,8 @@ func TestNewReleaseRebuildsStalePackagesInGOPATH(t *testing.T) {
} {
srcdir := filepath.Join(testGOROOT, copydir)
tg.tempDir(filepath.Join("goroot", copydir))
- err := filepath.Walk(srcdir,
- func(path string, info fs.FileInfo, err error) error {
+ err := filepath.WalkDir(srcdir,
+ func(path string, info fs.DirEntry, err error) error {
if err != nil {
return err
}
@@ -833,13 +832,13 @@ func TestNewReleaseRebuildsStalePackagesInGOPATH(t *testing.T) {
return err
}
dest := filepath.Join("goroot", copydir, srcrel)
- data, err := ioutil.ReadFile(path)
+ data, err := os.ReadFile(path)
if err != nil {
return err
}
tg.tempFile(dest, string(data))
- if err := os.Chmod(tg.path(dest), info.Mode()|0200); err != nil {
- return err
+ if strings.Contains(copydir, filepath.Join("pkg", "tool")) {
+ os.Chmod(tg.path(dest), 0777)
}
return nil
})
@@ -850,18 +849,18 @@ func TestNewReleaseRebuildsStalePackagesInGOPATH(t *testing.T) {
tg.setenv("GOROOT", tg.path("goroot"))
addVar := func(name string, idx int) (restore func()) {
- data, err := ioutil.ReadFile(name)
+ data, err := os.ReadFile(name)
if err != nil {
t.Fatal(err)
}
old := data
data = append(data, fmt.Sprintf("var DummyUnusedVar%d bool\n", idx)...)
- if err := ioutil.WriteFile(name, append(data, '\n'), 0666); err != nil {
+ if err := os.WriteFile(name, append(data, '\n'), 0666); err != nil {
t.Fatal(err)
}
tg.sleep()
return func() {
- if err := ioutil.WriteFile(name, old, 0666); err != nil {
+ if err := os.WriteFile(name, old, 0666); err != nil {
t.Fatal(err)
}
}
@@ -2674,7 +2673,7 @@ echo $* >>`+tg.path("pkg-config.out"))
tg.setenv("GOPATH", tg.path("."))
tg.setenv("PKG_CONFIG", tg.path("pkg-config.sh"))
tg.run("build", "x")
- out, err := ioutil.ReadFile(tg.path("pkg-config.out"))
+ out, err := os.ReadFile(tg.path("pkg-config.out"))
tg.must(err)
out = bytes.TrimSpace(out)
want := "--cflags --static --static -- a a\n--libs --static --static -- a a"
diff --git a/src/cmd/go/go_windows_test.go b/src/cmd/go/go_windows_test.go
index 02634f19f5..3094212bae 100644
--- a/src/cmd/go/go_windows_test.go
+++ b/src/cmd/go/go_windows_test.go
@@ -5,7 +5,6 @@
package main_test
import (
- "io/ioutil"
"os"
"os/exec"
"path/filepath"
@@ -20,14 +19,14 @@ func TestAbsolutePath(t *testing.T) {
defer tg.cleanup()
tg.parallel()
- tmp, err := ioutil.TempDir("", "TestAbsolutePath")
+ tmp, err := os.MkdirTemp("", "TestAbsolutePath")
if err != nil {
t.Fatal(err)
}
defer robustio.RemoveAll(tmp)
file := filepath.Join(tmp, "a.go")
- err = ioutil.WriteFile(file, []byte{}, 0644)
+ err = os.WriteFile(file, []byte{}, 0644)
if err != nil {
t.Fatal(err)
}
diff --git a/src/cmd/go/help_test.go b/src/cmd/go/help_test.go
index 78d63ff05e..abfc3db993 100644
--- a/src/cmd/go/help_test.go
+++ b/src/cmd/go/help_test.go
@@ -6,7 +6,7 @@ package main_test
import (
"bytes"
- "io/ioutil"
+ "os"
"testing"
"cmd/go/internal/help"
@@ -23,7 +23,7 @@ func TestDocsUpToDate(t *testing.T) {
buf := new(bytes.Buffer)
// Match the command in mkalldocs.sh that generates alldocs.go.
help.Help(buf, []string{"documentation"})
- data, err := ioutil.ReadFile("alldocs.go")
+ data, err := os.ReadFile("alldocs.go")
if err != nil {
t.Fatalf("error reading alldocs.go: %v", err)
}
diff --git a/src/cmd/go/internal/auth/netrc.go b/src/cmd/go/internal/auth/netrc.go
index 7a9bdbb72c..0107f20d7a 100644
--- a/src/cmd/go/internal/auth/netrc.go
+++ b/src/cmd/go/internal/auth/netrc.go
@@ -5,7 +5,6 @@
package auth
import (
- "io/ioutil"
"os"
"path/filepath"
"runtime"
@@ -99,7 +98,7 @@ func readNetrc() {
return
}
- data, err := ioutil.ReadFile(path)
+ data, err := os.ReadFile(path)
if err != nil {
if !os.IsNotExist(err) {
netrcErr = err
diff --git a/src/cmd/go/internal/base/signal.go b/src/cmd/go/internal/base/signal.go
index 54d11876d0..05befcf7f0 100644
--- a/src/cmd/go/internal/base/signal.go
+++ b/src/cmd/go/internal/base/signal.go
@@ -15,7 +15,7 @@ var Interrupted = make(chan struct{})
// processSignals setups signal handler.
func processSignals() {
- sig := make(chan os.Signal)
+ sig := make(chan os.Signal, 1)
signal.Notify(sig, signalsToIgnore...)
go func() {
<-sig
diff --git a/src/cmd/go/internal/bug/bug.go b/src/cmd/go/internal/bug/bug.go
index 07e3516855..1085feaaee 100644
--- a/src/cmd/go/internal/bug/bug.go
+++ b/src/cmd/go/internal/bug/bug.go
@@ -10,7 +10,6 @@ import (
"context"
"fmt"
"io"
- "io/ioutil"
urlpkg "net/url"
"os"
"os/exec"
@@ -117,7 +116,7 @@ func printOSDetails(w io.Writer) {
case "illumos", "solaris":
// Be sure to use the OS-supplied uname, in "/usr/bin":
printCmdOut(w, "uname -srv: ", "/usr/bin/uname", "-srv")
- out, err := ioutil.ReadFile("/etc/release")
+ out, err := os.ReadFile("/etc/release")
if err == nil {
fmt.Fprintf(w, "/etc/release: %s\n", out)
} else {
@@ -177,7 +176,7 @@ func printGlibcVersion(w io.Writer) {
src := []byte(`int main() {}`)
srcfile := filepath.Join(tempdir, "go-bug.c")
outfile := filepath.Join(tempdir, "go-bug")
- err := ioutil.WriteFile(srcfile, src, 0644)
+ err := os.WriteFile(srcfile, src, 0644)
if err != nil {
return
}
diff --git a/src/cmd/go/internal/cache/cache.go b/src/cmd/go/internal/cache/cache.go
index 5464fe5685..41f921641d 100644
--- a/src/cmd/go/internal/cache/cache.go
+++ b/src/cmd/go/internal/cache/cache.go
@@ -13,7 +13,6 @@ import (
"fmt"
"io"
"io/fs"
- "io/ioutil"
"os"
"path/filepath"
"strconv"
@@ -239,7 +238,7 @@ func (c *Cache) GetBytes(id ActionID) ([]byte, Entry, error) {
if err != nil {
return nil, entry, err
}
- data, _ := ioutil.ReadFile(c.OutputFile(entry.OutputID))
+ data, _ := os.ReadFile(c.OutputFile(entry.OutputID))
if sha256.Sum256(data) != entry.OutputID {
return nil, entry, &entryNotFoundError{Err: errors.New("bad checksum")}
}
@@ -378,7 +377,7 @@ func (c *Cache) putIndexEntry(id ActionID, out OutputID, size int64, allowVerify
// Truncate the file only *after* writing it.
// (This should be a no-op, but truncate just in case of previous corruption.)
//
- // This differs from ioutil.WriteFile, which truncates to 0 *before* writing
+ // This differs from os.WriteFile, which truncates to 0 *before* writing
// via os.O_TRUNC. Truncating only after writing ensures that a second write
// of the same content to the same file is idempotent, and does not — even
// temporarily! — undo the effect of the first write.
diff --git a/src/cmd/go/internal/cache/cache_test.go b/src/cmd/go/internal/cache/cache_test.go
index 1988c34502..a865b97018 100644
--- a/src/cmd/go/internal/cache/cache_test.go
+++ b/src/cmd/go/internal/cache/cache_test.go
@@ -8,7 +8,6 @@ import (
"bytes"
"encoding/binary"
"fmt"
- "io/ioutil"
"os"
"path/filepath"
"testing"
@@ -20,7 +19,7 @@ func init() {
}
func TestBasic(t *testing.T) {
- dir, err := ioutil.TempDir("", "cachetest-")
+ dir, err := os.MkdirTemp("", "cachetest-")
if err != nil {
t.Fatal(err)
}
@@ -65,7 +64,7 @@ func TestBasic(t *testing.T) {
}
func TestGrowth(t *testing.T) {
- dir, err := ioutil.TempDir("", "cachetest-")
+ dir, err := os.MkdirTemp("", "cachetest-")
if err != nil {
t.Fatal(err)
}
@@ -118,7 +117,7 @@ func TestVerifyPanic(t *testing.T) {
t.Fatal("initEnv did not set verify")
}
- dir, err := ioutil.TempDir("", "cachetest-")
+ dir, err := os.MkdirTemp("", "cachetest-")
if err != nil {
t.Fatal(err)
}
@@ -151,7 +150,7 @@ func dummyID(x int) [HashSize]byte {
}
func TestCacheTrim(t *testing.T) {
- dir, err := ioutil.TempDir("", "cachetest-")
+ dir, err := os.MkdirTemp("", "cachetest-")
if err != nil {
t.Fatal(err)
}
@@ -207,7 +206,7 @@ func TestCacheTrim(t *testing.T) {
t.Fatal(err)
}
c.OutputFile(entry.OutputID)
- data, err := ioutil.ReadFile(filepath.Join(dir, "trim.txt"))
+ data, err := os.ReadFile(filepath.Join(dir, "trim.txt"))
if err != nil {
t.Fatal(err)
}
@@ -220,7 +219,7 @@ func TestCacheTrim(t *testing.T) {
t.Fatal(err)
}
c.OutputFile(entry.OutputID)
- data2, err := ioutil.ReadFile(filepath.Join(dir, "trim.txt"))
+ data2, err := os.ReadFile(filepath.Join(dir, "trim.txt"))
if err != nil {
t.Fatal(err)
}
diff --git a/src/cmd/go/internal/cache/default.go b/src/cmd/go/internal/cache/default.go
index 9f8dd8af4b..0b1c1e0c20 100644
--- a/src/cmd/go/internal/cache/default.go
+++ b/src/cmd/go/internal/cache/default.go
@@ -6,7 +6,6 @@ package cache
import (
"fmt"
- "io/ioutil"
"os"
"path/filepath"
"sync"
@@ -49,7 +48,7 @@ func initDefaultCache() {
}
if _, err := os.Stat(filepath.Join(dir, "README")); err != nil {
// Best effort.
- ioutil.WriteFile(filepath.Join(dir, "README"), []byte(cacheREADME), 0666)
+ os.WriteFile(filepath.Join(dir, "README"), []byte(cacheREADME), 0666)
}
c, err := Open(dir)
diff --git a/src/cmd/go/internal/cache/hash_test.go b/src/cmd/go/internal/cache/hash_test.go
index 3bf7143039..a0356771ca 100644
--- a/src/cmd/go/internal/cache/hash_test.go
+++ b/src/cmd/go/internal/cache/hash_test.go
@@ -6,7 +6,6 @@ package cache
import (
"fmt"
- "io/ioutil"
"os"
"testing"
)
@@ -28,7 +27,7 @@ func TestHash(t *testing.T) {
}
func TestHashFile(t *testing.T) {
- f, err := ioutil.TempFile("", "cmd-go-test-")
+ f, err := os.CreateTemp("", "cmd-go-test-")
if err != nil {
t.Fatal(err)
}
diff --git a/src/cmd/go/internal/cfg/cfg.go b/src/cmd/go/internal/cfg/cfg.go
index 9bc48132ae..c48904eacc 100644
--- a/src/cmd/go/internal/cfg/cfg.go
+++ b/src/cmd/go/internal/cfg/cfg.go
@@ -12,7 +12,6 @@ import (
"go/build"
"internal/cfg"
"io"
- "io/ioutil"
"os"
"path/filepath"
"runtime"
@@ -187,7 +186,7 @@ func initEnvCache() {
if file == "" {
return
}
- data, err := ioutil.ReadFile(file)
+ data, err := os.ReadFile(file)
if err != nil {
return
}
diff --git a/src/cmd/go/internal/clean/clean.go b/src/cmd/go/internal/clean/clean.go
index 87933f04f3..b1d40feb27 100644
--- a/src/cmd/go/internal/clean/clean.go
+++ b/src/cmd/go/internal/clean/clean.go
@@ -9,7 +9,6 @@ import (
"context"
"fmt"
"io"
- "io/ioutil"
"os"
"path/filepath"
"strconv"
@@ -244,7 +243,7 @@ func clean(p *load.Package) {
base.Errorf("%v", p.Error)
return
}
- dirs, err := ioutil.ReadDir(p.Dir)
+ dirs, err := os.ReadDir(p.Dir)
if err != nil {
base.Errorf("go clean %s: %v", p.Dir, err)
return
diff --git a/src/cmd/go/internal/envcmd/env.go b/src/cmd/go/internal/envcmd/env.go
index 46af36eb11..6937187522 100644
--- a/src/cmd/go/internal/envcmd/env.go
+++ b/src/cmd/go/internal/envcmd/env.go
@@ -10,7 +10,6 @@ import (
"encoding/json"
"fmt"
"go/build"
- "io/ioutil"
"os"
"path/filepath"
"runtime"
@@ -452,7 +451,7 @@ func updateEnvFile(add map[string]string, del map[string]bool) {
if file == "" {
base.Fatalf("go env: cannot find go env config: %v", err)
}
- data, err := ioutil.ReadFile(file)
+ data, err := os.ReadFile(file)
if err != nil && (!os.IsNotExist(err) || len(add) == 0) {
base.Fatalf("go env: reading go env config: %v", err)
}
@@ -506,11 +505,11 @@ func updateEnvFile(add map[string]string, del map[string]bool) {
}
data = []byte(strings.Join(lines, ""))
- err = ioutil.WriteFile(file, data, 0666)
+ err = os.WriteFile(file, data, 0666)
if err != nil {
// Try creating directory.
os.MkdirAll(filepath.Dir(file), 0777)
- err = ioutil.WriteFile(file, data, 0666)
+ err = os.WriteFile(file, data, 0666)
if err != nil {
base.Fatalf("go env: writing go env config: %v", err)
}
diff --git a/src/cmd/go/internal/fsys/fsys.go b/src/cmd/go/internal/fsys/fsys.go
index 0264786e5b..7b06c3c7f3 100644
--- a/src/cmd/go/internal/fsys/fsys.go
+++ b/src/cmd/go/internal/fsys/fsys.go
@@ -86,7 +86,7 @@ func Init(wd string) error {
return nil
}
- b, err := ioutil.ReadFile(OverlayFile)
+ b, err := os.ReadFile(OverlayFile)
if err != nil {
return fmt.Errorf("reading overlay file: %v", err)
}
diff --git a/src/cmd/go/internal/fsys/fsys_test.go b/src/cmd/go/internal/fsys/fsys_test.go
index 90a69de14a..7f175c7031 100644
--- a/src/cmd/go/internal/fsys/fsys_test.go
+++ b/src/cmd/go/internal/fsys/fsys_test.go
@@ -8,7 +8,6 @@ import (
"internal/testenv"
"io"
"io/fs"
- "io/ioutil"
"os"
"path/filepath"
"reflect"
@@ -47,7 +46,7 @@ func initOverlay(t *testing.T, config string) {
if err := os.MkdirAll(filepath.Dir(name), 0777); err != nil {
t.Fatal(err)
}
- if err := ioutil.WriteFile(name, f.Data, 0666); err != nil {
+ if err := os.WriteFile(name, f.Data, 0666); err != nil {
t.Fatal(err)
}
}
diff --git a/src/cmd/go/internal/generate/generate.go b/src/cmd/go/internal/generate/generate.go
index 98c17bba8c..c7401948b8 100644
--- a/src/cmd/go/internal/generate/generate.go
+++ b/src/cmd/go/internal/generate/generate.go
@@ -13,7 +13,6 @@ import (
"go/parser"
"go/token"
"io"
- "io/ioutil"
"log"
"os"
"os/exec"
@@ -201,7 +200,7 @@ func runGenerate(ctx context.Context, cmd *base.Command, args []string) {
// generate runs the generation directives for a single file.
func generate(absFile string) bool {
- src, err := ioutil.ReadFile(absFile)
+ src, err := os.ReadFile(absFile)
if err != nil {
log.Fatalf("generate: %s", err)
}
diff --git a/src/cmd/go/internal/imports/scan_test.go b/src/cmd/go/internal/imports/scan_test.go
index e424656cae..2d245ee787 100644
--- a/src/cmd/go/internal/imports/scan_test.go
+++ b/src/cmd/go/internal/imports/scan_test.go
@@ -7,7 +7,7 @@ package imports
import (
"bytes"
"internal/testenv"
- "io/ioutil"
+ "os"
"path"
"path/filepath"
"runtime"
@@ -57,7 +57,7 @@ func TestScan(t *testing.T) {
func TestScanDir(t *testing.T) {
testenv.MustHaveGoBuild(t)
- dirs, err := ioutil.ReadDir("testdata")
+ dirs, err := os.ReadDir("testdata")
if err != nil {
t.Fatal(err)
}
@@ -66,7 +66,7 @@ func TestScanDir(t *testing.T) {
continue
}
t.Run(dir.Name(), func(t *testing.T) {
- tagsData, err := ioutil.ReadFile(filepath.Join("testdata", dir.Name(), "tags.txt"))
+ tagsData, err := os.ReadFile(filepath.Join("testdata", dir.Name(), "tags.txt"))
if err != nil {
t.Fatalf("error reading tags: %v", err)
}
@@ -75,7 +75,7 @@ func TestScanDir(t *testing.T) {
tags[t] = true
}
- wantData, err := ioutil.ReadFile(filepath.Join("testdata", dir.Name(), "want.txt"))
+ wantData, err := os.ReadFile(filepath.Join("testdata", dir.Name(), "want.txt"))
if err != nil {
t.Fatalf("error reading want: %v", err)
}
diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go
index 30ca33b663..6f95af4f7e 100644
--- a/src/cmd/go/internal/load/pkg.go
+++ b/src/cmd/go/internal/load/pkg.go
@@ -15,7 +15,6 @@ import (
"go/scanner"
"go/token"
"io/fs"
- "io/ioutil"
"os"
"path"
pathpkg "path"
@@ -1147,7 +1146,7 @@ var (
// goModPath returns the module path in the go.mod in dir, if any.
func goModPath(dir string) (path string) {
return goModPathCache.Do(dir, func() interface{} {
- data, err := ioutil.ReadFile(filepath.Join(dir, "go.mod"))
+ data, err := os.ReadFile(filepath.Join(dir, "go.mod"))
if err != nil {
return ""
}
@@ -1296,9 +1295,9 @@ HaveGoMod:
// Otherwise it is not possible to vendor just a/b/c and still import the
// non-vendored a/b. See golang.org/issue/13832.
func hasGoFiles(dir string) bool {
- fis, _ := ioutil.ReadDir(dir)
- for _, fi := range fis {
- if !fi.IsDir() && strings.HasSuffix(fi.Name(), ".go") {
+ files, _ := os.ReadDir(dir)
+ for _, f := range files {
+ if !f.IsDir() && strings.HasSuffix(f.Name(), ".go") {
return true
}
}
@@ -1728,7 +1727,7 @@ func (p *Package) load(ctx context.Context, path string, stk *ImportStack, impor
// not work for any package that lacks a Target — such as a non-main
// package in module mode. We should probably fix that.
shlibnamefile := p.Target[:len(p.Target)-2] + ".shlibname"
- shlib, err := ioutil.ReadFile(shlibnamefile)
+ shlib, err := os.ReadFile(shlibnamefile)
if err != nil && !os.IsNotExist(err) {
base.Fatalf("reading shlibname: %v", err)
}
@@ -1998,6 +1997,16 @@ func (p *Package) resolveEmbed(patterns []string) (files []string, pmap map[stri
return err
}
rel := filepath.ToSlash(path[len(p.Dir)+1:])
+ name := info.Name()
+ if path != file && (isBadEmbedName(name) || name[0] == '.' || name[0] == '_') {
+ // Ignore bad names, assuming they won't go into modules.
+ // Also avoid hidden files that user may not know about.
+ // See golang.org/issue/42328.
+ if info.IsDir() {
+ return fs.SkipDir
+ }
+ return nil
+ }
if info.IsDir() {
if _, err := fsys.Stat(filepath.Join(path, "go.mod")); err == nil {
return filepath.SkipDir
@@ -2007,10 +2016,6 @@ func (p *Package) resolveEmbed(patterns []string) (files []string, pmap map[stri
if !info.Mode().IsRegular() {
return nil
}
- if isBadEmbedName(info.Name()) {
- // Ignore bad names, assuming they won't go into modules.
- return nil
- }
count++
if have[rel] != pid {
have[rel] = pid
@@ -2050,6 +2055,9 @@ func validEmbedPattern(pattern string) bool {
// as existing for embedding.
func isBadEmbedName(name string) bool {
switch name {
+ // Empty string should be impossible but make it bad.
+ case "":
+ return true
// Version control directories won't be present in module.
case ".bzr", ".hg", ".git", ".svn":
return true
diff --git a/src/cmd/go/internal/lockedfile/internal/filelock/filelock_test.go b/src/cmd/go/internal/lockedfile/internal/filelock/filelock_test.go
index 8301fb6b6e..2ac2052b8f 100644
--- a/src/cmd/go/internal/lockedfile/internal/filelock/filelock_test.go
+++ b/src/cmd/go/internal/lockedfile/internal/filelock/filelock_test.go
@@ -9,7 +9,6 @@ package filelock_test
import (
"fmt"
"internal/testenv"
- "io/ioutil"
"os"
"os/exec"
"path/filepath"
@@ -51,9 +50,9 @@ func mustTempFile(t *testing.T) (f *os.File, remove func()) {
t.Helper()
base := filepath.Base(t.Name())
- f, err := ioutil.TempFile("", base)
+ f, err := os.CreateTemp("", base)
if err != nil {
- t.Fatalf(`ioutil.TempFile("", %q) = %v`, base, err)
+ t.Fatalf(`os.CreateTemp("", %q) = %v`, base, err)
}
t.Logf("fd %d = %s", f.Fd(), f.Name())
diff --git a/src/cmd/go/internal/lockedfile/lockedfile_test.go b/src/cmd/go/internal/lockedfile/lockedfile_test.go
index 416c69d83b..34327dd841 100644
--- a/src/cmd/go/internal/lockedfile/lockedfile_test.go
+++ b/src/cmd/go/internal/lockedfile/lockedfile_test.go
@@ -10,7 +10,6 @@ package lockedfile_test
import (
"fmt"
"internal/testenv"
- "io/ioutil"
"os"
"os/exec"
"path/filepath"
@@ -23,7 +22,7 @@ import (
func mustTempDir(t *testing.T) (dir string, remove func()) {
t.Helper()
- dir, err := ioutil.TempDir("", filepath.Base(t.Name()))
+ dir, err := os.MkdirTemp("", filepath.Base(t.Name()))
if err != nil {
t.Fatal(err)
}
@@ -155,8 +154,8 @@ func TestCanLockExistingFile(t *testing.T) {
defer remove()
path := filepath.Join(dir, "existing.txt")
- if err := ioutil.WriteFile(path, []byte("ok"), 0777); err != nil {
- t.Fatalf("ioutil.WriteFile: %v", err)
+ if err := os.WriteFile(path, []byte("ok"), 0777); err != nil {
+ t.Fatalf("os.WriteFile: %v", err)
}
f, err := lockedfile.Edit(path)
@@ -201,7 +200,7 @@ func TestSpuriousEDEADLK(t *testing.T) {
}
defer b.Close()
- if err := ioutil.WriteFile(filepath.Join(dir, "locked"), []byte("ok"), 0666); err != nil {
+ if err := os.WriteFile(filepath.Join(dir, "locked"), []byte("ok"), 0666); err != nil {
t.Fatal(err)
}
diff --git a/src/cmd/go/internal/modcmd/vendor.go b/src/cmd/go/internal/modcmd/vendor.go
index 38c473d36b..1bbb57d353 100644
--- a/src/cmd/go/internal/modcmd/vendor.go
+++ b/src/cmd/go/internal/modcmd/vendor.go
@@ -10,7 +10,6 @@ import (
"fmt"
"io"
"io/fs"
- "io/ioutil"
"os"
"path/filepath"
"sort"
@@ -155,7 +154,7 @@ func runVendor(ctx context.Context, cmd *base.Command, args []string) {
base.Fatalf("go mod vendor: %v", err)
}
- if err := ioutil.WriteFile(filepath.Join(vdir, "modules.txt"), buf.Bytes(), 0666); err != nil {
+ if err := os.WriteFile(filepath.Join(vdir, "modules.txt"), buf.Bytes(), 0666); err != nil {
base.Fatalf("go mod vendor: %v", err)
}
}
@@ -244,7 +243,7 @@ var metaPrefixes = []string{
}
// matchMetadata reports whether info is a metadata file.
-func matchMetadata(dir string, info fs.FileInfo) bool {
+func matchMetadata(dir string, info fs.DirEntry) bool {
name := info.Name()
for _, p := range metaPrefixes {
if strings.HasPrefix(name, p) {
@@ -255,7 +254,7 @@ func matchMetadata(dir string, info fs.FileInfo) bool {
}
// matchPotentialSourceFile reports whether info may be relevant to a build operation.
-func matchPotentialSourceFile(dir string, info fs.FileInfo) bool {
+func matchPotentialSourceFile(dir string, info fs.DirEntry) bool {
if strings.HasSuffix(info.Name(), "_test.go") {
return false
}
@@ -281,8 +280,8 @@ func matchPotentialSourceFile(dir string, info fs.FileInfo) bool {
}
// copyDir copies all regular files satisfying match(info) from src to dst.
-func copyDir(dst, src string, match func(dir string, info fs.FileInfo) bool) {
- files, err := ioutil.ReadDir(src)
+func copyDir(dst, src string, match func(dir string, info fs.DirEntry) bool) {
+ files, err := os.ReadDir(src)
if err != nil {
base.Fatalf("go mod vendor: %v", err)
}
@@ -290,7 +289,7 @@ func copyDir(dst, src string, match func(dir string, info fs.FileInfo) bool) {
base.Fatalf("go mod vendor: %v", err)
}
for _, file := range files {
- if file.IsDir() || !file.Mode().IsRegular() || !match(src, file) {
+ if file.IsDir() || !file.Type().IsRegular() || !match(src, file) {
continue
}
r, err := os.Open(filepath.Join(src, file.Name()))
diff --git a/src/cmd/go/internal/modcmd/verify.go b/src/cmd/go/internal/modcmd/verify.go
index ce24793929..c83e70076a 100644
--- a/src/cmd/go/internal/modcmd/verify.go
+++ b/src/cmd/go/internal/modcmd/verify.go
@@ -10,7 +10,6 @@ import (
"errors"
"fmt"
"io/fs"
- "io/ioutil"
"os"
"runtime"
@@ -87,7 +86,7 @@ func verifyMod(mod module.Version) []error {
_, zipErr = os.Stat(zip)
}
dir, dirErr := modfetch.DownloadDir(mod)
- data, err := ioutil.ReadFile(zip + "hash")
+ data, err := os.ReadFile(zip + "hash")
if err != nil {
if zipErr != nil && errors.Is(zipErr, fs.ErrNotExist) &&
dirErr != nil && errors.Is(dirErr, fs.ErrNotExist) {
diff --git a/src/cmd/go/internal/modconv/convert_test.go b/src/cmd/go/internal/modconv/convert_test.go
index faa2b4c606..66b9ff4f38 100644
--- a/src/cmd/go/internal/modconv/convert_test.go
+++ b/src/cmd/go/internal/modconv/convert_test.go
@@ -9,7 +9,6 @@ import (
"context"
"fmt"
"internal/testenv"
- "io/ioutil"
"log"
"os"
"os/exec"
@@ -37,7 +36,7 @@ func testMain(m *testing.M) int {
return 0
}
- dir, err := ioutil.TempDir("", "modconv-test-")
+ dir, err := os.MkdirTemp("", "modconv-test-")
if err != nil {
log.Fatal(err)
}
@@ -167,7 +166,7 @@ func TestConvertLegacyConfig(t *testing.T) {
for name := range Converters {
file := filepath.Join(dir, name)
- data, err := ioutil.ReadFile(file)
+ data, err := os.ReadFile(file)
if err == nil {
f := new(modfile.File)
f.AddModuleStmt(tt.path)
diff --git a/src/cmd/go/internal/modconv/modconv_test.go b/src/cmd/go/internal/modconv/modconv_test.go
index ccc4f3d576..750525d404 100644
--- a/src/cmd/go/internal/modconv/modconv_test.go
+++ b/src/cmd/go/internal/modconv/modconv_test.go
@@ -7,7 +7,7 @@ package modconv
import (
"bytes"
"fmt"
- "io/ioutil"
+ "os"
"path/filepath"
"testing"
)
@@ -42,7 +42,7 @@ func Test(t *testing.T) {
if Converters[extMap[ext]] == nil {
t.Fatalf("Converters[%q] == nil", extMap[ext])
}
- data, err := ioutil.ReadFile(test)
+ data, err := os.ReadFile(test)
if err != nil {
t.Fatal(err)
}
@@ -50,7 +50,7 @@ func Test(t *testing.T) {
if err != nil {
t.Fatal(err)
}
- want, err := ioutil.ReadFile(test[:len(test)-len(ext)] + ".out")
+ want, err := os.ReadFile(test[:len(test)-len(ext)] + ".out")
if err != nil {
t.Error(err)
}
diff --git a/src/cmd/go/internal/modfetch/cache.go b/src/cmd/go/internal/modfetch/cache.go
index 7572ff24f8..3a2ff63721 100644
--- a/src/cmd/go/internal/modfetch/cache.go
+++ b/src/cmd/go/internal/modfetch/cache.go
@@ -11,7 +11,6 @@ import (
"fmt"
"io"
"io/fs"
- "io/ioutil"
"os"
"path/filepath"
"strings"
@@ -598,7 +597,7 @@ func rewriteVersionList(dir string) {
}
defer unlock()
- infos, err := ioutil.ReadDir(dir)
+ infos, err := os.ReadDir(dir)
if err != nil {
return
}
diff --git a/src/cmd/go/internal/modfetch/cache_test.go b/src/cmd/go/internal/modfetch/cache_test.go
index 241c800e69..722c984e37 100644
--- a/src/cmd/go/internal/modfetch/cache_test.go
+++ b/src/cmd/go/internal/modfetch/cache_test.go
@@ -5,14 +5,13 @@
package modfetch
import (
- "io/ioutil"
"os"
"path/filepath"
"testing"
)
func TestWriteDiskCache(t *testing.T) {
- tmpdir, err := ioutil.TempDir("", "go-writeCache-test-")
+ tmpdir, err := os.MkdirTemp("", "go-writeCache-test-")
if err != nil {
t.Fatal(err)
}
diff --git a/src/cmd/go/internal/modfetch/codehost/codehost.go b/src/cmd/go/internal/modfetch/codehost/codehost.go
index c5fbb31b2b..86c1c14d4a 100644
--- a/src/cmd/go/internal/modfetch/codehost/codehost.go
+++ b/src/cmd/go/internal/modfetch/codehost/codehost.go
@@ -12,7 +12,6 @@ import (
"fmt"
"io"
"io/fs"
- "io/ioutil"
"os"
"os/exec"
"path/filepath"
@@ -189,7 +188,7 @@ func WorkDir(typ, name string) (dir, lockfile string, err error) {
}
defer unlock()
- data, err := ioutil.ReadFile(dir + ".info")
+ data, err := os.ReadFile(dir + ".info")
info, err2 := os.Stat(dir)
if err == nil && err2 == nil && info.IsDir() {
// Info file and directory both already exist: reuse.
@@ -211,7 +210,7 @@ func WorkDir(typ, name string) (dir, lockfile string, err error) {
if err := os.MkdirAll(dir, 0777); err != nil {
return "", "", err
}
- if err := ioutil.WriteFile(dir+".info", []byte(key), 0666); err != nil {
+ if err := os.WriteFile(dir+".info", []byte(key), 0666); err != nil {
os.RemoveAll(dir)
return "", "", err
}
@@ -264,6 +263,9 @@ func RunWithStdin(dir string, stdin io.Reader, cmdline ...interface{}) ([]byte,
}
cmd := str.StringList(cmdline...)
+ if os.Getenv("TESTGOVCS") == "panic" {
+ panic(fmt.Sprintf("use of vcs: %v", cmd))
+ }
if cfg.BuildX {
text := new(strings.Builder)
if dir != "" {
diff --git a/src/cmd/go/internal/modfetch/codehost/git_test.go b/src/cmd/go/internal/modfetch/codehost/git_test.go
index 981e3fe91f..89a73baad9 100644
--- a/src/cmd/go/internal/modfetch/codehost/git_test.go
+++ b/src/cmd/go/internal/modfetch/codehost/git_test.go
@@ -12,7 +12,6 @@ import (
"internal/testenv"
"io"
"io/fs"
- "io/ioutil"
"log"
"os"
"os/exec"
@@ -54,7 +53,7 @@ func testMain(m *testing.M) int {
return 0
}
- dir, err := ioutil.TempDir("", "gitrepo-test-")
+ dir, err := os.MkdirTemp("", "gitrepo-test-")
if err != nil {
log.Fatal(err)
}
diff --git a/src/cmd/go/internal/modfetch/codehost/shell.go b/src/cmd/go/internal/modfetch/codehost/shell.go
index b9525adf5e..ce8b501d53 100644
--- a/src/cmd/go/internal/modfetch/codehost/shell.go
+++ b/src/cmd/go/internal/modfetch/codehost/shell.go
@@ -15,7 +15,6 @@ import (
"flag"
"fmt"
"io"
- "io/ioutil"
"log"
"os"
"strings"
@@ -124,7 +123,7 @@ func main() {
}
if f[3] != "-" {
- if err := ioutil.WriteFile(f[3], data, 0666); err != nil {
+ if err := os.WriteFile(f[3], data, 0666); err != nil {
fmt.Fprintf(os.Stderr, "?%s\n", err)
continue
}
diff --git a/src/cmd/go/internal/modfetch/codehost/vcs.go b/src/cmd/go/internal/modfetch/codehost/vcs.go
index e67ee94ad8..c2cca084e3 100644
--- a/src/cmd/go/internal/modfetch/codehost/vcs.go
+++ b/src/cmd/go/internal/modfetch/codehost/vcs.go
@@ -10,7 +10,6 @@ import (
"internal/lazyregexp"
"io"
"io/fs"
- "io/ioutil"
"os"
"path/filepath"
"sort"
@@ -433,7 +432,7 @@ func (r *vcsRepo) ReadZip(rev, subdir string, maxSize int64) (zip io.ReadCloser,
if rev == "latest" {
rev = r.cmd.latest
}
- f, err := ioutil.TempFile("", "go-readzip-*.zip")
+ f, err := os.CreateTemp("", "go-readzip-*.zip")
if err != nil {
return nil, err
}
diff --git a/src/cmd/go/internal/modfetch/coderepo.go b/src/cmd/go/internal/modfetch/coderepo.go
index b6bcf83f1a..2dcbb99b18 100644
--- a/src/cmd/go/internal/modfetch/coderepo.go
+++ b/src/cmd/go/internal/modfetch/coderepo.go
@@ -11,7 +11,6 @@ import (
"fmt"
"io"
"io/fs"
- "io/ioutil"
"os"
"path"
"sort"
@@ -966,7 +965,7 @@ func (r *codeRepo) Zip(dst io.Writer, version string) error {
subdir = strings.Trim(subdir, "/")
// Spool to local file.
- f, err := ioutil.TempFile("", "go-codehost-")
+ f, err := os.CreateTemp("", "go-codehost-")
if err != nil {
dl.Close()
return err
diff --git a/src/cmd/go/internal/modfetch/coderepo_test.go b/src/cmd/go/internal/modfetch/coderepo_test.go
index 53b048dbdf..02e399f352 100644
--- a/src/cmd/go/internal/modfetch/coderepo_test.go
+++ b/src/cmd/go/internal/modfetch/coderepo_test.go
@@ -11,7 +11,6 @@ import (
"hash"
"internal/testenv"
"io"
- "io/ioutil"
"log"
"os"
"reflect"
@@ -38,7 +37,7 @@ func testMain(m *testing.M) int {
// code, bypass the sum database.
cfg.GOSUMDB = "off"
- dir, err := ioutil.TempDir("", "gitrepo-test-")
+ dir, err := os.MkdirTemp("", "gitrepo-test-")
if err != nil {
log.Fatal(err)
}
@@ -424,7 +423,7 @@ var codeRepoTests = []codeRepoTest{
func TestCodeRepo(t *testing.T) {
testenv.MustHaveExternalNetwork(t)
- tmpdir, err := ioutil.TempDir("", "modfetch-test-")
+ tmpdir, err := os.MkdirTemp("", "modfetch-test-")
if err != nil {
t.Fatal(err)
}
@@ -491,9 +490,9 @@ func TestCodeRepo(t *testing.T) {
needHash := !testing.Short() && (tt.zipFileHash != "" || tt.zipSum != "")
if tt.zip != nil || tt.zipErr != "" || needHash {
- f, err := ioutil.TempFile(tmpdir, tt.version+".zip.")
+ f, err := os.CreateTemp(tmpdir, tt.version+".zip.")
if err != nil {
- t.Fatalf("ioutil.TempFile: %v", err)
+ t.Fatalf("os.CreateTemp: %v", err)
}
zipfile := f.Name()
defer func() {
@@ -655,7 +654,7 @@ var codeRepoVersionsTests = []struct {
func TestCodeRepoVersions(t *testing.T) {
testenv.MustHaveExternalNetwork(t)
- tmpdir, err := ioutil.TempDir("", "vgo-modfetch-test-")
+ tmpdir, err := os.MkdirTemp("", "vgo-modfetch-test-")
if err != nil {
t.Fatal(err)
}
@@ -729,7 +728,7 @@ var latestTests = []struct {
func TestLatest(t *testing.T) {
testenv.MustHaveExternalNetwork(t)
- tmpdir, err := ioutil.TempDir("", "vgo-modfetch-test-")
+ tmpdir, err := os.MkdirTemp("", "vgo-modfetch-test-")
if err != nil {
t.Fatal(err)
}
diff --git a/src/cmd/go/internal/modfetch/fetch.go b/src/cmd/go/internal/modfetch/fetch.go
index a3e2cd1f9d..debeb3f319 100644
--- a/src/cmd/go/internal/modfetch/fetch.go
+++ b/src/cmd/go/internal/modfetch/fetch.go
@@ -12,7 +12,6 @@ import (
"fmt"
"io"
"io/fs"
- "io/ioutil"
"os"
"path/filepath"
"sort"
@@ -136,7 +135,7 @@ func download(ctx context.Context, mod module.Version) (dir string, err error) {
if err := os.MkdirAll(parentDir, 0777); err != nil {
return "", err
}
- if err := ioutil.WriteFile(partialPath, nil, 0666); err != nil {
+ if err := os.WriteFile(partialPath, nil, 0666); err != nil {
return "", err
}
if err := modzip.Unzip(dir, mod, zipfile); err != nil {
@@ -223,7 +222,7 @@ func downloadZip(ctx context.Context, mod module.Version, zipfile string) (err e
// contents of the file (by hashing it) before we commit it. Because the file
// is zip-compressed, we need an actual file — or at least an io.ReaderAt — to
// validate it: we can't just tee the stream as we write it.
- f, err := ioutil.TempFile(filepath.Dir(zipfile), filepath.Base(renameio.Pattern(zipfile)))
+ f, err := os.CreateTemp(filepath.Dir(zipfile), filepath.Base(renameio.Pattern(zipfile)))
if err != nil {
return err
}
@@ -318,9 +317,10 @@ func makeDirsReadOnly(dir string) {
mode fs.FileMode
}
var dirs []pathMode // in lexical order
- filepath.Walk(dir, func(path string, info fs.FileInfo, err error) error {
- if err == nil && info.Mode()&0222 != 0 {
- if info.IsDir() {
+ filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error {
+ if err == nil && d.IsDir() {
+ info, err := d.Info()
+ if err == nil && info.Mode()&0222 != 0 {
dirs = append(dirs, pathMode{path, info.Mode()})
}
}
@@ -337,7 +337,7 @@ func makeDirsReadOnly(dir string) {
// any permission changes needed to do so.
func RemoveAll(dir string) error {
// Module cache has 0555 directories; make them writable in order to remove content.
- filepath.Walk(dir, func(path string, info fs.FileInfo, err error) error {
+ filepath.WalkDir(dir, func(path string, info fs.DirEntry, err error) error {
if err != nil {
return nil // ignore errors walking in file system
}
diff --git a/src/cmd/go/internal/modfetch/zip_sum_test/zip_sum_test.go b/src/cmd/go/internal/modfetch/zip_sum_test/zip_sum_test.go
index 82398ebfed..d9ba8ef2da 100644
--- a/src/cmd/go/internal/modfetch/zip_sum_test/zip_sum_test.go
+++ b/src/cmd/go/internal/modfetch/zip_sum_test/zip_sum_test.go
@@ -24,7 +24,6 @@ import (
"fmt"
"internal/testenv"
"io"
- "io/ioutil"
"os"
"path/filepath"
"strings"
@@ -81,7 +80,7 @@ func TestZipSums(t *testing.T) {
if *modCacheDir != "" {
cfg.BuildContext.GOPATH = *modCacheDir
} else {
- tmpDir, err := ioutil.TempDir("", "TestZipSums")
+ tmpDir, err := os.MkdirTemp("", "TestZipSums")
if err != nil {
t.Fatal(err)
}
diff --git a/src/cmd/go/internal/modget/get.go b/src/cmd/go/internal/modget/get.go
index ecb0142524..e5f55879ee 100644
--- a/src/cmd/go/internal/modget/get.go
+++ b/src/cmd/go/internal/modget/get.go
@@ -436,32 +436,9 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) {
work.BuildInit()
pkgs := load.PackagesForBuild(ctx, pkgPatterns)
work.InstallPackages(ctx, pkgPatterns, pkgs)
-
- haveExe := false
- for _, pkg := range pkgs {
- if pkg.Name == "main" {
- haveExe = true
- break
- }
- }
- if haveExe {
- fmt.Fprint(os.Stderr, "go get: installing executables with 'go get' in module mode is deprecated.")
- var altMsg string
- if modload.HasModRoot() {
- altMsg = `
- To adjust dependencies of the current module, use 'go get -d'.
- To install using requirements of the current module, use 'go install'.
- To install ignoring the current module, use 'go install' with a version,
- like 'go install example.com/cmd@latest'.
-`
- } else {
- altMsg = "\n\tUse 'go install pkg@version' instead.\n"
- }
- fmt.Fprint(os.Stderr, altMsg)
- fmt.Fprint(os.Stderr, "\tSee 'go help get' and 'go help install' for more information.\n")
- }
- // TODO(golang.org/issue/40276): link to HTML documentation explaining
- // what's changing and gives more examples.
+ // TODO(#40276): After Go 1.16, print a deprecation notice when building
+ // and installing main packages. 'go install pkg' or
+ // 'go install pkg@version' should be used instead.
}
if !modload.HasModRoot() {
diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go
index a9b77c82b3..3f70d04145 100644
--- a/src/cmd/go/internal/modload/init.go
+++ b/src/cmd/go/internal/modload/init.go
@@ -12,7 +12,6 @@ import (
"fmt"
"go/build"
"internal/lazyregexp"
- "io/ioutil"
"os"
"path"
"path/filepath"
@@ -445,13 +444,13 @@ func CreateModFile(ctx context.Context, modPath string) {
// this is an existing project. Walking the tree for packages would be more
// accurate, but could take much longer.
empty := true
- fis, _ := ioutil.ReadDir(modRoot)
- for _, fi := range fis {
- name := fi.Name()
+ files, _ := os.ReadDir(modRoot)
+ for _, f := range files {
+ name := f.Name()
if strings.HasPrefix(name, ".") || strings.HasPrefix(name, "_") {
continue
}
- if strings.HasSuffix(name, ".go") || fi.IsDir() {
+ if strings.HasSuffix(name, ".go") || f.IsDir() {
empty = false
break
}
@@ -632,7 +631,7 @@ func setDefaultBuildMod() {
func convertLegacyConfig(modPath string) (from string, err error) {
for _, name := range altConfigs {
cfg := filepath.Join(modRoot, name)
- data, err := ioutil.ReadFile(cfg)
+ data, err := os.ReadFile(cfg)
if err == nil {
convert := modconv.Converters[name]
if convert == nil {
@@ -731,9 +730,9 @@ func findModulePath(dir string) (string, error) {
// Cast about for import comments,
// first in top-level directory, then in subdirectories.
- list, _ := ioutil.ReadDir(dir)
+ list, _ := os.ReadDir(dir)
for _, info := range list {
- if info.Mode().IsRegular() && strings.HasSuffix(info.Name(), ".go") {
+ if info.Type().IsRegular() && strings.HasSuffix(info.Name(), ".go") {
if com := findImportComment(filepath.Join(dir, info.Name())); com != "" {
return com, nil
}
@@ -741,9 +740,9 @@ func findModulePath(dir string) (string, error) {
}
for _, info1 := range list {
if info1.IsDir() {
- files, _ := ioutil.ReadDir(filepath.Join(dir, info1.Name()))
+ files, _ := os.ReadDir(filepath.Join(dir, info1.Name()))
for _, info2 := range files {
- if info2.Mode().IsRegular() && strings.HasSuffix(info2.Name(), ".go") {
+ if info2.Type().IsRegular() && strings.HasSuffix(info2.Name(), ".go") {
if com := findImportComment(filepath.Join(dir, info1.Name(), info2.Name())); com != "" {
return path.Dir(com), nil
}
@@ -753,7 +752,7 @@ func findModulePath(dir string) (string, error) {
}
// Look for Godeps.json declaring import path.
- data, _ := ioutil.ReadFile(filepath.Join(dir, "Godeps/Godeps.json"))
+ data, _ := os.ReadFile(filepath.Join(dir, "Godeps/Godeps.json"))
var cfg1 struct{ ImportPath string }
json.Unmarshal(data, &cfg1)
if cfg1.ImportPath != "" {
@@ -761,7 +760,7 @@ func findModulePath(dir string) (string, error) {
}
// Look for vendor.json declaring import path.
- data, _ = ioutil.ReadFile(filepath.Join(dir, "vendor/vendor.json"))
+ data, _ = os.ReadFile(filepath.Join(dir, "vendor/vendor.json"))
var cfg2 struct{ RootPath string }
json.Unmarshal(data, &cfg2)
if cfg2.RootPath != "" {
@@ -813,7 +812,7 @@ var (
)
func findImportComment(file string) string {
- data, err := ioutil.ReadFile(file)
+ data, err := os.ReadFile(file)
if err != nil {
return ""
}
@@ -1018,7 +1017,7 @@ func keepSums(addDirect bool) map[module.Version]bool {
}
}
for _, pkg := range loaded.pkgs {
- if pkg.testOf != nil || pkg.inStd {
+ if pkg.testOf != nil || pkg.inStd || module.CheckImportPath(pkg.path) != nil {
continue
}
for prefix := pkg.path; prefix != "."; prefix = path.Dir(prefix) {
diff --git a/src/cmd/go/internal/modload/load.go b/src/cmd/go/internal/modload/load.go
index 732c4af92b..a0f93d028a 100644
--- a/src/cmd/go/internal/modload/load.go
+++ b/src/cmd/go/internal/modload/load.go
@@ -61,8 +61,8 @@ package modload
// Similarly, if the LoadTests flag is set but the "all" pattern does not close
// over test dependencies, then when we load the test of a package that is in
// "all" but outside the main module, the dependencies of that test will not
-// necessarily themselves be in "all". That configuration does not arise in Go
-// 1.11–1.15, but it will be possible with lazy loading in Go 1.16+.
+// necessarily themselves be in "all". (That configuration does not arise in Go
+// 1.11–1.15, but it will be possible in Go 1.16+.)
//
// Loading proceeds from the roots, using a parallel work-queue with a limit on
// the amount of active work (to avoid saturating disks, CPU cores, and/or
@@ -158,8 +158,8 @@ type PackageOpts struct {
// UseVendorAll causes the "all" package pattern to be interpreted as if
// running "go mod vendor" (or building with "-mod=vendor").
//
- // Once lazy loading is implemented, this will be a no-op for modules that
- // declare 'go 1.16' or higher.
+ // This is a no-op for modules that declare 'go 1.16' or higher, for which this
+ // is the default (and only) interpretation of the "all" pattern in module mode.
UseVendorAll bool
// AllowErrors indicates that LoadPackages should not terminate the process if
diff --git a/src/cmd/go/internal/modload/modfile.go b/src/cmd/go/internal/modload/modfile.go
index ede07be4bf..eb05e9f9c9 100644
--- a/src/cmd/go/internal/modload/modfile.go
+++ b/src/cmd/go/internal/modload/modfile.go
@@ -25,10 +25,11 @@ import (
"golang.org/x/mod/semver"
)
-// lazyLoadingVersion is the Go version (plus leading "v") at which lazy module
-// loading takes effect.
-const lazyLoadingVersionV = "v1.16"
-const go116EnableLazyLoading = true
+// narrowAllVersionV is the Go version (plus leading "v") at which the
+// module-module "all" pattern no longer closes over the dependencies of
+// tests outside of the main module.
+const narrowAllVersionV = "v1.16"
+const go116EnableNarrowAll = true
var modFile *modfile.File
@@ -296,10 +297,10 @@ func indexModFile(data []byte, modFile *modfile.File, needsFix bool) *modFileInd
// (Otherwise — as in Go 1.16+ — the "all" pattern includes only the packages
// transitively *imported by* the packages and tests in the main module.)
func (i *modFileIndex) allPatternClosesOverTests() bool {
- if !go116EnableLazyLoading {
+ if !go116EnableNarrowAll {
return true
}
- if i != nil && semver.Compare(i.goVersionV, lazyLoadingVersionV) < 0 {
+ if i != nil && semver.Compare(i.goVersionV, narrowAllVersionV) < 0 {
// The module explicitly predates the change in "all" for lazy loading, so
// continue to use the older interpretation. (If i == nil, we not in any
// module at all and should use the latest semantics.)
diff --git a/src/cmd/go/internal/modload/query_test.go b/src/cmd/go/internal/modload/query_test.go
index 777a56b977..e225a0e71e 100644
--- a/src/cmd/go/internal/modload/query_test.go
+++ b/src/cmd/go/internal/modload/query_test.go
@@ -7,7 +7,6 @@ package modload
import (
"context"
"internal/testenv"
- "io/ioutil"
"log"
"os"
"path"
@@ -27,7 +26,7 @@ func TestMain(m *testing.M) {
func testMain(m *testing.M) int {
cfg.GOPROXY = "direct"
- dir, err := ioutil.TempDir("", "modload-test-")
+ dir, err := os.MkdirTemp("", "modload-test-")
if err != nil {
log.Fatal(err)
}
diff --git a/src/cmd/go/internal/modload/vendor.go b/src/cmd/go/internal/modload/vendor.go
index ab29d4d014..80d49053c6 100644
--- a/src/cmd/go/internal/modload/vendor.go
+++ b/src/cmd/go/internal/modload/vendor.go
@@ -8,7 +8,7 @@ import (
"errors"
"fmt"
"io/fs"
- "io/ioutil"
+ "os"
"path/filepath"
"strings"
"sync"
@@ -40,7 +40,7 @@ func readVendorList() {
vendorPkgModule = make(map[string]module.Version)
vendorVersion = make(map[string]string)
vendorMeta = make(map[module.Version]vendorMetadata)
- data, err := ioutil.ReadFile(filepath.Join(ModRoot(), "vendor/modules.txt"))
+ data, err := os.ReadFile(filepath.Join(ModRoot(), "vendor/modules.txt"))
if err != nil {
if !errors.Is(err, fs.ErrNotExist) {
base.Fatalf("go: %s", err)
diff --git a/src/cmd/go/internal/renameio/renameio.go b/src/cmd/go/internal/renameio/renameio.go
index 60a7138a76..9788171d6e 100644
--- a/src/cmd/go/internal/renameio/renameio.go
+++ b/src/cmd/go/internal/renameio/renameio.go
@@ -25,7 +25,7 @@ func Pattern(filename string) string {
return filepath.Join(filepath.Dir(filename), filepath.Base(filename)+patternSuffix)
}
-// WriteFile is like ioutil.WriteFile, but first writes data to an arbitrary
+// WriteFile is like os.WriteFile, but first writes data to an arbitrary
// file in the same directory as filename, then renames it atomically to the
// final name.
//
@@ -67,7 +67,7 @@ func WriteToFile(filename string, data io.Reader, perm fs.FileMode) (err error)
return robustio.Rename(f.Name(), filename)
}
-// ReadFile is like ioutil.ReadFile, but on Windows retries spurious errors that
+// ReadFile is like os.ReadFile, but on Windows retries spurious errors that
// may occur if the file is concurrently replaced.
//
// Errors are classified heuristically and retries are bounded, so even this
diff --git a/src/cmd/go/internal/renameio/renameio_test.go b/src/cmd/go/internal/renameio/renameio_test.go
index e6d2025a0e..5b2ed83624 100644
--- a/src/cmd/go/internal/renameio/renameio_test.go
+++ b/src/cmd/go/internal/renameio/renameio_test.go
@@ -10,7 +10,6 @@ import (
"encoding/binary"
"errors"
"internal/testenv"
- "io/ioutil"
"math/rand"
"os"
"path/filepath"
@@ -30,7 +29,7 @@ func TestConcurrentReadsAndWrites(t *testing.T) {
testenv.SkipFlaky(t, 33041)
}
- dir, err := ioutil.TempDir("", "renameio")
+ dir, err := os.MkdirTemp("", "renameio")
if err != nil {
t.Fatal(err)
}
diff --git a/src/cmd/go/internal/renameio/umask_test.go b/src/cmd/go/internal/renameio/umask_test.go
index 19e217c548..65e4fa587b 100644
--- a/src/cmd/go/internal/renameio/umask_test.go
+++ b/src/cmd/go/internal/renameio/umask_test.go
@@ -8,7 +8,6 @@ package renameio
import (
"io/fs"
- "io/ioutil"
"os"
"path/filepath"
"syscall"
@@ -16,7 +15,7 @@ import (
)
func TestWriteFileModeAppliesUmask(t *testing.T) {
- dir, err := ioutil.TempDir("", "renameio")
+ dir, err := os.MkdirTemp("", "renameio")
if err != nil {
t.Fatalf("Failed to create temporary directory: %v", err)
}
diff --git a/src/cmd/go/internal/robustio/robustio.go b/src/cmd/go/internal/robustio/robustio.go
index 76e47ad1ff..ce3dbbde6d 100644
--- a/src/cmd/go/internal/robustio/robustio.go
+++ b/src/cmd/go/internal/robustio/robustio.go
@@ -22,7 +22,7 @@ func Rename(oldpath, newpath string) error {
return rename(oldpath, newpath)
}
-// ReadFile is like ioutil.ReadFile, but on Windows retries errors that may
+// ReadFile is like os.ReadFile, but on Windows retries errors that may
// occur if the file is concurrently replaced.
//
// (See golang.org/issue/31247 and golang.org/issue/32188.)
diff --git a/src/cmd/go/internal/robustio/robustio_flaky.go b/src/cmd/go/internal/robustio/robustio_flaky.go
index d4cb7e6457..5bd44bd345 100644
--- a/src/cmd/go/internal/robustio/robustio_flaky.go
+++ b/src/cmd/go/internal/robustio/robustio_flaky.go
@@ -8,7 +8,6 @@ package robustio
import (
"errors"
- "io/ioutil"
"math/rand"
"os"
"syscall"
@@ -70,11 +69,11 @@ func rename(oldpath, newpath string) (err error) {
})
}
-// readFile is like ioutil.ReadFile, but retries ephemeral errors.
+// readFile is like os.ReadFile, but retries ephemeral errors.
func readFile(filename string) ([]byte, error) {
var b []byte
err := retry(func() (err error, mayRetry bool) {
- b, err = ioutil.ReadFile(filename)
+ b, err = os.ReadFile(filename)
// Unlike in rename, we do not retry errFileNotFound here: it can occur
// as a spurious error, but the file may also genuinely not exist, so the
diff --git a/src/cmd/go/internal/robustio/robustio_other.go b/src/cmd/go/internal/robustio/robustio_other.go
index 907b556858..6fe7b7e4e4 100644
--- a/src/cmd/go/internal/robustio/robustio_other.go
+++ b/src/cmd/go/internal/robustio/robustio_other.go
@@ -7,7 +7,6 @@
package robustio
import (
- "io/ioutil"
"os"
)
@@ -16,7 +15,7 @@ func rename(oldpath, newpath string) error {
}
func readFile(filename string) ([]byte, error) {
- return ioutil.ReadFile(filename)
+ return os.ReadFile(filename)
}
func removeAll(path string) error {
diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go
index 24601dc061..e8a7aacb85 100644
--- a/src/cmd/go/internal/test/test.go
+++ b/src/cmd/go/internal/test/test.go
@@ -13,7 +13,6 @@ import (
"go/build"
"io"
"io/fs"
- "io/ioutil"
"os"
"os/exec"
"path"
@@ -884,7 +883,7 @@ func builderTest(b *work.Builder, ctx context.Context, p *load.Package) (buildAc
if !cfg.BuildN {
// writeTestmain writes _testmain.go,
// using the test description gathered in t.
- if err := ioutil.WriteFile(testDir+"_testmain.go", *pmain.Internal.TestmainGo, 0666); err != nil {
+ if err := os.WriteFile(testDir+"_testmain.go", *pmain.Internal.TestmainGo, 0666); err != nil {
return nil, nil, nil, err
}
}
@@ -1561,13 +1560,18 @@ func hashOpen(name string) (cache.ActionID, error) {
}
hashWriteStat(h, info)
if info.IsDir() {
- names, err := ioutil.ReadDir(name)
+ files, err := os.ReadDir(name)
if err != nil {
fmt.Fprintf(h, "err %v\n", err)
}
- for _, f := range names {
+ for _, f := range files {
fmt.Fprintf(h, "file %s ", f.Name())
- hashWriteStat(h, f)
+ finfo, err := f.Info()
+ if err != nil {
+ fmt.Fprintf(h, "err %v\n", err)
+ } else {
+ hashWriteStat(h, finfo)
+ }
}
} else if info.Mode().IsRegular() {
// Because files might be very large, do not attempt
@@ -1616,7 +1620,7 @@ func (c *runCache) saveOutput(a *work.Action) {
}
// See comment about two-level lookup in tryCacheWithID above.
- testlog, err := ioutil.ReadFile(a.Objdir + "testlog.txt")
+ testlog, err := os.ReadFile(a.Objdir + "testlog.txt")
if err != nil || !bytes.HasPrefix(testlog, testlogMagic) || testlog[len(testlog)-1] != '\n' {
if cache.DebugTest {
if err != nil {
diff --git a/src/cmd/go/internal/txtar/archive.go b/src/cmd/go/internal/txtar/archive.go
index c384f33bdf..1796684877 100644
--- a/src/cmd/go/internal/txtar/archive.go
+++ b/src/cmd/go/internal/txtar/archive.go
@@ -34,7 +34,7 @@ package txtar
import (
"bytes"
"fmt"
- "io/ioutil"
+ "os"
"strings"
)
@@ -66,7 +66,7 @@ func Format(a *Archive) []byte {
// ParseFile parses the named file as an archive.
func ParseFile(file string) (*Archive, error) {
- data, err := ioutil.ReadFile(file)
+ data, err := os.ReadFile(file)
if err != nil {
return nil, err
}
diff --git a/src/cmd/go/internal/vcs/vcs.go b/src/cmd/go/internal/vcs/vcs.go
index e7bef9f591..4894ecdc35 100644
--- a/src/cmd/go/internal/vcs/vcs.go
+++ b/src/cmd/go/internal/vcs/vcs.go
@@ -23,6 +23,7 @@ import (
"cmd/go/internal/base"
"cmd/go/internal/cfg"
"cmd/go/internal/search"
+ "cmd/go/internal/str"
"cmd/go/internal/web"
"golang.org/x/mod/module"
@@ -539,7 +540,7 @@ func (v *Cmd) TagSync(dir, tag string) error {
// A vcsPath describes how to convert an import path into a
// version control system and repository name.
type vcsPath struct {
- prefix string // prefix this description applies to
+ pathPrefix string // prefix this description applies to
regexp *lazyregexp.Regexp // compiled pattern for import path
repo string // repository to use (expand with match of re)
vcs string // version control system to use (expand with match of re)
@@ -826,6 +827,20 @@ var errUnknownSite = errors.New("dynamic lookup required to find mapping")
// repoRootFromVCSPaths attempts to map importPath to a repoRoot
// using the mappings defined in vcsPaths.
func repoRootFromVCSPaths(importPath string, security web.SecurityMode, vcsPaths []*vcsPath) (*RepoRoot, error) {
+ if str.HasPathPrefix(importPath, "example.net") {
+ // TODO(rsc): This should not be necessary, but it's required to keep
+ // tests like ../../testdata/script/mod_get_extra.txt from using the network.
+ // That script has everything it needs in the replacement set, but it is still
+ // doing network calls.
+ return nil, fmt.Errorf("no modules on example.net")
+ }
+ if importPath == "rsc.io" {
+ // This special case allows tests like ../../testdata/script/govcs.txt
+ // to avoid making any network calls. The module lookup for a path
+ // like rsc.io/nonexist.svn/foo needs to not make a network call for
+ // a lookup on rsc.io.
+ return nil, fmt.Errorf("rsc.io is not a module")
+ }
// A common error is to use https://packagepath because that's what
// hg and git require. Diagnose this helpfully.
if prefix := httpPrefix(importPath); prefix != "" {
@@ -834,20 +849,20 @@ func repoRootFromVCSPaths(importPath string, security web.SecurityMode, vcsPaths
return nil, fmt.Errorf("%q not allowed in import path", prefix+"//")
}
for _, srv := range vcsPaths {
- if !strings.HasPrefix(importPath, srv.prefix) {
+ if !str.HasPathPrefix(importPath, srv.pathPrefix) {
continue
}
m := srv.regexp.FindStringSubmatch(importPath)
if m == nil {
- if srv.prefix != "" {
- return nil, importErrorf(importPath, "invalid %s import path %q", srv.prefix, importPath)
+ if srv.pathPrefix != "" {
+ return nil, importErrorf(importPath, "invalid %s import path %q", srv.pathPrefix, importPath)
}
continue
}
// Build map of named subexpression matches for expand.
match := map[string]string{
- "prefix": srv.prefix,
+ "prefix": srv.pathPrefix + "/",
"import": importPath,
}
for i, name := range srv.regexp.SubexpNames() {
@@ -1098,18 +1113,6 @@ type metaImport struct {
Prefix, VCS, RepoRoot string
}
-// pathPrefix reports whether sub is a prefix of s,
-// only considering entire path components.
-func pathPrefix(s, sub string) bool {
- // strings.HasPrefix is necessary but not sufficient.
- if !strings.HasPrefix(s, sub) {
- return false
- }
- // The remainder after the prefix must either be empty or start with a slash.
- rem := s[len(sub):]
- return rem == "" || rem[0] == '/'
-}
-
// A ImportMismatchError is returned where metaImport/s are present
// but none match our import path.
type ImportMismatchError struct {
@@ -1133,7 +1136,7 @@ func matchGoImport(imports []metaImport, importPath string) (metaImport, error)
errImportMismatch := ImportMismatchError{importPath: importPath}
for i, im := range imports {
- if !pathPrefix(importPath, im.Prefix) {
+ if !str.HasPathPrefix(importPath, im.Prefix) {
errImportMismatch.mismatches = append(errImportMismatch.mismatches, im.Prefix)
continue
}
@@ -1175,52 +1178,52 @@ func expand(match map[string]string, s string) string {
var vcsPaths = []*vcsPath{
// Github
{
- prefix: "github.com/",
- regexp: lazyregexp.New(`^(?Pgithub\.com/[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+)(/[A-Za-z0-9_.\-]+)*$`),
- vcs: "git",
- repo: "https://{root}",
- check: noVCSSuffix,
+ pathPrefix: "github.com",
+ regexp: lazyregexp.New(`^(?Pgithub\.com/[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+)(/[A-Za-z0-9_.\-]+)*$`),
+ vcs: "git",
+ repo: "https://{root}",
+ check: noVCSSuffix,
},
// Bitbucket
{
- prefix: "bitbucket.org/",
- regexp: lazyregexp.New(`^(?Pbitbucket\.org/(?P[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+))(/[A-Za-z0-9_.\-]+)*$`),
- repo: "https://{root}",
- check: bitbucketVCS,
+ pathPrefix: "bitbucket.org",
+ regexp: lazyregexp.New(`^(?Pbitbucket\.org/(?P[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+))(/[A-Za-z0-9_.\-]+)*$`),
+ repo: "https://{root}",
+ check: bitbucketVCS,
},
// IBM DevOps Services (JazzHub)
{
- prefix: "hub.jazz.net/git/",
- regexp: lazyregexp.New(`^(?Phub\.jazz\.net/git/[a-z0-9]+/[A-Za-z0-9_.\-]+)(/[A-Za-z0-9_.\-]+)*$`),
- vcs: "git",
- repo: "https://{root}",
- check: noVCSSuffix,
+ pathPrefix: "hub.jazz.net/git",
+ regexp: lazyregexp.New(`^(?Phub\.jazz\.net/git/[a-z0-9]+/[A-Za-z0-9_.\-]+)(/[A-Za-z0-9_.\-]+)*$`),
+ vcs: "git",
+ repo: "https://{root}",
+ check: noVCSSuffix,
},
// Git at Apache
{
- prefix: "git.apache.org/",
- regexp: lazyregexp.New(`^(?Pgit\.apache\.org/[a-z0-9_.\-]+\.git)(/[A-Za-z0-9_.\-]+)*$`),
- vcs: "git",
- repo: "https://{root}",
+ pathPrefix: "git.apache.org",
+ regexp: lazyregexp.New(`^(?Pgit\.apache\.org/[a-z0-9_.\-]+\.git)(/[A-Za-z0-9_.\-]+)*$`),
+ vcs: "git",
+ repo: "https://{root}",
},
// Git at OpenStack
{
- prefix: "git.openstack.org/",
- regexp: lazyregexp.New(`^(?Pgit\.openstack\.org/[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+)(\.git)?(/[A-Za-z0-9_.\-]+)*$`),
- vcs: "git",
- repo: "https://{root}",
+ pathPrefix: "git.openstack.org",
+ regexp: lazyregexp.New(`^(?Pgit\.openstack\.org/[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+)(\.git)?(/[A-Za-z0-9_.\-]+)*$`),
+ vcs: "git",
+ repo: "https://{root}",
},
// chiselapp.com for fossil
{
- prefix: "chiselapp.com/",
- regexp: lazyregexp.New(`^(?Pchiselapp\.com/user/[A-Za-z0-9]+/repository/[A-Za-z0-9_.\-]+)$`),
- vcs: "fossil",
- repo: "https://{root}",
+ pathPrefix: "chiselapp.com",
+ regexp: lazyregexp.New(`^(?Pchiselapp\.com/user/[A-Za-z0-9]+/repository/[A-Za-z0-9_.\-]+)$`),
+ vcs: "fossil",
+ repo: "https://{root}",
},
// General syntax for any server.
@@ -1238,11 +1241,11 @@ var vcsPaths = []*vcsPath{
var vcsPathsAfterDynamic = []*vcsPath{
// Launchpad. See golang.org/issue/11436.
{
- prefix: "launchpad.net/",
- regexp: lazyregexp.New(`^(?Plaunchpad\.net/((?P[A-Za-z0-9_.\-]+)(?P/[A-Za-z0-9_.\-]+)?|~[A-Za-z0-9_.\-]+/(\+junk|[A-Za-z0-9_.\-]+)/[A-Za-z0-9_.\-]+))(/[A-Za-z0-9_.\-]+)*$`),
- vcs: "bzr",
- repo: "https://{root}",
- check: launchpadVCS,
+ pathPrefix: "launchpad.net",
+ regexp: lazyregexp.New(`^(?Plaunchpad\.net/((?P[A-Za-z0-9_.\-]+)(?P/[A-Za-z0-9_.\-]+)?|~[A-Za-z0-9_.\-]+/(\+junk|[A-Za-z0-9_.\-]+)/[A-Za-z0-9_.\-]+))(/[A-Za-z0-9_.\-]+)*$`),
+ vcs: "bzr",
+ repo: "https://{root}",
+ check: launchpadVCS,
},
}
diff --git a/src/cmd/go/internal/vcs/vcs_test.go b/src/cmd/go/internal/vcs/vcs_test.go
index 72d74a01e3..c5c7a3283b 100644
--- a/src/cmd/go/internal/vcs/vcs_test.go
+++ b/src/cmd/go/internal/vcs/vcs_test.go
@@ -7,7 +7,6 @@ package vcs
import (
"errors"
"internal/testenv"
- "io/ioutil"
"os"
"path"
"path/filepath"
@@ -208,7 +207,7 @@ func TestRepoRootForImportPath(t *testing.T) {
// Test that vcsFromDir correctly inspects a given directory and returns the right VCS and root.
func TestFromDir(t *testing.T) {
- tempDir, err := ioutil.TempDir("", "vcstest")
+ tempDir, err := os.MkdirTemp("", "vcstest")
if err != nil {
t.Fatal(err)
}
diff --git a/src/cmd/go/internal/version/version.go b/src/cmd/go/internal/version/version.go
index 44ac24c62d..58cbd32e78 100644
--- a/src/cmd/go/internal/version/version.go
+++ b/src/cmd/go/internal/version/version.go
@@ -88,8 +88,15 @@ func runVersion(ctx context.Context, cmd *base.Command, args []string) {
// scanDir scans a directory for executables to run scanFile on.
func scanDir(dir string) {
- filepath.Walk(dir, func(path string, info fs.FileInfo, err error) error {
- if info.Mode().IsRegular() || info.Mode()&fs.ModeSymlink != 0 {
+ filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error {
+ if d.Type().IsRegular() || d.Type()&fs.ModeSymlink != 0 {
+ info, err := d.Info()
+ if err != nil {
+ if *versionV {
+ fmt.Fprintf(os.Stderr, "%s: %v\n", path, err)
+ }
+ return nil
+ }
scanFile(path, info, *versionV)
}
return nil
@@ -120,6 +127,7 @@ func scanFile(file string, info fs.FileInfo, mustPrint bool) {
}
info = i
}
+
if !isExe(file, info) {
if mustPrint {
fmt.Fprintf(os.Stderr, "%s: not executable file\n", file)
diff --git a/src/cmd/go/internal/web/file_test.go b/src/cmd/go/internal/web/file_test.go
index a1bb080e07..3734df5c4e 100644
--- a/src/cmd/go/internal/web/file_test.go
+++ b/src/cmd/go/internal/web/file_test.go
@@ -7,7 +7,6 @@ package web
import (
"errors"
"io/fs"
- "io/ioutil"
"os"
"path/filepath"
"testing"
@@ -16,7 +15,7 @@ import (
func TestGetFileURL(t *testing.T) {
const content = "Hello, file!\n"
- f, err := ioutil.TempFile("", "web-TestGetFileURL")
+ f, err := os.CreateTemp("", "web-TestGetFileURL")
if err != nil {
t.Fatal(err)
}
diff --git a/src/cmd/go/internal/web/http.go b/src/cmd/go/internal/web/http.go
index e0509808d6..72fa2b2ca6 100644
--- a/src/cmd/go/internal/web/http.go
+++ b/src/cmd/go/internal/web/http.go
@@ -80,6 +80,13 @@ func get(security SecurityMode, url *urlpkg.URL) (*Response, error) {
return res, nil
}
+ if url.Host == "localhost.localdev" {
+ return nil, fmt.Errorf("no such host localhost.localdev")
+ }
+ if os.Getenv("TESTGONETWORK") == "panic" && !strings.HasPrefix(url.Host, "127.0.0.1") && !strings.HasPrefix(url.Host, "0.0.0.0") {
+ panic("use of network: " + url.String())
+ }
+
fetch := func(url *urlpkg.URL) (*urlpkg.URL, *http.Response, error) {
// Note: The -v build flag does not mean "print logging information",
// despite its historical misuse for this in GOPATH-based go get.
diff --git a/src/cmd/go/internal/work/action.go b/src/cmd/go/internal/work/action.go
index f461c5780f..9d141ae233 100644
--- a/src/cmd/go/internal/work/action.go
+++ b/src/cmd/go/internal/work/action.go
@@ -14,7 +14,6 @@ import (
"debug/elf"
"encoding/json"
"fmt"
- "io/ioutil"
"os"
"path/filepath"
"runtime"
@@ -253,7 +252,7 @@ func (b *Builder) Init() {
if cfg.BuildN {
b.WorkDir = "$WORK"
} else {
- tmp, err := ioutil.TempDir(cfg.Getenv("GOTMPDIR"), "go-build")
+ tmp, err := os.MkdirTemp(cfg.Getenv("GOTMPDIR"), "go-build")
if err != nil {
base.Fatalf("go: creating work dir: %v", err)
}
diff --git a/src/cmd/go/internal/work/build_test.go b/src/cmd/go/internal/work/build_test.go
index e941729734..eaf2639e9e 100644
--- a/src/cmd/go/internal/work/build_test.go
+++ b/src/cmd/go/internal/work/build_test.go
@@ -8,7 +8,6 @@ import (
"bytes"
"fmt"
"io/fs"
- "io/ioutil"
"os"
"path/filepath"
"reflect"
@@ -170,7 +169,7 @@ func TestSharedLibName(t *testing.T) {
for _, data := range testData {
func() {
if data.rootedAt != "" {
- tmpGopath, err := ioutil.TempDir("", "gopath")
+ tmpGopath, err := os.MkdirTemp("", "gopath")
if err != nil {
t.Fatal(err)
}
@@ -238,7 +237,7 @@ func TestRespectSetgidDir(t *testing.T) {
return cmdBuf.WriteString(fmt.Sprint(a...))
}
- setgiddir, err := ioutil.TempDir("", "SetGroupID")
+ setgiddir, err := os.MkdirTemp("", "SetGroupID")
if err != nil {
t.Fatal(err)
}
@@ -258,9 +257,9 @@ func TestRespectSetgidDir(t *testing.T) {
t.Fatal(err)
}
- pkgfile, err := ioutil.TempFile("", "pkgfile")
+ pkgfile, err := os.CreateTemp("", "pkgfile")
if err != nil {
- t.Fatalf("ioutil.TempFile(\"\", \"pkgfile\"): %v", err)
+ t.Fatalf("os.CreateTemp(\"\", \"pkgfile\"): %v", err)
}
defer os.Remove(pkgfile.Name())
defer pkgfile.Close()
diff --git a/src/cmd/go/internal/work/buildid.go b/src/cmd/go/internal/work/buildid.go
index a88544e1af..d76988145b 100644
--- a/src/cmd/go/internal/work/buildid.go
+++ b/src/cmd/go/internal/work/buildid.go
@@ -7,7 +7,6 @@ package work
import (
"bytes"
"fmt"
- "io/ioutil"
"os"
"os/exec"
"strings"
@@ -344,7 +343,7 @@ func (b *Builder) gccgoBuildIDFile(a *Action) (string, error) {
}
}
- if err := ioutil.WriteFile(sfile, buf.Bytes(), 0666); err != nil {
+ if err := os.WriteFile(sfile, buf.Bytes(), 0666); err != nil {
return "", err
}
@@ -647,7 +646,7 @@ func (b *Builder) updateBuildID(a *Action, target string, rewrite bool) error {
}
if rewrite {
- w, err := os.OpenFile(target, os.O_WRONLY, 0)
+ w, err := os.OpenFile(target, os.O_RDWR, 0)
if err != nil {
return err
}
diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go
index 6ce56dd6f4..336751df27 100644
--- a/src/cmd/go/internal/work/exec.go
+++ b/src/cmd/go/internal/work/exec.go
@@ -16,7 +16,6 @@ import (
"internal/lazyregexp"
"io"
"io/fs"
- "io/ioutil"
"log"
"math/rand"
"os"
@@ -94,7 +93,7 @@ func (b *Builder) Do(ctx context.Context, root *Action) {
base.Fatalf("go: refusing to write action graph to %v\n", file)
}
js := actionGraphJSON(root)
- if err := ioutil.WriteFile(file, []byte(js), 0666); err != nil {
+ if err := os.WriteFile(file, []byte(js), 0666); err != nil {
fmt.Fprintf(os.Stderr, "go: writing action graph: %v\n", err)
base.SetExitStatus(1)
}
@@ -636,7 +635,7 @@ OverlayLoop:
sfiles, gccfiles = filter(sfiles, sfiles[:0], gccfiles)
} else {
for _, sfile := range sfiles {
- data, err := ioutil.ReadFile(filepath.Join(a.Package.Dir, sfile))
+ data, err := os.ReadFile(filepath.Join(a.Package.Dir, sfile))
if err == nil {
if bytes.HasPrefix(data, []byte("TEXT")) || bytes.Contains(data, []byte("\nTEXT")) ||
bytes.HasPrefix(data, []byte("DATA")) || bytes.Contains(data, []byte("\nDATA")) ||
@@ -1471,7 +1470,7 @@ func (b *Builder) installShlibname(ctx context.Context, a *Action) error {
// TODO: BuildN
a1 := a.Deps[0]
- err := ioutil.WriteFile(a.Target, []byte(filepath.Base(a1.Target)+"\n"), 0666)
+ err := os.WriteFile(a.Target, []byte(filepath.Base(a1.Target)+"\n"), 0666)
if err != nil {
return err
}
@@ -1788,7 +1787,7 @@ func (b *Builder) writeFile(file string, text []byte) error {
if cfg.BuildN {
return nil
}
- return ioutil.WriteFile(file, text, 0666)
+ return os.WriteFile(file, text, 0666)
}
// Install the cgo export header file, if there is one.
@@ -2537,7 +2536,7 @@ func (b *Builder) gccSupportsFlag(compiler []string, flag string) bool {
tmp := os.DevNull
if runtime.GOOS == "windows" {
- f, err := ioutil.TempFile(b.WorkDir, "")
+ f, err := os.CreateTemp(b.WorkDir, "")
if err != nil {
return false
}
@@ -2840,7 +2839,7 @@ func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgo
continue
}
- src, err := ioutil.ReadFile(f)
+ src, err := os.ReadFile(f)
if err != nil {
return nil, nil, err
}
@@ -3070,7 +3069,7 @@ func (b *Builder) swigDoIntSize(objdir string) (intsize string, err error) {
return "$INTBITS", nil
}
src := filepath.Join(b.WorkDir, "swig_intsize.go")
- if err = ioutil.WriteFile(src, []byte(swigIntSizeCode), 0666); err != nil {
+ if err = os.WriteFile(src, []byte(swigIntSizeCode), 0666); err != nil {
return
}
srcs := []string{src}
@@ -3230,7 +3229,7 @@ func passLongArgsInResponseFiles(cmd *exec.Cmd) (cleanup func()) {
return
}
- tf, err := ioutil.TempFile("", "args")
+ tf, err := os.CreateTemp("", "args")
if err != nil {
log.Fatalf("error writing long arguments to response file: %v", err)
}
diff --git a/src/cmd/go/internal/work/gc.go b/src/cmd/go/internal/work/gc.go
index 3a53c714e3..cc4e2b2b2b 100644
--- a/src/cmd/go/internal/work/gc.go
+++ b/src/cmd/go/internal/work/gc.go
@@ -9,7 +9,6 @@ import (
"bytes"
"fmt"
"io"
- "io/ioutil"
"log"
"os"
"path/filepath"
@@ -426,11 +425,11 @@ func toolVerify(a *Action, b *Builder, p *load.Package, newTool string, ofile st
if err := b.run(a, p.Dir, p.ImportPath, nil, newArgs...); err != nil {
return err
}
- data1, err := ioutil.ReadFile(ofile)
+ data1, err := os.ReadFile(ofile)
if err != nil {
return err
}
- data2, err := ioutil.ReadFile(ofile + ".new")
+ data2, err := os.ReadFile(ofile + ".new")
if err != nil {
return err
}
@@ -580,7 +579,7 @@ func pluginPath(a *Action) string {
}
fmt.Fprintf(h, "build ID: %s\n", buildID)
for _, file := range str.StringList(p.GoFiles, p.CgoFiles, p.SFiles) {
- data, err := ioutil.ReadFile(filepath.Join(p.Dir, file))
+ data, err := os.ReadFile(filepath.Join(p.Dir, file))
if err != nil {
base.Fatalf("go: %s", err)
}
diff --git a/src/cmd/go/internal/work/gccgo.go b/src/cmd/go/internal/work/gccgo.go
index 01d2b89159..3ffd01c473 100644
--- a/src/cmd/go/internal/work/gccgo.go
+++ b/src/cmd/go/internal/work/gccgo.go
@@ -6,7 +6,6 @@ package work
import (
"fmt"
- "io/ioutil"
"os"
"os/exec"
"path/filepath"
@@ -271,7 +270,7 @@ func (tools gccgoToolchain) link(b *Builder, root *Action, out, importcfg string
}
readCgoFlags := func(flagsFile string) error {
- flags, err := ioutil.ReadFile(flagsFile)
+ flags, err := os.ReadFile(flagsFile)
if err != nil {
return err
}
diff --git a/src/cmd/go/proxy_test.go b/src/cmd/go/proxy_test.go
index 3ed42face2..e390c73a9c 100644
--- a/src/cmd/go/proxy_test.go
+++ b/src/cmd/go/proxy_test.go
@@ -13,7 +13,6 @@ import (
"fmt"
"io"
"io/fs"
- "io/ioutil"
"log"
"net"
"net/http"
@@ -75,12 +74,12 @@ func StartProxy() {
var modList []module.Version
func readModList() {
- infos, err := ioutil.ReadDir("testdata/mod")
+ files, err := os.ReadDir("testdata/mod")
if err != nil {
log.Fatal(err)
}
- for _, info := range infos {
- name := info.Name()
+ for _, f := range files {
+ name := f.Name()
if !strings.HasSuffix(name, ".txt") {
continue
}
diff --git a/src/cmd/go/script_test.go b/src/cmd/go/script_test.go
index b1d1499038..dfaa40548e 100644
--- a/src/cmd/go/script_test.go
+++ b/src/cmd/go/script_test.go
@@ -15,7 +15,6 @@ import (
"go/build"
"internal/testenv"
"io/fs"
- "io/ioutil"
"os"
"os/exec"
"path/filepath"
@@ -142,6 +141,9 @@ func (ts *testScript) setup() {
"goversion=" + goVersion(ts),
":=" + string(os.PathListSeparator),
}
+ if !testenv.HasExternalNetwork() {
+ ts.env = append(ts.env, "TESTGONETWORK=panic", "TESTGOVCS=panic")
+ }
if runtime.GOOS == "plan9" {
ts.env = append(ts.env, "path="+testBin+string(filepath.ListSeparator)+os.Getenv("path"))
@@ -217,7 +219,7 @@ func (ts *testScript) run() {
for _, f := range a.Files {
name := ts.mkabs(ts.expand(f.Name, false))
ts.check(os.MkdirAll(filepath.Dir(name), 0777))
- ts.check(ioutil.WriteFile(name, f.Data, 0666))
+ ts.check(os.WriteFile(name, f.Data, 0666))
}
// With -v or -testwork, start log with full environment.
@@ -374,19 +376,19 @@ var (
func isCaseSensitive(t *testing.T) bool {
onceCaseSensitive.Do(func() {
- tmpdir, err := ioutil.TempDir("", "case-sensitive")
+ tmpdir, err := os.MkdirTemp("", "case-sensitive")
if err != nil {
t.Fatal("failed to create directory to determine case-sensitivity:", err)
}
defer os.RemoveAll(tmpdir)
fcap := filepath.Join(tmpdir, "FILE")
- if err := ioutil.WriteFile(fcap, []byte{}, 0644); err != nil {
+ if err := os.WriteFile(fcap, []byte{}, 0644); err != nil {
t.Fatal("error writing file to determine case-sensitivity:", err)
}
flow := filepath.Join(tmpdir, "file")
- _, err = ioutil.ReadFile(flow)
+ _, err = os.ReadFile(flow)
switch {
case err == nil:
caseSensitive = false
@@ -447,9 +449,9 @@ func (ts *testScript) cmdAddcrlf(want simpleStatus, args []string) {
for _, file := range args {
file = ts.mkabs(file)
- data, err := ioutil.ReadFile(file)
+ data, err := os.ReadFile(file)
ts.check(err)
- ts.check(ioutil.WriteFile(file, bytes.ReplaceAll(data, []byte("\n"), []byte("\r\n")), 0666))
+ ts.check(os.WriteFile(file, bytes.ReplaceAll(data, []byte("\n"), []byte("\r\n")), 0666))
}
}
@@ -554,12 +556,12 @@ func (ts *testScript) doCmdCmp(args []string, env, quiet bool) {
} else if name1 == "stderr" {
text1 = ts.stderr
} else {
- data, err := ioutil.ReadFile(ts.mkabs(name1))
+ data, err := os.ReadFile(ts.mkabs(name1))
ts.check(err)
text1 = string(data)
}
- data, err := ioutil.ReadFile(ts.mkabs(name2))
+ data, err := os.ReadFile(ts.mkabs(name2))
ts.check(err)
text2 = string(data)
@@ -611,14 +613,14 @@ func (ts *testScript) cmdCp(want simpleStatus, args []string) {
info, err := os.Stat(src)
ts.check(err)
mode = info.Mode() & 0777
- data, err = ioutil.ReadFile(src)
+ data, err = os.ReadFile(src)
ts.check(err)
}
targ := dst
if dstDir {
targ = filepath.Join(dst, filepath.Base(src))
}
- err := ioutil.WriteFile(targ, data, mode)
+ err := os.WriteFile(targ, data, mode)
switch want {
case failure:
if err == nil {
@@ -894,7 +896,7 @@ func scriptMatch(ts *testScript, want simpleStatus, args []string, text, name st
isGrep := name == "grep"
if isGrep {
name = args[1] // for error messages
- data, err := ioutil.ReadFile(ts.mkabs(args[1]))
+ data, err := os.ReadFile(ts.mkabs(args[1]))
ts.check(err)
text = string(data)
}
diff --git a/src/cmd/go/testdata/addmod.go b/src/cmd/go/testdata/addmod.go
index d1b6467c5d..58376b7ed4 100644
--- a/src/cmd/go/testdata/addmod.go
+++ b/src/cmd/go/testdata/addmod.go
@@ -23,7 +23,6 @@ import (
"flag"
"fmt"
"io/fs"
- "io/ioutil"
"log"
"os"
"os/exec"
@@ -58,7 +57,7 @@ func main() {
log.SetFlags(0)
var err error
- tmpdir, err = ioutil.TempDir("", "addmod-")
+ tmpdir, err = os.MkdirTemp("", "addmod-")
if err != nil {
log.Fatal(err)
}
@@ -82,7 +81,7 @@ func main() {
exitCode := 0
for _, arg := range flag.Args() {
- if err := ioutil.WriteFile(filepath.Join(tmpdir, "go.mod"), []byte("module m\n"), 0666); err != nil {
+ if err := os.WriteFile(filepath.Join(tmpdir, "go.mod"), []byte("module m\n"), 0666); err != nil {
fatalf("%v", err)
}
run(goCmd, "get", "-d", arg)
@@ -98,13 +97,13 @@ func main() {
continue
}
path, vers, dir := f[0], f[1], f[2]
- mod, err := ioutil.ReadFile(filepath.Join(gopath, "pkg/mod/cache/download", path, "@v", vers+".mod"))
+ mod, err := os.ReadFile(filepath.Join(gopath, "pkg/mod/cache/download", path, "@v", vers+".mod"))
if err != nil {
log.Printf("%s: %v", arg, err)
exitCode = 1
continue
}
- info, err := ioutil.ReadFile(filepath.Join(gopath, "pkg/mod/cache/download", path, "@v", vers+".info"))
+ info, err := os.ReadFile(filepath.Join(gopath, "pkg/mod/cache/download", path, "@v", vers+".info"))
if err != nil {
log.Printf("%s: %v", arg, err)
exitCode = 1
@@ -122,13 +121,13 @@ func main() {
{Name: ".info", Data: info},
}
dir = filepath.Clean(dir)
- err = filepath.Walk(dir, func(path string, info fs.FileInfo, err error) error {
- if !info.Mode().IsRegular() {
+ err = filepath.WalkDir(dir, func(path string, info fs.DirEntry, err error) error {
+ if !info.Type().IsRegular() {
return nil
}
name := info.Name()
if name == "go.mod" || strings.HasSuffix(name, ".go") {
- data, err := ioutil.ReadFile(path)
+ data, err := os.ReadFile(path)
if err != nil {
return err
}
@@ -144,7 +143,7 @@ func main() {
data := txtar.Format(a)
target := filepath.Join("mod", strings.ReplaceAll(path, "/", "_")+"_"+vers+".txt")
- if err := ioutil.WriteFile(target, data, 0666); err != nil {
+ if err := os.WriteFile(target, data, 0666); err != nil {
log.Printf("%s: %v", arg, err)
exitCode = 1
continue
diff --git a/src/cmd/go/testdata/savedir.go b/src/cmd/go/testdata/savedir.go
index 04902df61e..d469c31a91 100644
--- a/src/cmd/go/testdata/savedir.go
+++ b/src/cmd/go/testdata/savedir.go
@@ -18,7 +18,6 @@ import (
"flag"
"fmt"
"io/fs"
- "io/ioutil"
"log"
"os"
"path/filepath"
@@ -49,7 +48,7 @@ func main() {
a := new(txtar.Archive)
dir = filepath.Clean(dir)
- filepath.Walk(dir, func(path string, info fs.FileInfo, err error) error {
+ filepath.WalkDir(dir, func(path string, info fs.DirEntry, err error) error {
if path == dir {
return nil
}
@@ -60,10 +59,10 @@ func main() {
}
return nil
}
- if !info.Mode().IsRegular() {
+ if !info.Type().IsRegular() {
return nil
}
- data, err := ioutil.ReadFile(path)
+ data, err := os.ReadFile(path)
if err != nil {
log.Fatal(err)
}
diff --git a/src/cmd/go/testdata/script/build_issue6480.txt b/src/cmd/go/testdata/script/build_issue6480.txt
index ae99c60d99..cf1e9ea6c2 100644
--- a/src/cmd/go/testdata/script/build_issue6480.txt
+++ b/src/cmd/go/testdata/script/build_issue6480.txt
@@ -81,7 +81,6 @@ package main
import (
"encoding/json"
"fmt"
- "io/ioutil"
"os"
"time"
)
@@ -100,7 +99,7 @@ func truncateLike(t, p time.Time) time.Time {
func main() {
var t1 time.Time
- b1, err := ioutil.ReadFile(os.Args[1])
+ b1, err := os.ReadFile(os.Args[1])
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
@@ -111,7 +110,7 @@ func main() {
}
var t2 time.Time
- b2, err := ioutil.ReadFile(os.Args[2])
+ b2, err := os.ReadFile(os.Args[2])
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
diff --git a/src/cmd/go/testdata/script/build_trimpath.txt b/src/cmd/go/testdata/script/build_trimpath.txt
index 2c3bee8fdc..e1ea0a48b2 100644
--- a/src/cmd/go/testdata/script/build_trimpath.txt
+++ b/src/cmd/go/testdata/script/build_trimpath.txt
@@ -121,7 +121,6 @@ package main
import (
"bytes"
"fmt"
- "io/ioutil"
"log"
"os"
"os/exec"
@@ -131,7 +130,7 @@ import (
func main() {
exe := os.Args[1]
- data, err := ioutil.ReadFile(exe)
+ data, err := os.ReadFile(exe)
if err != nil {
log.Fatal(err)
}
diff --git a/src/cmd/go/testdata/script/cover_error.txt b/src/cmd/go/testdata/script/cover_error.txt
index 4abdf1137a..583a664237 100644
--- a/src/cmd/go/testdata/script/cover_error.txt
+++ b/src/cmd/go/testdata/script/cover_error.txt
@@ -54,7 +54,6 @@ func Test(t *testing.T) {}
package main
import (
- "io/ioutil"
"log"
"os"
"strings"
@@ -62,13 +61,13 @@ import (
func main() {
log.SetFlags(0)
- b, err := ioutil.ReadFile(os.Args[1])
+ b, err := os.ReadFile(os.Args[1])
if err != nil {
log.Fatal(err)
}
s := strings.ReplaceAll(string(b), "p.go:4:2:", "p.go:4:")
s = strings.ReplaceAll(s, "p1.go:6:2:", "p1.go:6:")
- ioutil.WriteFile(os.Args[1], []byte(s), 0644)
+ os.WriteFile(os.Args[1], []byte(s), 0644)
if err != nil {
log.Fatal(err)
}
diff --git a/src/cmd/go/testdata/script/gopath_moved_repo.txt b/src/cmd/go/testdata/script/gopath_moved_repo.txt
index 869980da7c..99d80bff5d 100644
--- a/src/cmd/go/testdata/script/gopath_moved_repo.txt
+++ b/src/cmd/go/testdata/script/gopath_moved_repo.txt
@@ -45,7 +45,6 @@ package main
import (
"bytes"
- "io/ioutil"
"log"
"os"
)
@@ -57,11 +56,11 @@ func main() {
base := []byte(os.Args[1])
path := os.Args[2]
- data, err := ioutil.ReadFile(path)
+ data, err := os.ReadFile(path)
if err != nil {
log.Fatal(err)
}
- err = ioutil.WriteFile(path, bytes.ReplaceAll(data, base, append(base, "XXX"...)), 0644)
+ err = os.WriteFile(path, bytes.ReplaceAll(data, base, append(base, "XXX"...)), 0644)
if err != nil {
log.Fatal(err)
}
diff --git a/src/cmd/go/testdata/script/mod_download_concurrent_read.txt b/src/cmd/go/testdata/script/mod_download_concurrent_read.txt
index caf105c6e5..231babd0c0 100644
--- a/src/cmd/go/testdata/script/mod_download_concurrent_read.txt
+++ b/src/cmd/go/testdata/script/mod_download_concurrent_read.txt
@@ -25,7 +25,6 @@ package main
import (
"fmt"
- "io/ioutil"
"log"
"os"
"os/exec"
@@ -45,7 +44,7 @@ func main() {
// don't need to clean the cache or synchronize closing files after each
// iteration.
func run() (err error) {
- tmpDir, err := ioutil.TempDir("", "")
+ tmpDir, err := os.MkdirTemp("", "")
if err != nil {
return err
}
diff --git a/src/cmd/go/testdata/script/mod_get_deprecate_install.txt b/src/cmd/go/testdata/script/mod_get_deprecate_install.txt
deleted file mode 100644
index 7f5bcad410..0000000000
--- a/src/cmd/go/testdata/script/mod_get_deprecate_install.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-[short] skip
-
-env GO111MODULE=on
-
-# 'go get' outside a module with an executable prints a deprecation message.
-go get example.com/cmd/a
-stderr '^go get: installing executables with ''go get'' in module mode is deprecated.$'
-stderr 'Use ''go install pkg@version'' instead.'
-
-
-go mod init m
-
-# 'go get' inside a module with a non-main package does not print a message.
-# This will stop building in the future, but it's the command we want to use.
-go get rsc.io/quote
-! stderr deprecated
-
-# 'go get' inside a module with an executable prints a different
-# deprecation message.
-go get example.com/cmd/a
-stderr '^go get: installing executables with ''go get'' in module mode is deprecated.$'
-stderr 'To adjust dependencies of the current module, use ''go get -d'''
diff --git a/src/cmd/go/testdata/script/mod_gonoproxy.txt b/src/cmd/go/testdata/script/mod_gonoproxy.txt
index 546605da21..204786969f 100644
--- a/src/cmd/go/testdata/script/mod_gonoproxy.txt
+++ b/src/cmd/go/testdata/script/mod_gonoproxy.txt
@@ -21,7 +21,7 @@ go get -d rsc.io/quote
# Download .info files needed for 'go list -m all' later.
# TODO(#42723): either 'go list -m' should not read these files,
# or 'go get' and 'go mod tidy' should download them.
-go list -m all
+go list -m all
stdout '^golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c$'
# When GOPROXY is not empty but contains no entries, an error should be reported.
diff --git a/src/cmd/go/testdata/script/mod_import_issue42891.txt b/src/cmd/go/testdata/script/mod_import_issue42891.txt
new file mode 100644
index 0000000000..a78cab29ba
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_import_issue42891.txt
@@ -0,0 +1,14 @@
+# If an import declaration is an absolute path, most commands should report
+# an error instead of going into an infinite loop.
+# Verifies golang.org/issue/42891.
+go list .
+stdout '^m$'
+
+-- go.mod --
+module m
+
+go 1.16
+-- m.go --
+package m
+
+import "/"
diff --git a/src/cmd/go/testdata/script/mod_modinfo.txt b/src/cmd/go/testdata/script/mod_modinfo.txt
index d9e9fdec21..8d77e224a5 100644
--- a/src/cmd/go/testdata/script/mod_modinfo.txt
+++ b/src/cmd/go/testdata/script/mod_modinfo.txt
@@ -69,7 +69,6 @@ package main
import (
"bytes"
"encoding/hex"
- "io/ioutil"
"log"
"os"
@@ -77,7 +76,7 @@ import (
)
func main() {
- b, err := ioutil.ReadFile(os.Args[0])
+ b, err := os.ReadFile(os.Args[0])
if err != nil {
log.Fatal(err)
}
diff --git a/src/cmd/go/testdata/script/mod_proxy_invalid.txt b/src/cmd/go/testdata/script/mod_proxy_invalid.txt
index b9418b4df1..6427cc1527 100644
--- a/src/cmd/go/testdata/script/mod_proxy_invalid.txt
+++ b/src/cmd/go/testdata/script/mod_proxy_invalid.txt
@@ -2,7 +2,7 @@ env GO111MODULE=on
env GOPROXY=$GOPROXY/invalid
! go list -m rsc.io/quote@latest
-stderr '^go list -m: module rsc.io/quote: invalid response from proxy "'$GOPROXY'": json: invalid character ''i'' looking for beginning of value$'
+stderr '^go list -m: module rsc.io/quote: invalid response from proxy "'$GOPROXY'": invalid character ''i'' looking for beginning of value$'
! go list -m rsc.io/quote@1.5.2
-stderr '^go list -m: rsc.io/quote@1.5.2: invalid version: invalid response from proxy "'$GOPROXY'": json: invalid character ''i'' looking for beginning of value$'
+stderr '^go list -m: rsc.io/quote@1.5.2: invalid version: invalid response from proxy "'$GOPROXY'": invalid character ''i'' looking for beginning of value$'
diff --git a/src/cmd/go/testdata/script/mod_query_empty.txt b/src/cmd/go/testdata/script/mod_query_empty.txt
index 1f13d7ad69..f8b6e3e97e 100644
--- a/src/cmd/go/testdata/script/mod_query_empty.txt
+++ b/src/cmd/go/testdata/script/mod_query_empty.txt
@@ -40,7 +40,7 @@ env GOPROXY=file:///$WORK/gatekeeper
chmod 0000 $WORK/gatekeeper/example.com/join/subpkg/@latest
cp go.mod.orig go.mod
! go get -d example.com/join/subpkg
-stderr 'go get: module example.com/join/subpkg: (invalid response from proxy ".+": json: invalid character .+|reading file://.*/gatekeeper/example.com/join/subpkg/@latest: .+)'
+stderr 'go get: module example.com/join/subpkg: (invalid response from proxy ".+": invalid character .+|reading file://.*/gatekeeper/example.com/join/subpkg/@latest: .+)'
-- go.mod.orig --
module example.com/othermodule
diff --git a/src/cmd/go/testdata/script/mod_sumdb_proxy.txt b/src/cmd/go/testdata/script/mod_sumdb_proxy.txt
index 7bbc3f9e19..70b8e3fc44 100644
--- a/src/cmd/go/testdata/script/mod_sumdb_proxy.txt
+++ b/src/cmd/go/testdata/script/mod_sumdb_proxy.txt
@@ -17,14 +17,12 @@ rm $GOPATH/pkg/mod/cache/download/sumdb
rm go.sum
# direct access fails (because localhost.localdev does not exist)
-# The text of the error message is hard to predict because some DNS servers
-# will resolve unknown domains like localhost.localdev to a real IP
-# to serve ads.
+# web.get is providing the error message - there's no actual network access.
cp go.mod.orig go.mod
env GOSUMDB=$sumdb
env GOPROXY=direct
! go get -d rsc.io/fortune@v1.0.0
-stderr 'verifying.*localhost.localdev'
+stderr 'verifying module: rsc.io/fortune@v1.0.0: .*: no such host localhost.localdev'
rm $GOPATH/pkg/mod/cache/download/sumdb
rm go.sum
diff --git a/src/cmd/go/testdata/script/mod_test_cached.txt b/src/cmd/go/testdata/script/mod_test_cached.txt
index ffd573c02a..3da4358fa1 100644
--- a/src/cmd/go/testdata/script/mod_test_cached.txt
+++ b/src/cmd/go/testdata/script/mod_test_cached.txt
@@ -51,26 +51,25 @@ bar
package foo_test
import (
- "io/ioutil"
"os"
"path/filepath"
"testing"
)
func TestWriteTmp(t *testing.T) {
- dir, err := ioutil.TempDir("", "")
+ dir, err := os.MkdirTemp("", "")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(dir)
- err = ioutil.WriteFile(filepath.Join(dir, "x"), nil, 0666)
+ err = os.WriteFile(filepath.Join(dir, "x"), nil, 0666)
if err != nil {
t.Fatal(err)
}
}
func TestReadTestdata(t *testing.T) {
- _, err := ioutil.ReadFile("testdata/foo.txt")
+ _, err := os.ReadFile("testdata/foo.txt")
if err != nil {
t.Fatal(err)
}
diff --git a/src/cmd/go/testdata/script/test_compile_tempfile.txt b/src/cmd/go/testdata/script/test_compile_tempfile.txt
index 912410814f..05f721a800 100644
--- a/src/cmd/go/testdata/script/test_compile_tempfile.txt
+++ b/src/cmd/go/testdata/script/test_compile_tempfile.txt
@@ -1,7 +1,7 @@
[short] skip
# Ensure that the target of 'go build -o' can be an existing, empty file so that
-# its name can be reserved using ioutil.TempFile or the 'mktemp` command.
+# its name can be reserved using os.CreateTemp or the 'mktemp` command.
go build -o empty-file$GOEXE main.go
diff --git a/src/cmd/go/testdata/script/test_generated_main.txt b/src/cmd/go/testdata/script/test_generated_main.txt
index 75ffa9cde2..2e991a5797 100644
--- a/src/cmd/go/testdata/script/test_generated_main.txt
+++ b/src/cmd/go/testdata/script/test_generated_main.txt
@@ -12,7 +12,6 @@ package x
import (
"os"
"path/filepath"
- "io/ioutil"
"regexp"
"testing"
)
@@ -23,7 +22,7 @@ func Test(t *testing.T) {
t.Fatal(err)
}
testmainPath := filepath.Join(filepath.Dir(exePath), "_testmain.go")
- source, err := ioutil.ReadFile(testmainPath)
+ source, err := os.ReadFile(testmainPath)
if err != nil {
t.Fatal(err)
}
diff --git a/src/cmd/go/testdata/script/test_race_install_cgo.txt b/src/cmd/go/testdata/script/test_race_install_cgo.txt
index 82f00f2086..3f4eb90e3f 100644
--- a/src/cmd/go/testdata/script/test_race_install_cgo.txt
+++ b/src/cmd/go/testdata/script/test_race_install_cgo.txt
@@ -29,7 +29,6 @@ go 1.16
package main
import (
- "io/ioutil"
"encoding/json"
"fmt"
"os"
@@ -37,7 +36,7 @@ import (
)
func main() {
- b, err := ioutil.ReadFile(os.Args[1])
+ b, err := os.ReadFile(os.Args[1])
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
@@ -59,7 +58,6 @@ package main
import (
"encoding/json"
"fmt"
- "io/ioutil"
"os"
"time"
)
@@ -67,7 +65,7 @@ import (
func main() {
var t1 time.Time
- b1, err := ioutil.ReadFile(os.Args[1])
+ b1, err := os.ReadFile(os.Args[1])
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
@@ -78,7 +76,7 @@ func main() {
}
var t2 time.Time
- b2, err := ioutil.ReadFile(os.Args[2])
+ b2, err := os.ReadFile(os.Args[2])
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
diff --git a/src/cmd/gofmt/gofmt.go b/src/cmd/gofmt/gofmt.go
index dba2411eed..2793c2c2a4 100644
--- a/src/cmd/gofmt/gofmt.go
+++ b/src/cmd/gofmt/gofmt.go
@@ -15,7 +15,6 @@ import (
"go/token"
"io"
"io/fs"
- "io/ioutil"
"os"
"path/filepath"
"runtime"
@@ -74,7 +73,7 @@ func initParserMode() {
}
}
-func isGoFile(f fs.FileInfo) bool {
+func isGoFile(f fs.DirEntry) bool {
// ignore non-Go files
name := f.Name()
return !f.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go")
@@ -137,7 +136,7 @@ func processFile(filename string, in io.Reader, out io.Writer, stdin bool) error
if err != nil {
return err
}
- err = ioutil.WriteFile(filename, res, perm)
+ err = os.WriteFile(filename, res, perm)
if err != nil {
os.Rename(bakname, filename)
return err
@@ -164,7 +163,7 @@ func processFile(filename string, in io.Reader, out io.Writer, stdin bool) error
return err
}
-func visitFile(path string, f fs.FileInfo, err error) error {
+func visitFile(path string, f fs.DirEntry, err error) error {
if err == nil && isGoFile(f) {
err = processFile(path, nil, os.Stdout, false)
}
@@ -177,7 +176,7 @@ func visitFile(path string, f fs.FileInfo, err error) error {
}
func walkDir(path string) {
- filepath.Walk(path, visitFile)
+ filepath.WalkDir(path, visitFile)
}
func main() {
@@ -278,7 +277,7 @@ const chmodSupported = runtime.GOOS != "windows"
// the chosen file name.
func backupFile(filename string, data []byte, perm fs.FileMode) (string, error) {
// create backup file
- f, err := ioutil.TempFile(filepath.Dir(filename), filepath.Base(filename))
+ f, err := os.CreateTemp(filepath.Dir(filename), filepath.Base(filename))
if err != nil {
return "", err
}
diff --git a/src/cmd/gofmt/gofmt_test.go b/src/cmd/gofmt/gofmt_test.go
index 98d3eb7eb2..bf2adfe64c 100644
--- a/src/cmd/gofmt/gofmt_test.go
+++ b/src/cmd/gofmt/gofmt_test.go
@@ -7,7 +7,6 @@ package main
import (
"bytes"
"flag"
- "io/ioutil"
"os"
"os/exec"
"path/filepath"
@@ -93,7 +92,7 @@ func runTest(t *testing.T, in, out string) {
return
}
- expected, err := ioutil.ReadFile(out)
+ expected, err := os.ReadFile(out)
if err != nil {
t.Error(err)
return
@@ -102,7 +101,7 @@ func runTest(t *testing.T, in, out string) {
if got := buf.Bytes(); !bytes.Equal(got, expected) {
if *update {
if in != out {
- if err := ioutil.WriteFile(out, got, 0666); err != nil {
+ if err := os.WriteFile(out, got, 0666); err != nil {
t.Error(err)
}
return
@@ -116,7 +115,7 @@ func runTest(t *testing.T, in, out string) {
if err == nil {
t.Errorf("%s", d)
}
- if err := ioutil.WriteFile(in+".gofmt", got, 0666); err != nil {
+ if err := os.WriteFile(in+".gofmt", got, 0666); err != nil {
t.Error(err)
}
}
@@ -157,7 +156,7 @@ func TestCRLF(t *testing.T) {
const input = "testdata/crlf.input" // must contain CR/LF's
const golden = "testdata/crlf.golden" // must not contain any CR's
- data, err := ioutil.ReadFile(input)
+ data, err := os.ReadFile(input)
if err != nil {
t.Error(err)
}
@@ -165,7 +164,7 @@ func TestCRLF(t *testing.T) {
t.Errorf("%s contains no CR/LF's", input)
}
- data, err = ioutil.ReadFile(golden)
+ data, err = os.ReadFile(golden)
if err != nil {
t.Error(err)
}
@@ -175,7 +174,7 @@ func TestCRLF(t *testing.T) {
}
func TestBackupFile(t *testing.T) {
- dir, err := ioutil.TempDir("", "gofmt_test")
+ dir, err := os.MkdirTemp("", "gofmt_test")
if err != nil {
t.Fatal(err)
}
diff --git a/src/cmd/gofmt/long_test.go b/src/cmd/gofmt/long_test.go
index 28306ce83e..4a821705f1 100644
--- a/src/cmd/gofmt/long_test.go
+++ b/src/cmd/gofmt/long_test.go
@@ -108,12 +108,12 @@ func testFiles(t *testing.T, filenames <-chan string, done chan<- int) {
func genFilenames(t *testing.T, filenames chan<- string) {
defer close(filenames)
- handleFile := func(filename string, fi fs.FileInfo, err error) error {
+ handleFile := func(filename string, d fs.DirEntry, err error) error {
if err != nil {
t.Error(err)
return nil
}
- if isGoFile(fi) {
+ if isGoFile(d) {
filenames <- filename
nfiles++
}
@@ -124,13 +124,13 @@ func genFilenames(t *testing.T, filenames chan<- string) {
if *files != "" {
for _, filename := range strings.Split(*files, ",") {
fi, err := os.Stat(filename)
- handleFile(filename, fi, err)
+ handleFile(filename, &statDirEntry{fi}, err)
}
return // ignore files under -root
}
// otherwise, test all Go files under *root
- filepath.Walk(*root, handleFile)
+ filepath.WalkDir(*root, handleFile)
}
func TestAll(t *testing.T) {
@@ -164,3 +164,12 @@ func TestAll(t *testing.T) {
fmt.Printf("processed %d files\n", nfiles)
}
}
+
+type statDirEntry struct {
+ info fs.FileInfo
+}
+
+func (d *statDirEntry) Name() string { return d.info.Name() }
+func (d *statDirEntry) IsDir() bool { return d.info.IsDir() }
+func (d *statDirEntry) Type() fs.FileMode { return d.info.Mode().Type() }
+func (d *statDirEntry) Info() (fs.FileInfo, error) { return d.info, nil }
diff --git a/src/cmd/internal/buildid/buildid_test.go b/src/cmd/internal/buildid/buildid_test.go
index 904c2c6f37..e832f9987e 100644
--- a/src/cmd/internal/buildid/buildid_test.go
+++ b/src/cmd/internal/buildid/buildid_test.go
@@ -11,6 +11,7 @@ import (
"io/ioutil"
"os"
"reflect"
+ "strings"
"testing"
)
@@ -146,3 +147,33 @@ func TestFindAndHash(t *testing.T) {
}
}
}
+
+func TestExcludedReader(t *testing.T) {
+ const s = "0123456789abcdefghijklmn"
+ tests := []struct {
+ start, end int64 // excluded range
+ results []string // expected results of reads
+ }{
+ {12, 15, []string{"0123456789", "ab\x00\x00\x00fghij", "klmn"}}, // within one read
+ {8, 21, []string{"01234567\x00\x00", "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x00lmn"}}, // across multiple reads
+ {10, 20, []string{"0123456789", "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", "klmn"}}, // a whole read
+ {0, 5, []string{"\x00\x00\x00\x00\x0056789", "abcdefghij", "klmn"}}, // start
+ {12, 24, []string{"0123456789", "ab\x00\x00\x00\x00\x00\x00\x00\x00", "\x00\x00\x00\x00"}}, // end
+ }
+ p := make([]byte, 10)
+ for _, test := range tests {
+ r := &excludedReader{strings.NewReader(s), 0, test.start, test.end}
+ for _, res := range test.results {
+ n, err := r.Read(p)
+ if err != nil {
+ t.Errorf("read failed: %v", err)
+ }
+ if n != len(res) {
+ t.Errorf("unexpected number of bytes read: want %d, got %d", len(res), n)
+ }
+ if string(p[:n]) != res {
+ t.Errorf("unexpected bytes: want %q, got %q", res, p[:n])
+ }
+ }
+ }
+}
diff --git a/src/cmd/internal/buildid/rewrite.go b/src/cmd/internal/buildid/rewrite.go
index 5be54552a6..a7928959c4 100644
--- a/src/cmd/internal/buildid/rewrite.go
+++ b/src/cmd/internal/buildid/rewrite.go
@@ -6,7 +6,9 @@ package buildid
import (
"bytes"
+ "cmd/internal/codesign"
"crypto/sha256"
+ "debug/macho"
"fmt"
"io"
)
@@ -26,6 +28,11 @@ func FindAndHash(r io.Reader, id string, bufSize int) (matches []int64, hash [32
zeros := make([]byte, len(id))
idBytes := []byte(id)
+ // For Mach-O files, we want to exclude the code signature.
+ // The code signature contains hashes of the whole file (except the signature
+ // itself), including the buildid. So the buildid cannot contain the signature.
+ r = excludeMachoCodeSignature(r)
+
// The strategy is to read the file through buf, looking for id,
// but we need to worry about what happens if id is broken up
// and returned in parts by two different reads.
@@ -87,5 +94,69 @@ func Rewrite(w io.WriterAt, pos []int64, id string) error {
return err
}
}
+
+ // Update Mach-O code signature, if any.
+ if f, cmd, ok := findMachoCodeSignature(w); ok {
+ if codesign.Size(int64(cmd.Dataoff), "a.out") == int64(cmd.Datasize) {
+ // Update the signature if the size matches, so we don't need to
+ // fix up headers. Binaries generated by the Go linker should have
+ // the expected size. Otherwise skip.
+ text := f.Segment("__TEXT")
+ cs := make([]byte, cmd.Datasize)
+ codesign.Sign(cs, w.(io.Reader), "a.out", int64(cmd.Dataoff), int64(text.Offset), int64(text.Filesz), f.Type == macho.TypeExec)
+ if _, err := w.WriteAt(cs, int64(cmd.Dataoff)); err != nil {
+ return err
+ }
+ }
+ }
+
return nil
}
+
+func excludeMachoCodeSignature(r io.Reader) io.Reader {
+ _, cmd, ok := findMachoCodeSignature(r)
+ if !ok {
+ return r
+ }
+ return &excludedReader{r, 0, int64(cmd.Dataoff), int64(cmd.Dataoff + cmd.Datasize)}
+}
+
+// excludedReader wraps an io.Reader. Reading from it returns the bytes from
+// the underlying reader, except that when the byte offset is within the
+// range between start and end, it returns zero bytes.
+type excludedReader struct {
+ r io.Reader
+ off int64 // current offset
+ start, end int64 // the range to be excluded (read as zero)
+}
+
+func (r *excludedReader) Read(p []byte) (int, error) {
+ n, err := r.r.Read(p)
+ if n > 0 && r.off+int64(n) > r.start && r.off < r.end {
+ cstart := r.start - r.off
+ if cstart < 0 {
+ cstart = 0
+ }
+ cend := r.end - r.off
+ if cend > int64(n) {
+ cend = int64(n)
+ }
+ zeros := make([]byte, cend-cstart)
+ copy(p[cstart:cend], zeros)
+ }
+ r.off += int64(n)
+ return n, err
+}
+
+func findMachoCodeSignature(r interface{}) (*macho.File, codesign.CodeSigCmd, bool) {
+ ra, ok := r.(io.ReaderAt)
+ if !ok {
+ return nil, codesign.CodeSigCmd{}, false
+ }
+ f, err := macho.NewFile(ra)
+ if err != nil {
+ return nil, codesign.CodeSigCmd{}, false
+ }
+ cmd, ok := codesign.FindCodeSigCmd(f)
+ return f, cmd, ok
+}
diff --git a/src/cmd/internal/codesign/codesign.go b/src/cmd/internal/codesign/codesign.go
new file mode 100644
index 0000000000..0517a10640
--- /dev/null
+++ b/src/cmd/internal/codesign/codesign.go
@@ -0,0 +1,268 @@
+// Copyright 2020 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 codesign provides basic functionalities for
+// ad-hoc code signing of Mach-O files.
+//
+// This is not a general tool for code-signing. It is made
+// specifically for the Go toolchain. It uses the same
+// ad-hoc signing algorithm as the Darwin linker.
+package codesign
+
+import (
+ "crypto/sha256"
+ "debug/macho"
+ "encoding/binary"
+ "io"
+)
+
+// Code signature layout.
+//
+// The code signature is a block of bytes that contains
+// a SuperBlob, which contains one or more Blobs. For ad-hoc
+// signing, a single CodeDirectory Blob suffices.
+//
+// A SuperBlob starts with its header (the binary representation
+// of the SuperBlob struct), followed by a list of (in our case,
+// one) Blobs (offset and size). A CodeDirectory Blob starts
+// with its head (the binary representation of CodeDirectory struct),
+// followed by the identifier (as a C string) and the hashes, at
+// the corresponding offsets.
+//
+// The signature data must be included in the __LINKEDIT segment.
+// In the Mach-O file header, an LC_CODE_SIGNATURE load command
+// points to the data.
+
+const (
+ pageSizeBits = 12
+ pageSize = 1 << pageSizeBits
+)
+
+const LC_CODE_SIGNATURE = 0x1d
+
+// Constants and struct layouts are from
+// https://opensource.apple.com/source/xnu/xnu-4903.270.47/osfmk/kern/cs_blobs.h
+
+const (
+ CSMAGIC_REQUIREMENT = 0xfade0c00 // single Requirement blob
+ CSMAGIC_REQUIREMENTS = 0xfade0c01 // Requirements vector (internal requirements)
+ CSMAGIC_CODEDIRECTORY = 0xfade0c02 // CodeDirectory blob
+ CSMAGIC_EMBEDDED_SIGNATURE = 0xfade0cc0 // embedded form of signature data
+ CSMAGIC_DETACHED_SIGNATURE = 0xfade0cc1 // multi-arch collection of embedded signatures
+
+ CSSLOT_CODEDIRECTORY = 0 // slot index for CodeDirectory
+)
+
+const (
+ CS_HASHTYPE_SHA1 = 1
+ CS_HASHTYPE_SHA256 = 2
+ CS_HASHTYPE_SHA256_TRUNCATED = 3
+ CS_HASHTYPE_SHA384 = 4
+)
+
+const (
+ CS_EXECSEG_MAIN_BINARY = 0x1 // executable segment denotes main binary
+ CS_EXECSEG_ALLOW_UNSIGNED = 0x10 // allow unsigned pages (for debugging)
+ CS_EXECSEG_DEBUGGER = 0x20 // main binary is debugger
+ CS_EXECSEG_JIT = 0x40 // JIT enabled
+ CS_EXECSEG_SKIP_LV = 0x80 // skip library validation
+ CS_EXECSEG_CAN_LOAD_CDHASH = 0x100 // can bless cdhash for execution
+ CS_EXECSEG_CAN_EXEC_CDHASH = 0x200 // can execute blessed cdhash
+)
+
+type Blob struct {
+ typ uint32 // type of entry
+ offset uint32 // offset of entry
+ // data follows
+}
+
+func (b *Blob) put(out []byte) []byte {
+ out = put32be(out, b.typ)
+ out = put32be(out, b.offset)
+ return out
+}
+
+const blobSize = 2 * 4
+
+type SuperBlob struct {
+ magic uint32 // magic number
+ length uint32 // total length of SuperBlob
+ count uint32 // number of index entries following
+ // blobs []Blob
+}
+
+func (s *SuperBlob) put(out []byte) []byte {
+ out = put32be(out, s.magic)
+ out = put32be(out, s.length)
+ out = put32be(out, s.count)
+ return out
+}
+
+const superBlobSize = 3 * 4
+
+type CodeDirectory struct {
+ magic uint32 // magic number (CSMAGIC_CODEDIRECTORY)
+ length uint32 // total length of CodeDirectory blob
+ version uint32 // compatibility version
+ flags uint32 // setup and mode flags
+ hashOffset uint32 // offset of hash slot element at index zero
+ identOffset uint32 // offset of identifier string
+ nSpecialSlots uint32 // number of special hash slots
+ nCodeSlots uint32 // number of ordinary (code) hash slots
+ codeLimit uint32 // limit to main image signature range
+ hashSize uint8 // size of each hash in bytes
+ hashType uint8 // type of hash (cdHashType* constants)
+ _pad1 uint8 // unused (must be zero)
+ pageSize uint8 // log2(page size in bytes); 0 => infinite
+ _pad2 uint32 // unused (must be zero)
+ scatterOffset uint32
+ teamOffset uint32
+ _pad3 uint32
+ codeLimit64 uint64
+ execSegBase uint64
+ execSegLimit uint64
+ execSegFlags uint64
+ // data follows
+}
+
+func (c *CodeDirectory) put(out []byte) []byte {
+ out = put32be(out, c.magic)
+ out = put32be(out, c.length)
+ out = put32be(out, c.version)
+ out = put32be(out, c.flags)
+ out = put32be(out, c.hashOffset)
+ out = put32be(out, c.identOffset)
+ out = put32be(out, c.nSpecialSlots)
+ out = put32be(out, c.nCodeSlots)
+ out = put32be(out, c.codeLimit)
+ out = put8(out, c.hashSize)
+ out = put8(out, c.hashType)
+ out = put8(out, c._pad1)
+ out = put8(out, c.pageSize)
+ out = put32be(out, c._pad2)
+ out = put32be(out, c.scatterOffset)
+ out = put32be(out, c.teamOffset)
+ out = put32be(out, c._pad3)
+ out = put64be(out, c.codeLimit64)
+ out = put64be(out, c.execSegBase)
+ out = put64be(out, c.execSegLimit)
+ out = put64be(out, c.execSegFlags)
+ return out
+}
+
+const codeDirectorySize = 13*4 + 4 + 4*8
+
+// CodeSigCmd is Mach-O LC_CODE_SIGNATURE load command.
+type CodeSigCmd struct {
+ Cmd uint32 // LC_CODE_SIGNATURE
+ Cmdsize uint32 // sizeof this command (16)
+ Dataoff uint32 // file offset of data in __LINKEDIT segment
+ Datasize uint32 // file size of data in __LINKEDIT segment
+}
+
+func FindCodeSigCmd(f *macho.File) (CodeSigCmd, bool) {
+ get32 := f.ByteOrder.Uint32
+ for _, l := range f.Loads {
+ data := l.Raw()
+ cmd := get32(data)
+ if cmd == LC_CODE_SIGNATURE {
+ return CodeSigCmd{
+ cmd,
+ get32(data[4:]),
+ get32(data[8:]),
+ get32(data[12:]),
+ }, true
+ }
+ }
+ return CodeSigCmd{}, false
+}
+
+func put32be(b []byte, x uint32) []byte { binary.BigEndian.PutUint32(b, x); return b[4:] }
+func put64be(b []byte, x uint64) []byte { binary.BigEndian.PutUint64(b, x); return b[8:] }
+func put8(b []byte, x uint8) []byte { b[0] = x; return b[1:] }
+func puts(b, s []byte) []byte { n := copy(b, s); return b[n:] }
+
+// Size computes the size of the code signature.
+// id is the identifier used for signing (a field in CodeDirectory blob, which
+// has no significance in ad-hoc signing).
+func Size(codeSize int64, id string) int64 {
+ nhashes := (codeSize + pageSize - 1) / pageSize
+ idOff := int64(codeDirectorySize)
+ hashOff := idOff + int64(len(id)+1)
+ cdirSz := hashOff + nhashes*sha256.Size
+ return int64(superBlobSize+blobSize) + cdirSz
+}
+
+// Sign generates an ad-hoc code signature and writes it to out.
+// out must have length at least Size(codeSize, id).
+// data is the file content without the signature, of size codeSize.
+// textOff and textSize is the file offset and size of the text segment.
+// isMain is true if this is a main executable.
+// id is the identifier used for signing (a field in CodeDirectory blob, which
+// has no significance in ad-hoc signing).
+func Sign(out []byte, data io.Reader, id string, codeSize, textOff, textSize int64, isMain bool) {
+ nhashes := (codeSize + pageSize - 1) / pageSize
+ idOff := int64(codeDirectorySize)
+ hashOff := idOff + int64(len(id)+1)
+ sz := Size(codeSize, id)
+
+ // emit blob headers
+ sb := SuperBlob{
+ magic: CSMAGIC_EMBEDDED_SIGNATURE,
+ length: uint32(sz),
+ count: 1,
+ }
+ blob := Blob{
+ typ: CSSLOT_CODEDIRECTORY,
+ offset: superBlobSize + blobSize,
+ }
+ cdir := CodeDirectory{
+ magic: CSMAGIC_CODEDIRECTORY,
+ length: uint32(sz) - (superBlobSize + blobSize),
+ version: 0x20400,
+ flags: 0x20002, // adhoc | linkerSigned
+ hashOffset: uint32(hashOff),
+ identOffset: uint32(idOff),
+ nCodeSlots: uint32(nhashes),
+ codeLimit: uint32(codeSize),
+ hashSize: sha256.Size,
+ hashType: CS_HASHTYPE_SHA256,
+ pageSize: uint8(pageSizeBits),
+ execSegBase: uint64(textOff),
+ execSegLimit: uint64(textSize),
+ }
+ if isMain {
+ cdir.execSegFlags = CS_EXECSEG_MAIN_BINARY
+ }
+
+ outp := out
+ outp = sb.put(outp)
+ outp = blob.put(outp)
+ outp = cdir.put(outp)
+
+ // emit the identifier
+ outp = puts(outp, []byte(id+"\000"))
+
+ // emit hashes
+ var buf [pageSize]byte
+ h := sha256.New()
+ p := 0
+ for p < int(codeSize) {
+ n, err := io.ReadFull(data, buf[:])
+ if err == io.EOF {
+ break
+ }
+ if err != nil && err != io.ErrUnexpectedEOF {
+ panic(err)
+ }
+ if p+n > int(codeSize) {
+ n = int(codeSize) - p
+ }
+ p += n
+ h.Reset()
+ h.Write(buf[:n])
+ b := h.Sum(nil)
+ outp = puts(outp, b[:])
+ }
+}
diff --git a/src/cmd/internal/moddeps/moddeps_test.go b/src/cmd/internal/moddeps/moddeps_test.go
index 7362e7868b..9ea21873c5 100644
--- a/src/cmd/internal/moddeps/moddeps_test.go
+++ b/src/cmd/internal/moddeps/moddeps_test.go
@@ -33,7 +33,7 @@ func findGorootModules(t *testing.T) []gorootModule {
goBin := testenv.GoToolPath(t)
goroot.once.Do(func() {
- goroot.err = filepath.Walk(runtime.GOROOT(), func(path string, info fs.FileInfo, err error) error {
+ goroot.err = filepath.WalkDir(runtime.GOROOT(), func(path string, info fs.DirEntry, err error) error {
if err != nil {
return err
}
diff --git a/src/cmd/internal/obj/link.go b/src/cmd/internal/obj/link.go
index 8c8ff587ff..eaebfaf4b6 100644
--- a/src/cmd/internal/obj/link.go
+++ b/src/cmd/internal/obj/link.go
@@ -723,8 +723,8 @@ func (s *LSym) String() string {
}
// The compiler needs *LSym to be assignable to cmd/compile/internal/ssa.Sym.
-func (s *LSym) CanBeAnSSASym() {
-}
+func (*LSym) CanBeAnSSASym() {}
+func (*LSym) CanBeAnSSAAux() {}
type Pcln struct {
// Aux symbols for pcln
diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go
index 0cffa54fa6..9257a6453a 100644
--- a/src/cmd/internal/obj/riscv/obj.go
+++ b/src/cmd/internal/obj/riscv/obj.go
@@ -1777,15 +1777,15 @@ func instructionsForProg(p *obj.Prog) []*instruction {
case ABGEZ:
ins.as, ins.rs1, ins.rs2 = ABGE, REG_ZERO, uint32(p.From.Reg)
case ABGT:
- ins.as, ins.rs1, ins.rs2 = ABLT, uint32(p.Reg), uint32(p.From.Reg)
+ ins.as, ins.rs1, ins.rs2 = ABLT, uint32(p.From.Reg), uint32(p.Reg)
case ABGTU:
- ins.as, ins.rs1, ins.rs2 = ABLTU, uint32(p.Reg), uint32(p.From.Reg)
+ ins.as, ins.rs1, ins.rs2 = ABLTU, uint32(p.From.Reg), uint32(p.Reg)
case ABGTZ:
ins.as, ins.rs1, ins.rs2 = ABLT, uint32(p.From.Reg), REG_ZERO
case ABLE:
- ins.as, ins.rs1, ins.rs2 = ABGE, uint32(p.Reg), uint32(p.From.Reg)
+ ins.as, ins.rs1, ins.rs2 = ABGE, uint32(p.From.Reg), uint32(p.Reg)
case ABLEU:
- ins.as, ins.rs1, ins.rs2 = ABGEU, uint32(p.Reg), uint32(p.From.Reg)
+ ins.as, ins.rs1, ins.rs2 = ABGEU, uint32(p.From.Reg), uint32(p.Reg)
case ABLEZ:
ins.as, ins.rs1, ins.rs2 = ABGE, uint32(p.From.Reg), REG_ZERO
case ABLTZ:
diff --git a/src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.go b/src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.go
index 803ba8c77c..279aeb2c32 100644
--- a/src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.go
+++ b/src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.go
@@ -11,6 +11,8 @@ import (
)
func testBEQZ(a int64) (r bool)
+func testBGE(a, b int64) (r bool)
+func testBGEU(a, b int64) (r bool)
func testBGEZ(a int64) (r bool)
func testBGT(a, b int64) (r bool)
func testBGTU(a, b int64) (r bool)
@@ -18,6 +20,8 @@ func testBGTZ(a int64) (r bool)
func testBLE(a, b int64) (r bool)
func testBLEU(a, b int64) (r bool)
func testBLEZ(a int64) (r bool)
+func testBLT(a, b int64) (r bool)
+func testBLTU(a, b int64) (r bool)
func testBLTZ(a int64) (r bool)
func testBNEZ(a int64) (r bool)
@@ -29,30 +33,75 @@ func TestBranchCondition(t *testing.T) {
fn func(a, b int64) bool
want bool
}{
- {"BGT", 0, 1, testBGT, true},
+ {"BGE", 0, 1, testBGE, false},
+ {"BGE", 0, 0, testBGE, true},
+ {"BGE", 0, -1, testBGE, true},
+ {"BGE", -1, 0, testBGE, false},
+ {"BGE", 1, 0, testBGE, true},
+ {"BGEU", 0, 1, testBGEU, false},
+ {"BGEU", 0, 0, testBGEU, true},
+ {"BGEU", 0, -1, testBGEU, false},
+ {"BGEU", -1, 0, testBGEU, true},
+ {"BGEU", 1, 0, testBGEU, true},
+ {"BGT", 0, 1, testBGT, false},
{"BGT", 0, 0, testBGT, false},
- {"BGT", 0, -1, testBGT, false},
- {"BGT", -1, 0, testBGT, true},
- {"BGT", 1, 0, testBGT, false},
- {"BGTU", 0, 1, testBGTU, true},
- {"BGTU", 0, -1, testBGTU, true},
- {"BGTU", -1, 0, testBGTU, false},
- {"BGTU", 1, 0, testBGTU, false},
- {"BLE", 0, 1, testBLE, false},
- {"BLE", 0, -1, testBLE, true},
+ {"BGT", 0, -1, testBGT, true},
+ {"BGT", -1, 0, testBGT, false},
+ {"BGT", 1, 0, testBGT, true},
+ {"BGTU", 0, 1, testBGTU, false},
+ {"BGTU", 0, 0, testBGTU, false},
+ {"BGTU", 0, -1, testBGTU, false},
+ {"BGTU", -1, 0, testBGTU, true},
+ {"BGTU", 1, 0, testBGTU, true},
+ {"BLE", 0, 1, testBLE, true},
{"BLE", 0, 0, testBLE, true},
- {"BLE", -1, 0, testBLE, false},
- {"BLE", 1, 0, testBLE, true},
- {"BLEU", 0, 1, testBLEU, false},
- {"BLEU", 0, -1, testBLEU, false},
+ {"BLE", 0, -1, testBLE, false},
+ {"BLE", -1, 0, testBLE, true},
+ {"BLE", 1, 0, testBLE, false},
+ {"BLEU", 0, 1, testBLEU, true},
{"BLEU", 0, 0, testBLEU, true},
- {"BLEU", -1, 0, testBLEU, true},
- {"BLEU", 1, 0, testBLEU, true},
+ {"BLEU", 0, -1, testBLEU, true},
+ {"BLEU", -1, 0, testBLEU, false},
+ {"BLEU", 1, 0, testBLEU, false},
+ {"BLT", 0, 1, testBLT, true},
+ {"BLT", 0, 0, testBLT, false},
+ {"BLT", 0, -1, testBLT, false},
+ {"BLT", -1, 0, testBLT, true},
+ {"BLT", 1, 0, testBLT, false},
+ {"BLTU", 0, 1, testBLTU, true},
+ {"BLTU", 0, 0, testBLTU, false},
+ {"BLTU", 0, -1, testBLTU, true},
+ {"BLTU", -1, 0, testBLTU, false},
+ {"BLTU", 1, 0, testBLTU, false},
}
for _, test := range tests {
t.Run(test.ins, func(t *testing.T) {
+ var fn func(a, b int64) bool
+ switch test.ins {
+ case "BGE":
+ fn = func(a, b int64) bool { return a >= b }
+ case "BGEU":
+ fn = func(a, b int64) bool { return uint64(a) >= uint64(b) }
+ case "BGT":
+ fn = func(a, b int64) bool { return a > b }
+ case "BGTU":
+ fn = func(a, b int64) bool { return uint64(a) > uint64(b) }
+ case "BLE":
+ fn = func(a, b int64) bool { return a <= b }
+ case "BLEU":
+ fn = func(a, b int64) bool { return uint64(a) <= uint64(b) }
+ case "BLT":
+ fn = func(a, b int64) bool { return a < b }
+ case "BLTU":
+ fn = func(a, b int64) bool { return uint64(a) < uint64(b) }
+ default:
+ t.Fatalf("Unknown instruction %q", test.ins)
+ }
+ if got := fn(test.a, test.b); got != test.want {
+ t.Errorf("Go %v %v, %v = %v, want %v", test.ins, test.a, test.b, got, test.want)
+ }
if got := test.fn(test.a, test.b); got != test.want {
- t.Errorf("%v %v, %v = %v, want %v", test.ins, test.a, test.b, got, test.want)
+ t.Errorf("Assembly %v %v, %v = %v, want %v", test.ins, test.a, test.b, got, test.want)
}
})
}
diff --git a/src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.s b/src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.s
index 6cff235848..8dd6f563af 100644
--- a/src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.s
+++ b/src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.s
@@ -16,6 +16,28 @@ b:
MOV X6, r+8(FP)
RET
+// func testBGE(a, b int64) (r bool)
+TEXT ·testBGE(SB),NOSPLIT,$0-0
+ MOV a+0(FP), X5
+ MOV b+8(FP), X6
+ MOV $1, X7
+ BGE X5, X6, b
+ MOV $0, X7
+b:
+ MOV X7, r+16(FP)
+ RET
+
+// func testBGEU(a, b int64) (r bool)
+TEXT ·testBGEU(SB),NOSPLIT,$0-0
+ MOV a+0(FP), X5
+ MOV b+8(FP), X6
+ MOV $1, X7
+ BGEU X5, X6, b
+ MOV $0, X7
+b:
+ MOV X7, r+16(FP)
+ RET
+
// func testBGEZ(a int64) (r bool)
TEXT ·testBGEZ(SB),NOSPLIT,$0-0
MOV a+0(FP), X5
@@ -90,6 +112,28 @@ b:
MOV X6, r+8(FP)
RET
+// func testBLT(a, b int64) (r bool)
+TEXT ·testBLT(SB),NOSPLIT,$0-0
+ MOV a+0(FP), X5
+ MOV b+8(FP), X6
+ MOV $1, X7
+ BLT X5, X6, b
+ MOV $0, X7
+b:
+ MOV X7, r+16(FP)
+ RET
+
+// func testBLTU(a, b int64) (r bool)
+TEXT ·testBLTU(SB),NOSPLIT,$0-0
+ MOV a+0(FP), X5
+ MOV b+8(FP), X6
+ MOV $1, X7
+ BLTU X5, X6, b
+ MOV $0, X7
+b:
+ MOV X7, r+16(FP)
+ RET
+
// func testBLTZ(a int64) (r bool)
TEXT ·testBLTZ(SB),NOSPLIT,$0-0
MOV a+0(FP), X5
diff --git a/src/cmd/internal/obj/s390x/condition_code.go b/src/cmd/internal/obj/s390x/condition_code.go
index 764fc5bc6a..f498fd6f77 100644
--- a/src/cmd/internal/obj/s390x/condition_code.go
+++ b/src/cmd/internal/obj/s390x/condition_code.go
@@ -124,3 +124,5 @@ func (c CCMask) String() string {
// invalid
return fmt.Sprintf("Invalid (%#x)", c)
}
+
+func (CCMask) CanBeAnSSAAux() {}
diff --git a/src/cmd/internal/obj/s390x/rotate.go b/src/cmd/internal/obj/s390x/rotate.go
index 7dbc45e648..c999880492 100644
--- a/src/cmd/internal/obj/s390x/rotate.go
+++ b/src/cmd/internal/obj/s390x/rotate.go
@@ -113,3 +113,5 @@ func (r RotateParams) OutMerge(mask uint64) *RotateParams {
func (r RotateParams) InMerge(mask uint64) *RotateParams {
return r.OutMerge(bits.RotateLeft64(mask, int(r.Amount)))
}
+
+func (RotateParams) CanBeAnSSAAux() {}
diff --git a/src/cmd/link/internal/amd64/asm.go b/src/cmd/link/internal/amd64/asm.go
index 360c5338ba..2d09a6160a 100644
--- a/src/cmd/link/internal/amd64/asm.go
+++ b/src/cmd/link/internal/amd64/asm.go
@@ -413,11 +413,7 @@ func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym,
case objabi.R_CALL:
if siz == 4 {
if ldr.SymType(r.Xsym) == sym.SDYNIMPORT {
- if ctxt.DynlinkingGo() {
- out.Write64(uint64(elf.R_X86_64_PLT32) | uint64(elfsym)<<32)
- } else {
- out.Write64(uint64(elf.R_X86_64_GOTPCREL) | uint64(elfsym)<<32)
- }
+ out.Write64(uint64(elf.R_X86_64_PLT32) | uint64(elfsym)<<32)
} else {
out.Write64(uint64(elf.R_X86_64_PC32) | uint64(elfsym)<<32)
}
diff --git a/src/cmd/link/internal/ld/config.go b/src/cmd/link/internal/ld/config.go
index 0cb3cc25c0..d1e06239a5 100644
--- a/src/cmd/link/internal/ld/config.go
+++ b/src/cmd/link/internal/ld/config.go
@@ -35,11 +35,12 @@ func (mode *BuildMode) Set(s string) error {
default:
return fmt.Errorf("invalid buildmode: %q", s)
case "exe":
- if objabi.GOOS == "darwin" && objabi.GOARCH == "arm64" {
- *mode = BuildModePIE // On darwin/arm64 everything is PIE.
- break
+ switch objabi.GOOS + "/" + objabi.GOARCH {
+ case "darwin/arm64", "windows/arm": // On these platforms, everything is PIE
+ *mode = BuildModePIE
+ default:
+ *mode = BuildModeExe
}
- *mode = BuildModeExe
case "pie":
switch objabi.GOOS {
case "aix", "android", "linux", "windows", "darwin", "ios":
diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go
index 735b84d37d..e1cc7184de 100644
--- a/src/cmd/link/internal/ld/lib.go
+++ b/src/cmd/link/internal/ld/lib.go
@@ -298,6 +298,11 @@ func (ctxt *Link) CanUsePlugins() bool {
return ctxt.canUsePlugins
}
+// NeedCodeSign reports whether we need to code-sign the output binary.
+func (ctxt *Link) NeedCodeSign() bool {
+ return ctxt.IsDarwin() && ctxt.IsARM64()
+}
+
var (
dynlib []string
ldflag []string
@@ -1642,6 +1647,12 @@ func (ctxt *Link) hostlink() {
Exitf("%s: %v", os.Args[0], err)
}
}
+ if ctxt.NeedCodeSign() {
+ err := machoCodeSign(ctxt, *flagOutfile)
+ if err != nil {
+ Exitf("%s: code signing failed: %v", os.Args[0], err)
+ }
+ }
}
var createTrivialCOnce sync.Once
diff --git a/src/cmd/link/internal/ld/macho.go b/src/cmd/link/internal/ld/macho.go
index 51abefc887..f459576420 100644
--- a/src/cmd/link/internal/ld/macho.go
+++ b/src/cmd/link/internal/ld/macho.go
@@ -6,6 +6,7 @@ package ld
import (
"bytes"
+ "cmd/internal/codesign"
"cmd/internal/objabi"
"cmd/internal/sys"
"cmd/link/internal/loader"
@@ -17,6 +18,7 @@ import (
"os"
"sort"
"strings"
+ "unsafe"
)
type MachoHdr struct {
@@ -245,6 +247,8 @@ const (
BIND_SUBOPCODE_THREADED_APPLY = 0x01
)
+const machoHeaderSize64 = 8 * 4 // size of 64-bit Mach-O header
+
// Mach-O file writing
// https://developer.apple.com/mac/library/DOCUMENTATION/DeveloperTools/Conceptual/MachORuntime/Reference/reference.html
@@ -643,6 +647,8 @@ func asmbMacho(ctxt *Link) {
}
ctxt.Out.SeekSet(0)
+ ldr := ctxt.loader
+
/* apple MACH */
va := *FlagTextAddr - int64(HEADR)
@@ -757,25 +763,27 @@ func asmbMacho(ctxt *Link) {
}
}
+ var codesigOff int64
if !*FlagD {
- ldr := ctxt.loader
-
- // must match domacholink below
+ // must match doMachoLink below
s1 := ldr.SymSize(ldr.Lookup(".machorebase", 0))
s2 := ldr.SymSize(ldr.Lookup(".machobind", 0))
s3 := ldr.SymSize(ldr.Lookup(".machosymtab", 0))
s4 := ldr.SymSize(ctxt.ArchSyms.LinkEditPLT)
s5 := ldr.SymSize(ctxt.ArchSyms.LinkEditGOT)
s6 := ldr.SymSize(ldr.Lookup(".machosymstr", 0))
+ s7 := ldr.SymSize(ldr.Lookup(".machocodesig", 0))
if ctxt.LinkMode != LinkExternal {
ms := newMachoSeg("__LINKEDIT", 0)
ms.vaddr = uint64(Rnd(int64(Segdata.Vaddr+Segdata.Length), int64(*FlagRound)))
- ms.vsize = uint64(s1 + s2 + s3 + s4 + s5 + s6)
+ ms.vsize = uint64(s1 + s2 + s3 + s4 + s5 + s6 + s7)
ms.fileoffset = uint64(linkoff)
ms.filesize = ms.vsize
ms.prot1 = 1
ms.prot2 = 1
+
+ codesigOff = linkoff + s1 + s2 + s3 + s4 + s5 + s6
}
if ctxt.LinkMode != LinkExternal && ctxt.IsPIE() {
@@ -814,12 +822,31 @@ func asmbMacho(ctxt *Link) {
stringtouint32(ml.data[4:], lib)
}
}
+
+ if ctxt.IsInternal() && ctxt.NeedCodeSign() {
+ ml := newMachoLoad(ctxt.Arch, LC_CODE_SIGNATURE, 2)
+ ml.data[0] = uint32(codesigOff)
+ ml.data[1] = uint32(s7)
+ }
}
a := machowrite(ctxt, ctxt.Arch, ctxt.Out, ctxt.LinkMode)
if int32(a) > HEADR {
Exitf("HEADR too small: %d > %d", a, HEADR)
}
+
+ // Now we have written everything. Compute the code signature (which
+ // is a hash of the file content, so it must be done at last.)
+ if ctxt.IsInternal() && ctxt.NeedCodeSign() {
+ cs := ldr.Lookup(".machocodesig", 0)
+ data := ctxt.Out.Data()
+ if int64(len(data)) != codesigOff {
+ panic("wrong size")
+ }
+ codesign.Sign(ldr.Data(cs), bytes.NewReader(data), "a.out", codesigOff, int64(Segtext.Fileoff), int64(Segtext.Filelen), ctxt.IsExe() || ctxt.IsPIE())
+ ctxt.Out.SeekSet(codesigOff)
+ ctxt.Out.Write(ldr.Data(cs))
+ }
}
func symkind(ldr *loader.Loader, s loader.Sym) int {
@@ -1057,7 +1084,6 @@ func machodysymtab(ctxt *Link, base int64) {
func doMachoLink(ctxt *Link) int64 {
machosymtab(ctxt)
-
machoDyldInfo(ctxt)
ldr := ctxt.loader
@@ -1070,6 +1096,8 @@ func doMachoLink(ctxt *Link) int64 {
s5 := ctxt.ArchSyms.LinkEditGOT
s6 := ldr.Lookup(".machosymstr", 0)
+ size := ldr.SymSize(s1) + ldr.SymSize(s2) + ldr.SymSize(s3) + ldr.SymSize(s4) + ldr.SymSize(s5) + ldr.SymSize(s6)
+
// Force the linkedit section to end on a 16-byte
// boundary. This allows pure (non-cgo) Go binaries
// to be code signed correctly.
@@ -1087,13 +1115,14 @@ func doMachoLink(ctxt *Link) int64 {
// boundary, codesign_allocate will not need to apply
// any alignment padding itself, working around the
// issue.
- s6b := ldr.MakeSymbolUpdater(s6)
- for s6b.Size()%16 != 0 {
- s6b.AddUint8(0)
+ if size%16 != 0 {
+ n := 16 - size%16
+ s6b := ldr.MakeSymbolUpdater(s6)
+ s6b.Grow(s6b.Size() + n)
+ s6b.SetSize(s6b.Size() + n)
+ size += n
}
- size := int(ldr.SymSize(s1) + ldr.SymSize(s2) + ldr.SymSize(s3) + ldr.SymSize(s4) + ldr.SymSize(s5) + ldr.SymSize(s6))
-
if size > 0 {
linkoff = Rnd(int64(uint64(HEADR)+Segtext.Length), int64(*FlagRound)) + Rnd(int64(Segrelrodata.Filelen), int64(*FlagRound)) + Rnd(int64(Segdata.Filelen), int64(*FlagRound)) + Rnd(int64(Segdwarf.Filelen), int64(*FlagRound))
ctxt.Out.SeekSet(linkoff)
@@ -1104,9 +1133,13 @@ func doMachoLink(ctxt *Link) int64 {
ctxt.Out.Write(ldr.Data(s4))
ctxt.Out.Write(ldr.Data(s5))
ctxt.Out.Write(ldr.Data(s6))
+
+ // Add code signature if necessary. This must be the last.
+ s7 := machoCodeSigSym(ctxt, linkoff+size)
+ size += ldr.SymSize(s7)
}
- return Rnd(int64(size), int64(*FlagRound))
+ return Rnd(size, int64(*FlagRound))
}
func machorelocsect(ctxt *Link, out *OutBuf, sect *sym.Section, syms []loader.Sym) {
@@ -1378,3 +1411,94 @@ func machoDyldInfo(ctxt *Link) {
// e.g. dlsym'd. But internal linking is not the default in that case, so
// it is fine.
}
+
+// machoCodeSigSym creates and returns a symbol for code signature.
+// The symbol context is left as zeros, which will be generated at the end
+// (as it depends on the rest of the file).
+func machoCodeSigSym(ctxt *Link, codeSize int64) loader.Sym {
+ ldr := ctxt.loader
+ cs := ldr.CreateSymForUpdate(".machocodesig", 0)
+ if !ctxt.NeedCodeSign() || ctxt.IsExternal() {
+ return cs.Sym()
+ }
+ sz := codesign.Size(codeSize, "a.out")
+ cs.Grow(sz)
+ cs.SetSize(sz)
+ return cs.Sym()
+}
+
+// machoCodeSign code-signs Mach-O file fname with an ad-hoc signature.
+// This is used for updating an external linker generated binary.
+func machoCodeSign(ctxt *Link, fname string) error {
+ f, err := os.OpenFile(fname, os.O_RDWR, 0)
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+
+ mf, err := macho.NewFile(f)
+ if err != nil {
+ return err
+ }
+ if mf.Magic != macho.Magic64 {
+ Exitf("not 64-bit Mach-O file: %s", fname)
+ }
+
+ // Find existing LC_CODE_SIGNATURE and __LINKEDIT segment
+ var sigOff, sigSz, csCmdOff, linkeditOff int64
+ var linkeditSeg, textSeg *macho.Segment
+ loadOff := int64(machoHeaderSize64)
+ get32 := mf.ByteOrder.Uint32
+ for _, l := range mf.Loads {
+ data := l.Raw()
+ cmd, sz := get32(data), get32(data[4:])
+ if cmd == LC_CODE_SIGNATURE {
+ sigOff = int64(get32(data[8:]))
+ sigSz = int64(get32(data[12:]))
+ csCmdOff = loadOff
+ }
+ if seg, ok := l.(*macho.Segment); ok {
+ switch seg.Name {
+ case "__LINKEDIT":
+ linkeditSeg = seg
+ linkeditOff = loadOff
+ case "__TEXT":
+ textSeg = seg
+ }
+ }
+ loadOff += int64(sz)
+ }
+
+ if sigOff == 0 {
+ // The C linker doesn't generate a signed binary, for some reason.
+ // Skip.
+ return nil
+ }
+ sz := codesign.Size(sigOff, "a.out")
+ if sz != sigSz {
+ // Update the load command,
+ var tmp [8]byte
+ mf.ByteOrder.PutUint32(tmp[:4], uint32(sz))
+ _, err = f.WriteAt(tmp[:4], csCmdOff+12)
+ if err != nil {
+ return err
+ }
+
+ // Uodate the __LINKEDIT segment.
+ segSz := sigOff + sz - int64(linkeditSeg.Offset)
+ mf.ByteOrder.PutUint64(tmp[:8], uint64(segSz))
+ _, err = f.WriteAt(tmp[:8], int64(linkeditOff)+int64(unsafe.Offsetof(macho.Segment64{}.Memsz)))
+ if err != nil {
+ return err
+ }
+ _, err = f.WriteAt(tmp[:8], int64(linkeditOff)+int64(unsafe.Offsetof(macho.Segment64{}.Filesz)))
+ if err != nil {
+ return err
+ }
+ }
+
+ cs := make([]byte, sz)
+ codesign.Sign(cs, f, "a.out", sigOff, int64(textSeg.Offset), int64(textSeg.Filesz), ctxt.IsExe() || ctxt.IsPIE())
+ _, err = f.WriteAt(cs, sigOff)
+ return err
+}
diff --git a/src/cmd/link/internal/ld/outbuf.go b/src/cmd/link/internal/ld/outbuf.go
index 36ec394077..530836ef7c 100644
--- a/src/cmd/link/internal/ld/outbuf.go
+++ b/src/cmd/link/internal/ld/outbuf.go
@@ -113,6 +113,7 @@ func (out *OutBuf) Close() error {
}
if out.isMmapped() {
out.copyHeap()
+ out.purgeSignatureCache()
out.munmap()
}
if out.f == nil {
@@ -135,6 +136,15 @@ func (out *OutBuf) isMmapped() bool {
return len(out.buf) != 0
}
+// Data returns the whole written OutBuf as a byte slice.
+func (out *OutBuf) Data() []byte {
+ if out.isMmapped() {
+ out.copyHeap()
+ return out.buf
+ }
+ return out.heap
+}
+
// copyHeap copies the heap to the mmapped section of memory, returning true if
// a copy takes place.
func (out *OutBuf) copyHeap() bool {
diff --git a/src/cmd/link/internal/ld/outbuf_darwin.go b/src/cmd/link/internal/ld/outbuf_darwin.go
index d7e3372230..9444b6567e 100644
--- a/src/cmd/link/internal/ld/outbuf_darwin.go
+++ b/src/cmd/link/internal/ld/outbuf_darwin.go
@@ -36,3 +36,12 @@ func (out *OutBuf) fallocate(size uint64) error {
return nil
}
+
+func (out *OutBuf) purgeSignatureCache() {
+ // Apparently, the Darwin kernel may cache the code signature at mmap.
+ // When we mmap the output buffer, it doesn't have a code signature
+ // (as we haven't generated one). Invalidate the kernel cache now that
+ // we have generated the signature. See issue #42684.
+ syscall.Syscall(syscall.SYS_MSYNC, uintptr(unsafe.Pointer(&out.buf[0])), uintptr(len(out.buf)), syscall.MS_INVALIDATE)
+ // Best effort. Ignore error.
+}
diff --git a/src/internal/cpu/cpu_android.go b/src/cmd/link/internal/ld/outbuf_notdarwin.go
similarity index 68%
rename from src/internal/cpu/cpu_android.go
rename to src/cmd/link/internal/ld/outbuf_notdarwin.go
index d995e8d5a7..8c5666f216 100644
--- a/src/internal/cpu/cpu_android.go
+++ b/src/cmd/link/internal/ld/outbuf_notdarwin.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package cpu
+// +build !darwin
-const GOOS = "android"
+package ld
+
+func (out *OutBuf) purgeSignatureCache() {}
diff --git a/src/cmd/nm/nm_test.go b/src/cmd/nm/nm_test.go
index 382446e9fe..0d51b07a44 100644
--- a/src/cmd/nm/nm_test.go
+++ b/src/cmd/nm/nm_test.go
@@ -8,7 +8,6 @@ import (
"fmt"
"internal/obscuretestdata"
"internal/testenv"
- "io/ioutil"
"os"
"os/exec"
"path/filepath"
@@ -31,7 +30,7 @@ func testMain(m *testing.M) int {
return 0
}
- tmpDir, err := ioutil.TempDir("", "TestNM")
+ tmpDir, err := os.MkdirTemp("", "TestNM")
if err != nil {
fmt.Println("TempDir failed:", err)
return 2
@@ -88,7 +87,7 @@ func TestNonGoExecs(t *testing.T) {
func testGoExec(t *testing.T, iscgo, isexternallinker bool) {
t.Parallel()
- tmpdir, err := ioutil.TempDir("", "TestGoExec")
+ tmpdir, err := os.MkdirTemp("", "TestGoExec")
if err != nil {
t.Fatal(err)
}
@@ -222,7 +221,7 @@ func TestGoExec(t *testing.T) {
func testGoLib(t *testing.T, iscgo bool) {
t.Parallel()
- tmpdir, err := ioutil.TempDir("", "TestGoLib")
+ tmpdir, err := os.MkdirTemp("", "TestGoLib")
if err != nil {
t.Fatal(err)
}
@@ -245,7 +244,7 @@ func testGoLib(t *testing.T, iscgo bool) {
err = e
}
if err == nil {
- err = ioutil.WriteFile(filepath.Join(libpath, "go.mod"), []byte("module mylib\n"), 0666)
+ err = os.WriteFile(filepath.Join(libpath, "go.mod"), []byte("module mylib\n"), 0666)
}
if err != nil {
t.Fatal(err)
diff --git a/src/cmd/objdump/objdump_test.go b/src/cmd/objdump/objdump_test.go
index cb692e7a81..edaca774f7 100644
--- a/src/cmd/objdump/objdump_test.go
+++ b/src/cmd/objdump/objdump_test.go
@@ -10,7 +10,6 @@ import (
"fmt"
"go/build"
"internal/testenv"
- "io/ioutil"
"os"
"os/exec"
"path/filepath"
@@ -39,7 +38,7 @@ func TestMain(m *testing.M) {
func buildObjdump() error {
var err error
- tmp, err = ioutil.TempDir("", "TestObjDump")
+ tmp, err = os.MkdirTemp("", "TestObjDump")
if err != nil {
return fmt.Errorf("TempDir failed: %v", err)
}
@@ -320,7 +319,7 @@ func TestGoobjFileNumber(t *testing.T) {
t.Parallel()
- tmpdir, err := ioutil.TempDir("", "TestGoobjFileNumber")
+ tmpdir, err := os.MkdirTemp("", "TestGoobjFileNumber")
if err != nil {
t.Fatal(err)
}
diff --git a/src/cmd/pack/pack_test.go b/src/cmd/pack/pack_test.go
index 9f65705def..218c7acda6 100644
--- a/src/cmd/pack/pack_test.go
+++ b/src/cmd/pack/pack_test.go
@@ -12,7 +12,6 @@ import (
"internal/testenv"
"io"
"io/fs"
- "io/ioutil"
"os"
"os/exec"
"path/filepath"
@@ -22,7 +21,7 @@ import (
// tmpDir creates a temporary directory and returns its name.
func tmpDir(t *testing.T) string {
- name, err := ioutil.TempDir("", "pack")
+ name, err := os.MkdirTemp("", "pack")
if err != nil {
t.Fatal(err)
}
@@ -158,7 +157,7 @@ func TestExtract(t *testing.T) {
ar = openArchive(name, os.O_RDONLY, []string{goodbyeFile.name})
ar.scan(ar.extractContents)
ar.a.File().Close()
- data, err := ioutil.ReadFile(goodbyeFile.name)
+ data, err := os.ReadFile(goodbyeFile.name)
if err != nil {
t.Fatal(err)
}
@@ -183,7 +182,7 @@ func TestHello(t *testing.T) {
println("hello world")
}
`
- err := ioutil.WriteFile(hello, []byte(prog), 0666)
+ err := os.WriteFile(hello, []byte(prog), 0666)
if err != nil {
t.Fatal(err)
}
@@ -251,7 +250,7 @@ func TestLargeDefs(t *testing.T) {
println("ok")
}
`
- err = ioutil.WriteFile(main, []byte(prog), 0666)
+ err = os.WriteFile(main, []byte(prog), 0666)
if err != nil {
t.Fatal(err)
}
@@ -281,13 +280,13 @@ func TestIssue21703(t *testing.T) {
defer os.RemoveAll(dir)
const aSrc = `package a; const X = "\n!\n"`
- err := ioutil.WriteFile(filepath.Join(dir, "a.go"), []byte(aSrc), 0666)
+ err := os.WriteFile(filepath.Join(dir, "a.go"), []byte(aSrc), 0666)
if err != nil {
t.Fatal(err)
}
const bSrc = `package b; import _ "a"`
- err = ioutil.WriteFile(filepath.Join(dir, "b.go"), []byte(bSrc), 0666)
+ err = os.WriteFile(filepath.Join(dir, "b.go"), []byte(bSrc), 0666)
if err != nil {
t.Fatal(err)
}
diff --git a/src/cmd/trace/annotations_test.go b/src/cmd/trace/annotations_test.go
index a9068d53c1..9c2d027366 100644
--- a/src/cmd/trace/annotations_test.go
+++ b/src/cmd/trace/annotations_test.go
@@ -12,7 +12,7 @@ import (
"flag"
"fmt"
traceparser "internal/trace"
- "io/ioutil"
+ "os"
"reflect"
"runtime/debug"
"runtime/trace"
@@ -386,7 +386,7 @@ func saveTrace(buf *bytes.Buffer, name string) {
if !*saveTraces {
return
}
- if err := ioutil.WriteFile(name+".trace", buf.Bytes(), 0600); err != nil {
+ if err := os.WriteFile(name+".trace", buf.Bytes(), 0600); err != nil {
panic(fmt.Errorf("failed to write trace file: %v", err))
}
}
diff --git a/src/cmd/trace/pprof.go b/src/cmd/trace/pprof.go
index a31d71b013..a73ff5336a 100644
--- a/src/cmd/trace/pprof.go
+++ b/src/cmd/trace/pprof.go
@@ -11,7 +11,6 @@ import (
"fmt"
"internal/trace"
"io"
- "io/ioutil"
"net/http"
"os"
"os/exec"
@@ -294,7 +293,7 @@ func serveSVGProfile(prof func(w io.Writer, r *http.Request) error) http.Handler
return
}
- blockf, err := ioutil.TempFile("", "block")
+ blockf, err := os.CreateTemp("", "block")
if err != nil {
http.Error(w, fmt.Sprintf("failed to create temp file: %v", err), http.StatusInternalServerError)
return
diff --git a/src/cmd/vendor/github.com/google/pprof/internal/graph/dotgraph.go b/src/cmd/vendor/github.com/google/pprof/internal/graph/dotgraph.go
index cde648f20b..8cb87da9af 100644
--- a/src/cmd/vendor/github.com/google/pprof/internal/graph/dotgraph.go
+++ b/src/cmd/vendor/github.com/google/pprof/internal/graph/dotgraph.go
@@ -127,7 +127,7 @@ func (b *builder) addLegend() {
}
title := labels[0]
fmt.Fprintf(b, `subgraph cluster_L { "%s" [shape=box fontsize=16`, title)
- fmt.Fprintf(b, ` label="%s\l"`, strings.Join(escapeForDot(labels), `\l`))
+ fmt.Fprintf(b, ` label="%s\l"`, strings.Join(escapeAllForDot(labels), `\l`))
if b.config.LegendURL != "" {
fmt.Fprintf(b, ` URL="%s" target="_blank"`, b.config.LegendURL)
}
@@ -187,7 +187,7 @@ func (b *builder) addNode(node *Node, nodeID int, maxFlat float64) {
// Create DOT attribute for node.
attr := fmt.Sprintf(`label="%s" id="node%d" fontsize=%d shape=%s tooltip="%s (%s)" color="%s" fillcolor="%s"`,
- label, nodeID, fontSize, shape, node.Info.PrintableName(), cumValue,
+ label, nodeID, fontSize, shape, escapeForDot(node.Info.PrintableName()), cumValue,
dotColor(float64(node.CumValue())/float64(abs64(b.config.Total)), false),
dotColor(float64(node.CumValue())/float64(abs64(b.config.Total)), true))
@@ -305,7 +305,8 @@ func (b *builder) addEdge(edge *Edge, from, to int, hasNodelets bool) {
arrow = "..."
}
tooltip := fmt.Sprintf(`"%s %s %s (%s)"`,
- edge.Src.Info.PrintableName(), arrow, edge.Dest.Info.PrintableName(), w)
+ escapeForDot(edge.Src.Info.PrintableName()), arrow,
+ escapeForDot(edge.Dest.Info.PrintableName()), w)
attr = fmt.Sprintf(`%s tooltip=%s labeltooltip=%s`, attr, tooltip, tooltip)
if edge.Residual {
@@ -382,7 +383,7 @@ func dotColor(score float64, isBackground bool) string {
func multilinePrintableName(info *NodeInfo) string {
infoCopy := *info
- infoCopy.Name = ShortenFunctionName(infoCopy.Name)
+ infoCopy.Name = escapeForDot(ShortenFunctionName(infoCopy.Name))
infoCopy.Name = strings.Replace(infoCopy.Name, "::", `\n`, -1)
infoCopy.Name = strings.Replace(infoCopy.Name, ".", `\n`, -1)
if infoCopy.File != "" {
@@ -473,13 +474,18 @@ func min64(a, b int64) int64 {
return b
}
-// escapeForDot escapes double quotes and backslashes, and replaces Graphviz's
-// "center" character (\n) with a left-justified character.
-// See https://graphviz.org/doc/info/attrs.html#k:escString for more info.
-func escapeForDot(in []string) []string {
+// escapeAllForDot applies escapeForDot to all strings in the given slice.
+func escapeAllForDot(in []string) []string {
var out = make([]string, len(in))
for i := range in {
- out[i] = strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(in[i], `\`, `\\`), `"`, `\"`), "\n", `\l`)
+ out[i] = escapeForDot(in[i])
}
return out
}
+
+// escapeForDot escapes double quotes and backslashes, and replaces Graphviz's
+// "center" character (\n) with a left-justified character.
+// See https://graphviz.org/doc/info/attrs.html#k:escString for more info.
+func escapeForDot(str string) string {
+ return strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(str, `\`, `\\`), `"`, `\"`), "\n", `\l`)
+}
diff --git a/src/cmd/vendor/github.com/google/pprof/internal/graph/graph.go b/src/cmd/vendor/github.com/google/pprof/internal/graph/graph.go
index d2397a93d8..74b904c402 100644
--- a/src/cmd/vendor/github.com/google/pprof/internal/graph/graph.go
+++ b/src/cmd/vendor/github.com/google/pprof/internal/graph/graph.go
@@ -28,12 +28,14 @@ import (
)
var (
- // Removes package name and method arugments for Java method names.
+ // Removes package name and method arguments for Java method names.
// See tests for examples.
javaRegExp = regexp.MustCompile(`^(?:[a-z]\w*\.)*([A-Z][\w\$]*\.(?:|[a-z][\w\$]*(?:\$\d+)?))(?:(?:\()|$)`)
- // Removes package name and method arugments for Go function names.
+ // Removes package name and method arguments for Go function names.
// See tests for examples.
goRegExp = regexp.MustCompile(`^(?:[\w\-\.]+\/)+(.+)`)
+ // Removes potential module versions in a package path.
+ goVerRegExp = regexp.MustCompile(`^(.*?)/v(?:[2-9]|[1-9][0-9]+)([./].*)$`)
// Strips C++ namespace prefix from a C++ function / method name.
// NOTE: Make sure to keep the template parameters in the name. Normally,
// template parameters are stripped from the C++ names but when
@@ -317,6 +319,8 @@ func New(prof *profile.Profile, o *Options) *Graph {
// nodes.
func newGraph(prof *profile.Profile, o *Options) (*Graph, map[uint64]Nodes) {
nodes, locationMap := CreateNodes(prof, o)
+ seenNode := make(map[*Node]bool)
+ seenEdge := make(map[nodePair]bool)
for _, sample := range prof.Sample {
var w, dw int64
w = o.SampleValue(sample.Value)
@@ -326,8 +330,12 @@ func newGraph(prof *profile.Profile, o *Options) (*Graph, map[uint64]Nodes) {
if dw == 0 && w == 0 {
continue
}
- seenNode := make(map[*Node]bool, len(sample.Location))
- seenEdge := make(map[nodePair]bool, len(sample.Location))
+ for k := range seenNode {
+ delete(seenNode, k)
+ }
+ for k := range seenEdge {
+ delete(seenEdge, k)
+ }
var parent *Node
// A residual edge goes over one or more nodes that were not kept.
residual := false
@@ -440,6 +448,7 @@ func newTree(prof *profile.Profile, o *Options) (g *Graph) {
// ShortenFunctionName returns a shortened version of a function's name.
func ShortenFunctionName(f string) string {
f = cppAnonymousPrefixRegExp.ReplaceAllString(f, "")
+ f = goVerRegExp.ReplaceAllString(f, `${1}${2}`)
for _, re := range []*regexp.Regexp{goRegExp, javaRegExp, cppRegExp} {
if matches := re.FindStringSubmatch(f); len(matches) >= 2 {
return strings.Join(matches[1:], "")
diff --git a/src/cmd/vendor/github.com/ianlancetaylor/demangle/ast.go b/src/cmd/vendor/github.com/ianlancetaylor/demangle/ast.go
index 0ad5354f58..ccbe5b3559 100644
--- a/src/cmd/vendor/github.com/ianlancetaylor/demangle/ast.go
+++ b/src/cmd/vendor/github.com/ianlancetaylor/demangle/ast.go
@@ -5,7 +5,6 @@
package demangle
import (
- "bytes"
"fmt"
"strings"
)
@@ -23,7 +22,10 @@ type AST interface {
// Copy an AST with possible transformations.
// If the skip function returns true, no copy is required.
// If the copy function returns nil, no copy is required.
- // Otherwise the AST returned by copy is used in a copy of the full AST.
+ // The Copy method will do the right thing if copy returns nil
+ // for some components of an AST but not others, so a good
+ // copy function will only return non-nil for AST values that
+ // need to change.
// Copy itself returns either a copy or nil.
Copy(copy func(AST) AST, skip func(AST) bool) AST
@@ -51,7 +53,7 @@ func ASTToString(a AST, options ...Option) string {
type printState struct {
tparams bool // whether to print template parameters
- buf bytes.Buffer
+ buf strings.Builder
last byte // Last byte written to buffer.
// The inner field is a list of items to print for a type
@@ -398,13 +400,172 @@ func (tp *TemplateParam) goString(indent int, field string) string {
return fmt.Sprintf("%*s%sTemplateParam: Template: %p; Index %d", indent, "", field, tp.Template, tp.Index)
}
+// LambdaAuto is a lambda auto parameter.
+type LambdaAuto struct {
+ Index int
+}
+
+func (la *LambdaAuto) print(ps *printState) {
+ // We print the index plus 1 because that is what the standard
+ // demangler does.
+ fmt.Fprintf(&ps.buf, "auto:%d", la.Index+1)
+}
+
+func (la *LambdaAuto) Traverse(fn func(AST) bool) {
+ fn(la)
+}
+
+func (la *LambdaAuto) Copy(fn func(AST) AST, skip func(AST) bool) AST {
+ if skip(la) {
+ return nil
+ }
+ return fn(la)
+}
+
+func (la *LambdaAuto) GoString() string {
+ return la.goString(0, "")
+}
+
+func (la *LambdaAuto) goString(indent int, field string) string {
+ return fmt.Sprintf("%*s%sLambdaAuto: Index %d", indent, "", field, la.Index)
+}
+
// Qualifiers is an ordered list of type qualifiers.
-type Qualifiers []string
+type Qualifiers struct {
+ Qualifiers []AST
+}
+
+func (qs *Qualifiers) print(ps *printState) {
+ first := true
+ for _, q := range qs.Qualifiers {
+ if !first {
+ ps.writeByte(' ')
+ }
+ q.print(ps)
+ first = false
+ }
+}
+
+func (qs *Qualifiers) Traverse(fn func(AST) bool) {
+ if fn(qs) {
+ for _, q := range qs.Qualifiers {
+ q.Traverse(fn)
+ }
+ }
+}
+
+func (qs *Qualifiers) Copy(fn func(AST) AST, skip func(AST) bool) AST {
+ if skip(qs) {
+ return nil
+ }
+ changed := false
+ qualifiers := make([]AST, len(qs.Qualifiers))
+ for i, q := range qs.Qualifiers {
+ qc := q.Copy(fn, skip)
+ if qc == nil {
+ qualifiers[i] = q
+ } else {
+ qualifiers[i] = qc
+ changed = true
+ }
+ }
+ if !changed {
+ return fn(qs)
+ }
+ qs = &Qualifiers{Qualifiers: qualifiers}
+ if r := fn(qs); r != nil {
+ return r
+ }
+ return qs
+}
+
+func (qs *Qualifiers) GoString() string {
+ return qs.goString(0, "")
+}
+
+func (qs *Qualifiers) goString(indent int, field string) string {
+ quals := fmt.Sprintf("%*s%s", indent, "", field)
+ for _, q := range qs.Qualifiers {
+ quals += "\n"
+ quals += q.goString(indent+2, "")
+ }
+ return quals
+}
+
+// Qualifier is a single type qualifier.
+type Qualifier struct {
+ Name string // qualifier name: const, volatile, etc.
+ Exprs []AST // can be non-nil for noexcept and throw
+}
+
+func (q *Qualifier) print(ps *printState) {
+ ps.writeString(q.Name)
+ if len(q.Exprs) > 0 {
+ ps.writeByte('(')
+ first := true
+ for _, e := range q.Exprs {
+ if !first {
+ ps.writeString(", ")
+ }
+ ps.print(e)
+ first = false
+ }
+ ps.writeByte(')')
+ }
+}
+
+func (q *Qualifier) Traverse(fn func(AST) bool) {
+ if fn(q) {
+ for _, e := range q.Exprs {
+ e.Traverse(fn)
+ }
+ }
+}
+
+func (q *Qualifier) Copy(fn func(AST) AST, skip func(AST) bool) AST {
+ if skip(q) {
+ return nil
+ }
+ exprs := make([]AST, len(q.Exprs))
+ changed := false
+ for i, e := range q.Exprs {
+ ec := e.Copy(fn, skip)
+ if ec == nil {
+ exprs[i] = e
+ } else {
+ exprs[i] = ec
+ changed = true
+ }
+ }
+ if !changed {
+ return fn(q)
+ }
+ q = &Qualifier{Name: q.Name, Exprs: exprs}
+ if r := fn(q); r != nil {
+ return r
+ }
+ return q
+}
+
+func (q *Qualifier) GoString() string {
+ return q.goString(0, "Qualifier: ")
+}
+
+func (q *Qualifier) goString(indent int, field string) string {
+ qs := fmt.Sprintf("%*s%s%s", indent, "", field, q.Name)
+ if len(q.Exprs) > 0 {
+ for i, e := range q.Exprs {
+ qs += "\n"
+ qs += e.goString(indent+2, fmt.Sprintf("%d: ", i))
+ }
+ }
+ return qs
+}
// TypeWithQualifiers is a type with standard qualifiers.
type TypeWithQualifiers struct {
Base AST
- Qualifiers Qualifiers
+ Qualifiers AST
}
func (twq *TypeWithQualifiers) print(ps *printState) {
@@ -414,7 +575,7 @@ func (twq *TypeWithQualifiers) print(ps *printState) {
if len(ps.inner) > 0 {
// The qualifier wasn't printed by Base.
ps.writeByte(' ')
- ps.writeString(strings.Join(twq.Qualifiers, " "))
+ ps.print(twq.Qualifiers)
ps.inner = ps.inner[:len(ps.inner)-1]
}
}
@@ -422,7 +583,7 @@ func (twq *TypeWithQualifiers) print(ps *printState) {
// Print qualifiers as an inner type by just printing the qualifiers.
func (twq *TypeWithQualifiers) printInner(ps *printState) {
ps.writeByte(' ')
- ps.writeString(strings.Join(twq.Qualifiers, " "))
+ ps.print(twq.Qualifiers)
}
func (twq *TypeWithQualifiers) Traverse(fn func(AST) bool) {
@@ -436,10 +597,17 @@ func (twq *TypeWithQualifiers) Copy(fn func(AST) AST, skip func(AST) bool) AST {
return nil
}
base := twq.Base.Copy(fn, skip)
- if base == nil {
+ quals := twq.Qualifiers.Copy(fn, skip)
+ if base == nil && quals == nil {
return fn(twq)
}
- twq = &TypeWithQualifiers{Base: base, Qualifiers: twq.Qualifiers}
+ if base == nil {
+ base = twq.Base
+ }
+ if quals == nil {
+ quals = twq.Qualifiers
+ }
+ twq = &TypeWithQualifiers{Base: base, Qualifiers: quals}
if r := fn(twq); r != nil {
return r
}
@@ -451,14 +619,15 @@ func (twq *TypeWithQualifiers) GoString() string {
}
func (twq *TypeWithQualifiers) goString(indent int, field string) string {
- return fmt.Sprintf("%*s%sTypeWithQualifiers: Qualifiers: %s\n%s", indent, "", field,
- twq.Qualifiers, twq.Base.goString(indent+2, "Base: "))
+ return fmt.Sprintf("%*s%sTypeWithQualifiers:\n%s\n%s", indent, "", field,
+ twq.Qualifiers.goString(indent+2, "Qualifiers: "),
+ twq.Base.goString(indent+2, "Base: "))
}
// MethodWithQualifiers is a method with qualifiers.
type MethodWithQualifiers struct {
Method AST
- Qualifiers Qualifiers
+ Qualifiers AST
RefQualifier string // "" or "&" or "&&"
}
@@ -467,9 +636,9 @@ func (mwq *MethodWithQualifiers) print(ps *printState) {
ps.inner = append(ps.inner, mwq)
ps.print(mwq.Method)
if len(ps.inner) > 0 {
- if len(mwq.Qualifiers) > 0 {
+ if mwq.Qualifiers != nil {
ps.writeByte(' ')
- ps.writeString(strings.Join(mwq.Qualifiers, " "))
+ ps.print(mwq.Qualifiers)
}
if mwq.RefQualifier != "" {
ps.writeByte(' ')
@@ -480,9 +649,9 @@ func (mwq *MethodWithQualifiers) print(ps *printState) {
}
func (mwq *MethodWithQualifiers) printInner(ps *printState) {
- if len(mwq.Qualifiers) > 0 {
+ if mwq.Qualifiers != nil {
ps.writeByte(' ')
- ps.writeString(strings.Join(mwq.Qualifiers, " "))
+ ps.print(mwq.Qualifiers)
}
if mwq.RefQualifier != "" {
ps.writeByte(' ')
@@ -501,10 +670,20 @@ func (mwq *MethodWithQualifiers) Copy(fn func(AST) AST, skip func(AST) bool) AST
return nil
}
method := mwq.Method.Copy(fn, skip)
- if method == nil {
+ var quals AST
+ if mwq.Qualifiers != nil {
+ quals = mwq.Qualifiers.Copy(fn, skip)
+ }
+ if method == nil && quals == nil {
return fn(mwq)
}
- mwq = &MethodWithQualifiers{Method: method, Qualifiers: mwq.Qualifiers, RefQualifier: mwq.RefQualifier}
+ if method == nil {
+ method = mwq.Method
+ }
+ if quals == nil {
+ quals = mwq.Qualifiers
+ }
+ mwq = &MethodWithQualifiers{Method: method, Qualifiers: quals, RefQualifier: mwq.RefQualifier}
if r := fn(mwq); r != nil {
return r
}
@@ -517,14 +696,14 @@ func (mwq *MethodWithQualifiers) GoString() string {
func (mwq *MethodWithQualifiers) goString(indent int, field string) string {
var q string
- if len(mwq.Qualifiers) > 0 {
- q += fmt.Sprintf(" Qualifiers: %v", mwq.Qualifiers)
+ if mwq.Qualifiers != nil {
+ q += "\n" + mwq.Qualifiers.goString(indent+2, "Qualifiers: ")
}
if mwq.RefQualifier != "" {
if q != "" {
- q += ";"
+ q += "\n"
}
- q += " RefQualifier: " + mwq.RefQualifier
+ q += fmt.Sprintf("%*s%s%s", indent+2, "", "RefQualifier: ", mwq.RefQualifier)
}
return fmt.Sprintf("%*s%sMethodWithQualifiers:%s\n%s", indent, "", field,
q, mwq.Method.goString(indent+2, "Method: "))
@@ -1955,6 +2134,22 @@ func (u *Unary) goString(indent int, field string) string {
u.Expr.goString(indent+2, "Expr: "))
}
+// isDesignatedInitializer reports whether x is a designated
+// initializer.
+func isDesignatedInitializer(x AST) bool {
+ switch x := x.(type) {
+ case *Binary:
+ if op, ok := x.Op.(*Operator); ok {
+ return op.Name == "=" || op.Name == "]="
+ }
+ case *Trinary:
+ if op, ok := x.Op.(*Operator); ok {
+ return op.Name == "[...]="
+ }
+ }
+ return false
+}
+
// Binary is a binary operation in an expression.
type Binary struct {
Op AST
@@ -1975,6 +2170,27 @@ func (b *Binary) print(ps *printState) {
return
}
+ if isDesignatedInitializer(b) {
+ if op.Name == "=" {
+ ps.writeByte('.')
+ } else {
+ ps.writeByte('[')
+ }
+ ps.print(b.Left)
+ if op.Name == "]=" {
+ ps.writeByte(']')
+ }
+ if isDesignatedInitializer(b.Right) {
+ // Don't add anything between designated
+ // initializer chains.
+ ps.print(b.Right)
+ } else {
+ ps.writeByte('=')
+ parenthesize(ps, b.Right)
+ }
+ return
+ }
+
// Use an extra set of parentheses around an expression that
// uses the greater-than operator, so that it does not get
// confused with the '>' that ends template parameters.
@@ -1984,15 +2200,28 @@ func (b *Binary) print(ps *printState) {
left := b.Left
- // A function call in an expression should not print the types
- // of the arguments.
+ // For a function call in an expression, don't print the types
+ // of the arguments unless there is a return type.
+ skipParens := false
if op != nil && op.Name == "()" {
if ty, ok := b.Left.(*Typed); ok {
- left = ty.Name
+ if ft, ok := ty.Type.(*FunctionType); ok {
+ if ft.Return == nil {
+ left = ty.Name
+ } else {
+ skipParens = true
+ }
+ } else {
+ left = ty.Name
+ }
}
}
- parenthesize(ps, left)
+ if skipParens {
+ ps.print(left)
+ } else {
+ parenthesize(ps, left)
+ }
if op != nil && op.Name == "[]" {
ps.writeByte('[')
@@ -2070,6 +2299,23 @@ type Trinary struct {
}
func (t *Trinary) print(ps *printState) {
+ if isDesignatedInitializer(t) {
+ ps.writeByte('[')
+ ps.print(t.First)
+ ps.writeString(" ... ")
+ ps.print(t.Second)
+ ps.writeByte(']')
+ if isDesignatedInitializer(t.Third) {
+ // Don't add anything between designated
+ // initializer chains.
+ ps.print(t.Third)
+ } else {
+ ps.writeByte('=')
+ parenthesize(ps, t.Third)
+ }
+ return
+ }
+
parenthesize(ps, t.First)
ps.writeByte('?')
parenthesize(ps, t.Second)
@@ -2362,6 +2608,9 @@ func (l *Literal) print(ps *printState) {
ps.writeString("true")
return
}
+ } else if b.Name == "decltype(nullptr)" && l.Val == "" {
+ ps.print(l.Type)
+ return
} else {
isFloat = builtinTypeFloat[b.Name]
}
@@ -2821,6 +3070,83 @@ func (s *Special2) goString(indent int, field string) string {
indent+2, "", s.Middle, s.Val2.goString(indent+2, "Val2: "))
}
+// EnableIf is used by clang for an enable_if attribute.
+type EnableIf struct {
+ Type AST
+ Args []AST
+}
+
+func (ei *EnableIf) print(ps *printState) {
+ ps.print(ei.Type)
+ ps.writeString(" [enable_if:")
+ first := true
+ for _, a := range ei.Args {
+ if !first {
+ ps.writeString(", ")
+ }
+ ps.print(a)
+ first = false
+ }
+ ps.writeString("]")
+}
+
+func (ei *EnableIf) Traverse(fn func(AST) bool) {
+ if fn(ei) {
+ ei.Type.Traverse(fn)
+ for _, a := range ei.Args {
+ a.Traverse(fn)
+ }
+ }
+}
+
+func (ei *EnableIf) Copy(fn func(AST) AST, skip func(AST) bool) AST {
+ if skip(ei) {
+ return nil
+ }
+ typ := ei.Type.Copy(fn, skip)
+ argsChanged := false
+ args := make([]AST, len(ei.Args))
+ for i, a := range ei.Args {
+ ac := a.Copy(fn, skip)
+ if ac == nil {
+ args[i] = a
+ } else {
+ args[i] = ac
+ argsChanged = true
+ }
+ }
+ if typ == nil && !argsChanged {
+ return fn(ei)
+ }
+ if typ == nil {
+ typ = ei.Type
+ }
+ ei = &EnableIf{Type: typ, Args: args}
+ if r := fn(ei); r != nil {
+ return r
+ }
+ return ei
+}
+
+func (ei *EnableIf) GoString() string {
+ return ei.goString(0, "")
+}
+
+func (ei *EnableIf) goString(indent int, field string) string {
+ var args string
+ if len(ei.Args) == 0 {
+ args = fmt.Sprintf("%*sArgs: nil", indent+2, "")
+ } else {
+ args = fmt.Sprintf("%*sArgs:", indent+2, "")
+ for i, a := range ei.Args {
+ args += "\n"
+ args += a.goString(indent+4, fmt.Sprintf("%d: ", i))
+ }
+ }
+ return fmt.Sprintf("%*s%sEnableIf:\n%s\n%s", indent, "", field,
+ ei.Type.goString(indent+2, "Type: "), args)
+}
+
// Print the inner types.
func (ps *printState) printInner(prefixOnly bool) []AST {
var save []AST
diff --git a/src/cmd/vendor/github.com/ianlancetaylor/demangle/demangle.go b/src/cmd/vendor/github.com/ianlancetaylor/demangle/demangle.go
index 7541b736ba..c2667446df 100644
--- a/src/cmd/vendor/github.com/ianlancetaylor/demangle/demangle.go
+++ b/src/cmd/vendor/github.com/ianlancetaylor/demangle/demangle.go
@@ -5,6 +5,8 @@
// Package demangle defines functions that demangle GCC/LLVM C++ symbol names.
// This package recognizes names that were mangled according to the C++ ABI
// defined at http://codesourcery.com/cxx-abi/.
+//
+// Most programs will want to call Filter or ToString.
package demangle
import (
@@ -45,7 +47,7 @@ func Filter(name string, options ...Option) string {
return ret
}
-// ToString demangles a C++ symbol name, returning human-readable C++
+// ToString demangles a C++ symbol name, returning a human-readable C++
// name or an error.
// If the name does not appear to be a C++ symbol name at all, the
// error will be ErrNotMangledName.
@@ -183,6 +185,7 @@ type state struct {
off int // offset of str within original string
subs substitutions // substitutions
templates []*Template // templates being processed
+ inLambda int // number of lambdas being parsed
}
// copy returns a copy of the current state.
@@ -310,15 +313,42 @@ func (st *state) encoding(params bool, local forLocalNameType) AST {
if mwq != nil {
check = mwq.Method
}
- template, _ := check.(*Template)
+
+ var template *Template
+ switch check := check.(type) {
+ case *Template:
+ template = check
+ case *Qualified:
+ if check.LocalName {
+ n := check.Name
+ if nmwq, ok := n.(*MethodWithQualifiers); ok {
+ n = nmwq.Method
+ }
+ template, _ = n.(*Template)
+ }
+ }
+ var oldInLambda int
if template != nil {
st.templates = append(st.templates, template)
+ oldInLambda = st.inLambda
+ st.inLambda = 0
+ }
+
+ // Checking for the enable_if attribute here is what the LLVM
+ // demangler does. This is not very general but perhaps it is
+ // sufficent.
+ const enableIfPrefix = "Ua9enable_ifI"
+ var enableIfArgs []AST
+ if strings.HasPrefix(st.str, enableIfPrefix) {
+ st.advance(len(enableIfPrefix) - 1)
+ enableIfArgs = st.templateArgs()
}
ft := st.bareFunctionType(hasReturnType(a))
if template != nil {
st.templates = st.templates[:len(st.templates)-1]
+ st.inLambda = oldInLambda
}
ft = simplify(ft)
@@ -349,13 +379,24 @@ func (st *state) encoding(params bool, local forLocalNameType) AST {
}
}
- return &Typed{Name: a, Type: ft}
+ r := AST(&Typed{Name: a, Type: ft})
+
+ if len(enableIfArgs) > 0 {
+ r = &EnableIf{Type: r, Args: enableIfArgs}
+ }
+
+ return r
}
// hasReturnType returns whether the mangled form of a will have a
// return type.
func hasReturnType(a AST) bool {
switch a := a.(type) {
+ case *Qualified:
+ if a.LocalName {
+ return hasReturnType(a.Name)
+ }
+ return false
case *Template:
return !isCDtorConversion(a.Name)
case *TypeWithQualifiers:
@@ -481,7 +522,7 @@ func (st *state) nestedName() AST {
q := st.cvQualifiers()
r := st.refQualifier()
a := st.prefix()
- if len(q) > 0 || r != "" {
+ if q != nil || r != "" {
a = &MethodWithQualifiers{Method: a, Qualifiers: q, RefQualifier: r}
}
if len(st.str) == 0 || st.str[0] != 'E' {
@@ -608,6 +649,29 @@ func (st *state) prefix() AST {
// gives appropriate output.
st.advance(1)
continue
+ case 'J':
+ // It appears that in some cases clang
+ // can emit a J for a template arg
+ // without the expected I. I don't
+ // know when this happens, but I've
+ // seen it in some large C++ programs.
+ if a == nil {
+ st.fail("unexpected template arguments")
+ }
+ var args []AST
+ for len(st.str) == 0 || st.str[0] != 'E' {
+ arg := st.templateArg()
+ args = append(args, arg)
+ }
+ st.advance(1)
+ tmpl := &Template{Name: a, Args: args}
+ if isCast {
+ st.setTemplate(a, tmpl)
+ st.clearTemplateArgs(args)
+ isCast = false
+ }
+ a = nil
+ next = tmpl
default:
st.fail("unrecognized letter in prefix")
}
@@ -754,19 +818,26 @@ var operators = map[string]operator{
"ad": {"&", 1},
"an": {"&", 2},
"at": {"alignof ", 1},
+ "aw": {"co_await ", 1},
"az": {"alignof ", 1},
"cc": {"const_cast", 2},
"cl": {"()", 2},
+ // cp is not in the ABI but is used by clang "when the call
+ // would use ADL except for being parenthesized."
+ "cp": {"()", 2},
"cm": {",", 2},
"co": {"~", 1},
"dV": {"/=", 2},
+ "dX": {"[...]=", 3},
"da": {"delete[] ", 1},
"dc": {"dynamic_cast", 2},
"de": {"*", 1},
+ "di": {"=", 2},
"dl": {"delete ", 1},
"ds": {".*", 2},
"dt": {".", 2},
"dv": {"/", 2},
+ "dx": {"]=", 2},
"eO": {"^=", 2},
"eo": {"^", 2},
"eq": {"==", 2},
@@ -808,7 +879,10 @@ var operators = map[string]operator{
"rc": {"reinterpret_cast", 2},
"rm": {"%", 2},
"rs": {">>", 2},
+ "sP": {"sizeof...", 1},
+ "sZ": {"sizeof...", 1},
"sc": {"static_cast", 2},
+ "ss": {"<=>", 2},
"st": {"sizeof ", 1},
"sz": {"sizeof ", 1},
"tr": {"throw", 0},
@@ -928,6 +1002,7 @@ func (st *state) javaResource() AST {
// ::= TT
// ::= TI
// ::= TS
+// ::= TA
// ::= GV <(object) name>
// ::= T <(base) encoding>
// ::= Tc <(base) encoding>
@@ -961,6 +1036,9 @@ func (st *state) specialName() AST {
case 'S':
t := st.demangleType(false)
return &Special{Prefix: "typeinfo name for ", Val: t}
+ case 'A':
+ t := st.templateArg()
+ return &Special{Prefix: "template parameter object for ", Val: t}
case 'h':
st.callOffset('h')
v := st.encoding(true, notForLocalName)
@@ -1138,7 +1216,7 @@ func (st *state) demangleType(isCast bool) AST {
addSubst := true
q := st.cvQualifiers()
- if len(q) > 0 {
+ if q != nil {
if len(st.str) == 0 {
st.fail("expected type")
}
@@ -1159,7 +1237,7 @@ func (st *state) demangleType(isCast bool) AST {
if btype, ok := builtinTypes[st.str[0]]; ok {
ret = &BuiltinType{Name: btype}
st.advance(1)
- if len(q) > 0 {
+ if q != nil {
ret = &TypeWithQualifiers{Base: ret, Qualifiers: q}
st.subs.add(ret)
}
@@ -1286,6 +1364,8 @@ func (st *state) demangleType(isCast bool) AST {
case 'a':
ret = &Name{Name: "auto"}
+ case 'c':
+ ret = &Name{Name: "decltype(auto)"}
case 'f':
ret = &BuiltinType{Name: "decimal32"}
@@ -1295,6 +1375,8 @@ func (st *state) demangleType(isCast bool) AST {
ret = &BuiltinType{Name: "decimal128"}
case 'h':
ret = &BuiltinType{Name: "half"}
+ case 'u':
+ ret = &BuiltinType{Name: "char8_t"}
case 's':
ret = &BuiltinType{Name: "char16_t"}
case 'i':
@@ -1343,7 +1425,7 @@ func (st *state) demangleType(isCast bool) AST {
}
}
- if len(q) > 0 {
+ if q != nil {
if _, ok := ret.(*FunctionType); ok {
ret = &MethodWithQualifiers{Method: ret, Qualifiers: q, RefQualifier: ""}
} else if mwq, ok := ret.(*MethodWithQualifiers); ok {
@@ -1433,17 +1515,32 @@ func (st *state) demangleCastTemplateArgs(tp AST, addSubst bool) AST {
}
// mergeQualifiers merges two qualifer lists into one.
-func mergeQualifiers(q1, q2 Qualifiers) Qualifiers {
- m := make(map[string]bool)
- for _, qual := range q1 {
- m[qual] = true
+func mergeQualifiers(q1AST, q2AST AST) AST {
+ if q1AST == nil {
+ return q2AST
}
- for _, qual := range q2 {
- if !m[qual] {
- q1 = append(q1, qual)
- m[qual] = true
+ if q2AST == nil {
+ return q1AST
+ }
+ q1 := q1AST.(*Qualifiers)
+ m := make(map[string]bool)
+ for _, qualAST := range q1.Qualifiers {
+ qual := qualAST.(*Qualifier)
+ if len(qual.Exprs) == 0 {
+ m[qual.Name] = true
}
}
+ rq := q1.Qualifiers
+ for _, qualAST := range q2AST.(*Qualifiers).Qualifiers {
+ qual := qualAST.(*Qualifier)
+ if len(qual.Exprs) > 0 {
+ rq = append(rq, qualAST)
+ } else if !m[qual.Name] {
+ rq = append(rq, qualAST)
+ m[qual.Name] = true
+ }
+ }
+ q1.Qualifiers = rq
return q1
}
@@ -1456,20 +1553,51 @@ var qualifiers = map[byte]string{
}
// ::= [r] [V] [K]
-func (st *state) cvQualifiers() Qualifiers {
- var q Qualifiers
+func (st *state) cvQualifiers() AST {
+ var q []AST
+qualLoop:
for len(st.str) > 0 {
if qv, ok := qualifiers[st.str[0]]; ok {
- q = append([]string{qv}, q...)
+ qual := &Qualifier{Name: qv}
+ q = append([]AST{qual}, q...)
st.advance(1)
- } else if len(st.str) > 1 && st.str[:2] == "Dx" {
- q = append([]string{"transaction_safe"}, q...)
- st.advance(2)
+ } else if len(st.str) > 1 && st.str[0] == 'D' {
+ var qual AST
+ switch st.str[1] {
+ case 'x':
+ qual = &Qualifier{Name: "transaction_safe"}
+ st.advance(2)
+ case 'o':
+ qual = &Qualifier{Name: "noexcept"}
+ st.advance(2)
+ case 'O':
+ st.advance(2)
+ expr := st.expression()
+ if len(st.str) == 0 || st.str[0] != 'E' {
+ st.fail("expected E after computed noexcept expression")
+ }
+ st.advance(1)
+ qual = &Qualifier{Name: "noexcept", Exprs: []AST{expr}}
+ case 'w':
+ st.advance(2)
+ parmlist := st.parmlist()
+ if len(st.str) == 0 || st.str[0] != 'E' {
+ st.fail("expected E after throw parameter list")
+ }
+ st.advance(1)
+ qual = &Qualifier{Name: "throw", Exprs: parmlist}
+ default:
+ break qualLoop
+ }
+ q = append([]AST{qual}, q...)
} else {
break
}
}
- return q
+ if len(q) == 0 {
+ return nil
+ }
+ return &Qualifiers{Qualifiers: q}
}
// ::= R
@@ -1677,7 +1805,7 @@ func (st *state) compactNumber() int {
// whatever the template parameter would be expanded to here. We sort
// this out in substitution and simplify.
func (st *state) templateParam() AST {
- if len(st.templates) == 0 {
+ if len(st.templates) == 0 && st.inLambda == 0 {
st.fail("template parameter not in scope of template")
}
off := st.off
@@ -1685,6 +1813,13 @@ func (st *state) templateParam() AST {
st.checkChar('T')
n := st.compactNumber()
+ if st.inLambda > 0 {
+ // g++ mangles lambda auto params as template params.
+ // Apparently we can't encounter a template within a lambda.
+ // See https://gcc.gnu.org/PR78252.
+ return &LambdaAuto{Index: n}
+ }
+
template := st.templates[len(st.templates)-1]
if template == nil {
@@ -1723,6 +1858,10 @@ func (st *state) setTemplate(a AST, tmpl *Template) {
}
a.Template = tmpl
return false
+ case *Closure:
+ // There are no template params in closure types.
+ // https://gcc.gnu.org/PR78252.
+ return false
default:
for _, v := range seen {
if v == a {
@@ -1812,12 +1951,60 @@ func (st *state) exprList(stop byte) AST {
// ::= <(unary) operator-name>
// ::= <(binary) operator-name>
// ::= <(trinary) operator-name>
+// ::= pp_
+// ::= mm_
// ::= cl + E
+// ::= cl + E
+// ::= cv
+// ::= cv _ * E
+// ::= tl * E
+// ::= il * E
+// ::= [gs] nw * _ E
+// ::= [gs] nw * _
+// ::= [gs] na * _ E
+// ::= [gs] na * _
+// ::= [gs] dl
+// ::= [gs] da
+// ::= dc
+// ::= sc
+// ::= cc
+// ::= rc
+// ::= ti
+// ::= te
// ::= st
+// ::= sz
+// ::= at
+// ::= az
+// ::= nx
// ::=
-// ::= sr
-// ::= sr
+// ::=
+// ::= dt
+// ::= pt
+// ::= ds
+// ::= sZ
+// ::= sZ
+// ::= sP * E
+// ::= sp
+// ::= fl
+// ::= fr
+// ::= fL
+// ::= fR
+// ::= tw
+// ::= tr
+// ::=
// ::=
+//
+// ::= fp _
+// ::= fp
+// ::= fL p _
+// ::= fL p
+// ::= fpT
+//
+// ::=
+// ::= di
+// ::= dx
+// ::= dX
+//
func (st *state) expression() AST {
if len(st.str) == 0 {
st.fail("expected expression")
@@ -1827,61 +2014,7 @@ func (st *state) expression() AST {
} else if st.str[0] == 'T' {
return st.templateParam()
} else if st.str[0] == 's' && len(st.str) > 1 && st.str[1] == 'r' {
- st.advance(2)
- if len(st.str) == 0 {
- st.fail("expected unresolved type")
- }
- switch st.str[0] {
- case 'T', 'D', 'S':
- t := st.demangleType(false)
- n := st.baseUnresolvedName()
- n = &Qualified{Scope: t, Name: n, LocalName: false}
- if len(st.str) > 0 && st.str[0] == 'I' {
- args := st.templateArgs()
- n = &Template{Name: n, Args: args}
- }
- return n
- default:
- var s AST
- if st.str[0] == 'N' {
- st.advance(1)
- s = st.demangleType(false)
- }
- for len(st.str) == 0 || st.str[0] != 'E' {
- // GCC does not seem to follow the ABI here.
- // It can emit type/name without an 'E'.
- if s != nil && len(st.str) > 0 && !isDigit(st.str[0]) {
- if q, ok := s.(*Qualified); ok {
- a := q.Scope
- if t, ok := a.(*Template); ok {
- st.subs.add(t.Name)
- st.subs.add(t)
- } else {
- st.subs.add(a)
- }
- return s
- }
- }
- n := st.sourceName()
- if len(st.str) > 0 && st.str[0] == 'I' {
- st.subs.add(n)
- args := st.templateArgs()
- n = &Template{Name: n, Args: args}
- }
- if s == nil {
- s = n
- } else {
- s = &Qualified{Scope: s, Name: n, LocalName: false}
- }
- st.subs.add(s)
- }
- if s == nil {
- st.fail("missing scope in unresolved name")
- }
- st.advance(1)
- n := st.baseUnresolvedName()
- return &Qualified{Scope: s, Name: n, LocalName: false}
- }
+ return st.unresolvedName()
} else if st.str[0] == 's' && len(st.str) > 1 && st.str[1] == 'p' {
st.advance(2)
e := st.expression()
@@ -1911,9 +2044,25 @@ func (st *state) expression() AST {
st.advance(1)
return &FunctionParam{Index: 0}
} else {
+ // We can see qualifiers here, but we don't
+ // include them in the demangled string.
+ st.cvQualifiers()
index := st.compactNumber()
return &FunctionParam{Index: index + 1}
}
+ } else if st.str[0] == 'f' && len(st.str) > 2 && st.str[1] == 'L' && isDigit(st.str[2]) {
+ st.advance(2)
+ // We don't include the scope count in the demangled string.
+ st.number()
+ if len(st.str) == 0 || st.str[0] != 'p' {
+ st.fail("expected p after function parameter scope count")
+ }
+ st.advance(1)
+ // We can see qualifiers here, but we don't include them
+ // in the demangled string.
+ st.cvQualifiers()
+ index := st.compactNumber()
+ return &FunctionParam{Index: index + 1}
} else if isDigit(st.str[0]) || (st.str[0] == 'o' && len(st.str) > 1 && st.str[1] == 'n') {
if st.str[0] == 'o' {
// Skip operator function ID.
@@ -1975,13 +2124,15 @@ func (st *state) expression() AST {
left, _ = st.operatorName(true)
right = st.expression()
return &Fold{Left: code[1] == 'l', Op: left, Arg1: right, Arg2: nil}
+ } else if code == "di" {
+ left, _ = st.unqualifiedName()
} else {
left = st.expression()
}
- if code == "cl" {
+ if code == "cl" || code == "cp" {
right = st.exprList('E')
} else if code == "dt" || code == "pt" {
- right, _ = st.unqualifiedName()
+ right = st.unresolvedName()
if len(st.str) > 0 && st.str[0] == 'I' {
args := st.templateArgs()
right = &Template{Name: right, Args: args}
@@ -2034,6 +2185,82 @@ func (st *state) expression() AST {
}
}
+// ::= [gs]
+// ::= sr
+// ::= srN + E
+// ::= [gs] sr + E
+func (st *state) unresolvedName() AST {
+ if len(st.str) >= 2 && st.str[:2] == "gs" {
+ st.advance(2)
+ n := st.unresolvedName()
+ return &Unary{
+ Op: &Operator{Name: "::"},
+ Expr: n,
+ Suffix: false,
+ SizeofType: false,
+ }
+ } else if len(st.str) >= 2 && st.str[:2] == "sr" {
+ st.advance(2)
+ if len(st.str) == 0 {
+ st.fail("expected unresolved type")
+ }
+ switch st.str[0] {
+ case 'T', 'D', 'S':
+ t := st.demangleType(false)
+ n := st.baseUnresolvedName()
+ n = &Qualified{Scope: t, Name: n, LocalName: false}
+ if len(st.str) > 0 && st.str[0] == 'I' {
+ args := st.templateArgs()
+ n = &Template{Name: n, Args: args}
+ st.subs.add(n)
+ }
+ return n
+ default:
+ var s AST
+ if st.str[0] == 'N' {
+ st.advance(1)
+ s = st.demangleType(false)
+ }
+ for len(st.str) == 0 || st.str[0] != 'E' {
+ // GCC does not seem to follow the ABI here.
+ // It can emit type/name without an 'E'.
+ if s != nil && len(st.str) > 0 && !isDigit(st.str[0]) {
+ if q, ok := s.(*Qualified); ok {
+ a := q.Scope
+ if t, ok := a.(*Template); ok {
+ st.subs.add(t.Name)
+ st.subs.add(t)
+ } else {
+ st.subs.add(a)
+ }
+ return s
+ }
+ }
+ n := st.sourceName()
+ if len(st.str) > 0 && st.str[0] == 'I' {
+ st.subs.add(n)
+ args := st.templateArgs()
+ n = &Template{Name: n, Args: args}
+ }
+ if s == nil {
+ s = n
+ } else {
+ s = &Qualified{Scope: s, Name: n, LocalName: false}
+ }
+ st.subs.add(s)
+ }
+ if s == nil {
+ st.fail("missing scope in unresolved name")
+ }
+ st.advance(1)
+ n := st.baseUnresolvedName()
+ return &Qualified{Scope: s, Name: n, LocalName: false}
+ }
+ } else {
+ return st.baseUnresolvedName()
+ }
+}
+
// ::=
// ::= on
// ::= on
@@ -2099,7 +2326,14 @@ func (st *state) exprPrimary() AST {
st.advance(1)
}
if len(st.str) > 0 && st.str[0] == 'E' {
- st.fail("missing literal value")
+ if bt, ok := t.(*BuiltinType); ok && bt.Name == "decltype(nullptr)" {
+ // A nullptr should not have a value.
+ // We accept one if present because GCC
+ // used to generate one.
+ // https://gcc.gnu.org/PR91979.
+ } else {
+ st.fail("missing literal value")
+ }
}
i := 0
for len(st.str) > i && st.str[i] != 'E' {
@@ -2116,17 +2350,29 @@ func (st *state) exprPrimary() AST {
return ret
}
-// ::= _ <(non-negative) number>
+// ::= _ <(non-negative) number> (when number < 10)
+// __ <(non-negative) number> _ (when number >= 10)
func (st *state) discriminator(a AST) AST {
if len(st.str) == 0 || st.str[0] != '_' {
return a
}
off := st.off
st.advance(1)
+ trailingUnderscore := false
+ if len(st.str) > 0 && st.str[0] == '_' {
+ st.advance(1)
+ trailingUnderscore = true
+ }
d := st.number()
if d < 0 {
st.failEarlier("invalid negative discriminator", st.off-off)
}
+ if trailingUnderscore && d >= 10 {
+ if len(st.str) == 0 || st.str[0] != '_' {
+ st.fail("expected _ after discriminator >= 10")
+ }
+ st.advance(1)
+ }
// We don't currently print out the discriminator, so we don't
// save it.
return a
@@ -2136,15 +2382,15 @@ func (st *state) discriminator(a AST) AST {
func (st *state) closureTypeName() AST {
st.checkChar('U')
st.checkChar('l')
+ st.inLambda++
types := st.parmlist()
+ st.inLambda--
if len(st.str) == 0 || st.str[0] != 'E' {
st.fail("expected E after closure type name")
}
st.advance(1)
num := st.compactNumber()
- ret := &Closure{Types: types, Num: num}
- st.subs.add(ret)
- return ret
+ return &Closure{Types: types, Num: num}
}
// ::= Ut [ ] _
@@ -2295,31 +2541,92 @@ func (st *state) substitution(forPrefix bool) AST {
// We need to update any references to template
// parameters to refer to the currently active
// template.
+
+ // When copying a Typed we may need to adjust
+ // the templates.
+ copyTemplates := st.templates
+ var oldInLambda []int
+
+ // pushTemplate is called from skip, popTemplate from copy.
+ pushTemplate := func(template *Template) {
+ copyTemplates = append(copyTemplates, template)
+ oldInLambda = append(oldInLambda, st.inLambda)
+ st.inLambda = 0
+ }
+ popTemplate := func() {
+ copyTemplates = copyTemplates[:len(copyTemplates)-1]
+ st.inLambda = oldInLambda[len(oldInLambda)-1]
+ oldInLambda = oldInLambda[:len(oldInLambda)-1]
+ }
+
copy := func(a AST) AST {
- tp, ok := a.(*TemplateParam)
- if !ok {
+ var index int
+ switch a := a.(type) {
+ case *Typed:
+ // Remove the template added in skip.
+ if _, ok := a.Name.(*Template); ok {
+ popTemplate()
+ }
+ return nil
+ case *Closure:
+ // Undo the decrement in skip.
+ st.inLambda--
+ return nil
+ case *TemplateParam:
+ index = a.Index
+ case *LambdaAuto:
+ // A lambda auto parameter is represented
+ // as a template parameter, so we may have
+ // to change back when substituting.
+ index = a.Index
+ default:
return nil
}
- if len(st.templates) == 0 {
+ if st.inLambda > 0 {
+ if _, ok := a.(*LambdaAuto); ok {
+ return nil
+ }
+ return &LambdaAuto{Index: index}
+ }
+ var template *Template
+ if len(copyTemplates) > 0 {
+ template = copyTemplates[len(copyTemplates)-1]
+ } else if rt, ok := ret.(*Template); ok {
+ // At least with clang we can see a template
+ // to start, and sometimes we need to refer
+ // to it. There is probably something wrong
+ // here.
+ template = rt
+ } else {
st.failEarlier("substituted template parameter not in scope of template", dec)
}
- template := st.templates[len(st.templates)-1]
if template == nil {
// This template parameter is within
// the scope of a cast operator.
- return &TemplateParam{Index: tp.Index, Template: nil}
+ return &TemplateParam{Index: index, Template: nil}
}
- if tp.Index >= len(template.Args) {
- st.failEarlier(fmt.Sprintf("substituted template index out of range (%d >= %d)", tp.Index, len(template.Args)), dec)
+ if index >= len(template.Args) {
+ st.failEarlier(fmt.Sprintf("substituted template index out of range (%d >= %d)", index, len(template.Args)), dec)
}
- return &TemplateParam{Index: tp.Index, Template: template}
+ return &TemplateParam{Index: index, Template: template}
}
var seen []AST
skip := func(a AST) bool {
- if _, ok := a.(*Typed); ok {
- return true
+ switch a := a.(type) {
+ case *Typed:
+ if template, ok := a.Name.(*Template); ok {
+ // This template is removed in copy.
+ pushTemplate(template)
+ }
+ return false
+ case *Closure:
+ // This is decremented in copy.
+ st.inLambda++
+ return false
+ case *TemplateParam, *LambdaAuto:
+ return false
}
for _, v := range seen {
if v == a {
@@ -2329,6 +2636,7 @@ func (st *state) substitution(forPrefix bool) AST {
seen = append(seen, a)
return false
}
+
if c := ret.Copy(copy, skip); c != nil {
return c
}
@@ -2351,6 +2659,7 @@ func (st *state) substitution(forPrefix bool) AST {
if len(st.str) > 0 && st.str[0] == 'B' {
a = st.taggedName(a)
+ st.subs.add(a)
}
return a
diff --git a/src/cmd/vendor/golang.org/x/mod/semver/semver.go b/src/cmd/vendor/golang.org/x/mod/semver/semver.go
index 2988e3cf9c..4338f35177 100644
--- a/src/cmd/vendor/golang.org/x/mod/semver/semver.go
+++ b/src/cmd/vendor/golang.org/x/mod/semver/semver.go
@@ -138,6 +138,9 @@ func Compare(v, w string) int {
// Max canonicalizes its arguments and then returns the version string
// that compares greater.
+//
+// Deprecated: use Compare instead. In most cases, returning a canonicalized
+// version is not expected or desired.
func Max(v, w string) string {
v = Canonical(v)
w = Canonical(w)
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_aix_ppc64.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_aix_ppc64.s
index 06f84b8555..6b4027b33f 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/asm_aix_ppc64.s
+++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_aix_ppc64.s
@@ -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 gc
#include "textflag.h"
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_darwin_386.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_darwin_386.s
index 8a7278319e..8a06b87d71 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/asm_darwin_386.s
+++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_darwin_386.s
@@ -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 gc
#include "textflag.h"
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_darwin_amd64.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_darwin_amd64.s
index 6321421f27..f2397fde55 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/asm_darwin_amd64.s
+++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_darwin_amd64.s
@@ -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 gc
#include "textflag.h"
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_darwin_arm.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_darwin_arm.s
index 333242d506..c9e6b6fc8b 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/asm_darwin_arm.s
+++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_darwin_arm.s
@@ -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 gc
// +build arm,darwin
#include "textflag.h"
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_darwin_arm64.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_darwin_arm64.s
index 97e0174371..89843f8f4b 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/asm_darwin_arm64.s
+++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_darwin_arm64.s
@@ -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 gc
// +build arm64,darwin
#include "textflag.h"
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_dragonfly_amd64.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_dragonfly_amd64.s
index 603dd5728c..27674e1caf 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/asm_dragonfly_amd64.s
+++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_dragonfly_amd64.s
@@ -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 gc
#include "textflag.h"
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_freebsd_386.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_freebsd_386.s
index c9a0a26015..49f0ac2364 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/asm_freebsd_386.s
+++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_freebsd_386.s
@@ -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 gc
#include "textflag.h"
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_freebsd_amd64.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_freebsd_amd64.s
index 35172477c8..f2dfc57b83 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/asm_freebsd_amd64.s
+++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_freebsd_amd64.s
@@ -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 gc
#include "textflag.h"
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_freebsd_arm.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_freebsd_arm.s
index 9227c875bf..6d740db2c0 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/asm_freebsd_arm.s
+++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_freebsd_arm.s
@@ -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 gc
#include "textflag.h"
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_freebsd_arm64.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_freebsd_arm64.s
index d9318cbf03..a8f5a29b35 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/asm_freebsd_arm64.s
+++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_freebsd_arm64.s
@@ -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 gc
#include "textflag.h"
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_386.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_386.s
index 448bebbb59..0655ecbfbb 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_386.s
+++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_386.s
@@ -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 gc
#include "textflag.h"
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_amd64.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_amd64.s
index c6468a9588..bc3fb6ac3e 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_amd64.s
+++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_amd64.s
@@ -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 gc
#include "textflag.h"
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_arm.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_arm.s
index cf0f3575c1..55b13c7ba4 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_arm.s
+++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_arm.s
@@ -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 gc
#include "textflag.h"
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_arm64.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_arm64.s
index afe6fdf6b1..22a83d8e3f 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_arm64.s
+++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_arm64.s
@@ -4,7 +4,7 @@
// +build linux
// +build arm64
-// +build !gccgo
+// +build gc
#include "textflag.h"
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_mips64x.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_mips64x.s
index ab9d63831a..dc222b90ce 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_mips64x.s
+++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_mips64x.s
@@ -4,7 +4,7 @@
// +build linux
// +build mips64 mips64le
-// +build !gccgo
+// +build gc
#include "textflag.h"
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_mipsx.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_mipsx.s
index 99e5399045..d333f13cff 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_mipsx.s
+++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_mipsx.s
@@ -4,7 +4,7 @@
// +build linux
// +build mips mipsle
-// +build !gccgo
+// +build gc
#include "textflag.h"
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_ppc64x.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_ppc64x.s
index 88f7125578..459a629c27 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_ppc64x.s
+++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_ppc64x.s
@@ -4,7 +4,7 @@
// +build linux
// +build ppc64 ppc64le
-// +build !gccgo
+// +build gc
#include "textflag.h"
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_riscv64.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_riscv64.s
index 3cfefed2ec..04d38497c6 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_riscv64.s
+++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_riscv64.s
@@ -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 riscv64,!gccgo
+// +build riscv64,gc
#include "textflag.h"
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_s390x.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_s390x.s
index a5a863c6bd..cc303989e1 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_s390x.s
+++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_s390x.s
@@ -4,7 +4,7 @@
// +build s390x
// +build linux
-// +build !gccgo
+// +build gc
#include "textflag.h"
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_netbsd_386.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_netbsd_386.s
index 48bdcd7632..ae7b498d50 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/asm_netbsd_386.s
+++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_netbsd_386.s
@@ -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 gc
#include "textflag.h"
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_netbsd_amd64.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_netbsd_amd64.s
index 2ede05c72f..e57367c17a 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/asm_netbsd_amd64.s
+++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_netbsd_amd64.s
@@ -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 gc
#include "textflag.h"
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_netbsd_arm.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_netbsd_arm.s
index e8928571c4..d7da175e1a 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/asm_netbsd_arm.s
+++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_netbsd_arm.s
@@ -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 gc
#include "textflag.h"
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_netbsd_arm64.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_netbsd_arm64.s
index 6f98ba5a37..e7cbe1904c 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/asm_netbsd_arm64.s
+++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_netbsd_arm64.s
@@ -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 gc
#include "textflag.h"
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_openbsd_386.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_openbsd_386.s
index 00576f3c83..2f00b0310f 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/asm_openbsd_386.s
+++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_openbsd_386.s
@@ -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 gc
#include "textflag.h"
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_openbsd_amd64.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_openbsd_amd64.s
index 790ef77f86..07632c99ce 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/asm_openbsd_amd64.s
+++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_openbsd_amd64.s
@@ -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 gc
#include "textflag.h"
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_openbsd_arm.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_openbsd_arm.s
index 469bfa1003..73e997320f 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/asm_openbsd_arm.s
+++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_openbsd_arm.s
@@ -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 gc
#include "textflag.h"
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_openbsd_arm64.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_openbsd_arm64.s
index 0cedea3d39..c47302aa46 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/asm_openbsd_arm64.s
+++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_openbsd_arm64.s
@@ -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 gc
#include "textflag.h"
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_openbsd_mips64.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_openbsd_mips64.s
index 567a4763c8..47c93fcb6c 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/asm_openbsd_mips64.s
+++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_openbsd_mips64.s
@@ -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 gc
#include "textflag.h"
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_solaris_amd64.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_solaris_amd64.s
index ded8260f3e..1f2c755a72 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/asm_solaris_amd64.s
+++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_solaris_amd64.s
@@ -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 gc
#include "textflag.h"
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/endian_big.go b/src/cmd/vendor/golang.org/x/sys/unix/endian_big.go
index 5e9269063f..86781eac22 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/endian_big.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/endian_big.go
@@ -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 ppc64 s390x mips mips64
+// +build armbe arm64be m68k mips mips64 mips64p32 ppc ppc64 s390 s390x shbe sparc sparc64
package unix
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/endian_little.go b/src/cmd/vendor/golang.org/x/sys/unix/endian_little.go
index bcdb5d30eb..8822d8541f 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/endian_little.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/endian_little.go
@@ -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 386 amd64 amd64p32 arm arm64 ppc64le mipsle mips64le riscv64
+// +build 386 amd64 amd64p32 alpha arm arm64 mipsle mips64le mips64p32le nios2 ppc64le riscv riscv64 sh
package unix
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/mkerrors.sh b/src/cmd/vendor/golang.org/x/sys/unix/mkerrors.sh
index 0c9a5c44bb..c0f9f2d523 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/mkerrors.sh
+++ b/src/cmd/vendor/golang.org/x/sys/unix/mkerrors.sh
@@ -225,6 +225,7 @@ struct ltchars {
#include
#include
#include
+#include
#include
#include
#include
@@ -561,6 +562,7 @@ ccflags="$@"
$2 ~ /^CRYPTO_/ ||
$2 ~ /^TIPC_/ ||
$2 ~ /^DEVLINK_/ ||
+ $2 ~ /^LWTUNNEL_IP/ ||
$2 !~ "WMESGLEN" &&
$2 ~ /^W[A-Z0-9]+$/ ||
$2 ~/^PPPIOC/ ||
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin.1_13.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin.1_13.go
index dc0befee37..ee852f1abc 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin.1_13.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin.1_13.go
@@ -26,7 +26,6 @@ func fdopendir(fd int) (dir uintptr, err error) {
func libc_fdopendir_trampoline()
-//go:linkname libc_fdopendir libc_fdopendir
//go:cgo_import_dynamic libc_fdopendir fdopendir "/usr/lib/libSystem.B.dylib"
func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_dragonfly.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_dragonfly.go
index 842ab5acde..a4f2944a24 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_dragonfly.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_dragonfly.go
@@ -105,6 +105,19 @@ func Pipe(p []int) (err error) {
return
}
+//sysnb pipe2(p *[2]_C_int, flags int) (err error)
+
+func Pipe2(p []int, flags int) error {
+ if len(p) != 2 {
+ return EINVAL
+ }
+ var pp [2]_C_int
+ err := pipe2(&pp, flags)
+ p[0] = int(pp[0])
+ p[1] = int(pp[1])
+ return err
+}
+
//sys extpread(fd int, p []byte, flags int, offset int64) (n int, err error)
func Pread(fd int, p []byte, offset int64) (n int, err error) {
return extpread(fd, p, 0, offset)
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux.go
index 84a9e5277a..28be1306ec 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux.go
@@ -641,6 +641,36 @@ func (sa *SockaddrCAN) sockaddr() (unsafe.Pointer, _Socklen, error) {
return unsafe.Pointer(&sa.raw), SizeofSockaddrCAN, nil
}
+// SockaddrCANJ1939 implements the Sockaddr interface for AF_CAN using J1939
+// protocol (https://en.wikipedia.org/wiki/SAE_J1939). For more information
+// on the purposes of the fields, check the official linux kernel documentation
+// available here: https://www.kernel.org/doc/Documentation/networking/j1939.rst
+type SockaddrCANJ1939 struct {
+ Ifindex int
+ Name uint64
+ PGN uint32
+ Addr uint8
+ raw RawSockaddrCAN
+}
+
+func (sa *SockaddrCANJ1939) sockaddr() (unsafe.Pointer, _Socklen, error) {
+ if sa.Ifindex < 0 || sa.Ifindex > 0x7fffffff {
+ return nil, 0, EINVAL
+ }
+ sa.raw.Family = AF_CAN
+ sa.raw.Ifindex = int32(sa.Ifindex)
+ n := (*[8]byte)(unsafe.Pointer(&sa.Name))
+ for i := 0; i < 8; i++ {
+ sa.raw.Addr[i] = n[i]
+ }
+ p := (*[4]byte)(unsafe.Pointer(&sa.PGN))
+ for i := 0; i < 4; i++ {
+ sa.raw.Addr[i+8] = p[i]
+ }
+ sa.raw.Addr[12] = sa.Addr
+ return unsafe.Pointer(&sa.raw), SizeofSockaddrCAN, nil
+}
+
// SockaddrALG implements the Sockaddr interface for AF_ALG type sockets.
// SockaddrALG enables userspace access to the Linux kernel's cryptography
// subsystem. The Type and Name fields specify which type of hash or cipher
@@ -952,6 +982,10 @@ func (sa *SockaddrIUCV) sockaddr() (unsafe.Pointer, _Socklen, error) {
return unsafe.Pointer(&sa.raw), SizeofSockaddrIUCV, nil
}
+var socketProtocol = func(fd int) (int, error) {
+ return GetsockoptInt(fd, SOL_SOCKET, SO_PROTOCOL)
+}
+
func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
switch rsa.Addr.Family {
case AF_NETLINK:
@@ -1002,7 +1036,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
return sa, nil
case AF_INET:
- proto, err := GetsockoptInt(fd, SOL_SOCKET, SO_PROTOCOL)
+ proto, err := socketProtocol(fd)
if err != nil {
return nil, err
}
@@ -1028,7 +1062,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
}
case AF_INET6:
- proto, err := GetsockoptInt(fd, SOL_SOCKET, SO_PROTOCOL)
+ proto, err := socketProtocol(fd)
if err != nil {
return nil, err
}
@@ -1063,7 +1097,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
}
return sa, nil
case AF_BLUETOOTH:
- proto, err := GetsockoptInt(fd, SOL_SOCKET, SO_PROTOCOL)
+ proto, err := socketProtocol(fd)
if err != nil {
return nil, err
}
@@ -1150,20 +1184,43 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
return sa, nil
case AF_CAN:
- pp := (*RawSockaddrCAN)(unsafe.Pointer(rsa))
- sa := &SockaddrCAN{
- Ifindex: int(pp.Ifindex),
+ proto, err := socketProtocol(fd)
+ if err != nil {
+ return nil, err
}
- rx := (*[4]byte)(unsafe.Pointer(&sa.RxID))
- for i := 0; i < 4; i++ {
- rx[i] = pp.Addr[i]
- }
- tx := (*[4]byte)(unsafe.Pointer(&sa.TxID))
- for i := 0; i < 4; i++ {
- tx[i] = pp.Addr[i+4]
- }
- return sa, nil
+ pp := (*RawSockaddrCAN)(unsafe.Pointer(rsa))
+
+ switch proto {
+ case CAN_J1939:
+ sa := &SockaddrCANJ1939{
+ Ifindex: int(pp.Ifindex),
+ }
+ name := (*[8]byte)(unsafe.Pointer(&sa.Name))
+ for i := 0; i < 8; i++ {
+ name[i] = pp.Addr[i]
+ }
+ pgn := (*[4]byte)(unsafe.Pointer(&sa.PGN))
+ for i := 0; i < 4; i++ {
+ pgn[i] = pp.Addr[i+8]
+ }
+ addr := (*[1]byte)(unsafe.Pointer(&sa.Addr))
+ addr[0] = pp.Addr[12]
+ return sa, nil
+ default:
+ sa := &SockaddrCAN{
+ Ifindex: int(pp.Ifindex),
+ }
+ rx := (*[4]byte)(unsafe.Pointer(&sa.RxID))
+ for i := 0; i < 4; i++ {
+ rx[i] = pp.Addr[i]
+ }
+ tx := (*[4]byte)(unsafe.Pointer(&sa.TxID))
+ for i := 0; i < 4; i++ {
+ tx[i] = pp.Addr[i+4]
+ }
+ return sa, nil
+ }
}
return nil, EAFNOSUPPORT
}
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_amd64_gc.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_amd64_gc.go
index 21a4946ba5..baa771f8ad 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_amd64_gc.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_amd64_gc.go
@@ -3,7 +3,7 @@
// license that can be found in the LICENSE file.
// +build amd64,linux
-// +build !gccgo
+// +build gc
package unix
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_gc.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_gc.go
index c26e6ec231..9edf3961b0 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_gc.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_gc.go
@@ -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 linux,!gccgo
+// +build linux,gc
package unix
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_gc_386.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_gc_386.go
index 070bd38994..90e33d8cf7 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_gc_386.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_gc_386.go
@@ -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 linux,!gccgo,386
+// +build linux,gc,386
package unix
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_gc_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_gc_arm.go
index 8c514c95ed..1a97baae73 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_gc_arm.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_gc_arm.go
@@ -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 arm,!gccgo,linux
+// +build arm,gc,linux
package unix
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_unix_gc.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_unix_gc.go
index 1c70d1b690..87bd161cef 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_unix_gc.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_unix_gc.go
@@ -3,7 +3,7 @@
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
-// +build !gccgo,!ppc64le,!ppc64
+// +build gc,!ppc64le,!ppc64
package unix
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_unix_gc_ppc64x.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_unix_gc_ppc64x.go
index 86dc765aba..d36216c3ca 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_unix_gc_ppc64x.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_unix_gc_ppc64x.go
@@ -4,7 +4,7 @@
// +build linux
// +build ppc64le ppc64
-// +build !gccgo
+// +build gc
package unix
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux.go
index 2069fb861d..b46110354d 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux.go
@@ -1217,6 +1217,12 @@ const (
LOOP_SET_STATUS_SETTABLE_FLAGS = 0xc
LO_KEY_SIZE = 0x20
LO_NAME_SIZE = 0x40
+ LWTUNNEL_IP6_MAX = 0x8
+ LWTUNNEL_IP_MAX = 0x8
+ LWTUNNEL_IP_OPTS_MAX = 0x3
+ LWTUNNEL_IP_OPT_ERSPAN_MAX = 0x4
+ LWTUNNEL_IP_OPT_GENEVE_MAX = 0x3
+ LWTUNNEL_IP_OPT_VXLAN_MAX = 0x1
MADV_COLD = 0x14
MADV_DODUMP = 0x11
MADV_DOFORK = 0xb
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gc.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gc.go
index 4b3a8ad7be..0550da06d1 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gc.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gc.go
@@ -2,7 +2,7 @@
// Code generated by the command above; see README.md. DO NOT EDIT.
// +build aix,ppc64
-// +build !gccgo
+// +build gc
package unix
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.1_13.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.1_13.go
index e263fbdb8b..c8c142c59a 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.1_13.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.1_13.go
@@ -24,7 +24,6 @@ func closedir(dir uintptr) (err error) {
func libc_closedir_trampoline()
-//go:linkname libc_closedir libc_closedir
//go:cgo_import_dynamic libc_closedir closedir "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -37,5 +36,4 @@ func readdir_r(dir uintptr, entry *Dirent, result **Dirent) (res Errno) {
func libc_readdir_r_trampoline()
-//go:linkname libc_readdir_r libc_readdir_r
//go:cgo_import_dynamic libc_readdir_r readdir_r "/usr/lib/libSystem.B.dylib"
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.go
index 6eb4579832..7f0f117d32 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.go
@@ -25,7 +25,6 @@ func getgroups(ngid int, gid *_Gid_t) (n int, err error) {
func libc_getgroups_trampoline()
-//go:linkname libc_getgroups libc_getgroups
//go:cgo_import_dynamic libc_getgroups getgroups "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -40,7 +39,6 @@ func setgroups(ngid int, gid *_Gid_t) (err error) {
func libc_setgroups_trampoline()
-//go:linkname libc_setgroups libc_setgroups
//go:cgo_import_dynamic libc_setgroups setgroups "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -56,7 +54,6 @@ func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err
func libc_wait4_trampoline()
-//go:linkname libc_wait4 libc_wait4
//go:cgo_import_dynamic libc_wait4 wait4 "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -72,7 +69,6 @@ func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) {
func libc_accept_trampoline()
-//go:linkname libc_accept libc_accept
//go:cgo_import_dynamic libc_accept accept "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -87,7 +83,6 @@ func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) {
func libc_bind_trampoline()
-//go:linkname libc_bind libc_bind
//go:cgo_import_dynamic libc_bind bind "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -102,7 +97,6 @@ func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) {
func libc_connect_trampoline()
-//go:linkname libc_connect libc_connect
//go:cgo_import_dynamic libc_connect connect "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -118,7 +112,6 @@ func socket(domain int, typ int, proto int) (fd int, err error) {
func libc_socket_trampoline()
-//go:linkname libc_socket libc_socket
//go:cgo_import_dynamic libc_socket socket "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -133,7 +126,6 @@ func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen
func libc_getsockopt_trampoline()
-//go:linkname libc_getsockopt libc_getsockopt
//go:cgo_import_dynamic libc_getsockopt getsockopt "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -148,7 +140,6 @@ func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr)
func libc_setsockopt_trampoline()
-//go:linkname libc_setsockopt libc_setsockopt
//go:cgo_import_dynamic libc_setsockopt setsockopt "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -163,7 +154,6 @@ func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
func libc_getpeername_trampoline()
-//go:linkname libc_getpeername libc_getpeername
//go:cgo_import_dynamic libc_getpeername getpeername "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -178,7 +168,6 @@ func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
func libc_getsockname_trampoline()
-//go:linkname libc_getsockname libc_getsockname
//go:cgo_import_dynamic libc_getsockname getsockname "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -193,7 +182,6 @@ func Shutdown(s int, how int) (err error) {
func libc_shutdown_trampoline()
-//go:linkname libc_shutdown libc_shutdown
//go:cgo_import_dynamic libc_shutdown shutdown "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -208,7 +196,6 @@ func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) {
func libc_socketpair_trampoline()
-//go:linkname libc_socketpair libc_socketpair
//go:cgo_import_dynamic libc_socketpair socketpair "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -230,7 +217,6 @@ func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Sockl
func libc_recvfrom_trampoline()
-//go:linkname libc_recvfrom libc_recvfrom
//go:cgo_import_dynamic libc_recvfrom recvfrom "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -251,7 +237,6 @@ func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (
func libc_sendto_trampoline()
-//go:linkname libc_sendto libc_sendto
//go:cgo_import_dynamic libc_sendto sendto "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -267,7 +252,6 @@ func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) {
func libc_recvmsg_trampoline()
-//go:linkname libc_recvmsg libc_recvmsg
//go:cgo_import_dynamic libc_recvmsg recvmsg "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -283,7 +267,6 @@ func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) {
func libc_sendmsg_trampoline()
-//go:linkname libc_sendmsg libc_sendmsg
//go:cgo_import_dynamic libc_sendmsg sendmsg "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -299,7 +282,6 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne
func libc_kevent_trampoline()
-//go:linkname libc_kevent libc_kevent
//go:cgo_import_dynamic libc_kevent kevent "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -319,7 +301,6 @@ func utimes(path string, timeval *[2]Timeval) (err error) {
func libc_utimes_trampoline()
-//go:linkname libc_utimes libc_utimes
//go:cgo_import_dynamic libc_utimes utimes "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -334,7 +315,6 @@ func futimes(fd int, timeval *[2]Timeval) (err error) {
func libc_futimes_trampoline()
-//go:linkname libc_futimes libc_futimes
//go:cgo_import_dynamic libc_futimes futimes "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -350,7 +330,6 @@ func poll(fds *PollFd, nfds int, timeout int) (n int, err error) {
func libc_poll_trampoline()
-//go:linkname libc_poll libc_poll
//go:cgo_import_dynamic libc_poll poll "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -371,7 +350,6 @@ func Madvise(b []byte, behav int) (err error) {
func libc_madvise_trampoline()
-//go:linkname libc_madvise libc_madvise
//go:cgo_import_dynamic libc_madvise madvise "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -392,7 +370,6 @@ func Mlock(b []byte) (err error) {
func libc_mlock_trampoline()
-//go:linkname libc_mlock libc_mlock
//go:cgo_import_dynamic libc_mlock mlock "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -407,7 +384,6 @@ func Mlockall(flags int) (err error) {
func libc_mlockall_trampoline()
-//go:linkname libc_mlockall libc_mlockall
//go:cgo_import_dynamic libc_mlockall mlockall "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -428,7 +404,6 @@ func Mprotect(b []byte, prot int) (err error) {
func libc_mprotect_trampoline()
-//go:linkname libc_mprotect libc_mprotect
//go:cgo_import_dynamic libc_mprotect mprotect "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -449,7 +424,6 @@ func Msync(b []byte, flags int) (err error) {
func libc_msync_trampoline()
-//go:linkname libc_msync libc_msync
//go:cgo_import_dynamic libc_msync msync "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -470,7 +444,6 @@ func Munlock(b []byte) (err error) {
func libc_munlock_trampoline()
-//go:linkname libc_munlock libc_munlock
//go:cgo_import_dynamic libc_munlock munlock "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -485,7 +458,6 @@ func Munlockall() (err error) {
func libc_munlockall_trampoline()
-//go:linkname libc_munlockall libc_munlockall
//go:cgo_import_dynamic libc_munlockall munlockall "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -502,7 +474,6 @@ func pipe() (r int, w int, err error) {
func libc_pipe_trampoline()
-//go:linkname libc_pipe libc_pipe
//go:cgo_import_dynamic libc_pipe pipe "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -528,7 +499,6 @@ func getxattr(path string, attr string, dest *byte, size int, position uint32, o
func libc_getxattr_trampoline()
-//go:linkname libc_getxattr libc_getxattr
//go:cgo_import_dynamic libc_getxattr getxattr "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -549,7 +519,6 @@ func fgetxattr(fd int, attr string, dest *byte, size int, position uint32, optio
func libc_fgetxattr_trampoline()
-//go:linkname libc_fgetxattr libc_fgetxattr
//go:cgo_import_dynamic libc_fgetxattr fgetxattr "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -574,7 +543,6 @@ func setxattr(path string, attr string, data *byte, size int, position uint32, o
func libc_setxattr_trampoline()
-//go:linkname libc_setxattr libc_setxattr
//go:cgo_import_dynamic libc_setxattr setxattr "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -594,7 +562,6 @@ func fsetxattr(fd int, attr string, data *byte, size int, position uint32, optio
func libc_fsetxattr_trampoline()
-//go:linkname libc_fsetxattr libc_fsetxattr
//go:cgo_import_dynamic libc_fsetxattr fsetxattr "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -619,7 +586,6 @@ func removexattr(path string, attr string, options int) (err error) {
func libc_removexattr_trampoline()
-//go:linkname libc_removexattr libc_removexattr
//go:cgo_import_dynamic libc_removexattr removexattr "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -639,7 +605,6 @@ func fremovexattr(fd int, attr string, options int) (err error) {
func libc_fremovexattr_trampoline()
-//go:linkname libc_fremovexattr libc_fremovexattr
//go:cgo_import_dynamic libc_fremovexattr fremovexattr "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -660,7 +625,6 @@ func listxattr(path string, dest *byte, size int, options int) (sz int, err erro
func libc_listxattr_trampoline()
-//go:linkname libc_listxattr libc_listxattr
//go:cgo_import_dynamic libc_listxattr listxattr "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -676,7 +640,6 @@ func flistxattr(fd int, dest *byte, size int, options int) (sz int, err error) {
func libc_flistxattr_trampoline()
-//go:linkname libc_flistxattr libc_flistxattr
//go:cgo_import_dynamic libc_flistxattr flistxattr "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -691,7 +654,6 @@ func setattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintp
func libc_setattrlist_trampoline()
-//go:linkname libc_setattrlist libc_setattrlist
//go:cgo_import_dynamic libc_setattrlist setattrlist "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -707,7 +669,6 @@ func fcntl(fd int, cmd int, arg int) (val int, err error) {
func libc_fcntl_trampoline()
-//go:linkname libc_fcntl libc_fcntl
//go:cgo_import_dynamic libc_fcntl fcntl "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -722,7 +683,6 @@ func kill(pid int, signum int, posix int) (err error) {
func libc_kill_trampoline()
-//go:linkname libc_kill libc_kill
//go:cgo_import_dynamic libc_kill kill "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -737,7 +697,6 @@ func ioctl(fd int, req uint, arg uintptr) (err error) {
func libc_ioctl_trampoline()
-//go:linkname libc_ioctl libc_ioctl
//go:cgo_import_dynamic libc_ioctl ioctl "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -758,7 +717,6 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr)
func libc_sysctl_trampoline()
-//go:linkname libc_sysctl libc_sysctl
//go:cgo_import_dynamic libc_sysctl sysctl "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -773,7 +731,6 @@ func sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer
func libc_sendfile_trampoline()
-//go:linkname libc_sendfile libc_sendfile
//go:cgo_import_dynamic libc_sendfile sendfile "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -793,7 +750,6 @@ func Access(path string, mode uint32) (err error) {
func libc_access_trampoline()
-//go:linkname libc_access libc_access
//go:cgo_import_dynamic libc_access access "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -808,7 +764,6 @@ func Adjtime(delta *Timeval, olddelta *Timeval) (err error) {
func libc_adjtime_trampoline()
-//go:linkname libc_adjtime libc_adjtime
//go:cgo_import_dynamic libc_adjtime adjtime "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -828,7 +783,6 @@ func Chdir(path string) (err error) {
func libc_chdir_trampoline()
-//go:linkname libc_chdir libc_chdir
//go:cgo_import_dynamic libc_chdir chdir "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -848,7 +802,6 @@ func Chflags(path string, flags int) (err error) {
func libc_chflags_trampoline()
-//go:linkname libc_chflags libc_chflags
//go:cgo_import_dynamic libc_chflags chflags "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -868,7 +821,6 @@ func Chmod(path string, mode uint32) (err error) {
func libc_chmod_trampoline()
-//go:linkname libc_chmod libc_chmod
//go:cgo_import_dynamic libc_chmod chmod "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -888,7 +840,6 @@ func Chown(path string, uid int, gid int) (err error) {
func libc_chown_trampoline()
-//go:linkname libc_chown libc_chown
//go:cgo_import_dynamic libc_chown chown "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -908,7 +859,6 @@ func Chroot(path string) (err error) {
func libc_chroot_trampoline()
-//go:linkname libc_chroot libc_chroot
//go:cgo_import_dynamic libc_chroot chroot "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -923,7 +873,6 @@ func ClockGettime(clockid int32, time *Timespec) (err error) {
func libc_clock_gettime_trampoline()
-//go:linkname libc_clock_gettime libc_clock_gettime
//go:cgo_import_dynamic libc_clock_gettime clock_gettime "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -938,7 +887,6 @@ func Close(fd int) (err error) {
func libc_close_trampoline()
-//go:linkname libc_close libc_close
//go:cgo_import_dynamic libc_close close "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -963,7 +911,6 @@ func Clonefile(src string, dst string, flags int) (err error) {
func libc_clonefile_trampoline()
-//go:linkname libc_clonefile libc_clonefile
//go:cgo_import_dynamic libc_clonefile clonefile "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -988,7 +935,6 @@ func Clonefileat(srcDirfd int, src string, dstDirfd int, dst string, flags int)
func libc_clonefileat_trampoline()
-//go:linkname libc_clonefileat libc_clonefileat
//go:cgo_import_dynamic libc_clonefileat clonefileat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1004,7 +950,6 @@ func Dup(fd int) (nfd int, err error) {
func libc_dup_trampoline()
-//go:linkname libc_dup libc_dup
//go:cgo_import_dynamic libc_dup dup "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1019,7 +964,6 @@ func Dup2(from int, to int) (err error) {
func libc_dup2_trampoline()
-//go:linkname libc_dup2 libc_dup2
//go:cgo_import_dynamic libc_dup2 dup2 "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1044,7 +988,6 @@ func Exchangedata(path1 string, path2 string, options int) (err error) {
func libc_exchangedata_trampoline()
-//go:linkname libc_exchangedata libc_exchangedata
//go:cgo_import_dynamic libc_exchangedata exchangedata "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1056,7 +999,6 @@ func Exit(code int) {
func libc_exit_trampoline()
-//go:linkname libc_exit libc_exit
//go:cgo_import_dynamic libc_exit exit "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1076,7 +1018,6 @@ func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) {
func libc_faccessat_trampoline()
-//go:linkname libc_faccessat libc_faccessat
//go:cgo_import_dynamic libc_faccessat faccessat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1091,7 +1032,6 @@ func Fchdir(fd int) (err error) {
func libc_fchdir_trampoline()
-//go:linkname libc_fchdir libc_fchdir
//go:cgo_import_dynamic libc_fchdir fchdir "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1106,7 +1046,6 @@ func Fchflags(fd int, flags int) (err error) {
func libc_fchflags_trampoline()
-//go:linkname libc_fchflags libc_fchflags
//go:cgo_import_dynamic libc_fchflags fchflags "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1121,7 +1060,6 @@ func Fchmod(fd int, mode uint32) (err error) {
func libc_fchmod_trampoline()
-//go:linkname libc_fchmod libc_fchmod
//go:cgo_import_dynamic libc_fchmod fchmod "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1141,7 +1079,6 @@ func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) {
func libc_fchmodat_trampoline()
-//go:linkname libc_fchmodat libc_fchmodat
//go:cgo_import_dynamic libc_fchmodat fchmodat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1156,7 +1093,6 @@ func Fchown(fd int, uid int, gid int) (err error) {
func libc_fchown_trampoline()
-//go:linkname libc_fchown libc_fchown
//go:cgo_import_dynamic libc_fchown fchown "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1176,7 +1112,6 @@ func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) {
func libc_fchownat_trampoline()
-//go:linkname libc_fchownat libc_fchownat
//go:cgo_import_dynamic libc_fchownat fchownat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1196,7 +1131,6 @@ func Fclonefileat(srcDirfd int, dstDirfd int, dst string, flags int) (err error)
func libc_fclonefileat_trampoline()
-//go:linkname libc_fclonefileat libc_fclonefileat
//go:cgo_import_dynamic libc_fclonefileat fclonefileat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1211,7 +1145,6 @@ func Flock(fd int, how int) (err error) {
func libc_flock_trampoline()
-//go:linkname libc_flock libc_flock
//go:cgo_import_dynamic libc_flock flock "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1227,7 +1160,6 @@ func Fpathconf(fd int, name int) (val int, err error) {
func libc_fpathconf_trampoline()
-//go:linkname libc_fpathconf libc_fpathconf
//go:cgo_import_dynamic libc_fpathconf fpathconf "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1242,7 +1174,6 @@ func Fsync(fd int) (err error) {
func libc_fsync_trampoline()
-//go:linkname libc_fsync libc_fsync
//go:cgo_import_dynamic libc_fsync fsync "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1257,7 +1188,6 @@ func Ftruncate(fd int, length int64) (err error) {
func libc_ftruncate_trampoline()
-//go:linkname libc_ftruncate libc_ftruncate
//go:cgo_import_dynamic libc_ftruncate ftruncate "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1279,7 +1209,6 @@ func Getcwd(buf []byte) (n int, err error) {
func libc_getcwd_trampoline()
-//go:linkname libc_getcwd libc_getcwd
//go:cgo_import_dynamic libc_getcwd getcwd "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1292,7 +1221,6 @@ func Getdtablesize() (size int) {
func libc_getdtablesize_trampoline()
-//go:linkname libc_getdtablesize libc_getdtablesize
//go:cgo_import_dynamic libc_getdtablesize getdtablesize "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1305,7 +1233,6 @@ func Getegid() (egid int) {
func libc_getegid_trampoline()
-//go:linkname libc_getegid libc_getegid
//go:cgo_import_dynamic libc_getegid getegid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1318,7 +1245,6 @@ func Geteuid() (uid int) {
func libc_geteuid_trampoline()
-//go:linkname libc_geteuid libc_geteuid
//go:cgo_import_dynamic libc_geteuid geteuid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1331,7 +1257,6 @@ func Getgid() (gid int) {
func libc_getgid_trampoline()
-//go:linkname libc_getgid libc_getgid
//go:cgo_import_dynamic libc_getgid getgid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1347,7 +1272,6 @@ func Getpgid(pid int) (pgid int, err error) {
func libc_getpgid_trampoline()
-//go:linkname libc_getpgid libc_getpgid
//go:cgo_import_dynamic libc_getpgid getpgid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1360,7 +1284,6 @@ func Getpgrp() (pgrp int) {
func libc_getpgrp_trampoline()
-//go:linkname libc_getpgrp libc_getpgrp
//go:cgo_import_dynamic libc_getpgrp getpgrp "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1373,7 +1296,6 @@ func Getpid() (pid int) {
func libc_getpid_trampoline()
-//go:linkname libc_getpid libc_getpid
//go:cgo_import_dynamic libc_getpid getpid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1386,7 +1308,6 @@ func Getppid() (ppid int) {
func libc_getppid_trampoline()
-//go:linkname libc_getppid libc_getppid
//go:cgo_import_dynamic libc_getppid getppid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1402,7 +1323,6 @@ func Getpriority(which int, who int) (prio int, err error) {
func libc_getpriority_trampoline()
-//go:linkname libc_getpriority libc_getpriority
//go:cgo_import_dynamic libc_getpriority getpriority "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1417,7 +1337,6 @@ func Getrlimit(which int, lim *Rlimit) (err error) {
func libc_getrlimit_trampoline()
-//go:linkname libc_getrlimit libc_getrlimit
//go:cgo_import_dynamic libc_getrlimit getrlimit "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1432,7 +1351,6 @@ func Getrusage(who int, rusage *Rusage) (err error) {
func libc_getrusage_trampoline()
-//go:linkname libc_getrusage libc_getrusage
//go:cgo_import_dynamic libc_getrusage getrusage "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1448,7 +1366,6 @@ func Getsid(pid int) (sid int, err error) {
func libc_getsid_trampoline()
-//go:linkname libc_getsid libc_getsid
//go:cgo_import_dynamic libc_getsid getsid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1463,7 +1380,6 @@ func Gettimeofday(tp *Timeval) (err error) {
func libc_gettimeofday_trampoline()
-//go:linkname libc_gettimeofday libc_gettimeofday
//go:cgo_import_dynamic libc_gettimeofday gettimeofday "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1476,7 +1392,6 @@ func Getuid() (uid int) {
func libc_getuid_trampoline()
-//go:linkname libc_getuid libc_getuid
//go:cgo_import_dynamic libc_getuid getuid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1489,7 +1404,6 @@ func Issetugid() (tainted bool) {
func libc_issetugid_trampoline()
-//go:linkname libc_issetugid libc_issetugid
//go:cgo_import_dynamic libc_issetugid issetugid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1505,7 +1419,6 @@ func Kqueue() (fd int, err error) {
func libc_kqueue_trampoline()
-//go:linkname libc_kqueue libc_kqueue
//go:cgo_import_dynamic libc_kqueue kqueue "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1525,7 +1438,6 @@ func Lchown(path string, uid int, gid int) (err error) {
func libc_lchown_trampoline()
-//go:linkname libc_lchown libc_lchown
//go:cgo_import_dynamic libc_lchown lchown "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1550,7 +1462,6 @@ func Link(path string, link string) (err error) {
func libc_link_trampoline()
-//go:linkname libc_link libc_link
//go:cgo_import_dynamic libc_link link "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1575,7 +1486,6 @@ func Linkat(pathfd int, path string, linkfd int, link string, flags int) (err er
func libc_linkat_trampoline()
-//go:linkname libc_linkat libc_linkat
//go:cgo_import_dynamic libc_linkat linkat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1590,7 +1500,6 @@ func Listen(s int, backlog int) (err error) {
func libc_listen_trampoline()
-//go:linkname libc_listen libc_listen
//go:cgo_import_dynamic libc_listen listen "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1610,7 +1519,6 @@ func Mkdir(path string, mode uint32) (err error) {
func libc_mkdir_trampoline()
-//go:linkname libc_mkdir libc_mkdir
//go:cgo_import_dynamic libc_mkdir mkdir "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1630,7 +1538,6 @@ func Mkdirat(dirfd int, path string, mode uint32) (err error) {
func libc_mkdirat_trampoline()
-//go:linkname libc_mkdirat libc_mkdirat
//go:cgo_import_dynamic libc_mkdirat mkdirat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1650,7 +1557,6 @@ func Mkfifo(path string, mode uint32) (err error) {
func libc_mkfifo_trampoline()
-//go:linkname libc_mkfifo libc_mkfifo
//go:cgo_import_dynamic libc_mkfifo mkfifo "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1670,7 +1576,6 @@ func Mknod(path string, mode uint32, dev int) (err error) {
func libc_mknod_trampoline()
-//go:linkname libc_mknod libc_mknod
//go:cgo_import_dynamic libc_mknod mknod "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1691,7 +1596,6 @@ func Open(path string, mode int, perm uint32) (fd int, err error) {
func libc_open_trampoline()
-//go:linkname libc_open libc_open
//go:cgo_import_dynamic libc_open open "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1712,7 +1616,6 @@ func Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) {
func libc_openat_trampoline()
-//go:linkname libc_openat libc_openat
//go:cgo_import_dynamic libc_openat openat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1733,7 +1636,6 @@ func Pathconf(path string, name int) (val int, err error) {
func libc_pathconf_trampoline()
-//go:linkname libc_pathconf libc_pathconf
//go:cgo_import_dynamic libc_pathconf pathconf "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1755,7 +1657,6 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) {
func libc_pread_trampoline()
-//go:linkname libc_pread libc_pread
//go:cgo_import_dynamic libc_pread pread "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1777,7 +1678,6 @@ func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
func libc_pwrite_trampoline()
-//go:linkname libc_pwrite libc_pwrite
//go:cgo_import_dynamic libc_pwrite pwrite "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1799,7 +1699,6 @@ func read(fd int, p []byte) (n int, err error) {
func libc_read_trampoline()
-//go:linkname libc_read libc_read
//go:cgo_import_dynamic libc_read read "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1826,7 +1725,6 @@ func Readlink(path string, buf []byte) (n int, err error) {
func libc_readlink_trampoline()
-//go:linkname libc_readlink libc_readlink
//go:cgo_import_dynamic libc_readlink readlink "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1853,7 +1751,6 @@ func Readlinkat(dirfd int, path string, buf []byte) (n int, err error) {
func libc_readlinkat_trampoline()
-//go:linkname libc_readlinkat libc_readlinkat
//go:cgo_import_dynamic libc_readlinkat readlinkat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1878,7 +1775,6 @@ func Rename(from string, to string) (err error) {
func libc_rename_trampoline()
-//go:linkname libc_rename libc_rename
//go:cgo_import_dynamic libc_rename rename "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1903,7 +1799,6 @@ func Renameat(fromfd int, from string, tofd int, to string) (err error) {
func libc_renameat_trampoline()
-//go:linkname libc_renameat libc_renameat
//go:cgo_import_dynamic libc_renameat renameat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1923,7 +1818,6 @@ func Revoke(path string) (err error) {
func libc_revoke_trampoline()
-//go:linkname libc_revoke libc_revoke
//go:cgo_import_dynamic libc_revoke revoke "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1943,7 +1837,6 @@ func Rmdir(path string) (err error) {
func libc_rmdir_trampoline()
-//go:linkname libc_rmdir libc_rmdir
//go:cgo_import_dynamic libc_rmdir rmdir "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1959,7 +1852,6 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
func libc_lseek_trampoline()
-//go:linkname libc_lseek libc_lseek
//go:cgo_import_dynamic libc_lseek lseek "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1975,7 +1867,6 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err
func libc_select_trampoline()
-//go:linkname libc_select libc_select
//go:cgo_import_dynamic libc_select select "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1990,7 +1881,6 @@ func Setegid(egid int) (err error) {
func libc_setegid_trampoline()
-//go:linkname libc_setegid libc_setegid
//go:cgo_import_dynamic libc_setegid setegid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2005,7 +1895,6 @@ func Seteuid(euid int) (err error) {
func libc_seteuid_trampoline()
-//go:linkname libc_seteuid libc_seteuid
//go:cgo_import_dynamic libc_seteuid seteuid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2020,7 +1909,6 @@ func Setgid(gid int) (err error) {
func libc_setgid_trampoline()
-//go:linkname libc_setgid libc_setgid
//go:cgo_import_dynamic libc_setgid setgid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2040,7 +1928,6 @@ func Setlogin(name string) (err error) {
func libc_setlogin_trampoline()
-//go:linkname libc_setlogin libc_setlogin
//go:cgo_import_dynamic libc_setlogin setlogin "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2055,7 +1942,6 @@ func Setpgid(pid int, pgid int) (err error) {
func libc_setpgid_trampoline()
-//go:linkname libc_setpgid libc_setpgid
//go:cgo_import_dynamic libc_setpgid setpgid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2070,7 +1956,6 @@ func Setpriority(which int, who int, prio int) (err error) {
func libc_setpriority_trampoline()
-//go:linkname libc_setpriority libc_setpriority
//go:cgo_import_dynamic libc_setpriority setpriority "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2085,7 +1970,6 @@ func Setprivexec(flag int) (err error) {
func libc_setprivexec_trampoline()
-//go:linkname libc_setprivexec libc_setprivexec
//go:cgo_import_dynamic libc_setprivexec setprivexec "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2100,7 +1984,6 @@ func Setregid(rgid int, egid int) (err error) {
func libc_setregid_trampoline()
-//go:linkname libc_setregid libc_setregid
//go:cgo_import_dynamic libc_setregid setregid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2115,7 +1998,6 @@ func Setreuid(ruid int, euid int) (err error) {
func libc_setreuid_trampoline()
-//go:linkname libc_setreuid libc_setreuid
//go:cgo_import_dynamic libc_setreuid setreuid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2130,7 +2012,6 @@ func Setrlimit(which int, lim *Rlimit) (err error) {
func libc_setrlimit_trampoline()
-//go:linkname libc_setrlimit libc_setrlimit
//go:cgo_import_dynamic libc_setrlimit setrlimit "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2146,7 +2027,6 @@ func Setsid() (pid int, err error) {
func libc_setsid_trampoline()
-//go:linkname libc_setsid libc_setsid
//go:cgo_import_dynamic libc_setsid setsid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2161,7 +2041,6 @@ func Settimeofday(tp *Timeval) (err error) {
func libc_settimeofday_trampoline()
-//go:linkname libc_settimeofday libc_settimeofday
//go:cgo_import_dynamic libc_settimeofday settimeofday "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2176,7 +2055,6 @@ func Setuid(uid int) (err error) {
func libc_setuid_trampoline()
-//go:linkname libc_setuid libc_setuid
//go:cgo_import_dynamic libc_setuid setuid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2201,7 +2079,6 @@ func Symlink(path string, link string) (err error) {
func libc_symlink_trampoline()
-//go:linkname libc_symlink libc_symlink
//go:cgo_import_dynamic libc_symlink symlink "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2226,7 +2103,6 @@ func Symlinkat(oldpath string, newdirfd int, newpath string) (err error) {
func libc_symlinkat_trampoline()
-//go:linkname libc_symlinkat libc_symlinkat
//go:cgo_import_dynamic libc_symlinkat symlinkat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2241,7 +2117,6 @@ func Sync() (err error) {
func libc_sync_trampoline()
-//go:linkname libc_sync libc_sync
//go:cgo_import_dynamic libc_sync sync "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2261,7 +2136,6 @@ func Truncate(path string, length int64) (err error) {
func libc_truncate_trampoline()
-//go:linkname libc_truncate libc_truncate
//go:cgo_import_dynamic libc_truncate truncate "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2274,7 +2148,6 @@ func Umask(newmask int) (oldmask int) {
func libc_umask_trampoline()
-//go:linkname libc_umask libc_umask
//go:cgo_import_dynamic libc_umask umask "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2294,7 +2167,6 @@ func Undelete(path string) (err error) {
func libc_undelete_trampoline()
-//go:linkname libc_undelete libc_undelete
//go:cgo_import_dynamic libc_undelete undelete "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2314,7 +2186,6 @@ func Unlink(path string) (err error) {
func libc_unlink_trampoline()
-//go:linkname libc_unlink libc_unlink
//go:cgo_import_dynamic libc_unlink unlink "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2334,7 +2205,6 @@ func Unlinkat(dirfd int, path string, flags int) (err error) {
func libc_unlinkat_trampoline()
-//go:linkname libc_unlinkat libc_unlinkat
//go:cgo_import_dynamic libc_unlinkat unlinkat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2354,7 +2224,6 @@ func Unmount(path string, flags int) (err error) {
func libc_unmount_trampoline()
-//go:linkname libc_unmount libc_unmount
//go:cgo_import_dynamic libc_unmount unmount "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2376,7 +2245,6 @@ func write(fd int, p []byte) (n int, err error) {
func libc_write_trampoline()
-//go:linkname libc_write libc_write
//go:cgo_import_dynamic libc_write write "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2392,7 +2260,6 @@ func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (
func libc_mmap_trampoline()
-//go:linkname libc_mmap libc_mmap
//go:cgo_import_dynamic libc_mmap mmap "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2407,7 +2274,6 @@ func munmap(addr uintptr, length uintptr) (err error) {
func libc_munmap_trampoline()
-//go:linkname libc_munmap libc_munmap
//go:cgo_import_dynamic libc_munmap munmap "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2444,7 +2310,6 @@ func Fstat(fd int, stat *Stat_t) (err error) {
func libc_fstat64_trampoline()
-//go:linkname libc_fstat64 libc_fstat64
//go:cgo_import_dynamic libc_fstat64 fstat64 "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2464,7 +2329,6 @@ func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) {
func libc_fstatat64_trampoline()
-//go:linkname libc_fstatat64 libc_fstatat64
//go:cgo_import_dynamic libc_fstatat64 fstatat64 "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2479,7 +2343,6 @@ func Fstatfs(fd int, stat *Statfs_t) (err error) {
func libc_fstatfs64_trampoline()
-//go:linkname libc_fstatfs64 libc_fstatfs64
//go:cgo_import_dynamic libc_fstatfs64 fstatfs64 "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2495,7 +2358,6 @@ func getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) {
func libc_getfsstat64_trampoline()
-//go:linkname libc_getfsstat64 libc_getfsstat64
//go:cgo_import_dynamic libc_getfsstat64 getfsstat64 "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2515,7 +2377,6 @@ func Lstat(path string, stat *Stat_t) (err error) {
func libc_lstat64_trampoline()
-//go:linkname libc_lstat64 libc_lstat64
//go:cgo_import_dynamic libc_lstat64 lstat64 "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2530,7 +2391,6 @@ func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) {
func libc_ptrace_trampoline()
-//go:linkname libc_ptrace libc_ptrace
//go:cgo_import_dynamic libc_ptrace ptrace "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2550,7 +2410,6 @@ func Stat(path string, stat *Stat_t) (err error) {
func libc_stat64_trampoline()
-//go:linkname libc_stat64 libc_stat64
//go:cgo_import_dynamic libc_stat64 stat64 "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2570,5 +2429,4 @@ func Statfs(path string, stat *Statfs_t) (err error) {
func libc_statfs64_trampoline()
-//go:linkname libc_statfs64 libc_statfs64
//go:cgo_import_dynamic libc_statfs64 statfs64 "/usr/lib/libSystem.B.dylib"
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.1_13.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.1_13.go
index 314042a9d4..8882623613 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.1_13.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.1_13.go
@@ -24,7 +24,6 @@ func closedir(dir uintptr) (err error) {
func libc_closedir_trampoline()
-//go:linkname libc_closedir libc_closedir
//go:cgo_import_dynamic libc_closedir closedir "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -37,5 +36,4 @@ func readdir_r(dir uintptr, entry *Dirent, result **Dirent) (res Errno) {
func libc_readdir_r_trampoline()
-//go:linkname libc_readdir_r libc_readdir_r
//go:cgo_import_dynamic libc_readdir_r readdir_r "/usr/lib/libSystem.B.dylib"
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go
index 889c14059e..2daf0bd628 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go
@@ -25,7 +25,6 @@ func getgroups(ngid int, gid *_Gid_t) (n int, err error) {
func libc_getgroups_trampoline()
-//go:linkname libc_getgroups libc_getgroups
//go:cgo_import_dynamic libc_getgroups getgroups "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -40,7 +39,6 @@ func setgroups(ngid int, gid *_Gid_t) (err error) {
func libc_setgroups_trampoline()
-//go:linkname libc_setgroups libc_setgroups
//go:cgo_import_dynamic libc_setgroups setgroups "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -56,7 +54,6 @@ func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err
func libc_wait4_trampoline()
-//go:linkname libc_wait4 libc_wait4
//go:cgo_import_dynamic libc_wait4 wait4 "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -72,7 +69,6 @@ func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) {
func libc_accept_trampoline()
-//go:linkname libc_accept libc_accept
//go:cgo_import_dynamic libc_accept accept "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -87,7 +83,6 @@ func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) {
func libc_bind_trampoline()
-//go:linkname libc_bind libc_bind
//go:cgo_import_dynamic libc_bind bind "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -102,7 +97,6 @@ func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) {
func libc_connect_trampoline()
-//go:linkname libc_connect libc_connect
//go:cgo_import_dynamic libc_connect connect "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -118,7 +112,6 @@ func socket(domain int, typ int, proto int) (fd int, err error) {
func libc_socket_trampoline()
-//go:linkname libc_socket libc_socket
//go:cgo_import_dynamic libc_socket socket "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -133,7 +126,6 @@ func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen
func libc_getsockopt_trampoline()
-//go:linkname libc_getsockopt libc_getsockopt
//go:cgo_import_dynamic libc_getsockopt getsockopt "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -148,7 +140,6 @@ func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr)
func libc_setsockopt_trampoline()
-//go:linkname libc_setsockopt libc_setsockopt
//go:cgo_import_dynamic libc_setsockopt setsockopt "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -163,7 +154,6 @@ func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
func libc_getpeername_trampoline()
-//go:linkname libc_getpeername libc_getpeername
//go:cgo_import_dynamic libc_getpeername getpeername "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -178,7 +168,6 @@ func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
func libc_getsockname_trampoline()
-//go:linkname libc_getsockname libc_getsockname
//go:cgo_import_dynamic libc_getsockname getsockname "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -193,7 +182,6 @@ func Shutdown(s int, how int) (err error) {
func libc_shutdown_trampoline()
-//go:linkname libc_shutdown libc_shutdown
//go:cgo_import_dynamic libc_shutdown shutdown "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -208,7 +196,6 @@ func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) {
func libc_socketpair_trampoline()
-//go:linkname libc_socketpair libc_socketpair
//go:cgo_import_dynamic libc_socketpair socketpair "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -230,7 +217,6 @@ func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Sockl
func libc_recvfrom_trampoline()
-//go:linkname libc_recvfrom libc_recvfrom
//go:cgo_import_dynamic libc_recvfrom recvfrom "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -251,7 +237,6 @@ func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (
func libc_sendto_trampoline()
-//go:linkname libc_sendto libc_sendto
//go:cgo_import_dynamic libc_sendto sendto "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -267,7 +252,6 @@ func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) {
func libc_recvmsg_trampoline()
-//go:linkname libc_recvmsg libc_recvmsg
//go:cgo_import_dynamic libc_recvmsg recvmsg "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -283,7 +267,6 @@ func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) {
func libc_sendmsg_trampoline()
-//go:linkname libc_sendmsg libc_sendmsg
//go:cgo_import_dynamic libc_sendmsg sendmsg "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -299,7 +282,6 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne
func libc_kevent_trampoline()
-//go:linkname libc_kevent libc_kevent
//go:cgo_import_dynamic libc_kevent kevent "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -319,7 +301,6 @@ func utimes(path string, timeval *[2]Timeval) (err error) {
func libc_utimes_trampoline()
-//go:linkname libc_utimes libc_utimes
//go:cgo_import_dynamic libc_utimes utimes "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -334,7 +315,6 @@ func futimes(fd int, timeval *[2]Timeval) (err error) {
func libc_futimes_trampoline()
-//go:linkname libc_futimes libc_futimes
//go:cgo_import_dynamic libc_futimes futimes "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -350,7 +330,6 @@ func poll(fds *PollFd, nfds int, timeout int) (n int, err error) {
func libc_poll_trampoline()
-//go:linkname libc_poll libc_poll
//go:cgo_import_dynamic libc_poll poll "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -371,7 +350,6 @@ func Madvise(b []byte, behav int) (err error) {
func libc_madvise_trampoline()
-//go:linkname libc_madvise libc_madvise
//go:cgo_import_dynamic libc_madvise madvise "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -392,7 +370,6 @@ func Mlock(b []byte) (err error) {
func libc_mlock_trampoline()
-//go:linkname libc_mlock libc_mlock
//go:cgo_import_dynamic libc_mlock mlock "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -407,7 +384,6 @@ func Mlockall(flags int) (err error) {
func libc_mlockall_trampoline()
-//go:linkname libc_mlockall libc_mlockall
//go:cgo_import_dynamic libc_mlockall mlockall "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -428,7 +404,6 @@ func Mprotect(b []byte, prot int) (err error) {
func libc_mprotect_trampoline()
-//go:linkname libc_mprotect libc_mprotect
//go:cgo_import_dynamic libc_mprotect mprotect "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -449,7 +424,6 @@ func Msync(b []byte, flags int) (err error) {
func libc_msync_trampoline()
-//go:linkname libc_msync libc_msync
//go:cgo_import_dynamic libc_msync msync "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -470,7 +444,6 @@ func Munlock(b []byte) (err error) {
func libc_munlock_trampoline()
-//go:linkname libc_munlock libc_munlock
//go:cgo_import_dynamic libc_munlock munlock "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -485,7 +458,6 @@ func Munlockall() (err error) {
func libc_munlockall_trampoline()
-//go:linkname libc_munlockall libc_munlockall
//go:cgo_import_dynamic libc_munlockall munlockall "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -502,7 +474,6 @@ func pipe() (r int, w int, err error) {
func libc_pipe_trampoline()
-//go:linkname libc_pipe libc_pipe
//go:cgo_import_dynamic libc_pipe pipe "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -528,7 +499,6 @@ func getxattr(path string, attr string, dest *byte, size int, position uint32, o
func libc_getxattr_trampoline()
-//go:linkname libc_getxattr libc_getxattr
//go:cgo_import_dynamic libc_getxattr getxattr "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -549,7 +519,6 @@ func fgetxattr(fd int, attr string, dest *byte, size int, position uint32, optio
func libc_fgetxattr_trampoline()
-//go:linkname libc_fgetxattr libc_fgetxattr
//go:cgo_import_dynamic libc_fgetxattr fgetxattr "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -574,7 +543,6 @@ func setxattr(path string, attr string, data *byte, size int, position uint32, o
func libc_setxattr_trampoline()
-//go:linkname libc_setxattr libc_setxattr
//go:cgo_import_dynamic libc_setxattr setxattr "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -594,7 +562,6 @@ func fsetxattr(fd int, attr string, data *byte, size int, position uint32, optio
func libc_fsetxattr_trampoline()
-//go:linkname libc_fsetxattr libc_fsetxattr
//go:cgo_import_dynamic libc_fsetxattr fsetxattr "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -619,7 +586,6 @@ func removexattr(path string, attr string, options int) (err error) {
func libc_removexattr_trampoline()
-//go:linkname libc_removexattr libc_removexattr
//go:cgo_import_dynamic libc_removexattr removexattr "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -639,7 +605,6 @@ func fremovexattr(fd int, attr string, options int) (err error) {
func libc_fremovexattr_trampoline()
-//go:linkname libc_fremovexattr libc_fremovexattr
//go:cgo_import_dynamic libc_fremovexattr fremovexattr "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -660,7 +625,6 @@ func listxattr(path string, dest *byte, size int, options int) (sz int, err erro
func libc_listxattr_trampoline()
-//go:linkname libc_listxattr libc_listxattr
//go:cgo_import_dynamic libc_listxattr listxattr "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -676,7 +640,6 @@ func flistxattr(fd int, dest *byte, size int, options int) (sz int, err error) {
func libc_flistxattr_trampoline()
-//go:linkname libc_flistxattr libc_flistxattr
//go:cgo_import_dynamic libc_flistxattr flistxattr "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -691,7 +654,6 @@ func setattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintp
func libc_setattrlist_trampoline()
-//go:linkname libc_setattrlist libc_setattrlist
//go:cgo_import_dynamic libc_setattrlist setattrlist "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -707,7 +669,6 @@ func fcntl(fd int, cmd int, arg int) (val int, err error) {
func libc_fcntl_trampoline()
-//go:linkname libc_fcntl libc_fcntl
//go:cgo_import_dynamic libc_fcntl fcntl "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -722,7 +683,6 @@ func kill(pid int, signum int, posix int) (err error) {
func libc_kill_trampoline()
-//go:linkname libc_kill libc_kill
//go:cgo_import_dynamic libc_kill kill "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -737,7 +697,6 @@ func ioctl(fd int, req uint, arg uintptr) (err error) {
func libc_ioctl_trampoline()
-//go:linkname libc_ioctl libc_ioctl
//go:cgo_import_dynamic libc_ioctl ioctl "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -758,7 +717,6 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr)
func libc_sysctl_trampoline()
-//go:linkname libc_sysctl libc_sysctl
//go:cgo_import_dynamic libc_sysctl sysctl "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -773,7 +731,6 @@ func sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer
func libc_sendfile_trampoline()
-//go:linkname libc_sendfile libc_sendfile
//go:cgo_import_dynamic libc_sendfile sendfile "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -793,7 +750,6 @@ func Access(path string, mode uint32) (err error) {
func libc_access_trampoline()
-//go:linkname libc_access libc_access
//go:cgo_import_dynamic libc_access access "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -808,7 +764,6 @@ func Adjtime(delta *Timeval, olddelta *Timeval) (err error) {
func libc_adjtime_trampoline()
-//go:linkname libc_adjtime libc_adjtime
//go:cgo_import_dynamic libc_adjtime adjtime "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -828,7 +783,6 @@ func Chdir(path string) (err error) {
func libc_chdir_trampoline()
-//go:linkname libc_chdir libc_chdir
//go:cgo_import_dynamic libc_chdir chdir "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -848,7 +802,6 @@ func Chflags(path string, flags int) (err error) {
func libc_chflags_trampoline()
-//go:linkname libc_chflags libc_chflags
//go:cgo_import_dynamic libc_chflags chflags "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -868,7 +821,6 @@ func Chmod(path string, mode uint32) (err error) {
func libc_chmod_trampoline()
-//go:linkname libc_chmod libc_chmod
//go:cgo_import_dynamic libc_chmod chmod "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -888,7 +840,6 @@ func Chown(path string, uid int, gid int) (err error) {
func libc_chown_trampoline()
-//go:linkname libc_chown libc_chown
//go:cgo_import_dynamic libc_chown chown "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -908,7 +859,6 @@ func Chroot(path string) (err error) {
func libc_chroot_trampoline()
-//go:linkname libc_chroot libc_chroot
//go:cgo_import_dynamic libc_chroot chroot "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -923,7 +873,6 @@ func ClockGettime(clockid int32, time *Timespec) (err error) {
func libc_clock_gettime_trampoline()
-//go:linkname libc_clock_gettime libc_clock_gettime
//go:cgo_import_dynamic libc_clock_gettime clock_gettime "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -938,7 +887,6 @@ func Close(fd int) (err error) {
func libc_close_trampoline()
-//go:linkname libc_close libc_close
//go:cgo_import_dynamic libc_close close "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -963,7 +911,6 @@ func Clonefile(src string, dst string, flags int) (err error) {
func libc_clonefile_trampoline()
-//go:linkname libc_clonefile libc_clonefile
//go:cgo_import_dynamic libc_clonefile clonefile "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -988,7 +935,6 @@ func Clonefileat(srcDirfd int, src string, dstDirfd int, dst string, flags int)
func libc_clonefileat_trampoline()
-//go:linkname libc_clonefileat libc_clonefileat
//go:cgo_import_dynamic libc_clonefileat clonefileat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1004,7 +950,6 @@ func Dup(fd int) (nfd int, err error) {
func libc_dup_trampoline()
-//go:linkname libc_dup libc_dup
//go:cgo_import_dynamic libc_dup dup "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1019,7 +964,6 @@ func Dup2(from int, to int) (err error) {
func libc_dup2_trampoline()
-//go:linkname libc_dup2 libc_dup2
//go:cgo_import_dynamic libc_dup2 dup2 "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1044,7 +988,6 @@ func Exchangedata(path1 string, path2 string, options int) (err error) {
func libc_exchangedata_trampoline()
-//go:linkname libc_exchangedata libc_exchangedata
//go:cgo_import_dynamic libc_exchangedata exchangedata "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1056,7 +999,6 @@ func Exit(code int) {
func libc_exit_trampoline()
-//go:linkname libc_exit libc_exit
//go:cgo_import_dynamic libc_exit exit "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1076,7 +1018,6 @@ func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) {
func libc_faccessat_trampoline()
-//go:linkname libc_faccessat libc_faccessat
//go:cgo_import_dynamic libc_faccessat faccessat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1091,7 +1032,6 @@ func Fchdir(fd int) (err error) {
func libc_fchdir_trampoline()
-//go:linkname libc_fchdir libc_fchdir
//go:cgo_import_dynamic libc_fchdir fchdir "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1106,7 +1046,6 @@ func Fchflags(fd int, flags int) (err error) {
func libc_fchflags_trampoline()
-//go:linkname libc_fchflags libc_fchflags
//go:cgo_import_dynamic libc_fchflags fchflags "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1121,7 +1060,6 @@ func Fchmod(fd int, mode uint32) (err error) {
func libc_fchmod_trampoline()
-//go:linkname libc_fchmod libc_fchmod
//go:cgo_import_dynamic libc_fchmod fchmod "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1141,7 +1079,6 @@ func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) {
func libc_fchmodat_trampoline()
-//go:linkname libc_fchmodat libc_fchmodat
//go:cgo_import_dynamic libc_fchmodat fchmodat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1156,7 +1093,6 @@ func Fchown(fd int, uid int, gid int) (err error) {
func libc_fchown_trampoline()
-//go:linkname libc_fchown libc_fchown
//go:cgo_import_dynamic libc_fchown fchown "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1176,7 +1112,6 @@ func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) {
func libc_fchownat_trampoline()
-//go:linkname libc_fchownat libc_fchownat
//go:cgo_import_dynamic libc_fchownat fchownat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1196,7 +1131,6 @@ func Fclonefileat(srcDirfd int, dstDirfd int, dst string, flags int) (err error)
func libc_fclonefileat_trampoline()
-//go:linkname libc_fclonefileat libc_fclonefileat
//go:cgo_import_dynamic libc_fclonefileat fclonefileat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1211,7 +1145,6 @@ func Flock(fd int, how int) (err error) {
func libc_flock_trampoline()
-//go:linkname libc_flock libc_flock
//go:cgo_import_dynamic libc_flock flock "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1227,7 +1160,6 @@ func Fpathconf(fd int, name int) (val int, err error) {
func libc_fpathconf_trampoline()
-//go:linkname libc_fpathconf libc_fpathconf
//go:cgo_import_dynamic libc_fpathconf fpathconf "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1242,7 +1174,6 @@ func Fsync(fd int) (err error) {
func libc_fsync_trampoline()
-//go:linkname libc_fsync libc_fsync
//go:cgo_import_dynamic libc_fsync fsync "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1257,7 +1188,6 @@ func Ftruncate(fd int, length int64) (err error) {
func libc_ftruncate_trampoline()
-//go:linkname libc_ftruncate libc_ftruncate
//go:cgo_import_dynamic libc_ftruncate ftruncate "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1279,7 +1209,6 @@ func Getcwd(buf []byte) (n int, err error) {
func libc_getcwd_trampoline()
-//go:linkname libc_getcwd libc_getcwd
//go:cgo_import_dynamic libc_getcwd getcwd "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1292,7 +1221,6 @@ func Getdtablesize() (size int) {
func libc_getdtablesize_trampoline()
-//go:linkname libc_getdtablesize libc_getdtablesize
//go:cgo_import_dynamic libc_getdtablesize getdtablesize "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1305,7 +1233,6 @@ func Getegid() (egid int) {
func libc_getegid_trampoline()
-//go:linkname libc_getegid libc_getegid
//go:cgo_import_dynamic libc_getegid getegid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1318,7 +1245,6 @@ func Geteuid() (uid int) {
func libc_geteuid_trampoline()
-//go:linkname libc_geteuid libc_geteuid
//go:cgo_import_dynamic libc_geteuid geteuid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1331,7 +1257,6 @@ func Getgid() (gid int) {
func libc_getgid_trampoline()
-//go:linkname libc_getgid libc_getgid
//go:cgo_import_dynamic libc_getgid getgid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1347,7 +1272,6 @@ func Getpgid(pid int) (pgid int, err error) {
func libc_getpgid_trampoline()
-//go:linkname libc_getpgid libc_getpgid
//go:cgo_import_dynamic libc_getpgid getpgid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1360,7 +1284,6 @@ func Getpgrp() (pgrp int) {
func libc_getpgrp_trampoline()
-//go:linkname libc_getpgrp libc_getpgrp
//go:cgo_import_dynamic libc_getpgrp getpgrp "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1373,7 +1296,6 @@ func Getpid() (pid int) {
func libc_getpid_trampoline()
-//go:linkname libc_getpid libc_getpid
//go:cgo_import_dynamic libc_getpid getpid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1386,7 +1308,6 @@ func Getppid() (ppid int) {
func libc_getppid_trampoline()
-//go:linkname libc_getppid libc_getppid
//go:cgo_import_dynamic libc_getppid getppid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1402,7 +1323,6 @@ func Getpriority(which int, who int) (prio int, err error) {
func libc_getpriority_trampoline()
-//go:linkname libc_getpriority libc_getpriority
//go:cgo_import_dynamic libc_getpriority getpriority "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1417,7 +1337,6 @@ func Getrlimit(which int, lim *Rlimit) (err error) {
func libc_getrlimit_trampoline()
-//go:linkname libc_getrlimit libc_getrlimit
//go:cgo_import_dynamic libc_getrlimit getrlimit "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1432,7 +1351,6 @@ func Getrusage(who int, rusage *Rusage) (err error) {
func libc_getrusage_trampoline()
-//go:linkname libc_getrusage libc_getrusage
//go:cgo_import_dynamic libc_getrusage getrusage "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1448,7 +1366,6 @@ func Getsid(pid int) (sid int, err error) {
func libc_getsid_trampoline()
-//go:linkname libc_getsid libc_getsid
//go:cgo_import_dynamic libc_getsid getsid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1463,7 +1380,6 @@ func Gettimeofday(tp *Timeval) (err error) {
func libc_gettimeofday_trampoline()
-//go:linkname libc_gettimeofday libc_gettimeofday
//go:cgo_import_dynamic libc_gettimeofday gettimeofday "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1476,7 +1392,6 @@ func Getuid() (uid int) {
func libc_getuid_trampoline()
-//go:linkname libc_getuid libc_getuid
//go:cgo_import_dynamic libc_getuid getuid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1489,7 +1404,6 @@ func Issetugid() (tainted bool) {
func libc_issetugid_trampoline()
-//go:linkname libc_issetugid libc_issetugid
//go:cgo_import_dynamic libc_issetugid issetugid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1505,7 +1419,6 @@ func Kqueue() (fd int, err error) {
func libc_kqueue_trampoline()
-//go:linkname libc_kqueue libc_kqueue
//go:cgo_import_dynamic libc_kqueue kqueue "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1525,7 +1438,6 @@ func Lchown(path string, uid int, gid int) (err error) {
func libc_lchown_trampoline()
-//go:linkname libc_lchown libc_lchown
//go:cgo_import_dynamic libc_lchown lchown "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1550,7 +1462,6 @@ func Link(path string, link string) (err error) {
func libc_link_trampoline()
-//go:linkname libc_link libc_link
//go:cgo_import_dynamic libc_link link "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1575,7 +1486,6 @@ func Linkat(pathfd int, path string, linkfd int, link string, flags int) (err er
func libc_linkat_trampoline()
-//go:linkname libc_linkat libc_linkat
//go:cgo_import_dynamic libc_linkat linkat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1590,7 +1500,6 @@ func Listen(s int, backlog int) (err error) {
func libc_listen_trampoline()
-//go:linkname libc_listen libc_listen
//go:cgo_import_dynamic libc_listen listen "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1610,7 +1519,6 @@ func Mkdir(path string, mode uint32) (err error) {
func libc_mkdir_trampoline()
-//go:linkname libc_mkdir libc_mkdir
//go:cgo_import_dynamic libc_mkdir mkdir "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1630,7 +1538,6 @@ func Mkdirat(dirfd int, path string, mode uint32) (err error) {
func libc_mkdirat_trampoline()
-//go:linkname libc_mkdirat libc_mkdirat
//go:cgo_import_dynamic libc_mkdirat mkdirat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1650,7 +1557,6 @@ func Mkfifo(path string, mode uint32) (err error) {
func libc_mkfifo_trampoline()
-//go:linkname libc_mkfifo libc_mkfifo
//go:cgo_import_dynamic libc_mkfifo mkfifo "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1670,7 +1576,6 @@ func Mknod(path string, mode uint32, dev int) (err error) {
func libc_mknod_trampoline()
-//go:linkname libc_mknod libc_mknod
//go:cgo_import_dynamic libc_mknod mknod "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1691,7 +1596,6 @@ func Open(path string, mode int, perm uint32) (fd int, err error) {
func libc_open_trampoline()
-//go:linkname libc_open libc_open
//go:cgo_import_dynamic libc_open open "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1712,7 +1616,6 @@ func Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) {
func libc_openat_trampoline()
-//go:linkname libc_openat libc_openat
//go:cgo_import_dynamic libc_openat openat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1733,7 +1636,6 @@ func Pathconf(path string, name int) (val int, err error) {
func libc_pathconf_trampoline()
-//go:linkname libc_pathconf libc_pathconf
//go:cgo_import_dynamic libc_pathconf pathconf "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1755,7 +1657,6 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) {
func libc_pread_trampoline()
-//go:linkname libc_pread libc_pread
//go:cgo_import_dynamic libc_pread pread "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1777,7 +1678,6 @@ func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
func libc_pwrite_trampoline()
-//go:linkname libc_pwrite libc_pwrite
//go:cgo_import_dynamic libc_pwrite pwrite "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1799,7 +1699,6 @@ func read(fd int, p []byte) (n int, err error) {
func libc_read_trampoline()
-//go:linkname libc_read libc_read
//go:cgo_import_dynamic libc_read read "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1826,7 +1725,6 @@ func Readlink(path string, buf []byte) (n int, err error) {
func libc_readlink_trampoline()
-//go:linkname libc_readlink libc_readlink
//go:cgo_import_dynamic libc_readlink readlink "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1853,7 +1751,6 @@ func Readlinkat(dirfd int, path string, buf []byte) (n int, err error) {
func libc_readlinkat_trampoline()
-//go:linkname libc_readlinkat libc_readlinkat
//go:cgo_import_dynamic libc_readlinkat readlinkat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1878,7 +1775,6 @@ func Rename(from string, to string) (err error) {
func libc_rename_trampoline()
-//go:linkname libc_rename libc_rename
//go:cgo_import_dynamic libc_rename rename "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1903,7 +1799,6 @@ func Renameat(fromfd int, from string, tofd int, to string) (err error) {
func libc_renameat_trampoline()
-//go:linkname libc_renameat libc_renameat
//go:cgo_import_dynamic libc_renameat renameat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1923,7 +1818,6 @@ func Revoke(path string) (err error) {
func libc_revoke_trampoline()
-//go:linkname libc_revoke libc_revoke
//go:cgo_import_dynamic libc_revoke revoke "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1943,7 +1837,6 @@ func Rmdir(path string) (err error) {
func libc_rmdir_trampoline()
-//go:linkname libc_rmdir libc_rmdir
//go:cgo_import_dynamic libc_rmdir rmdir "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1959,7 +1852,6 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
func libc_lseek_trampoline()
-//go:linkname libc_lseek libc_lseek
//go:cgo_import_dynamic libc_lseek lseek "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1975,7 +1867,6 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err
func libc_select_trampoline()
-//go:linkname libc_select libc_select
//go:cgo_import_dynamic libc_select select "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1990,7 +1881,6 @@ func Setegid(egid int) (err error) {
func libc_setegid_trampoline()
-//go:linkname libc_setegid libc_setegid
//go:cgo_import_dynamic libc_setegid setegid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2005,7 +1895,6 @@ func Seteuid(euid int) (err error) {
func libc_seteuid_trampoline()
-//go:linkname libc_seteuid libc_seteuid
//go:cgo_import_dynamic libc_seteuid seteuid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2020,7 +1909,6 @@ func Setgid(gid int) (err error) {
func libc_setgid_trampoline()
-//go:linkname libc_setgid libc_setgid
//go:cgo_import_dynamic libc_setgid setgid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2040,7 +1928,6 @@ func Setlogin(name string) (err error) {
func libc_setlogin_trampoline()
-//go:linkname libc_setlogin libc_setlogin
//go:cgo_import_dynamic libc_setlogin setlogin "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2055,7 +1942,6 @@ func Setpgid(pid int, pgid int) (err error) {
func libc_setpgid_trampoline()
-//go:linkname libc_setpgid libc_setpgid
//go:cgo_import_dynamic libc_setpgid setpgid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2070,7 +1956,6 @@ func Setpriority(which int, who int, prio int) (err error) {
func libc_setpriority_trampoline()
-//go:linkname libc_setpriority libc_setpriority
//go:cgo_import_dynamic libc_setpriority setpriority "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2085,7 +1970,6 @@ func Setprivexec(flag int) (err error) {
func libc_setprivexec_trampoline()
-//go:linkname libc_setprivexec libc_setprivexec
//go:cgo_import_dynamic libc_setprivexec setprivexec "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2100,7 +1984,6 @@ func Setregid(rgid int, egid int) (err error) {
func libc_setregid_trampoline()
-//go:linkname libc_setregid libc_setregid
//go:cgo_import_dynamic libc_setregid setregid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2115,7 +1998,6 @@ func Setreuid(ruid int, euid int) (err error) {
func libc_setreuid_trampoline()
-//go:linkname libc_setreuid libc_setreuid
//go:cgo_import_dynamic libc_setreuid setreuid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2130,7 +2012,6 @@ func Setrlimit(which int, lim *Rlimit) (err error) {
func libc_setrlimit_trampoline()
-//go:linkname libc_setrlimit libc_setrlimit
//go:cgo_import_dynamic libc_setrlimit setrlimit "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2146,7 +2027,6 @@ func Setsid() (pid int, err error) {
func libc_setsid_trampoline()
-//go:linkname libc_setsid libc_setsid
//go:cgo_import_dynamic libc_setsid setsid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2161,7 +2041,6 @@ func Settimeofday(tp *Timeval) (err error) {
func libc_settimeofday_trampoline()
-//go:linkname libc_settimeofday libc_settimeofday
//go:cgo_import_dynamic libc_settimeofday settimeofday "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2176,7 +2055,6 @@ func Setuid(uid int) (err error) {
func libc_setuid_trampoline()
-//go:linkname libc_setuid libc_setuid
//go:cgo_import_dynamic libc_setuid setuid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2201,7 +2079,6 @@ func Symlink(path string, link string) (err error) {
func libc_symlink_trampoline()
-//go:linkname libc_symlink libc_symlink
//go:cgo_import_dynamic libc_symlink symlink "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2226,7 +2103,6 @@ func Symlinkat(oldpath string, newdirfd int, newpath string) (err error) {
func libc_symlinkat_trampoline()
-//go:linkname libc_symlinkat libc_symlinkat
//go:cgo_import_dynamic libc_symlinkat symlinkat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2241,7 +2117,6 @@ func Sync() (err error) {
func libc_sync_trampoline()
-//go:linkname libc_sync libc_sync
//go:cgo_import_dynamic libc_sync sync "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2261,7 +2136,6 @@ func Truncate(path string, length int64) (err error) {
func libc_truncate_trampoline()
-//go:linkname libc_truncate libc_truncate
//go:cgo_import_dynamic libc_truncate truncate "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2274,7 +2148,6 @@ func Umask(newmask int) (oldmask int) {
func libc_umask_trampoline()
-//go:linkname libc_umask libc_umask
//go:cgo_import_dynamic libc_umask umask "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2294,7 +2167,6 @@ func Undelete(path string) (err error) {
func libc_undelete_trampoline()
-//go:linkname libc_undelete libc_undelete
//go:cgo_import_dynamic libc_undelete undelete "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2314,7 +2186,6 @@ func Unlink(path string) (err error) {
func libc_unlink_trampoline()
-//go:linkname libc_unlink libc_unlink
//go:cgo_import_dynamic libc_unlink unlink "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2334,7 +2205,6 @@ func Unlinkat(dirfd int, path string, flags int) (err error) {
func libc_unlinkat_trampoline()
-//go:linkname libc_unlinkat libc_unlinkat
//go:cgo_import_dynamic libc_unlinkat unlinkat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2354,7 +2224,6 @@ func Unmount(path string, flags int) (err error) {
func libc_unmount_trampoline()
-//go:linkname libc_unmount libc_unmount
//go:cgo_import_dynamic libc_unmount unmount "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2376,7 +2245,6 @@ func write(fd int, p []byte) (n int, err error) {
func libc_write_trampoline()
-//go:linkname libc_write libc_write
//go:cgo_import_dynamic libc_write write "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2392,7 +2260,6 @@ func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (
func libc_mmap_trampoline()
-//go:linkname libc_mmap libc_mmap
//go:cgo_import_dynamic libc_mmap mmap "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2407,7 +2274,6 @@ func munmap(addr uintptr, length uintptr) (err error) {
func libc_munmap_trampoline()
-//go:linkname libc_munmap libc_munmap
//go:cgo_import_dynamic libc_munmap munmap "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2444,7 +2310,6 @@ func Fstat(fd int, stat *Stat_t) (err error) {
func libc_fstat64_trampoline()
-//go:linkname libc_fstat64 libc_fstat64
//go:cgo_import_dynamic libc_fstat64 fstat64 "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2464,7 +2329,6 @@ func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) {
func libc_fstatat64_trampoline()
-//go:linkname libc_fstatat64 libc_fstatat64
//go:cgo_import_dynamic libc_fstatat64 fstatat64 "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2479,7 +2343,6 @@ func Fstatfs(fd int, stat *Statfs_t) (err error) {
func libc_fstatfs64_trampoline()
-//go:linkname libc_fstatfs64 libc_fstatfs64
//go:cgo_import_dynamic libc_fstatfs64 fstatfs64 "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2495,7 +2358,6 @@ func getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) {
func libc_getfsstat64_trampoline()
-//go:linkname libc_getfsstat64 libc_getfsstat64
//go:cgo_import_dynamic libc_getfsstat64 getfsstat64 "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2515,7 +2377,6 @@ func Lstat(path string, stat *Stat_t) (err error) {
func libc_lstat64_trampoline()
-//go:linkname libc_lstat64 libc_lstat64
//go:cgo_import_dynamic libc_lstat64 lstat64 "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2530,7 +2391,6 @@ func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) {
func libc_ptrace_trampoline()
-//go:linkname libc_ptrace libc_ptrace
//go:cgo_import_dynamic libc_ptrace ptrace "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2550,7 +2410,6 @@ func Stat(path string, stat *Stat_t) (err error) {
func libc_stat64_trampoline()
-//go:linkname libc_stat64 libc_stat64
//go:cgo_import_dynamic libc_stat64 stat64 "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2570,5 +2429,4 @@ func Statfs(path string, stat *Statfs_t) (err error) {
func libc_statfs64_trampoline()
-//go:linkname libc_statfs64 libc_statfs64
//go:cgo_import_dynamic libc_statfs64 statfs64 "/usr/lib/libSystem.B.dylib"
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.1_13.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.1_13.go
index f519ce9afb..de4738fff8 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.1_13.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.1_13.go
@@ -24,7 +24,6 @@ func closedir(dir uintptr) (err error) {
func libc_closedir_trampoline()
-//go:linkname libc_closedir libc_closedir
//go:cgo_import_dynamic libc_closedir closedir "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -37,5 +36,4 @@ func readdir_r(dir uintptr, entry *Dirent, result **Dirent) (res Errno) {
func libc_readdir_r_trampoline()
-//go:linkname libc_readdir_r libc_readdir_r
//go:cgo_import_dynamic libc_readdir_r readdir_r "/usr/lib/libSystem.B.dylib"
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.go
index d6b5249c2f..8e79ad377b 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.go
@@ -25,7 +25,6 @@ func getgroups(ngid int, gid *_Gid_t) (n int, err error) {
func libc_getgroups_trampoline()
-//go:linkname libc_getgroups libc_getgroups
//go:cgo_import_dynamic libc_getgroups getgroups "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -40,7 +39,6 @@ func setgroups(ngid int, gid *_Gid_t) (err error) {
func libc_setgroups_trampoline()
-//go:linkname libc_setgroups libc_setgroups
//go:cgo_import_dynamic libc_setgroups setgroups "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -56,7 +54,6 @@ func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err
func libc_wait4_trampoline()
-//go:linkname libc_wait4 libc_wait4
//go:cgo_import_dynamic libc_wait4 wait4 "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -72,7 +69,6 @@ func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) {
func libc_accept_trampoline()
-//go:linkname libc_accept libc_accept
//go:cgo_import_dynamic libc_accept accept "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -87,7 +83,6 @@ func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) {
func libc_bind_trampoline()
-//go:linkname libc_bind libc_bind
//go:cgo_import_dynamic libc_bind bind "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -102,7 +97,6 @@ func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) {
func libc_connect_trampoline()
-//go:linkname libc_connect libc_connect
//go:cgo_import_dynamic libc_connect connect "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -118,7 +112,6 @@ func socket(domain int, typ int, proto int) (fd int, err error) {
func libc_socket_trampoline()
-//go:linkname libc_socket libc_socket
//go:cgo_import_dynamic libc_socket socket "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -133,7 +126,6 @@ func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen
func libc_getsockopt_trampoline()
-//go:linkname libc_getsockopt libc_getsockopt
//go:cgo_import_dynamic libc_getsockopt getsockopt "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -148,7 +140,6 @@ func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr)
func libc_setsockopt_trampoline()
-//go:linkname libc_setsockopt libc_setsockopt
//go:cgo_import_dynamic libc_setsockopt setsockopt "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -163,7 +154,6 @@ func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
func libc_getpeername_trampoline()
-//go:linkname libc_getpeername libc_getpeername
//go:cgo_import_dynamic libc_getpeername getpeername "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -178,7 +168,6 @@ func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
func libc_getsockname_trampoline()
-//go:linkname libc_getsockname libc_getsockname
//go:cgo_import_dynamic libc_getsockname getsockname "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -193,7 +182,6 @@ func Shutdown(s int, how int) (err error) {
func libc_shutdown_trampoline()
-//go:linkname libc_shutdown libc_shutdown
//go:cgo_import_dynamic libc_shutdown shutdown "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -208,7 +196,6 @@ func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) {
func libc_socketpair_trampoline()
-//go:linkname libc_socketpair libc_socketpair
//go:cgo_import_dynamic libc_socketpair socketpair "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -230,7 +217,6 @@ func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Sockl
func libc_recvfrom_trampoline()
-//go:linkname libc_recvfrom libc_recvfrom
//go:cgo_import_dynamic libc_recvfrom recvfrom "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -251,7 +237,6 @@ func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (
func libc_sendto_trampoline()
-//go:linkname libc_sendto libc_sendto
//go:cgo_import_dynamic libc_sendto sendto "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -267,7 +252,6 @@ func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) {
func libc_recvmsg_trampoline()
-//go:linkname libc_recvmsg libc_recvmsg
//go:cgo_import_dynamic libc_recvmsg recvmsg "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -283,7 +267,6 @@ func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) {
func libc_sendmsg_trampoline()
-//go:linkname libc_sendmsg libc_sendmsg
//go:cgo_import_dynamic libc_sendmsg sendmsg "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -299,7 +282,6 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne
func libc_kevent_trampoline()
-//go:linkname libc_kevent libc_kevent
//go:cgo_import_dynamic libc_kevent kevent "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -319,7 +301,6 @@ func utimes(path string, timeval *[2]Timeval) (err error) {
func libc_utimes_trampoline()
-//go:linkname libc_utimes libc_utimes
//go:cgo_import_dynamic libc_utimes utimes "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -334,7 +315,6 @@ func futimes(fd int, timeval *[2]Timeval) (err error) {
func libc_futimes_trampoline()
-//go:linkname libc_futimes libc_futimes
//go:cgo_import_dynamic libc_futimes futimes "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -350,7 +330,6 @@ func poll(fds *PollFd, nfds int, timeout int) (n int, err error) {
func libc_poll_trampoline()
-//go:linkname libc_poll libc_poll
//go:cgo_import_dynamic libc_poll poll "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -371,7 +350,6 @@ func Madvise(b []byte, behav int) (err error) {
func libc_madvise_trampoline()
-//go:linkname libc_madvise libc_madvise
//go:cgo_import_dynamic libc_madvise madvise "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -392,7 +370,6 @@ func Mlock(b []byte) (err error) {
func libc_mlock_trampoline()
-//go:linkname libc_mlock libc_mlock
//go:cgo_import_dynamic libc_mlock mlock "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -407,7 +384,6 @@ func Mlockall(flags int) (err error) {
func libc_mlockall_trampoline()
-//go:linkname libc_mlockall libc_mlockall
//go:cgo_import_dynamic libc_mlockall mlockall "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -428,7 +404,6 @@ func Mprotect(b []byte, prot int) (err error) {
func libc_mprotect_trampoline()
-//go:linkname libc_mprotect libc_mprotect
//go:cgo_import_dynamic libc_mprotect mprotect "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -449,7 +424,6 @@ func Msync(b []byte, flags int) (err error) {
func libc_msync_trampoline()
-//go:linkname libc_msync libc_msync
//go:cgo_import_dynamic libc_msync msync "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -470,7 +444,6 @@ func Munlock(b []byte) (err error) {
func libc_munlock_trampoline()
-//go:linkname libc_munlock libc_munlock
//go:cgo_import_dynamic libc_munlock munlock "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -485,7 +458,6 @@ func Munlockall() (err error) {
func libc_munlockall_trampoline()
-//go:linkname libc_munlockall libc_munlockall
//go:cgo_import_dynamic libc_munlockall munlockall "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -502,7 +474,6 @@ func pipe() (r int, w int, err error) {
func libc_pipe_trampoline()
-//go:linkname libc_pipe libc_pipe
//go:cgo_import_dynamic libc_pipe pipe "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -528,7 +499,6 @@ func getxattr(path string, attr string, dest *byte, size int, position uint32, o
func libc_getxattr_trampoline()
-//go:linkname libc_getxattr libc_getxattr
//go:cgo_import_dynamic libc_getxattr getxattr "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -549,7 +519,6 @@ func fgetxattr(fd int, attr string, dest *byte, size int, position uint32, optio
func libc_fgetxattr_trampoline()
-//go:linkname libc_fgetxattr libc_fgetxattr
//go:cgo_import_dynamic libc_fgetxattr fgetxattr "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -574,7 +543,6 @@ func setxattr(path string, attr string, data *byte, size int, position uint32, o
func libc_setxattr_trampoline()
-//go:linkname libc_setxattr libc_setxattr
//go:cgo_import_dynamic libc_setxattr setxattr "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -594,7 +562,6 @@ func fsetxattr(fd int, attr string, data *byte, size int, position uint32, optio
func libc_fsetxattr_trampoline()
-//go:linkname libc_fsetxattr libc_fsetxattr
//go:cgo_import_dynamic libc_fsetxattr fsetxattr "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -619,7 +586,6 @@ func removexattr(path string, attr string, options int) (err error) {
func libc_removexattr_trampoline()
-//go:linkname libc_removexattr libc_removexattr
//go:cgo_import_dynamic libc_removexattr removexattr "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -639,7 +605,6 @@ func fremovexattr(fd int, attr string, options int) (err error) {
func libc_fremovexattr_trampoline()
-//go:linkname libc_fremovexattr libc_fremovexattr
//go:cgo_import_dynamic libc_fremovexattr fremovexattr "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -660,7 +625,6 @@ func listxattr(path string, dest *byte, size int, options int) (sz int, err erro
func libc_listxattr_trampoline()
-//go:linkname libc_listxattr libc_listxattr
//go:cgo_import_dynamic libc_listxattr listxattr "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -676,7 +640,6 @@ func flistxattr(fd int, dest *byte, size int, options int) (sz int, err error) {
func libc_flistxattr_trampoline()
-//go:linkname libc_flistxattr libc_flistxattr
//go:cgo_import_dynamic libc_flistxattr flistxattr "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -691,7 +654,6 @@ func setattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintp
func libc_setattrlist_trampoline()
-//go:linkname libc_setattrlist libc_setattrlist
//go:cgo_import_dynamic libc_setattrlist setattrlist "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -707,7 +669,6 @@ func fcntl(fd int, cmd int, arg int) (val int, err error) {
func libc_fcntl_trampoline()
-//go:linkname libc_fcntl libc_fcntl
//go:cgo_import_dynamic libc_fcntl fcntl "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -722,7 +683,6 @@ func kill(pid int, signum int, posix int) (err error) {
func libc_kill_trampoline()
-//go:linkname libc_kill libc_kill
//go:cgo_import_dynamic libc_kill kill "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -737,7 +697,6 @@ func ioctl(fd int, req uint, arg uintptr) (err error) {
func libc_ioctl_trampoline()
-//go:linkname libc_ioctl libc_ioctl
//go:cgo_import_dynamic libc_ioctl ioctl "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -758,7 +717,6 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr)
func libc_sysctl_trampoline()
-//go:linkname libc_sysctl libc_sysctl
//go:cgo_import_dynamic libc_sysctl sysctl "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -773,7 +731,6 @@ func sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer
func libc_sendfile_trampoline()
-//go:linkname libc_sendfile libc_sendfile
//go:cgo_import_dynamic libc_sendfile sendfile "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -793,7 +750,6 @@ func Access(path string, mode uint32) (err error) {
func libc_access_trampoline()
-//go:linkname libc_access libc_access
//go:cgo_import_dynamic libc_access access "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -808,7 +764,6 @@ func Adjtime(delta *Timeval, olddelta *Timeval) (err error) {
func libc_adjtime_trampoline()
-//go:linkname libc_adjtime libc_adjtime
//go:cgo_import_dynamic libc_adjtime adjtime "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -828,7 +783,6 @@ func Chdir(path string) (err error) {
func libc_chdir_trampoline()
-//go:linkname libc_chdir libc_chdir
//go:cgo_import_dynamic libc_chdir chdir "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -848,7 +802,6 @@ func Chflags(path string, flags int) (err error) {
func libc_chflags_trampoline()
-//go:linkname libc_chflags libc_chflags
//go:cgo_import_dynamic libc_chflags chflags "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -868,7 +821,6 @@ func Chmod(path string, mode uint32) (err error) {
func libc_chmod_trampoline()
-//go:linkname libc_chmod libc_chmod
//go:cgo_import_dynamic libc_chmod chmod "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -888,7 +840,6 @@ func Chown(path string, uid int, gid int) (err error) {
func libc_chown_trampoline()
-//go:linkname libc_chown libc_chown
//go:cgo_import_dynamic libc_chown chown "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -908,7 +859,6 @@ func Chroot(path string) (err error) {
func libc_chroot_trampoline()
-//go:linkname libc_chroot libc_chroot
//go:cgo_import_dynamic libc_chroot chroot "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -923,7 +873,6 @@ func ClockGettime(clockid int32, time *Timespec) (err error) {
func libc_clock_gettime_trampoline()
-//go:linkname libc_clock_gettime libc_clock_gettime
//go:cgo_import_dynamic libc_clock_gettime clock_gettime "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -938,7 +887,6 @@ func Close(fd int) (err error) {
func libc_close_trampoline()
-//go:linkname libc_close libc_close
//go:cgo_import_dynamic libc_close close "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -963,7 +911,6 @@ func Clonefile(src string, dst string, flags int) (err error) {
func libc_clonefile_trampoline()
-//go:linkname libc_clonefile libc_clonefile
//go:cgo_import_dynamic libc_clonefile clonefile "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -988,7 +935,6 @@ func Clonefileat(srcDirfd int, src string, dstDirfd int, dst string, flags int)
func libc_clonefileat_trampoline()
-//go:linkname libc_clonefileat libc_clonefileat
//go:cgo_import_dynamic libc_clonefileat clonefileat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1004,7 +950,6 @@ func Dup(fd int) (nfd int, err error) {
func libc_dup_trampoline()
-//go:linkname libc_dup libc_dup
//go:cgo_import_dynamic libc_dup dup "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1019,7 +964,6 @@ func Dup2(from int, to int) (err error) {
func libc_dup2_trampoline()
-//go:linkname libc_dup2 libc_dup2
//go:cgo_import_dynamic libc_dup2 dup2 "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1044,7 +988,6 @@ func Exchangedata(path1 string, path2 string, options int) (err error) {
func libc_exchangedata_trampoline()
-//go:linkname libc_exchangedata libc_exchangedata
//go:cgo_import_dynamic libc_exchangedata exchangedata "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1056,7 +999,6 @@ func Exit(code int) {
func libc_exit_trampoline()
-//go:linkname libc_exit libc_exit
//go:cgo_import_dynamic libc_exit exit "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1076,7 +1018,6 @@ func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) {
func libc_faccessat_trampoline()
-//go:linkname libc_faccessat libc_faccessat
//go:cgo_import_dynamic libc_faccessat faccessat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1091,7 +1032,6 @@ func Fchdir(fd int) (err error) {
func libc_fchdir_trampoline()
-//go:linkname libc_fchdir libc_fchdir
//go:cgo_import_dynamic libc_fchdir fchdir "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1106,7 +1046,6 @@ func Fchflags(fd int, flags int) (err error) {
func libc_fchflags_trampoline()
-//go:linkname libc_fchflags libc_fchflags
//go:cgo_import_dynamic libc_fchflags fchflags "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1121,7 +1060,6 @@ func Fchmod(fd int, mode uint32) (err error) {
func libc_fchmod_trampoline()
-//go:linkname libc_fchmod libc_fchmod
//go:cgo_import_dynamic libc_fchmod fchmod "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1141,7 +1079,6 @@ func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) {
func libc_fchmodat_trampoline()
-//go:linkname libc_fchmodat libc_fchmodat
//go:cgo_import_dynamic libc_fchmodat fchmodat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1156,7 +1093,6 @@ func Fchown(fd int, uid int, gid int) (err error) {
func libc_fchown_trampoline()
-//go:linkname libc_fchown libc_fchown
//go:cgo_import_dynamic libc_fchown fchown "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1176,7 +1112,6 @@ func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) {
func libc_fchownat_trampoline()
-//go:linkname libc_fchownat libc_fchownat
//go:cgo_import_dynamic libc_fchownat fchownat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1196,7 +1131,6 @@ func Fclonefileat(srcDirfd int, dstDirfd int, dst string, flags int) (err error)
func libc_fclonefileat_trampoline()
-//go:linkname libc_fclonefileat libc_fclonefileat
//go:cgo_import_dynamic libc_fclonefileat fclonefileat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1211,7 +1145,6 @@ func Flock(fd int, how int) (err error) {
func libc_flock_trampoline()
-//go:linkname libc_flock libc_flock
//go:cgo_import_dynamic libc_flock flock "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1227,7 +1160,6 @@ func Fpathconf(fd int, name int) (val int, err error) {
func libc_fpathconf_trampoline()
-//go:linkname libc_fpathconf libc_fpathconf
//go:cgo_import_dynamic libc_fpathconf fpathconf "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1242,7 +1174,6 @@ func Fsync(fd int) (err error) {
func libc_fsync_trampoline()
-//go:linkname libc_fsync libc_fsync
//go:cgo_import_dynamic libc_fsync fsync "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1257,7 +1188,6 @@ func Ftruncate(fd int, length int64) (err error) {
func libc_ftruncate_trampoline()
-//go:linkname libc_ftruncate libc_ftruncate
//go:cgo_import_dynamic libc_ftruncate ftruncate "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1279,7 +1209,6 @@ func Getcwd(buf []byte) (n int, err error) {
func libc_getcwd_trampoline()
-//go:linkname libc_getcwd libc_getcwd
//go:cgo_import_dynamic libc_getcwd getcwd "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1292,7 +1221,6 @@ func Getdtablesize() (size int) {
func libc_getdtablesize_trampoline()
-//go:linkname libc_getdtablesize libc_getdtablesize
//go:cgo_import_dynamic libc_getdtablesize getdtablesize "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1305,7 +1233,6 @@ func Getegid() (egid int) {
func libc_getegid_trampoline()
-//go:linkname libc_getegid libc_getegid
//go:cgo_import_dynamic libc_getegid getegid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1318,7 +1245,6 @@ func Geteuid() (uid int) {
func libc_geteuid_trampoline()
-//go:linkname libc_geteuid libc_geteuid
//go:cgo_import_dynamic libc_geteuid geteuid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1331,7 +1257,6 @@ func Getgid() (gid int) {
func libc_getgid_trampoline()
-//go:linkname libc_getgid libc_getgid
//go:cgo_import_dynamic libc_getgid getgid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1347,7 +1272,6 @@ func Getpgid(pid int) (pgid int, err error) {
func libc_getpgid_trampoline()
-//go:linkname libc_getpgid libc_getpgid
//go:cgo_import_dynamic libc_getpgid getpgid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1360,7 +1284,6 @@ func Getpgrp() (pgrp int) {
func libc_getpgrp_trampoline()
-//go:linkname libc_getpgrp libc_getpgrp
//go:cgo_import_dynamic libc_getpgrp getpgrp "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1373,7 +1296,6 @@ func Getpid() (pid int) {
func libc_getpid_trampoline()
-//go:linkname libc_getpid libc_getpid
//go:cgo_import_dynamic libc_getpid getpid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1386,7 +1308,6 @@ func Getppid() (ppid int) {
func libc_getppid_trampoline()
-//go:linkname libc_getppid libc_getppid
//go:cgo_import_dynamic libc_getppid getppid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1402,7 +1323,6 @@ func Getpriority(which int, who int) (prio int, err error) {
func libc_getpriority_trampoline()
-//go:linkname libc_getpriority libc_getpriority
//go:cgo_import_dynamic libc_getpriority getpriority "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1417,7 +1337,6 @@ func Getrlimit(which int, lim *Rlimit) (err error) {
func libc_getrlimit_trampoline()
-//go:linkname libc_getrlimit libc_getrlimit
//go:cgo_import_dynamic libc_getrlimit getrlimit "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1432,7 +1351,6 @@ func Getrusage(who int, rusage *Rusage) (err error) {
func libc_getrusage_trampoline()
-//go:linkname libc_getrusage libc_getrusage
//go:cgo_import_dynamic libc_getrusage getrusage "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1448,7 +1366,6 @@ func Getsid(pid int) (sid int, err error) {
func libc_getsid_trampoline()
-//go:linkname libc_getsid libc_getsid
//go:cgo_import_dynamic libc_getsid getsid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1463,7 +1380,6 @@ func Gettimeofday(tp *Timeval) (err error) {
func libc_gettimeofday_trampoline()
-//go:linkname libc_gettimeofday libc_gettimeofday
//go:cgo_import_dynamic libc_gettimeofday gettimeofday "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1476,7 +1392,6 @@ func Getuid() (uid int) {
func libc_getuid_trampoline()
-//go:linkname libc_getuid libc_getuid
//go:cgo_import_dynamic libc_getuid getuid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1489,7 +1404,6 @@ func Issetugid() (tainted bool) {
func libc_issetugid_trampoline()
-//go:linkname libc_issetugid libc_issetugid
//go:cgo_import_dynamic libc_issetugid issetugid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1505,7 +1419,6 @@ func Kqueue() (fd int, err error) {
func libc_kqueue_trampoline()
-//go:linkname libc_kqueue libc_kqueue
//go:cgo_import_dynamic libc_kqueue kqueue "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1525,7 +1438,6 @@ func Lchown(path string, uid int, gid int) (err error) {
func libc_lchown_trampoline()
-//go:linkname libc_lchown libc_lchown
//go:cgo_import_dynamic libc_lchown lchown "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1550,7 +1462,6 @@ func Link(path string, link string) (err error) {
func libc_link_trampoline()
-//go:linkname libc_link libc_link
//go:cgo_import_dynamic libc_link link "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1575,7 +1486,6 @@ func Linkat(pathfd int, path string, linkfd int, link string, flags int) (err er
func libc_linkat_trampoline()
-//go:linkname libc_linkat libc_linkat
//go:cgo_import_dynamic libc_linkat linkat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1590,7 +1500,6 @@ func Listen(s int, backlog int) (err error) {
func libc_listen_trampoline()
-//go:linkname libc_listen libc_listen
//go:cgo_import_dynamic libc_listen listen "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1610,7 +1519,6 @@ func Mkdir(path string, mode uint32) (err error) {
func libc_mkdir_trampoline()
-//go:linkname libc_mkdir libc_mkdir
//go:cgo_import_dynamic libc_mkdir mkdir "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1630,7 +1538,6 @@ func Mkdirat(dirfd int, path string, mode uint32) (err error) {
func libc_mkdirat_trampoline()
-//go:linkname libc_mkdirat libc_mkdirat
//go:cgo_import_dynamic libc_mkdirat mkdirat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1650,7 +1557,6 @@ func Mkfifo(path string, mode uint32) (err error) {
func libc_mkfifo_trampoline()
-//go:linkname libc_mkfifo libc_mkfifo
//go:cgo_import_dynamic libc_mkfifo mkfifo "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1670,7 +1576,6 @@ func Mknod(path string, mode uint32, dev int) (err error) {
func libc_mknod_trampoline()
-//go:linkname libc_mknod libc_mknod
//go:cgo_import_dynamic libc_mknod mknod "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1691,7 +1596,6 @@ func Open(path string, mode int, perm uint32) (fd int, err error) {
func libc_open_trampoline()
-//go:linkname libc_open libc_open
//go:cgo_import_dynamic libc_open open "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1712,7 +1616,6 @@ func Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) {
func libc_openat_trampoline()
-//go:linkname libc_openat libc_openat
//go:cgo_import_dynamic libc_openat openat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1733,7 +1636,6 @@ func Pathconf(path string, name int) (val int, err error) {
func libc_pathconf_trampoline()
-//go:linkname libc_pathconf libc_pathconf
//go:cgo_import_dynamic libc_pathconf pathconf "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1755,7 +1657,6 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) {
func libc_pread_trampoline()
-//go:linkname libc_pread libc_pread
//go:cgo_import_dynamic libc_pread pread "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1777,7 +1678,6 @@ func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
func libc_pwrite_trampoline()
-//go:linkname libc_pwrite libc_pwrite
//go:cgo_import_dynamic libc_pwrite pwrite "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1799,7 +1699,6 @@ func read(fd int, p []byte) (n int, err error) {
func libc_read_trampoline()
-//go:linkname libc_read libc_read
//go:cgo_import_dynamic libc_read read "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1826,7 +1725,6 @@ func Readlink(path string, buf []byte) (n int, err error) {
func libc_readlink_trampoline()
-//go:linkname libc_readlink libc_readlink
//go:cgo_import_dynamic libc_readlink readlink "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1853,7 +1751,6 @@ func Readlinkat(dirfd int, path string, buf []byte) (n int, err error) {
func libc_readlinkat_trampoline()
-//go:linkname libc_readlinkat libc_readlinkat
//go:cgo_import_dynamic libc_readlinkat readlinkat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1878,7 +1775,6 @@ func Rename(from string, to string) (err error) {
func libc_rename_trampoline()
-//go:linkname libc_rename libc_rename
//go:cgo_import_dynamic libc_rename rename "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1903,7 +1799,6 @@ func Renameat(fromfd int, from string, tofd int, to string) (err error) {
func libc_renameat_trampoline()
-//go:linkname libc_renameat libc_renameat
//go:cgo_import_dynamic libc_renameat renameat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1923,7 +1818,6 @@ func Revoke(path string) (err error) {
func libc_revoke_trampoline()
-//go:linkname libc_revoke libc_revoke
//go:cgo_import_dynamic libc_revoke revoke "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1943,7 +1837,6 @@ func Rmdir(path string) (err error) {
func libc_rmdir_trampoline()
-//go:linkname libc_rmdir libc_rmdir
//go:cgo_import_dynamic libc_rmdir rmdir "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1959,7 +1852,6 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
func libc_lseek_trampoline()
-//go:linkname libc_lseek libc_lseek
//go:cgo_import_dynamic libc_lseek lseek "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1975,7 +1867,6 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err
func libc_select_trampoline()
-//go:linkname libc_select libc_select
//go:cgo_import_dynamic libc_select select "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1990,7 +1881,6 @@ func Setegid(egid int) (err error) {
func libc_setegid_trampoline()
-//go:linkname libc_setegid libc_setegid
//go:cgo_import_dynamic libc_setegid setegid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2005,7 +1895,6 @@ func Seteuid(euid int) (err error) {
func libc_seteuid_trampoline()
-//go:linkname libc_seteuid libc_seteuid
//go:cgo_import_dynamic libc_seteuid seteuid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2020,7 +1909,6 @@ func Setgid(gid int) (err error) {
func libc_setgid_trampoline()
-//go:linkname libc_setgid libc_setgid
//go:cgo_import_dynamic libc_setgid setgid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2040,7 +1928,6 @@ func Setlogin(name string) (err error) {
func libc_setlogin_trampoline()
-//go:linkname libc_setlogin libc_setlogin
//go:cgo_import_dynamic libc_setlogin setlogin "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2055,7 +1942,6 @@ func Setpgid(pid int, pgid int) (err error) {
func libc_setpgid_trampoline()
-//go:linkname libc_setpgid libc_setpgid
//go:cgo_import_dynamic libc_setpgid setpgid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2070,7 +1956,6 @@ func Setpriority(which int, who int, prio int) (err error) {
func libc_setpriority_trampoline()
-//go:linkname libc_setpriority libc_setpriority
//go:cgo_import_dynamic libc_setpriority setpriority "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2085,7 +1970,6 @@ func Setprivexec(flag int) (err error) {
func libc_setprivexec_trampoline()
-//go:linkname libc_setprivexec libc_setprivexec
//go:cgo_import_dynamic libc_setprivexec setprivexec "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2100,7 +1984,6 @@ func Setregid(rgid int, egid int) (err error) {
func libc_setregid_trampoline()
-//go:linkname libc_setregid libc_setregid
//go:cgo_import_dynamic libc_setregid setregid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2115,7 +1998,6 @@ func Setreuid(ruid int, euid int) (err error) {
func libc_setreuid_trampoline()
-//go:linkname libc_setreuid libc_setreuid
//go:cgo_import_dynamic libc_setreuid setreuid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2130,7 +2012,6 @@ func Setrlimit(which int, lim *Rlimit) (err error) {
func libc_setrlimit_trampoline()
-//go:linkname libc_setrlimit libc_setrlimit
//go:cgo_import_dynamic libc_setrlimit setrlimit "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2146,7 +2027,6 @@ func Setsid() (pid int, err error) {
func libc_setsid_trampoline()
-//go:linkname libc_setsid libc_setsid
//go:cgo_import_dynamic libc_setsid setsid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2161,7 +2041,6 @@ func Settimeofday(tp *Timeval) (err error) {
func libc_settimeofday_trampoline()
-//go:linkname libc_settimeofday libc_settimeofday
//go:cgo_import_dynamic libc_settimeofday settimeofday "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2176,7 +2055,6 @@ func Setuid(uid int) (err error) {
func libc_setuid_trampoline()
-//go:linkname libc_setuid libc_setuid
//go:cgo_import_dynamic libc_setuid setuid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2201,7 +2079,6 @@ func Symlink(path string, link string) (err error) {
func libc_symlink_trampoline()
-//go:linkname libc_symlink libc_symlink
//go:cgo_import_dynamic libc_symlink symlink "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2226,7 +2103,6 @@ func Symlinkat(oldpath string, newdirfd int, newpath string) (err error) {
func libc_symlinkat_trampoline()
-//go:linkname libc_symlinkat libc_symlinkat
//go:cgo_import_dynamic libc_symlinkat symlinkat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2241,7 +2117,6 @@ func Sync() (err error) {
func libc_sync_trampoline()
-//go:linkname libc_sync libc_sync
//go:cgo_import_dynamic libc_sync sync "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2261,7 +2136,6 @@ func Truncate(path string, length int64) (err error) {
func libc_truncate_trampoline()
-//go:linkname libc_truncate libc_truncate
//go:cgo_import_dynamic libc_truncate truncate "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2274,7 +2148,6 @@ func Umask(newmask int) (oldmask int) {
func libc_umask_trampoline()
-//go:linkname libc_umask libc_umask
//go:cgo_import_dynamic libc_umask umask "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2294,7 +2167,6 @@ func Undelete(path string) (err error) {
func libc_undelete_trampoline()
-//go:linkname libc_undelete libc_undelete
//go:cgo_import_dynamic libc_undelete undelete "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2314,7 +2186,6 @@ func Unlink(path string) (err error) {
func libc_unlink_trampoline()
-//go:linkname libc_unlink libc_unlink
//go:cgo_import_dynamic libc_unlink unlink "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2334,7 +2205,6 @@ func Unlinkat(dirfd int, path string, flags int) (err error) {
func libc_unlinkat_trampoline()
-//go:linkname libc_unlinkat libc_unlinkat
//go:cgo_import_dynamic libc_unlinkat unlinkat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2354,7 +2224,6 @@ func Unmount(path string, flags int) (err error) {
func libc_unmount_trampoline()
-//go:linkname libc_unmount libc_unmount
//go:cgo_import_dynamic libc_unmount unmount "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2376,7 +2245,6 @@ func write(fd int, p []byte) (n int, err error) {
func libc_write_trampoline()
-//go:linkname libc_write libc_write
//go:cgo_import_dynamic libc_write write "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2392,7 +2260,6 @@ func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (
func libc_mmap_trampoline()
-//go:linkname libc_mmap libc_mmap
//go:cgo_import_dynamic libc_mmap mmap "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2407,7 +2274,6 @@ func munmap(addr uintptr, length uintptr) (err error) {
func libc_munmap_trampoline()
-//go:linkname libc_munmap libc_munmap
//go:cgo_import_dynamic libc_munmap munmap "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2444,7 +2310,6 @@ func Fstat(fd int, stat *Stat_t) (err error) {
func libc_fstat_trampoline()
-//go:linkname libc_fstat libc_fstat
//go:cgo_import_dynamic libc_fstat fstat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2464,7 +2329,6 @@ func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) {
func libc_fstatat_trampoline()
-//go:linkname libc_fstatat libc_fstatat
//go:cgo_import_dynamic libc_fstatat fstatat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2479,7 +2343,6 @@ func Fstatfs(fd int, stat *Statfs_t) (err error) {
func libc_fstatfs_trampoline()
-//go:linkname libc_fstatfs libc_fstatfs
//go:cgo_import_dynamic libc_fstatfs fstatfs "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2495,7 +2358,6 @@ func getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) {
func libc_getfsstat_trampoline()
-//go:linkname libc_getfsstat libc_getfsstat
//go:cgo_import_dynamic libc_getfsstat getfsstat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2515,7 +2377,6 @@ func Lstat(path string, stat *Stat_t) (err error) {
func libc_lstat_trampoline()
-//go:linkname libc_lstat libc_lstat
//go:cgo_import_dynamic libc_lstat lstat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2535,7 +2396,6 @@ func Stat(path string, stat *Stat_t) (err error) {
func libc_stat_trampoline()
-//go:linkname libc_stat libc_stat
//go:cgo_import_dynamic libc_stat stat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2555,5 +2415,4 @@ func Statfs(path string, stat *Statfs_t) (err error) {
func libc_statfs_trampoline()
-//go:linkname libc_statfs libc_statfs
//go:cgo_import_dynamic libc_statfs statfs "/usr/lib/libSystem.B.dylib"
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.1_13.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.1_13.go
index d64e6c806f..870eb37abf 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.1_13.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.1_13.go
@@ -24,7 +24,6 @@ func closedir(dir uintptr) (err error) {
func libc_closedir_trampoline()
-//go:linkname libc_closedir libc_closedir
//go:cgo_import_dynamic libc_closedir closedir "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -37,5 +36,4 @@ func readdir_r(dir uintptr, entry *Dirent, result **Dirent) (res Errno) {
func libc_readdir_r_trampoline()
-//go:linkname libc_readdir_r libc_readdir_r
//go:cgo_import_dynamic libc_readdir_r readdir_r "/usr/lib/libSystem.B.dylib"
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go
index 23b65a5301..23be592a9f 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go
@@ -25,7 +25,6 @@ func getgroups(ngid int, gid *_Gid_t) (n int, err error) {
func libc_getgroups_trampoline()
-//go:linkname libc_getgroups libc_getgroups
//go:cgo_import_dynamic libc_getgroups getgroups "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -40,7 +39,6 @@ func setgroups(ngid int, gid *_Gid_t) (err error) {
func libc_setgroups_trampoline()
-//go:linkname libc_setgroups libc_setgroups
//go:cgo_import_dynamic libc_setgroups setgroups "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -56,7 +54,6 @@ func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err
func libc_wait4_trampoline()
-//go:linkname libc_wait4 libc_wait4
//go:cgo_import_dynamic libc_wait4 wait4 "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -72,7 +69,6 @@ func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) {
func libc_accept_trampoline()
-//go:linkname libc_accept libc_accept
//go:cgo_import_dynamic libc_accept accept "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -87,7 +83,6 @@ func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) {
func libc_bind_trampoline()
-//go:linkname libc_bind libc_bind
//go:cgo_import_dynamic libc_bind bind "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -102,7 +97,6 @@ func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) {
func libc_connect_trampoline()
-//go:linkname libc_connect libc_connect
//go:cgo_import_dynamic libc_connect connect "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -118,7 +112,6 @@ func socket(domain int, typ int, proto int) (fd int, err error) {
func libc_socket_trampoline()
-//go:linkname libc_socket libc_socket
//go:cgo_import_dynamic libc_socket socket "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -133,7 +126,6 @@ func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen
func libc_getsockopt_trampoline()
-//go:linkname libc_getsockopt libc_getsockopt
//go:cgo_import_dynamic libc_getsockopt getsockopt "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -148,7 +140,6 @@ func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr)
func libc_setsockopt_trampoline()
-//go:linkname libc_setsockopt libc_setsockopt
//go:cgo_import_dynamic libc_setsockopt setsockopt "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -163,7 +154,6 @@ func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
func libc_getpeername_trampoline()
-//go:linkname libc_getpeername libc_getpeername
//go:cgo_import_dynamic libc_getpeername getpeername "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -178,7 +168,6 @@ func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
func libc_getsockname_trampoline()
-//go:linkname libc_getsockname libc_getsockname
//go:cgo_import_dynamic libc_getsockname getsockname "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -193,7 +182,6 @@ func Shutdown(s int, how int) (err error) {
func libc_shutdown_trampoline()
-//go:linkname libc_shutdown libc_shutdown
//go:cgo_import_dynamic libc_shutdown shutdown "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -208,7 +196,6 @@ func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) {
func libc_socketpair_trampoline()
-//go:linkname libc_socketpair libc_socketpair
//go:cgo_import_dynamic libc_socketpair socketpair "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -230,7 +217,6 @@ func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Sockl
func libc_recvfrom_trampoline()
-//go:linkname libc_recvfrom libc_recvfrom
//go:cgo_import_dynamic libc_recvfrom recvfrom "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -251,7 +237,6 @@ func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (
func libc_sendto_trampoline()
-//go:linkname libc_sendto libc_sendto
//go:cgo_import_dynamic libc_sendto sendto "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -267,7 +252,6 @@ func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) {
func libc_recvmsg_trampoline()
-//go:linkname libc_recvmsg libc_recvmsg
//go:cgo_import_dynamic libc_recvmsg recvmsg "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -283,7 +267,6 @@ func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) {
func libc_sendmsg_trampoline()
-//go:linkname libc_sendmsg libc_sendmsg
//go:cgo_import_dynamic libc_sendmsg sendmsg "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -299,7 +282,6 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne
func libc_kevent_trampoline()
-//go:linkname libc_kevent libc_kevent
//go:cgo_import_dynamic libc_kevent kevent "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -319,7 +301,6 @@ func utimes(path string, timeval *[2]Timeval) (err error) {
func libc_utimes_trampoline()
-//go:linkname libc_utimes libc_utimes
//go:cgo_import_dynamic libc_utimes utimes "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -334,7 +315,6 @@ func futimes(fd int, timeval *[2]Timeval) (err error) {
func libc_futimes_trampoline()
-//go:linkname libc_futimes libc_futimes
//go:cgo_import_dynamic libc_futimes futimes "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -350,7 +330,6 @@ func poll(fds *PollFd, nfds int, timeout int) (n int, err error) {
func libc_poll_trampoline()
-//go:linkname libc_poll libc_poll
//go:cgo_import_dynamic libc_poll poll "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -371,7 +350,6 @@ func Madvise(b []byte, behav int) (err error) {
func libc_madvise_trampoline()
-//go:linkname libc_madvise libc_madvise
//go:cgo_import_dynamic libc_madvise madvise "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -392,7 +370,6 @@ func Mlock(b []byte) (err error) {
func libc_mlock_trampoline()
-//go:linkname libc_mlock libc_mlock
//go:cgo_import_dynamic libc_mlock mlock "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -407,7 +384,6 @@ func Mlockall(flags int) (err error) {
func libc_mlockall_trampoline()
-//go:linkname libc_mlockall libc_mlockall
//go:cgo_import_dynamic libc_mlockall mlockall "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -428,7 +404,6 @@ func Mprotect(b []byte, prot int) (err error) {
func libc_mprotect_trampoline()
-//go:linkname libc_mprotect libc_mprotect
//go:cgo_import_dynamic libc_mprotect mprotect "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -449,7 +424,6 @@ func Msync(b []byte, flags int) (err error) {
func libc_msync_trampoline()
-//go:linkname libc_msync libc_msync
//go:cgo_import_dynamic libc_msync msync "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -470,7 +444,6 @@ func Munlock(b []byte) (err error) {
func libc_munlock_trampoline()
-//go:linkname libc_munlock libc_munlock
//go:cgo_import_dynamic libc_munlock munlock "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -485,7 +458,6 @@ func Munlockall() (err error) {
func libc_munlockall_trampoline()
-//go:linkname libc_munlockall libc_munlockall
//go:cgo_import_dynamic libc_munlockall munlockall "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -502,7 +474,6 @@ func pipe() (r int, w int, err error) {
func libc_pipe_trampoline()
-//go:linkname libc_pipe libc_pipe
//go:cgo_import_dynamic libc_pipe pipe "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -528,7 +499,6 @@ func getxattr(path string, attr string, dest *byte, size int, position uint32, o
func libc_getxattr_trampoline()
-//go:linkname libc_getxattr libc_getxattr
//go:cgo_import_dynamic libc_getxattr getxattr "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -549,7 +519,6 @@ func fgetxattr(fd int, attr string, dest *byte, size int, position uint32, optio
func libc_fgetxattr_trampoline()
-//go:linkname libc_fgetxattr libc_fgetxattr
//go:cgo_import_dynamic libc_fgetxattr fgetxattr "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -574,7 +543,6 @@ func setxattr(path string, attr string, data *byte, size int, position uint32, o
func libc_setxattr_trampoline()
-//go:linkname libc_setxattr libc_setxattr
//go:cgo_import_dynamic libc_setxattr setxattr "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -594,7 +562,6 @@ func fsetxattr(fd int, attr string, data *byte, size int, position uint32, optio
func libc_fsetxattr_trampoline()
-//go:linkname libc_fsetxattr libc_fsetxattr
//go:cgo_import_dynamic libc_fsetxattr fsetxattr "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -619,7 +586,6 @@ func removexattr(path string, attr string, options int) (err error) {
func libc_removexattr_trampoline()
-//go:linkname libc_removexattr libc_removexattr
//go:cgo_import_dynamic libc_removexattr removexattr "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -639,7 +605,6 @@ func fremovexattr(fd int, attr string, options int) (err error) {
func libc_fremovexattr_trampoline()
-//go:linkname libc_fremovexattr libc_fremovexattr
//go:cgo_import_dynamic libc_fremovexattr fremovexattr "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -660,7 +625,6 @@ func listxattr(path string, dest *byte, size int, options int) (sz int, err erro
func libc_listxattr_trampoline()
-//go:linkname libc_listxattr libc_listxattr
//go:cgo_import_dynamic libc_listxattr listxattr "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -676,7 +640,6 @@ func flistxattr(fd int, dest *byte, size int, options int) (sz int, err error) {
func libc_flistxattr_trampoline()
-//go:linkname libc_flistxattr libc_flistxattr
//go:cgo_import_dynamic libc_flistxattr flistxattr "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -691,7 +654,6 @@ func setattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintp
func libc_setattrlist_trampoline()
-//go:linkname libc_setattrlist libc_setattrlist
//go:cgo_import_dynamic libc_setattrlist setattrlist "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -707,7 +669,6 @@ func fcntl(fd int, cmd int, arg int) (val int, err error) {
func libc_fcntl_trampoline()
-//go:linkname libc_fcntl libc_fcntl
//go:cgo_import_dynamic libc_fcntl fcntl "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -722,7 +683,6 @@ func kill(pid int, signum int, posix int) (err error) {
func libc_kill_trampoline()
-//go:linkname libc_kill libc_kill
//go:cgo_import_dynamic libc_kill kill "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -737,7 +697,6 @@ func ioctl(fd int, req uint, arg uintptr) (err error) {
func libc_ioctl_trampoline()
-//go:linkname libc_ioctl libc_ioctl
//go:cgo_import_dynamic libc_ioctl ioctl "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -758,7 +717,6 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr)
func libc_sysctl_trampoline()
-//go:linkname libc_sysctl libc_sysctl
//go:cgo_import_dynamic libc_sysctl sysctl "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -773,7 +731,6 @@ func sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer
func libc_sendfile_trampoline()
-//go:linkname libc_sendfile libc_sendfile
//go:cgo_import_dynamic libc_sendfile sendfile "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -793,7 +750,6 @@ func Access(path string, mode uint32) (err error) {
func libc_access_trampoline()
-//go:linkname libc_access libc_access
//go:cgo_import_dynamic libc_access access "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -808,7 +764,6 @@ func Adjtime(delta *Timeval, olddelta *Timeval) (err error) {
func libc_adjtime_trampoline()
-//go:linkname libc_adjtime libc_adjtime
//go:cgo_import_dynamic libc_adjtime adjtime "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -828,7 +783,6 @@ func Chdir(path string) (err error) {
func libc_chdir_trampoline()
-//go:linkname libc_chdir libc_chdir
//go:cgo_import_dynamic libc_chdir chdir "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -848,7 +802,6 @@ func Chflags(path string, flags int) (err error) {
func libc_chflags_trampoline()
-//go:linkname libc_chflags libc_chflags
//go:cgo_import_dynamic libc_chflags chflags "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -868,7 +821,6 @@ func Chmod(path string, mode uint32) (err error) {
func libc_chmod_trampoline()
-//go:linkname libc_chmod libc_chmod
//go:cgo_import_dynamic libc_chmod chmod "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -888,7 +840,6 @@ func Chown(path string, uid int, gid int) (err error) {
func libc_chown_trampoline()
-//go:linkname libc_chown libc_chown
//go:cgo_import_dynamic libc_chown chown "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -908,7 +859,6 @@ func Chroot(path string) (err error) {
func libc_chroot_trampoline()
-//go:linkname libc_chroot libc_chroot
//go:cgo_import_dynamic libc_chroot chroot "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -923,7 +873,6 @@ func ClockGettime(clockid int32, time *Timespec) (err error) {
func libc_clock_gettime_trampoline()
-//go:linkname libc_clock_gettime libc_clock_gettime
//go:cgo_import_dynamic libc_clock_gettime clock_gettime "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -938,7 +887,6 @@ func Close(fd int) (err error) {
func libc_close_trampoline()
-//go:linkname libc_close libc_close
//go:cgo_import_dynamic libc_close close "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -963,7 +911,6 @@ func Clonefile(src string, dst string, flags int) (err error) {
func libc_clonefile_trampoline()
-//go:linkname libc_clonefile libc_clonefile
//go:cgo_import_dynamic libc_clonefile clonefile "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -988,7 +935,6 @@ func Clonefileat(srcDirfd int, src string, dstDirfd int, dst string, flags int)
func libc_clonefileat_trampoline()
-//go:linkname libc_clonefileat libc_clonefileat
//go:cgo_import_dynamic libc_clonefileat clonefileat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1004,7 +950,6 @@ func Dup(fd int) (nfd int, err error) {
func libc_dup_trampoline()
-//go:linkname libc_dup libc_dup
//go:cgo_import_dynamic libc_dup dup "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1019,7 +964,6 @@ func Dup2(from int, to int) (err error) {
func libc_dup2_trampoline()
-//go:linkname libc_dup2 libc_dup2
//go:cgo_import_dynamic libc_dup2 dup2 "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1044,7 +988,6 @@ func Exchangedata(path1 string, path2 string, options int) (err error) {
func libc_exchangedata_trampoline()
-//go:linkname libc_exchangedata libc_exchangedata
//go:cgo_import_dynamic libc_exchangedata exchangedata "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1056,7 +999,6 @@ func Exit(code int) {
func libc_exit_trampoline()
-//go:linkname libc_exit libc_exit
//go:cgo_import_dynamic libc_exit exit "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1076,7 +1018,6 @@ func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) {
func libc_faccessat_trampoline()
-//go:linkname libc_faccessat libc_faccessat
//go:cgo_import_dynamic libc_faccessat faccessat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1091,7 +1032,6 @@ func Fchdir(fd int) (err error) {
func libc_fchdir_trampoline()
-//go:linkname libc_fchdir libc_fchdir
//go:cgo_import_dynamic libc_fchdir fchdir "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1106,7 +1046,6 @@ func Fchflags(fd int, flags int) (err error) {
func libc_fchflags_trampoline()
-//go:linkname libc_fchflags libc_fchflags
//go:cgo_import_dynamic libc_fchflags fchflags "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1121,7 +1060,6 @@ func Fchmod(fd int, mode uint32) (err error) {
func libc_fchmod_trampoline()
-//go:linkname libc_fchmod libc_fchmod
//go:cgo_import_dynamic libc_fchmod fchmod "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1141,7 +1079,6 @@ func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) {
func libc_fchmodat_trampoline()
-//go:linkname libc_fchmodat libc_fchmodat
//go:cgo_import_dynamic libc_fchmodat fchmodat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1156,7 +1093,6 @@ func Fchown(fd int, uid int, gid int) (err error) {
func libc_fchown_trampoline()
-//go:linkname libc_fchown libc_fchown
//go:cgo_import_dynamic libc_fchown fchown "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1176,7 +1112,6 @@ func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) {
func libc_fchownat_trampoline()
-//go:linkname libc_fchownat libc_fchownat
//go:cgo_import_dynamic libc_fchownat fchownat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1196,7 +1131,6 @@ func Fclonefileat(srcDirfd int, dstDirfd int, dst string, flags int) (err error)
func libc_fclonefileat_trampoline()
-//go:linkname libc_fclonefileat libc_fclonefileat
//go:cgo_import_dynamic libc_fclonefileat fclonefileat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1211,7 +1145,6 @@ func Flock(fd int, how int) (err error) {
func libc_flock_trampoline()
-//go:linkname libc_flock libc_flock
//go:cgo_import_dynamic libc_flock flock "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1227,7 +1160,6 @@ func Fpathconf(fd int, name int) (val int, err error) {
func libc_fpathconf_trampoline()
-//go:linkname libc_fpathconf libc_fpathconf
//go:cgo_import_dynamic libc_fpathconf fpathconf "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1242,7 +1174,6 @@ func Fsync(fd int) (err error) {
func libc_fsync_trampoline()
-//go:linkname libc_fsync libc_fsync
//go:cgo_import_dynamic libc_fsync fsync "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1257,7 +1188,6 @@ func Ftruncate(fd int, length int64) (err error) {
func libc_ftruncate_trampoline()
-//go:linkname libc_ftruncate libc_ftruncate
//go:cgo_import_dynamic libc_ftruncate ftruncate "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1279,7 +1209,6 @@ func Getcwd(buf []byte) (n int, err error) {
func libc_getcwd_trampoline()
-//go:linkname libc_getcwd libc_getcwd
//go:cgo_import_dynamic libc_getcwd getcwd "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1292,7 +1221,6 @@ func Getdtablesize() (size int) {
func libc_getdtablesize_trampoline()
-//go:linkname libc_getdtablesize libc_getdtablesize
//go:cgo_import_dynamic libc_getdtablesize getdtablesize "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1305,7 +1233,6 @@ func Getegid() (egid int) {
func libc_getegid_trampoline()
-//go:linkname libc_getegid libc_getegid
//go:cgo_import_dynamic libc_getegid getegid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1318,7 +1245,6 @@ func Geteuid() (uid int) {
func libc_geteuid_trampoline()
-//go:linkname libc_geteuid libc_geteuid
//go:cgo_import_dynamic libc_geteuid geteuid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1331,7 +1257,6 @@ func Getgid() (gid int) {
func libc_getgid_trampoline()
-//go:linkname libc_getgid libc_getgid
//go:cgo_import_dynamic libc_getgid getgid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1347,7 +1272,6 @@ func Getpgid(pid int) (pgid int, err error) {
func libc_getpgid_trampoline()
-//go:linkname libc_getpgid libc_getpgid
//go:cgo_import_dynamic libc_getpgid getpgid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1360,7 +1284,6 @@ func Getpgrp() (pgrp int) {
func libc_getpgrp_trampoline()
-//go:linkname libc_getpgrp libc_getpgrp
//go:cgo_import_dynamic libc_getpgrp getpgrp "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1373,7 +1296,6 @@ func Getpid() (pid int) {
func libc_getpid_trampoline()
-//go:linkname libc_getpid libc_getpid
//go:cgo_import_dynamic libc_getpid getpid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1386,7 +1308,6 @@ func Getppid() (ppid int) {
func libc_getppid_trampoline()
-//go:linkname libc_getppid libc_getppid
//go:cgo_import_dynamic libc_getppid getppid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1402,7 +1323,6 @@ func Getpriority(which int, who int) (prio int, err error) {
func libc_getpriority_trampoline()
-//go:linkname libc_getpriority libc_getpriority
//go:cgo_import_dynamic libc_getpriority getpriority "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1417,7 +1337,6 @@ func Getrlimit(which int, lim *Rlimit) (err error) {
func libc_getrlimit_trampoline()
-//go:linkname libc_getrlimit libc_getrlimit
//go:cgo_import_dynamic libc_getrlimit getrlimit "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1432,7 +1351,6 @@ func Getrusage(who int, rusage *Rusage) (err error) {
func libc_getrusage_trampoline()
-//go:linkname libc_getrusage libc_getrusage
//go:cgo_import_dynamic libc_getrusage getrusage "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1448,7 +1366,6 @@ func Getsid(pid int) (sid int, err error) {
func libc_getsid_trampoline()
-//go:linkname libc_getsid libc_getsid
//go:cgo_import_dynamic libc_getsid getsid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1463,7 +1380,6 @@ func Gettimeofday(tp *Timeval) (err error) {
func libc_gettimeofday_trampoline()
-//go:linkname libc_gettimeofday libc_gettimeofday
//go:cgo_import_dynamic libc_gettimeofday gettimeofday "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1476,7 +1392,6 @@ func Getuid() (uid int) {
func libc_getuid_trampoline()
-//go:linkname libc_getuid libc_getuid
//go:cgo_import_dynamic libc_getuid getuid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1489,7 +1404,6 @@ func Issetugid() (tainted bool) {
func libc_issetugid_trampoline()
-//go:linkname libc_issetugid libc_issetugid
//go:cgo_import_dynamic libc_issetugid issetugid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1505,7 +1419,6 @@ func Kqueue() (fd int, err error) {
func libc_kqueue_trampoline()
-//go:linkname libc_kqueue libc_kqueue
//go:cgo_import_dynamic libc_kqueue kqueue "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1525,7 +1438,6 @@ func Lchown(path string, uid int, gid int) (err error) {
func libc_lchown_trampoline()
-//go:linkname libc_lchown libc_lchown
//go:cgo_import_dynamic libc_lchown lchown "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1550,7 +1462,6 @@ func Link(path string, link string) (err error) {
func libc_link_trampoline()
-//go:linkname libc_link libc_link
//go:cgo_import_dynamic libc_link link "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1575,7 +1486,6 @@ func Linkat(pathfd int, path string, linkfd int, link string, flags int) (err er
func libc_linkat_trampoline()
-//go:linkname libc_linkat libc_linkat
//go:cgo_import_dynamic libc_linkat linkat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1590,7 +1500,6 @@ func Listen(s int, backlog int) (err error) {
func libc_listen_trampoline()
-//go:linkname libc_listen libc_listen
//go:cgo_import_dynamic libc_listen listen "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1610,7 +1519,6 @@ func Mkdir(path string, mode uint32) (err error) {
func libc_mkdir_trampoline()
-//go:linkname libc_mkdir libc_mkdir
//go:cgo_import_dynamic libc_mkdir mkdir "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1630,7 +1538,6 @@ func Mkdirat(dirfd int, path string, mode uint32) (err error) {
func libc_mkdirat_trampoline()
-//go:linkname libc_mkdirat libc_mkdirat
//go:cgo_import_dynamic libc_mkdirat mkdirat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1650,7 +1557,6 @@ func Mkfifo(path string, mode uint32) (err error) {
func libc_mkfifo_trampoline()
-//go:linkname libc_mkfifo libc_mkfifo
//go:cgo_import_dynamic libc_mkfifo mkfifo "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1670,7 +1576,6 @@ func Mknod(path string, mode uint32, dev int) (err error) {
func libc_mknod_trampoline()
-//go:linkname libc_mknod libc_mknod
//go:cgo_import_dynamic libc_mknod mknod "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1691,7 +1596,6 @@ func Open(path string, mode int, perm uint32) (fd int, err error) {
func libc_open_trampoline()
-//go:linkname libc_open libc_open
//go:cgo_import_dynamic libc_open open "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1712,7 +1616,6 @@ func Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) {
func libc_openat_trampoline()
-//go:linkname libc_openat libc_openat
//go:cgo_import_dynamic libc_openat openat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1733,7 +1636,6 @@ func Pathconf(path string, name int) (val int, err error) {
func libc_pathconf_trampoline()
-//go:linkname libc_pathconf libc_pathconf
//go:cgo_import_dynamic libc_pathconf pathconf "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1755,7 +1657,6 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) {
func libc_pread_trampoline()
-//go:linkname libc_pread libc_pread
//go:cgo_import_dynamic libc_pread pread "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1777,7 +1678,6 @@ func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
func libc_pwrite_trampoline()
-//go:linkname libc_pwrite libc_pwrite
//go:cgo_import_dynamic libc_pwrite pwrite "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1799,7 +1699,6 @@ func read(fd int, p []byte) (n int, err error) {
func libc_read_trampoline()
-//go:linkname libc_read libc_read
//go:cgo_import_dynamic libc_read read "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1826,7 +1725,6 @@ func Readlink(path string, buf []byte) (n int, err error) {
func libc_readlink_trampoline()
-//go:linkname libc_readlink libc_readlink
//go:cgo_import_dynamic libc_readlink readlink "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1853,7 +1751,6 @@ func Readlinkat(dirfd int, path string, buf []byte) (n int, err error) {
func libc_readlinkat_trampoline()
-//go:linkname libc_readlinkat libc_readlinkat
//go:cgo_import_dynamic libc_readlinkat readlinkat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1878,7 +1775,6 @@ func Rename(from string, to string) (err error) {
func libc_rename_trampoline()
-//go:linkname libc_rename libc_rename
//go:cgo_import_dynamic libc_rename rename "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1903,7 +1799,6 @@ func Renameat(fromfd int, from string, tofd int, to string) (err error) {
func libc_renameat_trampoline()
-//go:linkname libc_renameat libc_renameat
//go:cgo_import_dynamic libc_renameat renameat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1923,7 +1818,6 @@ func Revoke(path string) (err error) {
func libc_revoke_trampoline()
-//go:linkname libc_revoke libc_revoke
//go:cgo_import_dynamic libc_revoke revoke "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1943,7 +1837,6 @@ func Rmdir(path string) (err error) {
func libc_rmdir_trampoline()
-//go:linkname libc_rmdir libc_rmdir
//go:cgo_import_dynamic libc_rmdir rmdir "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1959,7 +1852,6 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
func libc_lseek_trampoline()
-//go:linkname libc_lseek libc_lseek
//go:cgo_import_dynamic libc_lseek lseek "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1975,7 +1867,6 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err
func libc_select_trampoline()
-//go:linkname libc_select libc_select
//go:cgo_import_dynamic libc_select select "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1990,7 +1881,6 @@ func Setegid(egid int) (err error) {
func libc_setegid_trampoline()
-//go:linkname libc_setegid libc_setegid
//go:cgo_import_dynamic libc_setegid setegid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2005,7 +1895,6 @@ func Seteuid(euid int) (err error) {
func libc_seteuid_trampoline()
-//go:linkname libc_seteuid libc_seteuid
//go:cgo_import_dynamic libc_seteuid seteuid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2020,7 +1909,6 @@ func Setgid(gid int) (err error) {
func libc_setgid_trampoline()
-//go:linkname libc_setgid libc_setgid
//go:cgo_import_dynamic libc_setgid setgid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2040,7 +1928,6 @@ func Setlogin(name string) (err error) {
func libc_setlogin_trampoline()
-//go:linkname libc_setlogin libc_setlogin
//go:cgo_import_dynamic libc_setlogin setlogin "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2055,7 +1942,6 @@ func Setpgid(pid int, pgid int) (err error) {
func libc_setpgid_trampoline()
-//go:linkname libc_setpgid libc_setpgid
//go:cgo_import_dynamic libc_setpgid setpgid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2070,7 +1956,6 @@ func Setpriority(which int, who int, prio int) (err error) {
func libc_setpriority_trampoline()
-//go:linkname libc_setpriority libc_setpriority
//go:cgo_import_dynamic libc_setpriority setpriority "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2085,7 +1970,6 @@ func Setprivexec(flag int) (err error) {
func libc_setprivexec_trampoline()
-//go:linkname libc_setprivexec libc_setprivexec
//go:cgo_import_dynamic libc_setprivexec setprivexec "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2100,7 +1984,6 @@ func Setregid(rgid int, egid int) (err error) {
func libc_setregid_trampoline()
-//go:linkname libc_setregid libc_setregid
//go:cgo_import_dynamic libc_setregid setregid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2115,7 +1998,6 @@ func Setreuid(ruid int, euid int) (err error) {
func libc_setreuid_trampoline()
-//go:linkname libc_setreuid libc_setreuid
//go:cgo_import_dynamic libc_setreuid setreuid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2130,7 +2012,6 @@ func Setrlimit(which int, lim *Rlimit) (err error) {
func libc_setrlimit_trampoline()
-//go:linkname libc_setrlimit libc_setrlimit
//go:cgo_import_dynamic libc_setrlimit setrlimit "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2146,7 +2027,6 @@ func Setsid() (pid int, err error) {
func libc_setsid_trampoline()
-//go:linkname libc_setsid libc_setsid
//go:cgo_import_dynamic libc_setsid setsid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2161,7 +2041,6 @@ func Settimeofday(tp *Timeval) (err error) {
func libc_settimeofday_trampoline()
-//go:linkname libc_settimeofday libc_settimeofday
//go:cgo_import_dynamic libc_settimeofday settimeofday "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2176,7 +2055,6 @@ func Setuid(uid int) (err error) {
func libc_setuid_trampoline()
-//go:linkname libc_setuid libc_setuid
//go:cgo_import_dynamic libc_setuid setuid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2201,7 +2079,6 @@ func Symlink(path string, link string) (err error) {
func libc_symlink_trampoline()
-//go:linkname libc_symlink libc_symlink
//go:cgo_import_dynamic libc_symlink symlink "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2226,7 +2103,6 @@ func Symlinkat(oldpath string, newdirfd int, newpath string) (err error) {
func libc_symlinkat_trampoline()
-//go:linkname libc_symlinkat libc_symlinkat
//go:cgo_import_dynamic libc_symlinkat symlinkat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2241,7 +2117,6 @@ func Sync() (err error) {
func libc_sync_trampoline()
-//go:linkname libc_sync libc_sync
//go:cgo_import_dynamic libc_sync sync "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2261,7 +2136,6 @@ func Truncate(path string, length int64) (err error) {
func libc_truncate_trampoline()
-//go:linkname libc_truncate libc_truncate
//go:cgo_import_dynamic libc_truncate truncate "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2274,7 +2148,6 @@ func Umask(newmask int) (oldmask int) {
func libc_umask_trampoline()
-//go:linkname libc_umask libc_umask
//go:cgo_import_dynamic libc_umask umask "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2294,7 +2167,6 @@ func Undelete(path string) (err error) {
func libc_undelete_trampoline()
-//go:linkname libc_undelete libc_undelete
//go:cgo_import_dynamic libc_undelete undelete "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2314,7 +2186,6 @@ func Unlink(path string) (err error) {
func libc_unlink_trampoline()
-//go:linkname libc_unlink libc_unlink
//go:cgo_import_dynamic libc_unlink unlink "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2334,7 +2205,6 @@ func Unlinkat(dirfd int, path string, flags int) (err error) {
func libc_unlinkat_trampoline()
-//go:linkname libc_unlinkat libc_unlinkat
//go:cgo_import_dynamic libc_unlinkat unlinkat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2354,7 +2224,6 @@ func Unmount(path string, flags int) (err error) {
func libc_unmount_trampoline()
-//go:linkname libc_unmount libc_unmount
//go:cgo_import_dynamic libc_unmount unmount "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2376,7 +2245,6 @@ func write(fd int, p []byte) (n int, err error) {
func libc_write_trampoline()
-//go:linkname libc_write libc_write
//go:cgo_import_dynamic libc_write write "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2392,7 +2260,6 @@ func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (
func libc_mmap_trampoline()
-//go:linkname libc_mmap libc_mmap
//go:cgo_import_dynamic libc_mmap mmap "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2407,7 +2274,6 @@ func munmap(addr uintptr, length uintptr) (err error) {
func libc_munmap_trampoline()
-//go:linkname libc_munmap libc_munmap
//go:cgo_import_dynamic libc_munmap munmap "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2444,7 +2310,6 @@ func Fstat(fd int, stat *Stat_t) (err error) {
func libc_fstat_trampoline()
-//go:linkname libc_fstat libc_fstat
//go:cgo_import_dynamic libc_fstat fstat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2464,7 +2329,6 @@ func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) {
func libc_fstatat_trampoline()
-//go:linkname libc_fstatat libc_fstatat
//go:cgo_import_dynamic libc_fstatat fstatat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2479,7 +2343,6 @@ func Fstatfs(fd int, stat *Statfs_t) (err error) {
func libc_fstatfs_trampoline()
-//go:linkname libc_fstatfs libc_fstatfs
//go:cgo_import_dynamic libc_fstatfs fstatfs "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2495,7 +2358,6 @@ func getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) {
func libc_getfsstat_trampoline()
-//go:linkname libc_getfsstat libc_getfsstat
//go:cgo_import_dynamic libc_getfsstat getfsstat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2515,7 +2377,6 @@ func Lstat(path string, stat *Stat_t) (err error) {
func libc_lstat_trampoline()
-//go:linkname libc_lstat libc_lstat
//go:cgo_import_dynamic libc_lstat lstat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2530,7 +2391,6 @@ func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) {
func libc_ptrace_trampoline()
-//go:linkname libc_ptrace libc_ptrace
//go:cgo_import_dynamic libc_ptrace ptrace "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2550,7 +2410,6 @@ func Stat(path string, stat *Stat_t) (err error) {
func libc_stat_trampoline()
-//go:linkname libc_stat libc_stat
//go:cgo_import_dynamic libc_stat stat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2570,5 +2429,4 @@ func Statfs(path string, stat *Statfs_t) (err error) {
func libc_statfs_trampoline()
-//go:linkname libc_statfs libc_statfs
//go:cgo_import_dynamic libc_statfs statfs "/usr/lib/libSystem.B.dylib"
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go
index aebfe511ad..1aaccd3615 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go
@@ -362,6 +362,16 @@ func pipe() (r int, w int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+func pipe2(p *[2]_C_int, flags int) (err error) {
+ _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
func extpread(fd int, p []byte, flags int, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_386.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_386.go
index 830fbb35c0..725b4bee27 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_386.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_386.go
@@ -269,6 +269,7 @@ const (
SizeofSockaddrDatalink = 0x14
SizeofSockaddrCtl = 0x20
SizeofLinger = 0x8
+ SizeofIovec = 0x8
SizeofIPMreq = 0x8
SizeofIPv6Mreq = 0x14
SizeofMsghdr = 0x1c
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go
index e53a7c49ff..080ffce325 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go
@@ -274,6 +274,7 @@ const (
SizeofSockaddrDatalink = 0x14
SizeofSockaddrCtl = 0x20
SizeofLinger = 0x8
+ SizeofIovec = 0x10
SizeofIPMreq = 0x8
SizeofIPv6Mreq = 0x14
SizeofMsghdr = 0x30
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_arm.go
index 98be973ef9..f2a77bc4e2 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_arm.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_arm.go
@@ -269,6 +269,7 @@ const (
SizeofSockaddrDatalink = 0x14
SizeofSockaddrCtl = 0x20
SizeofLinger = 0x8
+ SizeofIovec = 0x8
SizeofIPMreq = 0x8
SizeofIPv6Mreq = 0x14
SizeofMsghdr = 0x1c
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go
index ddae5afe1b..c9492428bf 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go
@@ -274,6 +274,7 @@ const (
SizeofSockaddrDatalink = 0x14
SizeofSockaddrCtl = 0x20
SizeofLinger = 0x8
+ SizeofIovec = 0x10
SizeofIPMreq = 0x8
SizeofIPv6Mreq = 0x14
SizeofMsghdr = 0x30
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux.go
index a96ad4c299..504ef131fb 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux.go
@@ -2981,3 +2981,21 @@ type PPSKTime struct {
Nsec int32
Flags uint32
}
+
+const (
+ LWTUNNEL_ENCAP_NONE = 0x0
+ LWTUNNEL_ENCAP_MPLS = 0x1
+ LWTUNNEL_ENCAP_IP = 0x2
+ LWTUNNEL_ENCAP_ILA = 0x3
+ LWTUNNEL_ENCAP_IP6 = 0x4
+ LWTUNNEL_ENCAP_SEG6 = 0x5
+ LWTUNNEL_ENCAP_BPF = 0x6
+ LWTUNNEL_ENCAP_SEG6_LOCAL = 0x7
+ LWTUNNEL_ENCAP_RPL = 0x8
+ LWTUNNEL_ENCAP_MAX = 0x8
+
+ MPLS_IPTUNNEL_UNSPEC = 0x0
+ MPLS_IPTUNNEL_DST = 0x1
+ MPLS_IPTUNNEL_TTL = 0x2
+ MPLS_IPTUNNEL_MAX = 0x2
+)
diff --git a/src/cmd/vendor/golang.org/x/sys/windows/dll_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/dll_windows.go
index 82076fb74f..115341fba6 100644
--- a/src/cmd/vendor/golang.org/x/sys/windows/dll_windows.go
+++ b/src/cmd/vendor/golang.org/x/sys/windows/dll_windows.go
@@ -32,6 +32,8 @@ type DLLError struct {
func (e *DLLError) Error() string { return e.Msg }
+func (e *DLLError) Unwrap() error { return e.Err }
+
// A DLL implements access to a single DLL.
type DLL struct {
Name string
@@ -389,7 +391,6 @@ func loadLibraryEx(name string, system bool) (*DLL, error) {
var flags uintptr
if system {
if canDoSearchSystem32() {
- const LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800
flags = LOAD_LIBRARY_SEARCH_SYSTEM32
} else if isBaseName(name) {
// WindowsXP or unpatched Windows machine
diff --git a/src/cmd/vendor/golang.org/x/sys/windows/security_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/security_windows.go
index 9e3c44a855..69eb462c59 100644
--- a/src/cmd/vendor/golang.org/x/sys/windows/security_windows.go
+++ b/src/cmd/vendor/golang.org/x/sys/windows/security_windows.go
@@ -624,6 +624,7 @@ func (tml *Tokenmandatorylabel) Size() uint32 {
// Authorization Functions
//sys checkTokenMembership(tokenHandle Token, sidToCheck *SID, isMember *int32) (err error) = advapi32.CheckTokenMembership
+//sys isTokenRestricted(tokenHandle Token) (ret bool, err error) [!failretval] = advapi32.IsTokenRestricted
//sys OpenProcessToken(process Handle, access uint32, token *Token) (err error) = advapi32.OpenProcessToken
//sys OpenThreadToken(thread Handle, access uint32, openAsSelf bool, token *Token) (err error) = advapi32.OpenThreadToken
//sys ImpersonateSelf(impersonationlevel uint32) (err error) = advapi32.ImpersonateSelf
@@ -837,6 +838,16 @@ func (t Token) IsMember(sid *SID) (bool, error) {
return b != 0, nil
}
+// IsRestricted reports whether the access token t is a restricted token.
+func (t Token) IsRestricted() (isRestricted bool, err error) {
+ isRestricted, err = isTokenRestricted(t)
+ if !isRestricted && err == syscall.EINVAL {
+ // If err is EINVAL, this returned ERROR_SUCCESS indicating a non-restricted token.
+ err = nil
+ }
+ return
+}
+
const (
WTS_CONSOLE_CONNECT = 0x1
WTS_CONSOLE_DISCONNECT = 0x2
@@ -1103,9 +1114,10 @@ type OBJECTS_AND_NAME struct {
}
//sys getSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner **SID, group **SID, dacl **ACL, sacl **ACL, sd **SECURITY_DESCRIPTOR) (ret error) = advapi32.GetSecurityInfo
-//sys SetSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) = advapi32.SetSecurityInfo
+//sys SetSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) (ret error) = advapi32.SetSecurityInfo
//sys getNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner **SID, group **SID, dacl **ACL, sacl **ACL, sd **SECURITY_DESCRIPTOR) (ret error) = advapi32.GetNamedSecurityInfoW
//sys SetNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) (ret error) = advapi32.SetNamedSecurityInfoW
+//sys SetKernelObjectSecurity(handle Handle, securityInformation SECURITY_INFORMATION, securityDescriptor *SECURITY_DESCRIPTOR) (err error) = advapi32.SetKernelObjectSecurity
//sys buildSecurityDescriptor(owner *TRUSTEE, group *TRUSTEE, countAccessEntries uint32, accessEntries *EXPLICIT_ACCESS, countAuditEntries uint32, auditEntries *EXPLICIT_ACCESS, oldSecurityDescriptor *SECURITY_DESCRIPTOR, sizeNewSecurityDescriptor *uint32, newSecurityDescriptor **SECURITY_DESCRIPTOR) (ret error) = advapi32.BuildSecurityDescriptorW
//sys initializeSecurityDescriptor(absoluteSD *SECURITY_DESCRIPTOR, revision uint32) (err error) = advapi32.InitializeSecurityDescriptor
diff --git a/src/cmd/vendor/golang.org/x/sys/windows/service.go b/src/cmd/vendor/golang.org/x/sys/windows/service.go
index f54ff90aac..b269850d06 100644
--- a/src/cmd/vendor/golang.org/x/sys/windows/service.go
+++ b/src/cmd/vendor/golang.org/x/sys/windows/service.go
@@ -128,6 +128,10 @@ const (
SERVICE_NOTIFY_CREATED = 0x00000080
SERVICE_NOTIFY_DELETED = 0x00000100
SERVICE_NOTIFY_DELETE_PENDING = 0x00000200
+
+ SC_EVENT_DATABASE_CHANGE = 0
+ SC_EVENT_PROPERTY_CHANGE = 1
+ SC_EVENT_STATUS_CHANGE = 2
)
type SERVICE_STATUS struct {
@@ -229,3 +233,5 @@ type QUERY_SERVICE_LOCK_STATUS struct {
//sys EnumServicesStatusEx(mgr Handle, infoLevel uint32, serviceType uint32, serviceState uint32, services *byte, bufSize uint32, bytesNeeded *uint32, servicesReturned *uint32, resumeHandle *uint32, groupName *uint16) (err error) = advapi32.EnumServicesStatusExW
//sys QueryServiceStatusEx(service Handle, infoLevel uint32, buff *byte, buffSize uint32, bytesNeeded *uint32) (err error) = advapi32.QueryServiceStatusEx
//sys NotifyServiceStatusChange(service Handle, notifyMask uint32, notifier *SERVICE_NOTIFY) (ret error) = advapi32.NotifyServiceStatusChangeW
+//sys SubscribeServiceChangeNotifications(service Handle, eventType uint32, callback uintptr, callbackCtx uintptr, subscription *uintptr) (ret error) = sechost.SubscribeServiceChangeNotifications?
+//sys UnsubscribeServiceChangeNotifications(subscription uintptr) = sechost.UnsubscribeServiceChangeNotifications?
diff --git a/src/cmd/vendor/golang.org/x/sys/windows/setupapierrors_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/setupapierrors_windows.go
new file mode 100644
index 0000000000..1681810e04
--- /dev/null
+++ b/src/cmd/vendor/golang.org/x/sys/windows/setupapierrors_windows.go
@@ -0,0 +1,100 @@
+// Copyright 2020 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 windows
+
+import "syscall"
+
+const (
+ ERROR_EXPECTED_SECTION_NAME syscall.Errno = 0x20000000 | 0xC0000000 | 0
+ ERROR_BAD_SECTION_NAME_LINE syscall.Errno = 0x20000000 | 0xC0000000 | 1
+ ERROR_SECTION_NAME_TOO_LONG syscall.Errno = 0x20000000 | 0xC0000000 | 2
+ ERROR_GENERAL_SYNTAX syscall.Errno = 0x20000000 | 0xC0000000 | 3
+ ERROR_WRONG_INF_STYLE syscall.Errno = 0x20000000 | 0xC0000000 | 0x100
+ ERROR_SECTION_NOT_FOUND syscall.Errno = 0x20000000 | 0xC0000000 | 0x101
+ ERROR_LINE_NOT_FOUND syscall.Errno = 0x20000000 | 0xC0000000 | 0x102
+ ERROR_NO_BACKUP syscall.Errno = 0x20000000 | 0xC0000000 | 0x103
+ ERROR_NO_ASSOCIATED_CLASS syscall.Errno = 0x20000000 | 0xC0000000 | 0x200
+ ERROR_CLASS_MISMATCH syscall.Errno = 0x20000000 | 0xC0000000 | 0x201
+ ERROR_DUPLICATE_FOUND syscall.Errno = 0x20000000 | 0xC0000000 | 0x202
+ ERROR_NO_DRIVER_SELECTED syscall.Errno = 0x20000000 | 0xC0000000 | 0x203
+ ERROR_KEY_DOES_NOT_EXIST syscall.Errno = 0x20000000 | 0xC0000000 | 0x204
+ ERROR_INVALID_DEVINST_NAME syscall.Errno = 0x20000000 | 0xC0000000 | 0x205
+ ERROR_INVALID_CLASS syscall.Errno = 0x20000000 | 0xC0000000 | 0x206
+ ERROR_DEVINST_ALREADY_EXISTS syscall.Errno = 0x20000000 | 0xC0000000 | 0x207
+ ERROR_DEVINFO_NOT_REGISTERED syscall.Errno = 0x20000000 | 0xC0000000 | 0x208
+ ERROR_INVALID_REG_PROPERTY syscall.Errno = 0x20000000 | 0xC0000000 | 0x209
+ ERROR_NO_INF syscall.Errno = 0x20000000 | 0xC0000000 | 0x20A
+ ERROR_NO_SUCH_DEVINST syscall.Errno = 0x20000000 | 0xC0000000 | 0x20B
+ ERROR_CANT_LOAD_CLASS_ICON syscall.Errno = 0x20000000 | 0xC0000000 | 0x20C
+ ERROR_INVALID_CLASS_INSTALLER syscall.Errno = 0x20000000 | 0xC0000000 | 0x20D
+ ERROR_DI_DO_DEFAULT syscall.Errno = 0x20000000 | 0xC0000000 | 0x20E
+ ERROR_DI_NOFILECOPY syscall.Errno = 0x20000000 | 0xC0000000 | 0x20F
+ ERROR_INVALID_HWPROFILE syscall.Errno = 0x20000000 | 0xC0000000 | 0x210
+ ERROR_NO_DEVICE_SELECTED syscall.Errno = 0x20000000 | 0xC0000000 | 0x211
+ ERROR_DEVINFO_LIST_LOCKED syscall.Errno = 0x20000000 | 0xC0000000 | 0x212
+ ERROR_DEVINFO_DATA_LOCKED syscall.Errno = 0x20000000 | 0xC0000000 | 0x213
+ ERROR_DI_BAD_PATH syscall.Errno = 0x20000000 | 0xC0000000 | 0x214
+ ERROR_NO_CLASSINSTALL_PARAMS syscall.Errno = 0x20000000 | 0xC0000000 | 0x215
+ ERROR_FILEQUEUE_LOCKED syscall.Errno = 0x20000000 | 0xC0000000 | 0x216
+ ERROR_BAD_SERVICE_INSTALLSECT syscall.Errno = 0x20000000 | 0xC0000000 | 0x217
+ ERROR_NO_CLASS_DRIVER_LIST syscall.Errno = 0x20000000 | 0xC0000000 | 0x218
+ ERROR_NO_ASSOCIATED_SERVICE syscall.Errno = 0x20000000 | 0xC0000000 | 0x219
+ ERROR_NO_DEFAULT_DEVICE_INTERFACE syscall.Errno = 0x20000000 | 0xC0000000 | 0x21A
+ ERROR_DEVICE_INTERFACE_ACTIVE syscall.Errno = 0x20000000 | 0xC0000000 | 0x21B
+ ERROR_DEVICE_INTERFACE_REMOVED syscall.Errno = 0x20000000 | 0xC0000000 | 0x21C
+ ERROR_BAD_INTERFACE_INSTALLSECT syscall.Errno = 0x20000000 | 0xC0000000 | 0x21D
+ ERROR_NO_SUCH_INTERFACE_CLASS syscall.Errno = 0x20000000 | 0xC0000000 | 0x21E
+ ERROR_INVALID_REFERENCE_STRING syscall.Errno = 0x20000000 | 0xC0000000 | 0x21F
+ ERROR_INVALID_MACHINENAME syscall.Errno = 0x20000000 | 0xC0000000 | 0x220
+ ERROR_REMOTE_COMM_FAILURE syscall.Errno = 0x20000000 | 0xC0000000 | 0x221
+ ERROR_MACHINE_UNAVAILABLE syscall.Errno = 0x20000000 | 0xC0000000 | 0x222
+ ERROR_NO_CONFIGMGR_SERVICES syscall.Errno = 0x20000000 | 0xC0000000 | 0x223
+ ERROR_INVALID_PROPPAGE_PROVIDER syscall.Errno = 0x20000000 | 0xC0000000 | 0x224
+ ERROR_NO_SUCH_DEVICE_INTERFACE syscall.Errno = 0x20000000 | 0xC0000000 | 0x225
+ ERROR_DI_POSTPROCESSING_REQUIRED syscall.Errno = 0x20000000 | 0xC0000000 | 0x226
+ ERROR_INVALID_COINSTALLER syscall.Errno = 0x20000000 | 0xC0000000 | 0x227
+ ERROR_NO_COMPAT_DRIVERS syscall.Errno = 0x20000000 | 0xC0000000 | 0x228
+ ERROR_NO_DEVICE_ICON syscall.Errno = 0x20000000 | 0xC0000000 | 0x229
+ ERROR_INVALID_INF_LOGCONFIG syscall.Errno = 0x20000000 | 0xC0000000 | 0x22A
+ ERROR_DI_DONT_INSTALL syscall.Errno = 0x20000000 | 0xC0000000 | 0x22B
+ ERROR_INVALID_FILTER_DRIVER syscall.Errno = 0x20000000 | 0xC0000000 | 0x22C
+ ERROR_NON_WINDOWS_NT_DRIVER syscall.Errno = 0x20000000 | 0xC0000000 | 0x22D
+ ERROR_NON_WINDOWS_DRIVER syscall.Errno = 0x20000000 | 0xC0000000 | 0x22E
+ ERROR_NO_CATALOG_FOR_OEM_INF syscall.Errno = 0x20000000 | 0xC0000000 | 0x22F
+ ERROR_DEVINSTALL_QUEUE_NONNATIVE syscall.Errno = 0x20000000 | 0xC0000000 | 0x230
+ ERROR_NOT_DISABLEABLE syscall.Errno = 0x20000000 | 0xC0000000 | 0x231
+ ERROR_CANT_REMOVE_DEVINST syscall.Errno = 0x20000000 | 0xC0000000 | 0x232
+ ERROR_INVALID_TARGET syscall.Errno = 0x20000000 | 0xC0000000 | 0x233
+ ERROR_DRIVER_NONNATIVE syscall.Errno = 0x20000000 | 0xC0000000 | 0x234
+ ERROR_IN_WOW64 syscall.Errno = 0x20000000 | 0xC0000000 | 0x235
+ ERROR_SET_SYSTEM_RESTORE_POINT syscall.Errno = 0x20000000 | 0xC0000000 | 0x236
+ ERROR_SCE_DISABLED syscall.Errno = 0x20000000 | 0xC0000000 | 0x238
+ ERROR_UNKNOWN_EXCEPTION syscall.Errno = 0x20000000 | 0xC0000000 | 0x239
+ ERROR_PNP_REGISTRY_ERROR syscall.Errno = 0x20000000 | 0xC0000000 | 0x23A
+ ERROR_REMOTE_REQUEST_UNSUPPORTED syscall.Errno = 0x20000000 | 0xC0000000 | 0x23B
+ ERROR_NOT_AN_INSTALLED_OEM_INF syscall.Errno = 0x20000000 | 0xC0000000 | 0x23C
+ ERROR_INF_IN_USE_BY_DEVICES syscall.Errno = 0x20000000 | 0xC0000000 | 0x23D
+ ERROR_DI_FUNCTION_OBSOLETE syscall.Errno = 0x20000000 | 0xC0000000 | 0x23E
+ ERROR_NO_AUTHENTICODE_CATALOG syscall.Errno = 0x20000000 | 0xC0000000 | 0x23F
+ ERROR_AUTHENTICODE_DISALLOWED syscall.Errno = 0x20000000 | 0xC0000000 | 0x240
+ ERROR_AUTHENTICODE_TRUSTED_PUBLISHER syscall.Errno = 0x20000000 | 0xC0000000 | 0x241
+ ERROR_AUTHENTICODE_TRUST_NOT_ESTABLISHED syscall.Errno = 0x20000000 | 0xC0000000 | 0x242
+ ERROR_AUTHENTICODE_PUBLISHER_NOT_TRUSTED syscall.Errno = 0x20000000 | 0xC0000000 | 0x243
+ ERROR_SIGNATURE_OSATTRIBUTE_MISMATCH syscall.Errno = 0x20000000 | 0xC0000000 | 0x244
+ ERROR_ONLY_VALIDATE_VIA_AUTHENTICODE syscall.Errno = 0x20000000 | 0xC0000000 | 0x245
+ ERROR_DEVICE_INSTALLER_NOT_READY syscall.Errno = 0x20000000 | 0xC0000000 | 0x246
+ ERROR_DRIVER_STORE_ADD_FAILED syscall.Errno = 0x20000000 | 0xC0000000 | 0x247
+ ERROR_DEVICE_INSTALL_BLOCKED syscall.Errno = 0x20000000 | 0xC0000000 | 0x248
+ ERROR_DRIVER_INSTALL_BLOCKED syscall.Errno = 0x20000000 | 0xC0000000 | 0x249
+ ERROR_WRONG_INF_TYPE syscall.Errno = 0x20000000 | 0xC0000000 | 0x24A
+ ERROR_FILE_HASH_NOT_IN_CATALOG syscall.Errno = 0x20000000 | 0xC0000000 | 0x24B
+ ERROR_DRIVER_STORE_DELETE_FAILED syscall.Errno = 0x20000000 | 0xC0000000 | 0x24C
+ ERROR_UNRECOVERABLE_STACK_OVERFLOW syscall.Errno = 0x20000000 | 0xC0000000 | 0x300
+ EXCEPTION_SPAPI_UNRECOVERABLE_STACK_OVERFLOW syscall.Errno = ERROR_UNRECOVERABLE_STACK_OVERFLOW
+ ERROR_NO_DEFAULT_INTERFACE_DEVICE syscall.Errno = ERROR_NO_DEFAULT_DEVICE_INTERFACE
+ ERROR_INTERFACE_DEVICE_ACTIVE syscall.Errno = ERROR_DEVICE_INTERFACE_ACTIVE
+ ERROR_INTERFACE_DEVICE_REMOVED syscall.Errno = ERROR_DEVICE_INTERFACE_REMOVED
+ ERROR_NO_SUCH_INTERFACE_DEVICE syscall.Errno = ERROR_NO_SUCH_DEVICE_INTERFACE
+)
diff --git a/src/cmd/vendor/golang.org/x/sys/windows/syscall_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/syscall_windows.go
index 008ffc11a0..c71bad127d 100644
--- a/src/cmd/vendor/golang.org/x/sys/windows/syscall_windows.go
+++ b/src/cmd/vendor/golang.org/x/sys/windows/syscall_windows.go
@@ -170,10 +170,13 @@ func NewCallbackCDecl(fn interface{}) uintptr {
//sys GetProcAddress(module Handle, procname string) (proc uintptr, err error)
//sys GetModuleFileName(module Handle, filename *uint16, size uint32) (n uint32, err error) = kernel32.GetModuleFileNameW
//sys GetModuleHandleEx(flags uint32, moduleName *uint16, module *Handle) (err error) = kernel32.GetModuleHandleExW
+//sys SetDefaultDllDirectories(directoryFlags uint32) (err error)
+//sys SetDllDirectory(path string) (err error) = kernel32.SetDllDirectoryW
//sys GetVersion() (ver uint32, err error)
//sys FormatMessage(flags uint32, msgsrc uintptr, msgid uint32, langid uint32, buf []uint16, args *byte) (n uint32, err error) = FormatMessageW
//sys ExitProcess(exitcode uint32)
//sys IsWow64Process(handle Handle, isWow64 *bool) (err error) = IsWow64Process
+//sys IsWow64Process2(handle Handle, processMachine *uint16, nativeMachine *uint16) (err error) = IsWow64Process2?
//sys CreateFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes, createmode uint32, attrs uint32, templatefile Handle) (handle Handle, err error) [failretval==InvalidHandle] = CreateFileW
//sys ReadFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error)
//sys WriteFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error)
@@ -187,6 +190,7 @@ func NewCallbackCDecl(fn interface{}) uintptr {
//sys FindClose(handle Handle) (err error)
//sys GetFileInformationByHandle(handle Handle, data *ByHandleFileInformation) (err error)
//sys GetFileInformationByHandleEx(handle Handle, class uint32, outBuffer *byte, outBufferLen uint32) (err error)
+//sys SetFileInformationByHandle(handle Handle, class uint32, inBuffer *byte, inBufferLen uint32) (err error)
//sys GetCurrentDirectory(buflen uint32, buf *uint16) (n uint32, err error) = GetCurrentDirectoryW
//sys SetCurrentDirectory(path *uint16) (err error) = SetCurrentDirectoryW
//sys CreateDirectory(path *uint16, sa *SecurityAttributes) (err error) = CreateDirectoryW
@@ -243,6 +247,7 @@ func NewCallbackCDecl(fn interface{}) uintptr {
//sys GetFullPathName(path *uint16, buflen uint32, buf *uint16, fname **uint16) (n uint32, err error) = kernel32.GetFullPathNameW
//sys GetLongPathName(path *uint16, buf *uint16, buflen uint32) (n uint32, err error) = kernel32.GetLongPathNameW
//sys GetShortPathName(longpath *uint16, shortpath *uint16, buflen uint32) (n uint32, err error) = kernel32.GetShortPathNameW
+//sys GetFinalPathNameByHandle(file Handle, filePath *uint16, filePathSize uint32, flags uint32) (n uint32, err error) = kernel32.GetFinalPathNameByHandleW
//sys CreateFileMapping(fhandle Handle, sa *SecurityAttributes, prot uint32, maxSizeHigh uint32, maxSizeLow uint32, name *uint16) (handle Handle, err error) = kernel32.CreateFileMappingW
//sys MapViewOfFile(handle Handle, access uint32, offsetHigh uint32, offsetLow uint32, length uintptr) (addr uintptr, err error)
//sys UnmapViewOfFile(addr uintptr) (err error)
@@ -255,7 +260,7 @@ func NewCallbackCDecl(fn interface{}) uintptr {
//sys TransmitFile(s Handle, handle Handle, bytesToWrite uint32, bytsPerSend uint32, overlapped *Overlapped, transmitFileBuf *TransmitFileBuffers, flags uint32) (err error) = mswsock.TransmitFile
//sys ReadDirectoryChanges(handle Handle, buf *byte, buflen uint32, watchSubTree bool, mask uint32, retlen *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) = kernel32.ReadDirectoryChangesW
//sys CertOpenSystemStore(hprov Handle, name *uint16) (store Handle, err error) = crypt32.CertOpenSystemStoreW
-//sys CertOpenStore(storeProvider uintptr, msgAndCertEncodingType uint32, cryptProv uintptr, flags uint32, para uintptr) (handle Handle, err error) [failretval==InvalidHandle] = crypt32.CertOpenStore
+//sys CertOpenStore(storeProvider uintptr, msgAndCertEncodingType uint32, cryptProv uintptr, flags uint32, para uintptr) (handle Handle, err error) = crypt32.CertOpenStore
//sys CertEnumCertificatesInStore(store Handle, prevContext *CertContext) (context *CertContext, err error) [failretval==nil] = crypt32.CertEnumCertificatesInStore
//sys CertAddCertificateContextToStore(store Handle, certContext *CertContext, addDisposition uint32, storeContext **CertContext) (err error) = crypt32.CertAddCertificateContextToStore
//sys CertCloseStore(store Handle, flags uint32) (err error) = crypt32.CertCloseStore
@@ -351,7 +356,6 @@ func NewCallbackCDecl(fn interface{}) uintptr {
//sys getThreadPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) = kernel32.GetThreadPreferredUILanguages
//sys getUserPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) = kernel32.GetUserPreferredUILanguages
//sys getSystemPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) = kernel32.GetSystemPreferredUILanguages
-//sys GetFinalPathNameByHandleW(file syscall.Handle, filePath *uint16, filePathSize uint32, flags uint32) (n uint32, err error) = kernel32.GetFinalPathNameByHandleW
// Process Status API (PSAPI)
//sys EnumProcesses(processIds []uint32, bytesReturned *uint32) (err error) = psapi.EnumProcesses
diff --git a/src/cmd/vendor/golang.org/x/sys/windows/types_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/types_windows.go
index da1652e74b..265d797cac 100644
--- a/src/cmd/vendor/golang.org/x/sys/windows/types_windows.go
+++ b/src/cmd/vendor/golang.org/x/sys/windows/types_windows.go
@@ -1772,3 +1772,51 @@ const (
MUI_LANGUAGE_INSTALLED = 0x20
MUI_LANGUAGE_LICENSED = 0x40
)
+
+// FILE_INFO_BY_HANDLE_CLASS constants for SetFileInformationByHandle/GetFileInformationByHandleEx
+const (
+ FileBasicInfo = 0
+ FileStandardInfo = 1
+ FileNameInfo = 2
+ FileRenameInfo = 3
+ FileDispositionInfo = 4
+ FileAllocationInfo = 5
+ FileEndOfFileInfo = 6
+ FileStreamInfo = 7
+ FileCompressionInfo = 8
+ FileAttributeTagInfo = 9
+ FileIdBothDirectoryInfo = 10
+ FileIdBothDirectoryRestartInfo = 11
+ FileIoPriorityHintInfo = 12
+ FileRemoteProtocolInfo = 13
+ FileFullDirectoryInfo = 14
+ FileFullDirectoryRestartInfo = 15
+ FileStorageInfo = 16
+ FileAlignmentInfo = 17
+ FileIdInfo = 18
+ FileIdExtdDirectoryInfo = 19
+ FileIdExtdDirectoryRestartInfo = 20
+ FileDispositionInfoEx = 21
+ FileRenameInfoEx = 22
+ FileCaseSensitiveInfo = 23
+ FileNormalizedNameInfo = 24
+)
+
+// LoadLibrary flags for determining from where to search for a DLL
+const (
+ DONT_RESOLVE_DLL_REFERENCES = 0x1
+ LOAD_LIBRARY_AS_DATAFILE = 0x2
+ LOAD_WITH_ALTERED_SEARCH_PATH = 0x8
+ LOAD_IGNORE_CODE_AUTHZ_LEVEL = 0x10
+ LOAD_LIBRARY_AS_IMAGE_RESOURCE = 0x20
+ LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE = 0x40
+ LOAD_LIBRARY_REQUIRE_SIGNED_TARGET = 0x80
+ LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR = 0x100
+ LOAD_LIBRARY_SEARCH_APPLICATION_DIR = 0x200
+ LOAD_LIBRARY_SEARCH_USER_DIRS = 0x400
+ LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x800
+ LOAD_LIBRARY_SEARCH_DEFAULT_DIRS = 0x1000
+ LOAD_LIBRARY_SAFE_CURRENT_DIRS = 0x00002000
+ LOAD_LIBRARY_SEARCH_SYSTEM32_NO_FORWARDER = 0x00004000
+ LOAD_LIBRARY_OS_INTEGRITY_CONTINUITY = 0x00008000
+)
diff --git a/src/cmd/vendor/golang.org/x/sys/windows/zsyscall_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/zsyscall_windows.go
index d400c3512d..a933c0ee37 100644
--- a/src/cmd/vendor/golang.org/x/sys/windows/zsyscall_windows.go
+++ b/src/cmd/vendor/golang.org/x/sys/windows/zsyscall_windows.go
@@ -46,6 +46,7 @@ var (
modntdll = NewLazySystemDLL("ntdll.dll")
modole32 = NewLazySystemDLL("ole32.dll")
modpsapi = NewLazySystemDLL("psapi.dll")
+ modsechost = NewLazySystemDLL("sechost.dll")
modsecur32 = NewLazySystemDLL("secur32.dll")
modshell32 = NewLazySystemDLL("shell32.dll")
moduser32 = NewLazySystemDLL("user32.dll")
@@ -95,6 +96,7 @@ var (
procImpersonateSelf = modadvapi32.NewProc("ImpersonateSelf")
procInitializeSecurityDescriptor = modadvapi32.NewProc("InitializeSecurityDescriptor")
procInitiateSystemShutdownExW = modadvapi32.NewProc("InitiateSystemShutdownExW")
+ procIsTokenRestricted = modadvapi32.NewProc("IsTokenRestricted")
procIsValidSecurityDescriptor = modadvapi32.NewProc("IsValidSecurityDescriptor")
procIsValidSid = modadvapi32.NewProc("IsValidSid")
procIsWellKnownSid = modadvapi32.NewProc("IsWellKnownSid")
@@ -122,6 +124,7 @@ var (
procReportEventW = modadvapi32.NewProc("ReportEventW")
procRevertToSelf = modadvapi32.NewProc("RevertToSelf")
procSetEntriesInAclW = modadvapi32.NewProc("SetEntriesInAclW")
+ procSetKernelObjectSecurity = modadvapi32.NewProc("SetKernelObjectSecurity")
procSetNamedSecurityInfoW = modadvapi32.NewProc("SetNamedSecurityInfoW")
procSetSecurityDescriptorControl = modadvapi32.NewProc("SetSecurityDescriptorControl")
procSetSecurityDescriptorDacl = modadvapi32.NewProc("SetSecurityDescriptorDacl")
@@ -248,6 +251,7 @@ var (
procGetVolumePathNamesForVolumeNameW = modkernel32.NewProc("GetVolumePathNamesForVolumeNameW")
procGetWindowsDirectoryW = modkernel32.NewProc("GetWindowsDirectoryW")
procIsWow64Process = modkernel32.NewProc("IsWow64Process")
+ procIsWow64Process2 = modkernel32.NewProc("IsWow64Process2")
procLoadLibraryExW = modkernel32.NewProc("LoadLibraryExW")
procLoadLibraryW = modkernel32.NewProc("LoadLibraryW")
procLocalFree = modkernel32.NewProc("LocalFree")
@@ -277,12 +281,15 @@ var (
procSetConsoleCursorPosition = modkernel32.NewProc("SetConsoleCursorPosition")
procSetConsoleMode = modkernel32.NewProc("SetConsoleMode")
procSetCurrentDirectoryW = modkernel32.NewProc("SetCurrentDirectoryW")
+ procSetDefaultDllDirectories = modkernel32.NewProc("SetDefaultDllDirectories")
+ procSetDllDirectoryW = modkernel32.NewProc("SetDllDirectoryW")
procSetEndOfFile = modkernel32.NewProc("SetEndOfFile")
procSetEnvironmentVariableW = modkernel32.NewProc("SetEnvironmentVariableW")
procSetErrorMode = modkernel32.NewProc("SetErrorMode")
procSetEvent = modkernel32.NewProc("SetEvent")
procSetFileAttributesW = modkernel32.NewProc("SetFileAttributesW")
procSetFileCompletionNotificationModes = modkernel32.NewProc("SetFileCompletionNotificationModes")
+ procSetFileInformationByHandle = modkernel32.NewProc("SetFileInformationByHandle")
procSetFilePointer = modkernel32.NewProc("SetFilePointer")
procSetFileTime = modkernel32.NewProc("SetFileTime")
procSetHandleInformation = modkernel32.NewProc("SetHandleInformation")
@@ -323,6 +330,8 @@ var (
procCoTaskMemFree = modole32.NewProc("CoTaskMemFree")
procStringFromGUID2 = modole32.NewProc("StringFromGUID2")
procEnumProcesses = modpsapi.NewProc("EnumProcesses")
+ procSubscribeServiceChangeNotifications = modsechost.NewProc("SubscribeServiceChangeNotifications")
+ procUnsubscribeServiceChangeNotifications = modsechost.NewProc("UnsubscribeServiceChangeNotifications")
procGetUserNameExW = modsecur32.NewProc("GetUserNameExW")
procTranslateNameW = modsecur32.NewProc("TranslateNameW")
procCommandLineToArgvW = modshell32.NewProc("CommandLineToArgvW")
@@ -753,6 +762,15 @@ func InitiateSystemShutdownEx(machineName *uint16, message *uint16, timeout uint
return
}
+func isTokenRestricted(tokenHandle Token) (ret bool, err error) {
+ r0, _, e1 := syscall.Syscall(procIsTokenRestricted.Addr(), 1, uintptr(tokenHandle), 0, 0)
+ ret = r0 != 0
+ if !ret {
+ err = errnoErr(e1)
+ }
+ return
+}
+
func isValidSecurityDescriptor(sd *SECURITY_DESCRIPTOR) (isValid bool) {
r0, _, _ := syscall.Syscall(procIsValidSecurityDescriptor.Addr(), 1, uintptr(unsafe.Pointer(sd)), 0, 0)
isValid = r0 != 0
@@ -970,6 +988,14 @@ func setEntriesInAcl(countExplicitEntries uint32, explicitEntries *EXPLICIT_ACCE
return
}
+func SetKernelObjectSecurity(handle Handle, securityInformation SECURITY_INFORMATION, securityDescriptor *SECURITY_DESCRIPTOR) (err error) {
+ r1, _, e1 := syscall.Syscall(procSetKernelObjectSecurity.Addr(), 3, uintptr(handle), uintptr(securityInformation), uintptr(unsafe.Pointer(securityDescriptor)))
+ if r1 == 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
func SetNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) (ret error) {
var _p0 *uint16
_p0, ret = syscall.UTF16PtrFromString(objectName)
@@ -1056,8 +1082,11 @@ func setSecurityDescriptorSacl(sd *SECURITY_DESCRIPTOR, saclPresent bool, sacl *
return
}
-func SetSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) {
- syscall.Syscall9(procSetSecurityInfo.Addr(), 7, uintptr(handle), uintptr(objectType), uintptr(securityInformation), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(sacl)), 0, 0)
+func SetSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) (ret error) {
+ r0, _, _ := syscall.Syscall9(procSetSecurityInfo.Addr(), 7, uintptr(handle), uintptr(objectType), uintptr(securityInformation), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(sacl)), 0, 0)
+ if r0 != 0 {
+ ret = syscall.Errno(r0)
+ }
return
}
@@ -1167,7 +1196,7 @@ func CertGetCertificateChain(engine Handle, leaf *CertContext, time *Filetime, a
func CertOpenStore(storeProvider uintptr, msgAndCertEncodingType uint32, cryptProv uintptr, flags uint32, para uintptr) (handle Handle, err error) {
r0, _, e1 := syscall.Syscall6(procCertOpenStore.Addr(), 5, uintptr(storeProvider), uintptr(msgAndCertEncodingType), uintptr(cryptProv), uintptr(flags), uintptr(para), 0)
handle = Handle(r0)
- if handle == InvalidHandle {
+ if handle == 0 {
err = errnoErr(e1)
}
return
@@ -1727,7 +1756,7 @@ func GetFileType(filehandle Handle) (n uint32, err error) {
return
}
-func GetFinalPathNameByHandleW(file syscall.Handle, filePath *uint16, filePathSize uint32, flags uint32) (n uint32, err error) {
+func GetFinalPathNameByHandle(file Handle, filePath *uint16, filePathSize uint32, flags uint32) (n uint32, err error) {
r0, _, e1 := syscall.Syscall6(procGetFinalPathNameByHandleW.Addr(), 4, uintptr(file), uintptr(unsafe.Pointer(filePath)), uintptr(filePathSize), uintptr(flags), 0, 0)
n = uint32(r0)
if n == 0 {
@@ -2055,6 +2084,18 @@ func IsWow64Process(handle Handle, isWow64 *bool) (err error) {
return
}
+func IsWow64Process2(handle Handle, processMachine *uint16, nativeMachine *uint16) (err error) {
+ err = procIsWow64Process2.Find()
+ if err != nil {
+ return
+ }
+ r1, _, e1 := syscall.Syscall(procIsWow64Process2.Addr(), 3, uintptr(handle), uintptr(unsafe.Pointer(processMachine)), uintptr(unsafe.Pointer(nativeMachine)))
+ if r1 == 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
func LoadLibraryEx(libname string, zero Handle, flags uintptr) (handle Handle, err error) {
var _p0 *uint16
_p0, err = syscall.UTF16PtrFromString(libname)
@@ -2340,6 +2381,31 @@ func SetCurrentDirectory(path *uint16) (err error) {
return
}
+func SetDefaultDllDirectories(directoryFlags uint32) (err error) {
+ r1, _, e1 := syscall.Syscall(procSetDefaultDllDirectories.Addr(), 1, uintptr(directoryFlags), 0, 0)
+ if r1 == 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+func SetDllDirectory(path string) (err error) {
+ var _p0 *uint16
+ _p0, err = syscall.UTF16PtrFromString(path)
+ if err != nil {
+ return
+ }
+ return _SetDllDirectory(_p0)
+}
+
+func _SetDllDirectory(path *uint16) (err error) {
+ r1, _, e1 := syscall.Syscall(procSetDllDirectoryW.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0)
+ if r1 == 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
func SetEndOfFile(handle Handle) (err error) {
r1, _, e1 := syscall.Syscall(procSetEndOfFile.Addr(), 1, uintptr(handle), 0, 0)
if r1 == 0 {
@@ -2386,6 +2452,14 @@ func SetFileCompletionNotificationModes(handle Handle, flags uint8) (err error)
return
}
+func SetFileInformationByHandle(handle Handle, class uint32, inBuffer *byte, inBufferLen uint32) (err error) {
+ r1, _, e1 := syscall.Syscall6(procSetFileInformationByHandle.Addr(), 4, uintptr(handle), uintptr(class), uintptr(unsafe.Pointer(inBuffer)), uintptr(inBufferLen), 0, 0)
+ if r1 == 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
func SetFilePointer(handle Handle, lowoffset int32, highoffsetptr *int32, whence uint32) (newlowoffset uint32, err error) {
r0, _, e1 := syscall.Syscall6(procSetFilePointer.Addr(), 4, uintptr(handle), uintptr(lowoffset), uintptr(unsafe.Pointer(highoffsetptr)), uintptr(whence), 0, 0)
newlowoffset = uint32(r0)
@@ -2718,6 +2792,27 @@ func EnumProcesses(processIds []uint32, bytesReturned *uint32) (err error) {
return
}
+func SubscribeServiceChangeNotifications(service Handle, eventType uint32, callback uintptr, callbackCtx uintptr, subscription *uintptr) (ret error) {
+ ret = procSubscribeServiceChangeNotifications.Find()
+ if ret != nil {
+ return
+ }
+ r0, _, _ := syscall.Syscall6(procSubscribeServiceChangeNotifications.Addr(), 5, uintptr(service), uintptr(eventType), uintptr(callback), uintptr(callbackCtx), uintptr(unsafe.Pointer(subscription)), 0)
+ if r0 != 0 {
+ ret = syscall.Errno(r0)
+ }
+ return
+}
+
+func UnsubscribeServiceChangeNotifications(subscription uintptr) (err error) {
+ err = procUnsubscribeServiceChangeNotifications.Find()
+ if err != nil {
+ return
+ }
+ syscall.Syscall(procUnsubscribeServiceChangeNotifications.Addr(), 1, uintptr(subscription), 0, 0)
+ return
+}
+
func GetUserNameEx(nameFormat uint32, nameBuffre *uint16, nSize *uint32) (err error) {
r1, _, e1 := syscall.Syscall(procGetUserNameExW.Addr(), 3, uintptr(nameFormat), uintptr(unsafe.Pointer(nameBuffre)), uintptr(unsafe.Pointer(nSize)))
if r1&0xff == 0 {
diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/framepointer/framepointer.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/framepointer/framepointer.go
new file mode 100644
index 0000000000..741492e477
--- /dev/null
+++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/framepointer/framepointer.go
@@ -0,0 +1,91 @@
+// Copyright 2020 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 framepointer defines an Analyzer that reports assembly code
+// that clobbers the frame pointer before saving it.
+package framepointer
+
+import (
+ "go/build"
+ "regexp"
+ "strings"
+
+ "golang.org/x/tools/go/analysis"
+ "golang.org/x/tools/go/analysis/passes/internal/analysisutil"
+)
+
+const Doc = "report assembly that clobbers the frame pointer before saving it"
+
+var Analyzer = &analysis.Analyzer{
+ Name: "framepointer",
+ Doc: Doc,
+ Run: run,
+}
+
+var (
+ re = regexp.MustCompile
+ asmWriteBP = re(`,\s*BP$`) // TODO: can have false positive, e.g. for TESTQ BP,BP. Seems unlikely.
+ asmMentionBP = re(`\bBP\b`)
+ asmControlFlow = re(`^(J|RET)`)
+)
+
+func run(pass *analysis.Pass) (interface{}, error) {
+ if build.Default.GOARCH != "amd64" { // TODO: arm64 also?
+ return nil, nil
+ }
+ if build.Default.GOOS != "linux" && build.Default.GOOS != "darwin" {
+ return nil, nil
+ }
+
+ // Find assembly files to work on.
+ var sfiles []string
+ for _, fname := range pass.OtherFiles {
+ if strings.HasSuffix(fname, ".s") && pass.Pkg.Path() != "runtime" {
+ sfiles = append(sfiles, fname)
+ }
+ }
+
+ for _, fname := range sfiles {
+ content, tf, err := analysisutil.ReadFile(pass.Fset, fname)
+ if err != nil {
+ return nil, err
+ }
+
+ lines := strings.SplitAfter(string(content), "\n")
+ active := false
+ for lineno, line := range lines {
+ lineno++
+
+ // Ignore comments and commented-out code.
+ if i := strings.Index(line, "//"); i >= 0 {
+ line = line[:i]
+ }
+ line = strings.TrimSpace(line)
+
+ // We start checking code at a TEXT line for a frameless function.
+ if strings.HasPrefix(line, "TEXT") && strings.Contains(line, "(SB)") && strings.Contains(line, "$0") {
+ active = true
+ continue
+ }
+ if !active {
+ continue
+ }
+
+ if asmWriteBP.MatchString(line) { // clobber of BP, function is not OK
+ pass.Reportf(analysisutil.LineStart(tf, lineno), "frame pointer is clobbered before saving")
+ active = false
+ continue
+ }
+ if asmMentionBP.MatchString(line) { // any other use of BP might be a read, so function is OK
+ active = false
+ continue
+ }
+ if asmControlFlow.MatchString(line) { // give up after any branch instruction
+ active = false
+ continue
+ }
+ }
+ }
+ return nil, nil
+}
diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/ifaceassert/ifaceassert.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/ifaceassert/ifaceassert.go
index c5a71a7c57..fd2285332c 100644
--- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/ifaceassert/ifaceassert.go
+++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/ifaceassert/ifaceassert.go
@@ -41,6 +41,10 @@ var Analyzer = &analysis.Analyzer{
// assertableTo checks whether interface v can be asserted into t. It returns
// nil on success, or the first conflicting method on failure.
func assertableTo(v, t types.Type) *types.Func {
+ if t == nil || v == nil {
+ // not assertable to, but there is no missing method
+ return nil
+ }
// ensure that v and t are interfaces
V, _ := v.Underlying().(*types.Interface)
T, _ := t.Underlying().(*types.Interface)
diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt
index f20b6b2be1..b549258cfa 100644
--- a/src/cmd/vendor/modules.txt
+++ b/src/cmd/vendor/modules.txt
@@ -1,4 +1,4 @@
-# github.com/google/pprof v0.0.0-20201007051231-1066cbb265c7
+# github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2
## explicit
github.com/google/pprof/driver
github.com/google/pprof/internal/binutils
@@ -15,8 +15,7 @@ github.com/google/pprof/profile
github.com/google/pprof/third_party/d3
github.com/google/pprof/third_party/d3flamegraph
github.com/google/pprof/third_party/svgpan
-# github.com/ianlancetaylor/demangle v0.0.0-20200414190113-039b1ae3a340
-## explicit
+# github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639
github.com/ianlancetaylor/demangle
# golang.org/x/arch v0.0.0-20201008161808-52c3e6f60cff
## explicit
@@ -29,7 +28,7 @@ golang.org/x/arch/x86/x86asm
golang.org/x/crypto/ed25519
golang.org/x/crypto/ed25519/internal/edwards25519
golang.org/x/crypto/ssh/terminal
-# golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449
+# golang.org/x/mod v0.4.0
## explicit
golang.org/x/mod/internal/lazyregexp
golang.org/x/mod/modfile
@@ -40,12 +39,12 @@ golang.org/x/mod/sumdb/dirhash
golang.org/x/mod/sumdb/note
golang.org/x/mod/sumdb/tlog
golang.org/x/mod/zip
-# golang.org/x/sys v0.0.0-20201110211018-35f3e6cf4a65
+# golang.org/x/sys v0.0.0-20201204225414-ed752295db88
## explicit
golang.org/x/sys/internal/unsafeheader
golang.org/x/sys/unix
golang.org/x/sys/windows
-# golang.org/x/tools v0.0.0-20201110201400-7099162a900a
+# golang.org/x/tools v0.0.0-20201208211828-de58e7c01d49
## explicit
golang.org/x/tools/go/analysis
golang.org/x/tools/go/analysis/internal/analysisflags
@@ -60,6 +59,7 @@ golang.org/x/tools/go/analysis/passes/composite
golang.org/x/tools/go/analysis/passes/copylock
golang.org/x/tools/go/analysis/passes/ctrlflow
golang.org/x/tools/go/analysis/passes/errorsas
+golang.org/x/tools/go/analysis/passes/framepointer
golang.org/x/tools/go/analysis/passes/httpresponse
golang.org/x/tools/go/analysis/passes/ifaceassert
golang.org/x/tools/go/analysis/passes/inspect
diff --git a/src/cmd/vet/main.go b/src/cmd/vet/main.go
index bad3807039..d50c45d691 100644
--- a/src/cmd/vet/main.go
+++ b/src/cmd/vet/main.go
@@ -14,6 +14,7 @@ import (
"golang.org/x/tools/go/analysis/passes/composite"
"golang.org/x/tools/go/analysis/passes/copylock"
"golang.org/x/tools/go/analysis/passes/errorsas"
+ "golang.org/x/tools/go/analysis/passes/framepointer"
"golang.org/x/tools/go/analysis/passes/httpresponse"
"golang.org/x/tools/go/analysis/passes/ifaceassert"
"golang.org/x/tools/go/analysis/passes/loopclosure"
@@ -45,6 +46,7 @@ func main() {
composite.Analyzer,
copylock.Analyzer,
errorsas.Analyzer,
+ framepointer.Analyzer,
httpresponse.Analyzer,
ifaceassert.Analyzer,
loopclosure.Analyzer,
diff --git a/src/cmd/vet/vet_test.go b/src/cmd/vet/vet_test.go
index 5d8139d977..d15d1ce377 100644
--- a/src/cmd/vet/vet_test.go
+++ b/src/cmd/vet/vet_test.go
@@ -9,7 +9,6 @@ import (
"errors"
"fmt"
"internal/testenv"
- "io/ioutil"
"log"
"os"
"os/exec"
@@ -32,7 +31,7 @@ func TestMain(m *testing.M) {
}
func testMain(m *testing.M) int {
- dir, err := ioutil.TempDir("", "vet_test")
+ dir, err := os.MkdirTemp("", "vet_test")
if err != nil {
fmt.Fprintln(os.Stderr, err)
return 1
@@ -345,7 +344,7 @@ var (
func wantedErrors(file, short string) (errs []wantedError) {
cache := make(map[string]*regexp.Regexp)
- src, err := ioutil.ReadFile(file)
+ src, err := os.ReadFile(file)
if err != nil {
log.Fatal(err)
}
diff --git a/src/compress/bzip2/bzip2_test.go b/src/compress/bzip2/bzip2_test.go
index 98477791b3..e6065cb43f 100644
--- a/src/compress/bzip2/bzip2_test.go
+++ b/src/compress/bzip2/bzip2_test.go
@@ -9,7 +9,7 @@ import (
"encoding/hex"
"fmt"
"io"
- "io/ioutil"
+ "os"
"testing"
)
@@ -22,7 +22,7 @@ func mustDecodeHex(s string) []byte {
}
func mustLoadFile(f string) []byte {
- b, err := ioutil.ReadFile(f)
+ b, err := os.ReadFile(f)
if err != nil {
panic(err)
}
diff --git a/src/compress/flate/deflate_test.go b/src/compress/flate/deflate_test.go
index 6fc5abf4d5..ff56712123 100644
--- a/src/compress/flate/deflate_test.go
+++ b/src/compress/flate/deflate_test.go
@@ -10,8 +10,8 @@ import (
"fmt"
"internal/testenv"
"io"
- "io/ioutil"
"math/rand"
+ "os"
"reflect"
"runtime/debug"
"sync"
@@ -387,7 +387,7 @@ func TestDeflateInflateString(t *testing.T) {
t.Skip("skipping in short mode")
}
for _, test := range deflateInflateStringTests {
- gold, err := ioutil.ReadFile(test.filename)
+ gold, err := os.ReadFile(test.filename)
if err != nil {
t.Error(err)
}
@@ -685,7 +685,7 @@ func (w *failWriter) Write(b []byte) (int, error) {
func TestWriterPersistentError(t *testing.T) {
t.Parallel()
- d, err := ioutil.ReadFile("../../testdata/Isaac.Newton-Opticks.txt")
+ d, err := os.ReadFile("../../testdata/Isaac.Newton-Opticks.txt")
if err != nil {
t.Fatalf("ReadFile: %v", err)
}
diff --git a/src/compress/flate/huffman_bit_writer_test.go b/src/compress/flate/huffman_bit_writer_test.go
index 882d3abec1..a57799cae0 100644
--- a/src/compress/flate/huffman_bit_writer_test.go
+++ b/src/compress/flate/huffman_bit_writer_test.go
@@ -8,7 +8,6 @@ import (
"bytes"
"flag"
"fmt"
- "io/ioutil"
"os"
"path/filepath"
"strings"
@@ -38,7 +37,7 @@ func TestBlockHuff(t *testing.T) {
}
func testBlockHuff(t *testing.T, in, out string) {
- all, err := ioutil.ReadFile(in)
+ all, err := os.ReadFile(in)
if err != nil {
t.Error(err)
return
@@ -49,7 +48,7 @@ func testBlockHuff(t *testing.T, in, out string) {
bw.flush()
got := buf.Bytes()
- want, err := ioutil.ReadFile(out)
+ want, err := os.ReadFile(out)
if err != nil && !*update {
t.Error(err)
return
@@ -60,7 +59,7 @@ func testBlockHuff(t *testing.T, in, out string) {
if *update {
if in != out {
t.Logf("Updating %q", out)
- if err := ioutil.WriteFile(out, got, 0666); err != nil {
+ if err := os.WriteFile(out, got, 0666); err != nil {
t.Error(err)
}
return
@@ -70,7 +69,7 @@ func testBlockHuff(t *testing.T, in, out string) {
}
t.Errorf("%q != %q (see %q)", in, out, in+".got")
- if err := ioutil.WriteFile(in+".got", got, 0666); err != nil {
+ if err := os.WriteFile(in+".got", got, 0666); err != nil {
t.Error(err)
}
return
@@ -85,7 +84,7 @@ func testBlockHuff(t *testing.T, in, out string) {
got = buf.Bytes()
if !bytes.Equal(got, want) {
t.Errorf("after reset %q != %q (see %q)", in, out, in+".reset.got")
- if err := ioutil.WriteFile(in+".reset.got", got, 0666); err != nil {
+ if err := os.WriteFile(in+".reset.got", got, 0666); err != nil {
t.Error(err)
}
return
@@ -186,7 +185,7 @@ func testBlock(t *testing.T, test huffTest, ttype string) {
if *update {
if test.input != "" {
t.Logf("Updating %q", test.want)
- input, err := ioutil.ReadFile(test.input)
+ input, err := os.ReadFile(test.input)
if err != nil {
t.Error(err)
return
@@ -216,12 +215,12 @@ func testBlock(t *testing.T, test huffTest, ttype string) {
if test.input != "" {
t.Logf("Testing %q", test.want)
- input, err := ioutil.ReadFile(test.input)
+ input, err := os.ReadFile(test.input)
if err != nil {
t.Error(err)
return
}
- want, err := ioutil.ReadFile(test.want)
+ want, err := os.ReadFile(test.want)
if err != nil {
t.Error(err)
return
@@ -233,7 +232,7 @@ func testBlock(t *testing.T, test huffTest, ttype string) {
got := buf.Bytes()
if !bytes.Equal(got, want) {
t.Errorf("writeBlock did not yield expected result for file %q with input. See %q", test.want, test.want+".got")
- if err := ioutil.WriteFile(test.want+".got", got, 0666); err != nil {
+ if err := os.WriteFile(test.want+".got", got, 0666); err != nil {
t.Error(err)
}
}
@@ -247,7 +246,7 @@ func testBlock(t *testing.T, test huffTest, ttype string) {
got = buf.Bytes()
if !bytes.Equal(got, want) {
t.Errorf("reset: writeBlock did not yield expected result for file %q with input. See %q", test.want, test.want+".reset.got")
- if err := ioutil.WriteFile(test.want+".reset.got", got, 0666); err != nil {
+ if err := os.WriteFile(test.want+".reset.got", got, 0666); err != nil {
t.Error(err)
}
return
@@ -256,7 +255,7 @@ func testBlock(t *testing.T, test huffTest, ttype string) {
testWriterEOF(t, "wb", test, true)
}
t.Logf("Testing %q", test.wantNoInput)
- wantNI, err := ioutil.ReadFile(test.wantNoInput)
+ wantNI, err := os.ReadFile(test.wantNoInput)
if err != nil {
t.Error(err)
return
@@ -268,7 +267,7 @@ func testBlock(t *testing.T, test huffTest, ttype string) {
got := buf.Bytes()
if !bytes.Equal(got, wantNI) {
t.Errorf("writeBlock did not yield expected result for file %q with input. See %q", test.wantNoInput, test.wantNoInput+".got")
- if err := ioutil.WriteFile(test.want+".got", got, 0666); err != nil {
+ if err := os.WriteFile(test.want+".got", got, 0666); err != nil {
t.Error(err)
}
} else if got[0]&1 == 1 {
@@ -286,7 +285,7 @@ func testBlock(t *testing.T, test huffTest, ttype string) {
got = buf.Bytes()
if !bytes.Equal(got, wantNI) {
t.Errorf("reset: writeBlock did not yield expected result for file %q without input. See %q", test.want, test.want+".reset.got")
- if err := ioutil.WriteFile(test.want+".reset.got", got, 0666); err != nil {
+ if err := os.WriteFile(test.want+".reset.got", got, 0666); err != nil {
t.Error(err)
}
return
@@ -325,7 +324,7 @@ func testWriterEOF(t *testing.T, ttype string, test huffTest, useInput bool) {
var input []byte
if useInput {
var err error
- input, err = ioutil.ReadFile(test.input)
+ input, err = os.ReadFile(test.input)
if err != nil {
t.Error(err)
return
diff --git a/src/compress/flate/reader_test.go b/src/compress/flate/reader_test.go
index eb32c89184..94610fbb78 100644
--- a/src/compress/flate/reader_test.go
+++ b/src/compress/flate/reader_test.go
@@ -7,7 +7,7 @@ package flate
import (
"bytes"
"io"
- "io/ioutil"
+ "os"
"runtime"
"strings"
"testing"
@@ -80,7 +80,7 @@ var sizes = []struct {
func doBench(b *testing.B, f func(b *testing.B, buf []byte, level, n int)) {
for _, suite := range suites {
- buf, err := ioutil.ReadFile(suite.file)
+ buf, err := os.ReadFile(suite.file)
if err != nil {
b.Fatal(err)
}
diff --git a/src/compress/gzip/issue14937_test.go b/src/compress/gzip/issue14937_test.go
index 24db3641aa..20da0b6824 100644
--- a/src/compress/gzip/issue14937_test.go
+++ b/src/compress/gzip/issue14937_test.go
@@ -31,7 +31,7 @@ func TestGZIPFilesHaveZeroMTimes(t *testing.T) {
t.Fatal("error evaluating GOROOT: ", err)
}
var files []string
- err = filepath.Walk(goroot, func(path string, info fs.FileInfo, err error) error {
+ err = filepath.WalkDir(goroot, func(path string, info fs.DirEntry, err error) error {
if err != nil {
return err
}
diff --git a/src/compress/lzw/reader_test.go b/src/compress/lzw/reader_test.go
index 6d91dd806f..d1eb76d042 100644
--- a/src/compress/lzw/reader_test.go
+++ b/src/compress/lzw/reader_test.go
@@ -8,8 +8,8 @@ import (
"bytes"
"fmt"
"io"
- "io/ioutil"
"math"
+ "os"
"runtime"
"strconv"
"strings"
@@ -218,7 +218,7 @@ func TestNoLongerSavingPriorExpansions(t *testing.T) {
}
func BenchmarkDecoder(b *testing.B) {
- buf, err := ioutil.ReadFile("../testdata/e.txt")
+ buf, err := os.ReadFile("../testdata/e.txt")
if err != nil {
b.Fatal(err)
}
diff --git a/src/compress/lzw/writer_test.go b/src/compress/lzw/writer_test.go
index 33a28bdd3a..1a5dbcae93 100644
--- a/src/compress/lzw/writer_test.go
+++ b/src/compress/lzw/writer_test.go
@@ -8,7 +8,6 @@ import (
"fmt"
"internal/testenv"
"io"
- "io/ioutil"
"math"
"os"
"runtime"
@@ -125,7 +124,7 @@ func TestSmallLitWidth(t *testing.T) {
}
func BenchmarkEncoder(b *testing.B) {
- buf, err := ioutil.ReadFile("../testdata/e.txt")
+ buf, err := os.ReadFile("../testdata/e.txt")
if err != nil {
b.Fatal(err)
}
diff --git a/src/compress/zlib/writer_test.go b/src/compress/zlib/writer_test.go
index c518729146..f0b38880a6 100644
--- a/src/compress/zlib/writer_test.go
+++ b/src/compress/zlib/writer_test.go
@@ -9,7 +9,6 @@ import (
"fmt"
"internal/testenv"
"io"
- "io/ioutil"
"os"
"testing"
)
@@ -95,7 +94,7 @@ func testFileLevelDictReset(t *testing.T, fn string, level int, dict []byte) {
var b0 []byte
var err error
if fn != "" {
- b0, err = ioutil.ReadFile(fn)
+ b0, err = os.ReadFile(fn)
if err != nil {
t.Errorf("%s (level=%d): %v", fn, level, err)
return
diff --git a/src/crypto/ed25519/internal/edwards25519/edwards25519.go b/src/crypto/ed25519/internal/edwards25519/edwards25519.go
index fd03c252af..b091481b77 100644
--- a/src/crypto/ed25519/internal/edwards25519/edwards25519.go
+++ b/src/crypto/ed25519/internal/edwards25519/edwards25519.go
@@ -722,7 +722,7 @@ func (p *ExtendedGroupElement) FromBytes(s *[32]byte) bool {
FeOne(&p.Z)
FeSquare(&u, &p.Y)
FeMul(&v, &u, &d)
- FeSub(&u, &u, &p.Z) // y = y^2-1
+ FeSub(&u, &u, &p.Z) // u = y^2-1
FeAdd(&v, &v, &p.Z) // v = dy^2+1
FeSquare(&v3, &v)
diff --git a/src/crypto/md5/gen.go b/src/crypto/md5/gen.go
index a11f22059f..1468924cbc 100644
--- a/src/crypto/md5/gen.go
+++ b/src/crypto/md5/gen.go
@@ -15,8 +15,8 @@ import (
"bytes"
"flag"
"go/format"
- "io/ioutil"
"log"
+ "os"
"strings"
"text/template"
)
@@ -37,7 +37,7 @@ func main() {
if err != nil {
log.Fatal(err)
}
- err = ioutil.WriteFile(*filename, data, 0644)
+ err = os.WriteFile(*filename, data, 0644)
if err != nil {
log.Fatal(err)
}
diff --git a/src/crypto/tls/handshake_test.go b/src/crypto/tls/handshake_test.go
index 605be587b5..d9ff9fe948 100644
--- a/src/crypto/tls/handshake_test.go
+++ b/src/crypto/tls/handshake_test.go
@@ -13,7 +13,6 @@ import (
"flag"
"fmt"
"io"
- "io/ioutil"
"net"
"os"
"os/exec"
@@ -224,7 +223,7 @@ func parseTestData(r io.Reader) (flows [][]byte, err error) {
// tempFile creates a temp file containing contents and returns its path.
func tempFile(contents string) string {
- file, err := ioutil.TempFile("", "go-tls-test")
+ file, err := os.CreateTemp("", "go-tls-test")
if err != nil {
panic("failed to create temp file: " + err.Error())
}
diff --git a/src/crypto/tls/link_test.go b/src/crypto/tls/link_test.go
index 8224216b5c..8c392ff7c4 100644
--- a/src/crypto/tls/link_test.go
+++ b/src/crypto/tls/link_test.go
@@ -7,7 +7,6 @@ package tls
import (
"bytes"
"internal/testenv"
- "io/ioutil"
"os"
"os/exec"
"path/filepath"
@@ -77,7 +76,7 @@ func main() { tls.Dial("", "", nil) }
exeFile := filepath.Join(tmpDir, "x.exe")
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- if err := ioutil.WriteFile(goFile, []byte(tt.program), 0644); err != nil {
+ if err := os.WriteFile(goFile, []byte(tt.program), 0644); err != nil {
t.Fatal(err)
}
os.Remove(exeFile)
diff --git a/src/crypto/tls/tls.go b/src/crypto/tls/tls.go
index bf577cadea..19884f96e7 100644
--- a/src/crypto/tls/tls.go
+++ b/src/crypto/tls/tls.go
@@ -22,8 +22,8 @@ import (
"encoding/pem"
"errors"
"fmt"
- "io/ioutil"
"net"
+ "os"
"strings"
)
@@ -222,11 +222,11 @@ func (d *Dialer) DialContext(ctx context.Context, network, addr string) (net.Con
// form a certificate chain. On successful return, Certificate.Leaf will
// be nil because the parsed form of the certificate is not retained.
func LoadX509KeyPair(certFile, keyFile string) (Certificate, error) {
- certPEMBlock, err := ioutil.ReadFile(certFile)
+ certPEMBlock, err := os.ReadFile(certFile)
if err != nil {
return Certificate{}, err
}
- keyPEMBlock, err := ioutil.ReadFile(keyFile)
+ keyPEMBlock, err := os.ReadFile(keyFile)
if err != nil {
return Certificate{}, err
}
diff --git a/src/crypto/x509/internal/macos/corefoundation.go b/src/crypto/x509/internal/macos/corefoundation.go
index 9b776d4b85..0572c6ccd8 100644
--- a/src/crypto/x509/internal/macos/corefoundation.go
+++ b/src/crypto/x509/internal/macos/corefoundation.go
@@ -39,7 +39,6 @@ type CFString CFRef
const kCFAllocatorDefault = 0
const kCFStringEncodingUTF8 = 0x08000100
-//go:linkname x509_CFStringCreateWithBytes x509_CFStringCreateWithBytes
//go:cgo_import_dynamic x509_CFStringCreateWithBytes CFStringCreateWithBytes "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
// StringToCFString returns a copy of the UTF-8 contents of s as a new CFString.
@@ -52,7 +51,6 @@ func StringToCFString(s string) CFString {
}
func x509_CFStringCreateWithBytes_trampoline()
-//go:linkname x509_CFDictionaryGetValueIfPresent x509_CFDictionaryGetValueIfPresent
//go:cgo_import_dynamic x509_CFDictionaryGetValueIfPresent CFDictionaryGetValueIfPresent "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
func CFDictionaryGetValueIfPresent(dict CFRef, key CFString) (value CFRef, ok bool) {
@@ -67,7 +65,6 @@ func x509_CFDictionaryGetValueIfPresent_trampoline()
const kCFNumberSInt32Type = 3
-//go:linkname x509_CFNumberGetValue x509_CFNumberGetValue
//go:cgo_import_dynamic x509_CFNumberGetValue CFNumberGetValue "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
func CFNumberGetValue(num CFRef) (int32, error) {
@@ -81,7 +78,6 @@ func CFNumberGetValue(num CFRef) (int32, error) {
}
func x509_CFNumberGetValue_trampoline()
-//go:linkname x509_CFDataGetLength x509_CFDataGetLength
//go:cgo_import_dynamic x509_CFDataGetLength CFDataGetLength "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
func CFDataGetLength(data CFRef) int {
@@ -90,7 +86,6 @@ func CFDataGetLength(data CFRef) int {
}
func x509_CFDataGetLength_trampoline()
-//go:linkname x509_CFDataGetBytePtr x509_CFDataGetBytePtr
//go:cgo_import_dynamic x509_CFDataGetBytePtr CFDataGetBytePtr "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
func CFDataGetBytePtr(data CFRef) uintptr {
@@ -99,7 +94,6 @@ func CFDataGetBytePtr(data CFRef) uintptr {
}
func x509_CFDataGetBytePtr_trampoline()
-//go:linkname x509_CFArrayGetCount x509_CFArrayGetCount
//go:cgo_import_dynamic x509_CFArrayGetCount CFArrayGetCount "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
func CFArrayGetCount(array CFRef) int {
@@ -108,7 +102,6 @@ func CFArrayGetCount(array CFRef) int {
}
func x509_CFArrayGetCount_trampoline()
-//go:linkname x509_CFArrayGetValueAtIndex x509_CFArrayGetValueAtIndex
//go:cgo_import_dynamic x509_CFArrayGetValueAtIndex CFArrayGetValueAtIndex "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
func CFArrayGetValueAtIndex(array CFRef, index int) CFRef {
@@ -117,7 +110,6 @@ func CFArrayGetValueAtIndex(array CFRef, index int) CFRef {
}
func x509_CFArrayGetValueAtIndex_trampoline()
-//go:linkname x509_CFEqual x509_CFEqual
//go:cgo_import_dynamic x509_CFEqual CFEqual "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
func CFEqual(a, b CFRef) bool {
@@ -126,7 +118,6 @@ func CFEqual(a, b CFRef) bool {
}
func x509_CFEqual_trampoline()
-//go:linkname x509_CFRelease x509_CFRelease
//go:cgo_import_dynamic x509_CFRelease CFRelease "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
func CFRelease(ref CFRef) {
diff --git a/src/crypto/x509/internal/macos/security.go b/src/crypto/x509/internal/macos/security.go
index 5e39e93666..3163e3a4f7 100644
--- a/src/crypto/x509/internal/macos/security.go
+++ b/src/crypto/x509/internal/macos/security.go
@@ -63,7 +63,6 @@ var ErrNoTrustSettings = errors.New("no trust settings found")
const errSecNoTrustSettings = -25263
-//go:linkname x509_SecTrustSettingsCopyCertificates x509_SecTrustSettingsCopyCertificates
//go:cgo_import_dynamic x509_SecTrustSettingsCopyCertificates SecTrustSettingsCopyCertificates "/System/Library/Frameworks/Security.framework/Versions/A/Security"
func SecTrustSettingsCopyCertificates(domain SecTrustSettingsDomain) (certArray CFRef, err error) {
@@ -80,7 +79,6 @@ func x509_SecTrustSettingsCopyCertificates_trampoline()
const kSecFormatX509Cert int32 = 9
-//go:linkname x509_SecItemExport x509_SecItemExport
//go:cgo_import_dynamic x509_SecItemExport SecItemExport "/System/Library/Frameworks/Security.framework/Versions/A/Security"
func SecItemExport(cert CFRef) (data CFRef, err error) {
@@ -95,7 +93,6 @@ func x509_SecItemExport_trampoline()
const errSecItemNotFound = -25300
-//go:linkname x509_SecTrustSettingsCopyTrustSettings x509_SecTrustSettingsCopyTrustSettings
//go:cgo_import_dynamic x509_SecTrustSettingsCopyTrustSettings SecTrustSettingsCopyTrustSettings "/System/Library/Frameworks/Security.framework/Versions/A/Security"
func SecTrustSettingsCopyTrustSettings(cert CFRef, domain SecTrustSettingsDomain) (trustSettings CFRef, err error) {
@@ -110,7 +107,6 @@ func SecTrustSettingsCopyTrustSettings(cert CFRef, domain SecTrustSettingsDomain
}
func x509_SecTrustSettingsCopyTrustSettings_trampoline()
-//go:linkname x509_SecPolicyCopyProperties x509_SecPolicyCopyProperties
//go:cgo_import_dynamic x509_SecPolicyCopyProperties SecPolicyCopyProperties "/System/Library/Frameworks/Security.framework/Versions/A/Security"
func SecPolicyCopyProperties(policy CFRef) CFRef {
diff --git a/src/crypto/x509/name_constraints_test.go b/src/crypto/x509/name_constraints_test.go
index 34055d07b5..3826c82c38 100644
--- a/src/crypto/x509/name_constraints_test.go
+++ b/src/crypto/x509/name_constraints_test.go
@@ -14,7 +14,6 @@ import (
"encoding/hex"
"encoding/pem"
"fmt"
- "io/ioutil"
"math/big"
"net"
"net/url"
@@ -2005,7 +2004,7 @@ func TestConstraintCases(t *testing.T) {
}
func writePEMsToTempFile(certs []*Certificate) *os.File {
- file, err := ioutil.TempFile("", "name_constraints_test")
+ file, err := os.CreateTemp("", "name_constraints_test")
if err != nil {
panic("cannot create tempfile")
}
diff --git a/src/crypto/x509/root_ios_gen.go b/src/crypto/x509/root_ios_gen.go
index 2bcdab1a77..8bc6e7d9c4 100644
--- a/src/crypto/x509/root_ios_gen.go
+++ b/src/crypto/x509/root_ios_gen.go
@@ -27,9 +27,9 @@ import (
"fmt"
"go/format"
"io"
- "io/ioutil"
"log"
"net/http"
+ "os"
"path"
"sort"
"strings"
@@ -155,7 +155,7 @@ func main() {
if err != nil {
log.Fatal(err)
}
- if err := ioutil.WriteFile(*output, source, 0644); err != nil {
+ if err := os.WriteFile(*output, source, 0644); err != nil {
log.Fatal(err)
}
}
diff --git a/src/crypto/x509/root_plan9.go b/src/crypto/x509/root_plan9.go
index 09f0e23033..2dc4aaf5d7 100644
--- a/src/crypto/x509/root_plan9.go
+++ b/src/crypto/x509/root_plan9.go
@@ -7,7 +7,6 @@
package x509
import (
- "io/ioutil"
"os"
)
@@ -24,7 +23,7 @@ func loadSystemRoots() (*CertPool, error) {
roots := NewCertPool()
var bestErr error
for _, file := range certFiles {
- data, err := ioutil.ReadFile(file)
+ data, err := os.ReadFile(file)
if err == nil {
roots.AppendCertsFromPEM(data)
return roots, nil
diff --git a/src/crypto/x509/root_unix.go b/src/crypto/x509/root_unix.go
index 1090b69f83..262fc079d5 100644
--- a/src/crypto/x509/root_unix.go
+++ b/src/crypto/x509/root_unix.go
@@ -8,7 +8,6 @@ package x509
import (
"io/fs"
- "io/ioutil"
"os"
"path/filepath"
"strings"
@@ -40,7 +39,7 @@ func loadSystemRoots() (*CertPool, error) {
var firstErr error
for _, file := range files {
- data, err := ioutil.ReadFile(file)
+ data, err := os.ReadFile(file)
if err == nil {
roots.AppendCertsFromPEM(data)
break
@@ -68,7 +67,7 @@ func loadSystemRoots() (*CertPool, error) {
continue
}
for _, fi := range fis {
- data, err := ioutil.ReadFile(directory + "/" + fi.Name())
+ data, err := os.ReadFile(directory + "/" + fi.Name())
if err == nil {
roots.AppendCertsFromPEM(data)
}
@@ -82,17 +81,17 @@ func loadSystemRoots() (*CertPool, error) {
return nil, firstErr
}
-// readUniqueDirectoryEntries is like ioutil.ReadDir but omits
+// readUniqueDirectoryEntries is like os.ReadDir but omits
// symlinks that point within the directory.
-func readUniqueDirectoryEntries(dir string) ([]fs.FileInfo, error) {
- fis, err := ioutil.ReadDir(dir)
+func readUniqueDirectoryEntries(dir string) ([]fs.DirEntry, error) {
+ files, err := os.ReadDir(dir)
if err != nil {
return nil, err
}
- uniq := fis[:0]
- for _, fi := range fis {
- if !isSameDirSymlink(fi, dir) {
- uniq = append(uniq, fi)
+ uniq := files[:0]
+ for _, f := range files {
+ if !isSameDirSymlink(f, dir) {
+ uniq = append(uniq, f)
}
}
return uniq, nil
@@ -100,10 +99,10 @@ func readUniqueDirectoryEntries(dir string) ([]fs.FileInfo, error) {
// isSameDirSymlink reports whether fi in dir is a symlink with a
// target not containing a slash.
-func isSameDirSymlink(fi fs.FileInfo, dir string) bool {
- if fi.Mode()&fs.ModeSymlink == 0 {
+func isSameDirSymlink(f fs.DirEntry, dir string) bool {
+ if f.Type()&fs.ModeSymlink == 0 {
return false
}
- target, err := os.Readlink(filepath.Join(dir, fi.Name()))
+ target, err := os.Readlink(filepath.Join(dir, f.Name()))
return err == nil && !strings.Contains(target, "/")
}
diff --git a/src/crypto/x509/root_unix_test.go b/src/crypto/x509/root_unix_test.go
index b2e832ff36..878ed7c2fa 100644
--- a/src/crypto/x509/root_unix_test.go
+++ b/src/crypto/x509/root_unix_test.go
@@ -9,7 +9,6 @@ package x509
import (
"bytes"
"fmt"
- "io/ioutil"
"os"
"path/filepath"
"reflect"
@@ -147,7 +146,7 @@ func TestLoadSystemCertsLoadColonSeparatedDirs(t *testing.T) {
os.Setenv(certFileEnv, origFile)
}()
- tmpDir, err := ioutil.TempDir(os.TempDir(), "x509-issue35325")
+ tmpDir, err := os.MkdirTemp(os.TempDir(), "x509-issue35325")
if err != nil {
t.Fatalf("Failed to create temporary directory: %v", err)
}
@@ -166,7 +165,7 @@ func TestLoadSystemCertsLoadColonSeparatedDirs(t *testing.T) {
t.Fatalf("Failed to create certificate dir: %v", err)
}
certOutFile := filepath.Join(certDir, "cert.crt")
- if err := ioutil.WriteFile(certOutFile, []byte(certPEM), 0655); err != nil {
+ if err := os.WriteFile(certOutFile, []byte(certPEM), 0655); err != nil {
t.Fatalf("Failed to write certificate to file: %v", err)
}
certDirs = append(certDirs, certDir)
diff --git a/src/debug/dwarf/dwarf5ranges_test.go b/src/debug/dwarf/dwarf5ranges_test.go
index 2229d439a5..0ff1a55bc9 100644
--- a/src/debug/dwarf/dwarf5ranges_test.go
+++ b/src/debug/dwarf/dwarf5ranges_test.go
@@ -6,13 +6,13 @@ package dwarf
import (
"encoding/binary"
- "io/ioutil"
+ "os"
"reflect"
"testing"
)
func TestDwarf5Ranges(t *testing.T) {
- rngLists, err := ioutil.ReadFile("testdata/debug_rnglists")
+ rngLists, err := os.ReadFile("testdata/debug_rnglists")
if err != nil {
t.Fatalf("could not read test data: %v", err)
}
diff --git a/src/debug/gosym/pclntab_test.go b/src/debug/gosym/pclntab_test.go
index f93a5bf5e5..7347139b5d 100644
--- a/src/debug/gosym/pclntab_test.go
+++ b/src/debug/gosym/pclntab_test.go
@@ -10,7 +10,6 @@ import (
"debug/elf"
"internal/testenv"
"io"
- "io/ioutil"
"os"
"os/exec"
"path/filepath"
@@ -31,7 +30,7 @@ func dotest(t *testing.T) {
t.Skipf("skipping on non-AMD64 system %s", runtime.GOARCH)
}
var err error
- pclineTempDir, err = ioutil.TempDir("", "pclinetest")
+ pclineTempDir, err = os.MkdirTemp("", "pclinetest")
if err != nil {
t.Fatal(err)
}
@@ -278,7 +277,7 @@ func TestPCLine(t *testing.T) {
// }
// [END]
func Test115PclnParsing(t *testing.T) {
- zippedDat, err := ioutil.ReadFile("testdata/pcln115.gz")
+ zippedDat, err := os.ReadFile("testdata/pcln115.gz")
if err != nil {
t.Fatal(err)
}
diff --git a/src/debug/pe/file_test.go b/src/debug/pe/file_test.go
index d96cd30904..58deff1450 100644
--- a/src/debug/pe/file_test.go
+++ b/src/debug/pe/file_test.go
@@ -8,7 +8,6 @@ import (
"bytes"
"debug/dwarf"
"internal/testenv"
- "io/ioutil"
"os"
"os/exec"
"path/filepath"
@@ -354,7 +353,7 @@ func testDWARF(t *testing.T, linktype int) {
}
testenv.MustHaveGoRun(t)
- tmpdir, err := ioutil.TempDir("", "TestDWARF")
+ tmpdir, err := os.MkdirTemp("", "TestDWARF")
if err != nil {
t.Fatal(err)
}
@@ -473,7 +472,7 @@ func TestBSSHasZeros(t *testing.T) {
t.Skip("skipping test: gcc is missing")
}
- tmpdir, err := ioutil.TempDir("", "TestBSSHasZeros")
+ tmpdir, err := os.MkdirTemp("", "TestBSSHasZeros")
if err != nil {
t.Fatal(err)
}
@@ -492,7 +491,7 @@ main(void)
return 0;
}
`
- err = ioutil.WriteFile(srcpath, []byte(src), 0644)
+ err = os.WriteFile(srcpath, []byte(src), 0644)
if err != nil {
t.Fatal(err)
}
@@ -597,14 +596,14 @@ func TestBuildingWindowsGUI(t *testing.T) {
if runtime.GOOS != "windows" {
t.Skip("skipping windows only test")
}
- tmpdir, err := ioutil.TempDir("", "TestBuildingWindowsGUI")
+ tmpdir, err := os.MkdirTemp("", "TestBuildingWindowsGUI")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmpdir)
src := filepath.Join(tmpdir, "a.go")
- err = ioutil.WriteFile(src, []byte(`package main; func main() {}`), 0644)
+ err = os.WriteFile(src, []byte(`package main; func main() {}`), 0644)
if err != nil {
t.Fatal(err)
}
@@ -684,7 +683,7 @@ func TestInvalidOptionalHeaderMagic(t *testing.T) {
func TestImportedSymbolsNoPanicMissingOptionalHeader(t *testing.T) {
// https://golang.org/issue/30250
// ImportedSymbols shouldn't panic if optional headers is missing
- data, err := ioutil.ReadFile("testdata/gcc-amd64-mingw-obj")
+ data, err := os.ReadFile("testdata/gcc-amd64-mingw-obj")
if err != nil {
t.Fatal(err)
}
diff --git a/src/embed/embed.go b/src/embed/embed.go
index b22975cc3a..29e0adf1a6 100644
--- a/src/embed/embed.go
+++ b/src/embed/embed.go
@@ -59,12 +59,15 @@
// as Go double-quoted or back-quoted string literals.
//
// If a pattern names a directory, all files in the subtree rooted at that directory are
-// embedded (recursively), so the variable in the above example is equivalent to:
+// embedded (recursively), except that files with names beginning with ‘.’ or ‘_’
+// are excluded. So the variable in the above example is almost equivalent to:
//
// // content is our static web server content.
// //go:embed image template html/index.html
// var content embed.FS
//
+// The difference is that ‘image/*’ embeds ‘image/.tempfile’ while ‘image’ does not.
+//
// The //go:embed directive can be used with both exported and unexported variables,
// depending on whether the package wants to make the data available to other packages.
// Similarly, it can be used with both global and function-local variables,
diff --git a/src/embed/internal/embedtest/embed_test.go b/src/embed/internal/embedtest/embed_test.go
index c82ca9fed2..c6a7bea7a3 100644
--- a/src/embed/internal/embedtest/embed_test.go
+++ b/src/embed/internal/embedtest/embed_test.go
@@ -65,7 +65,7 @@ func TestGlobal(t *testing.T) {
testFiles(t, global, "testdata/hello.txt", "hello, world\n")
testFiles(t, global, "testdata/glass.txt", "I can eat glass and it doesn't hurt me.\n")
- if err := fstest.TestFS(global); err != nil {
+ if err := fstest.TestFS(global, "concurrency.txt", "testdata/hello.txt"); err != nil {
t.Fatal(err)
}
@@ -101,3 +101,24 @@ func TestDir(t *testing.T) {
testDir(t, all, "testdata/i/j", "k/")
testDir(t, all, "testdata/i/j/k", "k8s.txt")
}
+
+func TestHidden(t *testing.T) {
+ //go:embed testdata
+ var dir embed.FS
+
+ //go:embed testdata/*
+ var star embed.FS
+
+ t.Logf("//go:embed testdata")
+
+ testDir(t, dir, "testdata",
+ "ascii.txt", "glass.txt", "hello.txt", "i/", "ken.txt")
+
+ t.Logf("//go:embed testdata/*")
+
+ testDir(t, star, "testdata",
+ ".hidden/", "_hidden/", "ascii.txt", "glass.txt", "hello.txt", "i/", "ken.txt")
+
+ testDir(t, star, "testdata/.hidden",
+ "fortune.txt", "more/") // but not .more or _more
+}
diff --git a/src/embed/internal/embedtest/embedx_test.go b/src/embed/internal/embedtest/embedx_test.go
index 53d45488f1..20d5a28c11 100644
--- a/src/embed/internal/embedtest/embedx_test.go
+++ b/src/embed/internal/embedtest/embedx_test.go
@@ -6,7 +6,7 @@ package embedtest_test
import (
"embed"
- "io/ioutil"
+ "os"
"testing"
)
@@ -59,7 +59,7 @@ func TestXGlobal(t *testing.T) {
testString(t, concurrency2, "concurrency2", "Concurrency is not parallelism.\n")
testString(t, string(glass2), "glass2", "I can eat glass and it doesn't hurt me.\n")
- big, err := ioutil.ReadFile("testdata/ascii.txt")
+ big, err := os.ReadFile("testdata/ascii.txt")
if err != nil {
t.Fatal(err)
}
diff --git a/src/embed/internal/embedtest/testdata/.hidden/.more/tip.txt b/src/embed/internal/embedtest/testdata/.hidden/.more/tip.txt
new file mode 100644
index 0000000000..71b9c6955d
--- /dev/null
+++ b/src/embed/internal/embedtest/testdata/.hidden/.more/tip.txt
@@ -0,0 +1 @@
+#define struct union /* Great space saver */
diff --git a/src/embed/internal/embedtest/testdata/.hidden/_more/tip.txt b/src/embed/internal/embedtest/testdata/.hidden/_more/tip.txt
new file mode 100644
index 0000000000..71b9c6955d
--- /dev/null
+++ b/src/embed/internal/embedtest/testdata/.hidden/_more/tip.txt
@@ -0,0 +1 @@
+#define struct union /* Great space saver */
diff --git a/src/embed/internal/embedtest/testdata/.hidden/fortune.txt b/src/embed/internal/embedtest/testdata/.hidden/fortune.txt
new file mode 100644
index 0000000000..31f2013f94
--- /dev/null
+++ b/src/embed/internal/embedtest/testdata/.hidden/fortune.txt
@@ -0,0 +1,2 @@
+WARNING: terminal is not fully functional
+ - (press RETURN)
diff --git a/src/embed/internal/embedtest/testdata/.hidden/more/tip.txt b/src/embed/internal/embedtest/testdata/.hidden/more/tip.txt
new file mode 100644
index 0000000000..71b9c6955d
--- /dev/null
+++ b/src/embed/internal/embedtest/testdata/.hidden/more/tip.txt
@@ -0,0 +1 @@
+#define struct union /* Great space saver */
diff --git a/src/embed/internal/embedtest/testdata/_hidden/fortune.txt b/src/embed/internal/embedtest/testdata/_hidden/fortune.txt
new file mode 100644
index 0000000000..31f2013f94
--- /dev/null
+++ b/src/embed/internal/embedtest/testdata/_hidden/fortune.txt
@@ -0,0 +1,2 @@
+WARNING: terminal is not fully functional
+ - (press RETURN)
diff --git a/src/encoding/json/scanner.go b/src/encoding/json/scanner.go
index c3f5f6372d..9dc1903e2d 100644
--- a/src/encoding/json/scanner.go
+++ b/src/encoding/json/scanner.go
@@ -47,7 +47,7 @@ type SyntaxError struct {
Offset int64 // error occurred after reading Offset bytes
}
-func (e *SyntaxError) Error() string { return "json: " + e.msg }
+func (e *SyntaxError) Error() string { return e.msg }
// A scanner is a JSON scanning state machine.
// Callers call scan.reset and then pass bytes in one at a time
diff --git a/src/go.mod b/src/go.mod
index 37091e116a..1fcd02f9ba 100644
--- a/src/go.mod
+++ b/src/go.mod
@@ -5,6 +5,6 @@ go 1.16
require (
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897
golang.org/x/net v0.0.0-20201029221708-28c70e62bb1d
- golang.org/x/sys v0.0.0-20201110211018-35f3e6cf4a65 // indirect
+ golang.org/x/sys v0.0.0-20201204225414-ed752295db88 // indirect
golang.org/x/text v0.3.4 // indirect
)
diff --git a/src/go.sum b/src/go.sum
index 3f0270fb9a..913e6ea68d 100644
--- a/src/go.sum
+++ b/src/go.sum
@@ -8,8 +8,8 @@ golang.org/x/net v0.0.0-20201029221708-28c70e62bb1d/go.mod h1:sp8m0HH+o8qH0wwXwY
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20201110211018-35f3e6cf4a65 h1:Qo9oJ566/Sq7N4hrGftVXs8GI2CXBCuOd4S2wHE/e0M=
-golang.org/x/sys v0.0.0-20201110211018-35f3e6cf4a65/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201204225414-ed752295db88 h1:KmZPnMocC93w341XZp26yTJg8Za7lhb2KhkYmixoeso=
+golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc=
diff --git a/src/go/build/build_test.go b/src/go/build/build_test.go
index 5a4a2d62f5..5a3e9ee714 100644
--- a/src/go/build/build_test.go
+++ b/src/go/build/build_test.go
@@ -8,7 +8,6 @@ import (
"flag"
"internal/testenv"
"io"
- "io/ioutil"
"os"
"path/filepath"
"reflect"
@@ -454,7 +453,7 @@ func TestImportDirNotExist(t *testing.T) {
testenv.MustHaveGoBuild(t) // really must just have source
ctxt := Default
- emptyDir, err := ioutil.TempDir("", t.Name())
+ emptyDir, err := os.MkdirTemp("", t.Name())
if err != nil {
t.Fatal(err)
}
@@ -592,7 +591,7 @@ func TestImportPackageOutsideModule(t *testing.T) {
// Create a GOPATH in a temporary directory. We don't use testdata
// because it's in GOROOT, which interferes with the module heuristic.
- gopath, err := ioutil.TempDir("", "gobuild-notmodule")
+ gopath, err := os.MkdirTemp("", "gobuild-notmodule")
if err != nil {
t.Fatal(err)
}
@@ -600,7 +599,7 @@ func TestImportPackageOutsideModule(t *testing.T) {
if err := os.MkdirAll(filepath.Join(gopath, "src/example.com/p"), 0777); err != nil {
t.Fatal(err)
}
- if err := ioutil.WriteFile(filepath.Join(gopath, "src/example.com/p/p.go"), []byte("package p"), 0666); err != nil {
+ if err := os.WriteFile(filepath.Join(gopath, "src/example.com/p/p.go"), []byte("package p"), 0666); err != nil {
t.Fatal(err)
}
@@ -656,12 +655,12 @@ func TestIssue23594(t *testing.T) {
// Verifies golang.org/issue/34752.
func TestMissingImportErrorRepetition(t *testing.T) {
testenv.MustHaveGoBuild(t) // need 'go list' internally
- tmp, err := ioutil.TempDir("", "")
+ tmp, err := os.MkdirTemp("", "")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmp)
- if err := ioutil.WriteFile(filepath.Join(tmp, "go.mod"), []byte("module m"), 0666); err != nil {
+ if err := os.WriteFile(filepath.Join(tmp, "go.mod"), []byte("module m"), 0666); err != nil {
t.Fatal(err)
}
defer os.Setenv("GO111MODULE", os.Getenv("GO111MODULE"))
diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go
index bf1367355d..56942c0fd2 100644
--- a/src/go/build/deps_test.go
+++ b/src/go/build/deps_test.go
@@ -12,7 +12,6 @@ import (
"fmt"
"internal/testenv"
"io/fs"
- "io/ioutil"
"os"
"path/filepath"
"runtime"
@@ -510,8 +509,8 @@ func listStdPkgs(goroot string) ([]string, error) {
var pkgs []string
src := filepath.Join(goroot, "src") + string(filepath.Separator)
- walkFn := func(path string, fi fs.FileInfo, err error) error {
- if err != nil || !fi.IsDir() || path == src {
+ walkFn := func(path string, d fs.DirEntry, err error) error {
+ if err != nil || !d.IsDir() || path == src {
return nil
}
@@ -528,7 +527,7 @@ func listStdPkgs(goroot string) ([]string, error) {
pkgs = append(pkgs, strings.TrimPrefix(name, "vendor/"))
return nil
}
- if err := filepath.Walk(src, walkFn); err != nil {
+ if err := filepath.WalkDir(src, walkFn); err != nil {
return nil, err
}
return pkgs, nil
@@ -597,7 +596,7 @@ func findImports(pkg string) ([]string, error) {
vpkg = "vendor/" + pkg
}
dir := filepath.Join(Default.GOROOT, "src", vpkg)
- files, err := ioutil.ReadDir(dir)
+ files, err := os.ReadDir(dir)
if err != nil {
return nil, err
}
diff --git a/src/go/doc/doc_test.go b/src/go/doc/doc_test.go
index ab98bed62b..cbdca62aa1 100644
--- a/src/go/doc/doc_test.go
+++ b/src/go/doc/doc_test.go
@@ -13,7 +13,7 @@ import (
"go/printer"
"go/token"
"io/fs"
- "io/ioutil"
+ "os"
"path/filepath"
"regexp"
"strings"
@@ -127,7 +127,7 @@ func test(t *testing.T, mode Mode) {
// update golden file if necessary
golden := filepath.Join(dataDir, fmt.Sprintf("%s.%d.golden", pkg.Name, mode))
if *update {
- err := ioutil.WriteFile(golden, got, 0644)
+ err := os.WriteFile(golden, got, 0644)
if err != nil {
t.Error(err)
}
@@ -135,7 +135,7 @@ func test(t *testing.T, mode Mode) {
}
// get golden file
- want, err := ioutil.ReadFile(golden)
+ want, err := os.ReadFile(golden)
if err != nil {
t.Error(err)
continue
diff --git a/src/go/doc/headscan.go b/src/go/doc/headscan.go
index 8ea462366e..fe26a0ea84 100644
--- a/src/go/doc/headscan.go
+++ b/src/go/doc/headscan.go
@@ -69,8 +69,8 @@ func main() {
flag.Parse()
fset := token.NewFileSet()
nheadings := 0
- err := filepath.Walk(*root, func(path string, fi fs.FileInfo, err error) error {
- if !fi.IsDir() {
+ err := filepath.WalkDir(*root, func(path string, info fs.DirEntry, err error) error {
+ if !info.IsDir() {
return nil
}
pkgs, err := parser.ParseDir(fset, path, isGoFile, parser.ParseComments)
diff --git a/src/go/format/benchmark_test.go b/src/go/format/benchmark_test.go
index 7bd45c0e95..ac19aa3bf5 100644
--- a/src/go/format/benchmark_test.go
+++ b/src/go/format/benchmark_test.go
@@ -12,7 +12,7 @@ import (
"flag"
"fmt"
"go/format"
- "io/ioutil"
+ "os"
"testing"
)
@@ -67,7 +67,7 @@ func BenchmarkFormat(b *testing.B) {
if *debug {
filename := t.name + ".src"
- err := ioutil.WriteFile(filename, data, 0660)
+ err := os.WriteFile(filename, data, 0660)
if err != nil {
b.Fatalf("couldn't write %s: %v", filename, err)
}
diff --git a/src/go/format/format_test.go b/src/go/format/format_test.go
index 58e088ede3..27f4c74cdf 100644
--- a/src/go/format/format_test.go
+++ b/src/go/format/format_test.go
@@ -9,7 +9,7 @@ import (
"go/ast"
"go/parser"
"go/token"
- "io/ioutil"
+ "os"
"strings"
"testing"
)
@@ -38,7 +38,7 @@ func diff(t *testing.T, dst, src []byte) {
}
func TestNode(t *testing.T) {
- src, err := ioutil.ReadFile(testfile)
+ src, err := os.ReadFile(testfile)
if err != nil {
t.Fatal(err)
}
@@ -96,7 +96,7 @@ func TestNodeNoModify(t *testing.T) {
}
func TestSource(t *testing.T) {
- src, err := ioutil.ReadFile(testfile)
+ src, err := os.ReadFile(testfile)
if err != nil {
t.Fatal(err)
}
diff --git a/src/go/importer/importer_test.go b/src/go/importer/importer_test.go
index ff6e12c0da..0f5121d802 100644
--- a/src/go/importer/importer_test.go
+++ b/src/go/importer/importer_test.go
@@ -8,7 +8,6 @@ import (
"go/token"
"internal/testenv"
"io"
- "io/ioutil"
"os"
"os/exec"
"runtime"
@@ -52,7 +51,7 @@ func TestForCompiler(t *testing.T) {
mathBigInt := pkg.Scope().Lookup("Int")
posn := fset.Position(mathBigInt.Pos()) // "$GOROOT/src/math/big/int.go:25:1"
filename := strings.Replace(posn.Filename, "$GOROOT", runtime.GOROOT(), 1)
- data, err := ioutil.ReadFile(filename)
+ data, err := os.ReadFile(filename)
if err != nil {
t.Fatalf("can't read file containing declaration of math/big.Int: %v", err)
}
diff --git a/src/go/internal/gccgoimporter/importer_test.go b/src/go/internal/gccgoimporter/importer_test.go
index e42684d107..c5b520feb4 100644
--- a/src/go/internal/gccgoimporter/importer_test.go
+++ b/src/go/internal/gccgoimporter/importer_test.go
@@ -7,7 +7,6 @@ package gccgoimporter
import (
"go/types"
"internal/testenv"
- "io/ioutil"
"os"
"os/exec"
"path/filepath"
@@ -150,7 +149,7 @@ func TestObjImporter(t *testing.T) {
}
t.Logf("gccgo version %d.%d", major, minor)
- tmpdir, err := ioutil.TempDir("", "TestObjImporter")
+ tmpdir, err := os.MkdirTemp("", "TestObjImporter")
if err != nil {
t.Fatal(err)
}
@@ -159,7 +158,7 @@ func TestObjImporter(t *testing.T) {
initmap := make(map[*types.Package]InitData)
imp := GetImporter([]string{tmpdir}, initmap)
- artmpdir, err := ioutil.TempDir("", "TestObjImporter")
+ artmpdir, err := os.MkdirTemp("", "TestObjImporter")
if err != nil {
t.Fatal(err)
}
diff --git a/src/go/internal/gcimporter/gcimporter_test.go b/src/go/internal/gcimporter/gcimporter_test.go
index 663753a18a..3c76aafde3 100644
--- a/src/go/internal/gcimporter/gcimporter_test.go
+++ b/src/go/internal/gcimporter/gcimporter_test.go
@@ -8,7 +8,6 @@ import (
"bytes"
"fmt"
"internal/testenv"
- "io/ioutil"
"os"
"os/exec"
"path/filepath"
@@ -66,7 +65,7 @@ const maxTime = 30 * time.Second
func testDir(t *testing.T, dir string, endTime time.Time) (nimports int) {
dirname := filepath.Join(runtime.GOROOT(), "pkg", runtime.GOOS+"_"+runtime.GOARCH, dir)
- list, err := ioutil.ReadDir(dirname)
+ list, err := os.ReadDir(dirname)
if err != nil {
t.Fatalf("testDir(%s): %s", dirname, err)
}
@@ -94,7 +93,7 @@ func testDir(t *testing.T, dir string, endTime time.Time) (nimports int) {
}
func mktmpdir(t *testing.T) string {
- tmpdir, err := ioutil.TempDir("", "gcimporter_test")
+ tmpdir, err := os.MkdirTemp("", "gcimporter_test")
if err != nil {
t.Fatal("mktmpdir:", err)
}
@@ -144,7 +143,7 @@ func TestVersionHandling(t *testing.T) {
}
const dir = "./testdata/versions"
- list, err := ioutil.ReadDir(dir)
+ list, err := os.ReadDir(dir)
if err != nil {
t.Fatal(err)
}
@@ -199,7 +198,7 @@ func TestVersionHandling(t *testing.T) {
// create file with corrupted export data
// 1) read file
- data, err := ioutil.ReadFile(filepath.Join(dir, name))
+ data, err := os.ReadFile(filepath.Join(dir, name))
if err != nil {
t.Fatal(err)
}
@@ -216,7 +215,7 @@ func TestVersionHandling(t *testing.T) {
// 4) write the file
pkgpath += "_corrupted"
filename := filepath.Join(corruptdir, pkgpath) + ".a"
- ioutil.WriteFile(filename, data, 0666)
+ os.WriteFile(filename, data, 0666)
// test that importing the corrupted file results in an error
_, err = Import(fset, make(map[string]*types.Package), pkgpath, corruptdir, nil)
diff --git a/src/go/internal/srcimporter/srcimporter.go b/src/go/internal/srcimporter/srcimporter.go
index 90bb3a9bc1..c4d501dcd9 100644
--- a/src/go/internal/srcimporter/srcimporter.go
+++ b/src/go/internal/srcimporter/srcimporter.go
@@ -14,7 +14,6 @@ import (
"go/token"
"go/types"
"io"
- "io/ioutil"
"os"
"os/exec"
"path/filepath"
@@ -200,7 +199,7 @@ func (p *Importer) parseFiles(dir string, filenames []string) ([]*ast.File, erro
}
func (p *Importer) cgo(bp *build.Package) (*ast.File, error) {
- tmpdir, err := ioutil.TempDir("", "srcimporter")
+ tmpdir, err := os.MkdirTemp("", "srcimporter")
if err != nil {
return nil, err
}
diff --git a/src/go/internal/srcimporter/srcimporter_test.go b/src/go/internal/srcimporter/srcimporter_test.go
index 102ac43f94..05b12f1636 100644
--- a/src/go/internal/srcimporter/srcimporter_test.go
+++ b/src/go/internal/srcimporter/srcimporter_test.go
@@ -10,7 +10,6 @@ import (
"go/token"
"go/types"
"internal/testenv"
- "io/ioutil"
"os"
"path"
"path/filepath"
@@ -59,7 +58,7 @@ func walkDir(t *testing.T, path string, endTime time.Time) (int, bool) {
return 0, false
}
- list, err := ioutil.ReadDir(filepath.Join(runtime.GOROOT(), "src", path))
+ list, err := os.ReadDir(filepath.Join(runtime.GOROOT(), "src", path))
if err != nil {
t.Fatalf("walkDir %s failed (%v)", path, err)
}
diff --git a/src/go/parser/error_test.go b/src/go/parser/error_test.go
index 83bfdd40ad..8e20b7b468 100644
--- a/src/go/parser/error_test.go
+++ b/src/go/parser/error_test.go
@@ -25,7 +25,7 @@ package parser
import (
"go/scanner"
"go/token"
- "io/ioutil"
+ "os"
"path/filepath"
"regexp"
"strings"
@@ -179,13 +179,13 @@ func checkErrors(t *testing.T, filename string, input interface{}, mode Mode, ex
}
func TestErrors(t *testing.T) {
- list, err := ioutil.ReadDir(testdata)
+ list, err := os.ReadDir(testdata)
if err != nil {
t.Fatal(err)
}
- for _, fi := range list {
- name := fi.Name()
- if !fi.IsDir() && !strings.HasPrefix(name, ".") && (strings.HasSuffix(name, ".src") || strings.HasSuffix(name, ".go2")) {
+ for _, d := range list {
+ name := d.Name()
+ if !d.IsDir() && !strings.HasPrefix(name, ".") && (strings.HasSuffix(name, ".src") || strings.HasSuffix(name, ".go2")) {
mode := DeclarationErrors | AllErrors
if strings.HasSuffix(name, ".go2") {
mode |= ParseTypeParams
diff --git a/src/go/parser/interface.go b/src/go/parser/interface.go
index 1c9a1acd66..b8b312463f 100644
--- a/src/go/parser/interface.go
+++ b/src/go/parser/interface.go
@@ -13,7 +13,7 @@ import (
"go/token"
"io"
"io/fs"
- "io/ioutil"
+ "os"
"path/filepath"
"strings"
)
@@ -39,7 +39,7 @@ func readSource(filename string, src interface{}) ([]byte, error) {
}
return nil, errors.New("invalid source")
}
- return ioutil.ReadFile(filename)
+ return os.ReadFile(filename)
}
// A Mode value is a set of flags (or 0).
@@ -134,29 +134,39 @@ func ParseFile(fset *token.FileSet, filename string, src interface{}, mode Mode)
// first error encountered are returned.
//
func ParseDir(fset *token.FileSet, path string, filter func(fs.FileInfo) bool, mode Mode) (pkgs map[string]*ast.Package, first error) {
- list, err := ioutil.ReadDir(path)
+ list, err := os.ReadDir(path)
if err != nil {
return nil, err
}
pkgs = make(map[string]*ast.Package)
for _, d := range list {
- if strings.HasSuffix(d.Name(), ".go") && (filter == nil || filter(d)) {
- filename := filepath.Join(path, d.Name())
- if src, err := ParseFile(fset, filename, nil, mode); err == nil {
- name := src.Name.Name
- pkg, found := pkgs[name]
- if !found {
- pkg = &ast.Package{
- Name: name,
- Files: make(map[string]*ast.File),
- }
- pkgs[name] = pkg
- }
- pkg.Files[filename] = src
- } else if first == nil {
- first = err
+ if d.IsDir() || !strings.HasSuffix(d.Name(), ".go") {
+ continue
+ }
+ if filter != nil {
+ info, err := d.Info()
+ if err != nil {
+ return nil, err
}
+ if !filter(info) {
+ continue
+ }
+ }
+ filename := filepath.Join(path, d.Name())
+ if src, err := ParseFile(fset, filename, nil, mode); err == nil {
+ name := src.Name.Name
+ pkg, found := pkgs[name]
+ if !found {
+ pkg = &ast.Package{
+ Name: name,
+ Files: make(map[string]*ast.File),
+ }
+ pkgs[name] = pkg
+ }
+ pkg.Files[filename] = src
+ } else if first == nil {
+ first = err
}
}
diff --git a/src/go/parser/parser_test.go b/src/go/parser/parser_test.go
index 7193a329fe..a4f882d368 100644
--- a/src/go/parser/parser_test.go
+++ b/src/go/parser/parser_test.go
@@ -82,6 +82,14 @@ func TestParseDir(t *testing.T) {
}
}
+func TestIssue42951(t *testing.T) {
+ path := "./testdata/issue42951"
+ _, err := ParseDir(token.NewFileSet(), path, nil, 0)
+ if err != nil {
+ t.Errorf("ParseDir(%s): %v", path, err)
+ }
+}
+
func TestParseExpr(t *testing.T) {
// just kicking the tires:
// a valid arithmetic expression
diff --git a/src/go/parser/performance_test.go b/src/go/parser/performance_test.go
index f2732c0e2b..f81bcee969 100644
--- a/src/go/parser/performance_test.go
+++ b/src/go/parser/performance_test.go
@@ -6,14 +6,14 @@ package parser
import (
"go/token"
- "io/ioutil"
+ "os"
"testing"
)
var src = readFile("parser.go")
func readFile(filename string) []byte {
- data, err := ioutil.ReadFile(filename)
+ data, err := os.ReadFile(filename)
if err != nil {
panic(err)
}
diff --git a/src/go/parser/testdata/issue42951/not_a_file.go/invalid.go b/src/go/parser/testdata/issue42951/not_a_file.go/invalid.go
new file mode 100644
index 0000000000..bb698be11c
--- /dev/null
+++ b/src/go/parser/testdata/issue42951/not_a_file.go/invalid.go
@@ -0,0 +1 @@
+This file should not be parsed by ParseDir.
diff --git a/src/go/printer/performance_test.go b/src/go/printer/performance_test.go
index e23de3fbae..e655fa13ee 100644
--- a/src/go/printer/performance_test.go
+++ b/src/go/printer/performance_test.go
@@ -12,8 +12,8 @@ import (
"go/ast"
"go/parser"
"io"
- "io/ioutil"
"log"
+ "os"
"testing"
)
@@ -29,7 +29,7 @@ func testprint(out io.Writer, file *ast.File) {
func initialize() {
const filename = "testdata/parser.go"
- src, err := ioutil.ReadFile(filename)
+ src, err := os.ReadFile(filename)
if err != nil {
log.Fatalf("%s", err)
}
diff --git a/src/go/printer/printer_test.go b/src/go/printer/printer_test.go
index 3efa468d82..b15dcbf000 100644
--- a/src/go/printer/printer_test.go
+++ b/src/go/printer/printer_test.go
@@ -13,7 +13,7 @@ import (
"go/parser"
"go/token"
"io"
- "io/ioutil"
+ "os"
"path/filepath"
"testing"
"time"
@@ -119,7 +119,7 @@ func diff(aname, bname string, a, b []byte) error {
}
func runcheck(t *testing.T, source, golden string, mode checkMode) {
- src, err := ioutil.ReadFile(source)
+ src, err := os.ReadFile(source)
if err != nil {
t.Error(err)
return
@@ -133,14 +133,14 @@ func runcheck(t *testing.T, source, golden string, mode checkMode) {
// update golden files if necessary
if *update {
- if err := ioutil.WriteFile(golden, res, 0644); err != nil {
+ if err := os.WriteFile(golden, res, 0644); err != nil {
t.Error(err)
}
return
}
// get golden
- gld, err := ioutil.ReadFile(golden)
+ gld, err := os.ReadFile(golden)
if err != nil {
t.Error(err)
return
@@ -553,7 +553,7 @@ func TestBaseIndent(t *testing.T) {
// are not indented (because their values must not change) and make
// this test fail.
const filename = "printer.go"
- src, err := ioutil.ReadFile(filename)
+ src, err := os.ReadFile(filename)
if err != nil {
panic(err) // error in test
}
@@ -640,7 +640,7 @@ func (l *limitWriter) Write(buf []byte) (n int, err error) {
func TestWriteErrors(t *testing.T) {
t.Parallel()
const filename = "printer.go"
- src, err := ioutil.ReadFile(filename)
+ src, err := os.ReadFile(filename)
if err != nil {
panic(err) // error in test
}
diff --git a/src/go/scanner/scanner_test.go b/src/go/scanner/scanner_test.go
index 9d3bbbbb24..ab4c2dd962 100644
--- a/src/go/scanner/scanner_test.go
+++ b/src/go/scanner/scanner_test.go
@@ -6,7 +6,6 @@ package scanner
import (
"go/token"
- "io/ioutil"
"os"
"path/filepath"
"runtime"
@@ -893,7 +892,7 @@ func BenchmarkScan(b *testing.B) {
func BenchmarkScanFile(b *testing.B) {
b.StopTimer()
const filename = "scanner.go"
- src, err := ioutil.ReadFile(filename)
+ src, err := os.ReadFile(filename)
if err != nil {
panic(err)
}
diff --git a/src/go/types/check.go b/src/go/types/check.go
index 8d9e9a217e..f82c7fdf7b 100644
--- a/src/go/types/check.go
+++ b/src/go/types/check.go
@@ -46,6 +46,7 @@ type context struct {
scope *Scope // top-most scope for lookups
pos token.Pos // if valid, identifiers are looked up as if at position pos (used by Eval)
iota constant.Value // value of iota in a constant declaration; nil otherwise
+ errpos positioner // if set, identifier position of a constant with inherited initializer
sig *Signature // function signature if inside a function; nil otherwise
isPanic map[*ast.CallExpr]bool // set of panic call expressions (used for termination check)
hasLabel bool // set if a function makes use of labels (only ~1% of functions); unused outside functions
diff --git a/src/go/types/check_test.go b/src/go/types/check_test.go
index 37b287a20d..ce31dab68b 100644
--- a/src/go/types/check_test.go
+++ b/src/go/types/check_test.go
@@ -33,7 +33,7 @@ import (
"go/scanner"
"go/token"
"internal/testenv"
- "io/ioutil"
+ "os"
"path/filepath"
"regexp"
"strings"
@@ -153,7 +153,7 @@ func errMap(t *testing.T, testname string, files []*ast.File) map[string][]strin
for _, file := range files {
filename := fset.Position(file.Package).Filename
- src, err := ioutil.ReadFile(filename)
+ src, err := os.ReadFile(filename)
if err != nil {
t.Fatalf("%s: could not read %s", testname, filename)
}
@@ -329,17 +329,17 @@ func TestFixedBugs(t *testing.T) { testDir(t, "fixedbugs") }
func testDir(t *testing.T, dir string) {
testenv.MustHaveGoBuild(t)
- fis, err := ioutil.ReadDir(dir)
+ dirs, err := os.ReadDir(dir)
if err != nil {
t.Fatal(err)
}
- for _, fi := range fis {
- testname := filepath.Base(fi.Name())
+ for _, d := range dirs {
+ testname := filepath.Base(d.Name())
testname = strings.TrimSuffix(testname, filepath.Ext(testname))
t.Run(testname, func(t *testing.T) {
- filename := filepath.Join(dir, fi.Name())
- if fi.IsDir() {
+ filename := filepath.Join(dir, d.Name())
+ if d.IsDir() {
t.Errorf("skipped directory %q", filename)
return
}
diff --git a/src/go/types/decl.go b/src/go/types/decl.go
index cd610036b8..8baf223322 100644
--- a/src/go/types/decl.go
+++ b/src/go/types/decl.go
@@ -183,7 +183,7 @@ func (check *Checker) objDecl(obj Object, def *Named) {
switch obj := obj.(type) {
case *Const:
check.decl = d // new package-level const decl
- check.constDecl(obj, d.typ, d.init)
+ check.constDecl(obj, d.typ, d.init, d.inherited)
case *Var:
check.decl = d // new package-level var decl
check.varDecl(obj, d.lhs, d.typ, d.init)
@@ -388,10 +388,11 @@ type (
importDecl struct{ spec *ast.ImportSpec }
constDecl struct {
- spec *ast.ValueSpec
- iota int
- typ ast.Expr
- init []ast.Expr
+ spec *ast.ValueSpec
+ iota int
+ typ ast.Expr
+ init []ast.Expr
+ inherited bool
}
varDecl struct{ spec *ast.ValueSpec }
typeDecl struct{ spec *ast.TypeSpec }
@@ -424,14 +425,17 @@ func (check *Checker) walkDecl(d ast.Decl, f func(decl)) {
switch d.Tok {
case token.CONST:
// determine which initialization expressions to use
+ inherited := true
switch {
case s.Type != nil || len(s.Values) > 0:
last = s
+ inherited = false
case last == nil:
last = new(ast.ValueSpec) // make sure last exists
+ inherited = false
}
check.arityMatch(s, last)
- f(constDecl{spec: s, iota: iota, init: last.Values, typ: last.Type})
+ f(constDecl{spec: s, iota: iota, typ: last.Type, init: last.Values, inherited: inherited})
case token.VAR:
check.arityMatch(s, nil)
f(varDecl{s})
@@ -451,12 +455,16 @@ func (check *Checker) walkDecl(d ast.Decl, f func(decl)) {
}
}
-func (check *Checker) constDecl(obj *Const, typ, init ast.Expr) {
+func (check *Checker) constDecl(obj *Const, typ, init ast.Expr, inherited bool) {
assert(obj.typ == nil)
// use the correct value of iota
- defer func(iota constant.Value) { check.iota = iota }(check.iota)
+ defer func(iota constant.Value, errpos positioner) {
+ check.iota = iota
+ check.errpos = errpos
+ }(check.iota, check.errpos)
check.iota = obj.val
+ check.errpos = nil
// provide valid constant value under all circumstances
obj.val = constant.MakeUnknown()
@@ -479,6 +487,15 @@ func (check *Checker) constDecl(obj *Const, typ, init ast.Expr) {
// check initialization
var x operand
if init != nil {
+ if inherited {
+ // The initialization expression is inherited from a previous
+ // constant declaration, and (error) positions refer to that
+ // expression and not the current constant declaration. Use
+ // the constant identifier position for any errors during
+ // init expression evaluation since that is all we have
+ // (see issues #42991, #42992).
+ check.errpos = atPos(obj.pos)
+ }
check.expr(&x, init)
}
check.initConst(obj, &x)
@@ -756,7 +773,7 @@ func (check *Checker) declStmt(d ast.Decl) {
init = d.init[i]
}
- check.constDecl(obj, d.typ, init)
+ check.constDecl(obj, d.typ, init, d.inherited)
}
// process function literals in init expressions before scope changes
diff --git a/src/go/types/errors.go b/src/go/types/errors.go
index c9c475e469..a2195011f0 100644
--- a/src/go/types/errors.go
+++ b/src/go/types/errors.go
@@ -89,6 +89,18 @@ func (check *Checker) err(err error) {
return
}
+ if check.errpos != nil && isInternal {
+ // If we have an internal error and the errpos override is set, use it to
+ // augment our error positioning.
+ // TODO(rFindley) we may also want to augment the error message and refer
+ // to the position (pos) in the original expression.
+ span := spanOf(check.errpos)
+ e.Pos = span.pos
+ e.go116start = span.start
+ e.go116end = span.end
+ err = e
+ }
+
if check.firstErr == nil {
check.firstErr = err
}
@@ -111,15 +123,15 @@ func (check *Checker) err(err error) {
}
func (check *Checker) newError(at positioner, code errorCode, soft bool, msg string) error {
- ext := spanOf(at)
+ span := spanOf(at)
return Error{
Fset: check.fset,
- Pos: ext.pos,
+ Pos: span.pos,
Msg: msg,
Soft: soft,
go116code: code,
- go116start: ext.start,
- go116end: ext.end,
+ go116start: span.start,
+ go116end: span.end,
}
}
diff --git a/src/go/types/hilbert_test.go b/src/go/types/hilbert_test.go
index 9783ce6dc9..77954d2f8b 100644
--- a/src/go/types/hilbert_test.go
+++ b/src/go/types/hilbert_test.go
@@ -12,7 +12,7 @@ import (
"go/importer"
"go/parser"
"go/token"
- "io/ioutil"
+ "os"
"testing"
. "go/types"
@@ -27,7 +27,7 @@ func TestHilbert(t *testing.T) {
// generate source
src := program(*H, *out)
if *out != "" {
- ioutil.WriteFile(*out, src, 0666)
+ os.WriteFile(*out, src, 0666)
return
}
diff --git a/src/go/types/issues_test.go b/src/go/types/issues_test.go
index f59f905397..34850eb034 100644
--- a/src/go/types/issues_test.go
+++ b/src/go/types/issues_test.go
@@ -12,6 +12,7 @@ import (
"go/ast"
"go/importer"
"go/parser"
+ "go/token"
"internal/testenv"
"sort"
"strings"
@@ -523,3 +524,28 @@ func TestIssue34921(t *testing.T) {
pkg = res // res is imported by the next package in this test
}
}
+
+func TestIssue43088(t *testing.T) {
+ // type T1 struct {
+ // _ T2
+ // }
+ //
+ // type T2 struct {
+ // _ struct {
+ // _ T2
+ // }
+ // }
+ n1 := NewTypeName(token.NoPos, nil, "T1", nil)
+ T1 := NewNamed(n1, nil, nil)
+ n2 := NewTypeName(token.NoPos, nil, "T2", nil)
+ T2 := NewNamed(n2, nil, nil)
+ s1 := NewStruct([]*Var{NewField(token.NoPos, nil, "_", T2, false)}, nil)
+ T1.SetUnderlying(s1)
+ s2 := NewStruct([]*Var{NewField(token.NoPos, nil, "_", T2, false)}, nil)
+ s3 := NewStruct([]*Var{NewField(token.NoPos, nil, "_", s2, false)}, nil)
+ T2.SetUnderlying(s3)
+
+ // These calls must terminate (no endless recursion).
+ Comparable(T1)
+ Comparable(T2)
+}
diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go
index a139a4eb09..d580796d98 100644
--- a/src/go/types/predicates.go
+++ b/src/go/types/predicates.go
@@ -82,6 +82,18 @@ func IsInterface(typ Type) bool {
// Comparable reports whether values of type T are comparable.
func Comparable(T Type) bool {
+ return comparable(T, nil)
+}
+
+func comparable(T Type, seen map[Type]bool) bool {
+ if seen[T] {
+ return true
+ }
+ if seen == nil {
+ seen = make(map[Type]bool)
+ }
+ seen[T] = true
+
switch t := T.Underlying().(type) {
case *Basic:
// assume invalid types to be comparable
@@ -91,13 +103,13 @@ func Comparable(T Type) bool {
return true
case *Struct:
for _, f := range t.fields {
- if !Comparable(f.typ) {
+ if !comparable(f.typ, seen) {
return false
}
}
return true
case *Array:
- return Comparable(t.elem)
+ return comparable(t.elem, seen)
}
return false
}
diff --git a/src/go/types/resolver.go b/src/go/types/resolver.go
index 4092d55b4e..b637f8b8ca 100644
--- a/src/go/types/resolver.go
+++ b/src/go/types/resolver.go
@@ -17,12 +17,13 @@ import (
// A declInfo describes a package-level const, type, var, or func declaration.
type declInfo struct {
- file *Scope // scope of file containing this declaration
- lhs []*Var // lhs of n:1 variable declarations, or nil
- typ ast.Expr // type, or nil
- init ast.Expr // init/orig expression, or nil
- fdecl *ast.FuncDecl // func declaration, or nil
- alias bool // type alias declaration
+ file *Scope // scope of file containing this declaration
+ lhs []*Var // lhs of n:1 variable declarations, or nil
+ typ ast.Expr // type, or nil
+ init ast.Expr // init/orig expression, or nil
+ inherited bool // if set, the init expression is inherited from a previous constant declaration
+ fdecl *ast.FuncDecl // func declaration, or nil
+ alias bool // type alias declaration
// The deps field tracks initialization expression dependencies.
deps map[Object]bool // lazily initialized
@@ -323,7 +324,7 @@ func (check *Checker) collectObjects() {
init = d.init[i]
}
- d := &declInfo{file: fileScope, typ: d.typ, init: init}
+ d := &declInfo{file: fileScope, typ: d.typ, init: init, inherited: d.inherited}
check.declarePkgObj(name, obj, d)
}
diff --git a/src/go/types/stdlib_test.go b/src/go/types/stdlib_test.go
index 669e7bec20..96011c54ad 100644
--- a/src/go/types/stdlib_test.go
+++ b/src/go/types/stdlib_test.go
@@ -16,7 +16,6 @@ import (
"go/scanner"
"go/token"
"internal/testenv"
- "io/ioutil"
"os"
"path/filepath"
"runtime"
@@ -87,7 +86,7 @@ func firstComment(filename string) string {
}
func testTestDir(t *testing.T, path string, ignore ...string) {
- files, err := ioutil.ReadDir(path)
+ files, err := os.ReadDir(path)
if err != nil {
t.Fatal(err)
}
@@ -156,6 +155,7 @@ func TestStdTest(t *testing.T) {
testTestDir(t, filepath.Join(runtime.GOROOT(), "test"),
"cmplxdivide.go", // also needs file cmplxdivide1.go - ignore
"directive.go", // tests compiler rejection of bad directive placement - ignore
+ "linkname2.go", // go/types doesn't check validity of //go:xxx directives
)
}
@@ -297,7 +297,7 @@ func (w *walker) walk(dir string) {
return
}
- fis, err := ioutil.ReadDir(dir)
+ files, err := os.ReadDir(dir)
if err != nil {
w.errh(err)
return
@@ -317,9 +317,9 @@ func (w *walker) walk(dir string) {
}
// traverse subdirectories, but don't walk into testdata
- for _, fi := range fis {
- if fi.IsDir() && fi.Name() != "testdata" {
- w.walk(filepath.Join(dir, fi.Name()))
+ for _, f := range files {
+ if f.IsDir() && f.Name() != "testdata" {
+ w.walk(filepath.Join(dir, f.Name()))
}
}
}
diff --git a/src/go/types/testdata/constdecl.src b/src/go/types/testdata/constdecl.src
index c2f40ed6e6..680c85aff3 100644
--- a/src/go/types/testdata/constdecl.src
+++ b/src/go/types/testdata/constdecl.src
@@ -107,4 +107,35 @@ func _() {
const x, y, z = 0, 1, unsafe.Sizeof(func() { _ = x /* ERROR "undeclared name" */ + y /* ERROR "undeclared name" */ + z /* ERROR "undeclared name" */ })
}
+// Test cases for errors in inherited constant initialization expressions.
+// Errors related to inherited initialization expressions must appear at
+// the constant identifier being declared, not at the original expression
+// (issues #42991, #42992).
+const (
+ _ byte = 255 + iota
+ /* some gap */
+ _ // ERROR overflows
+ /* some gap */
+ /* some gap */ _ /* ERROR overflows */; _ /* ERROR overflows */
+ /* some gap */
+ _ = 255 + iota
+ _ = byte /* ERROR overflows */ (255) + iota
+ _ /* ERROR overflows */
+)
+
+// Test cases from issue.
+const (
+ ok = byte(iota + 253)
+ bad
+ barn
+ bard // ERROR cannot convert
+)
+
+const (
+ c = len([1 - iota]int{})
+ d
+ e // ERROR invalid array length
+ f // ERROR invalid array length
+)
+
// TODO(gri) move extra tests from testdata/const0.src into here
diff --git a/src/hash/crc32/gen_const_ppc64le.go b/src/hash/crc32/gen_const_ppc64le.go
index bfb3b3a227..d7af018af4 100644
--- a/src/hash/crc32/gen_const_ppc64le.go
+++ b/src/hash/crc32/gen_const_ppc64le.go
@@ -27,7 +27,7 @@ package main
import (
"bytes"
"fmt"
- "io/ioutil"
+ "os"
)
var blocking = 32 * 1024
@@ -103,7 +103,7 @@ func main() {
genCrc32ConstTable(w, 0xeb31d82e, "Koop")
b := w.Bytes()
- err := ioutil.WriteFile("crc32_table_ppc64le.s", b, 0666)
+ err := os.WriteFile("crc32_table_ppc64le.s", b, 0666)
if err != nil {
fmt.Printf("can't write output: %s\n", err)
}
diff --git a/src/html/template/escape_test.go b/src/html/template/escape_test.go
index b6031ea60a..fbc84a7592 100644
--- a/src/html/template/escape_test.go
+++ b/src/html/template/escape_test.go
@@ -243,7 +243,7 @@ func TestEscape(t *testing.T) {
{
"badMarshaler",
``,
- ``,
+ ``,
},
{
"jsMarshaler",
diff --git a/src/html/template/examplefiles_test.go b/src/html/template/examplefiles_test.go
index 60518aee9e..5eb2597464 100644
--- a/src/html/template/examplefiles_test.go
+++ b/src/html/template/examplefiles_test.go
@@ -6,7 +6,6 @@ package template_test
import (
"io"
- "io/ioutil"
"log"
"os"
"path/filepath"
@@ -20,7 +19,7 @@ type templateFile struct {
}
func createTestDir(files []templateFile) string {
- dir, err := ioutil.TempDir("", "template")
+ dir, err := os.MkdirTemp("", "template")
if err != nil {
log.Fatal(err)
}
diff --git a/src/html/template/template.go b/src/html/template/template.go
index bc960afe5f..69312d36fd 100644
--- a/src/html/template/template.go
+++ b/src/html/template/template.go
@@ -8,7 +8,7 @@ import (
"fmt"
"io"
"io/fs"
- "io/ioutil"
+ "os"
"path"
"path/filepath"
"sync"
@@ -523,7 +523,7 @@ func parseFS(t *Template, fsys fs.FS, patterns []string) (*Template, error) {
func readFileOS(file string) (name string, b []byte, err error) {
name = filepath.Base(file)
- b, err = ioutil.ReadFile(file)
+ b, err = os.ReadFile(file)
return
}
diff --git a/src/image/color/palette/gen.go b/src/image/color/palette/gen.go
index f8587db8f3..3243e53981 100644
--- a/src/image/color/palette/gen.go
+++ b/src/image/color/palette/gen.go
@@ -15,8 +15,8 @@ import (
"fmt"
"go/format"
"io"
- "io/ioutil"
"log"
+ "os"
)
var filename = flag.String("output", "palette.go", "output file name")
@@ -43,7 +43,7 @@ func main() {
if err != nil {
log.Fatal(err)
}
- err = ioutil.WriteFile(*filename, data, 0644)
+ err = os.WriteFile(*filename, data, 0644)
if err != nil {
log.Fatal(err)
}
diff --git a/src/image/gif/reader_test.go b/src/image/gif/reader_test.go
index 29f47b6c08..5eec5ecb4a 100644
--- a/src/image/gif/reader_test.go
+++ b/src/image/gif/reader_test.go
@@ -11,7 +11,7 @@ import (
"image/color"
"image/color/palette"
"io"
- "io/ioutil"
+ "os"
"reflect"
"runtime"
"runtime/debug"
@@ -424,7 +424,7 @@ func TestDecodeMemoryConsumption(t *testing.T) {
}
func BenchmarkDecode(b *testing.B) {
- data, err := ioutil.ReadFile("../testdata/video-001.gif")
+ data, err := os.ReadFile("../testdata/video-001.gif")
if err != nil {
b.Fatal(err)
}
diff --git a/src/image/internal/imageutil/gen.go b/src/image/internal/imageutil/gen.go
index bc85c512f9..36de5dc9cc 100644
--- a/src/image/internal/imageutil/gen.go
+++ b/src/image/internal/imageutil/gen.go
@@ -11,7 +11,6 @@ import (
"flag"
"fmt"
"go/format"
- "io/ioutil"
"log"
"os"
)
@@ -36,7 +35,7 @@ func main() {
if err != nil {
log.Fatal(err)
}
- if err := ioutil.WriteFile("impl.go", out, 0660); err != nil {
+ if err := os.WriteFile("impl.go", out, 0660); err != nil {
log.Fatal(err)
}
}
diff --git a/src/image/jpeg/reader_test.go b/src/image/jpeg/reader_test.go
index 1e2798c945..bf07fadede 100644
--- a/src/image/jpeg/reader_test.go
+++ b/src/image/jpeg/reader_test.go
@@ -11,7 +11,6 @@ import (
"image"
"image/color"
"io"
- "io/ioutil"
"math/rand"
"os"
"strings"
@@ -118,7 +117,7 @@ func (r *eofReader) Read(b []byte) (n int, err error) {
func TestDecodeEOF(t *testing.T) {
// Check that if reader returns final data and EOF at same time, jpeg handles it.
- data, err := ioutil.ReadFile("../testdata/video-001.jpeg")
+ data, err := os.ReadFile("../testdata/video-001.jpeg")
if err != nil {
t.Fatal(err)
}
@@ -189,7 +188,7 @@ func pixString(pix []byte, stride, x, y int) string {
}
func TestTruncatedSOSDataDoesntPanic(t *testing.T) {
- b, err := ioutil.ReadFile("../testdata/video-005.gray.q50.jpeg")
+ b, err := os.ReadFile("../testdata/video-005.gray.q50.jpeg")
if err != nil {
t.Fatal(err)
}
@@ -493,7 +492,7 @@ func TestExtraneousData(t *testing.T) {
}
func benchmarkDecode(b *testing.B, filename string) {
- data, err := ioutil.ReadFile(filename)
+ data, err := os.ReadFile(filename)
if err != nil {
b.Fatal(err)
}
diff --git a/src/image/png/reader_test.go b/src/image/png/reader_test.go
index 22c704e5cb..3937685294 100644
--- a/src/image/png/reader_test.go
+++ b/src/image/png/reader_test.go
@@ -11,7 +11,6 @@ import (
"image"
"image/color"
"io"
- "io/ioutil"
"os"
"reflect"
"strings"
@@ -785,7 +784,7 @@ func TestDimensionOverflow(t *testing.T) {
}
func benchmarkDecode(b *testing.B, filename string, bytesPerPixel int) {
- data, err := ioutil.ReadFile(filename)
+ data, err := os.ReadFile(filename)
if err != nil {
b.Fatal(err)
}
diff --git a/src/index/suffixarray/gen.go b/src/index/suffixarray/gen.go
index 8c3de553c9..94184d71b6 100644
--- a/src/index/suffixarray/gen.go
+++ b/src/index/suffixarray/gen.go
@@ -11,8 +11,8 @@ package main
import (
"bytes"
- "io/ioutil"
"log"
+ "os"
"strings"
)
@@ -20,7 +20,7 @@ func main() {
log.SetPrefix("gen: ")
log.SetFlags(0)
- data, err := ioutil.ReadFile("sais.go")
+ data, err := os.ReadFile("sais.go")
if err != nil {
log.Fatal(err)
}
@@ -64,7 +64,7 @@ func main() {
}
}
- if err := ioutil.WriteFile("sais2.go", buf.Bytes(), 0666); err != nil {
+ if err := os.WriteFile("sais2.go", buf.Bytes(), 0666); err != nil {
log.Fatal(err)
}
}
diff --git a/src/index/suffixarray/suffixarray_test.go b/src/index/suffixarray/suffixarray_test.go
index b6a81123b7..44c5041535 100644
--- a/src/index/suffixarray/suffixarray_test.go
+++ b/src/index/suffixarray/suffixarray_test.go
@@ -8,8 +8,8 @@ import (
"bytes"
"fmt"
"io/fs"
- "io/ioutil"
"math/rand"
+ "os"
"path/filepath"
"regexp"
"sort"
@@ -498,14 +498,14 @@ func makeText(name string) ([]byte, error) {
switch name {
case "opticks":
var err error
- data, err = ioutil.ReadFile("../../testdata/Isaac.Newton-Opticks.txt")
+ data, err = os.ReadFile("../../testdata/Isaac.Newton-Opticks.txt")
if err != nil {
return nil, err
}
case "go":
- err := filepath.Walk("../..", func(path string, info fs.FileInfo, err error) error {
+ err := filepath.WalkDir("../..", func(path string, info fs.DirEntry, err error) error {
if err == nil && strings.HasSuffix(path, ".go") && !info.IsDir() {
- file, err := ioutil.ReadFile(path)
+ file, err := os.ReadFile(path)
if err != nil {
return err
}
diff --git a/src/internal/cpu/cpu_arm64.go b/src/internal/cpu/cpu_arm64.go
index 4e9ea8ca96..f64d9e4dd3 100644
--- a/src/internal/cpu/cpu_arm64.go
+++ b/src/internal/cpu/cpu_arm64.go
@@ -6,21 +6,6 @@ package cpu
const CacheLinePadSize = 64
-// HWCap may be initialized by archauxv and
-// should not be changed after it was initialized.
-var HWCap uint
-
-// HWCAP bits. These are exposed by Linux.
-const (
- hwcap_AES = 1 << 3
- hwcap_PMULL = 1 << 4
- hwcap_SHA1 = 1 << 5
- hwcap_SHA2 = 1 << 6
- hwcap_CRC32 = 1 << 7
- hwcap_ATOMICS = 1 << 8
- hwcap_CPUID = 1 << 11
-)
-
func doinit() {
options = []option{
{Name: "aes", Feature: &ARM64.HasAES},
@@ -34,86 +19,8 @@ func doinit() {
{Name: "isZeus", Feature: &ARM64.IsZeus},
}
- switch GOOS {
- case "linux", "android":
- // HWCap was populated by the runtime from the auxillary vector.
- // Use HWCap information since reading aarch64 system registers
- // is not supported in user space on older linux kernels.
- ARM64.HasAES = isSet(HWCap, hwcap_AES)
- ARM64.HasPMULL = isSet(HWCap, hwcap_PMULL)
- ARM64.HasSHA1 = isSet(HWCap, hwcap_SHA1)
- ARM64.HasSHA2 = isSet(HWCap, hwcap_SHA2)
- ARM64.HasCRC32 = isSet(HWCap, hwcap_CRC32)
- ARM64.HasCPUID = isSet(HWCap, hwcap_CPUID)
-
- // The Samsung S9+ kernel reports support for atomics, but not all cores
- // actually support them, resulting in SIGILL. See issue #28431.
- // TODO(elias.naur): Only disable the optimization on bad chipsets on android.
- ARM64.HasATOMICS = isSet(HWCap, hwcap_ATOMICS) && GOOS != "android"
-
- // Check to see if executing on a NeoverseN1 and in order to do that,
- // check the AUXV for the CPUID bit. The getMIDR function executes an
- // instruction which would normally be an illegal instruction, but it's
- // trapped by the kernel, the value sanitized and then returned. Without
- // the CPUID bit the kernel will not trap the instruction and the process
- // will be terminated with SIGILL.
- if ARM64.HasCPUID {
- midr := getMIDR()
- part_num := uint16((midr >> 4) & 0xfff)
- implementor := byte((midr >> 24) & 0xff)
-
- if implementor == 'A' && part_num == 0xd0c {
- ARM64.IsNeoverseN1 = true
- }
- if implementor == 'A' && part_num == 0xd40 {
- ARM64.IsZeus = true
- }
- }
-
- case "freebsd":
- // Retrieve info from system register ID_AA64ISAR0_EL1.
- isar0 := getisar0()
-
- // ID_AA64ISAR0_EL1
- switch extractBits(isar0, 4, 7) {
- case 1:
- ARM64.HasAES = true
- case 2:
- ARM64.HasAES = true
- ARM64.HasPMULL = true
- }
-
- switch extractBits(isar0, 8, 11) {
- case 1:
- ARM64.HasSHA1 = true
- }
-
- switch extractBits(isar0, 12, 15) {
- case 1, 2:
- ARM64.HasSHA2 = true
- }
-
- switch extractBits(isar0, 16, 19) {
- case 1:
- ARM64.HasCRC32 = true
- }
-
- switch extractBits(isar0, 20, 23) {
- case 2:
- ARM64.HasATOMICS = true
- }
- default:
- // Other operating systems do not support reading HWCap from auxillary vector
- // or reading privileged aarch64 system registers in user space.
- }
-}
-
-func extractBits(data uint64, start, end uint) uint {
- return (uint)(data>>start) & ((1 << (end - start + 1)) - 1)
-}
-
-func isSet(hwc uint, value uint) bool {
- return hwc&value != 0
+ // arm64 uses different ways to detect CPU features at runtime depending on the operating system.
+ osInit()
}
func getisar0() uint64
diff --git a/src/internal/cpu/cpu_linux.go b/src/internal/cpu/cpu_arm64_android.go
similarity index 75%
rename from src/internal/cpu/cpu_linux.go
rename to src/internal/cpu/cpu_arm64_android.go
index ec0b84c510..3c9e57c52a 100644
--- a/src/internal/cpu/cpu_linux.go
+++ b/src/internal/cpu/cpu_arm64_android.go
@@ -2,8 +2,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build !android
+// +build arm64
package cpu
-const GOOS = "linux"
+func osInit() {
+ hwcapInit("android")
+}
diff --git a/src/internal/cpu/cpu_arm64_darwin.go b/src/internal/cpu/cpu_arm64_darwin.go
new file mode 100644
index 0000000000..e094b97f97
--- /dev/null
+++ b/src/internal/cpu/cpu_arm64_darwin.go
@@ -0,0 +1,34 @@
+// Copyright 2020 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 arm64
+// +build darwin
+// +build !ios
+
+package cpu
+
+func osInit() {
+ ARM64.HasATOMICS = sysctlEnabled([]byte("hw.optional.armv8_1_atomics\x00"))
+ ARM64.HasCRC32 = sysctlEnabled([]byte("hw.optional.armv8_crc32\x00"))
+
+ // There are no hw.optional sysctl values for the below features on Mac OS 11.0
+ // to detect their supported state dynamically. Assume the CPU features that
+ // Apple Silicon M1 supports to be available as a minimal set of features
+ // to all Go programs running on darwin/arm64.
+ ARM64.HasAES = true
+ ARM64.HasPMULL = true
+ ARM64.HasSHA1 = true
+ ARM64.HasSHA2 = true
+}
+
+//go:noescape
+func getsysctlbyname(name []byte) (int32, int32)
+
+func sysctlEnabled(name []byte) bool {
+ ret, value := getsysctlbyname(name)
+ if ret < 0 {
+ return false
+ }
+ return value > 0
+}
diff --git a/src/internal/cpu/cpu_arm64_freebsd.go b/src/internal/cpu/cpu_arm64_freebsd.go
new file mode 100644
index 0000000000..9de2005c2e
--- /dev/null
+++ b/src/internal/cpu/cpu_arm64_freebsd.go
@@ -0,0 +1,45 @@
+// Copyright 2020 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 arm64
+
+package cpu
+
+func osInit() {
+ // Retrieve info from system register ID_AA64ISAR0_EL1.
+ isar0 := getisar0()
+
+ // ID_AA64ISAR0_EL1
+ switch extractBits(isar0, 4, 7) {
+ case 1:
+ ARM64.HasAES = true
+ case 2:
+ ARM64.HasAES = true
+ ARM64.HasPMULL = true
+ }
+
+ switch extractBits(isar0, 8, 11) {
+ case 1:
+ ARM64.HasSHA1 = true
+ }
+
+ switch extractBits(isar0, 12, 15) {
+ case 1, 2:
+ ARM64.HasSHA2 = true
+ }
+
+ switch extractBits(isar0, 16, 19) {
+ case 1:
+ ARM64.HasCRC32 = true
+ }
+
+ switch extractBits(isar0, 20, 23) {
+ case 2:
+ ARM64.HasATOMICS = true
+ }
+}
+
+func extractBits(data uint64, start, end uint) uint {
+ return (uint)(data>>start) & ((1 << (end - start + 1)) - 1)
+}
diff --git a/src/internal/cpu/cpu_arm64_hwcap.go b/src/internal/cpu/cpu_arm64_hwcap.go
new file mode 100644
index 0000000000..fdaf43e1a2
--- /dev/null
+++ b/src/internal/cpu/cpu_arm64_hwcap.go
@@ -0,0 +1,63 @@
+// Copyright 2020 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 arm64
+// +build linux
+
+package cpu
+
+// HWCap may be initialized by archauxv and
+// should not be changed after it was initialized.
+var HWCap uint
+
+// HWCAP bits. These are exposed by Linux.
+const (
+ hwcap_AES = 1 << 3
+ hwcap_PMULL = 1 << 4
+ hwcap_SHA1 = 1 << 5
+ hwcap_SHA2 = 1 << 6
+ hwcap_CRC32 = 1 << 7
+ hwcap_ATOMICS = 1 << 8
+ hwcap_CPUID = 1 << 11
+)
+
+func hwcapInit(os string) {
+ // HWCap was populated by the runtime from the auxiliary vector.
+ // Use HWCap information since reading aarch64 system registers
+ // is not supported in user space on older linux kernels.
+ ARM64.HasAES = isSet(HWCap, hwcap_AES)
+ ARM64.HasPMULL = isSet(HWCap, hwcap_PMULL)
+ ARM64.HasSHA1 = isSet(HWCap, hwcap_SHA1)
+ ARM64.HasSHA2 = isSet(HWCap, hwcap_SHA2)
+ ARM64.HasCRC32 = isSet(HWCap, hwcap_CRC32)
+ ARM64.HasCPUID = isSet(HWCap, hwcap_CPUID)
+
+ // The Samsung S9+ kernel reports support for atomics, but not all cores
+ // actually support them, resulting in SIGILL. See issue #28431.
+ // TODO(elias.naur): Only disable the optimization on bad chipsets on android.
+ ARM64.HasATOMICS = isSet(HWCap, hwcap_ATOMICS) && os != "android"
+
+ // Check to see if executing on a NeoverseN1 and in order to do that,
+ // check the AUXV for the CPUID bit. The getMIDR function executes an
+ // instruction which would normally be an illegal instruction, but it's
+ // trapped by the kernel, the value sanitized and then returned. Without
+ // the CPUID bit the kernel will not trap the instruction and the process
+ // will be terminated with SIGILL.
+ if ARM64.HasCPUID {
+ midr := getMIDR()
+ part_num := uint16((midr >> 4) & 0xfff)
+ implementor := byte((midr >> 24) & 0xff)
+
+ if implementor == 'A' && part_num == 0xd0c {
+ ARM64.IsNeoverseN1 = true
+ }
+ if implementor == 'A' && part_num == 0xd40 {
+ ARM64.IsZeus = true
+ }
+ }
+}
+
+func isSet(hwc uint, value uint) bool {
+ return hwc&value != 0
+}
diff --git a/src/internal/cpu/cpu_other.go b/src/internal/cpu/cpu_arm64_linux.go
similarity index 73%
rename from src/internal/cpu/cpu_other.go
rename to src/internal/cpu/cpu_arm64_linux.go
index 8a15fbe79d..2f7411ff1e 100644
--- a/src/internal/cpu/cpu_other.go
+++ b/src/internal/cpu/cpu_arm64_linux.go
@@ -2,10 +2,12 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build !linux
-// +build !freebsd
+// +build arm64
+// +build linux
// +build !android
package cpu
-const GOOS = "other"
+func osInit() {
+ hwcapInit("linux")
+}
diff --git a/src/internal/cpu/cpu_arm64_other.go b/src/internal/cpu/cpu_arm64_other.go
new file mode 100644
index 0000000000..f191db28d2
--- /dev/null
+++ b/src/internal/cpu/cpu_arm64_other.go
@@ -0,0 +1,17 @@
+// Copyright 2020 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 arm64
+// +build !linux
+// +build !freebsd
+// +build !android
+// +build !darwin ios
+
+package cpu
+
+func osInit() {
+ // Other operating systems do not support reading HWCap from auxiliary vector,
+ // reading privileged aarch64 system registers or sysctl in user space to detect
+ // CPU features at runtime.
+}
diff --git a/src/internal/cpu/cpu_s390x_test.go b/src/internal/cpu/cpu_s390x_test.go
index d910bbe695..ad86858db0 100644
--- a/src/internal/cpu/cpu_s390x_test.go
+++ b/src/internal/cpu/cpu_s390x_test.go
@@ -7,13 +7,13 @@ package cpu_test
import (
"errors"
. "internal/cpu"
- "io/ioutil"
+ "os"
"regexp"
"testing"
)
func getFeatureList() ([]string, error) {
- cpuinfo, err := ioutil.ReadFile("/proc/cpuinfo")
+ cpuinfo, err := os.ReadFile("/proc/cpuinfo")
if err != nil {
return nil, err
}
diff --git a/src/internal/cpu/cpu_test.go b/src/internal/cpu/cpu_test.go
index 919bbd5ed7..2de7365732 100644
--- a/src/internal/cpu/cpu_test.go
+++ b/src/internal/cpu/cpu_test.go
@@ -18,7 +18,7 @@ func TestMinimalFeatures(t *testing.T) {
// TODO: maybe do MustSupportFeatureDectection(t) ?
if runtime.GOARCH == "arm64" {
switch runtime.GOOS {
- case "linux", "android":
+ case "linux", "android", "darwin":
default:
t.Skipf("%s/%s is not supported", runtime.GOOS, runtime.GOARCH)
}
@@ -38,10 +38,7 @@ func MustHaveDebugOptionsSupport(t *testing.T) {
}
func MustSupportFeatureDectection(t *testing.T) {
- if runtime.GOOS == "darwin" && runtime.GOARCH == "arm64" {
- t.Skipf("CPU feature detection is not supported on %s/%s", runtime.GOOS, runtime.GOARCH)
- }
- // TODO: maybe there are other platforms?
+ // TODO: add platforms that do not have CPU feature detection support.
}
func runDebugOptionsTest(t *testing.T, test string, options string) {
diff --git a/src/internal/cpu/cpu_x86.go b/src/internal/cpu/cpu_x86.go
index fb414adaf8..ba6bf69034 100644
--- a/src/internal/cpu/cpu_x86.go
+++ b/src/internal/cpu/cpu_x86.go
@@ -75,13 +75,22 @@ func doinit() {
X86.HasSSE3 = isSet(ecx1, cpuid_SSE3)
X86.HasPCLMULQDQ = isSet(ecx1, cpuid_PCLMULQDQ)
X86.HasSSSE3 = isSet(ecx1, cpuid_SSSE3)
- X86.HasFMA = isSet(ecx1, cpuid_FMA)
X86.HasSSE41 = isSet(ecx1, cpuid_SSE41)
X86.HasSSE42 = isSet(ecx1, cpuid_SSE42)
X86.HasPOPCNT = isSet(ecx1, cpuid_POPCNT)
X86.HasAES = isSet(ecx1, cpuid_AES)
+
+ // OSXSAVE can be false when using older Operating Systems
+ // or when explicitly disabled on newer Operating Systems by
+ // e.g. setting the xsavedisable boot option on Windows 10.
X86.HasOSXSAVE = isSet(ecx1, cpuid_OSXSAVE)
+ // The FMA instruction set extension only has VEX prefixed instructions.
+ // VEX prefixed instructions require OSXSAVE to be enabled.
+ // See Intel 64 and IA-32 Architecture Software Developer’s Manual Volume 2
+ // Section 2.4 "AVX and SSE Instruction Exception Specification"
+ X86.HasFMA = isSet(ecx1, cpuid_FMA) && X86.HasOSXSAVE
+
osSupportsAVX := false
// For XGETBV, OSXSAVE bit is required and sufficient.
if X86.HasOSXSAVE {
diff --git a/src/internal/obscuretestdata/obscuretestdata.go b/src/internal/obscuretestdata/obscuretestdata.go
index 06cd1df22c..5ea2cdf5d1 100644
--- a/src/internal/obscuretestdata/obscuretestdata.go
+++ b/src/internal/obscuretestdata/obscuretestdata.go
@@ -10,7 +10,6 @@ package obscuretestdata
import (
"encoding/base64"
"io"
- "io/ioutil"
"os"
)
@@ -24,7 +23,7 @@ func DecodeToTempFile(name string) (path string, err error) {
}
defer f.Close()
- tmp, err := ioutil.TempFile("", "obscuretestdata-decoded-")
+ tmp, err := os.CreateTemp("", "obscuretestdata-decoded-")
if err != nil {
return "", err
}
diff --git a/src/internal/poll/read_test.go b/src/internal/poll/read_test.go
index 2d4ef97da0..598a52ee44 100644
--- a/src/internal/poll/read_test.go
+++ b/src/internal/poll/read_test.go
@@ -5,7 +5,6 @@
package poll_test
import (
- "io/ioutil"
"os"
"runtime"
"sync"
@@ -22,7 +21,7 @@ func TestRead(t *testing.T) {
go func(p string) {
defer wg.Done()
for i := 0; i < 100; i++ {
- if _, err := ioutil.ReadFile(p); err != nil {
+ if _, err := os.ReadFile(p); err != nil {
t.Error(err)
return
}
diff --git a/src/internal/testenv/testenv_windows.go b/src/internal/testenv/testenv_windows.go
index eb8d6ac165..4802b13951 100644
--- a/src/internal/testenv/testenv_windows.go
+++ b/src/internal/testenv/testenv_windows.go
@@ -5,7 +5,6 @@
package testenv
import (
- "io/ioutil"
"os"
"path/filepath"
"sync"
@@ -16,7 +15,7 @@ var symlinkOnce sync.Once
var winSymlinkErr error
func initWinHasSymlink() {
- tmpdir, err := ioutil.TempDir("", "symtest")
+ tmpdir, err := os.MkdirTemp("", "symtest")
if err != nil {
panic("failed to create temp directory: " + err.Error())
}
diff --git a/src/internal/trace/gc_test.go b/src/internal/trace/gc_test.go
index 4f9c77041a..9b9771e7b0 100644
--- a/src/internal/trace/gc_test.go
+++ b/src/internal/trace/gc_test.go
@@ -6,8 +6,8 @@ package trace
import (
"bytes"
- "io/ioutil"
"math"
+ "os"
"testing"
"time"
)
@@ -84,7 +84,7 @@ func TestMMUTrace(t *testing.T) {
t.Skip("skipping in -short mode")
}
- data, err := ioutil.ReadFile("testdata/stress_1_10_good")
+ data, err := os.ReadFile("testdata/stress_1_10_good")
if err != nil {
t.Fatalf("failed to read input file: %v", err)
}
@@ -126,7 +126,7 @@ func TestMMUTrace(t *testing.T) {
}
func BenchmarkMMU(b *testing.B) {
- data, err := ioutil.ReadFile("testdata/stress_1_10_good")
+ data, err := os.ReadFile("testdata/stress_1_10_good")
if err != nil {
b.Fatalf("failed to read input file: %v", err)
}
diff --git a/src/internal/trace/parser_test.go b/src/internal/trace/parser_test.go
index 6d87970157..cdab95a59e 100644
--- a/src/internal/trace/parser_test.go
+++ b/src/internal/trace/parser_test.go
@@ -6,7 +6,6 @@ package trace
import (
"bytes"
- "io/ioutil"
"os"
"path/filepath"
"strings"
@@ -34,20 +33,20 @@ func TestCorruptedInputs(t *testing.T) {
}
func TestParseCanned(t *testing.T) {
- files, err := ioutil.ReadDir("./testdata")
+ files, err := os.ReadDir("./testdata")
if err != nil {
t.Fatalf("failed to read ./testdata: %v", err)
}
for _, f := range files {
- name := filepath.Join("./testdata", f.Name())
- info, err := os.Stat(name)
+ info, err := f.Info()
if err != nil {
t.Fatal(err)
}
if testing.Short() && info.Size() > 10000 {
continue
}
- data, err := ioutil.ReadFile(name)
+ name := filepath.Join("./testdata", f.Name())
+ data, err := os.ReadFile(name)
if err != nil {
t.Fatal(err)
}
diff --git a/src/io/fs/readdir_test.go b/src/io/fs/readdir_test.go
index 46a4bc2788..405bfa67ca 100644
--- a/src/io/fs/readdir_test.go
+++ b/src/io/fs/readdir_test.go
@@ -16,12 +16,12 @@ func (readDirOnly) Open(name string) (File, error) { return nil, ErrNotExist }
func TestReadDir(t *testing.T) {
check := func(desc string, dirs []DirEntry, err error) {
t.Helper()
- if err != nil || len(dirs) != 1 || dirs[0].Name() != "hello.txt" {
+ if err != nil || len(dirs) != 2 || dirs[0].Name() != "hello.txt" || dirs[1].Name() != "sub" {
var names []string
for _, d := range dirs {
names = append(names, d.Name())
}
- t.Errorf("ReadDir(%s) = %v, %v, want %v, nil", desc, names, err, []string{"hello.txt"})
+ t.Errorf("ReadDir(%s) = %v, %v, want %v, nil", desc, names, err, []string{"hello.txt", "sub"})
}
}
@@ -32,4 +32,12 @@ func TestReadDir(t *testing.T) {
// Test that ReadDir uses Open when the method is not present.
dirs, err = ReadDir(openOnly{testFsys}, ".")
check("openOnly", dirs, err)
+
+ // Test that ReadDir on Sub of . works (sub_test checks non-trivial subs).
+ sub, err := Sub(testFsys, ".")
+ if err != nil {
+ t.Fatal(err)
+ }
+ dirs, err = ReadDir(sub, ".")
+ check("sub(.)", dirs, err)
}
diff --git a/src/io/fs/readfile_test.go b/src/io/fs/readfile_test.go
index 0afa334ace..07219c1445 100644
--- a/src/io/fs/readfile_test.go
+++ b/src/io/fs/readfile_test.go
@@ -18,6 +18,12 @@ var testFsys = fstest.MapFS{
ModTime: time.Now(),
Sys: &sysValue,
},
+ "sub/goodbye.txt": {
+ Data: []byte("goodbye, world"),
+ Mode: 0456,
+ ModTime: time.Now(),
+ Sys: &sysValue,
+ },
}
var sysValue int
@@ -40,4 +46,14 @@ func TestReadFile(t *testing.T) {
if string(data) != "hello, world" || err != nil {
t.Fatalf(`ReadFile(openOnly, "hello.txt") = %q, %v, want %q, nil`, data, err, "hello, world")
}
+
+ // Test that ReadFile on Sub of . works (sub_test checks non-trivial subs).
+ sub, err := Sub(testFsys, ".")
+ if err != nil {
+ t.Fatal(err)
+ }
+ data, err = ReadFile(sub, "hello.txt")
+ if string(data) != "hello, world" || err != nil {
+ t.Fatalf(`ReadFile(sub(.), "hello.txt") = %q, %v, want %q, nil`, data, err, "hello, world")
+ }
}
diff --git a/src/io/fs/sub.go b/src/io/fs/sub.go
new file mode 100644
index 0000000000..64cdffe6de
--- /dev/null
+++ b/src/io/fs/sub.go
@@ -0,0 +1,127 @@
+// Copyright 2020 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 fs
+
+import (
+ "errors"
+ "path"
+)
+
+// A SubFS is a file system with a Sub method.
+type SubFS interface {
+ FS
+
+ // Sub returns an FS corresponding to the subtree rooted at dir.
+ Sub(dir string) (FS, error)
+}
+
+// Sub returns an FS corresponding to the subtree rooted at fsys's dir.
+//
+// If fs implements SubFS, Sub calls returns fsys.Sub(dir).
+// Otherwise, if dir is ".", Sub returns fsys unchanged.
+// Otherwise, Sub returns a new FS implementation sub that,
+// in effect, implements sub.Open(dir) as fsys.Open(path.Join(dir, name)).
+// The implementation also translates calls to ReadDir, ReadFile, and Glob appropriately.
+//
+// Note that Sub(os.DirFS("/"), "prefix") is equivalent to os.DirFS("/prefix")
+// and that neither of them guarantees to avoid operating system
+// accesses outside "/prefix", because the implementation of os.DirFS
+// does not check for symbolic links inside "/prefix" that point to
+// other directories. That is, os.DirFS is not a general substitute for a
+// chroot-style security mechanism, and Sub does not change that fact.
+func Sub(fsys FS, dir string) (FS, error) {
+ if !ValidPath(dir) {
+ return nil, &PathError{Op: "sub", Path: dir, Err: errors.New("invalid name")}
+ }
+ if dir == "." {
+ return fsys, nil
+ }
+ if fsys, ok := fsys.(SubFS); ok {
+ return fsys.Sub(dir)
+ }
+ return &subFS{fsys, dir}, nil
+}
+
+type subFS struct {
+ fsys FS
+ dir string
+}
+
+// fullName maps name to the fully-qualified name dir/name.
+func (f *subFS) fullName(op string, name string) (string, error) {
+ if !ValidPath(name) {
+ return "", &PathError{Op: op, Path: name, Err: errors.New("invalid name")}
+ }
+ return path.Join(f.dir, name), nil
+}
+
+// shorten maps name, which should start with f.dir, back to the suffix after f.dir.
+func (f *subFS) shorten(name string) (rel string, ok bool) {
+ if name == f.dir {
+ return ".", true
+ }
+ if len(name) >= len(f.dir)+2 && name[len(f.dir)] == '/' && name[:len(f.dir)] == f.dir {
+ return name[len(f.dir)+1:], true
+ }
+ return "", false
+}
+
+// fixErr shortens any reported names in PathErrors by stripping dir.
+func (f *subFS) fixErr(err error) error {
+ if e, ok := err.(*PathError); ok {
+ if short, ok := f.shorten(e.Path); ok {
+ e.Path = short
+ }
+ }
+ return err
+}
+
+func (f *subFS) Open(name string) (File, error) {
+ full, err := f.fullName("open", name)
+ if err != nil {
+ return nil, err
+ }
+ file, err := f.fsys.Open(full)
+ return file, f.fixErr(err)
+}
+
+func (f *subFS) ReadDir(name string) ([]DirEntry, error) {
+ full, err := f.fullName("read", name)
+ if err != nil {
+ return nil, err
+ }
+ dir, err := ReadDir(f.fsys, full)
+ return dir, f.fixErr(err)
+}
+
+func (f *subFS) ReadFile(name string) ([]byte, error) {
+ full, err := f.fullName("read", name)
+ if err != nil {
+ return nil, err
+ }
+ data, err := ReadFile(f.fsys, full)
+ return data, f.fixErr(err)
+}
+
+func (f *subFS) Glob(pattern string) ([]string, error) {
+ // Check pattern is well-formed.
+ if _, err := path.Match(pattern, ""); err != nil {
+ return nil, err
+ }
+ if pattern == "." {
+ return []string{"."}, nil
+ }
+
+ full := f.dir + "/" + pattern
+ list, err := Glob(f.fsys, full)
+ for i, name := range list {
+ name, ok := f.shorten(name)
+ if !ok {
+ return nil, errors.New("invalid result from inner fsys Glob: " + name + " not in " + f.dir) // can't use fmt in this package
+ }
+ list[i] = name
+ }
+ return list, f.fixErr(err)
+}
diff --git a/src/io/fs/sub_test.go b/src/io/fs/sub_test.go
new file mode 100644
index 0000000000..451b0efb02
--- /dev/null
+++ b/src/io/fs/sub_test.go
@@ -0,0 +1,57 @@
+// Copyright 2020 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 fs_test
+
+import (
+ . "io/fs"
+ "testing"
+)
+
+type subOnly struct{ SubFS }
+
+func (subOnly) Open(name string) (File, error) { return nil, ErrNotExist }
+
+func TestSub(t *testing.T) {
+ check := func(desc string, sub FS, err error) {
+ t.Helper()
+ if err != nil {
+ t.Errorf("Sub(sub): %v", err)
+ return
+ }
+ data, err := ReadFile(sub, "goodbye.txt")
+ if string(data) != "goodbye, world" || err != nil {
+ t.Errorf(`ReadFile(%s, "goodbye.txt" = %q, %v, want %q, nil`, desc, string(data), err, "goodbye, world")
+ }
+
+ dirs, err := ReadDir(sub, ".")
+ if err != nil || len(dirs) != 1 || dirs[0].Name() != "goodbye.txt" {
+ var names []string
+ for _, d := range dirs {
+ names = append(names, d.Name())
+ }
+ t.Errorf(`ReadDir(%s, ".") = %v, %v, want %v, nil`, desc, names, err, []string{"goodbye.txt"})
+ }
+ }
+
+ // Test that Sub uses the method when present.
+ sub, err := Sub(subOnly{testFsys}, "sub")
+ check("subOnly", sub, err)
+
+ // Test that Sub uses Open when the method is not present.
+ sub, err = Sub(openOnly{testFsys}, "sub")
+ check("openOnly", sub, err)
+
+ _, err = sub.Open("nonexist")
+ if err == nil {
+ t.Fatal("Open(nonexist): succeeded")
+ }
+ pe, ok := err.(*PathError)
+ if !ok {
+ t.Fatalf("Open(nonexist): error is %T, want *PathError", err)
+ }
+ if pe.Path != "nonexist" {
+ t.Fatalf("Open(nonexist): err.Path = %q, want %q", pe.Path, "nonexist")
+ }
+}
diff --git a/src/io/ioutil/ioutil.go b/src/io/ioutil/ioutil.go
index a001c86b2f..45682b89c9 100644
--- a/src/io/ioutil/ioutil.go
+++ b/src/io/ioutil/ioutil.go
@@ -3,6 +3,11 @@
// license that can be found in the LICENSE file.
// Package ioutil implements some I/O utility functions.
+//
+// As of Go 1.16, the same functionality is now provided
+// by package io or package os, and those implementations
+// should be preferred in new code.
+// See the specific function documentation for details.
package ioutil
import (
@@ -26,67 +31,30 @@ func ReadAll(r io.Reader) ([]byte, error) {
// A successful call returns err == nil, not err == EOF. Because ReadFile
// reads the whole file, it does not treat an EOF from Read as an error
// to be reported.
+//
+// As of Go 1.16, this function simply calls os.ReadFile.
func ReadFile(filename string) ([]byte, error) {
- f, err := os.Open(filename)
- if err != nil {
- return nil, err
- }
- defer f.Close()
- // It's a good but not certain bet that FileInfo will tell us exactly how much to
- // read, so let's try it but be prepared for the answer to be wrong.
- const minRead = 512
- var n int64 = minRead
-
- if fi, err := f.Stat(); err == nil {
- // As initial capacity for readAll, use Size + a little extra in case Size
- // is zero, and to avoid another allocation after Read has filled the
- // buffer. The readAll call will read into its allocated internal buffer
- // cheaply. If the size was wrong, we'll either waste some space off the end
- // or reallocate as needed, but in the overwhelmingly common case we'll get
- // it just right.
- if size := fi.Size() + minRead; size > n {
- n = size
- }
- }
-
- if int64(int(n)) != n {
- n = minRead
- }
-
- b := make([]byte, 0, n)
- for {
- if len(b) == cap(b) {
- // Add more capacity (let append pick how much).
- b = append(b, 0)[:len(b)]
- }
- n, err := f.Read(b[len(b):cap(b)])
- b = b[:len(b)+n]
- if err != nil {
- if err == io.EOF {
- err = nil
- }
- return b, err
- }
- }
+ return os.ReadFile(filename)
}
// WriteFile writes data to a file named by filename.
// If the file does not exist, WriteFile creates it with permissions perm
// (before umask); otherwise WriteFile truncates it before writing, without changing permissions.
+//
+// As of Go 1.16, this function simply calls os.WriteFile.
func WriteFile(filename string, data []byte, perm fs.FileMode) error {
- f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
- if err != nil {
- return err
- }
- _, err = f.Write(data)
- if err1 := f.Close(); err == nil {
- err = err1
- }
- return err
+ return os.WriteFile(filename, data, perm)
}
// ReadDir reads the directory named by dirname and returns
-// a list of directory entries sorted by filename.
+// a list of fs.FileInfo for the directory's contents,
+// sorted by filename. If an error occurs reading the directory,
+// ReadDir returns no directory entries along with the error.
+//
+// As of Go 1.16, os.ReadDir is a more efficient and correct choice:
+// it returns a list of fs.DirEntry instead of fs.FileInfo,
+// and it returns partial results in the case of an error
+// midway through reading a directory.
func ReadDir(dirname string) ([]fs.FileInfo, error) {
f, err := os.Open(dirname)
if err != nil {
diff --git a/src/log/log.go b/src/log/log.go
index 8c0f83f0d1..b77af29032 100644
--- a/src/log/log.go
+++ b/src/log/log.go
@@ -75,7 +75,7 @@ func (l *Logger) SetOutput(w io.Writer) {
var std = New(os.Stderr, "", LstdFlags)
-// Default returns the *Logger used by the package-level output functions.
+// Default returns the standard logger used by the package-level output functions.
func Default() *Logger { return std }
// Cheap integer to fixed-width decimal ASCII. Give a negative width to avoid zero-padding.
diff --git a/src/log/syslog/syslog_test.go b/src/log/syslog/syslog_test.go
index 8f472a56b7..207bcf57c1 100644
--- a/src/log/syslog/syslog_test.go
+++ b/src/log/syslog/syslog_test.go
@@ -10,7 +10,6 @@ import (
"bufio"
"fmt"
"io"
- "io/ioutil"
"log"
"net"
"os"
@@ -88,8 +87,8 @@ func startServer(n, la string, done chan<- string) (addr string, sock io.Closer,
} else {
// unix and unixgram: choose an address if none given
if la == "" {
- // use ioutil.TempFile to get a name that is unique
- f, err := ioutil.TempFile("", "syslogtest")
+ // use os.CreateTemp to get a name that is unique
+ f, err := os.CreateTemp("", "syslogtest")
if err != nil {
log.Fatal("TempFile: ", err)
}
diff --git a/src/math/big/arith_s390x.s b/src/math/big/arith_s390x.s
index 242aca7434..caa4db0829 100644
--- a/src/math/big/arith_s390x.s
+++ b/src/math/big/arith_s390x.s
@@ -693,199 +693,11 @@ returnC:
// func shlVU(z, x []Word, s uint) (c Word)
TEXT ·shlVU(SB), NOSPLIT, $0
- MOVD z_len+8(FP), R5
- MOVD $0, R0
- SUB $1, R5 // n--
- BLT X8b // n < 0 (n <= 0)
+ BR ·shlVU_g(SB)
- // n > 0
- MOVD s+48(FP), R4
- CMPBEQ R0, R4, Z80 // handle 0 case beq
- MOVD $64, R6
- CMPBEQ R6, R4, Z864 // handle 64 case beq
- MOVD z+0(FP), R2
- MOVD x+24(FP), R8
- SLD $3, R5 // n = n*8
- SUB R4, R6, R7
- MOVD (R8)(R5*1), R10 // w1 = x[i-1]
- SRD R7, R10, R3
- MOVD R3, c+56(FP)
-
- MOVD $0, R1 // i = 0
- BR E8
-
- // i < n-1
-L8:
- MOVD R10, R3 // w = w1
- MOVD -8(R8)(R5*1), R10 // w1 = x[i+1]
-
- SLD R4, R3 // w<>ŝ
- SRD R7, R10, R6
- OR R6, R3
- MOVD R3, (R2)(R5*1) // z[i] = w<>ŝ
- SUB $8, R5 // i--
-
-E8:
- CMPBGT R5, R0, L8 // i < n-1
-
- // i >= n-1
-X8a:
- SLD R4, R10 // w1<= n-1
- MOVD R10, (R2)(R5*1)
- RET
-
-Z864:
- MOVD z+0(FP), R2
- MOVD x+24(FP), R8
- SLD $3, R5 // n = n*8
- MOVD (R8)(R5*1), R3 // w1 = x[n-1]
- MOVD R3, c+56(FP) // z[i] = x[n-1]
-
- BR E864
-
- // i < n-1
-L864:
- MOVD -8(R8)(R5*1), R3
-
- MOVD R3, (R2)(R5*1) // z[i] = x[n-1]
- SUB $8, R5 // i--
-
-E864:
- CMPBGT R5, R0, L864 // i < n-1
-
- MOVD R0, (R2) // z[n-1] = 0
- RET
-
-// CX = R4, r8 = r8, r10 = r2 , r11 = r5, DX = r3, AX = r10 , BX = R1 , 64-count = r7 (R0 set to 0) temp = R6
// func shrVU(z, x []Word, s uint) (c Word)
TEXT ·shrVU(SB), NOSPLIT, $0
- MOVD z_len+8(FP), R5
- MOVD $0, R0
- SUB $1, R5 // n--
- BLT X9b // n < 0 (n <= 0)
-
- // n > 0
- MOVD s+48(FP), R4
- CMPBEQ R0, R4, ZB0 // handle 0 case beq
- MOVD $64, R6
- CMPBEQ R6, R4, ZB64 // handle 64 case beq
- MOVD z+0(FP), R2
- MOVD x+24(FP), R8
- SLD $3, R5 // n = n*8
- SUB R4, R6, R7
- MOVD (R8), R10 // w1 = x[0]
- SLD R7, R10, R3
- MOVD R3, c+56(FP)
-
- MOVD $0, R1 // i = 0
- BR E9
-
- // i < n-1
-L9:
- MOVD R10, R3 // w = w1
- MOVD 8(R8)(R1*1), R10 // w1 = x[i+1]
-
- SRD R4, R3 // w>>s | w1<>s | w1<= n-1
-X9a:
- SRD R4, R10 // w1>>s
- MOVD R10, (R2)(R5*1) // z[n-1] = w1>>s
- RET
-
-X9b:
- MOVD R0, c+56(FP)
- RET
-
-ZB0:
- MOVD z+0(FP), R2
- MOVD x+24(FP), R8
- SLD $3, R5 // n = n*8
-
- MOVD (R8), R10 // w1 = x[0]
- MOVD $0, R3 // R10 << 64
- MOVD R3, c+56(FP)
-
- MOVD $0, R1 // i = 0
- BR E9Z
-
- // i < n-1
-L9Z:
- MOVD R10, R3 // w = w1
- MOVD 8(R8)(R1*1), R10 // w1 = x[i+1]
-
- MOVD R3, (R2)(R1*1) // z[i] = w>>s | w1<= n-1
- MOVD R10, (R2)(R5*1) // z[n-1] = w1>>s
- RET
-
-ZB64:
- MOVD z+0(FP), R2
- MOVD x+24(FP), R8
- SLD $3, R5 // n = n*8
- MOVD (R8), R3 // w1 = x[0]
- MOVD R3, c+56(FP)
-
- MOVD $0, R1 // i = 0
- BR E964
-
- // i < n-1
-L964:
- MOVD 8(R8)(R1*1), R3 // w1 = x[i+1]
-
- MOVD R3, (R2)(R1*1) // z[i] = w>>s | w1<= n-1
- MOVD $0, R10 // w1>>s
- MOVD R10, (R2)(R5*1) // z[n-1] = w1>>s
- RET
+ BR ·shrVU_g(SB)
// CX = R4, r8 = r8, r9=r9, r10 = r2 , r11 = r5, DX = r3, AX = r6 , BX = R1 , (R0 set to 0) + use R11 + use R7 for i
// func mulAddVWW(z, x []Word, y, r Word) (c Word)
diff --git a/src/math/big/arith_test.go b/src/math/big/arith_test.go
index 808d178459..2aca0effde 100644
--- a/src/math/big/arith_test.go
+++ b/src/math/big/arith_test.go
@@ -285,20 +285,56 @@ type argVU struct {
m string // message.
}
+var argshlVUIn = []Word{1, 2, 4, 8, 16, 32, 64, 0, 0, 0}
+var argshlVUr0 = []Word{1, 2, 4, 8, 16, 32, 64}
+var argshlVUr1 = []Word{2, 4, 8, 16, 32, 64, 128}
+var argshlVUrWm1 = []Word{1 << (_W - 1), 0, 1, 2, 4, 8, 16}
+
var argshlVU = []argVU{
// test cases for shlVU
{[]Word{1, _M, _M, _M, _M, _M, 3 << (_W - 2), 0}, 7, 0, 0, 1, []Word{2, _M - 1, _M, _M, _M, _M, 1<<(_W-1) + 1}, 1, "complete overlap of shlVU"},
{[]Word{1, _M, _M, _M, _M, _M, 3 << (_W - 2), 0, 0, 0, 0}, 7, 0, 3, 1, []Word{2, _M - 1, _M, _M, _M, _M, 1<<(_W-1) + 1}, 1, "partial overlap by half of shlVU"},
{[]Word{1, _M, _M, _M, _M, _M, 3 << (_W - 2), 0, 0, 0, 0, 0, 0, 0}, 7, 0, 6, 1, []Word{2, _M - 1, _M, _M, _M, _M, 1<<(_W-1) + 1}, 1, "partial overlap by 1 Word of shlVU"},
{[]Word{1, _M, _M, _M, _M, _M, 3 << (_W - 2), 0, 0, 0, 0, 0, 0, 0, 0}, 7, 0, 7, 1, []Word{2, _M - 1, _M, _M, _M, _M, 1<<(_W-1) + 1}, 1, "no overlap of shlVU"},
+ // additional test cases with shift values of 0, 1 and (_W-1)
+ {argshlVUIn, 7, 0, 0, 0, argshlVUr0, 0, "complete overlap of shlVU and shift of 0"},
+ {argshlVUIn, 7, 0, 0, 1, argshlVUr1, 0, "complete overlap of shlVU and shift of 1"},
+ {argshlVUIn, 7, 0, 0, _W - 1, argshlVUrWm1, 32, "complete overlap of shlVU and shift of _W - 1"},
+ {argshlVUIn, 7, 0, 1, 0, argshlVUr0, 0, "partial overlap by 6 Words of shlVU and shift of 0"},
+ {argshlVUIn, 7, 0, 1, 1, argshlVUr1, 0, "partial overlap by 6 Words of shlVU and shift of 1"},
+ {argshlVUIn, 7, 0, 1, _W - 1, argshlVUrWm1, 32, "partial overlap by 6 Words of shlVU and shift of _W - 1"},
+ {argshlVUIn, 7, 0, 2, 0, argshlVUr0, 0, "partial overlap by 5 Words of shlVU and shift of 0"},
+ {argshlVUIn, 7, 0, 2, 1, argshlVUr1, 0, "partial overlap by 5 Words of shlVU and shift of 1"},
+ {argshlVUIn, 7, 0, 2, _W - 1, argshlVUrWm1, 32, "partial overlap by 5 Words of shlVU abd shift of _W - 1"},
+ {argshlVUIn, 7, 0, 3, 0, argshlVUr0, 0, "partial overlap by 4 Words of shlVU and shift of 0"},
+ {argshlVUIn, 7, 0, 3, 1, argshlVUr1, 0, "partial overlap by 4 Words of shlVU and shift of 1"},
+ {argshlVUIn, 7, 0, 3, _W - 1, argshlVUrWm1, 32, "partial overlap by 4 Words of shlVU and shift of _W - 1"},
}
+var argshrVUIn = []Word{0, 0, 0, 1, 2, 4, 8, 16, 32, 64}
+var argshrVUr0 = []Word{1, 2, 4, 8, 16, 32, 64}
+var argshrVUr1 = []Word{0, 1, 2, 4, 8, 16, 32}
+var argshrVUrWm1 = []Word{4, 8, 16, 32, 64, 128, 0}
+
var argshrVU = []argVU{
// test cases for shrVU
{[]Word{0, 3, _M, _M, _M, _M, _M, 1 << (_W - 1)}, 7, 1, 1, 1, []Word{1<<(_W-1) + 1, _M, _M, _M, _M, _M >> 1, 1 << (_W - 2)}, 1 << (_W - 1), "complete overlap of shrVU"},
{[]Word{0, 0, 0, 0, 3, _M, _M, _M, _M, _M, 1 << (_W - 1)}, 7, 4, 1, 1, []Word{1<<(_W-1) + 1, _M, _M, _M, _M, _M >> 1, 1 << (_W - 2)}, 1 << (_W - 1), "partial overlap by half of shrVU"},
{[]Word{0, 0, 0, 0, 0, 0, 0, 3, _M, _M, _M, _M, _M, 1 << (_W - 1)}, 7, 7, 1, 1, []Word{1<<(_W-1) + 1, _M, _M, _M, _M, _M >> 1, 1 << (_W - 2)}, 1 << (_W - 1), "partial overlap by 1 Word of shrVU"},
{[]Word{0, 0, 0, 0, 0, 0, 0, 0, 3, _M, _M, _M, _M, _M, 1 << (_W - 1)}, 7, 8, 1, 1, []Word{1<<(_W-1) + 1, _M, _M, _M, _M, _M >> 1, 1 << (_W - 2)}, 1 << (_W - 1), "no overlap of shrVU"},
+ // additional test cases with shift values of 0, 1 and (_W-1)
+ {argshrVUIn, 7, 3, 3, 0, argshrVUr0, 0, "complete overlap of shrVU and shift of 0"},
+ {argshrVUIn, 7, 3, 3, 1, argshrVUr1, 1 << (_W - 1), "complete overlap of shrVU and shift of 1"},
+ {argshrVUIn, 7, 3, 3, _W - 1, argshrVUrWm1, 2, "complete overlap of shrVU and shift of _W - 1"},
+ {argshrVUIn, 7, 3, 2, 0, argshrVUr0, 0, "partial overlap by 6 Words of shrVU and shift of 0"},
+ {argshrVUIn, 7, 3, 2, 1, argshrVUr1, 1 << (_W - 1), "partial overlap by 6 Words of shrVU and shift of 1"},
+ {argshrVUIn, 7, 3, 2, _W - 1, argshrVUrWm1, 2, "partial overlap by 6 Words of shrVU and shift of _W - 1"},
+ {argshrVUIn, 7, 3, 1, 0, argshrVUr0, 0, "partial overlap by 5 Words of shrVU and shift of 0"},
+ {argshrVUIn, 7, 3, 1, 1, argshrVUr1, 1 << (_W - 1), "partial overlap by 5 Words of shrVU and shift of 1"},
+ {argshrVUIn, 7, 3, 1, _W - 1, argshrVUrWm1, 2, "partial overlap by 5 Words of shrVU and shift of _W - 1"},
+ {argshrVUIn, 7, 3, 0, 0, argshrVUr0, 0, "partial overlap by 4 Words of shrVU and shift of 0"},
+ {argshrVUIn, 7, 3, 0, 1, argshrVUr1, 1 << (_W - 1), "partial overlap by 4 Words of shrVU and shift of 1"},
+ {argshrVUIn, 7, 3, 0, _W - 1, argshrVUrWm1, 2, "partial overlap by 4 Words of shrVU and shift of _W - 1"},
}
func testShiftFunc(t *testing.T, f func(z, x []Word, s uint) Word, a argVU) {
@@ -335,11 +371,24 @@ func TestIssue31084(t *testing.T) {
// compute 10^n via 5^n << n.
const n = 165
p := nat(nil).expNN(nat{5}, nat{n}, nil)
- p = p.shl(p, uint(n))
+ p = p.shl(p, n)
got := string(p.utoa(10))
want := "1" + strings.Repeat("0", n)
if got != want {
- t.Errorf("shl(%v, %v)\n\tgot %s; want %s\n", p, uint(n), got, want)
+ t.Errorf("shl(%v, %v)\n\tgot %s\n\twant %s", p, n, got, want)
+ }
+}
+
+const issue42838Value = "159309191113245227702888039776771180559110455519261878607388585338616290151305816094308987472018268594098344692611135542392730712890625"
+
+func TestIssue42838(t *testing.T) {
+ const s = 192
+ z, _, _, _ := nat(nil).scan(strings.NewReader(issue42838Value), 0, false)
+ z = z.shl(z, s)
+ got := string(z.utoa(10))
+ want := "1" + strings.Repeat("0", s)
+ if got != want {
+ t.Errorf("shl(%v, %v)\n\tgot %s\n\twant %s", z, s, got, want)
}
}
diff --git a/src/math/big/link_test.go b/src/math/big/link_test.go
index 2212bd444f..42f9cefca0 100644
--- a/src/math/big/link_test.go
+++ b/src/math/big/link_test.go
@@ -7,7 +7,7 @@ package big
import (
"bytes"
"internal/testenv"
- "io/ioutil"
+ "os"
"os/exec"
"path/filepath"
"testing"
@@ -27,7 +27,7 @@ func TestLinkerGC(t *testing.T) {
import _ "math/big"
func main() {}
`)
- if err := ioutil.WriteFile(goFile, file, 0644); err != nil {
+ if err := os.WriteFile(goFile, file, 0644); err != nil {
t.Fatal(err)
}
cmd := exec.Command(goBin, "build", "-o", "x.exe", "x.go")
diff --git a/src/math/bits/make_examples.go b/src/math/bits/make_examples.go
index cd81cd6c4d..1d3ad53fe6 100644
--- a/src/math/bits/make_examples.go
+++ b/src/math/bits/make_examples.go
@@ -11,9 +11,9 @@ package main
import (
"bytes"
"fmt"
- "io/ioutil"
"log"
"math/bits"
+ "os"
)
const header = `// Copyright 2017 The Go Authors. All rights reserved.
@@ -106,7 +106,7 @@ func main() {
}
}
- if err := ioutil.WriteFile("example_test.go", w.Bytes(), 0666); err != nil {
+ if err := os.WriteFile("example_test.go", w.Bytes(), 0666); err != nil {
log.Fatal(err)
}
}
diff --git a/src/math/bits/make_tables.go b/src/math/bits/make_tables.go
index ff2fe2e385..b068d5e0e3 100644
--- a/src/math/bits/make_tables.go
+++ b/src/math/bits/make_tables.go
@@ -13,8 +13,8 @@ import (
"fmt"
"go/format"
"io"
- "io/ioutil"
"log"
+ "os"
)
var header = []byte(`// Copyright 2017 The Go Authors. All rights reserved.
@@ -40,7 +40,7 @@ func main() {
log.Fatal(err)
}
- err = ioutil.WriteFile("bits_tables.go", out, 0666)
+ err = os.WriteFile("bits_tables.go", out, 0666)
if err != nil {
log.Fatal(err)
}
diff --git a/src/mime/multipart/formdata.go b/src/mime/multipart/formdata.go
index 4eb3101294..fca5f9e15f 100644
--- a/src/mime/multipart/formdata.go
+++ b/src/mime/multipart/formdata.go
@@ -7,9 +7,8 @@ package multipart
import (
"bytes"
"errors"
- "fmt"
"io"
- "io/ioutil"
+ "math"
"net/textproto"
"os"
)
@@ -43,7 +42,11 @@ func (r *Reader) readForm(maxMemory int64) (_ *Form, err error) {
// Reserve an additional 10 MB for non-file parts.
maxValueBytes := maxMemory + int64(10<<20)
if maxValueBytes <= 0 {
- return nil, fmt.Errorf("multipart: integer overflow from maxMemory(%d) + 10MiB for non-file parts", maxMemory)
+ if maxMemory < 0 {
+ maxValueBytes = 0
+ } else {
+ maxValueBytes = math.MaxInt64
+ }
}
for {
p, err := r.NextPart()
@@ -87,7 +90,7 @@ func (r *Reader) readForm(maxMemory int64) (_ *Form, err error) {
}
if n > maxMemory {
// too big, write to disk and flush buffer
- file, err := ioutil.TempFile("", "multipart-")
+ file, err := os.CreateTemp("", "multipart-")
if err != nil {
return nil, err
}
diff --git a/src/mime/multipart/formdata_test.go b/src/mime/multipart/formdata_test.go
index 7112e0d372..e3a3a3eae8 100644
--- a/src/mime/multipart/formdata_test.go
+++ b/src/mime/multipart/formdata_test.go
@@ -53,20 +53,16 @@ func TestReadFormWithNamelessFile(t *testing.T) {
}
}
-// Issue 40430: Ensure that we report integer overflows in additions of maxMemory,
-// instead of silently and subtly failing without indication.
+// Issue 40430: Handle ReadForm(math.MaxInt64)
func TestReadFormMaxMemoryOverflow(t *testing.T) {
b := strings.NewReader(strings.ReplaceAll(messageWithTextContentType, "\n", "\r\n"))
r := NewReader(b, boundary)
f, err := r.ReadForm(math.MaxInt64)
- if err == nil {
- t.Fatal("Unexpected a non-nil error")
+ if err != nil {
+ t.Fatalf("ReadForm(MaxInt64): %v", err)
}
- if f != nil {
- t.Fatalf("Unexpected returned a non-nil form: %v\n", f)
- }
- if g, w := err.Error(), "integer overflow from maxMemory"; !strings.Contains(g, w) {
- t.Errorf(`Error mismatch\n%q\ndid not contain\n%q`, g, w)
+ if f == nil {
+ t.Fatal("ReadForm(MaxInt64): missing form")
}
}
diff --git a/src/net/dnsclient_unix_test.go b/src/net/dnsclient_unix_test.go
index 06553636ee..0530c92c2e 100644
--- a/src/net/dnsclient_unix_test.go
+++ b/src/net/dnsclient_unix_test.go
@@ -10,7 +10,6 @@ import (
"context"
"errors"
"fmt"
- "io/ioutil"
"os"
"path"
"reflect"
@@ -235,7 +234,7 @@ type resolvConfTest struct {
}
func newResolvConfTest() (*resolvConfTest, error) {
- dir, err := ioutil.TempDir("", "go-resolvconftest")
+ dir, err := os.MkdirTemp("", "go-resolvconftest")
if err != nil {
return nil, err
}
diff --git a/src/net/error_test.go b/src/net/error_test.go
index 7823fdf9d8..556eb8c8d4 100644
--- a/src/net/error_test.go
+++ b/src/net/error_test.go
@@ -13,7 +13,6 @@ import (
"internal/poll"
"io"
"io/fs"
- "io/ioutil"
"net/internal/socktest"
"os"
"runtime"
@@ -730,7 +729,7 @@ func TestFileError(t *testing.T) {
t.Skipf("not supported on %s", runtime.GOOS)
}
- f, err := ioutil.TempFile("", "go-nettest")
+ f, err := os.CreateTemp("", "go-nettest")
if err != nil {
t.Fatal(err)
}
diff --git a/src/net/http/filetransport_test.go b/src/net/http/filetransport_test.go
index fdfd44d967..b58888dcb1 100644
--- a/src/net/http/filetransport_test.go
+++ b/src/net/http/filetransport_test.go
@@ -6,7 +6,6 @@ package http
import (
"io"
- "io/ioutil"
"os"
"path/filepath"
"testing"
@@ -24,10 +23,10 @@ func checker(t *testing.T) func(string, error) {
func TestFileTransport(t *testing.T) {
check := checker(t)
- dname, err := ioutil.TempDir("", "")
+ dname, err := os.MkdirTemp("", "")
check("TempDir", err)
fname := filepath.Join(dname, "foo.txt")
- err = ioutil.WriteFile(fname, []byte("Bar"), 0644)
+ err = os.WriteFile(fname, []byte("Bar"), 0644)
check("WriteFile", err)
defer os.Remove(dname)
defer os.Remove(fname)
diff --git a/src/net/http/fs_test.go b/src/net/http/fs_test.go
index 2e4751114d..2499051625 100644
--- a/src/net/http/fs_test.go
+++ b/src/net/http/fs_test.go
@@ -79,7 +79,7 @@ func TestServeFile(t *testing.T) {
var err error
- file, err := ioutil.ReadFile(testFile)
+ file, err := os.ReadFile(testFile)
if err != nil {
t.Fatal("reading file:", err)
}
@@ -379,12 +379,12 @@ func mustRemoveAll(dir string) {
func TestFileServerImplicitLeadingSlash(t *testing.T) {
defer afterTest(t)
- tempDir, err := ioutil.TempDir("", "")
+ tempDir, err := os.MkdirTemp("", "")
if err != nil {
t.Fatalf("TempDir: %v", err)
}
defer mustRemoveAll(tempDir)
- if err := ioutil.WriteFile(filepath.Join(tempDir, "foo.txt"), []byte("Hello world"), 0644); err != nil {
+ if err := os.WriteFile(filepath.Join(tempDir, "foo.txt"), []byte("Hello world"), 0644); err != nil {
t.Fatalf("WriteFile: %v", err)
}
ts := httptest.NewServer(StripPrefix("/bar/", FileServer(Dir(tempDir))))
@@ -1177,7 +1177,7 @@ func TestLinuxSendfile(t *testing.T) {
filename := fmt.Sprintf("1kb-%d", os.Getpid())
filepath := path.Join(os.TempDir(), filename)
- if err := ioutil.WriteFile(filepath, bytes.Repeat([]byte{'a'}, 1<<10), 0755); err != nil {
+ if err := os.WriteFile(filepath, bytes.Repeat([]byte{'a'}, 1<<10), 0755); err != nil {
t.Fatal(err)
}
defer os.Remove(filepath)
diff --git a/src/net/http/request_test.go b/src/net/http/request_test.go
index 19526b9ad7..29297b0e7b 100644
--- a/src/net/http/request_test.go
+++ b/src/net/http/request_test.go
@@ -12,7 +12,6 @@ import (
"encoding/base64"
"fmt"
"io"
- "io/ioutil"
"math"
"mime/multipart"
. "net/http"
@@ -285,7 +284,7 @@ func TestMaxInt64ForMultipartFormMaxMemoryOverflow(t *testing.T) {
t.Fatal(err)
}
res.Body.Close()
- if g, w := res.StatusCode, StatusBadRequest; g != w {
+ if g, w := res.StatusCode, StatusOK; g != w {
t.Fatalf("Status code mismatch: got %d, want %d", g, w)
}
}
@@ -1164,7 +1163,7 @@ func BenchmarkFileAndServer_64MB(b *testing.B) {
}
func benchmarkFileAndServer(b *testing.B, n int64) {
- f, err := ioutil.TempFile(os.TempDir(), "go-bench-http-file-and-server")
+ f, err := os.CreateTemp(os.TempDir(), "go-bench-http-file-and-server")
if err != nil {
b.Fatalf("Failed to create temp file: %v", err)
}
diff --git a/src/net/http/response.go b/src/net/http/response.go
index 72812f0642..b95abae646 100644
--- a/src/net/http/response.go
+++ b/src/net/http/response.go
@@ -352,10 +352,16 @@ func (r *Response) bodyIsWritable() bool {
return ok
}
-// isProtocolSwitch reports whether r is a response to a successful
-// protocol upgrade.
+// isProtocolSwitch reports whether the response code and header
+// indicate a successful protocol upgrade response.
func (r *Response) isProtocolSwitch() bool {
- return r.StatusCode == StatusSwitchingProtocols &&
- r.Header.Get("Upgrade") != "" &&
- httpguts.HeaderValuesContainsToken(r.Header["Connection"], "Upgrade")
+ return isProtocolSwitchResponse(r.StatusCode, r.Header)
+}
+
+// isProtocolSwitchResponse reports whether the response code and
+// response header indicate a successful protocol upgrade response.
+func isProtocolSwitchResponse(code int, h Header) bool {
+ return code == StatusSwitchingProtocols &&
+ h.Get("Upgrade") != "" &&
+ httpguts.HeaderValuesContainsToken(h["Connection"], "Upgrade")
}
diff --git a/src/net/http/serve_test.go b/src/net/http/serve_test.go
index ba54b31a29..b1bf8e6c5e 100644
--- a/src/net/http/serve_test.go
+++ b/src/net/http/serve_test.go
@@ -6448,3 +6448,56 @@ func BenchmarkResponseStatusLine(b *testing.B) {
}
})
}
+func TestDisableKeepAliveUpgrade(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping in short mode")
+ }
+
+ setParallel(t)
+ defer afterTest(t)
+
+ s := httptest.NewUnstartedServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ w.Header().Set("Connection", "Upgrade")
+ w.Header().Set("Upgrade", "someProto")
+ w.WriteHeader(StatusSwitchingProtocols)
+ c, _, err := w.(Hijacker).Hijack()
+ if err != nil {
+ return
+ }
+ defer c.Close()
+
+ io.Copy(c, c)
+ }))
+ s.Config.SetKeepAlivesEnabled(false)
+ s.Start()
+ defer s.Close()
+
+ cl := s.Client()
+ cl.Transport.(*Transport).DisableKeepAlives = true
+
+ resp, err := cl.Get(s.URL)
+ if err != nil {
+ t.Fatalf("failed to perform request: %v", err)
+ }
+ defer resp.Body.Close()
+
+ rwc, ok := resp.Body.(io.ReadWriteCloser)
+ if !ok {
+ t.Fatalf("Response.Body is not a io.ReadWriteCloser: %T", resp.Body)
+ }
+
+ _, err = rwc.Write([]byte("hello"))
+ if err != nil {
+ t.Fatalf("failed to write to body: %v", err)
+ }
+
+ b := make([]byte, 5)
+ _, err = io.ReadFull(rwc, b)
+ if err != nil {
+ t.Fatalf("failed to read from body: %v", err)
+ }
+
+ if string(b) != "hello" {
+ t.Fatalf("unexpected value read from body:\ngot: %q\nwant: %q", b, "hello")
+ }
+}
diff --git a/src/net/http/server.go b/src/net/http/server.go
index 6c7d281705..102e893d5f 100644
--- a/src/net/http/server.go
+++ b/src/net/http/server.go
@@ -1468,7 +1468,13 @@ func (cw *chunkWriter) writeHeader(p []byte) {
return
}
- if w.closeAfterReply && (!keepAlivesEnabled || !hasToken(cw.header.get("Connection"), "close")) {
+ // Only override the Connection header if it is not a successful
+ // protocol switch response and if KeepAlives are not enabled.
+ // See https://golang.org/issue/36381.
+ delConnectionHeader := w.closeAfterReply &&
+ (!keepAlivesEnabled || !hasToken(cw.header.get("Connection"), "close")) &&
+ !isProtocolSwitchResponse(w.status, header)
+ if delConnectionHeader {
delHeader("Connection")
if w.req.ProtoAtLeast(1, 1) {
setHeader.connection = "close"
diff --git a/src/net/http/transfer_test.go b/src/net/http/transfer_test.go
index 1f3d32526d..f0c28b2629 100644
--- a/src/net/http/transfer_test.go
+++ b/src/net/http/transfer_test.go
@@ -10,7 +10,6 @@ import (
"crypto/rand"
"fmt"
"io"
- "io/ioutil"
"os"
"reflect"
"strings"
@@ -118,7 +117,7 @@ func TestTransferWriterWriteBodyReaderTypes(t *testing.T) {
nBytes := int64(1 << 10)
newFileFunc := func() (r io.Reader, done func(), err error) {
- f, err := ioutil.TempFile("", "net-http-newfilefunc")
+ f, err := os.CreateTemp("", "net-http-newfilefunc")
if err != nil {
return nil, nil, err
}
diff --git a/src/net/http/transport.go b/src/net/http/transport.go
index 79b1fc7681..a5830703af 100644
--- a/src/net/http/transport.go
+++ b/src/net/http/transport.go
@@ -784,7 +784,8 @@ func (t *Transport) CancelRequest(req *Request) {
}
// Cancel an in-flight request, recording the error value.
-func (t *Transport) cancelRequest(key cancelKey, err error) {
+// Returns whether the request was canceled.
+func (t *Transport) cancelRequest(key cancelKey, err error) bool {
t.reqMu.Lock()
cancel := t.reqCanceler[key]
delete(t.reqCanceler, key)
@@ -792,6 +793,8 @@ func (t *Transport) cancelRequest(key cancelKey, err error) {
if cancel != nil {
cancel(err)
}
+
+ return cancel != nil
}
//
@@ -2127,18 +2130,17 @@ func (pc *persistConn) readLoop() {
}
if !hasBody || bodyWritable {
- pc.t.setReqCanceler(rc.cancelKey, nil)
+ replaced := pc.t.replaceReqCanceler(rc.cancelKey, nil)
// Put the idle conn back into the pool before we send the response
// so if they process it quickly and make another request, they'll
// get this same conn. But we use the unbuffered channel 'rc'
// to guarantee that persistConn.roundTrip got out of its select
// potentially waiting for this persistConn to close.
- // but after
alive = alive &&
!pc.sawEOF &&
pc.wroteRequest() &&
- tryPutIdleConn(trace)
+ replaced && tryPutIdleConn(trace)
if bodyWritable {
closeErr = errCallerOwnsConn
@@ -2200,12 +2202,12 @@ func (pc *persistConn) readLoop() {
// reading the response body. (or for cancellation or death)
select {
case bodyEOF := <-waitForBodyRead:
- pc.t.setReqCanceler(rc.cancelKey, nil) // before pc might return to idle pool
+ replaced := pc.t.replaceReqCanceler(rc.cancelKey, nil) // before pc might return to idle pool
alive = alive &&
bodyEOF &&
!pc.sawEOF &&
pc.wroteRequest() &&
- tryPutIdleConn(trace)
+ replaced && tryPutIdleConn(trace)
if bodyEOF {
eofc <- struct{}{}
}
@@ -2599,6 +2601,8 @@ func (pc *persistConn) roundTrip(req *transportRequest) (resp *Response, err err
var respHeaderTimer <-chan time.Time
cancelChan := req.Request.Cancel
ctxDoneChan := req.Context().Done()
+ pcClosed := pc.closech
+ canceled := false
for {
testHookWaitResLoop()
select {
@@ -2618,11 +2622,14 @@ func (pc *persistConn) roundTrip(req *transportRequest) (resp *Response, err err
defer timer.Stop() // prevent leaks
respHeaderTimer = timer.C
}
- case <-pc.closech:
- if debugRoundTrip {
- req.logf("closech recv: %T %#v", pc.closed, pc.closed)
+ case <-pcClosed:
+ pcClosed = nil
+ if canceled || pc.t.replaceReqCanceler(req.cancelKey, nil) {
+ if debugRoundTrip {
+ req.logf("closech recv: %T %#v", pc.closed, pc.closed)
+ }
+ return nil, pc.mapRoundTripError(req, startBytesWritten, pc.closed)
}
- return nil, pc.mapRoundTripError(req, startBytesWritten, pc.closed)
case <-respHeaderTimer:
if debugRoundTrip {
req.logf("timeout waiting for response headers.")
@@ -2641,10 +2648,10 @@ func (pc *persistConn) roundTrip(req *transportRequest) (resp *Response, err err
}
return re.res, nil
case <-cancelChan:
- pc.t.cancelRequest(req.cancelKey, errRequestCanceled)
+ canceled = pc.t.cancelRequest(req.cancelKey, errRequestCanceled)
cancelChan = nil
case <-ctxDoneChan:
- pc.t.cancelRequest(req.cancelKey, req.Context().Err())
+ canceled = pc.t.cancelRequest(req.cancelKey, req.Context().Err())
cancelChan = nil
ctxDoneChan = nil
}
diff --git a/src/net/http/transport_test.go b/src/net/http/transport_test.go
index 9086507d57..7f6e0938c2 100644
--- a/src/net/http/transport_test.go
+++ b/src/net/http/transport_test.go
@@ -23,7 +23,6 @@ import (
"go/token"
"internal/nettrace"
"io"
- "io/ioutil"
"log"
mrand "math/rand"
"net"
@@ -5746,7 +5745,7 @@ func (c *testMockTCPConn) ReadFrom(r io.Reader) (int64, error) {
func TestTransportRequestWriteRoundTrip(t *testing.T) {
nBytes := int64(1 << 10)
newFileFunc := func() (r io.Reader, done func(), err error) {
- f, err := ioutil.TempFile("", "net-http-newfilefunc")
+ f, err := os.CreateTemp("", "net-http-newfilefunc")
if err != nil {
return nil, nil, err
}
@@ -6433,3 +6432,54 @@ func TestErrorWriteLoopRace(t *testing.T) {
testTransportRace(req)
}
}
+
+// Issue 41600
+// Test that a new request which uses the connection of an active request
+// cannot cause it to be canceled as well.
+func TestCancelRequestWhenSharingConnection(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping in short mode")
+ }
+ ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, req *Request) {
+ w.Header().Add("Content-Length", "0")
+ }))
+ defer ts.Close()
+
+ client := ts.Client()
+ transport := client.Transport.(*Transport)
+ transport.MaxIdleConns = 1
+ transport.MaxConnsPerHost = 1
+
+ var wg sync.WaitGroup
+
+ ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+
+ for i := 0; i < 10; i++ {
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ for ctx.Err() == nil {
+ reqctx, reqcancel := context.WithCancel(ctx)
+ go reqcancel()
+ req, _ := NewRequestWithContext(reqctx, "GET", ts.URL, nil)
+ res, err := client.Do(req)
+ if err == nil {
+ res.Body.Close()
+ }
+ }
+ }()
+ }
+
+ for ctx.Err() == nil {
+ req, _ := NewRequest("GET", ts.URL, nil)
+ if res, err := client.Do(req); err != nil {
+ t.Errorf("unexpected: %p %v", req, err)
+ break
+ } else {
+ res.Body.Close()
+ }
+ }
+
+ cancel()
+ wg.Wait()
+}
diff --git a/src/net/mockserver_test.go b/src/net/mockserver_test.go
index e085f4440b..9faf173679 100644
--- a/src/net/mockserver_test.go
+++ b/src/net/mockserver_test.go
@@ -9,16 +9,15 @@ package net
import (
"errors"
"fmt"
- "io/ioutil"
"os"
"sync"
"testing"
"time"
)
-// testUnixAddr uses ioutil.TempFile to get a name that is unique.
+// testUnixAddr uses os.CreateTemp to get a name that is unique.
func testUnixAddr() string {
- f, err := ioutil.TempFile("", "go-nettest")
+ f, err := os.CreateTemp("", "go-nettest")
if err != nil {
panic(err)
}
diff --git a/src/net/net_windows_test.go b/src/net/net_windows_test.go
index 8aa719f433..a0000950c6 100644
--- a/src/net/net_windows_test.go
+++ b/src/net/net_windows_test.go
@@ -9,7 +9,6 @@ import (
"bytes"
"fmt"
"io"
- "io/ioutil"
"os"
"os/exec"
"regexp"
@@ -176,7 +175,7 @@ func runCmd(args ...string) ([]byte, error) {
}
return b
}
- f, err := ioutil.TempFile("", "netcmd")
+ f, err := os.CreateTemp("", "netcmd")
if err != nil {
return nil, err
}
@@ -189,7 +188,7 @@ func runCmd(args ...string) ([]byte, error) {
return nil, fmt.Errorf("%s failed: %v: %q", args[0], err, string(removeUTF8BOM(out)))
}
var err2 error
- out, err2 = ioutil.ReadFile(f.Name())
+ out, err2 = os.ReadFile(f.Name())
if err2 != nil {
return nil, err2
}
@@ -198,7 +197,7 @@ func runCmd(args ...string) ([]byte, error) {
}
return nil, fmt.Errorf("%s failed: %v", args[0], err)
}
- out, err = ioutil.ReadFile(f.Name())
+ out, err = os.ReadFile(f.Name())
if err != nil {
return nil, err
}
diff --git a/src/net/udpsock.go b/src/net/udpsock.go
index ec2bcfa607..571e099abd 100644
--- a/src/net/udpsock.go
+++ b/src/net/udpsock.go
@@ -259,6 +259,9 @@ func ListenUDP(network string, laddr *UDPAddr) (*UDPConn, error) {
// ListenMulticastUDP is just for convenience of simple, small
// applications. There are golang.org/x/net/ipv4 and
// golang.org/x/net/ipv6 packages for general purpose uses.
+//
+// Note that ListenMulticastUDP will set the IP_MULTICAST_LOOP socket option
+// to 0 under IPPROTO_IP, to disable loopback of multicast packets.
func ListenMulticastUDP(network string, ifi *Interface, gaddr *UDPAddr) (*UDPConn, error) {
switch network {
case "udp", "udp4", "udp6":
diff --git a/src/net/unixsock_test.go b/src/net/unixsock_test.go
index 4b2cfc4d62..0b13bf655f 100644
--- a/src/net/unixsock_test.go
+++ b/src/net/unixsock_test.go
@@ -9,7 +9,6 @@ package net
import (
"bytes"
"internal/testenv"
- "io/ioutil"
"os"
"reflect"
"runtime"
@@ -417,7 +416,7 @@ func TestUnixUnlink(t *testing.T) {
checkExists(t, "after Listen")
l.Close()
checkNotExists(t, "after Listener close")
- if err := ioutil.WriteFile(name, []byte("hello world"), 0666); err != nil {
+ if err := os.WriteFile(name, []byte("hello world"), 0666); err != nil {
t.Fatalf("cannot recreate socket file: %v", err)
}
checkExists(t, "after writing temp file")
diff --git a/src/os/dir.go b/src/os/dir.go
index 1d90b970e7..5306bcb3ba 100644
--- a/src/os/dir.go
+++ b/src/os/dir.go
@@ -4,7 +4,10 @@
package os
-import "io/fs"
+import (
+ "io/fs"
+ "sort"
+)
type readdirMode int
@@ -103,3 +106,20 @@ func (f *File) ReadDir(n int) ([]DirEntry, error) {
// testingForceReadDirLstat forces ReadDir to call Lstat, for testing that code path.
// This can be difficult to provoke on some Unix systems otherwise.
var testingForceReadDirLstat bool
+
+// ReadDir reads the named directory,
+// returning all its directory entries sorted by filename.
+// If an error occurs reading the directory,
+// ReadDir returns the entries it was able to read before the error,
+// along with the error.
+func ReadDir(name string) ([]DirEntry, error) {
+ f, err := Open(name)
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+
+ dirs, err := f.ReadDir(-1)
+ sort.Slice(dirs, func(i, j int) bool { return dirs[i].Name() < dirs[j].Name() })
+ return dirs, err
+}
diff --git a/src/os/error_test.go b/src/os/error_test.go
index 060cf59875..6264ccc966 100644
--- a/src/os/error_test.go
+++ b/src/os/error_test.go
@@ -8,14 +8,13 @@ import (
"errors"
"fmt"
"io/fs"
- "io/ioutil"
"os"
"path/filepath"
"testing"
)
func TestErrIsExist(t *testing.T) {
- f, err := ioutil.TempFile("", "_Go_ErrIsExist")
+ f, err := os.CreateTemp("", "_Go_ErrIsExist")
if err != nil {
t.Fatalf("open ErrIsExist tempfile: %s", err)
return
@@ -55,7 +54,7 @@ func testErrNotExist(name string) string {
}
func TestErrIsNotExist(t *testing.T) {
- tmpDir, err := ioutil.TempDir("", "_Go_ErrIsNotExist")
+ tmpDir, err := os.MkdirTemp("", "_Go_ErrIsNotExist")
if err != nil {
t.Fatalf("create ErrIsNotExist tempdir: %s", err)
return
@@ -147,12 +146,12 @@ func TestIsPermission(t *testing.T) {
}
func TestErrPathNUL(t *testing.T) {
- f, err := ioutil.TempFile("", "_Go_ErrPathNUL\x00")
+ f, err := os.CreateTemp("", "_Go_ErrPathNUL\x00")
if err == nil {
f.Close()
t.Fatal("TempFile should have failed")
}
- f, err = ioutil.TempFile("", "_Go_ErrPathNUL")
+ f, err = os.CreateTemp("", "_Go_ErrPathNUL")
if err != nil {
t.Fatalf("open ErrPathNUL tempfile: %s", err)
}
diff --git a/src/os/example_test.go b/src/os/example_test.go
index fbb277b6f1..3adce51784 100644
--- a/src/os/example_test.go
+++ b/src/os/example_test.go
@@ -9,6 +9,7 @@ import (
"io/fs"
"log"
"os"
+ "path/filepath"
"time"
)
@@ -144,3 +145,98 @@ func ExampleUnsetenv() {
os.Setenv("TMPDIR", "/my/tmp")
defer os.Unsetenv("TMPDIR")
}
+
+func ExampleReadDir() {
+ files, err := os.ReadDir(".")
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ for _, file := range files {
+ fmt.Println(file.Name())
+ }
+}
+
+func ExampleMkdirTemp() {
+ dir, err := os.MkdirTemp("", "example")
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer os.RemoveAll(dir) // clean up
+
+ file := filepath.Join(dir, "tmpfile")
+ if err := os.WriteFile(file, []byte("content"), 0666); err != nil {
+ log.Fatal(err)
+ }
+}
+
+func ExampleMkdirTemp_suffix() {
+ logsDir, err := os.MkdirTemp("", "*-logs")
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer os.RemoveAll(logsDir) // clean up
+
+ // Logs can be cleaned out earlier if needed by searching
+ // for all directories whose suffix ends in *-logs.
+ globPattern := filepath.Join(os.TempDir(), "*-logs")
+ matches, err := filepath.Glob(globPattern)
+ if err != nil {
+ log.Fatalf("Failed to match %q: %v", globPattern, err)
+ }
+
+ for _, match := range matches {
+ if err := os.RemoveAll(match); err != nil {
+ log.Printf("Failed to remove %q: %v", match, err)
+ }
+ }
+}
+
+func ExampleCreateTemp() {
+ f, err := os.CreateTemp("", "example")
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer os.Remove(f.Name()) // clean up
+
+ if _, err := f.Write([]byte("content")); err != nil {
+ log.Fatal(err)
+ }
+ if err := f.Close(); err != nil {
+ log.Fatal(err)
+ }
+}
+
+func ExampleCreateTemp_suffix() {
+ f, err := os.CreateTemp("", "example.*.txt")
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer os.Remove(f.Name()) // clean up
+
+ if _, err := f.Write([]byte("content")); err != nil {
+ f.Close()
+ log.Fatal(err)
+ }
+ if err := f.Close(); err != nil {
+ log.Fatal(err)
+ }
+}
+
+func ExampleReadFile() {
+ data, err := os.ReadFile("testdata/hello")
+ if err != nil {
+ log.Fatal(err)
+ }
+ os.Stdout.Write(data)
+
+ // Output:
+ // Hello, Gophers!
+}
+
+func ExampleWriteFile() {
+ err := os.WriteFile("testdata/hello", []byte("Hello, Gophers!"), 0666)
+ if err != nil {
+ log.Fatal(err)
+ }
+}
diff --git a/src/os/exec/exec_test.go b/src/os/exec/exec_test.go
index cd3d759ebc..8b0c93f382 100644
--- a/src/os/exec/exec_test.go
+++ b/src/os/exec/exec_test.go
@@ -15,7 +15,6 @@ import (
"internal/poll"
"internal/testenv"
"io"
- "io/ioutil"
"log"
"net"
"net/http"
@@ -386,7 +385,7 @@ func TestPipeLookPathLeak(t *testing.T) {
// Reading /proc/self/fd is more reliable than calling lsof, so try that
// first.
numOpenFDs := func() (int, []byte, error) {
- fds, err := ioutil.ReadDir("/proc/self/fd")
+ fds, err := os.ReadDir("/proc/self/fd")
if err != nil {
return 0, nil, err
}
@@ -645,7 +644,7 @@ func TestExtraFiles(t *testing.T) {
t.Errorf("success trying to fetch %s; want an error", ts.URL)
}
- tf, err := ioutil.TempFile("", "")
+ tf, err := os.CreateTemp("", "")
if err != nil {
t.Fatalf("TempFile: %v", err)
}
@@ -691,6 +690,18 @@ func TestExtraFiles(t *testing.T) {
c.Stdout = &stdout
c.Stderr = &stderr
c.ExtraFiles = []*os.File{tf}
+ if runtime.GOOS == "illumos" {
+ // Some facilities in illumos are implemented via access
+ // to /proc by libc; such accesses can briefly occupy a
+ // low-numbered fd. If this occurs concurrently with the
+ // test that checks for leaked descriptors, the check can
+ // become confused and report a spurious leaked descriptor.
+ // (See issue #42431 for more detailed analysis.)
+ //
+ // Attempt to constrain the use of additional threads in the
+ // child process to make this test less flaky:
+ c.Env = append(os.Environ(), "GOMAXPROCS=1")
+ }
err = c.Run()
if err != nil {
t.Fatalf("Run: %v\n--- stdout:\n%s--- stderr:\n%s", err, stdout.Bytes(), stderr.Bytes())
diff --git a/src/os/exec/lp_unix_test.go b/src/os/exec/lp_unix_test.go
index e4656cafb8..296480fd04 100644
--- a/src/os/exec/lp_unix_test.go
+++ b/src/os/exec/lp_unix_test.go
@@ -7,13 +7,12 @@
package exec
import (
- "io/ioutil"
"os"
"testing"
)
func TestLookPathUnixEmptyPath(t *testing.T) {
- tmp, err := ioutil.TempDir("", "TestLookPathUnixEmptyPath")
+ tmp, err := os.MkdirTemp("", "TestLookPathUnixEmptyPath")
if err != nil {
t.Fatal("TempDir failed: ", err)
}
diff --git a/src/os/exec/lp_windows_test.go b/src/os/exec/lp_windows_test.go
index 59b5f1c2c7..c6f3d5d406 100644
--- a/src/os/exec/lp_windows_test.go
+++ b/src/os/exec/lp_windows_test.go
@@ -11,7 +11,6 @@ import (
"fmt"
"internal/testenv"
"io"
- "io/ioutil"
"os"
"os/exec"
"path/filepath"
@@ -307,7 +306,7 @@ var lookPathTests = []lookPathTest{
}
func TestLookPath(t *testing.T) {
- tmp, err := ioutil.TempDir("", "TestLookPath")
+ tmp, err := os.MkdirTemp("", "TestLookPath")
if err != nil {
t.Fatal("TempDir failed: ", err)
}
@@ -504,7 +503,7 @@ var commandTests = []commandTest{
}
func TestCommand(t *testing.T) {
- tmp, err := ioutil.TempDir("", "TestCommand")
+ tmp, err := os.MkdirTemp("", "TestCommand")
if err != nil {
t.Fatal("TempDir failed: ", err)
}
@@ -529,7 +528,7 @@ func TestCommand(t *testing.T) {
func buildPrintPathExe(t *testing.T, dir string) string {
const name = "printpath"
srcname := name + ".go"
- err := ioutil.WriteFile(filepath.Join(dir, srcname), []byte(printpathSrc), 0644)
+ err := os.WriteFile(filepath.Join(dir, srcname), []byte(printpathSrc), 0644)
if err != nil {
t.Fatalf("failed to create source: %v", err)
}
diff --git a/src/os/export_test.go b/src/os/export_test.go
index d66264a68f..f3cb1a2bef 100644
--- a/src/os/export_test.go
+++ b/src/os/export_test.go
@@ -10,3 +10,4 @@ var Atime = atime
var LstatP = &lstat
var ErrWriteAtInAppendMode = errWriteAtInAppendMode
var TestingForceReadDirLstat = &testingForceReadDirLstat
+var ErrPatternHasSeparator = errPatternHasSeparator
diff --git a/src/os/fifo_test.go b/src/os/fifo_test.go
index 3041dcfa02..2439192a9d 100644
--- a/src/os/fifo_test.go
+++ b/src/os/fifo_test.go
@@ -11,7 +11,6 @@ import (
"bytes"
"fmt"
"io"
- "io/ioutil"
"os"
"path/filepath"
"runtime"
@@ -31,7 +30,7 @@ func TestFifoEOF(t *testing.T) {
t.Skip("skipping on OpenBSD; issue 25877")
}
- dir, err := ioutil.TempDir("", "TestFifoEOF")
+ dir, err := os.MkdirTemp("", "TestFifoEOF")
if err != nil {
t.Fatal(err)
}
diff --git a/src/os/file.go b/src/os/file.go
index 835d44ab8c..416bc0efa6 100644
--- a/src/os/file.go
+++ b/src/os/file.go
@@ -406,7 +406,7 @@ func UserCacheDir() (string, error) {
return "", errors.New("%LocalAppData% is not defined")
}
- case "darwin":
+ case "darwin", "ios":
dir = Getenv("HOME")
if dir == "" {
return "", errors.New("$HOME is not defined")
@@ -457,7 +457,7 @@ func UserConfigDir() (string, error) {
return "", errors.New("%AppData% is not defined")
}
- case "darwin":
+ case "darwin", "ios":
dir = Getenv("HOME")
if dir == "" {
return "", errors.New("$HOME is not defined")
@@ -505,10 +505,8 @@ func UserHomeDir() (string, error) {
switch runtime.GOOS {
case "android":
return "/sdcard", nil
- case "darwin":
- if runtime.GOARCH == "arm64" {
- return "/", nil
- }
+ case "ios":
+ return "/", nil
}
return "", errors.New(enverr + " is not defined")
}
@@ -611,6 +609,13 @@ func isWindowsNulName(name string) bool {
}
// DirFS returns a file system (an fs.FS) for the tree of files rooted at the directory dir.
+//
+// Note that DirFS("/prefix") only guarantees that the Open calls it makes to the
+// operating system will begin with "/prefix": DirFS("/prefix").Open("file") is the
+// same as os.Open("/prefix/file"). So if /prefix/file is a symbolic link pointing outside
+// the /prefix tree, then using DirFS does not stop the access any more than using
+// os.Open does. DirFS is therefore not a general substitute for a chroot-style security
+// mechanism when the directory tree contains arbitrary content.
func DirFS(dir string) fs.FS {
return dirFS(dir)
}
@@ -627,3 +632,63 @@ func (dir dirFS) Open(name string) (fs.File, error) {
}
return f, nil
}
+
+// ReadFile reads the named file and returns the contents.
+// A successful call returns err == nil, not err == EOF.
+// Because ReadFile reads the whole file, it does not treat an EOF from Read
+// as an error to be reported.
+func ReadFile(name string) ([]byte, error) {
+ f, err := Open(name)
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+
+ var size int
+ if info, err := f.Stat(); err == nil {
+ size64 := info.Size()
+ if int64(int(size64)) == size64 {
+ size = int(size64)
+ }
+ }
+ size++ // one byte for final read at EOF
+
+ // If a file claims a small size, read at least 512 bytes.
+ // In particular, files in Linux's /proc claim size 0 but
+ // then do not work right if read in small pieces,
+ // so an initial read of 1 byte would not work correctly.
+ if size < 512 {
+ size = 512
+ }
+
+ data := make([]byte, 0, size)
+ for {
+ if len(data) >= cap(data) {
+ d := append(data[:cap(data)], 0)
+ data = d[:len(data)]
+ }
+ n, err := f.Read(data[len(data):cap(data)])
+ data = data[:len(data)+n]
+ if err != nil {
+ if err == io.EOF {
+ err = nil
+ }
+ return data, err
+ }
+ }
+}
+
+// WriteFile writes data to the named file, creating it if necessary.
+// If the file does not exist, WriteFile creates it with permissions perm (before umask);
+// otherwise WriteFile truncates it before writing, without changing permissions.
+func WriteFile(name string, data []byte, perm FileMode) error {
+ f, err := OpenFile(name, O_WRONLY|O_CREATE|O_TRUNC, perm)
+ if err != nil {
+ return err
+ }
+ _, err = f.Write(data)
+ if err1 := f.Close(); err1 != nil && err == nil {
+ err = err1
+ }
+ return err
+}
diff --git a/src/os/os_test.go b/src/os/os_test.go
index a1c0578887..765797f5fb 100644
--- a/src/os/os_test.go
+++ b/src/os/os_test.go
@@ -11,7 +11,7 @@ import (
"fmt"
"internal/testenv"
"io"
- "io/ioutil"
+ "os"
. "os"
osexec "os/exec"
"path/filepath"
@@ -155,7 +155,7 @@ func localTmp() string {
}
func newFile(testName string, t *testing.T) (f *File) {
- f, err := ioutil.TempFile(localTmp(), "_Go_"+testName)
+ f, err := os.CreateTemp(localTmp(), "_Go_"+testName)
if err != nil {
t.Fatalf("TempFile %s: %s", testName, err)
}
@@ -163,7 +163,7 @@ func newFile(testName string, t *testing.T) (f *File) {
}
func newDir(testName string, t *testing.T) (name string) {
- name, err := ioutil.TempDir(localTmp(), "_Go_"+testName)
+ name, err := os.MkdirTemp(localTmp(), "_Go_"+testName)
if err != nil {
t.Fatalf("TempDir %s: %s", testName, err)
}
@@ -419,19 +419,19 @@ func testReadDir(dir string, contents []string, t *testing.T) {
}
}
-func TestReaddirnames(t *testing.T) {
+func TestFileReaddirnames(t *testing.T) {
testReaddirnames(".", dot, t)
testReaddirnames(sysdir.name, sysdir.files, t)
testReaddirnames(t.TempDir(), nil, t)
}
-func TestReaddir(t *testing.T) {
+func TestFileReaddir(t *testing.T) {
testReaddir(".", dot, t)
testReaddir(sysdir.name, sysdir.files, t)
testReaddir(t.TempDir(), nil, t)
}
-func TestReadDir(t *testing.T) {
+func TestFileReadDir(t *testing.T) {
testReadDir(".", dot, t)
testReadDir(sysdir.name, sysdir.files, t)
testReadDir(t.TempDir(), nil, t)
@@ -616,7 +616,7 @@ func TestReaddirNValues(t *testing.T) {
if testing.Short() {
t.Skip("test.short; skipping")
}
- dir, err := ioutil.TempDir("", "")
+ dir, err := os.MkdirTemp("", "")
if err != nil {
t.Fatalf("TempDir: %v", err)
}
@@ -715,7 +715,7 @@ func TestReaddirStatFailures(t *testing.T) {
// testing it wouldn't work.
t.Skipf("skipping test on %v", runtime.GOOS)
}
- dir, err := ioutil.TempDir("", "")
+ dir, err := os.MkdirTemp("", "")
if err != nil {
t.Fatalf("TempDir: %v", err)
}
@@ -776,7 +776,7 @@ func TestReaddirStatFailures(t *testing.T) {
// Readdir on a regular file should fail.
func TestReaddirOfFile(t *testing.T) {
- f, err := ioutil.TempFile("", "_Go_ReaddirOfFile")
+ f, err := os.CreateTemp("", "_Go_ReaddirOfFile")
if err != nil {
t.Fatal(err)
}
@@ -867,7 +867,7 @@ func chtmpdir(t *testing.T) func() {
if err != nil {
t.Fatalf("chtmpdir: %v", err)
}
- d, err := ioutil.TempDir("", "test")
+ d, err := os.MkdirTemp("", "test")
if err != nil {
t.Fatalf("chtmpdir: %v", err)
}
@@ -992,12 +992,12 @@ func TestRenameOverwriteDest(t *testing.T) {
toData := []byte("to")
fromData := []byte("from")
- err := ioutil.WriteFile(to, toData, 0777)
+ err := os.WriteFile(to, toData, 0777)
if err != nil {
t.Fatalf("write file %q failed: %v", to, err)
}
- err = ioutil.WriteFile(from, fromData, 0777)
+ err = os.WriteFile(from, fromData, 0777)
if err != nil {
t.Fatalf("write file %q failed: %v", from, err)
}
@@ -1235,6 +1235,7 @@ func TestChmod(t *testing.T) {
}
func checkSize(t *testing.T, f *File, size int64) {
+ t.Helper()
dir, err := f.Stat()
if err != nil {
t.Fatalf("Stat %q (looking for size %d): %s", f.Name(), size, err)
@@ -1340,7 +1341,7 @@ func testChtimes(t *testing.T, name string) {
// the contents are accessed; also, it is set
// whenever mtime is set.
case "netbsd":
- mounts, _ := ioutil.ReadFile("/proc/mounts")
+ mounts, _ := os.ReadFile("/proc/mounts")
if strings.Contains(string(mounts), "noatime") {
t.Logf("AccessTime didn't go backwards, but see a filesystem mounted noatime; ignoring. Issue 19293.")
} else {
@@ -1414,7 +1415,7 @@ func TestChdirAndGetwd(t *testing.T) {
case "arm64":
dirs = nil
for _, d := range []string{"d1", "d2"} {
- dir, err := ioutil.TempDir("", d)
+ dir, err := os.MkdirTemp("", d)
if err != nil {
t.Fatalf("TempDir: %v", err)
}
@@ -1508,7 +1509,7 @@ func TestProgWideChdir(t *testing.T) {
c <- true
t.Fatalf("Getwd: %v", err)
}
- d, err := ioutil.TempDir("", "test")
+ d, err := os.MkdirTemp("", "test")
if err != nil {
c <- true
t.Fatalf("TempDir: %v", err)
@@ -1575,7 +1576,7 @@ func TestSeek(t *testing.T) {
off, err := f.Seek(tt.in, tt.whence)
if off != tt.out || err != nil {
if e, ok := err.(*PathError); ok && e.Err == syscall.EINVAL && tt.out > 1<<32 && runtime.GOOS == "linux" {
- mounts, _ := ioutil.ReadFile("/proc/mounts")
+ mounts, _ := os.ReadFile("/proc/mounts")
if strings.Contains(string(mounts), "reiserfs") {
// Reiserfs rejects the big seeks.
t.Skipf("skipping test known to fail on reiserfs; https://golang.org/issue/91")
@@ -1857,7 +1858,7 @@ func TestWriteAt(t *testing.T) {
t.Fatalf("WriteAt 7: %d, %v", n, err)
}
- b, err := ioutil.ReadFile(f.Name())
+ b, err := os.ReadFile(f.Name())
if err != nil {
t.Fatalf("ReadFile %s: %v", f.Name(), err)
}
@@ -1905,7 +1906,7 @@ func writeFile(t *testing.T, fname string, flag int, text string) string {
t.Fatalf("WriteString: %d, %v", n, err)
}
f.Close()
- data, err := ioutil.ReadFile(fname)
+ data, err := os.ReadFile(fname)
if err != nil {
t.Fatalf("ReadFile: %v", err)
}
@@ -1947,7 +1948,7 @@ func TestAppend(t *testing.T) {
func TestStatDirWithTrailingSlash(t *testing.T) {
// Create new temporary directory and arrange to clean it up.
- path, err := ioutil.TempDir("", "_TestStatDirWithSlash_")
+ path, err := os.MkdirTemp("", "_TestStatDirWithSlash_")
if err != nil {
t.Fatalf("TempDir: %s", err)
}
@@ -2089,7 +2090,7 @@ func TestLargeWriteToConsole(t *testing.T) {
func TestStatDirModeExec(t *testing.T) {
const mode = 0111
- path, err := ioutil.TempDir("", "go-build")
+ path, err := os.MkdirTemp("", "go-build")
if err != nil {
t.Fatalf("Failed to create temp directory: %v", err)
}
@@ -2158,7 +2159,7 @@ func TestStatStdin(t *testing.T) {
func TestStatRelativeSymlink(t *testing.T) {
testenv.MustHaveSymlink(t)
- tmpdir, err := ioutil.TempDir("", "TestStatRelativeSymlink")
+ tmpdir, err := os.MkdirTemp("", "TestStatRelativeSymlink")
if err != nil {
t.Fatal(err)
}
@@ -2248,8 +2249,8 @@ func TestLongPath(t *testing.T) {
t.Fatalf("MkdirAll failed: %v", err)
}
data := []byte("hello world\n")
- if err := ioutil.WriteFile(sizedTempDir+"/foo.txt", data, 0644); err != nil {
- t.Fatalf("ioutil.WriteFile() failed: %v", err)
+ if err := os.WriteFile(sizedTempDir+"/foo.txt", data, 0644); err != nil {
+ t.Fatalf("os.WriteFile() failed: %v", err)
}
if err := Rename(sizedTempDir+"/foo.txt", sizedTempDir+"/bar.txt"); err != nil {
t.Fatalf("Rename failed: %v", err)
@@ -2433,7 +2434,7 @@ func TestRemoveAllRace(t *testing.T) {
n := runtime.GOMAXPROCS(16)
defer runtime.GOMAXPROCS(n)
- root, err := ioutil.TempDir("", "issue")
+ root, err := os.MkdirTemp("", "issue")
if err != nil {
t.Fatal(err)
}
@@ -2690,3 +2691,22 @@ func TestDirFS(t *testing.T) {
t.Fatal(err)
}
}
+
+func TestReadFileProc(t *testing.T) {
+ // Linux files in /proc report 0 size,
+ // but then if ReadFile reads just a single byte at offset 0,
+ // the read at offset 1 returns EOF instead of more data.
+ // ReadFile has a minimum read size of 512 to work around this,
+ // but test explicitly that it's working.
+ name := "/proc/sys/fs/pipe-max-size"
+ if _, err := Stat(name); err != nil {
+ t.Skip(err)
+ }
+ data, err := ReadFile(name)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(data) == 0 || data[len(data)-1] != '\n' {
+ t.Fatalf("read %s: not newline-terminated: %q", name, data)
+ }
+}
diff --git a/src/os/os_unix_test.go b/src/os/os_unix_test.go
index 0bce2989c4..51693fd82a 100644
--- a/src/os/os_unix_test.go
+++ b/src/os/os_unix_test.go
@@ -8,7 +8,7 @@ package os_test
import (
"io"
- "io/ioutil"
+ "os"
. "os"
"path/filepath"
"runtime"
@@ -190,7 +190,7 @@ func TestReaddirRemoveRace(t *testing.T) {
}
dir := newDir("TestReaddirRemoveRace", t)
defer RemoveAll(dir)
- if err := ioutil.WriteFile(filepath.Join(dir, "some-file"), []byte("hello"), 0644); err != nil {
+ if err := os.WriteFile(filepath.Join(dir, "some-file"), []byte("hello"), 0644); err != nil {
t.Fatal(err)
}
d, err := Open(dir)
diff --git a/src/os/os_windows_test.go b/src/os/os_windows_test.go
index e002774844..8d1d1f61b2 100644
--- a/src/os/os_windows_test.go
+++ b/src/os/os_windows_test.go
@@ -13,7 +13,6 @@ import (
"internal/testenv"
"io"
"io/fs"
- "io/ioutil"
"os"
osexec "os/exec"
"path/filepath"
@@ -31,7 +30,7 @@ import (
type syscallDescriptor = syscall.Handle
func TestSameWindowsFile(t *testing.T) {
- temp, err := ioutil.TempDir("", "TestSameWindowsFile")
+ temp, err := os.MkdirTemp("", "TestSameWindowsFile")
if err != nil {
t.Fatal(err)
}
@@ -90,7 +89,7 @@ type dirLinkTest struct {
}
func testDirLinks(t *testing.T, tests []dirLinkTest) {
- tmpdir, err := ioutil.TempDir("", "testDirLinks")
+ tmpdir, err := os.MkdirTemp("", "testDirLinks")
if err != nil {
t.Fatal(err)
}
@@ -115,7 +114,7 @@ func testDirLinks(t *testing.T, tests []dirLinkTest) {
if err != nil {
t.Fatal(err)
}
- err = ioutil.WriteFile(filepath.Join(dir, "abc"), []byte("abc"), 0644)
+ err = os.WriteFile(filepath.Join(dir, "abc"), []byte("abc"), 0644)
if err != nil {
t.Fatal(err)
}
@@ -127,7 +126,7 @@ func testDirLinks(t *testing.T, tests []dirLinkTest) {
continue
}
- data, err := ioutil.ReadFile(filepath.Join(link, "abc"))
+ data, err := os.ReadFile(filepath.Join(link, "abc"))
if err != nil {
t.Errorf("failed to read abc file: %v", err)
continue
@@ -439,7 +438,7 @@ func TestNetworkSymbolicLink(t *testing.T) {
const _NERR_ServerNotStarted = syscall.Errno(2114)
- dir, err := ioutil.TempDir("", "TestNetworkSymbolicLink")
+ dir, err := os.MkdirTemp("", "TestNetworkSymbolicLink")
if err != nil {
t.Fatal(err)
}
@@ -600,7 +599,7 @@ func TestStatDir(t *testing.T) {
}
func TestOpenVolumeName(t *testing.T) {
- tmpdir, err := ioutil.TempDir("", "TestOpenVolumeName")
+ tmpdir, err := os.MkdirTemp("", "TestOpenVolumeName")
if err != nil {
t.Fatal(err)
}
@@ -619,7 +618,7 @@ func TestOpenVolumeName(t *testing.T) {
want := []string{"file1", "file2", "file3", "gopher.txt"}
sort.Strings(want)
for _, name := range want {
- err := ioutil.WriteFile(filepath.Join(tmpdir, name), nil, 0777)
+ err := os.WriteFile(filepath.Join(tmpdir, name), nil, 0777)
if err != nil {
t.Fatal(err)
}
@@ -643,7 +642,7 @@ func TestOpenVolumeName(t *testing.T) {
}
func TestDeleteReadOnly(t *testing.T) {
- tmpdir, err := ioutil.TempDir("", "TestDeleteReadOnly")
+ tmpdir, err := os.MkdirTemp("", "TestDeleteReadOnly")
if err != nil {
t.Fatal(err)
}
@@ -804,7 +803,7 @@ func compareCommandLineToArgvWithSyscall(t *testing.T, cmd string) {
}
func TestCmdArgs(t *testing.T) {
- tmpdir, err := ioutil.TempDir("", "TestCmdArgs")
+ tmpdir, err := os.MkdirTemp("", "TestCmdArgs")
if err != nil {
t.Fatal(err)
}
@@ -823,7 +822,7 @@ func main() {
}
`
src := filepath.Join(tmpdir, "main.go")
- err = ioutil.WriteFile(src, []byte(prog), 0666)
+ err = os.WriteFile(src, []byte(prog), 0666)
if err != nil {
t.Fatal(err)
}
@@ -971,14 +970,14 @@ func TestSymlinkCreation(t *testing.T) {
}
t.Parallel()
- temp, err := ioutil.TempDir("", "TestSymlinkCreation")
+ temp, err := os.MkdirTemp("", "TestSymlinkCreation")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(temp)
dummyFile := filepath.Join(temp, "file")
- err = ioutil.WriteFile(dummyFile, []byte(""), 0644)
+ err = os.WriteFile(dummyFile, []byte(""), 0644)
if err != nil {
t.Fatal(err)
}
@@ -1207,7 +1206,7 @@ func mklinkd(t *testing.T, link, target string) {
}
func TestWindowsReadlink(t *testing.T) {
- tmpdir, err := ioutil.TempDir("", "TestWindowsReadlink")
+ tmpdir, err := os.MkdirTemp("", "TestWindowsReadlink")
if err != nil {
t.Fatal(err)
}
@@ -1272,7 +1271,7 @@ func TestWindowsReadlink(t *testing.T) {
testReadlink(t, "reldirlink", "dir")
file := filepath.Join(tmpdir, "file")
- err = ioutil.WriteFile(file, []byte(""), 0666)
+ err = os.WriteFile(file, []byte(""), 0666)
if err != nil {
t.Fatal(err)
}
diff --git a/src/os/path_test.go b/src/os/path_test.go
index 3fe9c5ffa3..b79d958711 100644
--- a/src/os/path_test.go
+++ b/src/os/path_test.go
@@ -6,7 +6,7 @@ package os_test
import (
"internal/testenv"
- "io/ioutil"
+ "os"
. "os"
"path/filepath"
"runtime"
@@ -78,7 +78,7 @@ func TestMkdirAll(t *testing.T) {
func TestMkdirAllWithSymlink(t *testing.T) {
testenv.MustHaveSymlink(t)
- tmpDir, err := ioutil.TempDir("", "TestMkdirAllWithSymlink-")
+ tmpDir, err := os.MkdirTemp("", "TestMkdirAllWithSymlink-")
if err != nil {
t.Fatal(err)
}
diff --git a/src/os/path_windows_test.go b/src/os/path_windows_test.go
index 862b404362..869db8fd6c 100644
--- a/src/os/path_windows_test.go
+++ b/src/os/path_windows_test.go
@@ -5,7 +5,6 @@
package os_test
import (
- "io/ioutil"
"os"
"strings"
"syscall"
@@ -48,7 +47,7 @@ func TestFixLongPath(t *testing.T) {
}
func TestMkdirAllExtendedLength(t *testing.T) {
- tmpDir, err := ioutil.TempDir("", "TestMkdirAllExtendedLength")
+ tmpDir, err := os.MkdirTemp("", "TestMkdirAllExtendedLength")
if err != nil {
t.Fatal(err)
}
diff --git a/src/os/pipe_test.go b/src/os/pipe_test.go
index 0593efec75..b98e53845c 100644
--- a/src/os/pipe_test.go
+++ b/src/os/pipe_test.go
@@ -14,7 +14,6 @@ import (
"internal/testenv"
"io"
"io/fs"
- "io/ioutil"
"os"
osexec "os/exec"
"os/signal"
@@ -161,7 +160,7 @@ func testClosedPipeRace(t *testing.T, read bool) {
// Get the amount we have to write to overload a pipe
// with no reader.
limit = 131073
- if b, err := ioutil.ReadFile("/proc/sys/fs/pipe-max-size"); err == nil {
+ if b, err := os.ReadFile("/proc/sys/fs/pipe-max-size"); err == nil {
if i, err := strconv.Atoi(strings.TrimSpace(string(b))); err == nil {
limit = i + 1
}
diff --git a/src/os/read_test.go b/src/os/read_test.go
new file mode 100644
index 0000000000..5c58d7d7df
--- /dev/null
+++ b/src/os/read_test.go
@@ -0,0 +1,127 @@
+// Copyright 2009 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 os_test
+
+import (
+ "bytes"
+ . "os"
+ "path/filepath"
+ "testing"
+)
+
+func checkNamedSize(t *testing.T, path string, size int64) {
+ dir, err := Stat(path)
+ if err != nil {
+ t.Fatalf("Stat %q (looking for size %d): %s", path, size, err)
+ }
+ if dir.Size() != size {
+ t.Errorf("Stat %q: size %d want %d", path, dir.Size(), size)
+ }
+}
+
+func TestReadFile(t *testing.T) {
+ filename := "rumpelstilzchen"
+ contents, err := ReadFile(filename)
+ if err == nil {
+ t.Fatalf("ReadFile %s: error expected, none found", filename)
+ }
+
+ filename = "read_test.go"
+ contents, err = ReadFile(filename)
+ if err != nil {
+ t.Fatalf("ReadFile %s: %v", filename, err)
+ }
+
+ checkNamedSize(t, filename, int64(len(contents)))
+}
+
+func TestWriteFile(t *testing.T) {
+ f, err := CreateTemp("", "ioutil-test")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer f.Close()
+ defer Remove(f.Name())
+
+ msg := "Programming today is a race between software engineers striving to " +
+ "build bigger and better idiot-proof programs, and the Universe trying " +
+ "to produce bigger and better idiots. So far, the Universe is winning."
+
+ if err := WriteFile(f.Name(), []byte(msg), 0644); err != nil {
+ t.Fatalf("WriteFile %s: %v", f.Name(), err)
+ }
+
+ data, err := ReadFile(f.Name())
+ if err != nil {
+ t.Fatalf("ReadFile %s: %v", f.Name(), err)
+ }
+
+ if string(data) != msg {
+ t.Fatalf("ReadFile: wrong data:\nhave %q\nwant %q", string(data), msg)
+ }
+}
+
+func TestReadOnlyWriteFile(t *testing.T) {
+ if Getuid() == 0 {
+ t.Skipf("Root can write to read-only files anyway, so skip the read-only test.")
+ }
+
+ // We don't want to use CreateTemp directly, since that opens a file for us as 0600.
+ tempDir, err := MkdirTemp("", t.Name())
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer RemoveAll(tempDir)
+ filename := filepath.Join(tempDir, "blurp.txt")
+
+ shmorp := []byte("shmorp")
+ florp := []byte("florp")
+ err = WriteFile(filename, shmorp, 0444)
+ if err != nil {
+ t.Fatalf("WriteFile %s: %v", filename, err)
+ }
+ err = WriteFile(filename, florp, 0444)
+ if err == nil {
+ t.Fatalf("Expected an error when writing to read-only file %s", filename)
+ }
+ got, err := ReadFile(filename)
+ if err != nil {
+ t.Fatalf("ReadFile %s: %v", filename, err)
+ }
+ if !bytes.Equal(got, shmorp) {
+ t.Fatalf("want %s, got %s", shmorp, got)
+ }
+}
+
+func TestReadDir(t *testing.T) {
+ dirname := "rumpelstilzchen"
+ _, err := ReadDir(dirname)
+ if err == nil {
+ t.Fatalf("ReadDir %s: error expected, none found", dirname)
+ }
+
+ dirname = "."
+ list, err := ReadDir(dirname)
+ if err != nil {
+ t.Fatalf("ReadDir %s: %v", dirname, err)
+ }
+
+ foundFile := false
+ foundSubDir := false
+ for _, dir := range list {
+ switch {
+ case !dir.IsDir() && dir.Name() == "read_test.go":
+ foundFile = true
+ case dir.IsDir() && dir.Name() == "exec":
+ foundSubDir = true
+ }
+ }
+ if !foundFile {
+ t.Fatalf("ReadDir %s: read_test.go file not found", dirname)
+ }
+ if !foundSubDir {
+ t.Fatalf("ReadDir %s: exec directory not found", dirname)
+ }
+}
diff --git a/src/os/readfrom_linux_test.go b/src/os/readfrom_linux_test.go
index 00faf39fe5..37047175e6 100644
--- a/src/os/readfrom_linux_test.go
+++ b/src/os/readfrom_linux_test.go
@@ -8,8 +8,8 @@ import (
"bytes"
"internal/poll"
"io"
- "io/ioutil"
"math/rand"
+ "os"
. "os"
"path/filepath"
"strconv"
@@ -173,7 +173,7 @@ func TestCopyFileRange(t *testing.T) {
})
t.Run("Nil", func(t *testing.T) {
var nilFile *File
- anyFile, err := ioutil.TempFile("", "")
+ anyFile, err := os.CreateTemp("", "")
if err != nil {
t.Fatal(err)
}
diff --git a/src/os/removeall_test.go b/src/os/removeall_test.go
index bc9c468ce3..3a2f6e3759 100644
--- a/src/os/removeall_test.go
+++ b/src/os/removeall_test.go
@@ -6,7 +6,7 @@ package os_test
import (
"fmt"
- "io/ioutil"
+ "os"
. "os"
"path/filepath"
"runtime"
@@ -15,7 +15,7 @@ import (
)
func TestRemoveAll(t *testing.T) {
- tmpDir, err := ioutil.TempDir("", "TestRemoveAll-")
+ tmpDir, err := os.MkdirTemp("", "TestRemoveAll-")
if err != nil {
t.Fatal(err)
}
@@ -128,7 +128,7 @@ func TestRemoveAllLarge(t *testing.T) {
t.Skip("skipping in short mode")
}
- tmpDir, err := ioutil.TempDir("", "TestRemoveAll-")
+ tmpDir, err := os.MkdirTemp("", "TestRemoveAll-")
if err != nil {
t.Fatal(err)
}
@@ -169,7 +169,7 @@ func TestRemoveAllLongPath(t *testing.T) {
t.Fatalf("Could not get wd: %s", err)
}
- startPath, err := ioutil.TempDir("", "TestRemoveAllLongPath-")
+ startPath, err := os.MkdirTemp("", "TestRemoveAllLongPath-")
if err != nil {
t.Fatalf("Could not create TempDir: %s", err)
}
@@ -211,7 +211,7 @@ func TestRemoveAllDot(t *testing.T) {
if err != nil {
t.Fatalf("Could not get wd: %s", err)
}
- tempDir, err := ioutil.TempDir("", "TestRemoveAllDot-")
+ tempDir, err := os.MkdirTemp("", "TestRemoveAllDot-")
if err != nil {
t.Fatalf("Could not create TempDir: %s", err)
}
@@ -236,7 +236,7 @@ func TestRemoveAllDot(t *testing.T) {
func TestRemoveAllDotDot(t *testing.T) {
t.Parallel()
- tempDir, err := ioutil.TempDir("", "TestRemoveAllDotDot-")
+ tempDir, err := os.MkdirTemp("", "TestRemoveAllDotDot-")
if err != nil {
t.Fatal(err)
}
@@ -261,7 +261,7 @@ func TestRemoveAllDotDot(t *testing.T) {
func TestRemoveReadOnlyDir(t *testing.T) {
t.Parallel()
- tempDir, err := ioutil.TempDir("", "TestRemoveReadOnlyDir-")
+ tempDir, err := os.MkdirTemp("", "TestRemoveReadOnlyDir-")
if err != nil {
t.Fatal(err)
}
@@ -298,7 +298,7 @@ func TestRemoveAllButReadOnlyAndPathError(t *testing.T) {
t.Parallel()
- tempDir, err := ioutil.TempDir("", "TestRemoveAllButReadOnly-")
+ tempDir, err := os.MkdirTemp("", "TestRemoveAllButReadOnly-")
if err != nil {
t.Fatal(err)
}
@@ -355,11 +355,12 @@ func TestRemoveAllButReadOnlyAndPathError(t *testing.T) {
// The error should be of type *PathError.
// see issue 30491 for details.
if pathErr, ok := err.(*PathError); ok {
- if g, w := pathErr.Path, filepath.Join(tempDir, "b", "y"); g != w {
- t.Errorf("got %q, expected pathErr.path %q", g, w)
+ want := filepath.Join(tempDir, "b", "y")
+ if pathErr.Path != want {
+ t.Errorf("RemoveAll(%q): err.Path=%q, want %q", tempDir, pathErr.Path, want)
}
} else {
- t.Errorf("got %T, expected *fs.PathError", err)
+ t.Errorf("RemoveAll(%q): error has type %T, want *fs.PathError", tempDir, err)
}
for _, dir := range dirs {
@@ -388,7 +389,7 @@ func TestRemoveUnreadableDir(t *testing.T) {
t.Parallel()
- tempDir, err := ioutil.TempDir("", "TestRemoveAllButReadOnly-")
+ tempDir, err := os.MkdirTemp("", "TestRemoveAllButReadOnly-")
if err != nil {
t.Fatal(err)
}
@@ -412,7 +413,7 @@ func TestRemoveAllWithMoreErrorThanReqSize(t *testing.T) {
t.Skip("skipping in short mode")
}
- tmpDir, err := ioutil.TempDir("", "TestRemoveAll-")
+ tmpDir, err := os.MkdirTemp("", "TestRemoveAll-")
if err != nil {
t.Fatal(err)
}
diff --git a/src/os/signal/signal_test.go b/src/os/signal/signal_test.go
index 23e33fe82b..8945cbfccb 100644
--- a/src/os/signal/signal_test.go
+++ b/src/os/signal/signal_test.go
@@ -12,7 +12,6 @@ import (
"flag"
"fmt"
"internal/testenv"
- "io/ioutil"
"os"
"os/exec"
"runtime"
@@ -304,7 +303,7 @@ func TestDetectNohup(t *testing.T) {
os.Remove("nohup.out")
out, err := exec.Command("/usr/bin/nohup", os.Args[0], "-test.run=TestDetectNohup", "-check_sighup_ignored").CombinedOutput()
- data, _ := ioutil.ReadFile("nohup.out")
+ data, _ := os.ReadFile("nohup.out")
os.Remove("nohup.out")
if err != nil {
t.Errorf("ran test with -check_sighup_ignored under nohup and it failed: expected success.\nError: %v\nOutput:\n%s%s", err, out, data)
diff --git a/src/os/signal/signal_windows_test.go b/src/os/signal/signal_windows_test.go
index c2b59010fc..4640428587 100644
--- a/src/os/signal/signal_windows_test.go
+++ b/src/os/signal/signal_windows_test.go
@@ -7,7 +7,6 @@ package signal
import (
"bytes"
"internal/testenv"
- "io/ioutil"
"os"
"os/exec"
"path/filepath"
@@ -57,7 +56,7 @@ func main() {
}
}
`
- tmp, err := ioutil.TempDir("", "TestCtrlBreak")
+ tmp, err := os.MkdirTemp("", "TestCtrlBreak")
if err != nil {
t.Fatal("TempDir failed: ", err)
}
diff --git a/src/os/stat_test.go b/src/os/stat_test.go
index 88b789080e..c409f0ff18 100644
--- a/src/os/stat_test.go
+++ b/src/os/stat_test.go
@@ -7,7 +7,6 @@ package os_test
import (
"internal/testenv"
"io/fs"
- "io/ioutil"
"os"
"path/filepath"
"runtime"
@@ -186,7 +185,7 @@ func testSymlinkSameFile(t *testing.T, path, link string) {
func TestDirAndSymlinkStats(t *testing.T) {
testenv.MustHaveSymlink(t)
- tmpdir, err := ioutil.TempDir("", "TestDirAndSymlinkStats")
+ tmpdir, err := os.MkdirTemp("", "TestDirAndSymlinkStats")
if err != nil {
t.Fatal(err)
}
@@ -219,14 +218,14 @@ func TestDirAndSymlinkStats(t *testing.T) {
func TestFileAndSymlinkStats(t *testing.T) {
testenv.MustHaveSymlink(t)
- tmpdir, err := ioutil.TempDir("", "TestFileAndSymlinkStats")
+ tmpdir, err := os.MkdirTemp("", "TestFileAndSymlinkStats")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmpdir)
file := filepath.Join(tmpdir, "file")
- err = ioutil.WriteFile(file, []byte(""), 0644)
+ err = os.WriteFile(file, []byte(""), 0644)
if err != nil {
t.Fatal(err)
}
@@ -253,7 +252,7 @@ func TestFileAndSymlinkStats(t *testing.T) {
func TestSymlinkWithTrailingSlash(t *testing.T) {
testenv.MustHaveSymlink(t)
- tmpdir, err := ioutil.TempDir("", "TestSymlinkWithTrailingSlash")
+ tmpdir, err := os.MkdirTemp("", "TestSymlinkWithTrailingSlash")
if err != nil {
t.Fatal(err)
}
diff --git a/src/os/tempfile.go b/src/os/tempfile.go
new file mode 100644
index 0000000000..2728485c32
--- /dev/null
+++ b/src/os/tempfile.go
@@ -0,0 +1,118 @@
+// Copyright 2010 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 os
+
+import (
+ "errors"
+ "strings"
+)
+
+// fastrand provided by runtime.
+// We generate random temporary file names so that there's a good
+// chance the file doesn't exist yet - keeps the number of tries in
+// TempFile to a minimum.
+func fastrand() uint32
+
+func nextRandom() string {
+ return uitoa(uint(fastrand()))
+}
+
+// CreateTemp creates a new temporary file in the directory dir,
+// opens the file for reading and writing, and returns the resulting file.
+// The filename is generated by taking pattern and adding a random string to the end.
+// If pattern includes a "*", the random string replaces the last "*".
+// If dir is the empty string, TempFile uses the default directory for temporary files, as returned by TempDir.
+// Multiple programs or goroutines calling CreateTemp simultaneously will not choose the same file.
+// The caller can use the file's Name method to find the pathname of the file.
+// It is the caller's responsibility to remove the file when it is no longer needed.
+func CreateTemp(dir, pattern string) (*File, error) {
+ if dir == "" {
+ dir = TempDir()
+ }
+
+ prefix, suffix, err := prefixAndSuffix(pattern)
+ if err != nil {
+ return nil, &PathError{Op: "createtemp", Path: pattern, Err: err}
+ }
+ prefix = joinPath(dir, prefix)
+
+ try := 0
+ for {
+ name := prefix + nextRandom() + suffix
+ f, err := OpenFile(name, O_RDWR|O_CREATE|O_EXCL, 0600)
+ if IsExist(err) {
+ if try++; try < 10000 {
+ continue
+ }
+ return nil, &PathError{Op: "createtemp", Path: dir + string(PathSeparator) + prefix + "*" + suffix, Err: ErrExist}
+ }
+ return f, err
+ }
+}
+
+var errPatternHasSeparator = errors.New("pattern contains path separator")
+
+// prefixAndSuffix splits pattern by the last wildcard "*", if applicable,
+// returning prefix as the part before "*" and suffix as the part after "*".
+func prefixAndSuffix(pattern string) (prefix, suffix string, err error) {
+ for i := 0; i < len(pattern); i++ {
+ if IsPathSeparator(pattern[i]) {
+ return "", "", errPatternHasSeparator
+ }
+ }
+ if pos := strings.LastIndex(pattern, "*"); pos != -1 {
+ prefix, suffix = pattern[:pos], pattern[pos+1:]
+ } else {
+ prefix = pattern
+ }
+ return prefix, suffix, nil
+}
+
+// MkdirTemp creates a new temporary directory in the directory dir
+// and returns the pathname of the new directory.
+// The new directory's name is generated by adding a random string to the end of pattern.
+// If pattern includes a "*", the random string replaces the last "*" instead.
+// If dir is the empty string, TempFile uses the default directory for temporary files, as returned by TempDir.
+// Multiple programs or goroutines calling MkdirTemp simultaneously will not choose the same directory.
+// It is the caller's responsibility to remove the directory when it is no longer needed.
+func MkdirTemp(dir, pattern string) (string, error) {
+ if dir == "" {
+ dir = TempDir()
+ }
+
+ prefix, suffix, err := prefixAndSuffix(pattern)
+ if err != nil {
+ return "", &PathError{Op: "mkdirtemp", Path: pattern, Err: err}
+ }
+ prefix = joinPath(dir, prefix)
+
+ try := 0
+ for {
+ name := prefix + nextRandom() + suffix
+ err := Mkdir(name, 0700)
+ if err == nil {
+ return name, nil
+ }
+ if IsExist(err) {
+ if try++; try < 10000 {
+ continue
+ }
+ return "", &PathError{Op: "mkdirtemp", Path: dir + string(PathSeparator) + prefix + "*" + suffix, Err: ErrExist}
+ }
+ if IsNotExist(err) {
+ if _, err := Stat(dir); IsNotExist(err) {
+ return "", err
+ }
+ }
+ return "", err
+ }
+}
+
+func joinPath(dir, name string) string {
+ if len(dir) > 0 && IsPathSeparator(dir[len(dir)-1]) {
+ return dir + name
+ }
+ return dir + string(PathSeparator) + name
+}
diff --git a/src/os/tempfile_test.go b/src/os/tempfile_test.go
new file mode 100644
index 0000000000..e71a2444c9
--- /dev/null
+++ b/src/os/tempfile_test.go
@@ -0,0 +1,193 @@
+// Copyright 2010 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 os_test
+
+import (
+ "errors"
+ "io/fs"
+ . "os"
+ "path/filepath"
+ "regexp"
+ "strings"
+ "testing"
+)
+
+func TestCreateTemp(t *testing.T) {
+ dir, err := MkdirTemp("", "TestCreateTempBadDir")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer RemoveAll(dir)
+
+ nonexistentDir := filepath.Join(dir, "_not_exists_")
+ f, err := CreateTemp(nonexistentDir, "foo")
+ if f != nil || err == nil {
+ t.Errorf("CreateTemp(%q, `foo`) = %v, %v", nonexistentDir, f, err)
+ }
+}
+
+func TestCreateTempPattern(t *testing.T) {
+ tests := []struct{ pattern, prefix, suffix string }{
+ {"tempfile_test", "tempfile_test", ""},
+ {"tempfile_test*", "tempfile_test", ""},
+ {"tempfile_test*xyz", "tempfile_test", "xyz"},
+ }
+ for _, test := range tests {
+ f, err := CreateTemp("", test.pattern)
+ if err != nil {
+ t.Errorf("CreateTemp(..., %q) error: %v", test.pattern, err)
+ continue
+ }
+ defer Remove(f.Name())
+ base := filepath.Base(f.Name())
+ f.Close()
+ if !(strings.HasPrefix(base, test.prefix) && strings.HasSuffix(base, test.suffix)) {
+ t.Errorf("CreateTemp pattern %q created bad name %q; want prefix %q & suffix %q",
+ test.pattern, base, test.prefix, test.suffix)
+ }
+ }
+}
+
+func TestCreateTempBadPattern(t *testing.T) {
+ tmpDir, err := MkdirTemp("", t.Name())
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer RemoveAll(tmpDir)
+
+ const sep = string(PathSeparator)
+ tests := []struct {
+ pattern string
+ wantErr bool
+ }{
+ {"ioutil*test", false},
+ {"tempfile_test*foo", false},
+ {"tempfile_test" + sep + "foo", true},
+ {"tempfile_test*" + sep + "foo", true},
+ {"tempfile_test" + sep + "*foo", true},
+ {sep + "tempfile_test" + sep + "*foo", true},
+ {"tempfile_test*foo" + sep, true},
+ }
+ for _, tt := range tests {
+ t.Run(tt.pattern, func(t *testing.T) {
+ tmpfile, err := CreateTemp(tmpDir, tt.pattern)
+ if tmpfile != nil {
+ defer tmpfile.Close()
+ }
+ if tt.wantErr {
+ if err == nil {
+ t.Errorf("CreateTemp(..., %#q) succeeded, expected error", tt.pattern)
+ }
+ if !errors.Is(err, ErrPatternHasSeparator) {
+ t.Errorf("CreateTemp(..., %#q): %v, expected ErrPatternHasSeparator", tt.pattern, err)
+ }
+ } else if err != nil {
+ t.Errorf("CreateTemp(..., %#q): %v", tt.pattern, err)
+ }
+ })
+ }
+}
+
+func TestMkdirTemp(t *testing.T) {
+ name, err := MkdirTemp("/_not_exists_", "foo")
+ if name != "" || err == nil {
+ t.Errorf("MkdirTemp(`/_not_exists_`, `foo`) = %v, %v", name, err)
+ }
+
+ tests := []struct {
+ pattern string
+ wantPrefix, wantSuffix string
+ }{
+ {"tempfile_test", "tempfile_test", ""},
+ {"tempfile_test*", "tempfile_test", ""},
+ {"tempfile_test*xyz", "tempfile_test", "xyz"},
+ }
+
+ dir := filepath.Clean(TempDir())
+
+ runTestMkdirTemp := func(t *testing.T, pattern, wantRePat string) {
+ name, err := MkdirTemp(dir, pattern)
+ if name == "" || err != nil {
+ t.Fatalf("MkdirTemp(dir, `tempfile_test`) = %v, %v", name, err)
+ }
+ defer Remove(name)
+
+ re := regexp.MustCompile(wantRePat)
+ if !re.MatchString(name) {
+ t.Errorf("MkdirTemp(%q, %q) created bad name\n\t%q\ndid not match pattern\n\t%q", dir, pattern, name, wantRePat)
+ }
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.pattern, func(t *testing.T) {
+ wantRePat := "^" + regexp.QuoteMeta(filepath.Join(dir, tt.wantPrefix)) + "[0-9]+" + regexp.QuoteMeta(tt.wantSuffix) + "$"
+ runTestMkdirTemp(t, tt.pattern, wantRePat)
+ })
+ }
+
+ // Separately testing "*xyz" (which has no prefix). That is when constructing the
+ // pattern to assert on, as in the previous loop, using filepath.Join for an empty
+ // prefix filepath.Join(dir, ""), produces the pattern:
+ // ^[0-9]+xyz$
+ // yet we just want to match
+ // "^/[0-9]+xyz"
+ t.Run("*xyz", func(t *testing.T) {
+ wantRePat := "^" + regexp.QuoteMeta(filepath.Join(dir)) + regexp.QuoteMeta(string(filepath.Separator)) + "[0-9]+xyz$"
+ runTestMkdirTemp(t, "*xyz", wantRePat)
+ })
+}
+
+// test that we return a nice error message if the dir argument to TempDir doesn't
+// exist (or that it's empty and TempDir doesn't exist)
+func TestMkdirTempBadDir(t *testing.T) {
+ dir, err := MkdirTemp("", "MkdirTempBadDir")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer RemoveAll(dir)
+
+ badDir := filepath.Join(dir, "not-exist")
+ _, err = MkdirTemp(badDir, "foo")
+ if pe, ok := err.(*fs.PathError); !ok || !IsNotExist(err) || pe.Path != badDir {
+ t.Errorf("TempDir error = %#v; want PathError for path %q satisifying IsNotExist", err, badDir)
+ }
+}
+
+func TestMkdirTempBadPattern(t *testing.T) {
+ tmpDir, err := MkdirTemp("", t.Name())
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer RemoveAll(tmpDir)
+
+ const sep = string(PathSeparator)
+ tests := []struct {
+ pattern string
+ wantErr bool
+ }{
+ {"ioutil*test", false},
+ {"tempfile_test*foo", false},
+ {"tempfile_test" + sep + "foo", true},
+ {"tempfile_test*" + sep + "foo", true},
+ {"tempfile_test" + sep + "*foo", true},
+ {sep + "tempfile_test" + sep + "*foo", true},
+ {"tempfile_test*foo" + sep, true},
+ }
+ for _, tt := range tests {
+ t.Run(tt.pattern, func(t *testing.T) {
+ _, err := MkdirTemp(tmpDir, tt.pattern)
+ if tt.wantErr {
+ if err == nil {
+ t.Errorf("MkdirTemp(..., %#q) succeeded, expected error", tt.pattern)
+ }
+ if !errors.Is(err, ErrPatternHasSeparator) {
+ t.Errorf("MkdirTemp(..., %#q): %v, expected ErrPatternHasSeparator", tt.pattern, err)
+ }
+ } else if err != nil {
+ t.Errorf("MkdirTemp(..., %#q): %v", tt.pattern, err)
+ }
+ })
+ }
+}
diff --git a/src/os/testdata/hello b/src/os/testdata/hello
new file mode 100644
index 0000000000..e47c092a51
--- /dev/null
+++ b/src/os/testdata/hello
@@ -0,0 +1 @@
+Hello, Gophers!
diff --git a/src/os/timeout_test.go b/src/os/timeout_test.go
index d848e41642..0a39f46333 100644
--- a/src/os/timeout_test.go
+++ b/src/os/timeout_test.go
@@ -11,7 +11,6 @@ package os_test
import (
"fmt"
"io"
- "io/ioutil"
"math/rand"
"os"
"os/signal"
@@ -29,7 +28,7 @@ func TestNonpollableDeadline(t *testing.T) {
t.Skipf("skipping on %s", runtime.GOOS)
}
- f, err := ioutil.TempFile("", "ostest")
+ f, err := os.CreateTemp("", "ostest")
if err != nil {
t.Fatal(err)
}
diff --git a/src/os/user/lookup_plan9.go b/src/os/user/lookup_plan9.go
index ea3ce0bc7c..33ae3a6adf 100644
--- a/src/os/user/lookup_plan9.go
+++ b/src/os/user/lookup_plan9.go
@@ -6,7 +6,6 @@ package user
import (
"fmt"
- "io/ioutil"
"os"
"syscall"
)
@@ -23,7 +22,7 @@ func init() {
}
func current() (*User, error) {
- ubytes, err := ioutil.ReadFile(userFile)
+ ubytes, err := os.ReadFile(userFile)
if err != nil {
return nil, fmt.Errorf("user: %s", err)
}
diff --git a/src/path/filepath/example_unix_walk_test.go b/src/path/filepath/example_unix_walk_test.go
index 66dc7f6b53..c8a818fd6e 100644
--- a/src/path/filepath/example_unix_walk_test.go
+++ b/src/path/filepath/example_unix_walk_test.go
@@ -9,13 +9,12 @@ package filepath_test
import (
"fmt"
"io/fs"
- "io/ioutil"
"os"
"path/filepath"
)
func prepareTestDirTree(tree string) (string, error) {
- tmpDir, err := ioutil.TempDir("", "")
+ tmpDir, err := os.MkdirTemp("", "")
if err != nil {
return "", fmt.Errorf("error creating temp directory: %v\n", err)
}
diff --git a/src/path/filepath/match_test.go b/src/path/filepath/match_test.go
index 1c3b567fa3..48880ea439 100644
--- a/src/path/filepath/match_test.go
+++ b/src/path/filepath/match_test.go
@@ -7,7 +7,6 @@ package filepath_test
import (
"fmt"
"internal/testenv"
- "io/ioutil"
"os"
. "path/filepath"
"reflect"
@@ -182,7 +181,7 @@ var globSymlinkTests = []struct {
func TestGlobSymlink(t *testing.T) {
testenv.MustHaveSymlink(t)
- tmpDir, err := ioutil.TempDir("", "globsymlink")
+ tmpDir, err := os.MkdirTemp("", "globsymlink")
if err != nil {
t.Fatal("creating temp dir:", err)
}
@@ -268,7 +267,7 @@ func TestWindowsGlob(t *testing.T) {
t.Skipf("skipping windows specific test")
}
- tmpDir, err := ioutil.TempDir("", "TestWindowsGlob")
+ tmpDir, err := os.MkdirTemp("", "TestWindowsGlob")
if err != nil {
t.Fatal(err)
}
@@ -302,7 +301,7 @@ func TestWindowsGlob(t *testing.T) {
}
}
for _, file := range files {
- err := ioutil.WriteFile(Join(tmpDir, file), nil, 0666)
+ err := os.WriteFile(Join(tmpDir, file), nil, 0666)
if err != nil {
t.Fatal(err)
}
diff --git a/src/path/filepath/path_test.go b/src/path/filepath/path_test.go
index d760530e26..8616256ac0 100644
--- a/src/path/filepath/path_test.go
+++ b/src/path/filepath/path_test.go
@@ -9,7 +9,6 @@ import (
"fmt"
"internal/testenv"
"io/fs"
- "io/ioutil"
"os"
"path/filepath"
"reflect"
@@ -416,7 +415,7 @@ func chtmpdir(t *testing.T) (restore func()) {
if err != nil {
t.Fatalf("chtmpdir: %v", err)
}
- d, err := ioutil.TempDir("", "test")
+ d, err := os.MkdirTemp("", "test")
if err != nil {
t.Fatalf("chtmpdir: %v", err)
}
@@ -459,7 +458,7 @@ func testWalk(t *testing.T, walk func(string, fs.WalkDirFunc) error, errVisit in
defer restore()
}
- tmpDir, err := ioutil.TempDir("", "TestWalk")
+ tmpDir, err := os.MkdirTemp("", "TestWalk")
if err != nil {
t.Fatal("creating temp dir:", err)
}
@@ -563,7 +562,7 @@ func touch(t *testing.T, name string) {
}
func TestWalkSkipDirOnFile(t *testing.T) {
- td, err := ioutil.TempDir("", "walktest")
+ td, err := os.MkdirTemp("", "walktest")
if err != nil {
t.Fatal(err)
}
@@ -613,7 +612,7 @@ func TestWalkSkipDirOnFile(t *testing.T) {
}
func TestWalkFileError(t *testing.T) {
- td, err := ioutil.TempDir("", "walktest")
+ td, err := os.MkdirTemp("", "walktest")
if err != nil {
t.Fatal(err)
}
@@ -892,7 +891,7 @@ func testEvalSymlinksAfterChdir(t *testing.T, wd, path, want string) {
func TestEvalSymlinks(t *testing.T) {
testenv.MustHaveSymlink(t)
- tmpDir, err := ioutil.TempDir("", "evalsymlink")
+ tmpDir, err := os.MkdirTemp("", "evalsymlink")
if err != nil {
t.Fatal("creating temp dir:", err)
}
@@ -978,7 +977,7 @@ func TestEvalSymlinksIsNotExist(t *testing.T) {
func TestIssue13582(t *testing.T) {
testenv.MustHaveSymlink(t)
- tmpDir, err := ioutil.TempDir("", "issue13582")
+ tmpDir, err := os.MkdirTemp("", "issue13582")
if err != nil {
t.Fatal(err)
}
@@ -995,7 +994,7 @@ func TestIssue13582(t *testing.T) {
t.Fatal(err)
}
file := filepath.Join(linkToDir, "file")
- err = ioutil.WriteFile(file, nil, 0644)
+ err = os.WriteFile(file, nil, 0644)
if err != nil {
t.Fatal(err)
}
@@ -1065,7 +1064,7 @@ var absTests = []string{
}
func TestAbs(t *testing.T) {
- root, err := ioutil.TempDir("", "TestAbs")
+ root, err := os.MkdirTemp("", "TestAbs")
if err != nil {
t.Fatal("TempDir failed: ", err)
}
@@ -1136,7 +1135,7 @@ func TestAbs(t *testing.T) {
// We test it separately from all other absTests because the empty string is not
// a valid path, so it can't be used with os.Stat.
func TestAbsEmptyString(t *testing.T) {
- root, err := ioutil.TempDir("", "TestAbsEmptyString")
+ root, err := os.MkdirTemp("", "TestAbsEmptyString")
if err != nil {
t.Fatal("TempDir failed: ", err)
}
@@ -1357,7 +1356,7 @@ func TestBug3486(t *testing.T) { // https://golang.org/issue/3486
}
func testWalkSymlink(t *testing.T, mklink func(target, link string) error) {
- tmpdir, err := ioutil.TempDir("", "testWalkSymlink")
+ tmpdir, err := os.MkdirTemp("", "testWalkSymlink")
if err != nil {
t.Fatal(err)
}
@@ -1407,14 +1406,14 @@ func TestWalkSymlink(t *testing.T) {
}
func TestIssue29372(t *testing.T) {
- tmpDir, err := ioutil.TempDir("", "TestIssue29372")
+ tmpDir, err := os.MkdirTemp("", "TestIssue29372")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmpDir)
path := filepath.Join(tmpDir, "file.txt")
- err = ioutil.WriteFile(path, nil, 0644)
+ err = os.WriteFile(path, nil, 0644)
if err != nil {
t.Fatal(err)
}
@@ -1443,7 +1442,7 @@ func TestEvalSymlinksAboveRoot(t *testing.T) {
t.Parallel()
- tmpDir, err := ioutil.TempDir("", "TestEvalSymlinksAboveRoot")
+ tmpDir, err := os.MkdirTemp("", "TestEvalSymlinksAboveRoot")
if err != nil {
t.Fatal(err)
}
@@ -1460,7 +1459,7 @@ func TestEvalSymlinksAboveRoot(t *testing.T) {
if err := os.Symlink(filepath.Join(evalTmpDir, "a"), filepath.Join(evalTmpDir, "b")); err != nil {
t.Fatal(err)
}
- if err := ioutil.WriteFile(filepath.Join(evalTmpDir, "a", "file"), nil, 0666); err != nil {
+ if err := os.WriteFile(filepath.Join(evalTmpDir, "a", "file"), nil, 0666); err != nil {
t.Fatal(err)
}
@@ -1491,7 +1490,7 @@ func TestEvalSymlinksAboveRoot(t *testing.T) {
func TestEvalSymlinksAboveRootChdir(t *testing.T) {
testenv.MustHaveSymlink(t)
- tmpDir, err := ioutil.TempDir("", "TestEvalSymlinksAboveRootChdir")
+ tmpDir, err := os.MkdirTemp("", "TestEvalSymlinksAboveRootChdir")
if err != nil {
t.Fatal(err)
}
@@ -1514,7 +1513,7 @@ func TestEvalSymlinksAboveRootChdir(t *testing.T) {
if err := os.Symlink(subdir, "c"); err != nil {
t.Fatal(err)
}
- if err := ioutil.WriteFile(filepath.Join(subdir, "file"), nil, 0666); err != nil {
+ if err := os.WriteFile(filepath.Join(subdir, "file"), nil, 0666); err != nil {
t.Fatal(err)
}
diff --git a/src/path/filepath/path_windows_test.go b/src/path/filepath/path_windows_test.go
index 9309a7dc4d..1c3d84c62d 100644
--- a/src/path/filepath/path_windows_test.go
+++ b/src/path/filepath/path_windows_test.go
@@ -9,7 +9,6 @@ import (
"fmt"
"internal/testenv"
"io/fs"
- "io/ioutil"
"os"
"os/exec"
"path/filepath"
@@ -38,7 +37,7 @@ func testWinSplitListTestIsValid(t *testing.T, ti int, tt SplitListTest,
perm fs.FileMode = 0700
)
- tmp, err := ioutil.TempDir("", "testWinSplitListTestIsValid")
+ tmp, err := os.MkdirTemp("", "testWinSplitListTestIsValid")
if err != nil {
t.Fatalf("TempDir failed: %v", err)
}
@@ -63,7 +62,7 @@ func testWinSplitListTestIsValid(t *testing.T, ti int, tt SplitListTest,
return
}
fn, data := filepath.Join(dd, cmdfile), []byte("@echo "+d+"\r\n")
- if err = ioutil.WriteFile(fn, data, perm); err != nil {
+ if err = os.WriteFile(fn, data, perm); err != nil {
t.Errorf("%d,%d: WriteFile(%#q) failed: %v", ti, i, fn, err)
return
}
@@ -104,7 +103,7 @@ func testWinSplitListTestIsValid(t *testing.T, ti int, tt SplitListTest,
func TestWindowsEvalSymlinks(t *testing.T) {
testenv.MustHaveSymlink(t)
- tmpDir, err := ioutil.TempDir("", "TestWindowsEvalSymlinks")
+ tmpDir, err := os.MkdirTemp("", "TestWindowsEvalSymlinks")
if err != nil {
t.Fatal(err)
}
@@ -162,13 +161,13 @@ func TestWindowsEvalSymlinks(t *testing.T) {
// TestEvalSymlinksCanonicalNames verify that EvalSymlinks
// returns "canonical" path names on windows.
func TestEvalSymlinksCanonicalNames(t *testing.T) {
- tmp, err := ioutil.TempDir("", "evalsymlinkcanonical")
+ tmp, err := os.MkdirTemp("", "evalsymlinkcanonical")
if err != nil {
t.Fatal("creating temp dir:", err)
}
defer os.RemoveAll(tmp)
- // ioutil.TempDir might return "non-canonical" name.
+ // os.MkdirTemp might return "non-canonical" name.
cTmpName, err := filepath.EvalSymlinks(tmp)
if err != nil {
t.Errorf("EvalSymlinks(%q) error: %v", tmp, err)
@@ -418,7 +417,7 @@ func TestToNorm(t *testing.T) {
{".", `\\localhost\c$`, `\\localhost\c$`},
}
- tmp, err := ioutil.TempDir("", "testToNorm")
+ tmp, err := os.MkdirTemp("", "testToNorm")
if err != nil {
t.Fatal(err)
}
@@ -429,7 +428,7 @@ func TestToNorm(t *testing.T) {
}
}()
- // ioutil.TempDir might return "non-canonical" name.
+ // os.MkdirTemp might return "non-canonical" name.
ctmp, err := filepath.EvalSymlinks(tmp)
if err != nil {
t.Fatal(err)
@@ -527,7 +526,7 @@ func TestNTNamespaceSymlink(t *testing.T) {
t.Skip("skipping test because mklink command does not support junctions")
}
- tmpdir, err := ioutil.TempDir("", "TestNTNamespaceSymlink")
+ tmpdir, err := os.MkdirTemp("", "TestNTNamespaceSymlink")
if err != nil {
t.Fatal(err)
}
@@ -564,7 +563,7 @@ func TestNTNamespaceSymlink(t *testing.T) {
testenv.MustHaveSymlink(t)
file := filepath.Join(tmpdir, "file")
- err = ioutil.WriteFile(file, []byte(""), 0666)
+ err = os.WriteFile(file, []byte(""), 0666)
if err != nil {
t.Fatal(err)
}
diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go
index a12712d254..b01158635f 100644
--- a/src/reflect/all_test.go
+++ b/src/reflect/all_test.go
@@ -4007,9 +4007,12 @@ var convertTests = []struct {
{V(int16(-3)), V(string("\uFFFD"))},
{V(int32(-4)), V(string("\uFFFD"))},
{V(int64(-5)), V(string("\uFFFD"))},
+ {V(int64(-1 << 32)), V(string("\uFFFD"))},
+ {V(int64(1 << 32)), V(string("\uFFFD"))},
{V(uint(0x110001)), V(string("\uFFFD"))},
{V(uint32(0x110002)), V(string("\uFFFD"))},
{V(uint64(0x110003)), V(string("\uFFFD"))},
+ {V(uint64(1 << 32)), V(string("\uFFFD"))},
{V(uintptr(0x110004)), V(string("\uFFFD"))},
// named string
diff --git a/src/reflect/type.go b/src/reflect/type.go
index a2076bb3f1..1f1e70d485 100644
--- a/src/reflect/type.go
+++ b/src/reflect/type.go
@@ -1104,12 +1104,16 @@ type StructField struct {
// A StructTag is the tag string in a struct field.
//
-// By convention, tag strings are a concatenation of
-// optionally space-separated key:"value" pairs.
-// Each key is a non-empty string consisting of non-control
-// characters other than space (U+0020 ' '), quote (U+0022 '"'),
-// and colon (U+003A ':'). Each value is quoted using U+0022 '"'
-// characters and Go string literal syntax.
+// By convention, tag strings are a mapping of keys to values.
+// The format is key:"value". Each key is a non-empty string consisting
+// of non-control characters other than space (U+0020 ' '),
+// quote (U+0022 '"'), and colon (U+003A ':'). Each value is quoted
+// using U+0022 '"' characters and Go string literal syntax.
+// Multiple key-value mappings are separated by zero or more spaces, as in
+// key1:"value1" key2:"value2"
+// Multiple keys may map to a single shared value by separating the keys
+// with spaces, as in
+// key1 key2:"value"
type StructTag string
// Get returns the value associated with key in the tag string.
diff --git a/src/reflect/value.go b/src/reflect/value.go
index bf926a7453..1f185b52e4 100644
--- a/src/reflect/value.go
+++ b/src/reflect/value.go
@@ -2681,12 +2681,20 @@ func cvtComplex(v Value, t Type) Value {
// convertOp: intXX -> string
func cvtIntString(v Value, t Type) Value {
- return makeString(v.flag.ro(), string(rune(v.Int())), t)
+ s := "\uFFFD"
+ if x := v.Int(); int64(rune(x)) == x {
+ s = string(rune(x))
+ }
+ return makeString(v.flag.ro(), s, t)
}
// convertOp: uintXX -> string
func cvtUintString(v Value, t Type) Value {
- return makeString(v.flag.ro(), string(rune(v.Uint())), t)
+ s := "\uFFFD"
+ if x := v.Uint(); uint64(rune(x)) == x {
+ s = string(rune(x))
+ }
+ return makeString(v.flag.ro(), s, t)
}
// convertOp: []byte -> string
diff --git a/src/runtime/cgo/linux_syscall.c b/src/runtime/cgo/linux_syscall.c
index c8e91918a1..56f3d67d8b 100644
--- a/src/runtime/cgo/linux_syscall.c
+++ b/src/runtime/cgo/linux_syscall.c
@@ -10,7 +10,7 @@
#include
#include
-#include
+#include
#include
#include "libcgo.h"
diff --git a/src/runtime/crash_test.go b/src/runtime/crash_test.go
index 5e22b7593e..58ad4f3eba 100644
--- a/src/runtime/crash_test.go
+++ b/src/runtime/crash_test.go
@@ -9,7 +9,6 @@ import (
"flag"
"fmt"
"internal/testenv"
- "io/ioutil"
"os"
"os/exec"
"path/filepath"
@@ -117,7 +116,7 @@ func buildTestProg(t *testing.T, binary string, flags ...string) (string, error)
testprog.Lock()
defer testprog.Unlock()
if testprog.dir == "" {
- dir, err := ioutil.TempDir("", "go-build")
+ dir, err := os.MkdirTemp("", "go-build")
if err != nil {
t.Fatalf("failed to create temp directory: %v", err)
}
diff --git a/src/runtime/crash_unix_test.go b/src/runtime/crash_unix_test.go
index c50d62d552..803b031873 100644
--- a/src/runtime/crash_unix_test.go
+++ b/src/runtime/crash_unix_test.go
@@ -10,7 +10,6 @@ import (
"bytes"
"internal/testenv"
"io"
- "io/ioutil"
"os"
"os/exec"
"path/filepath"
@@ -85,13 +84,13 @@ func TestCrashDumpsAllThreads(t *testing.T) {
t.Parallel()
- dir, err := ioutil.TempDir("", "go-build")
+ dir, err := os.MkdirTemp("", "go-build")
if err != nil {
t.Fatalf("failed to create temp directory: %v", err)
}
defer os.RemoveAll(dir)
- if err := ioutil.WriteFile(filepath.Join(dir, "main.go"), []byte(crashDumpsAllThreadsSource), 0666); err != nil {
+ if err := os.WriteFile(filepath.Join(dir, "main.go"), []byte(crashDumpsAllThreadsSource), 0666); err != nil {
t.Fatalf("failed to create Go file: %v", err)
}
@@ -244,7 +243,7 @@ func TestPanicSystemstack(t *testing.T) {
// we don't have a way to know when it is fully blocked, sleep a bit to
// make us less likely to lose the race and signal before the child
// blocks.
- time.Sleep(100*time.Millisecond)
+ time.Sleep(100 * time.Millisecond)
// Send SIGQUIT.
if err := cmd.Process.Signal(syscall.SIGQUIT); err != nil {
diff --git a/src/runtime/debug/heapdump_test.go b/src/runtime/debug/heapdump_test.go
index de1ec27d21..768934d05d 100644
--- a/src/runtime/debug/heapdump_test.go
+++ b/src/runtime/debug/heapdump_test.go
@@ -5,7 +5,6 @@
package debug_test
import (
- "io/ioutil"
"os"
"runtime"
. "runtime/debug"
@@ -16,7 +15,7 @@ func TestWriteHeapDumpNonempty(t *testing.T) {
if runtime.GOOS == "js" {
t.Skipf("WriteHeapDump is not available on %s.", runtime.GOOS)
}
- f, err := ioutil.TempFile("", "heapdumptest")
+ f, err := os.CreateTemp("", "heapdumptest")
if err != nil {
t.Fatalf("TempFile failed: %v", err)
}
@@ -45,7 +44,7 @@ func TestWriteHeapDumpFinalizers(t *testing.T) {
if runtime.GOOS == "js" {
t.Skipf("WriteHeapDump is not available on %s.", runtime.GOOS)
}
- f, err := ioutil.TempFile("", "heapdumptest")
+ f, err := os.CreateTemp("", "heapdumptest")
if err != nil {
t.Fatalf("TempFile failed: %v", err)
}
diff --git a/src/runtime/debug_test.go b/src/runtime/debug_test.go
index 722e81121f..a0b3f84382 100644
--- a/src/runtime/debug_test.go
+++ b/src/runtime/debug_test.go
@@ -17,7 +17,7 @@ package runtime_test
import (
"fmt"
- "io/ioutil"
+ "os"
"regexp"
"runtime"
"runtime/debug"
@@ -95,7 +95,7 @@ func debugCallTKill(tid int) error {
// Linux-specific.
func skipUnderDebugger(t *testing.T) {
pid := syscall.Getpid()
- status, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/status", pid))
+ status, err := os.ReadFile(fmt.Sprintf("/proc/%d/status", pid))
if err != nil {
t.Logf("couldn't get proc tracer: %s", err)
return
diff --git a/src/runtime/env_plan9.go b/src/runtime/env_plan9.go
index b7ea863735..f1ac4760a7 100644
--- a/src/runtime/env_plan9.go
+++ b/src/runtime/env_plan9.go
@@ -23,8 +23,8 @@ const (
// to the (possibly shared) Plan 9 environment, so that Setenv and Getenv
// conform to the same Posix semantics as on other operating systems.
// For Plan 9 shared environment semantics, instead of Getenv(key) and
-// Setenv(key, value), one can use ioutil.ReadFile("/env/" + key) and
-// ioutil.WriteFile("/env/" + key, value, 0666) respectively.
+// Setenv(key, value), one can use os.ReadFile("/env/" + key) and
+// os.WriteFile("/env/" + key, value, 0666) respectively.
//go:nosplit
func goenvs() {
buf := make([]byte, envBufSize)
diff --git a/src/runtime/internal/sys/gengoos.go b/src/runtime/internal/sys/gengoos.go
index 2a4bf0c3b4..9bbc48d94f 100644
--- a/src/runtime/internal/sys/gengoos.go
+++ b/src/runtime/internal/sys/gengoos.go
@@ -9,8 +9,8 @@ package main
import (
"bytes"
"fmt"
- "io/ioutil"
"log"
+ "os"
"strconv"
"strings"
)
@@ -18,7 +18,7 @@ import (
var gooses, goarches []string
func main() {
- data, err := ioutil.ReadFile("../../../go/build/syslist.go")
+ data, err := os.ReadFile("../../../go/build/syslist.go")
if err != nil {
log.Fatal(err)
}
@@ -68,7 +68,7 @@ func main() {
}
fmt.Fprintf(&buf, "const Goos%s = %d\n", strings.Title(goos), value)
}
- err := ioutil.WriteFile("zgoos_"+target+".go", buf.Bytes(), 0666)
+ err := os.WriteFile("zgoos_"+target+".go", buf.Bytes(), 0666)
if err != nil {
log.Fatal(err)
}
@@ -90,7 +90,7 @@ func main() {
}
fmt.Fprintf(&buf, "const Goarch%s = %d\n", strings.Title(goarch), value)
}
- err := ioutil.WriteFile("zgoarch_"+target+".go", buf.Bytes(), 0666)
+ err := os.WriteFile("zgoarch_"+target+".go", buf.Bytes(), 0666)
if err != nil {
log.Fatal(err)
}
diff --git a/src/runtime/memmove_linux_amd64_test.go b/src/runtime/memmove_linux_amd64_test.go
index d0e8b42a5a..b3ccd907b9 100644
--- a/src/runtime/memmove_linux_amd64_test.go
+++ b/src/runtime/memmove_linux_amd64_test.go
@@ -5,7 +5,6 @@
package runtime_test
import (
- "io/ioutil"
"os"
"reflect"
"syscall"
@@ -18,7 +17,7 @@ import (
func TestMemmoveOverflow(t *testing.T) {
t.Parallel()
// Create a temporary file.
- tmp, err := ioutil.TempFile("", "go-memmovetest")
+ tmp, err := os.CreateTemp("", "go-memmovetest")
if err != nil {
t.Fatal(err)
}
diff --git a/src/runtime/metrics/description_test.go b/src/runtime/metrics/description_test.go
index e966a281a1..448639ee77 100644
--- a/src/runtime/metrics/description_test.go
+++ b/src/runtime/metrics/description_test.go
@@ -7,9 +7,7 @@ package metrics_test
import (
"bufio"
"os"
- "path/filepath"
"regexp"
- "runtime"
"runtime/metrics"
"strings"
"testing"
@@ -26,17 +24,9 @@ func TestDescriptionNameFormat(t *testing.T) {
}
func extractMetricDocs(t *testing.T) map[string]string {
- if runtime.GOOS == "android" {
- t.Skip("no access to Go source on android")
- }
-
- // Get doc.go.
- _, filename, _, _ := runtime.Caller(0)
- filename = filepath.Join(filepath.Dir(filename), "doc.go")
-
- f, err := os.Open(filename)
+ f, err := os.Open("doc.go")
if err != nil {
- t.Fatal(err)
+ t.Fatalf("failed to open doc.go in runtime/metrics package: %v", err)
}
const (
stateSearch = iota // look for list of metrics
@@ -90,7 +80,7 @@ func extractMetricDocs(t *testing.T) map[string]string {
}
}
if state == stateSearch {
- t.Fatalf("failed to find supported metrics docs in %s", filename)
+ t.Fatalf("failed to find supported metrics docs in %s", f.Name())
}
return result
}
diff --git a/src/runtime/mkduff.go b/src/runtime/mkduff.go
index 6ddf0256e9..94ae75fbfe 100644
--- a/src/runtime/mkduff.go
+++ b/src/runtime/mkduff.go
@@ -27,8 +27,8 @@ import (
"bytes"
"fmt"
"io"
- "io/ioutil"
"log"
+ "os"
)
func main() {
@@ -54,7 +54,7 @@ func gen(arch string, tags, zero, copy func(io.Writer)) {
fmt.Fprintln(&buf)
copy(&buf)
- if err := ioutil.WriteFile("duff_"+arch+".s", buf.Bytes(), 0644); err != nil {
+ if err := os.WriteFile("duff_"+arch+".s", buf.Bytes(), 0644); err != nil {
log.Fatalln(err)
}
}
diff --git a/src/runtime/mkfastlog2table.go b/src/runtime/mkfastlog2table.go
index 305c84a7c1..d650292394 100644
--- a/src/runtime/mkfastlog2table.go
+++ b/src/runtime/mkfastlog2table.go
@@ -12,9 +12,9 @@ package main
import (
"bytes"
"fmt"
- "io/ioutil"
"log"
"math"
+ "os"
)
func main() {
@@ -36,7 +36,7 @@ func main() {
}
fmt.Fprintln(&buf, "}")
- if err := ioutil.WriteFile("fastlog2table.go", buf.Bytes(), 0644); err != nil {
+ if err := os.WriteFile("fastlog2table.go", buf.Bytes(), 0644); err != nil {
log.Fatalln(err)
}
}
diff --git a/src/runtime/mksizeclasses.go b/src/runtime/mksizeclasses.go
index 1a210953a4..b92d1fed5f 100644
--- a/src/runtime/mksizeclasses.go
+++ b/src/runtime/mksizeclasses.go
@@ -35,7 +35,6 @@ import (
"fmt"
"go/format"
"io"
- "io/ioutil"
"log"
"os"
)
@@ -65,7 +64,7 @@ func main() {
if *stdout {
_, err = os.Stdout.Write(out)
} else {
- err = ioutil.WriteFile("sizeclasses.go", out, 0666)
+ err = os.WriteFile("sizeclasses.go", out, 0666)
}
if err != nil {
log.Fatal(err)
diff --git a/src/runtime/msan.go b/src/runtime/msan.go
index c0f3957e28..6a5960b0a8 100644
--- a/src/runtime/msan.go
+++ b/src/runtime/msan.go
@@ -50,8 +50,12 @@ func msanmalloc(addr unsafe.Pointer, sz uintptr)
//go:noescape
func msanfree(addr unsafe.Pointer, sz uintptr)
-// These are called from msan_amd64.s
+//go:noescape
+func msanmove(dst, src unsafe.Pointer, sz uintptr)
+
+// These are called from msan_GOARCH.s
//go:cgo_import_static __msan_read_go
//go:cgo_import_static __msan_write_go
//go:cgo_import_static __msan_malloc_go
//go:cgo_import_static __msan_free_go
+//go:cgo_import_static __msan_memmove
diff --git a/src/runtime/msan_amd64.s b/src/runtime/msan_amd64.s
index cbe739df53..669e9ca73f 100644
--- a/src/runtime/msan_amd64.s
+++ b/src/runtime/msan_amd64.s
@@ -58,6 +58,15 @@ TEXT runtime·msanfree(SB), NOSPLIT, $0-16
MOVQ $__msan_free_go(SB), AX
JMP msancall<>(SB)
+// func runtime·msanmove(dst, src unsafe.Pointer, sz uintptr)
+TEXT runtime·msanmove(SB), NOSPLIT, $0-24
+ MOVQ dst+0(FP), RARG0
+ MOVQ src+8(FP), RARG1
+ MOVQ size+16(FP), RARG2
+ // void __msan_memmove(void *dst, void *src, uintptr_t sz);
+ MOVQ $__msan_memmove(SB), AX
+ JMP msancall<>(SB)
+
// Switches SP to g0 stack and calls (AX). Arguments already set.
TEXT msancall<>(SB), NOSPLIT, $0-0
get_tls(R12)
diff --git a/src/runtime/msan_arm64.s b/src/runtime/msan_arm64.s
index 5e29f1aefb..f19906cfc8 100644
--- a/src/runtime/msan_arm64.s
+++ b/src/runtime/msan_arm64.s
@@ -9,6 +9,7 @@
#define RARG0 R0
#define RARG1 R1
+#define RARG2 R2
#define FARG R3
// func runtime·domsanread(addr unsafe.Pointer, sz uintptr)
@@ -45,6 +46,15 @@ TEXT runtime·msanfree(SB), NOSPLIT, $0-16
MOVD $__msan_free_go(SB), FARG
JMP msancall<>(SB)
+// func runtime·msanmove(dst, src unsafe.Pointer, sz uintptr)
+TEXT runtime·msanmove(SB), NOSPLIT, $0-24
+ MOVD dst+0(FP), RARG0
+ MOVD src+8(FP), RARG1
+ MOVD size+16(FP), RARG2
+ // void __msan_memmove(void *dst, void *src, uintptr_t sz);
+ MOVD $__msan_memmove(SB), FARG
+ JMP msancall<>(SB)
+
// Switches SP to g0 stack and calls (FARG). Arguments already set.
TEXT msancall<>(SB), NOSPLIT, $0-0
MOVD RSP, R19 // callee-saved
diff --git a/src/runtime/os2_aix.go b/src/runtime/os2_aix.go
index 428ff7f225..abd1010be9 100644
--- a/src/runtime/os2_aix.go
+++ b/src/runtime/os2_aix.go
@@ -18,11 +18,11 @@ import (
//go:cgo_import_dynamic libc___n_pthreads __n_pthreads "libpthread.a/shr_xpg5_64.o"
//go:cgo_import_dynamic libc___mod_init __mod_init "libc.a/shr_64.o"
-//go:linkname libc___n_pthreads libc___n_pthread
+//go:linkname libc___n_pthreads libc___n_pthreads
//go:linkname libc___mod_init libc___mod_init
var (
- libc___n_pthread,
+ libc___n_pthreads,
libc___mod_init libFunc
)
diff --git a/src/runtime/os_darwin.go b/src/runtime/os_darwin.go
index 3f5bb7cf96..e0a43c28aa 100644
--- a/src/runtime/os_darwin.go
+++ b/src/runtime/os_darwin.go
@@ -130,6 +130,18 @@ func osinit() {
physPageSize = getPageSize()
}
+func sysctlbynameInt32(name []byte) (int32, int32) {
+ out := int32(0)
+ nout := unsafe.Sizeof(out)
+ ret := sysctlbyname(&name[0], (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
+ return ret, out
+}
+
+//go:linkname internal_cpu_getsysctlbyname internal/cpu.getsysctlbyname
+func internal_cpu_getsysctlbyname(name []byte) (int32, int32) {
+ return sysctlbynameInt32(name)
+}
+
const (
_CTL_HW = 6
_HW_NCPU = 3
@@ -283,6 +295,12 @@ func libpreinit() {
func mpreinit(mp *m) {
mp.gsignal = malg(32 * 1024) // OS X wants >= 8K
mp.gsignal.m = mp
+ if GOOS == "darwin" && GOARCH == "arm64" {
+ // mlock the signal stack to work around a kernel bug where it may
+ // SIGILL when the signal stack is not faulted in while a signal
+ // arrives. See issue 42774.
+ mlock(unsafe.Pointer(mp.gsignal.stack.hi-physPageSize), physPageSize)
+ }
}
// Called to initialize a new m (including the bootstrap m).
diff --git a/src/runtime/os_linux_be64.go b/src/runtime/os_linux_be64.go
index 14fbad5d5f..9860002ee4 100644
--- a/src/runtime/os_linux_be64.go
+++ b/src/runtime/os_linux_be64.go
@@ -38,6 +38,7 @@ func sigdelset(mask *sigset, i int) {
*mask &^= 1 << (uint(i) - 1)
}
+//go:nosplit
func sigfillset(mask *uint64) {
*mask = ^uint64(0)
}
diff --git a/src/runtime/os_linux_generic.go b/src/runtime/os_linux_generic.go
index 14810e3cc3..e1d0952ddf 100644
--- a/src/runtime/os_linux_generic.go
+++ b/src/runtime/os_linux_generic.go
@@ -38,6 +38,7 @@ func sigdelset(mask *sigset, i int) {
(*mask)[(i-1)/32] &^= 1 << ((uint32(i) - 1) & 31)
}
+//go:nosplit
func sigfillset(mask *uint64) {
*mask = ^uint64(0)
}
diff --git a/src/runtime/os_linux_mips64x.go b/src/runtime/os_linux_mips64x.go
index 4ff66f9538..815a83a04b 100644
--- a/src/runtime/os_linux_mips64x.go
+++ b/src/runtime/os_linux_mips64x.go
@@ -48,6 +48,7 @@ func sigdelset(mask *sigset, i int) {
(*mask)[(i-1)/64] &^= 1 << ((uint32(i) - 1) & 63)
}
+//go:nosplit
func sigfillset(mask *[2]uint64) {
(*mask)[0], (*mask)[1] = ^uint64(0), ^uint64(0)
}
diff --git a/src/runtime/os_linux_mipsx.go b/src/runtime/os_linux_mipsx.go
index 87962ed982..00fb02e4bf 100644
--- a/src/runtime/os_linux_mipsx.go
+++ b/src/runtime/os_linux_mipsx.go
@@ -42,6 +42,7 @@ func sigdelset(mask *sigset, i int) {
(*mask)[(i-1)/32] &^= 1 << ((uint32(i) - 1) & 31)
}
+//go:nosplit
func sigfillset(mask *[4]uint32) {
(*mask)[0], (*mask)[1], (*mask)[2], (*mask)[3] = ^uint32(0), ^uint32(0), ^uint32(0), ^uint32(0)
}
diff --git a/src/runtime/pprof/pprof_test.go b/src/runtime/pprof/pprof_test.go
index 43307aeab9..b6ee160e84 100644
--- a/src/runtime/pprof/pprof_test.go
+++ b/src/runtime/pprof/pprof_test.go
@@ -13,7 +13,6 @@ import (
"internal/profile"
"internal/testenv"
"io"
- "io/ioutil"
"math/big"
"os"
"os/exec"
@@ -286,6 +285,10 @@ func testCPUProfile(t *testing.T, matches matchFunc, need []string, avoid []stri
if runtime.GOARCH == "arm" || runtime.GOARCH == "arm64" {
broken = true
}
+ case "windows":
+ if runtime.GOARCH == "arm" {
+ broken = true // See https://golang.org/issues/42862
+ }
}
maxDuration := 5 * time.Second
@@ -1175,7 +1178,7 @@ func TestLabelRace(t *testing.T) {
// Check that there is no deadlock when the program receives SIGPROF while in
// 64bit atomics' critical section. Used to happen on mips{,le}. See #20146.
func TestAtomicLoadStore64(t *testing.T) {
- f, err := ioutil.TempFile("", "profatomic")
+ f, err := os.CreateTemp("", "profatomic")
if err != nil {
t.Fatalf("TempFile: %v", err)
}
@@ -1204,7 +1207,7 @@ func TestAtomicLoadStore64(t *testing.T) {
func TestTracebackAll(t *testing.T) {
// With gccgo, if a profiling signal arrives at the wrong time
// during traceback, it may crash or hang. See issue #29448.
- f, err := ioutil.TempFile("", "proftraceback")
+ f, err := os.CreateTemp("", "proftraceback")
if err != nil {
t.Fatalf("TempFile: %v", err)
}
diff --git a/src/runtime/pprof/proto.go b/src/runtime/pprof/proto.go
index 8519af6985..bdb4454b6e 100644
--- a/src/runtime/pprof/proto.go
+++ b/src/runtime/pprof/proto.go
@@ -9,7 +9,7 @@ import (
"compress/gzip"
"fmt"
"io"
- "io/ioutil"
+ "os"
"runtime"
"strconv"
"time"
@@ -575,7 +575,7 @@ func (b *profileBuilder) emitLocation() uint64 {
// It saves the address ranges of the mappings in b.mem for use
// when emitting locations.
func (b *profileBuilder) readMapping() {
- data, _ := ioutil.ReadFile("/proc/self/maps")
+ data, _ := os.ReadFile("/proc/self/maps")
parseProcSelfMaps(data, b.addMapping)
if len(b.mem) == 0 { // pprof expects a map entry, so fake one.
b.addMappingEntry(0, 0, 0, "", "", true)
diff --git a/src/runtime/pprof/proto_test.go b/src/runtime/pprof/proto_test.go
index 3043d5353f..5eb1aab140 100644
--- a/src/runtime/pprof/proto_test.go
+++ b/src/runtime/pprof/proto_test.go
@@ -10,7 +10,6 @@ import (
"fmt"
"internal/profile"
"internal/testenv"
- "io/ioutil"
"os"
"os/exec"
"reflect"
@@ -78,7 +77,7 @@ func testPCs(t *testing.T) (addr1, addr2 uint64, map1, map2 *profile.Mapping) {
switch runtime.GOOS {
case "linux", "android", "netbsd":
// Figure out two addresses from /proc/self/maps.
- mmap, err := ioutil.ReadFile("/proc/self/maps")
+ mmap, err := os.ReadFile("/proc/self/maps")
if err != nil {
t.Fatal(err)
}
diff --git a/src/runtime/proc.go b/src/runtime/proc.go
index 0319de5fde..64e102fb0a 100644
--- a/src/runtime/proc.go
+++ b/src/runtime/proc.go
@@ -1363,7 +1363,7 @@ found:
checkdead()
unlock(&sched.lock)
- if GOOS == "darwin" {
+ if GOOS == "darwin" || GOOS == "ios" {
// Make sure pendingPreemptSignals is correct when an M exits.
// For #41702.
if atomic.Load(&m.signalPending) != 0 {
@@ -3852,7 +3852,7 @@ func syscall_runtime_BeforeExec() {
// On Darwin, wait for all pending preemption signals to
// be received. See issue #41702.
- if GOOS == "darwin" {
+ if GOOS == "darwin" || GOOS == "ios" {
for int32(atomic.Load(&pendingPreemptSignals)) > 0 {
osyield()
}
diff --git a/src/runtime/race/output_test.go b/src/runtime/race/output_test.go
index 5d0192f67f..986667332f 100644
--- a/src/runtime/race/output_test.go
+++ b/src/runtime/race/output_test.go
@@ -8,7 +8,6 @@ package race_test
import (
"internal/testenv"
- "io/ioutil"
"os"
"os/exec"
"path/filepath"
@@ -19,7 +18,7 @@ import (
)
func TestOutput(t *testing.T) {
- pkgdir, err := ioutil.TempDir("", "go-build-race-output")
+ pkgdir, err := os.MkdirTemp("", "go-build-race-output")
if err != nil {
t.Fatal(err)
}
@@ -34,7 +33,7 @@ func TestOutput(t *testing.T) {
t.Logf("test %v runs only on %v, skipping: ", test.name, test.goos)
continue
}
- dir, err := ioutil.TempDir("", "go-build")
+ dir, err := os.MkdirTemp("", "go-build")
if err != nil {
t.Fatalf("failed to create temp directory: %v", err)
}
diff --git a/src/runtime/race/testdata/io_test.go b/src/runtime/race/testdata/io_test.go
index 30a121bee4..c5055f7837 100644
--- a/src/runtime/race/testdata/io_test.go
+++ b/src/runtime/race/testdata/io_test.go
@@ -6,7 +6,6 @@ package race_test
import (
"fmt"
- "io/ioutil"
"net"
"net/http"
"os"
@@ -18,7 +17,7 @@ import (
func TestNoRaceIOFile(t *testing.T) {
x := 0
- path, _ := ioutil.TempDir("", "race_test")
+ path, _ := os.MkdirTemp("", "race_test")
fname := filepath.Join(path, "data")
go func() {
x = 42
diff --git a/src/runtime/runtime-gdb_test.go b/src/runtime/runtime-gdb_test.go
index e52bd1c4c4..5df8c3c745 100644
--- a/src/runtime/runtime-gdb_test.go
+++ b/src/runtime/runtime-gdb_test.go
@@ -8,7 +8,6 @@ import (
"bytes"
"fmt"
"internal/testenv"
- "io/ioutil"
"os"
"os/exec"
"path/filepath"
@@ -170,7 +169,7 @@ func testGdbPython(t *testing.T, cgo bool) {
checkGdbVersion(t)
checkGdbPython(t)
- dir, err := ioutil.TempDir("", "go-build")
+ dir, err := os.MkdirTemp("", "go-build")
if err != nil {
t.Fatalf("failed to create temp directory: %v", err)
}
@@ -195,7 +194,7 @@ func testGdbPython(t *testing.T, cgo bool) {
}
}
- err = ioutil.WriteFile(filepath.Join(dir, "main.go"), src, 0644)
+ err = os.WriteFile(filepath.Join(dir, "main.go"), src, 0644)
if err != nil {
t.Fatalf("failed to create file: %v", err)
}
@@ -404,7 +403,7 @@ func TestGdbBacktrace(t *testing.T) {
t.Parallel()
checkGdbVersion(t)
- dir, err := ioutil.TempDir("", "go-build")
+ dir, err := os.MkdirTemp("", "go-build")
if err != nil {
t.Fatalf("failed to create temp directory: %v", err)
}
@@ -412,7 +411,7 @@ func TestGdbBacktrace(t *testing.T) {
// Build the source code.
src := filepath.Join(dir, "main.go")
- err = ioutil.WriteFile(src, []byte(backtraceSource), 0644)
+ err = os.WriteFile(src, []byte(backtraceSource), 0644)
if err != nil {
t.Fatalf("failed to create file: %v", err)
}
@@ -482,7 +481,7 @@ func TestGdbAutotmpTypes(t *testing.T) {
t.Skip("TestGdbAutotmpTypes is too slow on aix/ppc64")
}
- dir, err := ioutil.TempDir("", "go-build")
+ dir, err := os.MkdirTemp("", "go-build")
if err != nil {
t.Fatalf("failed to create temp directory: %v", err)
}
@@ -490,7 +489,7 @@ func TestGdbAutotmpTypes(t *testing.T) {
// Build the source code.
src := filepath.Join(dir, "main.go")
- err = ioutil.WriteFile(src, []byte(autotmpTypeSource), 0644)
+ err = os.WriteFile(src, []byte(autotmpTypeSource), 0644)
if err != nil {
t.Fatalf("failed to create file: %v", err)
}
@@ -551,7 +550,7 @@ func TestGdbConst(t *testing.T) {
t.Parallel()
checkGdbVersion(t)
- dir, err := ioutil.TempDir("", "go-build")
+ dir, err := os.MkdirTemp("", "go-build")
if err != nil {
t.Fatalf("failed to create temp directory: %v", err)
}
@@ -559,7 +558,7 @@ func TestGdbConst(t *testing.T) {
// Build the source code.
src := filepath.Join(dir, "main.go")
- err = ioutil.WriteFile(src, []byte(constsSource), 0644)
+ err = os.WriteFile(src, []byte(constsSource), 0644)
if err != nil {
t.Fatalf("failed to create file: %v", err)
}
@@ -618,7 +617,7 @@ func TestGdbPanic(t *testing.T) {
t.Parallel()
checkGdbVersion(t)
- dir, err := ioutil.TempDir("", "go-build")
+ dir, err := os.MkdirTemp("", "go-build")
if err != nil {
t.Fatalf("failed to create temp directory: %v", err)
}
@@ -626,7 +625,7 @@ func TestGdbPanic(t *testing.T) {
// Build the source code.
src := filepath.Join(dir, "main.go")
- err = ioutil.WriteFile(src, []byte(panicSource), 0644)
+ err = os.WriteFile(src, []byte(panicSource), 0644)
if err != nil {
t.Fatalf("failed to create file: %v", err)
}
@@ -696,7 +695,7 @@ func TestGdbInfCallstack(t *testing.T) {
t.Parallel()
checkGdbVersion(t)
- dir, err := ioutil.TempDir("", "go-build")
+ dir, err := os.MkdirTemp("", "go-build")
if err != nil {
t.Fatalf("failed to create temp directory: %v", err)
}
@@ -704,7 +703,7 @@ func TestGdbInfCallstack(t *testing.T) {
// Build the source code.
src := filepath.Join(dir, "main.go")
- err = ioutil.WriteFile(src, []byte(InfCallstackSource), 0644)
+ err = os.WriteFile(src, []byte(InfCallstackSource), 0644)
if err != nil {
t.Fatalf("failed to create file: %v", err)
}
diff --git a/src/runtime/runtime-lldb_test.go b/src/runtime/runtime-lldb_test.go
index 1e2e5d5be9..c923b872aa 100644
--- a/src/runtime/runtime-lldb_test.go
+++ b/src/runtime/runtime-lldb_test.go
@@ -6,7 +6,6 @@ package runtime_test
import (
"internal/testenv"
- "io/ioutil"
"os"
"os/exec"
"path/filepath"
@@ -143,20 +142,20 @@ func TestLldbPython(t *testing.T) {
checkLldbPython(t)
- dir, err := ioutil.TempDir("", "go-build")
+ dir, err := os.MkdirTemp("", "go-build")
if err != nil {
t.Fatalf("failed to create temp directory: %v", err)
}
defer os.RemoveAll(dir)
src := filepath.Join(dir, "main.go")
- err = ioutil.WriteFile(src, []byte(lldbHelloSource), 0644)
+ err = os.WriteFile(src, []byte(lldbHelloSource), 0644)
if err != nil {
t.Fatalf("failed to create src file: %v", err)
}
mod := filepath.Join(dir, "go.mod")
- err = ioutil.WriteFile(mod, []byte("module lldbtest"), 0644)
+ err = os.WriteFile(mod, []byte("module lldbtest"), 0644)
if err != nil {
t.Fatalf("failed to create mod file: %v", err)
}
@@ -172,7 +171,7 @@ func TestLldbPython(t *testing.T) {
}
src = filepath.Join(dir, "script.py")
- err = ioutil.WriteFile(src, []byte(lldbScriptSource), 0755)
+ err = os.WriteFile(src, []byte(lldbScriptSource), 0755)
if err != nil {
t.Fatalf("failed to create script: %v", err)
}
diff --git a/src/runtime/signal_unix.go b/src/runtime/signal_unix.go
index 6aad079f03..e8f39c3321 100644
--- a/src/runtime/signal_unix.go
+++ b/src/runtime/signal_unix.go
@@ -336,7 +336,7 @@ func doSigPreempt(gp *g, ctxt *sigctxt) {
atomic.Xadd(&gp.m.preemptGen, 1)
atomic.Store(&gp.m.signalPending, 0)
- if GOOS == "darwin" {
+ if GOOS == "darwin" || GOOS == "ios" {
atomic.Xadd(&pendingPreemptSignals, -1)
}
}
@@ -352,12 +352,12 @@ const preemptMSupported = true
func preemptM(mp *m) {
// On Darwin, don't try to preempt threads during exec.
// Issue #41702.
- if GOOS == "darwin" {
+ if GOOS == "darwin" || GOOS == "ios" {
execLock.rlock()
}
if atomic.Cas(&mp.signalPending, 0, 1) {
- if GOOS == "darwin" {
+ if GOOS == "darwin" || GOOS == "ios" {
atomic.Xadd(&pendingPreemptSignals, 1)
}
@@ -369,7 +369,7 @@ func preemptM(mp *m) {
signalM(mp, sigPreempt)
}
- if GOOS == "darwin" {
+ if GOOS == "darwin" || GOOS == "ios" {
execLock.runlock()
}
}
@@ -432,7 +432,7 @@ func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) {
// no non-Go signal handler for sigPreempt.
// The default behavior for sigPreempt is to ignore
// the signal, so badsignal will be a no-op anyway.
- if GOOS == "darwin" {
+ if GOOS == "darwin" || GOOS == "ios" {
atomic.Xadd(&pendingPreemptSignals, -1)
}
return
diff --git a/src/runtime/signal_windows.go b/src/runtime/signal_windows.go
index 6d98d02598..3af2e39b08 100644
--- a/src/runtime/signal_windows.go
+++ b/src/runtime/signal_windows.go
@@ -43,16 +43,9 @@ func initExceptionHandler() {
//
//go:nosplit
func isAbort(r *context) bool {
- switch GOARCH {
- case "386", "amd64":
- // In the case of an abort, the exception IP is one byte after
- // the INT3 (this differs from UNIX OSes).
- return isAbortPC(r.ip() - 1)
- case "arm":
- return isAbortPC(r.ip())
- default:
- return false
- }
+ // In the case of an abort, the exception IP is one byte after
+ // the INT3 (this differs from UNIX OSes).
+ return isAbortPC(r.ip() - 1)
}
// isgoexception reports whether this exception should be translated
diff --git a/src/runtime/signal_windows_test.go b/src/runtime/signal_windows_test.go
index f99857193c..a5a885c2f7 100644
--- a/src/runtime/signal_windows_test.go
+++ b/src/runtime/signal_windows_test.go
@@ -7,7 +7,6 @@ import (
"bytes"
"fmt"
"internal/testenv"
- "io/ioutil"
"os"
"os/exec"
"path/filepath"
@@ -28,7 +27,7 @@ func TestVectoredHandlerDontCrashOnLibrary(t *testing.T) {
testenv.MustHaveExecPath(t, "gcc")
testprog.Lock()
defer testprog.Unlock()
- dir, err := ioutil.TempDir("", "go-build")
+ dir, err := os.MkdirTemp("", "go-build")
if err != nil {
t.Fatalf("failed to create temp directory: %v", err)
}
@@ -93,7 +92,7 @@ func TestLibraryCtrlHandler(t *testing.T) {
testenv.MustHaveExecPath(t, "gcc")
testprog.Lock()
defer testprog.Unlock()
- dir, err := ioutil.TempDir("", "go-build")
+ dir, err := os.MkdirTemp("", "go-build")
if err != nil {
t.Fatalf("failed to create temp directory: %v", err)
}
diff --git a/src/runtime/stubs.go b/src/runtime/stubs.go
index d77cb4d460..b55c3c0590 100644
--- a/src/runtime/stubs.go
+++ b/src/runtime/stubs.go
@@ -133,6 +133,9 @@ func sync_fastrand() uint32 { return fastrand() }
//go:linkname net_fastrand net.fastrand
func net_fastrand() uint32 { return fastrand() }
+//go:linkname os_fastrand os.fastrand
+func os_fastrand() uint32 { return fastrand() }
+
// in internal/bytealg/equal_*.s
//go:noescape
func memequal(a, b unsafe.Pointer, size uintptr) bool
diff --git a/src/runtime/sys_darwin.go b/src/runtime/sys_darwin.go
index a7983be2ef..c89ce78012 100644
--- a/src/runtime/sys_darwin.go
+++ b/src/runtime/sys_darwin.go
@@ -226,6 +226,13 @@ func madvise(addr unsafe.Pointer, n uintptr, flags int32) {
}
func madvise_trampoline()
+//go:nosplit
+//go:cgo_unsafe_args
+func mlock(addr unsafe.Pointer, n uintptr) {
+ libcCall(unsafe.Pointer(funcPC(mlock_trampoline)), unsafe.Pointer(&addr))
+}
+func mlock_trampoline()
+
//go:nosplit
//go:cgo_unsafe_args
func read(fd int32, p unsafe.Pointer, n int32) int32 {
@@ -353,11 +360,18 @@ func setitimer_trampoline()
//go:nosplit
//go:cgo_unsafe_args
-func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32 {
+func sysctl(mib *uint32, miblen uint32, oldp *byte, oldlenp *uintptr, newp *byte, newlen uintptr) int32 {
return libcCall(unsafe.Pointer(funcPC(sysctl_trampoline)), unsafe.Pointer(&mib))
}
func sysctl_trampoline()
+//go:nosplit
+//go:cgo_unsafe_args
+func sysctlbyname(name *byte, oldp *byte, oldlenp *uintptr, newp *byte, newlen uintptr) int32 {
+ return libcCall(unsafe.Pointer(funcPC(sysctlbyname_trampoline)), unsafe.Pointer(&name))
+}
+func sysctlbyname_trampoline()
+
//go:nosplit
//go:cgo_unsafe_args
func fcntl(fd, cmd, arg int32) int32 {
@@ -465,6 +479,7 @@ func setNonblock(fd int32) {
//go:cgo_import_dynamic libc_mmap mmap "/usr/lib/libSystem.B.dylib"
//go:cgo_import_dynamic libc_munmap munmap "/usr/lib/libSystem.B.dylib"
//go:cgo_import_dynamic libc_madvise madvise "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic libc_mlock mlock "/usr/lib/libSystem.B.dylib"
//go:cgo_import_dynamic libc_error __error "/usr/lib/libSystem.B.dylib"
//go:cgo_import_dynamic libc_usleep usleep "/usr/lib/libSystem.B.dylib"
@@ -478,6 +493,7 @@ func setNonblock(fd int32) {
//go:cgo_import_dynamic libc_kill kill "/usr/lib/libSystem.B.dylib"
//go:cgo_import_dynamic libc_setitimer setitimer "/usr/lib/libSystem.B.dylib"
//go:cgo_import_dynamic libc_sysctl sysctl "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic libc_sysctlbyname sysctlbyname "/usr/lib/libSystem.B.dylib"
//go:cgo_import_dynamic libc_fcntl fcntl "/usr/lib/libSystem.B.dylib"
//go:cgo_import_dynamic libc_kqueue kqueue "/usr/lib/libSystem.B.dylib"
//go:cgo_import_dynamic libc_kevent kevent "/usr/lib/libSystem.B.dylib"
diff --git a/src/runtime/sys_darwin_amd64.s b/src/runtime/sys_darwin_amd64.s
index 129e1e1a96..630fb5df64 100644
--- a/src/runtime/sys_darwin_amd64.s
+++ b/src/runtime/sys_darwin_amd64.s
@@ -105,6 +105,9 @@ TEXT runtime·madvise_trampoline(SB), NOSPLIT, $0
POPQ BP
RET
+TEXT runtime·mlock_trampoline(SB), NOSPLIT, $0
+ UNDEF // unimplemented
+
GLOBL timebase<>(SB),NOPTR,$(machTimebaseInfo__size)
TEXT runtime·nanotime_trampoline(SB),NOSPLIT,$0
@@ -368,15 +371,27 @@ TEXT runtime·sysctl_trampoline(SB),NOSPLIT,$0
PUSHQ BP
MOVQ SP, BP
MOVL 8(DI), SI // arg 2 miblen
- MOVQ 16(DI), DX // arg 3 out
- MOVQ 24(DI), CX // arg 4 size
- MOVQ 32(DI), R8 // arg 5 dst
- MOVQ 40(DI), R9 // arg 6 ndst
+ MOVQ 16(DI), DX // arg 3 oldp
+ MOVQ 24(DI), CX // arg 4 oldlenp
+ MOVQ 32(DI), R8 // arg 5 newp
+ MOVQ 40(DI), R9 // arg 6 newlen
MOVQ 0(DI), DI // arg 1 mib
CALL libc_sysctl(SB)
POPQ BP
RET
+TEXT runtime·sysctlbyname_trampoline(SB),NOSPLIT,$0
+ PUSHQ BP
+ MOVQ SP, BP
+ MOVQ 8(DI), SI // arg 2 oldp
+ MOVQ 16(DI), DX // arg 3 oldlenp
+ MOVQ 24(DI), CX // arg 4 newp
+ MOVQ 32(DI), R8 // arg 5 newlen
+ MOVQ 0(DI), DI // arg 1 name
+ CALL libc_sysctlbyname(SB)
+ POPQ BP
+ RET
+
TEXT runtime·kqueue_trampoline(SB),NOSPLIT,$0
PUSHQ BP
MOVQ SP, BP
diff --git a/src/runtime/sys_darwin_arm64.s b/src/runtime/sys_darwin_arm64.s
index 88cdb281d4..96d2ed1076 100644
--- a/src/runtime/sys_darwin_arm64.s
+++ b/src/runtime/sys_darwin_arm64.s
@@ -120,6 +120,12 @@ TEXT runtime·madvise_trampoline(SB),NOSPLIT,$0
BL libc_madvise(SB)
RET
+TEXT runtime·mlock_trampoline(SB),NOSPLIT,$0
+ MOVD 8(R0), R1 // arg 2 len
+ MOVD 0(R0), R0 // arg 1 addr
+ BL libc_mlock(SB)
+ RET
+
TEXT runtime·setitimer_trampoline(SB),NOSPLIT,$0
MOVD 8(R0), R1 // arg 2 new
MOVD 16(R0), R2 // arg 3 old
@@ -295,14 +301,24 @@ TEXT runtime·usleep_trampoline(SB),NOSPLIT,$0
TEXT runtime·sysctl_trampoline(SB),NOSPLIT,$0
MOVW 8(R0), R1 // arg 2 miblen
- MOVD 16(R0), R2 // arg 3 out
- MOVD 24(R0), R3 // arg 4 size
- MOVD 32(R0), R4 // arg 5 dst
- MOVD 40(R0), R5 // arg 6 ndst
+ MOVD 16(R0), R2 // arg 3 oldp
+ MOVD 24(R0), R3 // arg 4 oldlenp
+ MOVD 32(R0), R4 // arg 5 newp
+ MOVD 40(R0), R5 // arg 6 newlen
MOVD 0(R0), R0 // arg 1 mib
BL libc_sysctl(SB)
RET
+TEXT runtime·sysctlbyname_trampoline(SB),NOSPLIT,$0
+ MOVD 8(R0), R1 // arg 2 oldp
+ MOVD 16(R0), R2 // arg 3 oldlenp
+ MOVD 24(R0), R3 // arg 4 newp
+ MOVD 32(R0), R4 // arg 5 newlen
+ MOVD 0(R0), R0 // arg 1 name
+ BL libc_sysctlbyname(SB)
+ RET
+
+
TEXT runtime·kqueue_trampoline(SB),NOSPLIT,$0
BL libc_kqueue(SB)
RET
diff --git a/src/runtime/sys_openbsd_mips64.s b/src/runtime/sys_openbsd_mips64.s
index 57a5dbd40e..3e4d209081 100644
--- a/src/runtime/sys_openbsd_mips64.s
+++ b/src/runtime/sys_openbsd_mips64.s
@@ -244,8 +244,8 @@ TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
MOVW sig+8(FP), R4
MOVV info+16(FP), R5
MOVV ctx+24(FP), R6
- MOVV fn+0(FP), R7
- CALL (R7) // Alignment for ELF ABI?
+ MOVV fn+0(FP), R25 // Must use R25, needed for PIC code.
+ CALL (R25)
RET
TEXT runtime·sigtramp(SB),NOSPLIT,$192
diff --git a/src/runtime/syscall2_solaris.go b/src/runtime/syscall2_solaris.go
index e098e8006a..3310489202 100644
--- a/src/runtime/syscall2_solaris.go
+++ b/src/runtime/syscall2_solaris.go
@@ -15,7 +15,6 @@ import _ "unsafe" // for go:linkname
//go:cgo_import_dynamic libc_gethostname gethostname "libc.so"
//go:cgo_import_dynamic libc_getpid getpid "libc.so"
//go:cgo_import_dynamic libc_ioctl ioctl "libc.so"
-//go:cgo_import_dynamic libc_pipe pipe "libc.so"
//go:cgo_import_dynamic libc_setgid setgid "libc.so"
//go:cgo_import_dynamic libc_setgroups setgroups "libc.so"
//go:cgo_import_dynamic libc_setsid setsid "libc.so"
@@ -33,7 +32,6 @@ import _ "unsafe" // for go:linkname
//go:linkname libc_gethostname libc_gethostname
//go:linkname libc_getpid libc_getpid
//go:linkname libc_ioctl libc_ioctl
-//go:linkname libc_pipe libc_pipe
//go:linkname libc_setgid libc_setgid
//go:linkname libc_setgroups libc_setgroups
//go:linkname libc_setsid libc_setsid
diff --git a/src/runtime/syscall_windows_test.go b/src/runtime/syscall_windows_test.go
index 3827c6ed83..fb215b3c31 100644
--- a/src/runtime/syscall_windows_test.go
+++ b/src/runtime/syscall_windows_test.go
@@ -10,7 +10,6 @@ import (
"internal/syscall/windows/sysdll"
"internal/testenv"
"io"
- "io/ioutil"
"math"
"os"
"os/exec"
@@ -446,7 +445,7 @@ func TestStdcallAndCDeclCallbacks(t *testing.T) {
if _, err := exec.LookPath("gcc"); err != nil {
t.Skip("skipping test: gcc is missing")
}
- tmp, err := ioutil.TempDir("", "TestCDeclCallback")
+ tmp, err := os.MkdirTemp("", "TestCDeclCallback")
if err != nil {
t.Fatal("TempDir failed: ", err)
}
@@ -602,14 +601,14 @@ uintptr_t cfunc(callback f, uintptr_t n) {
return r;
}
`
- tmpdir, err := ioutil.TempDir("", "TestReturnAfterStackGrowInCallback")
+ tmpdir, err := os.MkdirTemp("", "TestReturnAfterStackGrowInCallback")
if err != nil {
t.Fatal("TempDir failed: ", err)
}
defer os.RemoveAll(tmpdir)
srcname := "mydll.c"
- err = ioutil.WriteFile(filepath.Join(tmpdir, srcname), []byte(src), 0)
+ err = os.WriteFile(filepath.Join(tmpdir, srcname), []byte(src), 0)
if err != nil {
t.Fatal(err)
}
@@ -671,14 +670,14 @@ uintptr_t cfunc(uintptr_t a, double b, float c, double d) {
return 0;
}
`
- tmpdir, err := ioutil.TempDir("", "TestFloatArgs")
+ tmpdir, err := os.MkdirTemp("", "TestFloatArgs")
if err != nil {
t.Fatal("TempDir failed: ", err)
}
defer os.RemoveAll(tmpdir)
srcname := "mydll.c"
- err = ioutil.WriteFile(filepath.Join(tmpdir, srcname), []byte(src), 0)
+ err = os.WriteFile(filepath.Join(tmpdir, srcname), []byte(src), 0)
if err != nil {
t.Fatal(err)
}
@@ -733,14 +732,14 @@ double cfuncDouble(uintptr_t a, double b, float c, double d) {
return 0;
}
`
- tmpdir, err := ioutil.TempDir("", "TestFloatReturn")
+ tmpdir, err := os.MkdirTemp("", "TestFloatReturn")
if err != nil {
t.Fatal("TempDir failed: ", err)
}
defer os.RemoveAll(tmpdir)
srcname := "mydll.c"
- err = ioutil.WriteFile(filepath.Join(tmpdir, srcname), []byte(src), 0)
+ err = os.WriteFile(filepath.Join(tmpdir, srcname), []byte(src), 0)
if err != nil {
t.Fatal(err)
}
@@ -948,7 +947,7 @@ func TestDLLPreloadMitigation(t *testing.T) {
t.Skip("skipping test: gcc is missing")
}
- tmpdir, err := ioutil.TempDir("", "TestDLLPreloadMitigation")
+ tmpdir, err := os.MkdirTemp("", "TestDLLPreloadMitigation")
if err != nil {
t.Fatal("TempDir failed: ", err)
}
@@ -969,12 +968,13 @@ func TestDLLPreloadMitigation(t *testing.T) {
#include
#include
-uintptr_t cfunc() {
+uintptr_t cfunc(void) {
SetLastError(123);
+ return 0;
}
`
srcname := "nojack.c"
- err = ioutil.WriteFile(filepath.Join(tmpdir, srcname), []byte(src), 0)
+ err = os.WriteFile(filepath.Join(tmpdir, srcname), []byte(src), 0)
if err != nil {
t.Fatal(err)
}
@@ -1034,7 +1034,7 @@ func TestBigStackCallbackSyscall(t *testing.T) {
t.Fatal("Abs failed: ", err)
}
- tmpdir, err := ioutil.TempDir("", "TestBigStackCallback")
+ tmpdir, err := os.MkdirTemp("", "TestBigStackCallback")
if err != nil {
t.Fatal("TempDir failed: ", err)
}
@@ -1183,14 +1183,14 @@ func BenchmarkOsYield(b *testing.B) {
}
func BenchmarkRunningGoProgram(b *testing.B) {
- tmpdir, err := ioutil.TempDir("", "BenchmarkRunningGoProgram")
+ tmpdir, err := os.MkdirTemp("", "BenchmarkRunningGoProgram")
if err != nil {
b.Fatal(err)
}
defer os.RemoveAll(tmpdir)
src := filepath.Join(tmpdir, "main.go")
- err = ioutil.WriteFile(src, []byte(benchmarkRunningGoProgram), 0666)
+ err = os.WriteFile(src, []byte(benchmarkRunningGoProgram), 0666)
if err != nil {
b.Fatal(err)
}
diff --git a/src/runtime/testdata/testprog/memprof.go b/src/runtime/testdata/testprog/memprof.go
index 7b134bc078..0392e60f84 100644
--- a/src/runtime/testdata/testprog/memprof.go
+++ b/src/runtime/testdata/testprog/memprof.go
@@ -7,7 +7,6 @@ package main
import (
"bytes"
"fmt"
- "io/ioutil"
"os"
"runtime"
"runtime/pprof"
@@ -31,7 +30,7 @@ func MemProf() {
runtime.GC()
- f, err := ioutil.TempFile("", "memprof")
+ f, err := os.CreateTemp("", "memprof")
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(2)
diff --git a/src/runtime/testdata/testprog/syscalls_linux.go b/src/runtime/testdata/testprog/syscalls_linux.go
index b8ac087626..48f8014237 100644
--- a/src/runtime/testdata/testprog/syscalls_linux.go
+++ b/src/runtime/testdata/testprog/syscalls_linux.go
@@ -7,7 +7,6 @@ package main
import (
"bytes"
"fmt"
- "io/ioutil"
"os"
"syscall"
)
@@ -17,7 +16,7 @@ func gettid() int {
}
func tidExists(tid int) (exists, supported bool) {
- stat, err := ioutil.ReadFile(fmt.Sprintf("/proc/self/task/%d/stat", tid))
+ stat, err := os.ReadFile(fmt.Sprintf("/proc/self/task/%d/stat", tid))
if os.IsNotExist(err) {
return false, true
}
diff --git a/src/runtime/testdata/testprog/timeprof.go b/src/runtime/testdata/testprog/timeprof.go
index 0702885369..1e90af4033 100644
--- a/src/runtime/testdata/testprog/timeprof.go
+++ b/src/runtime/testdata/testprog/timeprof.go
@@ -6,7 +6,6 @@ package main
import (
"fmt"
- "io/ioutil"
"os"
"runtime/pprof"
"time"
@@ -17,7 +16,7 @@ func init() {
}
func TimeProf() {
- f, err := ioutil.TempFile("", "timeprof")
+ f, err := os.CreateTemp("", "timeprof")
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(2)
diff --git a/src/runtime/testdata/testprog/vdso.go b/src/runtime/testdata/testprog/vdso.go
index ef92f48758..d2a300d8f2 100644
--- a/src/runtime/testdata/testprog/vdso.go
+++ b/src/runtime/testdata/testprog/vdso.go
@@ -8,7 +8,6 @@ package main
import (
"fmt"
- "io/ioutil"
"os"
"runtime/pprof"
"time"
@@ -19,7 +18,7 @@ func init() {
}
func signalInVDSO() {
- f, err := ioutil.TempFile("", "timeprofnow")
+ f, err := os.CreateTemp("", "timeprofnow")
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(2)
diff --git a/src/runtime/testdata/testprogcgo/pprof.go b/src/runtime/testdata/testprogcgo/pprof.go
index 00f2c42e93..3b73fa0bdd 100644
--- a/src/runtime/testdata/testprogcgo/pprof.go
+++ b/src/runtime/testdata/testprogcgo/pprof.go
@@ -60,7 +60,6 @@ import "C"
import (
"fmt"
- "io/ioutil"
"os"
"runtime"
"runtime/pprof"
@@ -75,7 +74,7 @@ func init() {
func CgoPprof() {
runtime.SetCgoTraceback(0, unsafe.Pointer(C.pprofCgoTraceback), nil, nil)
- f, err := ioutil.TempFile("", "prof")
+ f, err := os.CreateTemp("", "prof")
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(2)
diff --git a/src/runtime/testdata/testprogcgo/threadpprof.go b/src/runtime/testdata/testprogcgo/threadpprof.go
index 37a2a1ab65..feb774ba59 100644
--- a/src/runtime/testdata/testprogcgo/threadpprof.go
+++ b/src/runtime/testdata/testprogcgo/threadpprof.go
@@ -74,7 +74,6 @@ import "C"
import (
"fmt"
- "io/ioutil"
"os"
"runtime"
"runtime/pprof"
@@ -97,7 +96,7 @@ func CgoPprofThreadNoTraceback() {
}
func pprofThread() {
- f, err := ioutil.TempFile("", "prof")
+ f, err := os.CreateTemp("", "prof")
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(2)
diff --git a/src/runtime/time.go b/src/runtime/time.go
index 75b66f8492..d338705b7c 100644
--- a/src/runtime/time.go
+++ b/src/runtime/time.go
@@ -23,6 +23,8 @@ type timer struct {
// Timer wakes up at when, and then at when+period, ... (period > 0 only)
// each time calling f(arg, now) in the timer goroutine, so f must be
// a well-behaved function and not block.
+ //
+ // when must be positive on an active timer.
when int64
period int64
f func(interface{}, uintptr)
@@ -185,6 +187,9 @@ func timeSleep(ns int64) {
t.f = goroutineReady
t.arg = gp
t.nextwhen = nanotime() + ns
+ if t.nextwhen < 0 { // check for overflow.
+ t.nextwhen = maxWhen
+ }
gopark(resetForSleep, unsafe.Pointer(t), waitReasonSleep, traceEvGoSleep, 1)
}
@@ -242,10 +247,14 @@ func goroutineReady(arg interface{}, seq uintptr) {
// That avoids the risk of changing the when field of a timer in some P's heap,
// which could cause the heap to become unsorted.
func addtimer(t *timer) {
- // when must never be negative; otherwise runtimer will overflow
- // during its delta calculation and never expire other runtime timers.
- if t.when < 0 {
- t.when = maxWhen
+ // when must be positive. A negative value will cause runtimer to
+ // overflow during its delta calculation and never expire other runtime
+ // timers. Zero will cause checkTimers to fail to notice the timer.
+ if t.when <= 0 {
+ throw("timer when must be positive")
+ }
+ if t.period < 0 {
+ throw("timer period must be non-negative")
}
if t.status != timerNoStatus {
throw("addtimer called with initialized timer")
@@ -406,8 +415,11 @@ func dodeltimer0(pp *p) {
// This is called by the netpoll code or time.Ticker.Reset or time.Timer.Reset.
// Reports whether the timer was modified before it was run.
func modtimer(t *timer, when, period int64, f func(interface{}, uintptr), arg interface{}, seq uintptr) bool {
- if when < 0 {
- when = maxWhen
+ if when <= 0 {
+ throw("timer when must be positive")
+ }
+ if period < 0 {
+ throw("timer period must be non-negative")
}
status := uint32(timerNoStatus)
@@ -846,6 +858,9 @@ func runOneTimer(pp *p, t *timer, now int64) {
// Leave in heap but adjust next time to fire.
delta := t.when - now
t.when += t.period * (1 + -delta/t.period)
+ if t.when < 0 { // check for overflow.
+ t.when = maxWhen
+ }
siftdownTimer(pp.timers, 0)
if !atomic.Cas(&t.status, timerRunning, timerWaiting) {
badTimer()
@@ -1064,6 +1079,9 @@ func siftupTimer(t []*timer, i int) {
badTimer()
}
when := t[i].when
+ if when <= 0 {
+ badTimer()
+ }
tmp := t[i]
for i > 0 {
p := (i - 1) / 4 // parent
@@ -1084,6 +1102,9 @@ func siftdownTimer(t []*timer, i int) {
badTimer()
}
when := t[i].when
+ if when <= 0 {
+ badTimer()
+ }
tmp := t[i]
for {
c := i*4 + 1 // left child
diff --git a/src/runtime/trace/trace_test.go b/src/runtime/trace/trace_test.go
index 235845df4e..b316eafe4c 100644
--- a/src/runtime/trace/trace_test.go
+++ b/src/runtime/trace/trace_test.go
@@ -10,7 +10,6 @@ import (
"internal/race"
"internal/trace"
"io"
- "io/ioutil"
"net"
"os"
"runtime"
@@ -586,7 +585,7 @@ func saveTrace(t *testing.T, buf *bytes.Buffer, name string) {
if !*saveTraces {
return
}
- if err := ioutil.WriteFile(name+".trace", buf.Bytes(), 0600); err != nil {
+ if err := os.WriteFile(name+".trace", buf.Bytes(), 0600); err != nil {
t.Errorf("failed to write trace file: %s", err)
}
}
diff --git a/src/runtime/wincallback.go b/src/runtime/wincallback.go
index c022916422..fb452222da 100644
--- a/src/runtime/wincallback.go
+++ b/src/runtime/wincallback.go
@@ -11,7 +11,6 @@ package main
import (
"bytes"
"fmt"
- "io/ioutil"
"os"
)
@@ -38,7 +37,7 @@ TEXT runtime·callbackasm(SB),7,$0
}
filename := fmt.Sprintf("zcallback_windows.s")
- err := ioutil.WriteFile(filename, buf.Bytes(), 0666)
+ err := os.WriteFile(filename, buf.Bytes(), 0666)
if err != nil {
fmt.Fprintf(os.Stderr, "wincallback: %s\n", err)
os.Exit(2)
@@ -66,7 +65,7 @@ TEXT runtime·callbackasm(SB),NOSPLIT|NOFRAME,$0
buf.WriteString("\tB\truntime·callbackasm1(SB)\n")
}
- err := ioutil.WriteFile("zcallback_windows_arm.s", buf.Bytes(), 0666)
+ err := os.WriteFile("zcallback_windows_arm.s", buf.Bytes(), 0666)
if err != nil {
fmt.Fprintf(os.Stderr, "wincallback: %s\n", err)
os.Exit(2)
@@ -82,7 +81,7 @@ package runtime
const cb_max = %d // maximum number of windows callbacks allowed
`, maxCallback))
- err := ioutil.WriteFile("zcallback_windows.go", buf.Bytes(), 0666)
+ err := os.WriteFile("zcallback_windows.go", buf.Bytes(), 0666)
if err != nil {
fmt.Fprintf(os.Stderr, "wincallback: %s\n", err)
os.Exit(2)
diff --git a/src/sort/genzfunc.go b/src/sort/genzfunc.go
index 66408d26c6..e7eb573737 100644
--- a/src/sort/genzfunc.go
+++ b/src/sort/genzfunc.go
@@ -20,8 +20,8 @@ import (
"go/format"
"go/parser"
"go/token"
- "io/ioutil"
"log"
+ "os"
"regexp"
)
@@ -92,7 +92,7 @@ func main() {
out.Write(src)
const target = "zfuncversion.go"
- if err := ioutil.WriteFile(target, out.Bytes(), 0644); err != nil {
+ if err := os.WriteFile(target, out.Bytes(), 0644); err != nil {
log.Fatal(err)
}
}
diff --git a/src/strconv/makeisprint.go b/src/strconv/makeisprint.go
index 1a3248f308..0e6e90a6c6 100644
--- a/src/strconv/makeisprint.go
+++ b/src/strconv/makeisprint.go
@@ -17,8 +17,8 @@ import (
"flag"
"fmt"
"go/format"
- "io/ioutil"
"log"
+ "os"
"unicode"
)
@@ -196,7 +196,7 @@ func main() {
if err != nil {
log.Fatal(err)
}
- err = ioutil.WriteFile(*filename, data, 0644)
+ err = os.WriteFile(*filename, data, 0644)
if err != nil {
log.Fatal(err)
}
diff --git a/src/syscall/dirent_test.go b/src/syscall/dirent_test.go
index f63153340a..7dac98ff4b 100644
--- a/src/syscall/dirent_test.go
+++ b/src/syscall/dirent_test.go
@@ -9,7 +9,6 @@ package syscall_test
import (
"bytes"
"fmt"
- "io/ioutil"
"os"
"path/filepath"
"runtime"
@@ -27,7 +26,7 @@ func TestDirent(t *testing.T) {
filenameMinSize = 11
)
- d, err := ioutil.TempDir("", "dirent-test")
+ d, err := os.MkdirTemp("", "dirent-test")
if err != nil {
t.Fatalf("tempdir: %v", err)
}
@@ -36,7 +35,7 @@ func TestDirent(t *testing.T) {
for i, c := range []byte("0123456789") {
name := string(bytes.Repeat([]byte{c}, filenameMinSize+i))
- err = ioutil.WriteFile(filepath.Join(d, name), nil, 0644)
+ err = os.WriteFile(filepath.Join(d, name), nil, 0644)
if err != nil {
t.Fatalf("writefile: %v", err)
}
@@ -93,7 +92,7 @@ func TestDirentRepeat(t *testing.T) {
}
// Make a directory containing N files
- d, err := ioutil.TempDir("", "direntRepeat-test")
+ d, err := os.MkdirTemp("", "direntRepeat-test")
if err != nil {
t.Fatalf("tempdir: %v", err)
}
@@ -104,7 +103,7 @@ func TestDirentRepeat(t *testing.T) {
files = append(files, fmt.Sprintf("file%d", i))
}
for _, file := range files {
- err = ioutil.WriteFile(filepath.Join(d, file), []byte("contents"), 0644)
+ err = os.WriteFile(filepath.Join(d, file), []byte("contents"), 0644)
if err != nil {
t.Fatalf("writefile: %v", err)
}
diff --git a/src/syscall/exec_linux_test.go b/src/syscall/exec_linux_test.go
index b79dee7525..ac3a5754ae 100644
--- a/src/syscall/exec_linux_test.go
+++ b/src/syscall/exec_linux_test.go
@@ -11,7 +11,6 @@ import (
"fmt"
"internal/testenv"
"io"
- "io/ioutil"
"os"
"os/exec"
"os/user"
@@ -65,7 +64,7 @@ func skipNoUserNamespaces(t *testing.T) {
func skipUnprivilegedUserClone(t *testing.T) {
// Skip the test if the sysctl that prevents unprivileged user
// from creating user namespaces is enabled.
- data, errRead := ioutil.ReadFile("/proc/sys/kernel/unprivileged_userns_clone")
+ data, errRead := os.ReadFile("/proc/sys/kernel/unprivileged_userns_clone")
if errRead != nil || len(data) < 1 || data[0] == '0' {
t.Skip("kernel prohibits user namespace in unprivileged process")
}
@@ -98,7 +97,7 @@ func checkUserNS(t *testing.T) {
// On Centos 7 make sure they set the kernel parameter user_namespace=1
// See issue 16283 and 20796.
if _, err := os.Stat("/sys/module/user_namespace/parameters/enable"); err == nil {
- buf, _ := ioutil.ReadFile("/sys/module/user_namespace/parameters/enabled")
+ buf, _ := os.ReadFile("/sys/module/user_namespace/parameters/enabled")
if !strings.HasPrefix(string(buf), "Y") {
t.Skip("kernel doesn't support user namespaces")
}
@@ -106,7 +105,7 @@ func checkUserNS(t *testing.T) {
// On Centos 7.5+, user namespaces are disabled if user.max_user_namespaces = 0
if _, err := os.Stat("/proc/sys/user/max_user_namespaces"); err == nil {
- buf, errRead := ioutil.ReadFile("/proc/sys/user/max_user_namespaces")
+ buf, errRead := os.ReadFile("/proc/sys/user/max_user_namespaces")
if errRead == nil && buf[0] == '0' {
t.Skip("kernel doesn't support user namespaces")
}
@@ -226,7 +225,7 @@ func TestUnshare(t *testing.T) {
t.Fatal(err)
}
- orig, err := ioutil.ReadFile(path)
+ orig, err := os.ReadFile(path)
if err != nil {
t.Fatal(err)
}
@@ -349,7 +348,7 @@ func TestUnshareMountNameSpace(t *testing.T) {
t.Skip("kernel prohibits unshare in unprivileged process, unless using user namespace")
}
- d, err := ioutil.TempDir("", "unshare")
+ d, err := os.MkdirTemp("", "unshare")
if err != nil {
t.Fatalf("tempdir: %v", err)
}
@@ -391,7 +390,7 @@ func TestUnshareMountNameSpaceChroot(t *testing.T) {
t.Skip("kernel prohibits unshare in unprivileged process, unless using user namespace")
}
- d, err := ioutil.TempDir("", "unshare")
+ d, err := os.MkdirTemp("", "unshare")
if err != nil {
t.Fatalf("tempdir: %v", err)
}
@@ -599,7 +598,7 @@ func testAmbientCaps(t *testing.T, userns bool) {
}
// Copy the test binary to a temporary location which is readable by nobody.
- f, err := ioutil.TempFile("", "gotest")
+ f, err := os.CreateTemp("", "gotest")
if err != nil {
t.Fatal(err)
}
diff --git a/src/syscall/getdirentries_test.go b/src/syscall/getdirentries_test.go
index 2a3419c230..66bb8acba2 100644
--- a/src/syscall/getdirentries_test.go
+++ b/src/syscall/getdirentries_test.go
@@ -8,7 +8,6 @@ package syscall_test
import (
"fmt"
- "io/ioutil"
"os"
"path/filepath"
"sort"
@@ -29,7 +28,7 @@ func testGetdirentries(t *testing.T, count int) {
if count > 100 && testing.Short() && os.Getenv("GO_BUILDER_NAME") == "" {
t.Skip("skipping in -short mode")
}
- d, err := ioutil.TempDir("", "getdirentries-test")
+ d, err := os.MkdirTemp("", "getdirentries-test")
if err != nil {
t.Fatalf("Tempdir: %v", err)
}
@@ -41,7 +40,7 @@ func testGetdirentries(t *testing.T, count int) {
// Make files in the temp directory
for _, name := range names {
- err := ioutil.WriteFile(filepath.Join(d, name), []byte("data"), 0)
+ err := os.WriteFile(filepath.Join(d, name), []byte("data"), 0)
if err != nil {
t.Fatalf("WriteFile: %v", err)
}
diff --git a/src/syscall/mkasm_darwin.go b/src/syscall/mkasm_darwin.go
index f6f75f99f6..1783387a53 100644
--- a/src/syscall/mkasm_darwin.go
+++ b/src/syscall/mkasm_darwin.go
@@ -11,23 +11,22 @@ package main
import (
"bytes"
"fmt"
- "io/ioutil"
"log"
"os"
"strings"
)
func main() {
- in1, err := ioutil.ReadFile("syscall_darwin.go")
+ in1, err := os.ReadFile("syscall_darwin.go")
if err != nil {
log.Fatalf("can't open syscall_darwin.go: %s", err)
}
arch := os.Args[1]
- in2, err := ioutil.ReadFile(fmt.Sprintf("syscall_darwin_%s.go", arch))
+ in2, err := os.ReadFile(fmt.Sprintf("syscall_darwin_%s.go", arch))
if err != nil {
log.Fatalf("can't open syscall_darwin_%s.go: %s", arch, err)
}
- in3, err := ioutil.ReadFile(fmt.Sprintf("zsyscall_darwin_%s.go", arch))
+ in3, err := os.ReadFile(fmt.Sprintf("zsyscall_darwin_%s.go", arch))
if err != nil {
log.Fatalf("can't open zsyscall_darwin_%s.go: %s", arch, err)
}
@@ -51,7 +50,7 @@ func main() {
fmt.Fprintf(&out, "\tJMP\t%s(SB)\n", fn)
}
}
- err = ioutil.WriteFile(fmt.Sprintf("zsyscall_darwin_%s.s", arch), out.Bytes(), 0644)
+ err = os.WriteFile(fmt.Sprintf("zsyscall_darwin_%s.s", arch), out.Bytes(), 0644)
if err != nil {
log.Fatalf("can't write zsyscall_darwin_%s.s: %s", arch, err)
}
diff --git a/src/syscall/mksyscall.pl b/src/syscall/mksyscall.pl
index 25b40d7ba2..790df3825b 100755
--- a/src/syscall/mksyscall.pl
+++ b/src/syscall/mksyscall.pl
@@ -343,9 +343,6 @@ while(<>) {
$trampolines{$funcname} = 1;
# The assembly trampoline that jumps to the libc routine.
$text .= "func ${funcname}_trampoline()\n";
- # Map syscall.funcname to just plain funcname.
- # (The jump to this function is in the assembly trampoline, generated by mksyscallasm_darwin.go.)
- $text .= "//go:linkname $funcname $funcname\n";
# Tell the linker that funcname can be found in libSystem using varname without the libc_ prefix.
my $basename = substr $funcname, 5;
$text .= "//go:cgo_import_dynamic $funcname $basename \"/usr/lib/libSystem.B.dylib\"\n\n";
diff --git a/src/syscall/syscall_darwin.go b/src/syscall/syscall_darwin.go
index afdadbf894..162e94479f 100644
--- a/src/syscall/syscall_darwin.go
+++ b/src/syscall/syscall_darwin.go
@@ -115,7 +115,6 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
func libc_getfsstat_trampoline()
-//go:linkname libc_getfsstat libc_getfsstat
//go:cgo_import_dynamic libc_getfsstat getfsstat "/usr/lib/libSystem.B.dylib"
func setattrlistTimes(path string, times []Timespec) error {
@@ -148,7 +147,6 @@ func setattrlistTimes(path string, times []Timespec) error {
func libc_setattrlist_trampoline()
-//go:linkname libc_setattrlist libc_setattrlist
//go:cgo_import_dynamic libc_setattrlist setattrlist "/usr/lib/libSystem.B.dylib"
func utimensat(dirfd int, path string, times *[2]Timespec, flag int) error {
@@ -276,7 +274,6 @@ func fdopendir(fd int) (dir uintptr, err error) {
func libc_fdopendir_trampoline()
-//go:linkname libc_fdopendir libc_fdopendir
//go:cgo_import_dynamic libc_fdopendir fdopendir "/usr/lib/libSystem.B.dylib"
func readlen(fd int, buf *byte, nbuf int) (n int, err error) {
diff --git a/src/syscall/syscall_darwin_amd64.go b/src/syscall/syscall_darwin_amd64.go
index 23a4e5f996..96fadf7837 100644
--- a/src/syscall/syscall_darwin_amd64.go
+++ b/src/syscall/syscall_darwin_amd64.go
@@ -56,7 +56,6 @@ func sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
func libc_sendfile_trampoline()
-//go:linkname libc_sendfile libc_sendfile
//go:cgo_import_dynamic libc_sendfile sendfile "/usr/lib/libSystem.B.dylib"
// Implemented in the runtime package (runtime/sys_darwin_64.go)
diff --git a/src/syscall/syscall_darwin_arm64.go b/src/syscall/syscall_darwin_arm64.go
index c824f6d89d..d267a4ae6e 100644
--- a/src/syscall/syscall_darwin_arm64.go
+++ b/src/syscall/syscall_darwin_arm64.go
@@ -56,7 +56,6 @@ func sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
func libc_sendfile_trampoline()
-//go:linkname libc_sendfile libc_sendfile
//go:cgo_import_dynamic libc_sendfile sendfile "/usr/lib/libSystem.B.dylib"
// Implemented in the runtime package (runtime/sys_darwin_64.go)
diff --git a/src/syscall/syscall_linux_test.go b/src/syscall/syscall_linux_test.go
index 92764323ee..153d0efef1 100644
--- a/src/syscall/syscall_linux_test.go
+++ b/src/syscall/syscall_linux_test.go
@@ -9,7 +9,6 @@ import (
"fmt"
"io"
"io/fs"
- "io/ioutil"
"os"
"os/exec"
"os/signal"
@@ -30,7 +29,7 @@ func chtmpdir(t *testing.T) func() {
if err != nil {
t.Fatalf("chtmpdir: %v", err)
}
- d, err := ioutil.TempDir("", "test")
+ d, err := os.MkdirTemp("", "test")
if err != nil {
t.Fatalf("chtmpdir: %v", err)
}
@@ -160,7 +159,7 @@ func TestLinuxDeathSignal(t *testing.T) {
// Copy the test binary to a location that a non-root user can read/execute
// after we drop privileges
- tempDir, err := ioutil.TempDir("", "TestDeathSignal")
+ tempDir, err := os.MkdirTemp("", "TestDeathSignal")
if err != nil {
t.Fatalf("cannot create temporary directory: %v", err)
}
@@ -321,7 +320,7 @@ func TestSyscallNoError(t *testing.T) {
// Copy the test binary to a location that a non-root user can read/execute
// after we drop privileges
- tempDir, err := ioutil.TempDir("", "TestSyscallNoError")
+ tempDir, err := os.MkdirTemp("", "TestSyscallNoError")
if err != nil {
t.Fatalf("cannot create temporary directory: %v", err)
}
@@ -543,7 +542,7 @@ func TestAllThreadsSyscall(t *testing.T) {
func compareStatus(filter, expect string) error {
expected := filter + expect
pid := syscall.Getpid()
- fs, err := ioutil.ReadDir(fmt.Sprintf("/proc/%d/task", pid))
+ fs, err := os.ReadDir(fmt.Sprintf("/proc/%d/task", pid))
if err != nil {
return fmt.Errorf("unable to find %d tasks: %v", pid, err)
}
@@ -551,7 +550,7 @@ func compareStatus(filter, expect string) error {
foundAThread := false
for _, f := range fs {
tf := fmt.Sprintf("/proc/%s/status", f.Name())
- d, err := ioutil.ReadFile(tf)
+ d, err := os.ReadFile(tf)
if err != nil {
// There are a surprising number of ways this
// can error out on linux. We've seen all of
diff --git a/src/syscall/syscall_unix_test.go b/src/syscall/syscall_unix_test.go
index 1c34ed2c27..7e6a8c9043 100644
--- a/src/syscall/syscall_unix_test.go
+++ b/src/syscall/syscall_unix_test.go
@@ -11,7 +11,6 @@ import (
"fmt"
"internal/testenv"
"io"
- "io/ioutil"
"net"
"os"
"os/exec"
@@ -79,7 +78,7 @@ func TestFcntlFlock(t *testing.T) {
}
if os.Getenv("GO_WANT_HELPER_PROCESS") == "" {
// parent
- tempDir, err := ioutil.TempDir("", "TestFcntlFlock")
+ tempDir, err := os.MkdirTemp("", "TestFcntlFlock")
if err != nil {
t.Fatalf("Failed to create temp dir: %v", err)
}
@@ -157,7 +156,7 @@ func TestPassFD(t *testing.T) {
}
- tempDir, err := ioutil.TempDir("", "TestPassFD")
+ tempDir, err := os.MkdirTemp("", "TestPassFD")
if err != nil {
t.Fatal(err)
}
@@ -257,7 +256,7 @@ func passFDChild() {
// We make it in tempDir, which our parent will clean up.
flag.Parse()
tempDir := flag.Arg(0)
- f, err := ioutil.TempFile(tempDir, "")
+ f, err := os.CreateTemp(tempDir, "")
if err != nil {
fmt.Printf("TempFile: %v", err)
return
diff --git a/src/syscall/syscall_windows.go b/src/syscall/syscall_windows.go
index 0eea2b87a9..c1a12ccba3 100644
--- a/src/syscall/syscall_windows.go
+++ b/src/syscall/syscall_windows.go
@@ -260,7 +260,7 @@ func NewCallbackCDecl(fn interface{}) uintptr {
//sys TransmitFile(s Handle, handle Handle, bytesToWrite uint32, bytsPerSend uint32, overlapped *Overlapped, transmitFileBuf *TransmitFileBuffers, flags uint32) (err error) = mswsock.TransmitFile
//sys ReadDirectoryChanges(handle Handle, buf *byte, buflen uint32, watchSubTree bool, mask uint32, retlen *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) = kernel32.ReadDirectoryChangesW
//sys CertOpenSystemStore(hprov Handle, name *uint16) (store Handle, err error) = crypt32.CertOpenSystemStoreW
-//sys CertOpenStore(storeProvider uintptr, msgAndCertEncodingType uint32, cryptProv uintptr, flags uint32, para uintptr) (handle Handle, err error) [failretval==InvalidHandle] = crypt32.CertOpenStore
+//sys CertOpenStore(storeProvider uintptr, msgAndCertEncodingType uint32, cryptProv uintptr, flags uint32, para uintptr) (handle Handle, err error) = crypt32.CertOpenStore
//sys CertEnumCertificatesInStore(store Handle, prevContext *CertContext) (context *CertContext, err error) [failretval==nil] = crypt32.CertEnumCertificatesInStore
//sys CertAddCertificateContextToStore(store Handle, certContext *CertContext, addDisposition uint32, storeContext **CertContext) (err error) = crypt32.CertAddCertificateContextToStore
//sys CertCloseStore(store Handle, flags uint32) (err error) = crypt32.CertCloseStore
diff --git a/src/syscall/syscall_windows_test.go b/src/syscall/syscall_windows_test.go
index d146911073..a9ae54752b 100644
--- a/src/syscall/syscall_windows_test.go
+++ b/src/syscall/syscall_windows_test.go
@@ -5,7 +5,6 @@
package syscall_test
import (
- "io/ioutil"
"os"
"path/filepath"
"syscall"
@@ -13,7 +12,7 @@ import (
)
func TestWin32finddata(t *testing.T) {
- dir, err := ioutil.TempDir("", "go-build")
+ dir, err := os.MkdirTemp("", "go-build")
if err != nil {
t.Fatalf("failed to create temp directory: %v", err)
}
diff --git a/src/syscall/zsyscall_darwin_amd64.go b/src/syscall/zsyscall_darwin_amd64.go
index 093739ebc7..ee726fb24d 100644
--- a/src/syscall/zsyscall_darwin_amd64.go
+++ b/src/syscall/zsyscall_darwin_amd64.go
@@ -20,7 +20,6 @@ func getgroups(ngid int, gid *_Gid_t) (n int, err error) {
func libc_getgroups_trampoline()
-//go:linkname libc_getgroups libc_getgroups
//go:cgo_import_dynamic libc_getgroups getgroups "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -35,7 +34,6 @@ func setgroups(ngid int, gid *_Gid_t) (err error) {
func libc_setgroups_trampoline()
-//go:linkname libc_setgroups libc_setgroups
//go:cgo_import_dynamic libc_setgroups setgroups "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -51,7 +49,6 @@ func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err
func libc_wait4_trampoline()
-//go:linkname libc_wait4 libc_wait4
//go:cgo_import_dynamic libc_wait4 wait4 "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -67,7 +64,6 @@ func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) {
func libc_accept_trampoline()
-//go:linkname libc_accept libc_accept
//go:cgo_import_dynamic libc_accept accept "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -82,7 +78,6 @@ func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) {
func libc_bind_trampoline()
-//go:linkname libc_bind libc_bind
//go:cgo_import_dynamic libc_bind bind "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -97,7 +92,6 @@ func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) {
func libc_connect_trampoline()
-//go:linkname libc_connect libc_connect
//go:cgo_import_dynamic libc_connect connect "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -113,7 +107,6 @@ func socket(domain int, typ int, proto int) (fd int, err error) {
func libc_socket_trampoline()
-//go:linkname libc_socket libc_socket
//go:cgo_import_dynamic libc_socket socket "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -128,7 +121,6 @@ func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen
func libc_getsockopt_trampoline()
-//go:linkname libc_getsockopt libc_getsockopt
//go:cgo_import_dynamic libc_getsockopt getsockopt "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -143,7 +135,6 @@ func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr)
func libc_setsockopt_trampoline()
-//go:linkname libc_setsockopt libc_setsockopt
//go:cgo_import_dynamic libc_setsockopt setsockopt "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -158,7 +149,6 @@ func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
func libc_getpeername_trampoline()
-//go:linkname libc_getpeername libc_getpeername
//go:cgo_import_dynamic libc_getpeername getpeername "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -173,7 +163,6 @@ func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
func libc_getsockname_trampoline()
-//go:linkname libc_getsockname libc_getsockname
//go:cgo_import_dynamic libc_getsockname getsockname "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -188,7 +177,6 @@ func Shutdown(s int, how int) (err error) {
func libc_shutdown_trampoline()
-//go:linkname libc_shutdown libc_shutdown
//go:cgo_import_dynamic libc_shutdown shutdown "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -203,7 +191,6 @@ func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) {
func libc_socketpair_trampoline()
-//go:linkname libc_socketpair libc_socketpair
//go:cgo_import_dynamic libc_socketpair socketpair "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -225,7 +212,6 @@ func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Sockl
func libc_recvfrom_trampoline()
-//go:linkname libc_recvfrom libc_recvfrom
//go:cgo_import_dynamic libc_recvfrom recvfrom "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -246,7 +232,6 @@ func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (
func libc_sendto_trampoline()
-//go:linkname libc_sendto libc_sendto
//go:cgo_import_dynamic libc_sendto sendto "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -262,7 +247,6 @@ func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) {
func libc_recvmsg_trampoline()
-//go:linkname libc_recvmsg libc_recvmsg
//go:cgo_import_dynamic libc_recvmsg recvmsg "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -278,7 +262,6 @@ func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) {
func libc_sendmsg_trampoline()
-//go:linkname libc_sendmsg libc_sendmsg
//go:cgo_import_dynamic libc_sendmsg sendmsg "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -294,7 +277,6 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne
func libc_kevent_trampoline()
-//go:linkname libc_kevent libc_kevent
//go:cgo_import_dynamic libc_kevent kevent "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -314,7 +296,6 @@ func utimes(path string, timeval *[2]Timeval) (err error) {
func libc_utimes_trampoline()
-//go:linkname libc_utimes libc_utimes
//go:cgo_import_dynamic libc_utimes utimes "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -329,7 +310,6 @@ func futimes(fd int, timeval *[2]Timeval) (err error) {
func libc_futimes_trampoline()
-//go:linkname libc_futimes libc_futimes
//go:cgo_import_dynamic libc_futimes futimes "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -345,7 +325,6 @@ func fcntl(fd int, cmd int, arg int) (val int, err error) {
func libc_fcntl_trampoline()
-//go:linkname libc_fcntl libc_fcntl
//go:cgo_import_dynamic libc_fcntl fcntl "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -360,7 +339,6 @@ func pipe(p *[2]int32) (err error) {
func libc_pipe_trampoline()
-//go:linkname libc_pipe libc_pipe
//go:cgo_import_dynamic libc_pipe pipe "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -375,7 +353,6 @@ func kill(pid int, signum int, posix int) (err error) {
func libc_kill_trampoline()
-//go:linkname libc_kill libc_kill
//go:cgo_import_dynamic libc_kill kill "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -395,7 +372,6 @@ func Access(path string, mode uint32) (err error) {
func libc_access_trampoline()
-//go:linkname libc_access libc_access
//go:cgo_import_dynamic libc_access access "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -410,7 +386,6 @@ func Adjtime(delta *Timeval, olddelta *Timeval) (err error) {
func libc_adjtime_trampoline()
-//go:linkname libc_adjtime libc_adjtime
//go:cgo_import_dynamic libc_adjtime adjtime "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -430,7 +405,6 @@ func Chdir(path string) (err error) {
func libc_chdir_trampoline()
-//go:linkname libc_chdir libc_chdir
//go:cgo_import_dynamic libc_chdir chdir "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -450,7 +424,6 @@ func Chflags(path string, flags int) (err error) {
func libc_chflags_trampoline()
-//go:linkname libc_chflags libc_chflags
//go:cgo_import_dynamic libc_chflags chflags "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -470,7 +443,6 @@ func Chmod(path string, mode uint32) (err error) {
func libc_chmod_trampoline()
-//go:linkname libc_chmod libc_chmod
//go:cgo_import_dynamic libc_chmod chmod "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -490,7 +462,6 @@ func Chown(path string, uid int, gid int) (err error) {
func libc_chown_trampoline()
-//go:linkname libc_chown libc_chown
//go:cgo_import_dynamic libc_chown chown "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -510,7 +481,6 @@ func Chroot(path string) (err error) {
func libc_chroot_trampoline()
-//go:linkname libc_chroot libc_chroot
//go:cgo_import_dynamic libc_chroot chroot "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -525,7 +495,6 @@ func Close(fd int) (err error) {
func libc_close_trampoline()
-//go:linkname libc_close libc_close
//go:cgo_import_dynamic libc_close close "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -540,7 +509,6 @@ func closedir(dir uintptr) (err error) {
func libc_closedir_trampoline()
-//go:linkname libc_closedir libc_closedir
//go:cgo_import_dynamic libc_closedir closedir "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -556,7 +524,6 @@ func Dup(fd int) (nfd int, err error) {
func libc_dup_trampoline()
-//go:linkname libc_dup libc_dup
//go:cgo_import_dynamic libc_dup dup "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -571,7 +538,6 @@ func Dup2(from int, to int) (err error) {
func libc_dup2_trampoline()
-//go:linkname libc_dup2 libc_dup2
//go:cgo_import_dynamic libc_dup2 dup2 "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -596,7 +562,6 @@ func Exchangedata(path1 string, path2 string, options int) (err error) {
func libc_exchangedata_trampoline()
-//go:linkname libc_exchangedata libc_exchangedata
//go:cgo_import_dynamic libc_exchangedata exchangedata "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -611,7 +576,6 @@ func Fchdir(fd int) (err error) {
func libc_fchdir_trampoline()
-//go:linkname libc_fchdir libc_fchdir
//go:cgo_import_dynamic libc_fchdir fchdir "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -626,7 +590,6 @@ func Fchflags(fd int, flags int) (err error) {
func libc_fchflags_trampoline()
-//go:linkname libc_fchflags libc_fchflags
//go:cgo_import_dynamic libc_fchflags fchflags "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -641,7 +604,6 @@ func Fchmod(fd int, mode uint32) (err error) {
func libc_fchmod_trampoline()
-//go:linkname libc_fchmod libc_fchmod
//go:cgo_import_dynamic libc_fchmod fchmod "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -656,7 +618,6 @@ func Fchown(fd int, uid int, gid int) (err error) {
func libc_fchown_trampoline()
-//go:linkname libc_fchown libc_fchown
//go:cgo_import_dynamic libc_fchown fchown "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -671,7 +632,6 @@ func Flock(fd int, how int) (err error) {
func libc_flock_trampoline()
-//go:linkname libc_flock libc_flock
//go:cgo_import_dynamic libc_flock flock "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -687,7 +647,6 @@ func Fpathconf(fd int, name int) (val int, err error) {
func libc_fpathconf_trampoline()
-//go:linkname libc_fpathconf libc_fpathconf
//go:cgo_import_dynamic libc_fpathconf fpathconf "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -702,7 +661,6 @@ func Fsync(fd int) (err error) {
func libc_fsync_trampoline()
-//go:linkname libc_fsync libc_fsync
//go:cgo_import_dynamic libc_fsync fsync "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -717,7 +675,6 @@ func Ftruncate(fd int, length int64) (err error) {
func libc_ftruncate_trampoline()
-//go:linkname libc_ftruncate libc_ftruncate
//go:cgo_import_dynamic libc_ftruncate ftruncate "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -730,7 +687,6 @@ func Getdtablesize() (size int) {
func libc_getdtablesize_trampoline()
-//go:linkname libc_getdtablesize libc_getdtablesize
//go:cgo_import_dynamic libc_getdtablesize getdtablesize "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -743,7 +699,6 @@ func Getegid() (egid int) {
func libc_getegid_trampoline()
-//go:linkname libc_getegid libc_getegid
//go:cgo_import_dynamic libc_getegid getegid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -756,7 +711,6 @@ func Geteuid() (uid int) {
func libc_geteuid_trampoline()
-//go:linkname libc_geteuid libc_geteuid
//go:cgo_import_dynamic libc_geteuid geteuid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -769,7 +723,6 @@ func Getgid() (gid int) {
func libc_getgid_trampoline()
-//go:linkname libc_getgid libc_getgid
//go:cgo_import_dynamic libc_getgid getgid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -785,7 +738,6 @@ func Getpgid(pid int) (pgid int, err error) {
func libc_getpgid_trampoline()
-//go:linkname libc_getpgid libc_getpgid
//go:cgo_import_dynamic libc_getpgid getpgid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -798,7 +750,6 @@ func Getpgrp() (pgrp int) {
func libc_getpgrp_trampoline()
-//go:linkname libc_getpgrp libc_getpgrp
//go:cgo_import_dynamic libc_getpgrp getpgrp "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -811,7 +762,6 @@ func Getpid() (pid int) {
func libc_getpid_trampoline()
-//go:linkname libc_getpid libc_getpid
//go:cgo_import_dynamic libc_getpid getpid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -824,7 +774,6 @@ func Getppid() (ppid int) {
func libc_getppid_trampoline()
-//go:linkname libc_getppid libc_getppid
//go:cgo_import_dynamic libc_getppid getppid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -840,7 +789,6 @@ func Getpriority(which int, who int) (prio int, err error) {
func libc_getpriority_trampoline()
-//go:linkname libc_getpriority libc_getpriority
//go:cgo_import_dynamic libc_getpriority getpriority "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -855,7 +803,6 @@ func Getrlimit(which int, lim *Rlimit) (err error) {
func libc_getrlimit_trampoline()
-//go:linkname libc_getrlimit libc_getrlimit
//go:cgo_import_dynamic libc_getrlimit getrlimit "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -870,7 +817,6 @@ func Getrusage(who int, rusage *Rusage) (err error) {
func libc_getrusage_trampoline()
-//go:linkname libc_getrusage libc_getrusage
//go:cgo_import_dynamic libc_getrusage getrusage "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -886,7 +832,6 @@ func Getsid(pid int) (sid int, err error) {
func libc_getsid_trampoline()
-//go:linkname libc_getsid libc_getsid
//go:cgo_import_dynamic libc_getsid getsid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -899,7 +844,6 @@ func Getuid() (uid int) {
func libc_getuid_trampoline()
-//go:linkname libc_getuid libc_getuid
//go:cgo_import_dynamic libc_getuid getuid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -912,7 +856,6 @@ func Issetugid() (tainted bool) {
func libc_issetugid_trampoline()
-//go:linkname libc_issetugid libc_issetugid
//go:cgo_import_dynamic libc_issetugid issetugid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -928,7 +871,6 @@ func Kqueue() (fd int, err error) {
func libc_kqueue_trampoline()
-//go:linkname libc_kqueue libc_kqueue
//go:cgo_import_dynamic libc_kqueue kqueue "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -948,7 +890,6 @@ func Lchown(path string, uid int, gid int) (err error) {
func libc_lchown_trampoline()
-//go:linkname libc_lchown libc_lchown
//go:cgo_import_dynamic libc_lchown lchown "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -973,7 +914,6 @@ func Link(path string, link string) (err error) {
func libc_link_trampoline()
-//go:linkname libc_link libc_link
//go:cgo_import_dynamic libc_link link "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -988,7 +928,6 @@ func Listen(s int, backlog int) (err error) {
func libc_listen_trampoline()
-//go:linkname libc_listen libc_listen
//go:cgo_import_dynamic libc_listen listen "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1008,7 +947,6 @@ func Mkdir(path string, mode uint32) (err error) {
func libc_mkdir_trampoline()
-//go:linkname libc_mkdir libc_mkdir
//go:cgo_import_dynamic libc_mkdir mkdir "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1028,7 +966,6 @@ func Mkfifo(path string, mode uint32) (err error) {
func libc_mkfifo_trampoline()
-//go:linkname libc_mkfifo libc_mkfifo
//go:cgo_import_dynamic libc_mkfifo mkfifo "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1048,7 +985,6 @@ func Mknod(path string, mode uint32, dev int) (err error) {
func libc_mknod_trampoline()
-//go:linkname libc_mknod libc_mknod
//go:cgo_import_dynamic libc_mknod mknod "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1069,7 +1005,6 @@ func Mlock(b []byte) (err error) {
func libc_mlock_trampoline()
-//go:linkname libc_mlock libc_mlock
//go:cgo_import_dynamic libc_mlock mlock "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1084,7 +1019,6 @@ func Mlockall(flags int) (err error) {
func libc_mlockall_trampoline()
-//go:linkname libc_mlockall libc_mlockall
//go:cgo_import_dynamic libc_mlockall mlockall "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1105,7 +1039,6 @@ func Mprotect(b []byte, prot int) (err error) {
func libc_mprotect_trampoline()
-//go:linkname libc_mprotect libc_mprotect
//go:cgo_import_dynamic libc_mprotect mprotect "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1126,7 +1059,6 @@ func Munlock(b []byte) (err error) {
func libc_munlock_trampoline()
-//go:linkname libc_munlock libc_munlock
//go:cgo_import_dynamic libc_munlock munlock "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1141,7 +1073,6 @@ func Munlockall() (err error) {
func libc_munlockall_trampoline()
-//go:linkname libc_munlockall libc_munlockall
//go:cgo_import_dynamic libc_munlockall munlockall "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1162,7 +1093,6 @@ func Open(path string, mode int, perm uint32) (fd int, err error) {
func libc_open_trampoline()
-//go:linkname libc_open libc_open
//go:cgo_import_dynamic libc_open open "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1183,7 +1113,6 @@ func Pathconf(path string, name int) (val int, err error) {
func libc_pathconf_trampoline()
-//go:linkname libc_pathconf libc_pathconf
//go:cgo_import_dynamic libc_pathconf pathconf "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1205,7 +1134,6 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) {
func libc_pread_trampoline()
-//go:linkname libc_pread libc_pread
//go:cgo_import_dynamic libc_pread pread "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1227,7 +1155,6 @@ func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
func libc_pwrite_trampoline()
-//go:linkname libc_pwrite libc_pwrite
//go:cgo_import_dynamic libc_pwrite pwrite "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1249,7 +1176,6 @@ func read(fd int, p []byte) (n int, err error) {
func libc_read_trampoline()
-//go:linkname libc_read libc_read
//go:cgo_import_dynamic libc_read read "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1262,7 +1188,6 @@ func readdir_r(dir uintptr, entry *Dirent, result **Dirent) (res Errno) {
func libc_readdir_r_trampoline()
-//go:linkname libc_readdir_r libc_readdir_r
//go:cgo_import_dynamic libc_readdir_r readdir_r "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1289,7 +1214,6 @@ func Readlink(path string, buf []byte) (n int, err error) {
func libc_readlink_trampoline()
-//go:linkname libc_readlink libc_readlink
//go:cgo_import_dynamic libc_readlink readlink "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1314,7 +1238,6 @@ func Rename(from string, to string) (err error) {
func libc_rename_trampoline()
-//go:linkname libc_rename libc_rename
//go:cgo_import_dynamic libc_rename rename "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1334,7 +1257,6 @@ func Revoke(path string) (err error) {
func libc_revoke_trampoline()
-//go:linkname libc_revoke libc_revoke
//go:cgo_import_dynamic libc_revoke revoke "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1354,7 +1276,6 @@ func Rmdir(path string) (err error) {
func libc_rmdir_trampoline()
-//go:linkname libc_rmdir libc_rmdir
//go:cgo_import_dynamic libc_rmdir rmdir "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1370,7 +1291,6 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
func libc_lseek_trampoline()
-//go:linkname libc_lseek libc_lseek
//go:cgo_import_dynamic libc_lseek lseek "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1385,7 +1305,6 @@ func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) {
func libc_select_trampoline()
-//go:linkname libc_select libc_select
//go:cgo_import_dynamic libc_select select "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1400,7 +1319,6 @@ func Setegid(egid int) (err error) {
func libc_setegid_trampoline()
-//go:linkname libc_setegid libc_setegid
//go:cgo_import_dynamic libc_setegid setegid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1415,7 +1333,6 @@ func Seteuid(euid int) (err error) {
func libc_seteuid_trampoline()
-//go:linkname libc_seteuid libc_seteuid
//go:cgo_import_dynamic libc_seteuid seteuid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1430,7 +1347,6 @@ func Setgid(gid int) (err error) {
func libc_setgid_trampoline()
-//go:linkname libc_setgid libc_setgid
//go:cgo_import_dynamic libc_setgid setgid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1450,7 +1366,6 @@ func Setlogin(name string) (err error) {
func libc_setlogin_trampoline()
-//go:linkname libc_setlogin libc_setlogin
//go:cgo_import_dynamic libc_setlogin setlogin "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1465,7 +1380,6 @@ func Setpgid(pid int, pgid int) (err error) {
func libc_setpgid_trampoline()
-//go:linkname libc_setpgid libc_setpgid
//go:cgo_import_dynamic libc_setpgid setpgid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1480,7 +1394,6 @@ func Setpriority(which int, who int, prio int) (err error) {
func libc_setpriority_trampoline()
-//go:linkname libc_setpriority libc_setpriority
//go:cgo_import_dynamic libc_setpriority setpriority "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1495,7 +1408,6 @@ func Setprivexec(flag int) (err error) {
func libc_setprivexec_trampoline()
-//go:linkname libc_setprivexec libc_setprivexec
//go:cgo_import_dynamic libc_setprivexec setprivexec "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1510,7 +1422,6 @@ func Setregid(rgid int, egid int) (err error) {
func libc_setregid_trampoline()
-//go:linkname libc_setregid libc_setregid
//go:cgo_import_dynamic libc_setregid setregid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1525,7 +1436,6 @@ func Setreuid(ruid int, euid int) (err error) {
func libc_setreuid_trampoline()
-//go:linkname libc_setreuid libc_setreuid
//go:cgo_import_dynamic libc_setreuid setreuid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1540,7 +1450,6 @@ func Setrlimit(which int, lim *Rlimit) (err error) {
func libc_setrlimit_trampoline()
-//go:linkname libc_setrlimit libc_setrlimit
//go:cgo_import_dynamic libc_setrlimit setrlimit "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1556,7 +1465,6 @@ func Setsid() (pid int, err error) {
func libc_setsid_trampoline()
-//go:linkname libc_setsid libc_setsid
//go:cgo_import_dynamic libc_setsid setsid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1571,7 +1479,6 @@ func Settimeofday(tp *Timeval) (err error) {
func libc_settimeofday_trampoline()
-//go:linkname libc_settimeofday libc_settimeofday
//go:cgo_import_dynamic libc_settimeofday settimeofday "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1586,7 +1493,6 @@ func Setuid(uid int) (err error) {
func libc_setuid_trampoline()
-//go:linkname libc_setuid libc_setuid
//go:cgo_import_dynamic libc_setuid setuid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1611,7 +1517,6 @@ func Symlink(path string, link string) (err error) {
func libc_symlink_trampoline()
-//go:linkname libc_symlink libc_symlink
//go:cgo_import_dynamic libc_symlink symlink "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1626,7 +1531,6 @@ func Sync() (err error) {
func libc_sync_trampoline()
-//go:linkname libc_sync libc_sync
//go:cgo_import_dynamic libc_sync sync "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1646,7 +1550,6 @@ func Truncate(path string, length int64) (err error) {
func libc_truncate_trampoline()
-//go:linkname libc_truncate libc_truncate
//go:cgo_import_dynamic libc_truncate truncate "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1659,7 +1562,6 @@ func Umask(newmask int) (oldmask int) {
func libc_umask_trampoline()
-//go:linkname libc_umask libc_umask
//go:cgo_import_dynamic libc_umask umask "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1679,7 +1581,6 @@ func Undelete(path string) (err error) {
func libc_undelete_trampoline()
-//go:linkname libc_undelete libc_undelete
//go:cgo_import_dynamic libc_undelete undelete "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1699,7 +1600,6 @@ func Unlink(path string) (err error) {
func libc_unlink_trampoline()
-//go:linkname libc_unlink libc_unlink
//go:cgo_import_dynamic libc_unlink unlink "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1719,7 +1619,6 @@ func Unmount(path string, flags int) (err error) {
func libc_unmount_trampoline()
-//go:linkname libc_unmount libc_unmount
//go:cgo_import_dynamic libc_unmount unmount "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1741,7 +1640,6 @@ func write(fd int, p []byte) (n int, err error) {
func libc_write_trampoline()
-//go:linkname libc_write libc_write
//go:cgo_import_dynamic libc_write write "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1763,7 +1661,6 @@ func writev(fd int, iovecs []Iovec) (cnt uintptr, err error) {
func libc_writev_trampoline()
-//go:linkname libc_writev libc_writev
//go:cgo_import_dynamic libc_writev writev "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1779,7 +1676,6 @@ func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (
func libc_mmap_trampoline()
-//go:linkname libc_mmap libc_mmap
//go:cgo_import_dynamic libc_mmap mmap "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1794,7 +1690,6 @@ func munmap(addr uintptr, length uintptr) (err error) {
func libc_munmap_trampoline()
-//go:linkname libc_munmap libc_munmap
//go:cgo_import_dynamic libc_munmap munmap "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1810,7 +1705,6 @@ func fork() (pid int, err error) {
func libc_fork_trampoline()
-//go:linkname libc_fork libc_fork
//go:cgo_import_dynamic libc_fork fork "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1825,7 +1719,6 @@ func ioctl(fd int, req int, arg int) (err error) {
func libc_ioctl_trampoline()
-//go:linkname libc_ioctl libc_ioctl
//go:cgo_import_dynamic libc_ioctl ioctl "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1850,7 +1743,6 @@ func execve(path *byte, argv **byte, envp **byte) (err error) {
func libc_execve_trampoline()
-//go:linkname libc_execve libc_execve
//go:cgo_import_dynamic libc_execve execve "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1865,7 +1757,6 @@ func exit(res int) (err error) {
func libc_exit_trampoline()
-//go:linkname libc_exit libc_exit
//go:cgo_import_dynamic libc_exit exit "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1886,7 +1777,6 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr)
func libc_sysctl_trampoline()
-//go:linkname libc_sysctl libc_sysctl
//go:cgo_import_dynamic libc_sysctl sysctl "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1917,7 +1807,6 @@ func unlinkat(fd int, path string, flags int) (err error) {
func libc_unlinkat_trampoline()
-//go:linkname libc_unlinkat libc_unlinkat
//go:cgo_import_dynamic libc_unlinkat unlinkat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1938,7 +1827,6 @@ func openat(fd int, path string, flags int, perm uint32) (fdret int, err error)
func libc_openat_trampoline()
-//go:linkname libc_openat libc_openat
//go:cgo_import_dynamic libc_openat openat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1960,7 +1848,6 @@ func getcwd(buf []byte) (n int, err error) {
func libc_getcwd_trampoline()
-//go:linkname libc_getcwd libc_getcwd
//go:cgo_import_dynamic libc_getcwd getcwd "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1975,7 +1862,6 @@ func Fstat(fd int, stat *Stat_t) (err error) {
func libc_fstat64_trampoline()
-//go:linkname libc_fstat64 libc_fstat64
//go:cgo_import_dynamic libc_fstat64 fstat64 "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1990,7 +1876,6 @@ func Fstatfs(fd int, stat *Statfs_t) (err error) {
func libc_fstatfs64_trampoline()
-//go:linkname libc_fstatfs64 libc_fstatfs64
//go:cgo_import_dynamic libc_fstatfs64 fstatfs64 "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2005,7 +1890,6 @@ func Gettimeofday(tp *Timeval) (err error) {
func libc_gettimeofday_trampoline()
-//go:linkname libc_gettimeofday libc_gettimeofday
//go:cgo_import_dynamic libc_gettimeofday gettimeofday "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2025,7 +1909,6 @@ func Lstat(path string, stat *Stat_t) (err error) {
func libc_lstat64_trampoline()
-//go:linkname libc_lstat64 libc_lstat64
//go:cgo_import_dynamic libc_lstat64 lstat64 "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2045,7 +1928,6 @@ func Stat(path string, stat *Stat_t) (err error) {
func libc_stat64_trampoline()
-//go:linkname libc_stat64 libc_stat64
//go:cgo_import_dynamic libc_stat64 stat64 "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2065,7 +1947,6 @@ func Statfs(path string, stat *Statfs_t) (err error) {
func libc_statfs64_trampoline()
-//go:linkname libc_statfs64 libc_statfs64
//go:cgo_import_dynamic libc_statfs64 statfs64 "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2085,7 +1966,6 @@ func fstatat(fd int, path string, stat *Stat_t, flags int) (err error) {
func libc_fstatat64_trampoline()
-//go:linkname libc_fstatat64 libc_fstatat64
//go:cgo_import_dynamic libc_fstatat64 fstatat64 "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2101,5 +1981,4 @@ func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) {
func libc_ptrace_trampoline()
-//go:linkname libc_ptrace libc_ptrace
//go:cgo_import_dynamic libc_ptrace ptrace "/usr/lib/libSystem.B.dylib"
diff --git a/src/syscall/zsyscall_darwin_arm64.go b/src/syscall/zsyscall_darwin_arm64.go
index 7698b2503e..ac530f3108 100644
--- a/src/syscall/zsyscall_darwin_arm64.go
+++ b/src/syscall/zsyscall_darwin_arm64.go
@@ -20,7 +20,6 @@ func getgroups(ngid int, gid *_Gid_t) (n int, err error) {
func libc_getgroups_trampoline()
-//go:linkname libc_getgroups libc_getgroups
//go:cgo_import_dynamic libc_getgroups getgroups "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -35,7 +34,6 @@ func setgroups(ngid int, gid *_Gid_t) (err error) {
func libc_setgroups_trampoline()
-//go:linkname libc_setgroups libc_setgroups
//go:cgo_import_dynamic libc_setgroups setgroups "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -51,7 +49,6 @@ func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err
func libc_wait4_trampoline()
-//go:linkname libc_wait4 libc_wait4
//go:cgo_import_dynamic libc_wait4 wait4 "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -67,7 +64,6 @@ func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) {
func libc_accept_trampoline()
-//go:linkname libc_accept libc_accept
//go:cgo_import_dynamic libc_accept accept "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -82,7 +78,6 @@ func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) {
func libc_bind_trampoline()
-//go:linkname libc_bind libc_bind
//go:cgo_import_dynamic libc_bind bind "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -97,7 +92,6 @@ func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) {
func libc_connect_trampoline()
-//go:linkname libc_connect libc_connect
//go:cgo_import_dynamic libc_connect connect "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -113,7 +107,6 @@ func socket(domain int, typ int, proto int) (fd int, err error) {
func libc_socket_trampoline()
-//go:linkname libc_socket libc_socket
//go:cgo_import_dynamic libc_socket socket "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -128,7 +121,6 @@ func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen
func libc_getsockopt_trampoline()
-//go:linkname libc_getsockopt libc_getsockopt
//go:cgo_import_dynamic libc_getsockopt getsockopt "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -143,7 +135,6 @@ func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr)
func libc_setsockopt_trampoline()
-//go:linkname libc_setsockopt libc_setsockopt
//go:cgo_import_dynamic libc_setsockopt setsockopt "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -158,7 +149,6 @@ func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
func libc_getpeername_trampoline()
-//go:linkname libc_getpeername libc_getpeername
//go:cgo_import_dynamic libc_getpeername getpeername "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -173,7 +163,6 @@ func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
func libc_getsockname_trampoline()
-//go:linkname libc_getsockname libc_getsockname
//go:cgo_import_dynamic libc_getsockname getsockname "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -188,7 +177,6 @@ func Shutdown(s int, how int) (err error) {
func libc_shutdown_trampoline()
-//go:linkname libc_shutdown libc_shutdown
//go:cgo_import_dynamic libc_shutdown shutdown "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -203,7 +191,6 @@ func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) {
func libc_socketpair_trampoline()
-//go:linkname libc_socketpair libc_socketpair
//go:cgo_import_dynamic libc_socketpair socketpair "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -225,7 +212,6 @@ func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Sockl
func libc_recvfrom_trampoline()
-//go:linkname libc_recvfrom libc_recvfrom
//go:cgo_import_dynamic libc_recvfrom recvfrom "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -246,7 +232,6 @@ func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (
func libc_sendto_trampoline()
-//go:linkname libc_sendto libc_sendto
//go:cgo_import_dynamic libc_sendto sendto "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -262,7 +247,6 @@ func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) {
func libc_recvmsg_trampoline()
-//go:linkname libc_recvmsg libc_recvmsg
//go:cgo_import_dynamic libc_recvmsg recvmsg "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -278,7 +262,6 @@ func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) {
func libc_sendmsg_trampoline()
-//go:linkname libc_sendmsg libc_sendmsg
//go:cgo_import_dynamic libc_sendmsg sendmsg "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -294,7 +277,6 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne
func libc_kevent_trampoline()
-//go:linkname libc_kevent libc_kevent
//go:cgo_import_dynamic libc_kevent kevent "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -314,7 +296,6 @@ func utimes(path string, timeval *[2]Timeval) (err error) {
func libc_utimes_trampoline()
-//go:linkname libc_utimes libc_utimes
//go:cgo_import_dynamic libc_utimes utimes "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -329,7 +310,6 @@ func futimes(fd int, timeval *[2]Timeval) (err error) {
func libc_futimes_trampoline()
-//go:linkname libc_futimes libc_futimes
//go:cgo_import_dynamic libc_futimes futimes "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -345,7 +325,6 @@ func fcntl(fd int, cmd int, arg int) (val int, err error) {
func libc_fcntl_trampoline()
-//go:linkname libc_fcntl libc_fcntl
//go:cgo_import_dynamic libc_fcntl fcntl "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -360,7 +339,6 @@ func pipe(p *[2]int32) (err error) {
func libc_pipe_trampoline()
-//go:linkname libc_pipe libc_pipe
//go:cgo_import_dynamic libc_pipe pipe "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -375,7 +353,6 @@ func kill(pid int, signum int, posix int) (err error) {
func libc_kill_trampoline()
-//go:linkname libc_kill libc_kill
//go:cgo_import_dynamic libc_kill kill "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -395,7 +372,6 @@ func Access(path string, mode uint32) (err error) {
func libc_access_trampoline()
-//go:linkname libc_access libc_access
//go:cgo_import_dynamic libc_access access "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -410,7 +386,6 @@ func Adjtime(delta *Timeval, olddelta *Timeval) (err error) {
func libc_adjtime_trampoline()
-//go:linkname libc_adjtime libc_adjtime
//go:cgo_import_dynamic libc_adjtime adjtime "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -430,7 +405,6 @@ func Chdir(path string) (err error) {
func libc_chdir_trampoline()
-//go:linkname libc_chdir libc_chdir
//go:cgo_import_dynamic libc_chdir chdir "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -450,7 +424,6 @@ func Chflags(path string, flags int) (err error) {
func libc_chflags_trampoline()
-//go:linkname libc_chflags libc_chflags
//go:cgo_import_dynamic libc_chflags chflags "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -470,7 +443,6 @@ func Chmod(path string, mode uint32) (err error) {
func libc_chmod_trampoline()
-//go:linkname libc_chmod libc_chmod
//go:cgo_import_dynamic libc_chmod chmod "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -490,7 +462,6 @@ func Chown(path string, uid int, gid int) (err error) {
func libc_chown_trampoline()
-//go:linkname libc_chown libc_chown
//go:cgo_import_dynamic libc_chown chown "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -510,7 +481,6 @@ func Chroot(path string) (err error) {
func libc_chroot_trampoline()
-//go:linkname libc_chroot libc_chroot
//go:cgo_import_dynamic libc_chroot chroot "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -525,7 +495,6 @@ func Close(fd int) (err error) {
func libc_close_trampoline()
-//go:linkname libc_close libc_close
//go:cgo_import_dynamic libc_close close "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -540,7 +509,6 @@ func closedir(dir uintptr) (err error) {
func libc_closedir_trampoline()
-//go:linkname libc_closedir libc_closedir
//go:cgo_import_dynamic libc_closedir closedir "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -556,7 +524,6 @@ func Dup(fd int) (nfd int, err error) {
func libc_dup_trampoline()
-//go:linkname libc_dup libc_dup
//go:cgo_import_dynamic libc_dup dup "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -571,7 +538,6 @@ func Dup2(from int, to int) (err error) {
func libc_dup2_trampoline()
-//go:linkname libc_dup2 libc_dup2
//go:cgo_import_dynamic libc_dup2 dup2 "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -596,7 +562,6 @@ func Exchangedata(path1 string, path2 string, options int) (err error) {
func libc_exchangedata_trampoline()
-//go:linkname libc_exchangedata libc_exchangedata
//go:cgo_import_dynamic libc_exchangedata exchangedata "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -611,7 +576,6 @@ func Fchdir(fd int) (err error) {
func libc_fchdir_trampoline()
-//go:linkname libc_fchdir libc_fchdir
//go:cgo_import_dynamic libc_fchdir fchdir "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -626,7 +590,6 @@ func Fchflags(fd int, flags int) (err error) {
func libc_fchflags_trampoline()
-//go:linkname libc_fchflags libc_fchflags
//go:cgo_import_dynamic libc_fchflags fchflags "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -641,7 +604,6 @@ func Fchmod(fd int, mode uint32) (err error) {
func libc_fchmod_trampoline()
-//go:linkname libc_fchmod libc_fchmod
//go:cgo_import_dynamic libc_fchmod fchmod "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -656,7 +618,6 @@ func Fchown(fd int, uid int, gid int) (err error) {
func libc_fchown_trampoline()
-//go:linkname libc_fchown libc_fchown
//go:cgo_import_dynamic libc_fchown fchown "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -671,7 +632,6 @@ func Flock(fd int, how int) (err error) {
func libc_flock_trampoline()
-//go:linkname libc_flock libc_flock
//go:cgo_import_dynamic libc_flock flock "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -687,7 +647,6 @@ func Fpathconf(fd int, name int) (val int, err error) {
func libc_fpathconf_trampoline()
-//go:linkname libc_fpathconf libc_fpathconf
//go:cgo_import_dynamic libc_fpathconf fpathconf "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -702,7 +661,6 @@ func Fsync(fd int) (err error) {
func libc_fsync_trampoline()
-//go:linkname libc_fsync libc_fsync
//go:cgo_import_dynamic libc_fsync fsync "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -717,7 +675,6 @@ func Ftruncate(fd int, length int64) (err error) {
func libc_ftruncate_trampoline()
-//go:linkname libc_ftruncate libc_ftruncate
//go:cgo_import_dynamic libc_ftruncate ftruncate "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -730,7 +687,6 @@ func Getdtablesize() (size int) {
func libc_getdtablesize_trampoline()
-//go:linkname libc_getdtablesize libc_getdtablesize
//go:cgo_import_dynamic libc_getdtablesize getdtablesize "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -743,7 +699,6 @@ func Getegid() (egid int) {
func libc_getegid_trampoline()
-//go:linkname libc_getegid libc_getegid
//go:cgo_import_dynamic libc_getegid getegid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -756,7 +711,6 @@ func Geteuid() (uid int) {
func libc_geteuid_trampoline()
-//go:linkname libc_geteuid libc_geteuid
//go:cgo_import_dynamic libc_geteuid geteuid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -769,7 +723,6 @@ func Getgid() (gid int) {
func libc_getgid_trampoline()
-//go:linkname libc_getgid libc_getgid
//go:cgo_import_dynamic libc_getgid getgid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -785,7 +738,6 @@ func Getpgid(pid int) (pgid int, err error) {
func libc_getpgid_trampoline()
-//go:linkname libc_getpgid libc_getpgid
//go:cgo_import_dynamic libc_getpgid getpgid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -798,7 +750,6 @@ func Getpgrp() (pgrp int) {
func libc_getpgrp_trampoline()
-//go:linkname libc_getpgrp libc_getpgrp
//go:cgo_import_dynamic libc_getpgrp getpgrp "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -811,7 +762,6 @@ func Getpid() (pid int) {
func libc_getpid_trampoline()
-//go:linkname libc_getpid libc_getpid
//go:cgo_import_dynamic libc_getpid getpid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -824,7 +774,6 @@ func Getppid() (ppid int) {
func libc_getppid_trampoline()
-//go:linkname libc_getppid libc_getppid
//go:cgo_import_dynamic libc_getppid getppid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -840,7 +789,6 @@ func Getpriority(which int, who int) (prio int, err error) {
func libc_getpriority_trampoline()
-//go:linkname libc_getpriority libc_getpriority
//go:cgo_import_dynamic libc_getpriority getpriority "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -855,7 +803,6 @@ func Getrlimit(which int, lim *Rlimit) (err error) {
func libc_getrlimit_trampoline()
-//go:linkname libc_getrlimit libc_getrlimit
//go:cgo_import_dynamic libc_getrlimit getrlimit "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -870,7 +817,6 @@ func Getrusage(who int, rusage *Rusage) (err error) {
func libc_getrusage_trampoline()
-//go:linkname libc_getrusage libc_getrusage
//go:cgo_import_dynamic libc_getrusage getrusage "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -886,7 +832,6 @@ func Getsid(pid int) (sid int, err error) {
func libc_getsid_trampoline()
-//go:linkname libc_getsid libc_getsid
//go:cgo_import_dynamic libc_getsid getsid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -899,7 +844,6 @@ func Getuid() (uid int) {
func libc_getuid_trampoline()
-//go:linkname libc_getuid libc_getuid
//go:cgo_import_dynamic libc_getuid getuid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -912,7 +856,6 @@ func Issetugid() (tainted bool) {
func libc_issetugid_trampoline()
-//go:linkname libc_issetugid libc_issetugid
//go:cgo_import_dynamic libc_issetugid issetugid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -928,7 +871,6 @@ func Kqueue() (fd int, err error) {
func libc_kqueue_trampoline()
-//go:linkname libc_kqueue libc_kqueue
//go:cgo_import_dynamic libc_kqueue kqueue "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -948,7 +890,6 @@ func Lchown(path string, uid int, gid int) (err error) {
func libc_lchown_trampoline()
-//go:linkname libc_lchown libc_lchown
//go:cgo_import_dynamic libc_lchown lchown "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -973,7 +914,6 @@ func Link(path string, link string) (err error) {
func libc_link_trampoline()
-//go:linkname libc_link libc_link
//go:cgo_import_dynamic libc_link link "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -988,7 +928,6 @@ func Listen(s int, backlog int) (err error) {
func libc_listen_trampoline()
-//go:linkname libc_listen libc_listen
//go:cgo_import_dynamic libc_listen listen "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1008,7 +947,6 @@ func Mkdir(path string, mode uint32) (err error) {
func libc_mkdir_trampoline()
-//go:linkname libc_mkdir libc_mkdir
//go:cgo_import_dynamic libc_mkdir mkdir "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1028,7 +966,6 @@ func Mkfifo(path string, mode uint32) (err error) {
func libc_mkfifo_trampoline()
-//go:linkname libc_mkfifo libc_mkfifo
//go:cgo_import_dynamic libc_mkfifo mkfifo "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1048,7 +985,6 @@ func Mknod(path string, mode uint32, dev int) (err error) {
func libc_mknod_trampoline()
-//go:linkname libc_mknod libc_mknod
//go:cgo_import_dynamic libc_mknod mknod "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1069,7 +1005,6 @@ func Mlock(b []byte) (err error) {
func libc_mlock_trampoline()
-//go:linkname libc_mlock libc_mlock
//go:cgo_import_dynamic libc_mlock mlock "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1084,7 +1019,6 @@ func Mlockall(flags int) (err error) {
func libc_mlockall_trampoline()
-//go:linkname libc_mlockall libc_mlockall
//go:cgo_import_dynamic libc_mlockall mlockall "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1105,7 +1039,6 @@ func Mprotect(b []byte, prot int) (err error) {
func libc_mprotect_trampoline()
-//go:linkname libc_mprotect libc_mprotect
//go:cgo_import_dynamic libc_mprotect mprotect "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1126,7 +1059,6 @@ func Munlock(b []byte) (err error) {
func libc_munlock_trampoline()
-//go:linkname libc_munlock libc_munlock
//go:cgo_import_dynamic libc_munlock munlock "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1141,7 +1073,6 @@ func Munlockall() (err error) {
func libc_munlockall_trampoline()
-//go:linkname libc_munlockall libc_munlockall
//go:cgo_import_dynamic libc_munlockall munlockall "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1162,7 +1093,6 @@ func Open(path string, mode int, perm uint32) (fd int, err error) {
func libc_open_trampoline()
-//go:linkname libc_open libc_open
//go:cgo_import_dynamic libc_open open "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1183,7 +1113,6 @@ func Pathconf(path string, name int) (val int, err error) {
func libc_pathconf_trampoline()
-//go:linkname libc_pathconf libc_pathconf
//go:cgo_import_dynamic libc_pathconf pathconf "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1205,7 +1134,6 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) {
func libc_pread_trampoline()
-//go:linkname libc_pread libc_pread
//go:cgo_import_dynamic libc_pread pread "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1227,7 +1155,6 @@ func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
func libc_pwrite_trampoline()
-//go:linkname libc_pwrite libc_pwrite
//go:cgo_import_dynamic libc_pwrite pwrite "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1249,7 +1176,6 @@ func read(fd int, p []byte) (n int, err error) {
func libc_read_trampoline()
-//go:linkname libc_read libc_read
//go:cgo_import_dynamic libc_read read "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1262,7 +1188,6 @@ func readdir_r(dir uintptr, entry *Dirent, result **Dirent) (res Errno) {
func libc_readdir_r_trampoline()
-//go:linkname libc_readdir_r libc_readdir_r
//go:cgo_import_dynamic libc_readdir_r readdir_r "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1289,7 +1214,6 @@ func Readlink(path string, buf []byte) (n int, err error) {
func libc_readlink_trampoline()
-//go:linkname libc_readlink libc_readlink
//go:cgo_import_dynamic libc_readlink readlink "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1314,7 +1238,6 @@ func Rename(from string, to string) (err error) {
func libc_rename_trampoline()
-//go:linkname libc_rename libc_rename
//go:cgo_import_dynamic libc_rename rename "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1334,7 +1257,6 @@ func Revoke(path string) (err error) {
func libc_revoke_trampoline()
-//go:linkname libc_revoke libc_revoke
//go:cgo_import_dynamic libc_revoke revoke "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1354,7 +1276,6 @@ func Rmdir(path string) (err error) {
func libc_rmdir_trampoline()
-//go:linkname libc_rmdir libc_rmdir
//go:cgo_import_dynamic libc_rmdir rmdir "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1370,7 +1291,6 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
func libc_lseek_trampoline()
-//go:linkname libc_lseek libc_lseek
//go:cgo_import_dynamic libc_lseek lseek "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1385,7 +1305,6 @@ func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) {
func libc_select_trampoline()
-//go:linkname libc_select libc_select
//go:cgo_import_dynamic libc_select select "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1400,7 +1319,6 @@ func Setegid(egid int) (err error) {
func libc_setegid_trampoline()
-//go:linkname libc_setegid libc_setegid
//go:cgo_import_dynamic libc_setegid setegid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1415,7 +1333,6 @@ func Seteuid(euid int) (err error) {
func libc_seteuid_trampoline()
-//go:linkname libc_seteuid libc_seteuid
//go:cgo_import_dynamic libc_seteuid seteuid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1430,7 +1347,6 @@ func Setgid(gid int) (err error) {
func libc_setgid_trampoline()
-//go:linkname libc_setgid libc_setgid
//go:cgo_import_dynamic libc_setgid setgid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1450,7 +1366,6 @@ func Setlogin(name string) (err error) {
func libc_setlogin_trampoline()
-//go:linkname libc_setlogin libc_setlogin
//go:cgo_import_dynamic libc_setlogin setlogin "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1465,7 +1380,6 @@ func Setpgid(pid int, pgid int) (err error) {
func libc_setpgid_trampoline()
-//go:linkname libc_setpgid libc_setpgid
//go:cgo_import_dynamic libc_setpgid setpgid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1480,7 +1394,6 @@ func Setpriority(which int, who int, prio int) (err error) {
func libc_setpriority_trampoline()
-//go:linkname libc_setpriority libc_setpriority
//go:cgo_import_dynamic libc_setpriority setpriority "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1495,7 +1408,6 @@ func Setprivexec(flag int) (err error) {
func libc_setprivexec_trampoline()
-//go:linkname libc_setprivexec libc_setprivexec
//go:cgo_import_dynamic libc_setprivexec setprivexec "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1510,7 +1422,6 @@ func Setregid(rgid int, egid int) (err error) {
func libc_setregid_trampoline()
-//go:linkname libc_setregid libc_setregid
//go:cgo_import_dynamic libc_setregid setregid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1525,7 +1436,6 @@ func Setreuid(ruid int, euid int) (err error) {
func libc_setreuid_trampoline()
-//go:linkname libc_setreuid libc_setreuid
//go:cgo_import_dynamic libc_setreuid setreuid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1540,7 +1450,6 @@ func Setrlimit(which int, lim *Rlimit) (err error) {
func libc_setrlimit_trampoline()
-//go:linkname libc_setrlimit libc_setrlimit
//go:cgo_import_dynamic libc_setrlimit setrlimit "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1556,7 +1465,6 @@ func Setsid() (pid int, err error) {
func libc_setsid_trampoline()
-//go:linkname libc_setsid libc_setsid
//go:cgo_import_dynamic libc_setsid setsid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1571,7 +1479,6 @@ func Settimeofday(tp *Timeval) (err error) {
func libc_settimeofday_trampoline()
-//go:linkname libc_settimeofday libc_settimeofday
//go:cgo_import_dynamic libc_settimeofday settimeofday "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1586,7 +1493,6 @@ func Setuid(uid int) (err error) {
func libc_setuid_trampoline()
-//go:linkname libc_setuid libc_setuid
//go:cgo_import_dynamic libc_setuid setuid "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1611,7 +1517,6 @@ func Symlink(path string, link string) (err error) {
func libc_symlink_trampoline()
-//go:linkname libc_symlink libc_symlink
//go:cgo_import_dynamic libc_symlink symlink "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1626,7 +1531,6 @@ func Sync() (err error) {
func libc_sync_trampoline()
-//go:linkname libc_sync libc_sync
//go:cgo_import_dynamic libc_sync sync "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1646,7 +1550,6 @@ func Truncate(path string, length int64) (err error) {
func libc_truncate_trampoline()
-//go:linkname libc_truncate libc_truncate
//go:cgo_import_dynamic libc_truncate truncate "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1659,7 +1562,6 @@ func Umask(newmask int) (oldmask int) {
func libc_umask_trampoline()
-//go:linkname libc_umask libc_umask
//go:cgo_import_dynamic libc_umask umask "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1679,7 +1581,6 @@ func Undelete(path string) (err error) {
func libc_undelete_trampoline()
-//go:linkname libc_undelete libc_undelete
//go:cgo_import_dynamic libc_undelete undelete "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1699,7 +1600,6 @@ func Unlink(path string) (err error) {
func libc_unlink_trampoline()
-//go:linkname libc_unlink libc_unlink
//go:cgo_import_dynamic libc_unlink unlink "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1719,7 +1619,6 @@ func Unmount(path string, flags int) (err error) {
func libc_unmount_trampoline()
-//go:linkname libc_unmount libc_unmount
//go:cgo_import_dynamic libc_unmount unmount "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1741,7 +1640,6 @@ func write(fd int, p []byte) (n int, err error) {
func libc_write_trampoline()
-//go:linkname libc_write libc_write
//go:cgo_import_dynamic libc_write write "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1763,7 +1661,6 @@ func writev(fd int, iovecs []Iovec) (cnt uintptr, err error) {
func libc_writev_trampoline()
-//go:linkname libc_writev libc_writev
//go:cgo_import_dynamic libc_writev writev "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1779,7 +1676,6 @@ func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (
func libc_mmap_trampoline()
-//go:linkname libc_mmap libc_mmap
//go:cgo_import_dynamic libc_mmap mmap "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1794,7 +1690,6 @@ func munmap(addr uintptr, length uintptr) (err error) {
func libc_munmap_trampoline()
-//go:linkname libc_munmap libc_munmap
//go:cgo_import_dynamic libc_munmap munmap "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1810,7 +1705,6 @@ func fork() (pid int, err error) {
func libc_fork_trampoline()
-//go:linkname libc_fork libc_fork
//go:cgo_import_dynamic libc_fork fork "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1825,7 +1719,6 @@ func ioctl(fd int, req int, arg int) (err error) {
func libc_ioctl_trampoline()
-//go:linkname libc_ioctl libc_ioctl
//go:cgo_import_dynamic libc_ioctl ioctl "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1850,7 +1743,6 @@ func execve(path *byte, argv **byte, envp **byte) (err error) {
func libc_execve_trampoline()
-//go:linkname libc_execve libc_execve
//go:cgo_import_dynamic libc_execve execve "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1865,7 +1757,6 @@ func exit(res int) (err error) {
func libc_exit_trampoline()
-//go:linkname libc_exit libc_exit
//go:cgo_import_dynamic libc_exit exit "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1886,7 +1777,6 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr)
func libc_sysctl_trampoline()
-//go:linkname libc_sysctl libc_sysctl
//go:cgo_import_dynamic libc_sysctl sysctl "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1917,7 +1807,6 @@ func unlinkat(fd int, path string, flags int) (err error) {
func libc_unlinkat_trampoline()
-//go:linkname libc_unlinkat libc_unlinkat
//go:cgo_import_dynamic libc_unlinkat unlinkat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1938,7 +1827,6 @@ func openat(fd int, path string, flags int, perm uint32) (fdret int, err error)
func libc_openat_trampoline()
-//go:linkname libc_openat libc_openat
//go:cgo_import_dynamic libc_openat openat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1960,7 +1848,6 @@ func getcwd(buf []byte) (n int, err error) {
func libc_getcwd_trampoline()
-//go:linkname libc_getcwd libc_getcwd
//go:cgo_import_dynamic libc_getcwd getcwd "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1975,7 +1862,6 @@ func Fstat(fd int, stat *Stat_t) (err error) {
func libc_fstat_trampoline()
-//go:linkname libc_fstat libc_fstat
//go:cgo_import_dynamic libc_fstat fstat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1990,7 +1876,6 @@ func Fstatfs(fd int, stat *Statfs_t) (err error) {
func libc_fstatfs_trampoline()
-//go:linkname libc_fstatfs libc_fstatfs
//go:cgo_import_dynamic libc_fstatfs fstatfs "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2005,7 +1890,6 @@ func Gettimeofday(tp *Timeval) (err error) {
func libc_gettimeofday_trampoline()
-//go:linkname libc_gettimeofday libc_gettimeofday
//go:cgo_import_dynamic libc_gettimeofday gettimeofday "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2025,7 +1909,6 @@ func Lstat(path string, stat *Stat_t) (err error) {
func libc_lstat_trampoline()
-//go:linkname libc_lstat libc_lstat
//go:cgo_import_dynamic libc_lstat lstat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2045,7 +1928,6 @@ func Stat(path string, stat *Stat_t) (err error) {
func libc_stat_trampoline()
-//go:linkname libc_stat libc_stat
//go:cgo_import_dynamic libc_stat stat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2065,7 +1947,6 @@ func Statfs(path string, stat *Statfs_t) (err error) {
func libc_statfs_trampoline()
-//go:linkname libc_statfs libc_statfs
//go:cgo_import_dynamic libc_statfs statfs "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2085,7 +1966,6 @@ func fstatat(fd int, path string, stat *Stat_t, flags int) (err error) {
func libc_fstatat_trampoline()
-//go:linkname libc_fstatat libc_fstatat
//go:cgo_import_dynamic libc_fstatat fstatat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -2101,5 +1981,4 @@ func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) {
func libc_ptrace_trampoline()
-//go:linkname libc_ptrace libc_ptrace
//go:cgo_import_dynamic libc_ptrace ptrace "/usr/lib/libSystem.B.dylib"
diff --git a/src/syscall/zsyscall_windows.go b/src/syscall/zsyscall_windows.go
index 5d03ca9de9..86c4cac2ad 100644
--- a/src/syscall/zsyscall_windows.go
+++ b/src/syscall/zsyscall_windows.go
@@ -399,7 +399,7 @@ func CertGetCertificateChain(engine Handle, leaf *CertContext, time *Filetime, a
func CertOpenStore(storeProvider uintptr, msgAndCertEncodingType uint32, cryptProv uintptr, flags uint32, para uintptr) (handle Handle, err error) {
r0, _, e1 := Syscall6(procCertOpenStore.Addr(), 5, uintptr(storeProvider), uintptr(msgAndCertEncodingType), uintptr(cryptProv), uintptr(flags), uintptr(para), 0)
handle = Handle(r0)
- if handle == InvalidHandle {
+ if handle == 0 {
err = errnoErr(e1)
}
return
diff --git a/src/testing/fstest/mapfs.go b/src/testing/fstest/mapfs.go
index 10e56f5b3c..a5d4a23fac 100644
--- a/src/testing/fstest/mapfs.go
+++ b/src/testing/fstest/mapfs.go
@@ -132,6 +132,16 @@ func (fsys MapFS) Glob(pattern string) ([]string, error) {
return fs.Glob(fsOnly{fsys}, pattern)
}
+type noSub struct {
+ MapFS
+}
+
+func (noSub) Sub() {} // not the fs.SubFS signature
+
+func (fsys MapFS) Sub(dir string) (fs.FS, error) {
+ return fs.Sub(noSub{fsys}, dir)
+}
+
// A mapFileInfo implements fs.FileInfo and fs.DirEntry for a given map file.
type mapFileInfo struct {
name string
diff --git a/src/testing/fstest/testfs.go b/src/testing/fstest/testfs.go
index 4912a271b2..2602bdf0cc 100644
--- a/src/testing/fstest/testfs.go
+++ b/src/testing/fstest/testfs.go
@@ -22,6 +22,8 @@ import (
// It walks the entire tree of files in fsys,
// opening and checking that each file behaves correctly.
// It also checks that the file system contains at least the expected files.
+// As a special case, if no expected files are listed, fsys must be empty.
+// Otherwise, fsys must only contain at least the listed files: it can also contain others.
//
// If TestFS finds any misbehaviors, it returns an error reporting all of them.
// The error text spans multiple lines, one per detected misbehavior.
@@ -33,6 +35,32 @@ import (
// }
//
func TestFS(fsys fs.FS, expected ...string) error {
+ if err := testFS(fsys, expected...); err != nil {
+ return err
+ }
+ for _, name := range expected {
+ if i := strings.Index(name, "/"); i >= 0 {
+ dir, dirSlash := name[:i], name[:i+1]
+ var subExpected []string
+ for _, name := range expected {
+ if strings.HasPrefix(name, dirSlash) {
+ subExpected = append(subExpected, name[len(dirSlash):])
+ }
+ }
+ sub, err := fs.Sub(fsys, dir)
+ if err != nil {
+ return err
+ }
+ if err := testFS(sub, subExpected...); err != nil {
+ return fmt.Errorf("testing fs.Sub(fsys, %s): %v", dir, err)
+ }
+ break // one sub-test is enough
+ }
+ }
+ return nil
+}
+
+func testFS(fsys fs.FS, expected ...string) error {
t := fsTester{fsys: fsys}
t.checkDir(".")
t.checkOpen(".")
@@ -43,6 +71,20 @@ func TestFS(fsys fs.FS, expected ...string) error {
for _, file := range t.files {
found[file] = true
}
+ delete(found, ".")
+ if len(expected) == 0 && len(found) > 0 {
+ var list []string
+ for k := range found {
+ if k != "." {
+ list = append(list, k)
+ }
+ }
+ sort.Strings(list)
+ if len(list) > 15 {
+ list = append(list[:10], "...")
+ }
+ t.errorf("expected empty file system but found files:\n%s", strings.Join(list, "\n"))
+ }
for _, name := range expected {
if !found[name] {
t.errorf("expected but not found: %s", name)
diff --git a/src/testing/testing.go b/src/testing/testing.go
index d4b108a183..80354d5ce8 100644
--- a/src/testing/testing.go
+++ b/src/testing/testing.go
@@ -242,7 +242,6 @@ import (
"fmt"
"internal/race"
"io"
- "io/ioutil"
"os"
"runtime"
"runtime/debug"
@@ -936,14 +935,14 @@ func (c *common) TempDir() string {
if nonExistent {
c.Helper()
- // ioutil.TempDir doesn't like path separators in its pattern,
+ // os.MkdirTemp doesn't like path separators in its pattern,
// so mangle the name to accommodate subtests.
tempDirReplacer.Do(func() {
tempDirReplacer.r = strings.NewReplacer("/", "_", "\\", "_", ":", "_")
})
pattern := tempDirReplacer.r.Replace(c.Name())
- c.tempDir, c.tempDirErr = ioutil.TempDir("", pattern)
+ c.tempDir, c.tempDirErr = os.MkdirTemp("", pattern)
if c.tempDirErr == nil {
c.Cleanup(func() {
if err := os.RemoveAll(c.tempDir); err != nil {
diff --git a/src/testing/testing_test.go b/src/testing/testing_test.go
index d665a334e4..0f096980ca 100644
--- a/src/testing/testing_test.go
+++ b/src/testing/testing_test.go
@@ -5,7 +5,6 @@
package testing_test
import (
- "io/ioutil"
"os"
"path/filepath"
"testing"
@@ -102,11 +101,11 @@ func testTempDir(t *testing.T) {
if !fi.IsDir() {
t.Errorf("dir %q is not a dir", dir)
}
- fis, err := ioutil.ReadDir(dir)
+ files, err := os.ReadDir(dir)
if err != nil {
t.Fatal(err)
}
- if len(fis) > 0 {
- t.Errorf("unexpected %d files in TempDir: %v", len(fis), fis)
+ if len(files) > 0 {
+ t.Errorf("unexpected %d files in TempDir: %v", len(files), files)
}
}
diff --git a/src/text/template/examplefiles_test.go b/src/text/template/examplefiles_test.go
index a15c7a62a3..6534ee3315 100644
--- a/src/text/template/examplefiles_test.go
+++ b/src/text/template/examplefiles_test.go
@@ -6,7 +6,6 @@ package template_test
import (
"io"
- "io/ioutil"
"log"
"os"
"path/filepath"
@@ -20,7 +19,7 @@ type templateFile struct {
}
func createTestDir(files []templateFile) string {
- dir, err := ioutil.TempDir("", "template")
+ dir, err := os.MkdirTemp("", "template")
if err != nil {
log.Fatal(err)
}
diff --git a/src/text/template/helper.go b/src/text/template/helper.go
index 8269fa28c5..57905e613a 100644
--- a/src/text/template/helper.go
+++ b/src/text/template/helper.go
@@ -9,7 +9,7 @@ package template
import (
"fmt"
"io/fs"
- "io/ioutil"
+ "os"
"path"
"path/filepath"
)
@@ -164,7 +164,7 @@ func parseFS(t *Template, fsys fs.FS, patterns []string) (*Template, error) {
func readFileOS(file string) (name string, b []byte, err error) {
name = filepath.Base(file)
- b, err = ioutil.ReadFile(file)
+ b, err = os.ReadFile(file)
return
}
diff --git a/src/text/template/link_test.go b/src/text/template/link_test.go
index 4eac7e6755..9dc70dfc0d 100644
--- a/src/text/template/link_test.go
+++ b/src/text/template/link_test.go
@@ -7,7 +7,6 @@ package template_test
import (
"bytes"
"internal/testenv"
- "io/ioutil"
"os"
"os/exec"
"path/filepath"
@@ -40,13 +39,13 @@ func main() {
t.Used()
}
`
- td, err := ioutil.TempDir("", "text_template_TestDeadCodeElimination")
+ td, err := os.MkdirTemp("", "text_template_TestDeadCodeElimination")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(td)
- if err := ioutil.WriteFile(filepath.Join(td, "x.go"), []byte(prog), 0644); err != nil {
+ if err := os.WriteFile(filepath.Join(td, "x.go"), []byte(prog), 0644); err != nil {
t.Fatal(err)
}
cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", "x.exe", "x.go")
@@ -54,7 +53,7 @@ func main() {
if out, err := cmd.CombinedOutput(); err != nil {
t.Fatalf("go build: %v, %s", err, out)
}
- slurp, err := ioutil.ReadFile(filepath.Join(td, "x.exe"))
+ slurp, err := os.ReadFile(filepath.Join(td, "x.exe"))
if err != nil {
t.Fatal(err)
}
diff --git a/src/time/genzabbrs.go b/src/time/genzabbrs.go
index 1d59ba73ce..9825e705d2 100644
--- a/src/time/genzabbrs.go
+++ b/src/time/genzabbrs.go
@@ -18,9 +18,9 @@ import (
"flag"
"go/format"
"io"
- "io/ioutil"
"log"
"net/http"
+ "os"
"sort"
"text/template"
"time"
@@ -128,7 +128,7 @@ func main() {
if err != nil {
log.Fatal(err)
}
- err = ioutil.WriteFile(*filename, data, 0644)
+ err = os.WriteFile(*filename, data, 0644)
if err != nil {
log.Fatal(err)
}
diff --git a/src/time/internal_test.go b/src/time/internal_test.go
index 35ce69b228..ffe54e47c2 100644
--- a/src/time/internal_test.go
+++ b/src/time/internal_test.go
@@ -33,48 +33,30 @@ var DaysIn = daysIn
func empty(arg interface{}, seq uintptr) {}
-// Test that a runtimeTimer with a duration so large it overflows
-// does not cause other timers to hang.
+// Test that a runtimeTimer with a period that would overflow when on
+// expiration does not throw or cause other timers to hang.
//
// This test has to be in internal_test.go since it fiddles with
// unexported data structures.
-func CheckRuntimeTimerOverflow() {
- // We manually create a runtimeTimer to bypass the overflow
- // detection logic in NewTimer: we're testing the underlying
- // runtime.addtimer function.
+func CheckRuntimeTimerPeriodOverflow() {
+ // We manually create a runtimeTimer with huge period, but that expires
+ // immediately. The public Timer interface would require waiting for
+ // the entire period before the first update.
r := &runtimeTimer{
- when: runtimeNano() + (1<<63 - 1),
- f: empty,
- arg: nil,
+ when: runtimeNano(),
+ period: 1<<63 - 1,
+ f: empty,
+ arg: nil,
}
startTimer(r)
+ defer stopTimer(r)
- // Start a goroutine that should send on t.C right away.
- t := NewTimer(1)
-
- defer func() {
- // Subsequent tests won't work correctly if we don't stop the
- // overflow timer and kick the timer proc back into service.
- //
- // The timer proc is now sleeping and can only be awoken by
- // adding a timer to the *beginning* of the heap. We can't
- // wake it up by calling NewTimer since other tests may have
- // left timers running that should have expired before ours.
- // Instead we zero the overflow timer duration and start it
- // once more.
- stopTimer(r)
- t.Stop()
- resetTimer(r, 0)
- }()
-
- // If the test fails, we will hang here until the timeout in the
- // testing package fires, which is 10 minutes. It would be nice to
- // catch the problem sooner, but there is no reliable way to guarantee
- // that timers are run without doing something involving the scheduler.
- // Previous failed attempts have tried calling runtime.Gosched and
- // runtime.GC, but neither is reliable. So we fall back to hope:
- // We hope we don't hang here.
- <-t.C
+ // If this test fails, we will either throw (when siftdownTimer detects
+ // bad when on update), or other timers will hang (if the timer in a
+ // heap is in a bad state). There is no reliable way to test this, but
+ // we wait on a short timer here as a smoke test (alternatively, timers
+ // in later tests may hang).
+ <-After(25 * Millisecond)
}
var (
diff --git a/src/time/sleep.go b/src/time/sleep.go
index 22ffd68282..90d8a18a68 100644
--- a/src/time/sleep.go
+++ b/src/time/sleep.go
@@ -31,6 +31,8 @@ func when(d Duration) int64 {
}
t := runtimeNano() + int64(d)
if t < 0 {
+ // N.B. runtimeNano() and d are always positive, so addition
+ // (including overflow) will never result in t == 0.
t = 1<<63 - 1 // math.MaxInt64
}
return t
diff --git a/src/time/sleep_test.go b/src/time/sleep_test.go
index ba0016bf49..084ac33f51 100644
--- a/src/time/sleep_test.go
+++ b/src/time/sleep_test.go
@@ -434,17 +434,29 @@ func TestReset(t *testing.T) {
t.Error(err)
}
-// Test that sleeping for an interval so large it overflows does not
-// result in a short sleep duration.
+// Test that sleeping (via Sleep or Timer) for an interval so large it
+// overflows does not result in a short sleep duration. Nor does it interfere
+// with execution of other timers. If it does, timers in this or subsequent
+// tests may not fire.
func TestOverflowSleep(t *testing.T) {
const big = Duration(int64(1<<63 - 1))
+
+ go func() {
+ Sleep(big)
+ // On failure, this may return after the test has completed, so
+ // we need to panic instead.
+ panic("big sleep returned")
+ }()
+
select {
case <-After(big):
t.Fatalf("big timeout fired")
case <-After(25 * Millisecond):
// OK
}
+
const neg = Duration(-1 << 63)
+ Sleep(neg) // Returns immediately.
select {
case <-After(neg):
// OK
@@ -473,13 +485,10 @@ func TestIssue5745(t *testing.T) {
t.Error("Should be unreachable.")
}
-func TestOverflowRuntimeTimer(t *testing.T) {
- if testing.Short() {
- t.Skip("skipping in short mode, see issue 6874")
- }
+func TestOverflowPeriodRuntimeTimer(t *testing.T) {
// This may hang forever if timers are broken. See comment near
// the end of CheckRuntimeTimerOverflow in internal_test.go.
- CheckRuntimeTimerOverflow()
+ CheckRuntimeTimerPeriodOverflow()
}
func checkZeroPanicString(t *testing.T) {
diff --git a/src/time/tzdata/generate_zipdata.go b/src/time/tzdata/generate_zipdata.go
index d8b47e7878..21357fbf1c 100644
--- a/src/time/tzdata/generate_zipdata.go
+++ b/src/time/tzdata/generate_zipdata.go
@@ -10,7 +10,6 @@ package main
import (
"bufio"
"fmt"
- "io/ioutil"
"os"
"strconv"
)
@@ -40,7 +39,7 @@ const zipdata = `
func main() {
// We should be run in the $GOROOT/src/time/tzdata directory.
- data, err := ioutil.ReadFile("../../../lib/time/zoneinfo.zip")
+ data, err := os.ReadFile("../../../lib/time/zoneinfo.zip")
if err != nil {
die("cannot find zoneinfo.zip file: %v", err)
}
diff --git a/src/time/zoneinfo_read.go b/src/time/zoneinfo_read.go
index 22a60f3211..c739864815 100644
--- a/src/time/zoneinfo_read.go
+++ b/src/time/zoneinfo_read.go
@@ -546,7 +546,7 @@ func loadLocation(name string, sources []string) (z *Location, firstErr error) {
}
// readFile reads and returns the content of the named file.
-// It is a trivial implementation of ioutil.ReadFile, reimplemented
+// It is a trivial implementation of os.ReadFile, reimplemented
// here to avoid depending on io/ioutil or os.
// It returns an error if name exceeds maxFileSize bytes.
func readFile(name string) ([]byte, error) {
diff --git a/src/vendor/golang.org/x/sys/cpu/asm_aix_ppc64.s b/src/vendor/golang.org/x/sys/cpu/asm_aix_ppc64.s
index 06f84b8555..6b4027b33f 100644
--- a/src/vendor/golang.org/x/sys/cpu/asm_aix_ppc64.s
+++ b/src/vendor/golang.org/x/sys/cpu/asm_aix_ppc64.s
@@ -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 gc
#include "textflag.h"
diff --git a/src/vendor/golang.org/x/sys/cpu/cpu_arm64.s b/src/vendor/golang.org/x/sys/cpu/cpu_arm64.s
index a54436e390..cfc08c9794 100644
--- a/src/vendor/golang.org/x/sys/cpu/cpu_arm64.s
+++ b/src/vendor/golang.org/x/sys/cpu/cpu_arm64.s
@@ -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 gc
#include "textflag.h"
diff --git a/src/vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go b/src/vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go
index 7b88e865a4..7f7f272a01 100644
--- a/src/vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go
+++ b/src/vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go
@@ -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 gc
package cpu
diff --git a/src/vendor/golang.org/x/sys/cpu/cpu_gc_s390x.go b/src/vendor/golang.org/x/sys/cpu/cpu_gc_s390x.go
index 568bcd031a..75a9556616 100644
--- a/src/vendor/golang.org/x/sys/cpu/cpu_gc_s390x.go
+++ b/src/vendor/golang.org/x/sys/cpu/cpu_gc_s390x.go
@@ -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 gc
package cpu
diff --git a/src/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go b/src/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go
index f7cb46971c..4adb89cf9c 100644
--- a/src/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go
+++ b/src/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go
@@ -3,7 +3,7 @@
// license that can be found in the LICENSE file.
// +build 386 amd64 amd64p32
-// +build !gccgo
+// +build gc
package cpu
diff --git a/src/vendor/golang.org/x/sys/cpu/cpu_s390x.s b/src/vendor/golang.org/x/sys/cpu/cpu_s390x.s
index e5037d92e0..964946df95 100644
--- a/src/vendor/golang.org/x/sys/cpu/cpu_s390x.s
+++ b/src/vendor/golang.org/x/sys/cpu/cpu_s390x.s
@@ -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 gc
#include "textflag.h"
diff --git a/src/vendor/golang.org/x/sys/cpu/cpu_x86.s b/src/vendor/golang.org/x/sys/cpu/cpu_x86.s
index 47f084128c..2f557a5887 100644
--- a/src/vendor/golang.org/x/sys/cpu/cpu_x86.s
+++ b/src/vendor/golang.org/x/sys/cpu/cpu_x86.s
@@ -3,7 +3,7 @@
// license that can be found in the LICENSE file.
// +build 386 amd64 amd64p32
-// +build !gccgo
+// +build gc
#include "textflag.h"
diff --git a/src/vendor/golang.org/x/sys/cpu/syscall_aix_ppc64_gc.go b/src/vendor/golang.org/x/sys/cpu/syscall_aix_ppc64_gc.go
index 78fe25e86f..5b427d67e2 100644
--- a/src/vendor/golang.org/x/sys/cpu/syscall_aix_ppc64_gc.go
+++ b/src/vendor/golang.org/x/sys/cpu/syscall_aix_ppc64_gc.go
@@ -7,7 +7,7 @@
// (See golang.org/issue/32102)
// +build aix,ppc64
-// +build !gccgo
+// +build gc
package cpu
diff --git a/src/vendor/modules.txt b/src/vendor/modules.txt
index 24a3751400..de727ef71f 100644
--- a/src/vendor/modules.txt
+++ b/src/vendor/modules.txt
@@ -18,7 +18,7 @@ golang.org/x/net/idna
golang.org/x/net/lif
golang.org/x/net/nettest
golang.org/x/net/route
-# golang.org/x/sys v0.0.0-20201110211018-35f3e6cf4a65
+# golang.org/x/sys v0.0.0-20201204225414-ed752295db88
## explicit
golang.org/x/sys/cpu
# golang.org/x/text v0.3.4
diff --git a/test/assign.go b/test/assign.go
index 549f42eb80..bdec58b710 100644
--- a/test/assign.go
+++ b/test/assign.go
@@ -42,7 +42,7 @@ func main() {
_ = x
}
{
- x := sync.Mutex{key: 0} // ERROR "(unknown|assignment).*Mutex|unknown field.* in struct literal"
+ x := sync.Mutex{key: 0} // ERROR "(unknown|assignment).*Mutex"
_ = x
}
{
@@ -56,13 +56,13 @@ func main() {
{
var x = 1
{
- x, x := 2, 3 // ERROR "x repeated on left side of :=|x redeclared in this block"
+ x, x := 2, 3 // ERROR ".*x.* repeated on left side of :=|x redeclared in this block"
_ = x
}
_ = x
}
{
- a, a := 1, 2 // ERROR "a repeated on left side of :=|a redeclared in this block"
+ a, a := 1, 2 // ERROR ".*a.* repeated on left side of :=|a redeclared in this block"
_ = a
}
}
diff --git a/test/blank1.go b/test/blank1.go
index 3c981cd5eb..815a7e9b5a 100644
--- a/test/blank1.go
+++ b/test/blank1.go
@@ -13,7 +13,7 @@ var t struct {
_ int
}
-func (x int) _() { // ERROR "cannot define new methods on non-local type"
+func (x int) _() { // ERROR "methods on non-local type"
println(x)
}
diff --git a/test/chan/perm.go b/test/chan/perm.go
index 607a356a02..4c94ab7ffa 100644
--- a/test/chan/perm.go
+++ b/test/chan/perm.go
@@ -25,8 +25,8 @@ func main() {
cs = cr // ERROR "illegal types|incompatible|cannot"
var n int
- <-n // ERROR "receive from non-chan"
- n <- 2 // ERROR "send to non-chan"
+ <-n // ERROR "receive from non-chan|expected channel"
+ n <- 2 // ERROR "send to non-chan|must be channel"
c <- 0 // ok
<-c // ok
@@ -66,5 +66,5 @@ func main() {
close(c)
close(cs)
close(cr) // ERROR "receive"
- close(n) // ERROR "invalid operation.*non-chan type|not a channel"
+ close(n) // ERROR "invalid operation.*non-chan type|must be channel|not a channel"
}
diff --git a/test/complit1.go b/test/complit1.go
index eb0f920fcb..7c2a4e2996 100644
--- a/test/complit1.go
+++ b/test/complit1.go
@@ -22,9 +22,9 @@ var (
_ = m[0][:] // ERROR "slice of unaddressable value"
_ = f()[:] // ERROR "slice of unaddressable value"
- _ = 301[:] // ERROR "cannot slice"
- _ = 3.1[:] // ERROR "cannot slice"
- _ = true[:] // ERROR "cannot slice"
+ _ = 301[:] // ERROR "cannot slice|attempt to slice object that is not"
+ _ = 3.1[:] // ERROR "cannot slice|attempt to slice object that is not"
+ _ = true[:] // ERROR "cannot slice|attempt to slice object that is not"
// these are okay because they are slicing a pointer to an array
_ = (&[3]int{1, 2, 3})[:]
@@ -46,8 +46,8 @@ var (
_ = &T{0, 0, "", nil} // ok
_ = &T{i: 0, f: 0, s: "", next: {}} // ERROR "missing type in composite literal|omit types within composite literal"
_ = &T{0, 0, "", {}} // ERROR "missing type in composite literal|omit types within composite literal"
- _ = TP{i: 0, f: 0, s: "", next: {}} // ERROR "invalid composite literal type TP"
- _ = &Ti{} // ERROR "invalid composite literal type Ti"
+ _ = TP{i: 0, f: 0, s: "", next: {}} // ERROR "invalid composite literal type TP|omit types within composite literal"
+ _ = &Ti{} // ERROR "invalid composite literal type Ti|expected.*type for composite literal"
)
type M map[T]T
diff --git a/test/convlit.go b/test/convlit.go
index de760542da..1c66c89e88 100644
--- a/test/convlit.go
+++ b/test/convlit.go
@@ -21,9 +21,9 @@ var x6 = int(1e100) // ERROR "overflow"
var x7 = float32(1e1000) // ERROR "overflow"
// unsafe.Pointer can only convert to/from uintptr
-var _ = string(unsafe.Pointer(uintptr(65))) // ERROR "convert"
-var _ = float64(unsafe.Pointer(uintptr(65))) // ERROR "convert"
-var _ = int(unsafe.Pointer(uintptr(65))) // ERROR "convert"
+var _ = string(unsafe.Pointer(uintptr(65))) // ERROR "convert|conversion"
+var _ = float64(unsafe.Pointer(uintptr(65))) // ERROR "convert|conversion"
+var _ = int(unsafe.Pointer(uintptr(65))) // ERROR "convert|conversion"
// implicit conversions merit scrutiny
var s string
diff --git a/test/ddd1.go b/test/ddd1.go
index 9857814648..01b9c0eadb 100644
--- a/test/ddd1.go
+++ b/test/ddd1.go
@@ -60,5 +60,5 @@ func bad(args ...int) {
_ = [...]byte("foo") // ERROR "[.][.][.]"
_ = [...][...]int{{1,2,3},{4,5,6}} // ERROR "[.][.][.]"
- Foo(x...) // ERROR "invalid use of [.][.][.] in call"
+ Foo(x...) // ERROR "invalid use of .*[.][.][.]"
}
diff --git a/test/fixedbugs/bug176.go b/test/fixedbugs/bug176.go
index ea3a909747..7001dd081e 100644
--- a/test/fixedbugs/bug176.go
+++ b/test/fixedbugs/bug176.go
@@ -9,6 +9,6 @@ package main
var x int
var a = []int{ x: 1} // ERROR "constant"
-var b = [...]int{x: 1}
+var b = [...]int{x: 1} // GCCGO_ERROR "constant"
var c = map[int]int{ x: 1}
diff --git a/test/fixedbugs/bug332.go b/test/fixedbugs/bug332.go
index d43c2ddcff..159c8b4e68 100644
--- a/test/fixedbugs/bug332.go
+++ b/test/fixedbugs/bug332.go
@@ -14,4 +14,4 @@ func main() {}
// important: no newline on end of next line.
// 6g used to print instead of bug332.go:111
-func (t *T) F() {} // ERROR "undefined: T"
\ No newline at end of file
+func (t *T) F() {} // ERROR "undefined.*T"
\ No newline at end of file
diff --git a/test/fixedbugs/bug340.go b/test/fixedbugs/bug340.go
index a067940408..542a6eab03 100644
--- a/test/fixedbugs/bug340.go
+++ b/test/fixedbugs/bug340.go
@@ -13,6 +13,6 @@ func main() {
switch t := x.(type) {
case 0: // ERROR "type"
t.x = 1
- x.x = 1 // ERROR "type interface \{\}|reference to undefined field or method"
+ x.x = 1 // ERROR "type interface \{\}|reference to undefined field or method|interface with no methods"
}
}
diff --git a/test/fixedbugs/bug487.go b/test/fixedbugs/bug487.go
index ab61a19a94..e60af6c8e2 100644
--- a/test/fixedbugs/bug487.go
+++ b/test/fixedbugs/bug487.go
@@ -14,8 +14,8 @@ func G() (int, int, int) {
}
func F() {
- a, b := G() // ERROR "assignment mismatch"
- a, b = G() // ERROR "assignment mismatch"
+ a, b := G() // ERROR "mismatch"
+ a, b = G() // ERROR "mismatch"
_, _ = a, b
}
diff --git a/test/fixedbugs/bug510.dir/a.go b/test/fixedbugs/bug510.dir/a.go
new file mode 100644
index 0000000000..db1cfef366
--- /dev/null
+++ b/test/fixedbugs/bug510.dir/a.go
@@ -0,0 +1,13 @@
+// Copyright 2020 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
+
+import "reflect"
+
+type A = map[int] bool
+
+func F() interface{} {
+ return reflect.New(reflect.TypeOf((*A)(nil))).Elem().Interface()
+}
diff --git a/test/fixedbugs/bug510.dir/b.go b/test/fixedbugs/bug510.dir/b.go
new file mode 100644
index 0000000000..56b0201858
--- /dev/null
+++ b/test/fixedbugs/bug510.dir/b.go
@@ -0,0 +1,14 @@
+// Copyright 2020 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
+
+import "./a"
+
+func main() {
+ _, ok := a.F().(*map[int]bool)
+ if !ok {
+ panic("bad type")
+ }
+}
diff --git a/src/internal/cpu/cpu_freebsd.go b/test/fixedbugs/bug510.go
similarity index 68%
rename from src/internal/cpu/cpu_freebsd.go
rename to test/fixedbugs/bug510.go
index dc37173dac..8a6da5dfd6 100644
--- a/src/internal/cpu/cpu_freebsd.go
+++ b/test/fixedbugs/bug510.go
@@ -1,7 +1,9 @@
+// rundir
+
// Copyright 2020 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 cpu
+// Gccgo confused type descriptors for aliases.
-const GOOS = "freebsd"
+package ignored
diff --git a/test/fixedbugs/issue22822.go b/test/fixedbugs/issue22822.go
index 554b534503..27c873ab10 100644
--- a/test/fixedbugs/issue22822.go
+++ b/test/fixedbugs/issue22822.go
@@ -11,7 +11,9 @@ package main
func F() {
slice := []int{1, 2, 3}
- len := int(2)
- println(len(slice)) // ERROR "cannot call non-function len .type int., declared at|cannot call non-function len"
_ = slice
+ len := int(2)
+ println(len(slice)) // ERROR "cannot call non-function len .type int., declared at LINE-1|cannot call non-function len"
+ const iota = 1
+ println(iota(slice)) // ERROR "cannot call non-function iota .type int., declared at LINE-1|cannot call non-function iota"
}
diff --git a/test/fixedbugs/issue28079b.go b/test/fixedbugs/issue28079b.go
index 47cc16dfb2..9ff221baff 100644
--- a/test/fixedbugs/issue28079b.go
+++ b/test/fixedbugs/issue28079b.go
@@ -13,5 +13,5 @@ import "unsafe"
type T [uintptr(unsafe.Pointer(nil))]int // ERROR "non-constant array bound"
func f() {
- _ = complex(1< x[1] {
+ panic("fail 1")
+ }
+ if x[2]&x[3] < 0 {
+ panic("fail 2") // Fails here
+ }
+}
diff --git a/test/fixedbugs/issue42944.go b/test/fixedbugs/issue42944.go
new file mode 100644
index 0000000000..bb947bc609
--- /dev/null
+++ b/test/fixedbugs/issue42944.go
@@ -0,0 +1,24 @@
+// errorcheck -0 -live
+
+// Copyright 2020 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 42944: address of callee args area should only be short-lived
+// and never across a call.
+
+package p
+
+type T [10]int // trigger DUFFCOPY when passing by value, so it uses the address
+
+func F() {
+ var x T
+ var i int
+ for {
+ x = G(i) // no autotmp live at this and next calls
+ H(i, x)
+ }
+}
+
+func G(int) T
+func H(int, T)
diff --git a/test/fixedbugs/issue43099.go b/test/fixedbugs/issue43099.go
new file mode 100644
index 0000000000..16f18e5f96
--- /dev/null
+++ b/test/fixedbugs/issue43099.go
@@ -0,0 +1,34 @@
+// compile
+
+// Copyright 2020 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.
+
+// Check to make sure we don't try to constant fold a divide by zero.
+// This is a tricky test, as we need a value that's not recognized as 0
+// until lowering (otherwise it gets handled in a different path).
+
+package p
+
+func f() {
+ var i int
+ var s string
+ for i > 0 {
+ _ = s[0]
+ i++
+ }
+
+ var c chan int
+ c <- 1 % i
+}
+
+func f32() uint32 {
+ s := "\x00\x00\x00\x00"
+ c := uint32(s[0]) | uint32(s[1])<<8 | uint32(s[2])<<16 | uint32(s[3])<<24
+ return 1 / c
+}
+func f64() uint64 {
+ s := "\x00\x00\x00\x00\x00\x00\x00\x00"
+ c := uint64(s[0]) | uint64(s[1])<<8 | uint64(s[2])<<16 | uint64(s[3])<<24 | uint64(s[4])<<32 | uint64(s[5])<<40 | uint64(s[6])<<48 | uint64(s[7])<<56
+ return 1 / c
+}
diff --git a/test/fixedbugs/issue4458.go b/test/fixedbugs/issue4458.go
index 3ae9910d9e..6ac6d86db3 100644
--- a/test/fixedbugs/issue4458.go
+++ b/test/fixedbugs/issue4458.go
@@ -16,5 +16,5 @@ func (T) foo() {}
func main() {
av := T{}
pav := &av
- (**T).foo(&pav) // ERROR "no method foo|requires named type or pointer to named|undefined"
+ (**T).foo(&pav) // ERROR "no method .*foo|requires named type or pointer to named|undefined"
}
diff --git a/test/fixedbugs/issue5172.go b/test/fixedbugs/issue5172.go
index 0339935b64..ed92ac6ff2 100644
--- a/test/fixedbugs/issue5172.go
+++ b/test/fixedbugs/issue5172.go
@@ -21,6 +21,6 @@ func main() {
go f.bar() // ERROR "undefined"
defer f.bar() // ERROR "undefined"
- t := T{1} // ERROR "too many values"
+ t := T{1} // ERROR "too many"
go t.Bar()
}
diff --git a/test/fixedbugs/issue6977.go b/test/fixedbugs/issue6977.go
index 0f657eec41..4525e406b8 100644
--- a/test/fixedbugs/issue6977.go
+++ b/test/fixedbugs/issue6977.go
@@ -34,7 +34,7 @@ type U3 interface { M; m() }
type U4 interface { M; M; M }
type U5 interface { U1; U2; U3; U4 }
-type U6 interface { m(); m() } // ERROR "duplicate method m"
-type U7 interface { M32; m() } // ERROR "duplicate method m"
-type U8 interface { m(); M32 } // ERROR "duplicate method m"
-type U9 interface { M32; M64 } // ERROR "duplicate method m"
+type U6 interface { m(); m() } // ERROR "duplicate method .*m"
+type U7 interface { M32; m() } // ERROR "duplicate method .*m"
+type U8 interface { m(); M32 } // ERROR "duplicate method .*m"
+type U9 interface { M32; M64 } // ERROR "duplicate method .*m"
diff --git a/test/init.go b/test/init.go
index c2c25c7860..43bb3c6503 100644
--- a/test/init.go
+++ b/test/init.go
@@ -14,6 +14,6 @@ func init() {
func main() {
init() // ERROR "undefined.*init"
- runtime.init() // ERROR "undefined.*runtime\.init|undefined: runtime"
+ runtime.init() // ERROR "undefined.*runtime\.init|reference to undefined name|undefined: runtime"
var _ = init // ERROR "undefined.*init"
}
diff --git a/test/initializerr.go b/test/initializerr.go
index 990ab60f96..5e2e9a91a0 100644
--- a/test/initializerr.go
+++ b/test/initializerr.go
@@ -23,7 +23,7 @@ var a2 = S { Y: 3, Z: 2, Y: 3 } // ERROR "duplicate"
var a3 = T { S{}, 2, 3, 4, 5, 6 } // ERROR "convert|too many"
var a4 = [5]byte{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 } // ERROR "index|too many"
var a5 = []byte { x: 2 } // ERROR "index"
-var a6 = []byte{1: 1, 2: 2, 1: 3} // ERROR "duplicate index"
+var a6 = []byte{1: 1, 2: 2, 1: 3} // ERROR "duplicate"
var ok1 = S { } // should be ok
var ok2 = T { S: ok1 } // should be ok
diff --git a/test/interface/explicit.go b/test/interface/explicit.go
index 7aaaad4e48..1b7af6712b 100644
--- a/test/interface/explicit.go
+++ b/test/interface/explicit.go
@@ -47,7 +47,7 @@ func main() {
t = i // ERROR "incompatible|assignment$"
i = i2 // ok
- i2 = i // ERROR "incompatible|missing N method|cannot convert"
+ i2 = i // ERROR "incompatible|missing N method"
i = I(i2) // ok
i2 = I2(i) // ERROR "invalid|missing N method|cannot convert"
@@ -57,7 +57,7 @@ func main() {
// cannot type-assert non-interfaces
f := 2.0
- _ = f.(int) // ERROR "non-interface type|not an interface type"
+ _ = f.(int) // ERROR "non-interface type|only valid for interface types|not an interface type"
}
@@ -100,10 +100,7 @@ type T2 struct{}
func (t *T2) M() {}
func (t *T2) _() {}
-// Check that nothing satisfies an interface with blank methods.
-// Disabled this test as it's not clear we need this behavior.
-// See also issue #42964.
-/*
-var b1 B1 = &T2{} // "incompatible|missing _ method"
-var b2 B2 = &T2{} // "incompatible|missing _ method"
-*/
\ No newline at end of file
+// Already reported about the invalid blank interface method above;
+// no need to report about not implementing it.
+var b1 B1 = &T2{}
+var b2 B2 = &T2{}
diff --git a/test/label.go b/test/label.go
index 11716cc2c5..7deead6fba 100644
--- a/test/label.go
+++ b/test/label.go
@@ -61,5 +61,5 @@ L10:
goto L10
- goto go2 // ERROR "label go2 not defined"
+ goto go2 // ERROR "label go2 not defined|reference to undefined label .*go2"
}
diff --git a/test/label1.go b/test/label1.go
index b2e0ef09b8..a8eaecbff2 100644
--- a/test/label1.go
+++ b/test/label1.go
@@ -15,11 +15,11 @@ var x int
func f1() {
switch x {
case 1:
- continue // ERROR "continue is not in a loop$"
+ continue // ERROR "continue is not in a loop$|continue statement not within for"
}
select {
default:
- continue // ERROR "continue is not in a loop$"
+ continue // ERROR "continue is not in a loop$|continue statement not within for"
}
}
@@ -103,14 +103,14 @@ L5:
}
}
- continue // ERROR "continue is not in a loop$"
+ continue // ERROR "continue is not in a loop$|continue statement not within for"
for {
- continue on // ERROR "continue label not defined: on"
+ continue on // ERROR "continue label not defined: on|invalid continue label .*on"
}
- break // ERROR "break is not in a loop, switch, or select"
+ break // ERROR "break is not in a loop, switch, or select|break statement not within for or switch or select"
for {
- break dance // ERROR "break label not defined: dance"
+ break dance // ERROR "break label not defined: dance|invalid break label .*dance"
}
for {
diff --git a/test/linkname2.go b/test/linkname2.go
new file mode 100644
index 0000000000..43e66a5849
--- /dev/null
+++ b/test/linkname2.go
@@ -0,0 +1,30 @@
+// errorcheck
+
+// Copyright 2020 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.
+
+// Tests that errors are reported for misuse of linkname.
+package p
+
+import _ "unsafe"
+
+type t int
+
+var x, y int
+
+//go:linkname x ok
+
+// ERROR "//go:linkname requires linkname argument or -p compiler flag"
+// BAD: want error "//go:linkname must refer to declared function or variable"
+// BAD: want error "//go:linkname must refer to declared function or variable"
+// ERROR "duplicate //go:linkname for x"
+
+// The two BAD lines are just waiting for #42938 before we can
+// re-enable the errors.
+
+//line linkname2.go:18
+//go:linkname y
+//go:linkname nonexist nonexist
+//go:linkname t notvarfunc
+//go:linkname x duplicate
diff --git a/test/live.go b/test/live.go
index 3df7ab01af..d52ce7f007 100644
--- a/test/live.go
+++ b/test/live.go
@@ -718,5 +718,5 @@ func f44(f func() [2]*int) interface{} { // ERROR "live at entry to f44: f"
}
ret := T{}
ret.s[0] = f()
- return ret // ERROR "stack object .autotmp_5 T"
+ return ret // ERROR "stack object .autotmp_[0-9]+ T"
}
diff --git a/test/map1.go b/test/map1.go
index bd4d87b871..a6b27e6ebd 100644
--- a/test/map1.go
+++ b/test/map1.go
@@ -64,5 +64,5 @@ func main() {
delete() // ERROR "missing arguments|not enough arguments"
delete(m) // ERROR "missing second \(key\) argument|not enough arguments"
delete(m, 2, 3) // ERROR "too many arguments"
- delete(1, m) // ERROR "first argument to delete must be map|is not a map"
-}
\ No newline at end of file
+ delete(1, m) // ERROR "first argument to delete must be map|argument 1 must be a map|is not a map"
+}
diff --git a/test/method2.go b/test/method2.go
index 790062c2af..2a92136d6c 100644
--- a/test/method2.go
+++ b/test/method2.go
@@ -33,9 +33,9 @@ var _ = (*Val).val // ERROR "method"
var v Val
var pv = &v
-var _ = pv.val() // ERROR "pv.val undefined"
-var _ = pv.val // ERROR "pv.val undefined"
+var _ = pv.val() // ERROR "undefined|pointer to interface"
+var _ = pv.val // ERROR "undefined|pointer to interface"
func (t *T) g() int { return t.a }
-var _ = (T).g() // ERROR "needs pointer receiver|undefined|cannot call pointer method"
+var _ = (T).g() // ERROR "needs pointer receiver|undefined|method requires pointer|cannot call pointer method"
diff --git a/test/run.go b/test/run.go
index 3e0e7ab368..91bdd629bf 100644
--- a/test/run.go
+++ b/test/run.go
@@ -14,6 +14,7 @@ import (
"fmt"
"hash/fnv"
"io"
+ "io/fs"
"io/ioutil"
"log"
"os"
@@ -1869,7 +1870,7 @@ func overlayDir(dstRoot, srcRoot string) error {
return err
}
- return filepath.Walk(srcRoot, func(srcPath string, info os.FileInfo, err error) error {
+ return filepath.WalkDir(srcRoot, func(srcPath string, d fs.DirEntry, err error) error {
if err != nil || srcPath == srcRoot {
return err
}
@@ -1880,14 +1881,16 @@ func overlayDir(dstRoot, srcRoot string) error {
}
dstPath := filepath.Join(dstRoot, suffix)
- perm := info.Mode() & os.ModePerm
- if info.Mode()&os.ModeSymlink != 0 {
+ var info fs.FileInfo
+ if d.Type()&os.ModeSymlink != 0 {
info, err = os.Stat(srcPath)
- if err != nil {
- return err
- }
- perm = info.Mode() & os.ModePerm
+ } else {
+ info, err = d.Info()
}
+ if err != nil {
+ return err
+ }
+ perm := info.Mode() & os.ModePerm
// Always copy directories (don't symlink them).
// If we add a file in the overlay, we don't want to add it in the original.
@@ -1933,6 +1936,7 @@ var excluded = map[string]bool{
"import5.go": true, // issue #42988
"import6.go": true,
"initializerr.go": true,
+ "linkname2.go": true,
"makechan.go": true,
"makemap.go": true,
"shift1.go": true, // issue #42989
diff --git a/test/shift1.go b/test/shift1.go
index df0c032cd5..d6a6c38839 100644
--- a/test/shift1.go
+++ b/test/shift1.go
@@ -73,8 +73,8 @@ func _() {
// non constants arguments trigger a different path
f2 := 1.2
s2 := "hi"
- _ = f2 << 2 // ERROR "shift of type float64"
- _ = s2 << 2 // ERROR "shift of type string"
+ _ = f2 << 2 // ERROR "shift of type float64|non-integer"
+ _ = s2 << 2 // ERROR "shift of type string|non-integer"
}
// shifts in comparisons w/ untyped operands
diff --git a/test/syntax/chan1.go b/test/syntax/chan1.go
index 56103d1d79..88a5b4777b 100644
--- a/test/syntax/chan1.go
+++ b/test/syntax/chan1.go
@@ -10,8 +10,8 @@ var c chan int
var v int
func main() {
- if c <- v { // ERROR "cannot use c <- v as value"
+ if c <- v { // ERROR "cannot use c <- v as value|send statement used as value"
}
}
-var _ = c <- v // ERROR "unexpected <-"
+var _ = c <- v // ERROR "unexpected <-|send statement used as value"
diff --git a/test/syntax/semi4.go b/test/syntax/semi4.go
index f21431b3f5..08c354751b 100644
--- a/test/syntax/semi4.go
+++ b/test/syntax/semi4.go
@@ -8,5 +8,5 @@ package main
func main() {
for x // GCCGO_ERROR "undefined"
- { // ERROR "unexpected {, expecting for loop condition"
- z
+ { // ERROR "unexpected {, expecting for loop condition|expecting .*{.* after for clause"
+ z // GCCGO_ERROR "undefined"
diff --git a/test/syntax/semi6.go b/test/syntax/semi6.go
index 4a04f89ddb..9bc730d43d 100644
--- a/test/syntax/semi6.go
+++ b/test/syntax/semi6.go
@@ -6,6 +6,6 @@
package main
-type T1 // ERROR "unexpected newline in type declaration"
+type T1 // ERROR "newline in type declaration"
-type T2 /* // ERROR "unexpected EOF in type declaration" */
\ No newline at end of file
+type T2 /* // ERROR "(semicolon.*|EOF) in type declaration" */
\ No newline at end of file
diff --git a/test/used.go b/test/used.go
new file mode 100644
index 0000000000..a3f0e1270b
--- /dev/null
+++ b/test/used.go
@@ -0,0 +1,144 @@
+// errorcheck
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+import "unsafe"
+
+const C = 1
+
+var x, x1, x2 int
+var b bool
+var s string
+var c chan int
+var cp complex128
+var slice []int
+var array [2]int
+var bytes []byte
+var runes []rune
+var r rune
+
+func f0() {}
+func f1() int { return 1 }
+func f2() (int, int) { return 1, 1 }
+
+type T struct{ X int }
+
+func (T) M1() int { return 1 }
+func (T) M0() {}
+func (T) M() {}
+
+var t T
+var tp *T
+
+type I interface{ M() }
+
+var i I
+
+var m map[int]int
+
+func _() {
+ // Note: if the next line changes to x, the error silences the x+x etc below!
+ x1 // ERROR "x1 .* not used"
+
+ nil // ERROR "nil .* not used"
+ C // ERROR "C .* not used"
+ 1 // ERROR "1 .* not used"
+ x + x // ERROR "x \+ x .* not used"
+ x - x // ERROR "x - x .* not used"
+ x | x // ERROR "x \| x .* not used"
+ "a" + s // ERROR ".a. \+ s .* not used"
+ &x // ERROR "&x .* not used"
+ b && b // ERROR "b && b .* not used"
+ append(slice, 1) // ERROR "append\(slice, 1\) .* not used"
+ string(bytes) // ERROR "string\(bytes\) .* not used"
+ string(runes) // ERROR "string\(runes\) .* not used"
+ f0() // ok
+ f1() // ok
+ f2() // ok
+ _ = f0() // ERROR "f0\(\) .*used as value"
+ _ = f1() // ok
+ _, _ = f2() // ok
+ _ = f2() // ERROR "assignment mismatch: 1 variable but f2 returns 2 values|cannot assign"
+ T.M0 // ERROR "T.M0 .* not used"
+ t.M0 // ERROR "t.M0 .* not used"
+ cap // ERROR "use of builtin cap not in function call|must be called"
+ cap(slice) // ERROR "cap\(slice\) .* not used"
+ close(c) // ok
+ _ = close(c) // ERROR "close\(c\) .*used as value"
+ func() {} // ERROR "func literal .* not used|is not used"
+ X{} // ERROR "undefined: X"
+ map[string]int{} // ERROR "map\[string\]int{} .* not used"
+ struct{}{} // ERROR "struct ?{}{} .* not used"
+ [1]int{} // ERROR "\[1\]int{} .* not used"
+ []int{} // ERROR "\[\]int{} .* not used"
+ &struct{}{} // ERROR "&struct ?{}{} .* not used"
+ float32(x) // ERROR "float32\(x\) .* not used"
+ I(t) // ERROR "I\(t\) .* not used"
+ int(x) // ERROR "int\(x\) .* not used"
+ copy(slice, slice) // ok
+ _ = copy(slice, slice) // ok
+ delete(m, 1) // ok
+ _ = delete(m, 1) // ERROR "delete\(m, 1\) .*used as value"
+ t.X // ERROR "t.X .* not used"
+ tp.X // ERROR "tp.X .* not used"
+ t.M // ERROR "t.M .* not used"
+ I.M // ERROR "I.M .* not used"
+ i.(T) // ERROR "i.\(T\) .* not used"
+ x == x // ERROR "x == x .* not used"
+ x != x // ERROR "x != x .* not used"
+ x != x // ERROR "x != x .* not used"
+ x < x // ERROR "x < x .* not used"
+ x >= x // ERROR "x >= x .* not used"
+ x > x // ERROR "x > x .* not used"
+ *tp // ERROR "\*tp .* not used"
+ slice[0] // ERROR "slice\[0\] .* not used"
+ m[1] // ERROR "m\[1\] .* not used"
+ len(slice) // ERROR "len\(slice\) .* not used"
+ make(chan int) // ERROR "make\(chan int\) .* not used"
+ make(map[int]int) // ERROR "make\(map\[int\]int\) .* not used"
+ make([]int, 1) // ERROR "make\(\[\]int, 1\) .* not used"
+ x * x // ERROR "x \* x .* not used"
+ x / x // ERROR "x / x .* not used"
+ x % x // ERROR "x % x .* not used"
+ x << x // ERROR "x << x .* not used"
+ x >> x // ERROR "x >> x .* not used"
+ x & x // ERROR "x & x .* not used"
+ x &^ x // ERROR "x &\^ x .* not used"
+ new(int) // ERROR "new\(int\) .* not used"
+ !b // ERROR "!b .* not used"
+ ^x // ERROR "\^x .* not used"
+ +x // ERROR "\+x .* not used"
+ -x // ERROR "-x .* not used"
+ b || b // ERROR "b \|\| b .* not used"
+ panic(1) // ok
+ _ = panic(1) // ERROR "panic\(1\) .*used as value"
+ print(1) // ok
+ _ = print(1) // ERROR "print\(1\) .*used as value"
+ println(1) // ok
+ _ = println(1) // ERROR "println\(1\) .*used as value"
+ c <- 1 // ok
+ slice[1:1] // ERROR "slice\[1:1\] .* not used"
+ array[1:1] // ERROR "array\[1:1\] .* not used"
+ s[1:1] // ERROR "s\[1:1\] .* not used"
+ slice[1:1:1] // ERROR "slice\[1:1:1\] .* not used"
+ array[1:1:1] // ERROR "array\[1:1:1\] .* not used"
+ recover() // ok
+ <-c // ok
+ string(r) // ERROR "string\(r\) .* not used"
+ iota // ERROR "undefined: iota|cannot use iota"
+ real(cp) // ERROR "real\(cp\) .* not used"
+ imag(cp) // ERROR "imag\(cp\) .* not used"
+ complex(1, 2) // ERROR "complex\(1, 2\) .* not used"
+ unsafe.Alignof(t.X) // ERROR "unsafe.Alignof\(t.X\) .* not used"
+ unsafe.Offsetof(t.X) // ERROR "unsafe.Offsetof\(t.X\) .* not used"
+ unsafe.Sizeof(t) // ERROR "unsafe.Sizeof\(t\) .* not used"
+ _ = int // ERROR "type int is not an expression|not an expression"
+ (x) // ERROR "x .* not used|not used"
+ _ = new(x2) // ERROR "x2 is not a type|not a type"
+ // Disabled due to issue #43125.
+ // _ = new(1 + 1) // DISABLED "1 \+ 1 is not a type"
+}
diff --git a/test/winbatch.go b/test/winbatch.go
index c3b48d385c..54c2fff134 100644
--- a/test/winbatch.go
+++ b/test/winbatch.go
@@ -27,11 +27,11 @@ func main() {
// Walk the entire Go repository source tree (without GOROOT/pkg),
// skipping directories that start with "." and named "testdata",
// and ensure all .bat files found have exact CRLF line endings.
- err := filepath.Walk(runtime.GOROOT(), func(path string, fi os.FileInfo, err error) error {
+ err := filepath.WalkDir(runtime.GOROOT(), func(path string, d os.DirEntry, err error) error {
if err != nil {
return err
}
- if fi.IsDir() && (strings.HasPrefix(fi.Name(), ".") || fi.Name() == "testdata") {
+ if d.IsDir() && (strings.HasPrefix(d.Name(), ".") || d.Name() == "testdata") {
return filepath.SkipDir
}
if path == filepath.Join(runtime.GOROOT(), "pkg") {
@@ -39,7 +39,7 @@ func main() {
// Skip it to avoid false positives. (Also see golang.org/issue/37929.)
return filepath.SkipDir
}
- if filepath.Ext(fi.Name()) == ".bat" {
+ if filepath.Ext(d.Name()) == ".bat" {
enforceBatchStrictCRLF(path)
}
return nil