diff --git a/AUTHORS b/AUTHORS index ad907967b4..8d7e196732 100644 --- a/AUTHORS +++ b/AUTHORS @@ -817,6 +817,7 @@ Lehner Florian Leigh McCulloch Leo Antunes Leon Klingele +Leonard Wang Leonel Quinteros Lev Shamardin Lewin Bormann diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 706d630193..a548cb0e2f 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -1569,7 +1569,7 @@ Leigh McCulloch Leo Antunes Leo Rudberg Leon Klingele -Leonard Wang +Leonard Wang Leonardo Comelli Leonel Quinteros Lev Shamardin diff --git a/api/next.txt b/api/next.txt index 9e4bb83cb7..cc4120b7ab 100644 --- a/api/next.txt +++ b/api/next.txt @@ -8,114 +8,6 @@ pkg runtime/debug, type BuildInfo struct, Settings []BuildSetting pkg runtime/debug, type BuildSetting struct pkg runtime/debug, type BuildSetting struct, Key string pkg runtime/debug, type BuildSetting struct, Value string -pkg syscall (darwin-amd64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (darwin-amd64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (darwin-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (darwin-amd64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (darwin-amd64-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (darwin-amd64-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (darwin-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (darwin-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (freebsd-386), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (freebsd-386), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (freebsd-386), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (freebsd-386), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (freebsd-386-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (freebsd-386-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (freebsd-386-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (freebsd-386-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (freebsd-amd64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (freebsd-amd64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (freebsd-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (freebsd-amd64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (freebsd-amd64-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (freebsd-amd64-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (freebsd-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (freebsd-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (freebsd-arm), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (freebsd-arm), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (freebsd-arm), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (freebsd-arm), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (freebsd-arm-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (freebsd-arm-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (freebsd-arm-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (freebsd-arm-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (linux-386), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (linux-386), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (linux-386), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (linux-386), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (linux-386-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (linux-386-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (linux-386-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (linux-386-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (linux-amd64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (linux-amd64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (linux-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (linux-amd64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (linux-amd64-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (linux-amd64-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (linux-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (linux-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (linux-arm), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (linux-arm), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (linux-arm), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (linux-arm), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (linux-arm-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (linux-arm-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (linux-arm-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (linux-arm-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (netbsd-386), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (netbsd-386), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (netbsd-386), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (netbsd-386), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (netbsd-386-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (netbsd-386-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (netbsd-386-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (netbsd-386-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (netbsd-amd64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (netbsd-amd64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (netbsd-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (netbsd-amd64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (netbsd-amd64-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (netbsd-amd64-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (netbsd-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (netbsd-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (netbsd-arm), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (netbsd-arm), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (netbsd-arm), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (netbsd-arm), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (netbsd-arm-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (netbsd-arm-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (netbsd-arm-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (netbsd-arm-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (netbsd-arm64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (netbsd-arm64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (netbsd-arm64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (netbsd-arm64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (netbsd-arm64-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (netbsd-arm64-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (netbsd-arm64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (netbsd-arm64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (openbsd-386), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (openbsd-386), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (openbsd-386), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (openbsd-386), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (openbsd-386-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (openbsd-386-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (openbsd-386-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (openbsd-386-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (openbsd-amd64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (openbsd-amd64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (openbsd-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (openbsd-amd64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (openbsd-amd64-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (openbsd-amd64-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (openbsd-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (openbsd-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (windows-386), func WSASendtoInet4(Handle, *WSABuf, uint32, *uint32, uint32, SockaddrInet4, *Overlapped, *uint8) error -pkg syscall (windows-386), func WSASendtoInet6(Handle, *WSABuf, uint32, *uint32, uint32, SockaddrInet6, *Overlapped, *uint8) error -pkg syscall (windows-amd64), func WSASendtoInet4(Handle, *WSABuf, uint32, *uint32, uint32, SockaddrInet4, *Overlapped, *uint8) error -pkg syscall (windows-amd64), func WSASendtoInet6(Handle, *WSABuf, uint32, *uint32, uint32, SockaddrInet6, *Overlapped, *uint8) error pkg testing, func Fuzz(func(*F)) FuzzResult pkg testing, func MainStart(testDeps, []InternalTest, []InternalBenchmark, []InternalFuzzTarget, []InternalExample) *M pkg testing, func RunFuzzTargets(func(string, string) (bool, error), []InternalFuzzTarget) bool diff --git a/doc/go1.18.html b/doc/go1.18.html index 2ed37124d5..40fe30e844 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -31,19 +31,30 @@ Do not send CLs removing the interior tags from such phrases.

Ports

-

+

FreeBSD

+ +

Go 1.18 is the last release that is supported on FreeBSD 11.x, which has already reached end-of-life. Go 1.19 will require FreeBSD 12.2+ or FreeBSD 13.0+. FreeBSD 13.0+ will require a kernel with the COMPAT_FREEBSD12 option set (this is the default).

-

Tools

+

PPC64

-

- TODO: complete this section, or delete if not needed +

+ TODO: https://golang.org/cl/353969: internal/buildcfg: enable register ABI for PPC64

+

RISC-V

+ +

+ The 64-bit RISC-V architecture on Linux (the linux/riscv64 port) + now supports the c-archive and c-shared build modes. +

+ +

Tools

+

Go command

@@ -90,8 +101,21 @@ Do not send CLs removing the interior tags from such phrases. package.

-

- TODO: complete this section, or delete if not needed +

+ If the main module's go.mod file + specifies go 1.17 + or higher, go mod download without + arguments now downloads source code for only the modules + explicitly required in the main + module's go.mod file. (In a go 1.17 or + higher module, that set already includes all dependencies needed to build the + packages and tests in the main module.) + To also download source code for transitive dependencies, use + go mod download all. +

+ +

+ TODO: https://golang.org/cl/349595: https://golang.org/cl/349595: cmd/go: add GOAMD64 environment variable

gofmt

@@ -102,7 +126,6 @@ Do not send CLs removing the interior tags from such phrases. multiple CPUs, gofmt should now be significantly faster.

-

Runtime

@@ -111,18 +134,53 @@ Do not send CLs removing the interior tags from such phrases.

Compiler

-

- TODO: complete this section, or delete if not needed +

+ TODO: https://golang.org/cl/298611: https://golang.org/cl/298611: cmd/compile: add -asan option +

+ +

+ TODO: https://golang.org/cl/352057: https://golang.org/cl/352057: cmd/compile, runtime: track argument stack slot liveness

Linker

-

- TODO: complete this section, or delete if not needed +

+ TODO: https://golang.org/cl/298610: https://golang.org/cl/298610: cmd/link: add -asan option

Core library

+

New constraints package

+ +

+ TODO: https://golang.org/cl/349709: constraints: new package +

+ +

New net/netip package

+ +

+ The new net/netip + package defines a new IP address type, Addr. + Compared to the existing + net.IP type, the netip.Addr type takes less + memory, is immutable, and is comparable so it supports == + and can be used as a map key. +

+

+ In addition to Addr, the package defines + AddrPort, representing + an IP and port, and + Prefix, representing + a network CIDR prefix. +

+

+ The net package now has methods to send and receive UDP packets + using netip.Addr values instead of the relatively heavy + *net.UDPAddr values. +

+ +

TODO

+

TODO: complete this section

@@ -139,6 +197,26 @@ Do not send CLs removing the interior tags from such phrases. TODO: complete this section

+
bufio
+
+

+ TODO: https://golang.org/cl/345569: add Writer.AvailableBuffer +

+ +

+ TODO: https://golang.org/cl/345570: make Reader.Reset and Writer.Reset work on the zero value +

+
+
+ +
crypto/tls
+
+

+ TODO: https://golang.org/cl/325250: add Conn.NetConn method +

+
+
+
debug/buildinfo

@@ -165,6 +243,14 @@ Do not send CLs removing the interior tags from such phrases.

+
net
+
+

+ TODO: https://golang.org/cl/340261: deprecate (net.Error).Temporary +

+
+
+
net/http

@@ -174,12 +260,24 @@ Do not send CLs removing the interior tags from such phrases. will now be correctly used, if specified, for making HTTP requests when running on WebAssembly targets.

+ +

+ TODO: https://golang.org/cl/338590: add Cookie.Valid method +

+
os/user
+
+

+ TODO: https://golang.org/cl/330753: implement go native GroupIds +

+
+
+
reflect
-

+

The new Value.SetIterKey and Value.SetIterValue @@ -187,8 +285,7 @@ Do not send CLs removing the interior tags from such phrases. Value.Set(iter.Key()) and Value.Set(iter.Value()) but do fewer allocations.

-
-
+

The new Value.UnsafePointer @@ -197,9 +294,69 @@ Do not send CLs removing the interior tags from such phrases. and Value.Pointer to eliminate the need to perform uintptr to unsafe.Pointer conversions at the callsite (as unsafe.Pointer rules require).

+ +

+ TODO: https://golang.org/cl/321889: allocate hiter as part of MapIter +

+ +

+ TODO: https://golang.org/cl/321891: add MapIter.Reset +

+ +

+ TODO: https://golang.org/cl/345486: optimize for maps with string keys +

+ +

+ TODO: https://golang.org/cl/352131: add Value.{CanInt, CanUint, CanFloat, CanComplex} +

+ +

+ TODO: https://golang.org/cl/357962: add FieldByIndexErr +

+
regexp
+
+

+ TODO: https://golang.org/cl/354569: document and implement that invalid UTF-8 bytes are the same as U+FFFD +

+
+
+ +
strconv
+
+

+ TODO: https://golang.org/cl/343877: reject surrogate halves in Unquote +

+
+
+ +
strings
+
+

+ TODO: https://golang.org/cl/345849: add Clone function +

+
+
+ +
strings,bytes
+
+

+ TODO: https://golang.org/cl/332771: avoid allocations in Trim/TrimLeft/TrimRight +

+
+
+ +
sync
+
+

+ TODO: https://golang.org/cl/319769: add Mutex.TryLock, RWMutex.TryLock, RWMutex.TryRLock +

+
+
+
syscall

@@ -214,5 +371,45 @@ Do not send CLs removing the interior tags from such phrases. Syscall18 are deprecated in favor of SyscallN.

+ +

+ TODO: https://golang.org/cl/355570: add support for SysProcAttr.Pdeathsig on FreeBSD +

+ +
syscall/js
+
+

+ TODO: https://golang.org/cl/356430: remove Wrapper interface +

+
+
+ +
testing
+
+

+ TODO: https://golang.org/cl/343883: increase alternation precedence +

+ +

+ TODO: https://golang.org/cl/356669: skip extra -count iterations if there are no tests +

+
+
+ +
text/template
+
+

+ TODO: https://golang.org/cl/321490: implement short-circuit and, or +

+
+
+ +
unicode/utf8
+
+

+ TODO: https://golang.org/cl/345571: add AppendRune +

+
+
diff --git a/misc/cgo/testcarchive/carchive_test.go b/misc/cgo/testcarchive/carchive_test.go index 55be3c5f70..a2b43bb72d 100644 --- a/misc/cgo/testcarchive/carchive_test.go +++ b/misc/cgo/testcarchive/carchive_test.go @@ -931,3 +931,55 @@ func TestManyCalls(t *testing.T) { t.Error(err) } } + +// Issue 49288. +func TestPreemption(t *testing.T) { + if runtime.Compiler == "gccgo" { + t.Skip("skipping asynchronous preemption test with gccgo") + } + + t.Parallel() + + if !testWork { + defer func() { + os.Remove("testp8" + exeSuffix) + os.Remove("libgo8.a") + os.Remove("libgo8.h") + }() + } + + cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo8.a", "./libgo8") + if out, err := cmd.CombinedOutput(); err != nil { + t.Logf("%s", out) + t.Fatal(err) + } + checkLineComments(t, "libgo8.h") + + ccArgs := append(cc, "-o", "testp8"+exeSuffix, "main8.c", "libgo8.a") + if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil { + t.Logf("%s", out) + t.Fatal(err) + } + + argv := cmdToRun("./testp8") + cmd = exec.Command(argv[0], argv[1:]...) + var sb strings.Builder + cmd.Stdout = &sb + cmd.Stderr = &sb + if err := cmd.Start(); err != nil { + t.Fatal(err) + } + + timer := time.AfterFunc(time.Minute, + func() { + t.Error("test program timed out") + cmd.Process.Kill() + }, + ) + defer timer.Stop() + + if err := cmd.Wait(); err != nil { + t.Log(sb.String()) + t.Error(err) + } +} diff --git a/misc/cgo/testcarchive/testdata/libgo8/a.go b/misc/cgo/testcarchive/testdata/libgo8/a.go new file mode 100644 index 0000000000..718418ecb8 --- /dev/null +++ b/misc/cgo/testcarchive/testdata/libgo8/a.go @@ -0,0 +1,36 @@ +// Copyright 2021 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 "C" + +import ( + "os" + "runtime" + "sync/atomic" +) + +var started int32 + +// Start a goroutine that loops forever. +func init() { + runtime.GOMAXPROCS(1) + go func() { + for { + atomic.StoreInt32(&started, 1) + } + }() +} + +//export GoFunction8 +func GoFunction8() { + for atomic.LoadInt32(&started) == 0 { + runtime.Gosched() + } + os.Exit(0) +} + +func main() { +} diff --git a/misc/cgo/testcarchive/testdata/main8.c b/misc/cgo/testcarchive/testdata/main8.c new file mode 100644 index 0000000000..95fb7a349e --- /dev/null +++ b/misc/cgo/testcarchive/testdata/main8.c @@ -0,0 +1,16 @@ +// Copyright 2021 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. + +// Test preemption. + +#include + +#include "libgo8.h" + +int main() { + GoFunction8(); + + // That should have exited the program. + abort(); +} diff --git a/misc/cgo/testcshared/testdata/libgo2/dup2.go b/misc/cgo/testcshared/testdata/libgo2/dup2.go index d18f0b130d..d343aa54d9 100644 --- a/misc/cgo/testcshared/testdata/libgo2/dup2.go +++ b/misc/cgo/testcshared/testdata/libgo2/dup2.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 darwin dragonfly freebsd linux,!arm64 netbsd openbsd +// +build darwin dragonfly freebsd linux,!arm64,!riscv64 netbsd openbsd package main diff --git a/misc/cgo/testcshared/testdata/libgo2/dup3.go b/misc/cgo/testcshared/testdata/libgo2/dup3.go index c9c65a6e3c..459f0dc196 100644 --- a/misc/cgo/testcshared/testdata/libgo2/dup3.go +++ b/misc/cgo/testcshared/testdata/libgo2/dup3.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,arm64 +// +build linux,arm64 linux,riscv64 package main diff --git a/misc/cgo/testsanitizers/asan_test.go b/misc/cgo/testsanitizers/asan_test.go new file mode 100644 index 0000000000..dbcce2fe28 --- /dev/null +++ b/misc/cgo/testsanitizers/asan_test.go @@ -0,0 +1,66 @@ +// Copyright 2021 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 sanitizers_test + +import ( + "strings" + "testing" +) + +func TestASAN(t *testing.T) { + goos, err := goEnv("GOOS") + if err != nil { + t.Fatal(err) + } + goarch, err := goEnv("GOARCH") + if err != nil { + t.Fatal(err) + } + // The asan tests require support for the -asan option. + if !aSanSupported(goos, goarch) { + t.Skipf("skipping on %s/%s; -asan option is not supported.", goos, goarch) + } + + t.Parallel() + requireOvercommit(t) + config := configure("address") + config.skipIfCSanitizerBroken(t) + + mustRun(t, config.goCmd("build", "std")) + + cases := []struct { + src string + memoryAccessError string + }{ + {src: "asan1_fail.go", memoryAccessError: "heap-use-after-free"}, + {src: "asan2_fail.go", memoryAccessError: "heap-buffer-overflow"}, + {src: "asan3_fail.go", memoryAccessError: "use-after-poison"}, + {src: "asan4_fail.go", memoryAccessError: "use-after-poison"}, + {src: "asan_useAfterReturn.go"}, + } + for _, tc := range cases { + tc := tc + name := strings.TrimSuffix(tc.src, ".go") + t.Run(name, func(t *testing.T) { + t.Parallel() + + dir := newTempDir(t) + defer dir.RemoveAll(t) + + outPath := dir.Join(name) + mustRun(t, config.goCmd("build", "-o", outPath, srcPath(tc.src))) + + cmd := hangProneCmd(outPath) + if tc.memoryAccessError != "" { + out, err := cmd.CombinedOutput() + if err != nil && strings.Contains(string(out), tc.memoryAccessError) { + return + } + t.Fatalf("%#q exited without expected memory access error\n%s; got failure\n%s", strings.Join(cmd.Args, " "), tc.memoryAccessError, out) + } + mustRun(t, cmd) + }) + } +} diff --git a/misc/cgo/testsanitizers/cc_test.go b/misc/cgo/testsanitizers/cc_test.go index 7af30ab557..b776afa3e6 100644 --- a/misc/cgo/testsanitizers/cc_test.go +++ b/misc/cgo/testsanitizers/cc_test.go @@ -267,6 +267,9 @@ func configure(sanitizer string) *config { c.ldFlags = append(c.ldFlags, "-fPIC", "-static-libtsan") } + case "address": + c.goFlags = append(c.goFlags, "-asan") + default: panic(fmt.Sprintf("unrecognized sanitizer: %q", sanitizer)) } @@ -450,3 +453,14 @@ func mSanSupported(goos, goarch string) bool { return false } } + +// aSanSupported is a copy of the function cmd/internal/sys.ASanSupported, +// because the internal pacakage can't be used here. +func aSanSupported(goos, goarch string) bool { + switch goos { + case "linux": + return goarch == "amd64" || goarch == "arm64" + default: + return false + } +} diff --git a/misc/cgo/testsanitizers/testdata/asan1_fail.go b/misc/cgo/testsanitizers/testdata/asan1_fail.go new file mode 100644 index 0000000000..e60db76981 --- /dev/null +++ b/misc/cgo/testsanitizers/testdata/asan1_fail.go @@ -0,0 +1,28 @@ +// Copyright 2021 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 + +/* +#include +#include + +int *p; +int* test() { + p = (int *)malloc(2 * sizeof(int)); + free(p); + return p; +} +*/ +import "C" +import "fmt" + +func main() { + // C passes Go an invalid pointer. + a := C.test() + // Use after free + *a = 2 + // We shouldn't get here; asan should stop us first. + fmt.Println(*a) +} diff --git a/misc/cgo/testsanitizers/testdata/asan2_fail.go b/misc/cgo/testsanitizers/testdata/asan2_fail.go new file mode 100644 index 0000000000..e35670c440 --- /dev/null +++ b/misc/cgo/testsanitizers/testdata/asan2_fail.go @@ -0,0 +1,34 @@ +// Copyright 2021 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 + +/* +#include +#include + +int *p; +int* f() { + int i; + p = (int *)malloc(5*sizeof(int)); + for (i = 0; i < 5; i++) { + p[i] = i+10; + } + return p; +} +*/ +import "C" +import ( + "fmt" + "unsafe" +) + +func main() { + a := C.f() + q5 := (*C.int)(unsafe.Add(unsafe.Pointer(a), 4*5)) + // Access to C pointer out of bounds. + *q5 = 100 + // We shouldn't get here; asan should stop us first. + fmt.Printf("q5: %d, %x\n", *q5, q5) +} diff --git a/misc/cgo/testsanitizers/testdata/asan3_fail.go b/misc/cgo/testsanitizers/testdata/asan3_fail.go new file mode 100644 index 0000000000..9f6d26dd89 --- /dev/null +++ b/misc/cgo/testsanitizers/testdata/asan3_fail.go @@ -0,0 +1,23 @@ +// Copyright 2021 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 + +/* +#include +#include + +void test(int *a) { + // Access Go pointer out of bounds. + int c = a[5]; // BOOM + // We shouldn't get here; asan should stop us first. + printf("a[5]=%d\n", c); +} +*/ +import "C" + +func main() { + cIntSlice := []C.int{200, 201, 203, 203, 204} + C.test(&cIntSlice[0]) +} diff --git a/misc/cgo/testsanitizers/testdata/asan4_fail.go b/misc/cgo/testsanitizers/testdata/asan4_fail.go new file mode 100644 index 0000000000..12098458ae --- /dev/null +++ b/misc/cgo/testsanitizers/testdata/asan4_fail.go @@ -0,0 +1,22 @@ +// Copyright 2021 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 + +/* +#include +#include + +void test(int* a) { + // Access Go pointer out of bounds. + a[3] = 300; // BOOM + // We shouldn't get here; asan should stop us first. + printf("a[3]=%d\n", a[3]); +}*/ +import "C" + +func main() { + var cIntArray [2]C.int + C.test(&cIntArray[0]) // cIntArray is moved to heap. +} diff --git a/misc/cgo/testsanitizers/testdata/asan_useAfterReturn.go b/misc/cgo/testsanitizers/testdata/asan_useAfterReturn.go new file mode 100644 index 0000000000..3d3d5a6ab1 --- /dev/null +++ b/misc/cgo/testsanitizers/testdata/asan_useAfterReturn.go @@ -0,0 +1,26 @@ +// Copyright 2021 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 + +// The -fsanitize=address option of C compier can detect stack-use-after-return bugs. +// In the following program, the local variable 'local' was moved to heap by the Go +// compiler because foo() is returning the reference to 'local', and return stack of +// foo() will be invalid. Thus for main() to use the reference to 'local', the 'local' +// must be available even after foo() has finished. Therefore, Go has no such issue. + +import "fmt" + +var ptr *int + +func main() { + foo() + fmt.Printf("ptr=%x, %v", *ptr, ptr) +} + +func foo() { + var local int + local = 1 + ptr = &local // local is moved to heap. +} diff --git a/src/archive/zip/reader.go b/src/archive/zip/reader.go index c91a8d00e6..e40a2c656b 100644 --- a/src/archive/zip/reader.go +++ b/src/archive/zip/reader.go @@ -741,6 +741,9 @@ func (r *Reader) initFileList() { for _, file := range r.File { isDir := len(file.Name) > 0 && file.Name[len(file.Name)-1] == '/' name := toValidName(file.Name) + if name == "" { + continue + } for dir := path.Dir(name); dir != "."; dir = path.Dir(dir) { dirs[dir] = true } @@ -782,8 +785,11 @@ func fileEntryLess(x, y string) bool { func (r *Reader) Open(name string) (fs.File, error) { r.initFileList() + if !fs.ValidPath(name) { + return nil, &fs.PathError{Op: "open", Path: name, Err: fs.ErrInvalid} + } e := r.openLookup(name) - if e == nil || !fs.ValidPath(name) { + if e == nil { return nil, &fs.PathError{Op: "open", Path: name, Err: fs.ErrNotExist} } if e.isDir { @@ -797,7 +803,7 @@ func (r *Reader) Open(name string) (fs.File, error) { } func split(name string) (dir, elem string, isDir bool) { - if name[len(name)-1] == '/' { + if len(name) > 0 && name[len(name)-1] == '/' { isDir = true name = name[:len(name)-1] } diff --git a/src/archive/zip/reader_test.go b/src/archive/zip/reader_test.go index afb03ace24..a54915316c 100644 --- a/src/archive/zip/reader_test.go +++ b/src/archive/zip/reader_test.go @@ -13,6 +13,7 @@ import ( "io/fs" "os" "path/filepath" + "reflect" "regexp" "strings" "testing" @@ -1202,6 +1203,15 @@ func TestCVE202127919(t *testing.T) { if err != nil { t.Errorf("Error reading file: %v", err) } + if len(r.File) != 1 { + t.Fatalf("No entries in the file list") + } + if r.File[0].Name != "../test.txt" { + t.Errorf("Unexpected entry name: %s", r.File[0].Name) + } + if _, err := r.File[0].Open(); err != nil { + t.Errorf("Error opening file: %v", err) + } } func TestReadDataDescriptor(t *testing.T) { @@ -1402,3 +1412,121 @@ func TestCVE202139293(t *testing.T) { t.Fatalf("unexpected error, got: %v, want: %v", err, ErrFormat) } } + +func TestCVE202141772(t *testing.T) { + // Archive contains a file whose name is exclusively made up of '/', '\' + // characters, or "../", "..\" paths, which would previously cause a panic. + // + // Length Method Size Cmpr Date Time CRC-32 Name + // -------- ------ ------- ---- ---------- ----- -------- ---- + // 0 Stored 0 0% 08-05-2021 18:32 00000000 / + // 0 Stored 0 0% 09-14-2021 12:59 00000000 // + // 0 Stored 0 0% 09-14-2021 12:59 00000000 \ + // 11 Stored 11 0% 09-14-2021 13:04 0d4a1185 /test.txt + // -------- ------- --- ------- + // 11 11 0% 4 files + data := []byte{ + 0x50, 0x4b, 0x03, 0x04, 0x0a, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x06, 0x94, 0x05, 0x53, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2f, 0x50, + 0x4b, 0x03, 0x04, 0x0a, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x78, 0x67, 0x2e, 0x53, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x2f, 0x2f, 0x50, + 0x4b, 0x03, 0x04, 0x0a, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x78, 0x67, 0x2e, 0x53, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x5c, 0x50, 0x4b, + 0x03, 0x04, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x91, 0x68, 0x2e, 0x53, 0x85, 0x11, 0x4a, 0x0d, + 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x2f, 0x74, 0x65, 0x73, + 0x74, 0x2e, 0x74, 0x78, 0x74, 0x68, 0x65, 0x6c, + 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, + 0x50, 0x4b, 0x01, 0x02, 0x14, 0x03, 0x0a, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x06, 0x94, 0x05, 0x53, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, + 0xed, 0x41, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x50, + 0x4b, 0x01, 0x02, 0x3f, 0x00, 0x0a, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x78, 0x67, 0x2e, 0x53, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x24, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x1f, 0x00, 0x00, 0x00, 0x2f, 0x2f, 0x0a, + 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x18, 0x00, 0x93, 0x98, 0x25, 0x57, 0x25, + 0xa9, 0xd7, 0x01, 0x93, 0x98, 0x25, 0x57, 0x25, + 0xa9, 0xd7, 0x01, 0x93, 0x98, 0x25, 0x57, 0x25, + 0xa9, 0xd7, 0x01, 0x50, 0x4b, 0x01, 0x02, 0x3f, + 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, + 0x67, 0x2e, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, + 0x00, 0x5c, 0x0a, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x93, 0x98, + 0x25, 0x57, 0x25, 0xa9, 0xd7, 0x01, 0x93, 0x98, + 0x25, 0x57, 0x25, 0xa9, 0xd7, 0x01, 0x93, 0x98, + 0x25, 0x57, 0x25, 0xa9, 0xd7, 0x01, 0x50, 0x4b, + 0x01, 0x02, 0x3f, 0x00, 0x0a, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x91, 0x68, 0x2e, 0x53, 0x85, 0x11, + 0x4a, 0x0d, 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, + 0x00, 0x00, 0x09, 0x00, 0x24, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x5e, 0x00, 0x00, 0x00, 0x2f, 0x74, 0x65, 0x73, + 0x74, 0x2e, 0x74, 0x78, 0x74, 0x0a, 0x00, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, + 0x00, 0xa9, 0x80, 0x51, 0x01, 0x26, 0xa9, 0xd7, + 0x01, 0x31, 0xd1, 0x57, 0x01, 0x26, 0xa9, 0xd7, + 0x01, 0xdf, 0x48, 0x85, 0xf9, 0x25, 0xa9, 0xd7, + 0x01, 0x50, 0x4b, 0x05, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x00, 0x04, 0x00, 0x31, 0x01, 0x00, + 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, + } + r, err := NewReader(bytes.NewReader([]byte(data)), int64(len(data))) + if err != nil { + t.Fatalf("Error reading the archive: %v", err) + } + entryNames := []string{`/`, `//`, `\`, `/test.txt`} + var names []string + for _, f := range r.File { + names = append(names, f.Name) + if _, err := f.Open(); err != nil { + t.Errorf("Error opening %q: %v", f.Name, err) + } + if _, err := r.Open(f.Name); err == nil { + t.Errorf("Opening %q with fs.FS API succeeded", f.Name) + } + } + if !reflect.DeepEqual(names, entryNames) { + t.Errorf("Unexpected file entries: %q", names) + } + if _, err := r.Open(""); err == nil { + t.Errorf("Opening %q with fs.FS API succeeded", "") + } + if _, err := r.Open("test.txt"); err != nil { + t.Errorf("Error opening %q with fs.FS API: %v", "test.txt", err) + } + dirEntries, err := fs.ReadDir(r, ".") + if err != nil { + t.Fatalf("Error reading the root directory: %v", err) + } + if len(dirEntries) != 1 || dirEntries[0].Name() != "test.txt" { + t.Errorf("Unexpected directory entries") + for _, dirEntry := range dirEntries { + _, err := r.Open(dirEntry.Name()) + t.Logf("%q (Open error: %v)", dirEntry.Name(), err) + } + t.FailNow() + } + info, err := dirEntries[0].Info() + if err != nil { + t.Fatalf("Error reading info entry: %v", err) + } + if name := info.Name(); name != "test.txt" { + t.Errorf("Inconsistent name in info entry: %v", name) + } +} diff --git a/src/bufio/bufio_test.go b/src/bufio/bufio_test.go index 66b3e70053..4dddfa9085 100644 --- a/src/bufio/bufio_test.go +++ b/src/bufio/bufio_test.go @@ -1520,7 +1520,7 @@ func TestReaderDiscard(t *testing.T) { wantBuffered: 0, }, // Any error from filling shouldn't show up until we - // get past the valid bytes. Here we return we return 5 valid bytes at the same time + // get past the valid bytes. Here we return 5 valid bytes at the same time // as an error, but test that we don't see the error from Discard. { name: "fill error, discard less", diff --git a/src/bytes/boundary_test.go b/src/bytes/boundary_test.go index 8dac751866..f9855fcb05 100644 --- a/src/bytes/boundary_test.go +++ b/src/bytes/boundary_test.go @@ -65,7 +65,11 @@ func TestIndexByteNearPageBoundary(t *testing.T) { func TestIndexNearPageBoundary(t *testing.T) { t.Parallel() - var q [64]byte + q := dangerousSlice(t) + if len(q) > 64 { + // Only worry about when we're near the end of a page. + q = q[len(q)-64:] + } b := dangerousSlice(t) if len(b) > 256 { // Only worry about when we're near the end of a page. @@ -81,4 +85,16 @@ func TestIndexNearPageBoundary(t *testing.T) { } q[j-1] = 0 } + + // Test differing alignments and sizes of q which always end on a page boundary. + q[len(q)-1] = 1 // difference is only found on the last byte + for j := 0; j < len(q); j++ { + for i := range b { + idx := Index(b[i:], q[j:]) + if idx != -1 { + t.Fatalf("Index(b[%d:], q[%d:])=%d, want -1\n", i, j, idx) + } + } + } + q[len(q)-1] = 0 } diff --git a/src/bytes/bytes.go b/src/bytes/bytes.go index 529d95a888..6fdaa49c73 100644 --- a/src/bytes/bytes.go +++ b/src/bytes/bytes.go @@ -21,7 +21,7 @@ func Equal(a, b []byte) bool { } // Compare returns an integer comparing two byte slices lexicographically. -// The result will be 0 if a==b, -1 if a < b, and +1 if a > b. +// The result will be 0 if a == b, -1 if a < b, and +1 if a > b. // A nil argument is equivalent to an empty slice. func Compare(a, b []byte) int { return bytealg.Compare(a, b) @@ -746,7 +746,8 @@ func isSeparator(r rune) bool { // Title treats s as UTF-8-encoded bytes and returns a copy with all Unicode letters that begin // words mapped to their title case. // -// BUG(rsc): The rule Title uses for word boundaries does not handle Unicode punctuation properly. +// Deprecated: The rule Title uses for word boundaries does not handle Unicode +// punctuation properly. Use golang.org/x/text/cases instead. func Title(s []byte) []byte { // Use a closure here to remember state. // Hackish but effective. Depends on Map scanning in order and calling diff --git a/src/bytes/example_test.go b/src/bytes/example_test.go index d04b088fab..54a7aa6ae6 100644 --- a/src/bytes/example_test.go +++ b/src/bytes/example_test.go @@ -37,6 +37,16 @@ func ExampleBuffer_Bytes() { // Output: hello world } +func ExampleBuffer_Cap() { + buf1 := bytes.NewBuffer(make([]byte, 10)) + buf2 := bytes.NewBuffer(make([]byte, 0, 10)) + fmt.Println(buf1.Cap()) + fmt.Println(buf2.Cap()) + // Output: + // 10 + // 10 +} + func ExampleBuffer_Grow() { var b bytes.Buffer b.Grow(64) @@ -67,6 +77,39 @@ func ExampleBuffer_Next() { // e } +func ExampleBuffer_Read() { + var b bytes.Buffer + b.Grow(64) + b.Write([]byte("abcde")) + rdbuf := make([]byte, 1) + n, err := b.Read(rdbuf) + if err != nil { + panic(err) + } + fmt.Println(n) + fmt.Println(b.String()) + fmt.Println(string(rdbuf)) + // Output + // 1 + // bcde + // a +} + +func ExampleBuffer_ReadByte() { + var b bytes.Buffer + b.Grow(64) + b.Write([]byte("abcde")) + c, err := b.ReadByte() + if err != nil { + panic(err) + } + fmt.Println(c) + fmt.Println(b.String()) + // Output + // 97 + // bcde +} + func ExampleCompare() { // Interpret Compare's result by comparing it to zero. var a, b []byte diff --git a/src/cmd/asm/internal/arch/arch.go b/src/cmd/asm/internal/arch/arch.go index 8c71b79965..4d374cb828 100644 --- a/src/cmd/asm/internal/arch/arch.go +++ b/src/cmd/asm/internal/arch/arch.go @@ -50,7 +50,7 @@ func nilRegisterNumber(name string, n int16) (int16, bool) { // Set configures the architecture specified by GOARCH and returns its representation. // It returns nil if GOARCH is not recognized. -func Set(GOARCH string) *Arch { +func Set(GOARCH string, shared bool) *Arch { switch GOARCH { case "386": return archX86(&x86.Link386) @@ -73,7 +73,7 @@ func Set(GOARCH string) *Arch { case "ppc64le": return archPPC64(&ppc64.Linkppc64le) case "riscv64": - return archRISCV64() + return archRISCV64(shared) case "s390x": return archS390x() case "wasm": @@ -541,12 +541,18 @@ func archMips64(linkArch *obj.LinkArch) *Arch { } } -func archRISCV64() *Arch { +func archRISCV64(shared bool) *Arch { register := make(map[string]int16) // Standard register names. for i := riscv.REG_X0; i <= riscv.REG_X31; i++ { - if i == riscv.REG_G { + // Disallow X3 in shared mode, as this will likely be used as the + // GP register, which could result in problems in non-Go code, + // including signal handlers. + if shared && i == riscv.REG_GP { + continue + } + if i == riscv.REG_TP || i == riscv.REG_G { continue } name := fmt.Sprintf("X%d", i-riscv.REG_X0) diff --git a/src/cmd/asm/internal/asm/operand_test.go b/src/cmd/asm/internal/asm/operand_test.go index 8ef02b1a0e..c1295a0c42 100644 --- a/src/cmd/asm/internal/asm/operand_test.go +++ b/src/cmd/asm/internal/asm/operand_test.go @@ -19,7 +19,7 @@ import ( func setArch(goarch string) (*arch.Arch, *obj.Link) { buildcfg.GOOS = "linux" // obj can handle this OS for all architectures. buildcfg.GOARCH = goarch - architecture := arch.Set(goarch) + architecture := arch.Set(goarch, false) if architecture == nil { panic("asm: unrecognized architecture " + goarch) } diff --git a/src/cmd/asm/internal/flags/flags.go b/src/cmd/asm/internal/flags/flags.go index dd947c7b5b..607166e664 100644 --- a/src/cmd/asm/internal/flags/flags.go +++ b/src/cmd/asm/internal/flags/flags.go @@ -28,6 +28,10 @@ var ( CompilingRuntime = flag.Bool("compiling-runtime", false, "source to be compiled is part of the Go runtime") ) +var DebugFlags struct { + MayMoreStack string `help:"call named function before all stack growth checks"` +} + var ( D MultiFlag I MultiFlag @@ -39,6 +43,7 @@ func init() { flag.Var(&D, "D", "predefined symbol with optional simple value -D=identifier=value; can be set multiple times") flag.Var(&I, "I", "include directory; can be set multiple times") flag.BoolVar(&DebugV, "v", false, "print debug output") + flag.Var(objabi.NewDebugFlag(&DebugFlags, nil), "d", "enable debugging settings; try -d help") objabi.AddVersionFlag() // -V objabi.Flagcount("S", "print assembly and machine code", &PrintOut) } diff --git a/src/cmd/asm/main.go b/src/cmd/asm/main.go index 043bc696e5..3683527f5b 100644 --- a/src/cmd/asm/main.go +++ b/src/cmd/asm/main.go @@ -29,19 +29,20 @@ func main() { buildcfg.Check() GOARCH := buildcfg.GOARCH - architecture := arch.Set(GOARCH) + flags.Parse() + + architecture := arch.Set(GOARCH, *flags.Shared || *flags.Dynlink) if architecture == nil { log.Fatalf("unrecognized architecture %s", GOARCH) } - flags.Parse() - ctxt := obj.Linknew(architecture.LinkArch) ctxt.Debugasm = flags.PrintOut ctxt.Debugvlog = flags.DebugV ctxt.Flag_dynlink = *flags.Dynlink ctxt.Flag_linkshared = *flags.Linkshared ctxt.Flag_shared = *flags.Shared || *flags.Dynlink + ctxt.Flag_maymorestack = flags.DebugFlags.MayMoreStack ctxt.IsAsm = true ctxt.Pkgpath = *flags.Importpath switch *flags.Spectre { diff --git a/src/cmd/compile/internal/abi/abiutils.go b/src/cmd/compile/internal/abi/abiutils.go index 4da4e9ca3a..74c8707b29 100644 --- a/src/cmd/compile/internal/abi/abiutils.go +++ b/src/cmd/compile/internal/abi/abiutils.go @@ -780,11 +780,11 @@ func (state *assignState) assignParamOrReturn(pt *types.Type, n types.Object, is } // ComputePadding returns a list of "post element" padding values in -// the case where we have a structure being passed in registers. Give -// a param assignment corresponding to a struct, it returns a list of -// contaning padding values for each field, e.g. the Kth element in +// the case where we have a structure being passed in registers. Given +// a param assignment corresponding to a struct, it returns a list +// containing padding values for each field, e.g. the Kth element in // the list is the amount of padding between field K and the following -// field. For things that are not struct (or structs without padding) +// field. For things that are not structs (or structs without padding) // it returns a list of zeros. Example: // // type small struct { @@ -796,8 +796,8 @@ func (state *assignState) assignParamOrReturn(pt *types.Type, n types.Object, is // // For this struct we would return a list [0, 1, 0, 0], meaning that // we have one byte of padding after the second field, and no bytes of -// padding after any of the other fields. Input parameter "storage" -// is with enough capacity to accommodate padding elements for +// padding after any of the other fields. Input parameter "storage" is +// a slice with enough capacity to accommodate padding elements for // the architected register set in question. func (pa *ABIParamAssignment) ComputePadding(storage []uint64) []uint64 { nr := len(pa.Registers) diff --git a/src/cmd/compile/internal/base/debug.go b/src/cmd/compile/internal/base/debug.go index e2245e1c26..b105e46e35 100644 --- a/src/cmd/compile/internal/base/debug.go +++ b/src/cmd/compile/internal/base/debug.go @@ -6,15 +6,6 @@ package base -import ( - "fmt" - "log" - "os" - "reflect" - "strconv" - "strings" -) - // Debug holds the parsed debugging configuration values. var Debug DebugFlags @@ -26,7 +17,7 @@ var Debug DebugFlags // Each setting is name=value; for ints, name is short for name=1. type DebugFlags struct { Append int `help:"print information about append compilation"` - Checkptr int `help:"instrument unsafe pointer conversions"` + Checkptr int `help:"instrument unsafe pointer conversions\n0: instrumentation disabled\n1: conversions involving unsafe.Pointer are instrumented\n2: conversions to unsafe.Pointer force heap allocation"` Closure int `help:"print information about closure compilation"` DclStack int `help:"run internal dclstack check"` Defer int `help:"print information about defer compilation"` @@ -40,7 +31,7 @@ type DebugFlags struct { LocationLists int `help:"print information about DWARF location list creation"` Nil int `help:"print information about nil checks"` NoOpenDefer int `help:"disable open-coded defers"` - PCTab string `help:"print named pc-value table"` + PCTab string `help:"print named pc-value table\nOne of: pctospadj, pctofile, pctoline, pctoinline, pctopcdata"` Panic int `help:"show all compiler panics"` Slice int `help:"print information about slice compilation"` SoftFloat int `help:"force compiler to emit soft-float code"` @@ -51,142 +42,12 @@ type DebugFlags struct { UnifiedQuirks int `help:"enable unified IR construction's quirks mode"` WB int `help:"print information about write barriers"` ABIWrap int `help:"print information about ABI wrapper generation"` + MayMoreStack string `help:"call named function before all stack growth checks"` - any bool // set when any of the values have been set -} - -// Any reports whether any of the debug flags have been set. -func (d *DebugFlags) Any() bool { return d.any } - -type debugField struct { - name string - help string - val interface{} // *int or *string -} - -var debugTab []debugField - -func init() { - v := reflect.ValueOf(&Debug).Elem() - t := v.Type() - for i := 0; i < t.NumField(); i++ { - f := t.Field(i) - if f.Name == "any" { - continue - } - name := strings.ToLower(f.Name) - help := f.Tag.Get("help") - if help == "" { - panic(fmt.Sprintf("base.Debug.%s is missing help text", f.Name)) - } - ptr := v.Field(i).Addr().Interface() - switch ptr.(type) { - default: - panic(fmt.Sprintf("base.Debug.%s has invalid type %v (must be int or string)", f.Name, f.Type)) - case *int, *string: - // ok - } - debugTab = append(debugTab, debugField{name, help, ptr}) - } + Any bool // set when any of the debug flags have been set } // DebugSSA is called to set a -d ssa/... option. // If nil, those options are reported as invalid options. // If DebugSSA returns a non-empty string, that text is reported as a compiler error. var DebugSSA func(phase, flag string, val int, valString string) string - -// parseDebug parses the -d debug string argument. -func parseDebug(debugstr string) { - // parse -d argument - if debugstr == "" { - return - } - Debug.any = true -Split: - for _, name := range strings.Split(debugstr, ",") { - if name == "" { - continue - } - // display help about the -d option itself and quit - if name == "help" { - fmt.Print(debugHelpHeader) - maxLen := len("ssa/help") - for _, t := range debugTab { - if len(t.name) > maxLen { - maxLen = len(t.name) - } - } - for _, t := range debugTab { - fmt.Printf("\t%-*s\t%s\n", maxLen, t.name, t.help) - } - // ssa options have their own help - fmt.Printf("\t%-*s\t%s\n", maxLen, "ssa/help", "print help about SSA debugging") - fmt.Print(debugHelpFooter) - os.Exit(0) - } - val, valstring, haveInt := 1, "", true - if i := strings.IndexAny(name, "=:"); i >= 0 { - var err error - name, valstring = name[:i], name[i+1:] - val, err = strconv.Atoi(valstring) - if err != nil { - val, haveInt = 1, false - } - } - for _, t := range debugTab { - if t.name != name { - continue - } - switch vp := t.val.(type) { - case nil: - // Ignore - case *string: - *vp = valstring - case *int: - if !haveInt { - log.Fatalf("invalid debug value %v", name) - } - *vp = val - default: - panic("bad debugtab type") - } - continue Split - } - // special case for ssa for now - if DebugSSA != nil && strings.HasPrefix(name, "ssa/") { - // expect form ssa/phase/flag - // e.g. -d=ssa/generic_cse/time - // _ in phase name also matches space - phase := name[4:] - flag := "debug" // default flag is debug - if i := strings.Index(phase, "/"); i >= 0 { - flag = phase[i+1:] - phase = phase[:i] - } - err := DebugSSA(phase, flag, val, valstring) - if err != "" { - log.Fatalf(err) - } - continue Split - } - log.Fatalf("unknown debug key -d %s\n", name) - } -} - -const debugHelpHeader = `usage: -d arg[,arg]* and arg is [=] - - is one of: - -` - -const debugHelpFooter = ` - is key-specific. - -Key "checkptr" supports values: - "0": instrumentation disabled - "1": conversions involving unsafe.Pointer are instrumented - "2": conversions to unsafe.Pointer force heap allocation - -Key "pctab" supports values: - "pctospadj", "pctofile", "pctoline", "pctoinline", "pctopcdata" -` diff --git a/src/cmd/compile/internal/base/flag.go b/src/cmd/compile/internal/base/flag.go index 9d630ce97a..d78f93b343 100644 --- a/src/cmd/compile/internal/base/flag.go +++ b/src/cmd/compile/internal/base/flag.go @@ -64,19 +64,19 @@ type CmdFlags struct { // V is added by objabi.AddVersionFlag W CountFlag "help:\"debug parse tree after type checking\"" - LowerC int "help:\"concurrency during compilation (1 means no concurrency)\"" - LowerD func(string) "help:\"enable debugging settings; try -d help\"" - LowerE CountFlag "help:\"no limit on number of errors reported\"" - LowerH CountFlag "help:\"halt on error\"" - LowerJ CountFlag "help:\"debug runtime-initialized variables\"" - LowerL CountFlag "help:\"disable inlining\"" - LowerM CountFlag "help:\"print optimization decisions\"" - LowerO string "help:\"write output to `file`\"" - LowerP *string "help:\"set expected package import `path`\"" // &Ctxt.Pkgpath, set below - LowerR CountFlag "help:\"debug generated wrappers\"" - LowerT bool "help:\"enable tracing for debugging the compiler\"" - LowerW CountFlag "help:\"debug type checking\"" - LowerV *bool "help:\"increase debug verbosity\"" + LowerC int "help:\"concurrency during compilation (1 means no concurrency)\"" + LowerD flag.Value "help:\"enable debugging settings; try -d help\"" + LowerE CountFlag "help:\"no limit on number of errors reported\"" + LowerH CountFlag "help:\"halt on error\"" + LowerJ CountFlag "help:\"debug runtime-initialized variables\"" + LowerL CountFlag "help:\"disable inlining\"" + LowerM CountFlag "help:\"print optimization decisions\"" + LowerO string "help:\"write output to `file`\"" + LowerP *string "help:\"set expected package import `path`\"" // &Ctxt.Pkgpath, set below + LowerR CountFlag "help:\"debug generated wrappers\"" + LowerT bool "help:\"enable tracing for debugging the compiler\"" + LowerW CountFlag "help:\"debug type checking\"" + LowerV *bool "help:\"increase debug verbosity\"" // Special characters Percent int "flag:\"%\" help:\"debug non-static initializers\"" @@ -145,7 +145,7 @@ func ParseFlags() { Flag.I = addImportDir Flag.LowerC = 1 - Flag.LowerD = parseDebug + Flag.LowerD = objabi.NewDebugFlag(&Debug, DebugSSA) Flag.LowerP = &Ctxt.Pkgpath Flag.LowerV = &Ctxt.Debugvlog @@ -192,6 +192,7 @@ func ParseFlags() { Ctxt.Flag_shared = Ctxt.Flag_dynlink || Ctxt.Flag_shared Ctxt.Flag_optimize = Flag.N == 0 Ctxt.Debugasm = int(Flag.S) + Ctxt.Flag_maymorestack = Debug.MayMoreStack if flag.NArg() < 1 { usage() @@ -331,7 +332,11 @@ func registerFlags() { f := v.Field(i).Interface().(func(string)) objabi.Flagfn1(name, help, f) default: - panic(fmt.Sprintf("base.Flag.%s has unexpected type %s", f.Name, f.Type)) + if val, ok := v.Field(i).Interface().(flag.Value); ok { + flag.Var(val, name, help) + } else { + panic(fmt.Sprintf("base.Flag.%s has unexpected type %s", f.Name, f.Type)) + } } } } @@ -359,7 +364,7 @@ func concurrentBackendAllowed() bool { // while writing the object file, and that is non-concurrent. // Adding Debug_vlog, however, causes Debug.S to also print // while flushing the plist, which happens concurrently. - if Ctxt.Debugvlog || Debug.Any() || Flag.Live > 0 { + if Ctxt.Debugvlog || Debug.Any || Flag.Live > 0 { return false } // TODO: Test and delete this condition. diff --git a/src/cmd/compile/internal/escape/call.go b/src/cmd/compile/internal/escape/call.go index 9e5abed591..d1215afca8 100644 --- a/src/cmd/compile/internal/escape/call.go +++ b/src/cmd/compile/internal/escape/call.go @@ -333,11 +333,32 @@ func (e *escape) rewriteArgument(argp *ir.Node, init *ir.Nodes, call ir.Node, fn } } - // Peel away any slice lits. + // Peel away any slice literals for better escape analyze + // them. For example: + // + // go F([]int{a, b}) + // + // If F doesn't escape its arguments, then the slice can + // be allocated on the new goroutine's stack. + // + // For variadic functions, the compiler has already rewritten: + // + // f(a, b, c) + // + // to: + // + // f([]T{a, b, c}...) + // + // So we need to look into slice elements to handle uintptr(ptr) + // arguments to syscall-like functions correctly. if arg := *argp; arg.Op() == ir.OSLICELIT { list := arg.(*ir.CompLitExpr).List for i := range list { - visit(arg.Pos(), &list[i]) + el := &list[i] + if list[i].Op() == ir.OKEY { + el = &list[i].(*ir.KeyExpr).Value + } + visit(arg.Pos(), el) } } else { visit(call.Pos(), argp) diff --git a/src/cmd/compile/internal/inline/inl.go b/src/cmd/compile/internal/inline/inl.go index da905bd627..47b895f7e3 100644 --- a/src/cmd/compile/internal/inline/inl.go +++ b/src/cmd/compile/internal/inline/inl.go @@ -309,7 +309,7 @@ func (v *hairyVisitor) doNode(n ir.Node) bool { break } - if fn := inlCallee(n.X); fn != nil && fn.Inl != nil { + if fn := inlCallee(n.X); fn != nil && typecheck.HaveInlineBody(fn) { v.budget -= fn.Inl.Cost break } @@ -585,7 +585,7 @@ func inlnode(n ir.Node, maxCost int32, inlMap map[*ir.Func]bool, edit func(ir.No if ir.IsIntrinsicCall(call) { break } - if fn := inlCallee(call.X); fn != nil && fn.Inl != nil { + if fn := inlCallee(call.X); fn != nil && typecheck.HaveInlineBody(fn) { n = mkinlcall(call, fn, maxCost, inlMap, edit) } } @@ -685,6 +685,27 @@ func mkinlcall(n *ir.CallExpr, fn *ir.Func, maxCost int32, inlMap map[*ir.Func]b return n } + // Don't inline a function fn that has no shape parameters, but is passed at + // least one shape arg. This means we must be inlining a non-generic function + // fn that was passed into a generic function, and can be called with a shape + // arg because it matches an appropriate type parameters. But fn may include + // an interface conversion (that may be applied to a shape arg) that was not + // apparent when we first created the instantiation of the generic function. + // We can't handle this if we actually do the inlining, since we want to know + // all interface conversions immediately after stenciling. So, we avoid + // inlining in this case. See #49309. + if !fn.Type().HasShape() { + for _, arg := range n.Args { + if arg.Type().HasShape() { + if logopt.Enabled() { + logopt.LogOpt(n.Pos(), "cannotInlineCall", "inline", ir.FuncName(ir.CurFunc), + fmt.Sprintf("inlining non-shape function %v with shape args", ir.FuncName(fn))) + } + return n + } + } + } + if base.Flag.Cfg.Instrumenting && types.IsRuntimePkg(fn.Sym().Pkg) { // Runtime package must not be instrumented. // Instrument skips runtime package. However, some runtime code can be diff --git a/src/cmd/compile/internal/ir/name.go b/src/cmd/compile/internal/ir/name.go index dcfff7deba..1d4110c73c 100644 --- a/src/cmd/compile/internal/ir/name.go +++ b/src/cmd/compile/internal/ir/name.go @@ -146,7 +146,10 @@ func (n *Name) editChildren(edit func(Node) Node) {} // That is, given "type T Defn", it returns Defn. // It is used by package types. func (n *Name) TypeDefn() *types.Type { - return n.Ntype.Type() + if n.Ntype != nil { + return n.Ntype.Type() + } + return n.Type() } // RecordFrameOffset records the frame offset for the name. diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go index d19513a1ac..24e6dbefe7 100644 --- a/src/cmd/compile/internal/noder/expr.go +++ b/src/cmd/compile/internal/noder/expr.go @@ -235,12 +235,6 @@ func (g *irgen) selectorExpr(pos src.XPos, typ types2.Type, expr *syntax.Selecto return DotField(pos, x, last) } - // TODO(danscales,mdempsky): Interface method sets are not sorted the - // same between types and types2. In particular, using "last" here - // without conversion will likely fail if an interface contains - // unexported methods from two different packages (due to cross-package - // interface embedding). - var n ir.Node method2 := selinfo.Obj().(*types2.Func) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 56010a356e..74281bc479 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -624,7 +624,7 @@ func (g *genInst) getDictOrSubdict(declInfo *instInfo, n ir.Node, nameNode *ir.N // yet. If so, it imports the body. func checkFetchBody(nameNode *ir.Name) { if nameNode.Func.Body == nil && nameNode.Func.Inl != nil { - // If there is no body yet but Func.Inl exists, then we can can + // If there is no body yet but Func.Inl exists, then we can // import the whole generic body. assert(nameNode.Func.Inl.Cost == 1 && nameNode.Sym().Pkg != types.LocalPkg) typecheck.ImportBody(nameNode.Func) @@ -638,7 +638,18 @@ func checkFetchBody(nameNode *ir.Name) { // with the type arguments shapes. If the instantiated function is not already // cached, then it calls genericSubst to create the new instantiation. func (g *genInst) getInstantiation(nameNode *ir.Name, shapes []*types.Type, isMeth bool) *instInfo { - checkFetchBody(nameNode) + if nameNode.Func == nil { + // If nameNode.Func is nil, this must be a reference to a method of + // an imported instantiated type. We will have already called + // g.instantiateMethods() on the fully-instantiated type, so + // g.instInfoMap[sym] will be non-nil below. + rcvr := nameNode.Type().Recv() + if rcvr == nil || !deref(rcvr.Type).IsFullyInstantiated() { + base.FatalfAt(nameNode.Pos(), "Unexpected function instantiation %v with no body", nameNode) + } + } else { + checkFetchBody(nameNode) + } // Convert any non-shape type arguments to their shape, so we can reduce the // number of instantiations we have to generate. You can actually have a mix diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index ce41b8c934..d396c249e4 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -959,11 +959,6 @@ func writeType(t *types.Type) *obj.LSym { base.Fatalf("unresolved defined type: %v", tbase) } - dupok := 0 - if tbase.Sym() == nil || tbase.HasShape() { // TODO(mdempsky): Probably need DUPOK for instantiated types too. - dupok = obj.DUPOK - } - if !NeedEmit(tbase) { if i := typecheck.BaseTypeIndex(t); i >= 0 { lsym.Pkg = tbase.Sym().Pkg.Prefix @@ -1196,7 +1191,9 @@ func writeType(t *types.Type) *obj.LSym { } ot = dextratypeData(lsym, ot, t) - objw.Global(lsym, int32(ot), int16(dupok|obj.RODATA)) + objw.Global(lsym, int32(ot), int16(obj.DUPOK|obj.RODATA)) + // Note: DUPOK is required to ensure that we don't end up with more + // than one type descriptor for a given type. // The linker will leave a table of all the typelinks for // types in the binary, so the runtime can find them. diff --git a/src/cmd/compile/internal/ssa/expand_calls.go b/src/cmd/compile/internal/ssa/expand_calls.go index 18c9ab696d..a3cea855f2 100644 --- a/src/cmd/compile/internal/ssa/expand_calls.go +++ b/src/cmd/compile/internal/ssa/expand_calls.go @@ -958,6 +958,7 @@ func (x *expandState) storeArgOrLoad(pos src.XPos, b *Block, source, mem *Value, return x.storeArgOrLoad(pos, b, source, mem, t, storeOffset, loadRegOffset, storeRc) } eltRO := x.regWidth(elt) + source.Type = t for i := int64(0); i < t.NumElem(); i++ { sel := source.Block.NewValue1I(pos, OpArraySelect, elt, i, source) mem = x.storeArgOrLoad(pos, b, sel, mem, elt, storeOffset+i*elt.Size(), loadRegOffset, storeRc.at(t, 0)) @@ -991,6 +992,7 @@ func (x *expandState) storeArgOrLoad(pos src.XPos, b *Block, source, mem *Value, return x.storeArgOrLoad(pos, b, source, mem, t, storeOffset, loadRegOffset, storeRc) } + source.Type = t for i := 0; i < t.NumFields(); i++ { fld := t.Field(i) sel := source.Block.NewValue1I(pos, OpStructSelect, fld.Type, int64(i), source) diff --git a/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go b/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go index 880fad1c49..076919773b 100644 --- a/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go @@ -29,6 +29,7 @@ const ( riscv64REG_CTXT = 20 riscv64REG_LR = 1 riscv64REG_SP = 2 + riscv64REG_GP = 3 riscv64REG_TP = 4 riscv64REG_TMP = 31 riscv64REG_ZERO = 0 @@ -80,8 +81,8 @@ func init() { // Add general purpose registers to gpMask. switch r { - // ZERO, TP and TMP are not in any gp mask. - case riscv64REG_ZERO, riscv64REG_TP, riscv64REG_TMP: + // ZERO, GP, TP and TMP are not in any gp mask. + case riscv64REG_ZERO, riscv64REG_GP, riscv64REG_TP, riscv64REG_TMP: case riscv64REG_G: gpgMask |= mask gpspsbgMask |= mask diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index ed10f35fb9..2038575b0c 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -27949,11 +27949,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.AADD, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27964,10 +27964,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AADDI, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27978,10 +27978,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AADDIW, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27991,10 +27991,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.ANEG, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28004,10 +28004,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.ANEGW, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28017,11 +28017,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.ASUB, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28031,11 +28031,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.ASUBW, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28046,11 +28046,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMUL, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28061,11 +28061,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMULW, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28076,11 +28076,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMULH, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28091,11 +28091,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMULHU, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28105,12 +28105,12 @@ var opcodeTable = [...]opInfo{ resultNotInArgs: true, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28120,12 +28120,12 @@ var opcodeTable = [...]opInfo{ resultNotInArgs: true, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28135,11 +28135,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.ADIV, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28149,11 +28149,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.ADIVU, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28163,11 +28163,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.ADIVW, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28177,11 +28177,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.ADIVUW, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28191,11 +28191,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.AREM, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28205,11 +28205,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.AREMU, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28219,11 +28219,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.AREMW, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28233,11 +28233,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.AREMUW, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28250,10 +28250,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOV, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28265,7 +28265,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOV, reg: regInfo{ outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28278,10 +28278,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVB, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28294,10 +28294,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVH, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28310,10 +28310,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVW, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28326,10 +28326,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOV, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28342,10 +28342,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVBU, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28358,10 +28358,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVHU, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28374,10 +28374,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVWU, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28390,8 +28390,8 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVB, reg: regInfo{ inputs: []inputInfo{ - {1, 1006632950}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {1, 1006632946}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, }, }, @@ -28404,8 +28404,8 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVH, reg: regInfo{ inputs: []inputInfo{ - {1, 1006632950}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {1, 1006632946}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, }, }, @@ -28418,8 +28418,8 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVW, reg: regInfo{ inputs: []inputInfo{ - {1, 1006632950}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {1, 1006632946}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, }, }, @@ -28432,8 +28432,8 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOV, reg: regInfo{ inputs: []inputInfo{ - {1, 1006632950}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {1, 1006632946}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, }, }, @@ -28446,7 +28446,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVB, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, }, }, @@ -28459,7 +28459,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVH, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, }, }, @@ -28472,7 +28472,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVW, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, }, }, @@ -28485,7 +28485,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOV, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, }, }, @@ -28495,10 +28495,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVB, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28508,10 +28508,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVH, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28521,10 +28521,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVW, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28534,10 +28534,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOV, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28547,10 +28547,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVBU, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28560,10 +28560,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVHU, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28573,10 +28573,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVWU, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28586,10 +28586,10 @@ var opcodeTable = [...]opInfo{ resultInArg0: true, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28599,11 +28599,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.ASLL, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28613,11 +28613,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.ASRA, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28627,11 +28627,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.ASRL, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28642,10 +28642,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.ASLLI, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28656,10 +28656,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.ASRAI, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28670,10 +28670,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.ASRLI, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28684,11 +28684,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.AXOR, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28699,10 +28699,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AXORI, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28713,11 +28713,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.AOR, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28728,10 +28728,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AORI, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28742,11 +28742,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.AAND, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28757,10 +28757,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AANDI, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28770,10 +28770,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.ANOT, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28783,10 +28783,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.ASEQZ, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28796,10 +28796,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.ASNEZ, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28809,11 +28809,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.ASLT, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28824,10 +28824,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.ASLTI, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28837,11 +28837,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.ASLTU, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28852,10 +28852,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.ASLTIU, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28865,10 +28865,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOV, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28878,7 +28878,7 @@ var opcodeTable = [...]opInfo{ argLen: 1, call: true, reg: regInfo{ - clobbers: 9223372035781033972, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + clobbers: 9223372035781033968, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, }, { @@ -28888,7 +28888,7 @@ var opcodeTable = [...]opInfo{ call: true, tailCall: true, reg: regInfo{ - clobbers: 9223372035781033972, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + clobbers: 9223372035781033968, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, }, { @@ -28899,9 +28899,9 @@ var opcodeTable = [...]opInfo{ reg: regInfo{ inputs: []inputInfo{ {1, 524288}, // X20 - {0, 1006632950}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632946}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, - clobbers: 9223372035781033972, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + clobbers: 9223372035781033968, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, }, { @@ -28911,9 +28911,9 @@ var opcodeTable = [...]opInfo{ call: true, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, - clobbers: 9223372035781033972, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + clobbers: 9223372035781033968, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, }, { @@ -28950,7 +28950,7 @@ var opcodeTable = [...]opInfo{ reg: regInfo{ inputs: []inputInfo{ {0, 16}, // X5 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, clobbers: 16, // X5 }, @@ -28965,7 +28965,7 @@ var opcodeTable = [...]opInfo{ inputs: []inputInfo{ {0, 16}, // X5 {1, 32}, // X6 - {2, 1006632884}, // X3 X5 X6 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {2, 1006632880}, // X5 X6 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, clobbers: 112, // X5 X6 X7 }, @@ -28976,10 +28976,10 @@ var opcodeTable = [...]opInfo{ faultOnNilArg0: true, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28989,10 +28989,10 @@ var opcodeTable = [...]opInfo{ faultOnNilArg0: true, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -29002,10 +29002,10 @@ var opcodeTable = [...]opInfo{ faultOnNilArg0: true, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -29016,8 +29016,8 @@ var opcodeTable = [...]opInfo{ hasSideEffects: true, reg: regInfo{ inputs: []inputInfo{ - {1, 1006632950}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {1, 1006632946}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, }, }, @@ -29028,8 +29028,8 @@ var opcodeTable = [...]opInfo{ hasSideEffects: true, reg: regInfo{ inputs: []inputInfo{ - {1, 1006632950}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {1, 1006632946}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, }, }, @@ -29040,8 +29040,8 @@ var opcodeTable = [...]opInfo{ hasSideEffects: true, reg: regInfo{ inputs: []inputInfo{ - {1, 1006632950}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {1, 1006632946}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, }, }, @@ -29053,11 +29053,11 @@ var opcodeTable = [...]opInfo{ hasSideEffects: true, reg: regInfo{ inputs: []inputInfo{ - {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 - {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB + {1, 1073741808}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 + {0, 9223372037928517618}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -29069,11 +29069,11 @@ var opcodeTable = [...]opInfo{ hasSideEffects: true, reg: regInfo{ inputs: []inputInfo{ - {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 - {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB + {1, 1073741808}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 + {0, 9223372037928517618}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -29086,11 +29086,11 @@ var opcodeTable = [...]opInfo{ unsafePoint: true, reg: regInfo{ inputs: []inputInfo{ - {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 - {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB + {1, 1073741808}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 + {0, 9223372037928517618}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -29103,11 +29103,11 @@ var opcodeTable = [...]opInfo{ unsafePoint: true, reg: regInfo{ inputs: []inputInfo{ - {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 - {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB + {1, 1073741808}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 + {0, 9223372037928517618}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -29120,12 +29120,12 @@ var opcodeTable = [...]opInfo{ unsafePoint: true, reg: regInfo{ inputs: []inputInfo{ - {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 - {2, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 - {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB + {1, 1073741808}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 + {2, 1073741808}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 + {0, 9223372037928517618}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -29138,12 +29138,12 @@ var opcodeTable = [...]opInfo{ unsafePoint: true, reg: regInfo{ inputs: []inputInfo{ - {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 - {2, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 - {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB + {1, 1073741808}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 + {2, 1073741808}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 + {0, 9223372037928517618}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -29155,8 +29155,8 @@ var opcodeTable = [...]opInfo{ asm: riscv.AAMOANDW, reg: regInfo{ inputs: []inputInfo{ - {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 - {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB + {1, 1073741808}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 + {0, 9223372037928517618}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB }, }, }, @@ -29168,8 +29168,8 @@ var opcodeTable = [...]opInfo{ asm: riscv.AAMOORW, reg: regInfo{ inputs: []inputInfo{ - {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 - {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB + {1, 1073741808}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 + {0, 9223372037928517618}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB }, }, }, @@ -29180,7 +29180,7 @@ var opcodeTable = [...]opInfo{ faultOnNilArg0: true, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632950}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632946}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -29199,7 +29199,7 @@ var opcodeTable = [...]opInfo{ rematerializeable: true, reg: regInfo{ outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -29209,7 +29209,7 @@ var opcodeTable = [...]opInfo{ rematerializeable: true, reg: regInfo{ outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -29353,7 +29353,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AFMVSX, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 @@ -29366,7 +29366,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AFCVTSW, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 @@ -29379,7 +29379,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AFCVTSL, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 @@ -29395,7 +29395,7 @@ var opcodeTable = [...]opInfo{ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -29408,7 +29408,7 @@ var opcodeTable = [...]opInfo{ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -29421,7 +29421,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVF, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, outputs: []outputInfo{ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 @@ -29437,7 +29437,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVF, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, }, @@ -29453,7 +29453,7 @@ var opcodeTable = [...]opInfo{ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -29468,7 +29468,7 @@ var opcodeTable = [...]opInfo{ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -29482,7 +29482,7 @@ var opcodeTable = [...]opInfo{ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -29496,7 +29496,7 @@ var opcodeTable = [...]opInfo{ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -29681,7 +29681,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AFMVDX, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 @@ -29694,7 +29694,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AFCVTDW, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 @@ -29707,7 +29707,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AFCVTDL, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 @@ -29723,7 +29723,7 @@ var opcodeTable = [...]opInfo{ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -29736,7 +29736,7 @@ var opcodeTable = [...]opInfo{ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -29775,7 +29775,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVD, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, outputs: []outputInfo{ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 @@ -29791,7 +29791,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVD, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, }, @@ -29807,7 +29807,7 @@ var opcodeTable = [...]opInfo{ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -29822,7 +29822,7 @@ var opcodeTable = [...]opInfo{ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -29836,7 +29836,7 @@ var opcodeTable = [...]opInfo{ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -29850,7 +29850,7 @@ var opcodeTable = [...]opInfo{ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -37293,34 +37293,34 @@ var linkRegPPC64 = int8(-1) var registersRISCV64 = [...]Register{ {0, riscv.REG_X0, -1, "X0"}, {1, riscv.REGSP, -1, "SP"}, - {2, riscv.REG_X3, 0, "X3"}, + {2, riscv.REG_X3, -1, "X3"}, {3, riscv.REG_X4, -1, "X4"}, - {4, riscv.REG_X5, 1, "X5"}, - {5, riscv.REG_X6, 2, "X6"}, - {6, riscv.REG_X7, 3, "X7"}, - {7, riscv.REG_X8, 4, "X8"}, - {8, riscv.REG_X9, 5, "X9"}, - {9, riscv.REG_X10, 6, "X10"}, - {10, riscv.REG_X11, 7, "X11"}, - {11, riscv.REG_X12, 8, "X12"}, - {12, riscv.REG_X13, 9, "X13"}, - {13, riscv.REG_X14, 10, "X14"}, - {14, riscv.REG_X15, 11, "X15"}, - {15, riscv.REG_X16, 12, "X16"}, - {16, riscv.REG_X17, 13, "X17"}, - {17, riscv.REG_X18, 14, "X18"}, - {18, riscv.REG_X19, 15, "X19"}, - {19, riscv.REG_X20, 16, "X20"}, - {20, riscv.REG_X21, 17, "X21"}, - {21, riscv.REG_X22, 18, "X22"}, - {22, riscv.REG_X23, 19, "X23"}, - {23, riscv.REG_X24, 20, "X24"}, - {24, riscv.REG_X25, 21, "X25"}, - {25, riscv.REG_X26, 22, "X26"}, + {4, riscv.REG_X5, 0, "X5"}, + {5, riscv.REG_X6, 1, "X6"}, + {6, riscv.REG_X7, 2, "X7"}, + {7, riscv.REG_X8, 3, "X8"}, + {8, riscv.REG_X9, 4, "X9"}, + {9, riscv.REG_X10, 5, "X10"}, + {10, riscv.REG_X11, 6, "X11"}, + {11, riscv.REG_X12, 7, "X12"}, + {12, riscv.REG_X13, 8, "X13"}, + {13, riscv.REG_X14, 9, "X14"}, + {14, riscv.REG_X15, 10, "X15"}, + {15, riscv.REG_X16, 11, "X16"}, + {16, riscv.REG_X17, 12, "X17"}, + {17, riscv.REG_X18, 13, "X18"}, + {18, riscv.REG_X19, 14, "X19"}, + {19, riscv.REG_X20, 15, "X20"}, + {20, riscv.REG_X21, 16, "X21"}, + {21, riscv.REG_X22, 17, "X22"}, + {22, riscv.REG_X23, 18, "X23"}, + {23, riscv.REG_X24, 19, "X24"}, + {24, riscv.REG_X25, 20, "X25"}, + {25, riscv.REG_X26, 21, "X26"}, {26, riscv.REGG, -1, "g"}, - {27, riscv.REG_X28, 23, "X28"}, - {28, riscv.REG_X29, 24, "X29"}, - {29, riscv.REG_X30, 25, "X30"}, + {27, riscv.REG_X28, 22, "X28"}, + {28, riscv.REG_X29, 23, "X29"}, + {29, riscv.REG_X30, 24, "X30"}, {30, riscv.REG_X31, -1, "X31"}, {31, riscv.REG_F0, -1, "F0"}, {32, riscv.REG_F1, -1, "F1"}, @@ -37358,7 +37358,7 @@ var registersRISCV64 = [...]Register{ } var paramIntRegRISCV64 = []int8(nil) var paramFloatRegRISCV64 = []int8(nil) -var gpRegMaskRISCV64 = regMask(1006632948) +var gpRegMaskRISCV64 = regMask(1006632944) var fpRegMaskRISCV64 = regMask(9223372034707292160) var specialRegMaskRISCV64 = regMask(0) var framepointerRegRISCV64 = int8(-1) diff --git a/src/cmd/compile/internal/ssa/regalloc.go b/src/cmd/compile/internal/ssa/regalloc.go index 91b04e99f4..64792d0c80 100644 --- a/src/cmd/compile/internal/ssa/regalloc.go +++ b/src/cmd/compile/internal/ssa/regalloc.go @@ -635,6 +635,8 @@ func (s *regAllocState) init(f *Func) { // nothing to do case "ppc64le": // R2 already reserved. // nothing to do + case "riscv64": // X3 (aka GP) and X4 (aka TP) already reserved. + // nothing to do case "s390x": s.allocatable &^= 1 << 11 // R11 default: diff --git a/src/cmd/compile/internal/ssa/stmtlines_test.go b/src/cmd/compile/internal/ssa/stmtlines_test.go index 90dd261c55..088f9802e6 100644 --- a/src/cmd/compile/internal/ssa/stmtlines_test.go +++ b/src/cmd/compile/internal/ssa/stmtlines_test.go @@ -89,6 +89,9 @@ func TestStmtLines(t *testing.T) { if pkgname == "runtime" { continue } + if pkgname == "crypto/elliptic/internal/fiat" { + continue // golang.org/issue/49372 + } if e.Val(dwarf.AttrStmtList) == nil { continue } diff --git a/src/cmd/compile/internal/syntax/parser.go b/src/cmd/compile/internal/syntax/parser.go index 9f02cb6c2c..770175fe54 100644 --- a/src/cmd/compile/internal/syntax/parser.go +++ b/src/cmd/compile/internal/syntax/parser.go @@ -708,15 +708,7 @@ func (p *parser) funcDeclOrNil() *FuncDecl { } f.Name = p.name() - if p.allowGenerics() && p.got(_Lbrack) { - if p.tok == _Rbrack { - p.syntaxError("empty type parameter list") - p.next() - } else { - f.TParamList = p.paramList(nil, _Rbrack, true) - } - } - f.Type = p.funcType() + f.TParamList, f.Type = p.funcType("") if p.tok == _Lbrace { f.Body = p.funcBody() } @@ -944,7 +936,7 @@ func (p *parser) operand(keep_parens bool) Expr { case _Func: pos := p.pos() p.next() - ftyp := p.funcType() + _, ftyp := p.funcType("function literal") if p.tok == _Lbrace { p.xnest++ @@ -1284,7 +1276,8 @@ func (p *parser) typeOrNil() Expr { case _Func: // fntype p.next() - return p.funcType() + _, t := p.funcType("function type") + return t case _Lbrack: // '[' oexpr ']' ntype @@ -1357,18 +1350,34 @@ func (p *parser) typeInstance(typ Expr) Expr { return x } -func (p *parser) funcType() *FuncType { +// If context != "", type parameters are not permitted. +func (p *parser) funcType(context string) ([]*Field, *FuncType) { if trace { defer p.trace("funcType")() } typ := new(FuncType) typ.pos = p.pos() + + var tparamList []*Field + if p.allowGenerics() && p.got(_Lbrack) { + if context != "" { + // accept but complain + p.syntaxErrorAt(typ.pos, context+" cannot have type parameters") + } + if p.tok == _Rbrack { + p.syntaxError("empty type parameter list") + p.next() + } else { + tparamList = p.paramList(nil, _Rbrack, true) + } + } + p.want(_Lparen) typ.ParamList = p.paramList(nil, _Rparen, false) typ.ResultList = p.funcResult() - return typ + return tparamList, typ } // "[" has already been consumed, and pos is its position. @@ -1697,11 +1706,13 @@ func (p *parser) methodDecl() *Field { // already progressed, no need to advance } + const context = "interface method" + switch p.tok { case _Lparen: // method f.Name = name - f.Type = p.funcType() + _, f.Type = p.funcType(context) case _Lbrack: if p.allowGenerics() { @@ -1721,7 +1732,7 @@ func (p *parser) methodDecl() *Field { // name[]( p.errorAt(pos, "empty type parameter list") f.Name = name - f.Type = p.funcType() + _, f.Type = p.funcType(context) } else { p.errorAt(pos, "empty type argument list") f.Type = name @@ -1738,7 +1749,7 @@ func (p *parser) methodDecl() *Field { // as if [] were absent. if p.tok == _Lparen { f.Name = name - f.Type = p.funcType() + _, f.Type = p.funcType(context) } else { f.Type = name } @@ -1749,7 +1760,7 @@ func (p *parser) methodDecl() *Field { if list[0].Name != nil { // generic method f.Name = name - f.Type = p.funcType() + _, f.Type = p.funcType(context) // TODO(gri) Record list as type parameter list with f.Type // if we want to type-check the generic method. // For now, report an error so this is not a silent event. diff --git a/src/cmd/compile/internal/syntax/testdata/issue48382.go2 b/src/cmd/compile/internal/syntax/testdata/issue48382.go2 new file mode 100644 index 0000000000..1e8f4b0ec6 --- /dev/null +++ b/src/cmd/compile/internal/syntax/testdata/issue48382.go2 @@ -0,0 +1,15 @@ +// Copyright 2021 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 + +type _ func /* ERROR function type cannot have type parameters */ [ /* ERROR empty type parameter list */ ]() +type _ func /* ERROR function type cannot have type parameters */ [ x /* ERROR missing type constraint */ ]() +type _ func /* ERROR function type cannot have type parameters */ [P any]() + +var _ = func /* ERROR function literal cannot have type parameters */ [P any]() {} + +type _ interface{ + m /* ERROR interface method cannot have type parameters */ [P any]() +} diff --git a/src/cmd/compile/internal/typecheck/crawler.go b/src/cmd/compile/internal/typecheck/crawler.go index ae2b3b1df4..ae6542d071 100644 --- a/src/cmd/compile/internal/typecheck/crawler.go +++ b/src/cmd/compile/internal/typecheck/crawler.go @@ -207,7 +207,7 @@ func (p *crawler) markInlBody(n *ir.Name) { if fn == nil { base.Fatalf("markInlBody: missing Func on %v", n) } - if fn.Inl == nil { + if !HaveInlineBody(fn) { return } diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index 7c6c23e737..26bc838ed9 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -81,6 +81,27 @@ func ImportBody(fn *ir.Func) { inimport = false } +// HaveInlineBody reports whether we have fn's inline body available +// for inlining. +func HaveInlineBody(fn *ir.Func) bool { + if fn.Inl == nil { + return false + } + + // Unified IR is much more conservative about pruning unreachable + // methods (at the cost of increased build artifact size). + if base.Debug.Unified != 0 { + return true + } + + if fn.Inl.Body != nil { + return true + } + + _, ok := inlineImporter[fn.Nname.Sym()] + return ok +} + func importReaderFor(sym *types.Sym, importers map[*types.Sym]iimporterAndOffset) *importReader { x, ok := importers[sym] if !ok { diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index 96e120fe03..1986845f64 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -1421,7 +1421,9 @@ func Shapify(t *types.Type, index int) *types.Type { // All pointers have the same shape. // TODO: Make unsafe.Pointer the same shape as normal pointers. - if u.Kind() == types.TPTR { + // Note: pointers to arrays are special because of slice-to-array-pointer + // conversions. See issue 49295. + if u.Kind() == types.TPTR && u.Elem().Kind() != types.TARRAY { u = types.Types[types.TUINT8].PtrTo() } diff --git a/src/cmd/compile/internal/types/pkg.go b/src/cmd/compile/internal/types/pkg.go index f63a357f0d..fe42049cee 100644 --- a/src/cmd/compile/internal/types/pkg.go +++ b/src/cmd/compile/internal/types/pkg.go @@ -9,6 +9,7 @@ import ( "cmd/internal/objabi" "fmt" "sort" + "strings" "sync" ) @@ -48,7 +49,13 @@ func NewPkg(path, name string) *Pkg { p := new(Pkg) p.Path = path p.Name = name - p.Prefix = objabi.PathToPrefix(path) + if strings.HasPrefix(path, "go.") { + // Special compiler-internal packages don't need to be escaped. + // This particularly helps with the go.shape package. + p.Prefix = path + } else { + p.Prefix = objabi.PathToPrefix(path) + } p.Syms = make(map[string]*Sym) pkgMap[path] = p diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index c3efbc9f07..6288df30d6 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -2202,4 +2202,4 @@ var ( var SimType [NTYPE]Kind -var ShapePkg = NewPkg(".shape", ".shape") +var ShapePkg = NewPkg("go.shape", "go.shape") diff --git a/src/cmd/compile/internal/types2/api_test.go b/src/cmd/compile/internal/types2/api_test.go index 26652f3e74..30cfbe0ee4 100644 --- a/src/cmd/compile/internal/types2/api_test.go +++ b/src/cmd/compile/internal/types2/api_test.go @@ -326,25 +326,25 @@ func TestTypesInfo(t *testing.T) { {brokenPkg + `x5; func _() { var x map[string][...]int; x = map[string][...]int{"": {1,2,3}} }`, `x`, `map[string]invalid type`}, // parameterized functions - {genericPkg + `p0; func f[T any](T) {}; var _ = f[int]`, `f`, `func[generic_p0.T₁ interface{}](generic_p0.T₁)`}, + {genericPkg + `p0; func f[T any](T) {}; var _ = f[int]`, `f`, `func[T interface{}](T)`}, {genericPkg + `p1; func f[T any](T) {}; var _ = f[int]`, `f[int]`, `func(int)`}, {genericPkg + `p2; func f[T any](T) {}; func _() { f(42) }`, `f`, `func(int)`}, {genericPkg + `p3; func f[T any](T) {}; func _() { f[int](42) }`, `f[int]`, `func(int)`}, - {genericPkg + `p4; func f[T any](T) {}; func _() { f[int](42) }`, `f`, `func[generic_p4.T₁ interface{}](generic_p4.T₁)`}, + {genericPkg + `p4; func f[T any](T) {}; func _() { f[int](42) }`, `f`, `func[T interface{}](T)`}, {genericPkg + `p5; func f[T any](T) {}; func _() { f(42) }`, `f(42)`, `()`}, // type parameters {genericPkg + `t0; type t[] int; var _ t`, `t`, `generic_t0.t`}, // t[] is a syntax error that is ignored in this test in favor of t - {genericPkg + `t1; type t[P any] int; var _ t[int]`, `t`, `generic_t1.t[generic_t1.P₁ interface{}]`}, - {genericPkg + `t2; type t[P interface{}] int; var _ t[int]`, `t`, `generic_t2.t[generic_t2.P₁ interface{}]`}, - {genericPkg + `t3; type t[P, Q interface{}] int; var _ t[int, int]`, `t`, `generic_t3.t[generic_t3.P₁, generic_t3.Q₂ interface{}]`}, - {brokenPkg + `t4; type t[P, Q interface{ m() }] int; var _ t[int, int]`, `t`, `broken_t4.t[broken_t4.P₁, broken_t4.Q₂ interface{m()}]`}, + {genericPkg + `t1; type t[P any] int; var _ t[int]`, `t`, `generic_t1.t[P interface{}]`}, + {genericPkg + `t2; type t[P interface{}] int; var _ t[int]`, `t`, `generic_t2.t[P interface{}]`}, + {genericPkg + `t3; type t[P, Q interface{}] int; var _ t[int, int]`, `t`, `generic_t3.t[P, Q interface{}]`}, + {brokenPkg + `t4; type t[P, Q interface{ m() }] int; var _ t[int, int]`, `t`, `broken_t4.t[P, Q interface{m()}]`}, // instantiated types must be sanitized {genericPkg + `g0; type t[P any] int; var x struct{ f t[int] }; var _ = x.f`, `x.f`, `generic_g0.t[int]`}, // issue 45096 - {genericPkg + `issue45096; func _[T interface{ ~int8 | ~int16 | ~int32 }](x T) { _ = x < 0 }`, `0`, `generic_issue45096.T₁`}, + {genericPkg + `issue45096; func _[T interface{ ~int8 | ~int16 | ~int32 }](x T) { _ = x < 0 }`, `0`, `T`}, // issue 47895 {`package p; import "unsafe"; type S struct { f int }; var s S; var _ = unsafe.Offsetof(s.f)`, `s.f`, `int`}, diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index c5c6bdf0a5..548d55e10c 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -101,7 +101,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( if x.mode == invalid { return } - if isString(x.typ) { + if allString(x.typ) { if check.Types != nil { sig := makeSig(S, S, x.typ) sig.variadic = true diff --git a/src/cmd/compile/internal/types2/builtins_test.go b/src/cmd/compile/internal/types2/builtins_test.go index 52dbba1cb9..be5707cdfe 100644 --- a/src/cmd/compile/internal/types2/builtins_test.go +++ b/src/cmd/compile/internal/types2/builtins_test.go @@ -112,15 +112,15 @@ var builtinCalls = []struct { {"Alignof", `_ = unsafe.Alignof(0)`, `invalid type`}, // constant {"Alignof", `var x struct{}; _ = unsafe.Alignof(x)`, `invalid type`}, // constant - {"Alignof", `var x P; _ = unsafe.Alignof(x)`, `func(p.P₁) uintptr`}, + {"Alignof", `var x P; _ = unsafe.Alignof(x)`, `func(P) uintptr`}, {"Offsetof", `var x struct{f bool}; _ = unsafe.Offsetof(x.f)`, `invalid type`}, // constant {"Offsetof", `var x struct{_ int; f bool}; _ = unsafe.Offsetof((&x).f)`, `invalid type`}, // constant - {"Offsetof", `var x struct{_ int; f P}; _ = unsafe.Offsetof((&x).f)`, `func(p.P₁) uintptr`}, + {"Offsetof", `var x struct{_ int; f P}; _ = unsafe.Offsetof((&x).f)`, `func(P) uintptr`}, {"Sizeof", `_ = unsafe.Sizeof(0)`, `invalid type`}, // constant {"Sizeof", `var x struct{}; _ = unsafe.Sizeof(x)`, `invalid type`}, // constant - {"Sizeof", `var x P; _ = unsafe.Sizeof(x)`, `func(p.P₁) uintptr`}, + {"Sizeof", `var x P; _ = unsafe.Sizeof(x)`, `func(P) uintptr`}, {"Slice", `var p *int; _ = unsafe.Slice(p, 1)`, `func(*int, int) []int`}, {"Slice", `var p *byte; var n uintptr; _ = unsafe.Slice(p, n)`, `func(*byte, uintptr) []byte`}, diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go index 220ba940b3..49cae5a930 100644 --- a/src/cmd/compile/internal/types2/call.go +++ b/src/cmd/compile/internal/types2/call.go @@ -88,6 +88,8 @@ func (check *Checker) instantiateSignature(pos syntax.Pos, typ *Signature, targs pos = posList[i] } check.softErrorf(pos, err.Error()) + } else { + check.mono.recordInstance(check.pkg, pos, tparams, targs, posList) } return inst diff --git a/src/cmd/compile/internal/types2/check.go b/src/cmd/compile/internal/types2/check.go index 6e8883e5de..b9a76a8990 100644 --- a/src/cmd/compile/internal/types2/check.go +++ b/src/cmd/compile/internal/types2/check.go @@ -126,6 +126,7 @@ type Checker struct { imports []*PkgName // list of imported packages dotImportMap map[dotImportKey]*PkgName // maps dot-imported objects to the package they were dot-imported through recvTParamMap map[*syntax.Name]*TypeParam // maps blank receiver type parameters to their type + mono monoGraph // graph for detecting non-monomorphizable instantiation loops firstErr error // first error encountered methods map[*TypeName][]*Func // maps package scope type names to associated non-blank (non-interface) methods @@ -317,6 +318,11 @@ func (check *Checker) checkFiles(files []*syntax.File) (err error) { print("== recordUntyped ==") check.recordUntyped() + if check.firstErr == nil { + // TODO(mdempsky): Ensure monomorph is safe when errors exist. + check.monomorph() + } + check.pkg.complete = true // no longer needed - release memory @@ -424,9 +430,9 @@ func (check *Checker) recordTypeAndValue(x syntax.Expr, mode operandMode, typ Ty } if mode == constant_ { assert(val != nil) - // We check is(typ, IsConstType) here as constant expressions may be + // We check allBasic(typ, IsConstType) here as constant expressions may be // recorded as type parameters. - assert(typ == Typ[Invalid] || is(typ, IsConstType)) + assert(typ == Typ[Invalid] || allBasic(typ, IsConstType)) } if m := check.Types; m != nil { m[x] = TypeAndValue{mode, typ, val} diff --git a/src/cmd/compile/internal/types2/conversions.go b/src/cmd/compile/internal/types2/conversions.go index bc33b3a44b..44e8aad84f 100644 --- a/src/cmd/compile/internal/types2/conversions.go +++ b/src/cmd/compile/internal/types2/conversions.go @@ -16,26 +16,54 @@ import ( func (check *Checker) conversion(x *operand, T Type) { constArg := x.mode == constant_ - var ok bool - var cause string - switch { - case constArg && isConstType(T): - // constant conversion (T cannot be a type parameter) + constConvertibleTo := func(T Type, val *constant.Value) bool { switch t := asBasic(T); { - case representableConst(x.val, check, t, &x.val): - ok = true + case t == nil: + // nothing to do + case representableConst(x.val, check, t, val): + return true case isInteger(x.typ) && isString(t): codepoint := unicode.ReplacementChar if i, ok := constant.Uint64Val(x.val); ok && i <= unicode.MaxRune { codepoint = rune(i) } - x.val = constant.MakeString(string(codepoint)) - ok = true + if val != nil { + *val = constant.MakeString(string(codepoint)) + } + return true } + return false + } + + var ok bool + var cause string + switch { + case constArg && isConstType(T): + // constant conversion + ok = constConvertibleTo(T, &x.val) + case constArg && isTypeParam(T): + // x is convertible to T if it is convertible + // to each specific type in the type set of T. + // If T's type set is empty, or if it doesn't + // have specific types, constant x cannot be + // converted. + ok = under(T).(*TypeParam).underIs(func(u Type) bool { + // t is nil if there are no specific type terms + if u == nil { + cause = check.sprintf("%s does not contain specific types", T) + return false + } + if !constConvertibleTo(u, nil) { + cause = check.sprintf("cannot convert %s to %s (in %s)", x, u, T) + return false + } + return true + }) + x.mode = value // type parameters are not constants case x.convertibleTo(check, T, &cause): // non-constant conversion - x.mode = value ok = true + x.mode = value } if !ok { @@ -65,7 +93,7 @@ func (check *Checker) conversion(x *operand, T Type) { // ok } else if IsInterface(T) || constArg && !isConstType(T) { final = Default(x.typ) - } else if isInteger(x.typ) && isString(T) { + } else if isInteger(x.typ) && allString(T) { final = x.typ } check.updateExprType(x.expr, final, true) @@ -94,64 +122,8 @@ func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool { return true } - // determine type parameter operands with specific type terms - Vp, _ := under(x.typ).(*TypeParam) - Tp, _ := under(T).(*TypeParam) - if Vp != nil && !Vp.hasTerms() { - Vp = nil - } - if Tp != nil && !Tp.hasTerms() { - Tp = nil - } - - errorf := func(format string, args ...interface{}) { - if check != nil && cause != nil { - msg := check.sprintf(format, args...) - if *cause != "" { - msg += "\n\t" + *cause - } - *cause = msg - } - } - - // generic cases with specific type terms - // (generic operands cannot be constants, so we can ignore x.val) - switch { - case Vp != nil && Tp != nil: - return Vp.is(func(V *term) bool { - return Tp.is(func(T *term) bool { - if !convertibleToImpl(check, V.typ, T.typ, cause) { - errorf("cannot convert %s (in %s) to %s (in %s)", V.typ, Vp, T.typ, Tp) - return false - } - return true - }) - }) - case Vp != nil: - return Vp.is(func(V *term) bool { - if !convertibleToImpl(check, V.typ, T, cause) { - errorf("cannot convert %s (in %s) to %s", V.typ, Vp, T) - return false - } - return true - }) - case Tp != nil: - return Tp.is(func(T *term) bool { - if !convertibleToImpl(check, x.typ, T.typ, cause) { - errorf("cannot convert %s to %s (in %s)", x.typ, T.typ, Tp) - return false - } - return true - }) - } - - // non-generic case - return convertibleToImpl(check, x.typ, T, cause) -} - -// convertibleToImpl should only be called by convertibleTo -func convertibleToImpl(check *Checker, V, T Type, cause *string) bool { // "V and T have identical underlying types if tags are ignored" + V := x.typ Vu := under(V) Tu := under(T) if IdenticalIgnoreTags(Vu, Tu) { @@ -222,6 +194,67 @@ func convertibleToImpl(check *Checker, V, T Type, cause *string) bool { } } + // optimization: if we don't have type parameters, we're done + Vp, _ := Vu.(*TypeParam) + Tp, _ := Tu.(*TypeParam) + if Vp == nil && Tp == nil { + return false + } + + errorf := func(format string, args ...interface{}) { + if check != nil && cause != nil { + msg := check.sprintf(format, args...) + if *cause != "" { + msg += "\n\t" + *cause + } + *cause = msg + } + } + + // generic cases with specific type terms + // (generic operands cannot be constants, so we can ignore x.val) + switch { + case Vp != nil && Tp != nil: + x := *x // don't clobber outer x + return Vp.is(func(V *term) bool { + if V == nil { + return false // no specific types + } + x.typ = V.typ + return Tp.is(func(T *term) bool { + if !x.convertibleTo(check, T.typ, cause) { + errorf("cannot convert %s (in %s) to %s (in %s)", V.typ, Vp, T.typ, Tp) + return false + } + return true + }) + }) + case Vp != nil: + x := *x // don't clobber outer x + return Vp.is(func(V *term) bool { + if V == nil { + return false // no specific types + } + x.typ = V.typ + if !x.convertibleTo(check, T, cause) { + errorf("cannot convert %s (in %s) to %s", V.typ, Vp, T) + return false + } + return true + }) + case Tp != nil: + return Tp.is(func(T *term) bool { + if T == nil { + return false // no specific types + } + if !x.convertibleTo(check, T.typ, cause) { + errorf("cannot convert %s to %s (in %s)", x.typ, T.typ, Tp) + return false + } + return true + }) + } + return false } diff --git a/src/cmd/compile/internal/types2/errors.go b/src/cmd/compile/internal/types2/errors.go index 0c8a4a90ff..b56d11a28b 100644 --- a/src/cmd/compile/internal/types2/errors.go +++ b/src/cmd/compile/internal/types2/errors.go @@ -66,7 +66,7 @@ func (err *error_) msg(qf Qualifier) string { fmt.Fprintf(&buf, "%s: ", p.pos) } } - buf.WriteString(sprintf(qf, p.format, p.args...)) + buf.WriteString(sprintf(qf, false, p.format, p.args...)) } return buf.String() } @@ -85,7 +85,7 @@ func (err *error_) errorf(at poser, format string, args ...interface{}) { err.desc = append(err.desc, errorDesc{posFor(at), format, args}) } -func sprintf(qf Qualifier, format string, args ...interface{}) string { +func sprintf(qf Qualifier, debug bool, format string, args ...interface{}) string { for i, arg := range args { switch a := arg.(type) { case nil: @@ -101,7 +101,7 @@ func sprintf(qf Qualifier, format string, args ...interface{}) string { case Object: arg = ObjectString(a, qf) case Type: - arg = TypeString(a, qf) + arg = typeString(a, qf, debug) } args[i] = arg } @@ -146,7 +146,7 @@ func (check *Checker) markImports(pkg *Package) { } func (check *Checker) sprintf(format string, args ...interface{}) string { - return sprintf(check.qualifier, format, args...) + return sprintf(check.qualifier, false, format, args...) } func (check *Checker) report(err *error_) { @@ -160,13 +160,13 @@ func (check *Checker) trace(pos syntax.Pos, format string, args ...interface{}) fmt.Printf("%s:\t%s%s\n", pos, strings.Repeat(". ", check.indent), - check.sprintf(format, args...), + sprintf(check.qualifier, true, format, args...), ) } // dump is only needed for debugging func (check *Checker) dump(format string, args ...interface{}) { - fmt.Println(check.sprintf(format, args...)) + fmt.Println(sprintf(check.qualifier, true, format, args...)) } func (check *Checker) err(at poser, msg string, soft bool) { diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index ae7b205e53..95b96f2334 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -63,10 +63,10 @@ var unaryOpPredicates opPredicates func init() { // Setting unaryOpPredicates in init avoids declaration cycles. unaryOpPredicates = opPredicates{ - syntax.Add: isNumeric, - syntax.Sub: isNumeric, - syntax.Xor: isInteger, - syntax.Not: isBoolean, + syntax.Add: allNumeric, + syntax.Sub: allNumeric, + syntax.Xor: allInteger, + syntax.Not: allBoolean, } } @@ -710,10 +710,10 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const return nil, nil, _InvalidUntypedConversion } - switch t := under(target).(type) { + switch u := under(target).(type) { case *Basic: if x.mode == constant_ { - v, code := check.representation(x, t) + v, code := check.representation(x, u) if code != 0 { return nil, nil, code } @@ -743,7 +743,8 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const return nil, nil, _InvalidUntypedConversion } case *TypeParam: - ok := t.underIs(func(t Type) bool { + // TODO(gri) review this code - doesn't look quite right + ok := u.underIs(func(t Type) bool { target, _, _ := check.implicitTypeAndValue(x, t) return target != nil }) @@ -754,7 +755,7 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const // Update operand types to the default type rather than the target // (interface) type: values must have concrete dynamic types. // Untyped nil was handled upfront. - if !t.Empty() { + if !u.Empty() { return nil, nil, _InvalidUntypedConversion // cannot assign untyped values to non-empty interfaces } return Default(x.typ), nil, 0 // default type for nil is nil @@ -778,7 +779,7 @@ func (check *Checker) comparison(x, y *operand, op syntax.Operator) { defined = Comparable(x.typ) && Comparable(y.typ) || x.isNil() && hasNil(y.typ) || y.isNil() && hasNil(x.typ) case syntax.Lss, syntax.Leq, syntax.Gtr, syntax.Geq: // spec: The ordering operators <, <=, >, and >= apply to operands that are ordered." - defined = isOrdered(x.typ) && isOrdered(y.typ) + defined = allOrdered(x.typ) && allOrdered(y.typ) default: unreachable() } @@ -832,7 +833,7 @@ func (check *Checker) shift(x, y *operand, e syntax.Expr, op syntax.Operator) { xval = constant.ToInt(x.val) } - if isInteger(x.typ) || isUntyped(x.typ) && xval != nil && xval.Kind() == constant.Int { + if allInteger(x.typ) || isUntyped(x.typ) && xval != nil && xval.Kind() == constant.Int { // The lhs is of integer type or an untyped constant representable // as an integer. Nothing to do. } else { @@ -863,11 +864,11 @@ func (check *Checker) shift(x, y *operand, e syntax.Expr, op syntax.Operator) { x.mode = invalid return } - } else if !isInteger(y.typ) { + } else if !allInteger(y.typ) { check.errorf(y, invalidOp+"shift count %s must be integer", y) x.mode = invalid return - } else if !isUnsigned(y.typ) && !check.allowVersion(check.pkg, 1, 13) { + } else if !allUnsigned(y.typ) && !check.allowVersion(check.pkg, 1, 13) { check.errorf(y, invalidOp+"signed shift count %s requires go1.13 or later", y) x.mode = invalid return @@ -938,7 +939,7 @@ func (check *Checker) shift(x, y *operand, e syntax.Expr, op syntax.Operator) { } // non-constant shift - lhs must be an integer - if !isInteger(x.typ) { + if !allInteger(x.typ) { check.errorf(x, invalidOp+"shifted operand %s must be integer", x) x.mode = invalid return @@ -952,19 +953,19 @@ var binaryOpPredicates opPredicates func init() { // Setting binaryOpPredicates in init avoids declaration cycles. binaryOpPredicates = opPredicates{ - syntax.Add: isNumericOrString, - syntax.Sub: isNumeric, - syntax.Mul: isNumeric, - syntax.Div: isNumeric, - syntax.Rem: isInteger, + syntax.Add: allNumericOrString, + syntax.Sub: allNumeric, + syntax.Mul: allNumeric, + syntax.Div: allNumeric, + syntax.Rem: allInteger, - syntax.And: isInteger, - syntax.Or: isInteger, - syntax.Xor: isInteger, - syntax.AndNot: isInteger, + syntax.And: allInteger, + syntax.Or: allInteger, + syntax.Xor: allInteger, + syntax.AndNot: allInteger, - syntax.AndAnd: isBoolean, - syntax.OrOr: isBoolean, + syntax.AndAnd: allBoolean, + syntax.OrOr: allBoolean, } } @@ -994,10 +995,10 @@ func (check *Checker) binary(x *operand, e syntax.Expr, lhs, rhs syntax.Expr, op if IsInterface(x.typ) || IsInterface(y.typ) { return true } - if isBoolean(x.typ) != isBoolean(y.typ) { + if allBoolean(x.typ) != allBoolean(y.typ) { return false } - if isString(x.typ) != isString(y.typ) { + if allString(x.typ) != allString(y.typ) { return false } if x.isNil() && !hasNil(y.typ) { @@ -1046,7 +1047,7 @@ func (check *Checker) binary(x *operand, e syntax.Expr, lhs, rhs syntax.Expr, op if op == syntax.Div || op == syntax.Rem { // check for zero divisor - if (x.mode == constant_ || isInteger(x.typ)) && y.mode == constant_ && constant.Sign(y.val) == 0 { + if (x.mode == constant_ || allInteger(x.typ)) && y.mode == constant_ && constant.Sign(y.val) == 0 { check.error(&y, invalidOp+"division by zero") x.mode = invalid return diff --git a/src/cmd/compile/internal/types2/index.go b/src/cmd/compile/internal/types2/index.go index 23e433ac6a..67110704e9 100644 --- a/src/cmd/compile/internal/types2/index.go +++ b/src/cmd/compile/internal/types2/index.go @@ -101,77 +101,80 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo case *TypeParam: // TODO(gri) report detailed failure cause for better error messages - var tkey, telem Type // tkey != nil if we have maps + var key, elem Type // key != nil: we must have all maps + mode := variable // non-maps result mode + // TODO(gri) factor out closure and use it for non-typeparam cases as well if typ.underIs(func(u Type) bool { - var key, elem Type - alen := int64(-1) // valid if >= 0 + l := int64(-1) // valid if >= 0 + var k, e Type // k is only set for maps switch t := u.(type) { case *Basic: - if !isString(t) { - return false + if isString(t) { + e = universeByte + mode = value } - elem = universeByte case *Array: - elem = t.elem - alen = t.len - case *Pointer: - a, _ := under(t.base).(*Array) - if a == nil { - return false + l = t.len + e = t.elem + if x.mode != variable { + mode = value + } + case *Pointer: + if t := asArray(t.base); t != nil { + l = t.len + e = t.elem } - elem = a.elem - alen = a.len case *Slice: - elem = t.elem + e = t.elem case *Map: - key = t.key - elem = t.elem - default: + k = t.key + e = t.elem + } + if e == nil { return false } - assert(elem != nil) - if telem == nil { + if elem == nil { // first type - tkey, telem = key, elem - length = alen - } else { - // all map keys must be identical (incl. all nil) - if !Identical(key, tkey) { - return false - } - // all element types must be identical - if !Identical(elem, telem) { - return false - } - tkey, telem = key, elem - // track the minimal length for arrays - if alen >= 0 && alen < length { - length = alen - } + length = l + key, elem = k, e + return true + } + // all map keys must be identical (incl. all nil) + // (that is, we cannot mix maps with other types) + if !Identical(key, k) { + return false + } + // all element types must be identical + if !Identical(elem, e) { + return false + } + // track the minimal length for arrays, if any + if l >= 0 && l < length { + length = l } return true }) { // For maps, the index expression must be assignable to the map key type. - if tkey != nil { + if key != nil { index := check.singleIndex(e) if index == nil { x.mode = invalid return false } - var key operand - check.expr(&key, index) - check.assignment(&key, tkey, "map index") + var k operand + check.expr(&k, index) + check.assignment(&k, key, "map index") // ok to continue even if indexing failed - map element type is known x.mode = mapindex - x.typ = telem + x.typ = elem x.expr = e return false } // no maps valid = true - x.mode = variable - x.typ = telem + x.mode = mode + x.typ = elem } } @@ -383,7 +386,7 @@ func (check *Checker) isValidIndex(x *operand, what string, allowNegative bool) } // spec: "the index x must be of integer type or an untyped constant" - if !isInteger(x.typ) { + if !allInteger(x.typ) { check.errorf(x, invalidArg+"%s %s must be integer", what, x) return false } diff --git a/src/cmd/compile/internal/types2/infer.go b/src/cmd/compile/internal/types2/infer.go index 156c2290f7..24c461f1c3 100644 --- a/src/cmd/compile/internal/types2/infer.go +++ b/src/cmd/compile/internal/types2/infer.go @@ -218,7 +218,7 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type, // At least one type argument couldn't be inferred. assert(targs != nil && index >= 0 && targs[index] == nil) tpar := tparams[index] - check.errorf(pos, "cannot infer %s (%s) (%s)", tpar.obj.name, tpar.obj.pos, targs) + check.errorf(pos, "cannot infer %s (%s)", tpar.obj.name, tpar.obj.pos) return nil } @@ -378,7 +378,6 @@ func (check *Checker) inferB(tparams []*TypeParam, targs []Type) (types []Type, // If a constraint has a structural type, unify the corresponding type parameter with it. for _, tpar := range tparams { - typ := tpar sbound := structure(tpar) if sbound != nil { // If the structural type is the underlying type of a single @@ -386,8 +385,10 @@ func (check *Checker) inferB(tparams []*TypeParam, targs []Type) (types []Type, if named, _ := tpar.singleType().(*Named); named != nil { sbound = named } - if !u.unify(typ, sbound) { - check.errorf(tpar.obj, "%s does not match %s", tpar.obj, sbound) + if !u.unify(tpar, sbound) { + // TODO(gri) improve error message by providing the type arguments + // which we know already + check.errorf(tpar.obj, "%s does not match %s", tpar, sbound) return nil, 0 } } diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index 8228ef2c31..44cf593ffb 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -155,7 +155,7 @@ func (check *Checker) satisfies(pos syntax.Pos, targ Type, tpar *TypeParam, smap qf = check.qualifier } errorf := func(format string, args ...interface{}) error { - return errors.New(sprintf(qf, format, args...)) + return errors.New(sprintf(qf, false, format, args...)) } // No type argument with non-empty type set satisfies the empty type set. diff --git a/src/cmd/compile/internal/types2/mono.go b/src/cmd/compile/internal/types2/mono.go new file mode 100644 index 0000000000..39c4d4fbef --- /dev/null +++ b/src/cmd/compile/internal/types2/mono.go @@ -0,0 +1,337 @@ +// Copyright 2021 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 types2 + +import ( + "cmd/compile/internal/syntax" +) + +// This file implements a check to validate that a Go package doesn't +// have unbounded recursive instantiation, which is not compatible +// with compilers using static instantiation (such as +// monomorphization). +// +// It implements a sort of "type flow" analysis by detecting which +// type parameters are instantiated with other type parameters (or +// types derived thereof). A package cannot be statically instantiated +// if the graph has any cycles involving at least one derived type. +// +// Concretely, we construct a directed, weighted graph. Vertices are +// used to represent type parameters as well as some defined +// types. Edges are used to represent how types depend on each other: +// +// * Everywhere a type-parameterized function or type is instantiated, +// we add edges to each type parameter from the vertices (if any) +// representing each type parameter or defined type referenced by +// the type argument. If the type argument is just the referenced +// type itself, then the edge has weight 0, otherwise 1. +// +// * For every defined type declared within a type-parameterized +// function or method, we add an edge of weight 1 to the defined +// type from each ambient type parameter. +// +// For example, given: +// +// func f[A, B any]() { +// type T int +// f[T, map[A]B]() +// } +// +// we construct vertices representing types A, B, and T. Because of +// declaration "type T int", we construct edges T<-A and T<-B with +// weight 1; and because of instantiation "f[T, map[A]B]" we construct +// edges A<-T with weight 0, and B<-A and B<-B with weight 1. +// +// Finally, we look for any positive-weight cycles. Zero-weight cycles +// are allowed because static instantiation will reach a fixed point. + +type monoGraph struct { + vertices []monoVertex + edges []monoEdge + + // canon maps method receiver type parameters to their respective + // receiver type's type parameters. + canon map[*TypeParam]*TypeParam + + // nameIdx maps a defined type or (canonical) type parameter to its + // vertex index. + nameIdx map[*TypeName]int +} + +type monoVertex struct { + weight int // weight of heaviest known path to this vertex + pre int // previous edge (if any) in the above path + len int // length of the above path + + // obj is the defined type or type parameter represented by this + // vertex. + obj *TypeName +} + +type monoEdge struct { + dst, src int + weight int + + pos syntax.Pos + typ Type +} + +func (check *Checker) monomorph() { + // We detect unbounded instantiation cycles using a variant of + // Bellman-Ford's algorithm. Namely, instead of always running |V| + // iterations, we run until we either reach a fixed point or we've + // found a path of length |V|. This allows us to terminate earlier + // when there are no cycles, which should be the common case. + + again := true + for again { + again = false + + for i, edge := range check.mono.edges { + src := &check.mono.vertices[edge.src] + dst := &check.mono.vertices[edge.dst] + + // N.B., we're looking for the greatest weight paths, unlike + // typical Bellman-Ford. + w := src.weight + edge.weight + if w <= dst.weight { + continue + } + + dst.pre = i + dst.len = src.len + 1 + if dst.len == len(check.mono.vertices) { + check.reportInstanceLoop(edge.dst) + return + } + + dst.weight = w + again = true + } + } +} + +func (check *Checker) reportInstanceLoop(v int) { + var stack []int + seen := make([]bool, len(check.mono.vertices)) + + // We have a path that contains a cycle and ends at v, but v may + // only be reachable from the cycle, not on the cycle itself. We + // start by walking backwards along the path until we find a vertex + // that appears twice. + for !seen[v] { + stack = append(stack, v) + seen[v] = true + v = check.mono.edges[check.mono.vertices[v].pre].src + } + + // Trim any vertices we visited before visiting v the first + // time. Since v is the first vertex we found within the cycle, any + // vertices we visited earlier cannot be part of the cycle. + for stack[0] != v { + stack = stack[1:] + } + + // TODO(mdempsky): Pivot stack so we report the cycle from the top? + + var err error_ + obj0 := check.mono.vertices[v].obj + err.errorf(obj0, "instantiation cycle:") + + qf := RelativeTo(check.pkg) + for _, v := range stack { + edge := check.mono.edges[check.mono.vertices[v].pre] + obj := check.mono.vertices[edge.dst].obj + + switch obj.Type().(type) { + default: + panic("unexpected type") + case *Named: + err.errorf(edge.pos, "%s implicitly parameterized by %s", obj.Name(), TypeString(edge.typ, qf)) // secondary error, \t indented + case *TypeParam: + err.errorf(edge.pos, "%s instantiated as %s", obj.Name(), TypeString(edge.typ, qf)) // secondary error, \t indented + } + } + check.report(&err) +} + +// recordCanon records that tpar is the canonical type parameter +// corresponding to method type parameter mpar. +func (w *monoGraph) recordCanon(mpar, tpar *TypeParam) { + if w.canon == nil { + w.canon = make(map[*TypeParam]*TypeParam) + } + w.canon[mpar] = tpar +} + +// recordInstance records that the given type parameters were +// instantiated with the corresponding type arguments. +func (w *monoGraph) recordInstance(pkg *Package, pos syntax.Pos, tparams []*TypeParam, targs []Type, posList []syntax.Pos) { + for i, tpar := range tparams { + pos := pos + if i < len(posList) { + pos = posList[i] + } + w.assign(pkg, pos, tpar, targs[i]) + } +} + +// assign records that tpar was instantiated as targ at pos. +func (w *monoGraph) assign(pkg *Package, pos syntax.Pos, tpar *TypeParam, targ Type) { + // Go generics do not have an analog to C++`s template-templates, + // where a template parameter can itself be an instantiable + // template. So any instantiation cycles must occur within a single + // package. Accordingly, we can ignore instantiations of imported + // type parameters. + // + // TODO(mdempsky): Push this check up into recordInstance? All type + // parameters in a list will appear in the same package. + if tpar.Obj().Pkg() != pkg { + return + } + + // flow adds an edge from vertex src representing that typ flows to tpar. + flow := func(src int, typ Type) { + weight := 1 + if typ == targ { + weight = 0 + } + + w.addEdge(w.typeParamVertex(tpar), src, weight, pos, targ) + } + + // Recursively walk the type argument to find any defined types or + // type parameters. + var do func(typ Type) + do = func(typ Type) { + switch typ := typ.(type) { + default: + panic("unexpected type") + + case *TypeParam: + assert(typ.Obj().Pkg() == pkg) + flow(w.typeParamVertex(typ), typ) + + case *Named: + if src := w.localNamedVertex(pkg, typ.Origin()); src >= 0 { + flow(src, typ) + } + + targs := typ.TypeArgs() + for i := 0; i < targs.Len(); i++ { + do(targs.At(i)) + } + + case *Array: + do(typ.Elem()) + case *Basic: + // ok + case *Chan: + do(typ.Elem()) + case *Map: + do(typ.Key()) + do(typ.Elem()) + case *Pointer: + do(typ.Elem()) + case *Slice: + do(typ.Elem()) + + case *Interface: + for i := 0; i < typ.NumMethods(); i++ { + do(typ.Method(i).Type()) + } + case *Signature: + tuple := func(tup *Tuple) { + for i := 0; i < tup.Len(); i++ { + do(tup.At(i).Type()) + } + } + tuple(typ.Params()) + tuple(typ.Results()) + case *Struct: + for i := 0; i < typ.NumFields(); i++ { + do(typ.Field(i).Type()) + } + } + } + do(targ) +} + +// localNamedVertex returns the index of the vertex representing +// named, or -1 if named doesn't need representation. +func (w *monoGraph) localNamedVertex(pkg *Package, named *Named) int { + obj := named.Obj() + if obj.Pkg() != pkg { + return -1 // imported type + } + + root := pkg.Scope() + if obj.Parent() == root { + return -1 // package scope, no ambient type parameters + } + + if idx, ok := w.nameIdx[obj]; ok { + return idx + } + + idx := -1 + + // Walk the type definition's scope to find any ambient type + // parameters that it's implicitly parameterized by. + for scope := obj.Parent(); scope != root; scope = scope.Parent() { + for _, elem := range scope.elems { + if elem, ok := elem.(*TypeName); ok && !elem.IsAlias() && elem.Pos().Cmp(obj.Pos()) < 0 { + if tpar, ok := elem.Type().(*TypeParam); ok { + if idx < 0 { + idx = len(w.vertices) + w.vertices = append(w.vertices, monoVertex{obj: obj}) + } + + w.addEdge(idx, w.typeParamVertex(tpar), 1, obj.Pos(), tpar) + } + } + } + } + + if w.nameIdx == nil { + w.nameIdx = make(map[*TypeName]int) + } + w.nameIdx[obj] = idx + return idx +} + +// typeParamVertex returns the index of the vertex representing tpar. +func (w *monoGraph) typeParamVertex(tpar *TypeParam) int { + if x, ok := w.canon[tpar]; ok { + tpar = x + } + + obj := tpar.Obj() + + if idx, ok := w.nameIdx[obj]; ok { + return idx + } + + if w.nameIdx == nil { + w.nameIdx = make(map[*TypeName]int) + } + + idx := len(w.vertices) + w.vertices = append(w.vertices, monoVertex{obj: obj}) + w.nameIdx[obj] = idx + return idx +} + +func (w *monoGraph) addEdge(dst, src, weight int, pos syntax.Pos, typ Type) { + // TODO(mdempsky): Deduplicate redundant edges? + w.edges = append(w.edges, monoEdge{ + dst: dst, + src: src, + weight: weight, + + pos: pos, + typ: typ, + }) +} diff --git a/src/cmd/compile/internal/types2/mono_test.go b/src/cmd/compile/internal/types2/mono_test.go new file mode 100644 index 0000000000..19d0e95637 --- /dev/null +++ b/src/cmd/compile/internal/types2/mono_test.go @@ -0,0 +1,89 @@ +// Copyright 2021 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 types2_test + +import ( + "bytes" + "cmd/compile/internal/syntax" + "cmd/compile/internal/types2" + "errors" + "fmt" + "strings" + "testing" +) + +func checkMono(t *testing.T, body string) error { + src := "package x; import `unsafe`; var _ unsafe.Pointer;\n" + body + file, err := syntax.Parse(syntax.NewFileBase("x.go"), strings.NewReader(src), nil, nil, syntax.AllowGenerics) + if err != nil { + t.Fatal(err) + } + files := []*syntax.File{file} + + var buf bytes.Buffer + conf := types2.Config{ + Error: func(err error) { fmt.Fprintln(&buf, err) }, + Importer: defaultImporter(), + } + conf.Check("x", files, nil) + if buf.Len() == 0 { + return nil + } + return errors.New(strings.TrimRight(buf.String(), "\n")) +} + +func TestMonoGood(t *testing.T) { + for i, good := range goods { + if err := checkMono(t, good); err != nil { + t.Errorf("%d: unexpected failure: %v", i, err) + } + } +} + +func TestMonoBad(t *testing.T) { + for i, bad := range bads { + if err := checkMono(t, bad); err == nil { + t.Errorf("%d: unexpected success", i) + } else { + t.Log(err) + } + } +} + +var goods = []string{ + "func F[T any](x T) { F(x) }", + "func F[T, U, V any]() { F[U, V, T](); F[V, T, U]() }", + "type Ring[A, B, C any] struct { L *Ring[B, C, A]; R *Ring[C, A, B] }", + "func F[T any]() { type U[T any] [unsafe.Sizeof(F[*T])]byte }", + "func F[T any]() { type U[T any] [unsafe.Sizeof(F[*T])]byte; var _ U[int] }", + "type U[T any] [unsafe.Sizeof(F[*T])]byte; func F[T any]() { var _ U[U[int]] }", + "func F[T any]() { type A = int; F[A]() }", +} + +// TODO(mdempsky): Validate specific error messages and positioning. + +var bads = []string{ + "func F[T any](x T) { F(&x) }", + "func F[T any]() { F[*T]() }", + "func F[T any]() { F[[]T]() }", + "func F[T any]() { F[[1]T]() }", + "func F[T any]() { F[chan T]() }", + "func F[T any]() { F[map[*T]int]() }", + "func F[T any]() { F[map[error]T]() }", + "func F[T any]() { F[func(T)]() }", + "func F[T any]() { F[func() T]() }", + "func F[T any]() { F[struct{ t T }]() }", + "func F[T any]() { F[interface{ t() T }]() }", + "type U[_ any] int; func F[T any]() { F[U[T]]() }", + "func F[T any]() { type U int; F[U]() }", + "func F[T any]() { type U int; F[*U]() }", + "type U[T any] int; func (U[T]) m() { var _ U[*T] }", + "type U[T any] int; func (*U[T]) m() { var _ U[*T] }", + "type U[T1 any] [unsafe.Sizeof(F[*T1])]byte; func F[T2 any]() { var _ U[T2] }", + "func F[A, B, C, D, E any]() { F[B, C, D, E, *A]() }", + "type U[_ any] int; const X = unsafe.Sizeof(func() { type A[T any] U[A[*T]] })", + "func F[T any]() { type A = *T; F[A]() }", + "type A[T any] struct { _ A[*T] }", +} diff --git a/src/cmd/compile/internal/types2/object.go b/src/cmd/compile/internal/types2/object.go index affeaf61f2..c7d6709c26 100644 --- a/src/cmd/compile/internal/types2/object.go +++ b/src/cmd/compile/internal/types2/object.go @@ -315,6 +315,8 @@ func (obj *TypeName) IsAlias() bool { return obj.pkg != nil || t.name != obj.name || t == universeByte || t == universeRune case *Named: return obj != t.obj + case *TypeParam: + return obj != t.obj default: return true } diff --git a/src/cmd/compile/internal/types2/object_test.go b/src/cmd/compile/internal/types2/object_test.go index a86733a5c9..ed3c123023 100644 --- a/src/cmd/compile/internal/types2/object_test.go +++ b/src/cmd/compile/internal/types2/object_test.go @@ -33,6 +33,8 @@ func TestIsAlias(t *testing.T) { pkg := NewPackage("p", "p") t1 := NewTypeName(nopos, pkg, "t1", nil) n1 := NewNamed(t1, new(Struct), nil) + t5 := NewTypeName(nopos, pkg, "t5", nil) + NewTypeParam(t5, nil) for _, test := range []struct { name *TypeName alias bool @@ -46,6 +48,7 @@ func TestIsAlias(t *testing.T) { {NewTypeName(nopos, nil, "int32", Typ[Int32]), false}, // type name refers to basic type with same name {NewTypeName(nopos, pkg, "int32", Typ[Int32]), true}, // type name is declared in user-defined package (outside Universe) {NewTypeName(nopos, nil, "rune", Typ[Rune]), true}, // type name refers to basic type rune which is an alias already + {t5, false}, // type name refers to type parameter and vice versa } { check(test.name, test.alias) } diff --git a/src/cmd/compile/internal/types2/operand.go b/src/cmd/compile/internal/types2/operand.go index e4db0554f3..2f85802701 100644 --- a/src/cmd/compile/internal/types2/operand.go +++ b/src/cmd/compile/internal/types2/operand.go @@ -317,19 +317,11 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er } } - // common case: if we don't have type parameters, we're done + // optimization: if we don't have type parameters, we're done if Vp == nil && Tp == nil { return false, _IncompatibleAssign } - // determine type parameter operands with specific type terms - if Vp != nil && !Vp.hasTerms() { - Vp = nil - } - if Tp != nil && !Tp.hasTerms() { - Tp = nil - } - errorf := func(format string, args ...interface{}) { if check != nil && reason != nil { msg := check.sprintf(format, args...) @@ -340,25 +332,36 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er } } - ok := false - code := _IncompatibleAssign - switch { - case Vp != nil && Tp != nil: - x := *x // don't clobber outer x - ok = Vp.is(func(V *term) bool { - x.typ = V.typ - return Tp.is(func(T *term) bool { - ok, code = x.assignableTo(check, T.typ, reason) - if !ok { - errorf("cannot assign %s (in %s) to %s (in %s)", V.typ, Vp, T.typ, Tp) - return false - } - return true - }) + // x's type V is not a named type and T is a type parameter, and + // x is assignable to each specific type in T's type set. + if !hasName(V) && Tp != nil { + ok := false + code := _IncompatibleAssign + Tp.is(func(T *term) bool { + if T == nil { + return false // no specific types + } + ok, code = x.assignableTo(check, T.typ, reason) + if !ok { + errorf("cannot assign %s to %s (in %s)", x.typ, T.typ, Tp) + return false + } + return true }) - case Vp != nil: + return ok, code + } + + // x's type V is a type parameter and T is not a named type, + // and values x' of each specific type in V's type set are + // assignable to T. + if Vp != nil && !hasName(T) { x := *x // don't clobber outer x - ok = Vp.is(func(V *term) bool { + ok := false + code := _IncompatibleAssign + Vp.is(func(V *term) bool { + if V == nil { + return false // no specific types + } x.typ = V.typ ok, code = x.assignableTo(check, T, reason) if !ok { @@ -367,19 +370,10 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er } return true }) - case Tp != nil: - x := *x // don't clobber outer x - ok = Tp.is(func(T *term) bool { - ok, code = x.assignableTo(check, T.typ, reason) - if !ok { - errorf("cannot assign %s to %s (in %s)", x.typ, T.typ, Tp) - return false - } - return true - }) + return ok, code } - return ok, code + return false, _IncompatibleAssign } // kind2tok translates syntax.LitKinds into token.Tokens. diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index 380fb6489c..7fbb91eb61 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -6,78 +6,100 @@ package types2 -// hasName reports whether typ has a name. This includes +// The isX predicates below report whether t is an X. +// If t is a type parameter the result is false; i.e., +// these predicates don't look inside a type parameter. + +func isBoolean(t Type) bool { return isBasic(t, IsBoolean) } +func isInteger(t Type) bool { return isBasic(t, IsInteger) } +func isUnsigned(t Type) bool { return isBasic(t, IsUnsigned) } +func isFloat(t Type) bool { return isBasic(t, IsFloat) } +func isComplex(t Type) bool { return isBasic(t, IsComplex) } +func isNumeric(t Type) bool { return isBasic(t, IsNumeric) } +func isString(t Type) bool { return isBasic(t, IsString) } +func isIntegerOrFloat(t Type) bool { return isBasic(t, IsInteger|IsFloat) } +func isConstType(t Type) bool { return isBasic(t, IsConstType) } + +// isBasic reports whether under(t) is a basic type with the specified info. +// If t is a type parameter the result is false; i.e., +// isBasic does not look inside a type parameter. +func isBasic(t Type, info BasicInfo) bool { + u, _ := under(t).(*Basic) + return u != nil && u.info&info != 0 +} + +// The allX predicates below report whether t is an X. +// If t is a type parameter the result is true if isX is true +// for all specified types of the type parameter's type set. +// allX is an optimized version of isX(structure(t)) (which +// is the same as underIs(t, isX)). + +func allBoolean(t Type) bool { return allBasic(t, IsBoolean) } +func allInteger(t Type) bool { return allBasic(t, IsInteger) } +func allUnsigned(t Type) bool { return allBasic(t, IsUnsigned) } +func allNumeric(t Type) bool { return allBasic(t, IsNumeric) } +func allString(t Type) bool { return allBasic(t, IsString) } +func allOrdered(t Type) bool { return allBasic(t, IsOrdered) } +func allNumericOrString(t Type) bool { return allBasic(t, IsNumeric|IsString) } + +// allBasic reports whether under(t) is a basic type with the specified info. +// If t is a type parameter, the result is true if isBasic(t, info) is true +// for all specific types of the type parameter's type set. +// allBasic(t, info) is an optimized version of isBasic(structure(t), info). +func allBasic(t Type, info BasicInfo) bool { + switch u := under(t).(type) { + case *Basic: + return u.info&info != 0 + case *TypeParam: + return u.is(func(t *term) bool { return t != nil && isBasic(t.typ, info) }) + } + return false +} + +// hasName reports whether t has a name. This includes // predeclared types, defined types, and type parameters. // hasName may be called with types that are not fully set up. -func hasName(typ Type) bool { - switch typ.(type) { +func hasName(t Type) bool { + switch t.(type) { case *Basic, *Named, *TypeParam: return true } return false } -// isGeneric reports whether a type is a generic, uninstantiated type (generic -// signatures are not included). -func isGeneric(typ Type) bool { - // A parameterized type is only instantiated if it doesn't have an instantiation already. - named, _ := typ.(*Named) - return named != nil && named.obj != nil && named.targs == nil && named.TypeParams() != nil -} - -func is(typ Type, what BasicInfo) bool { - switch t := under(typ).(type) { - case *Basic: - return t.info&what != 0 - case *TypeParam: - return t.underIs(func(t Type) bool { return is(t, what) }) - } - return false -} - -func isBoolean(typ Type) bool { return is(typ, IsBoolean) } -func isInteger(typ Type) bool { return is(typ, IsInteger) } -func isUnsigned(typ Type) bool { return is(typ, IsUnsigned) } -func isFloat(typ Type) bool { return is(typ, IsFloat) } -func isComplex(typ Type) bool { return is(typ, IsComplex) } -func isNumeric(typ Type) bool { return is(typ, IsNumeric) } -func isString(typ Type) bool { return is(typ, IsString) } - -// Note that if typ is a type parameter, isInteger(typ) || isFloat(typ) does not -// produce the expected result because a type set that contains both an integer -// and a floating-point type is neither (all) integers, nor (all) floats. -// Use isIntegerOrFloat instead. -func isIntegerOrFloat(typ Type) bool { return is(typ, IsInteger|IsFloat) } - -// isNumericOrString is the equivalent of isIntegerOrFloat for isNumeric(typ) || isString(typ). -func isNumericOrString(typ Type) bool { return is(typ, IsNumeric|IsString) } - -// isTyped reports whether typ is typed; i.e., not an untyped +// isTyped reports whether t is typed; i.e., not an untyped // constant or boolean. isTyped may be called with types that // are not fully set up. -func isTyped(typ Type) bool { +func isTyped(t Type) bool { // isTyped is called with types that are not fully // set up. Must not call asBasic()! - t, _ := typ.(*Basic) - return t == nil || t.info&IsUntyped == 0 + b, _ := t.(*Basic) + return b == nil || b.info&IsUntyped == 0 } -// isUntyped(typ) is the same as !isTyped(typ). -func isUntyped(typ Type) bool { - return !isTyped(typ) +// isUntyped(t) is the same as !isTyped(t). +func isUntyped(t Type) bool { + return !isTyped(t) } -func isOrdered(typ Type) bool { return is(typ, IsOrdered) } - -func isConstType(typ Type) bool { - // Type parameters are never const types. - t := asBasic(typ) - return t != nil && t.info&IsConstType != 0 +// IsInterface reports whether t is an interface type. +func IsInterface(t Type) bool { + return asInterface(t) != nil } -// IsInterface reports whether typ is an interface type. -func IsInterface(typ Type) bool { - return asInterface(typ) != nil +// isTypeParam reports whether t is a type parameter. +func isTypeParam(t Type) bool { + _, ok := under(t).(*TypeParam) + return ok +} + +// isGeneric reports whether a type is a generic, uninstantiated type +// (generic signatures are not included). +// TODO(gri) should we include signatures or assert that they are not present? +func isGeneric(t Type) bool { + // A parameterized type is only generic if it doesn't have an instantiation already. + named, _ := t.(*Named) + return named != nil && named.obj != nil && named.targs == nil && named.TypeParams() != nil } // Comparable reports whether values of type T are comparable. @@ -116,15 +138,15 @@ func comparable(T Type, seen map[Type]bool) bool { return false } -// hasNil reports whether a type includes the nil value. -func hasNil(typ Type) bool { - switch t := under(typ).(type) { +// hasNil reports whether type t includes the nil value. +func hasNil(t Type) bool { + switch u := under(t).(type) { case *Basic: - return t.kind == UnsafePointer + return u.kind == UnsafePointer case *Slice, *Pointer, *Signature, *Interface, *Map, *Chan: return true case *TypeParam: - return t.underIs(hasNil) + return u.underIs(hasNil) } return false } @@ -366,9 +388,8 @@ func identicalTParams(x, y []*TypeParam, cmpTags bool, p *ifacePair) bool { // Default returns the default "typed" type for an "untyped" type; // it returns the incoming type for all other types. The default type // for untyped nil is untyped nil. -// -func Default(typ Type) Type { - if t, ok := typ.(*Basic); ok { +func Default(t Type) Type { + if t, ok := t.(*Basic); ok { switch t.kind { case UntypedBool: return Typ[Bool] @@ -384,5 +405,5 @@ func Default(typ Type) Type { return Typ[String] } } - return typ + return t } diff --git a/src/cmd/compile/internal/types2/signature.go b/src/cmd/compile/internal/types2/signature.go index 604d0c9dbd..4541435587 100644 --- a/src/cmd/compile/internal/types2/signature.go +++ b/src/cmd/compile/internal/types2/signature.go @@ -148,6 +148,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams [] list := make([]Type, sig.RecvTypeParams().Len()) for i, t := range sig.RecvTypeParams().list() { list[i] = t + check.mono.recordCanon(t, recvTParams[i]) } smap := makeSubstMap(recvTParams, list) for i, tpar := range sig.RecvTypeParams().list() { diff --git a/src/cmd/compile/internal/types2/stmt.go b/src/cmd/compile/internal/types2/stmt.go index dd2100f711..eaf420aca7 100644 --- a/src/cmd/compile/internal/types2/stmt.go +++ b/src/cmd/compile/internal/types2/stmt.go @@ -443,7 +443,7 @@ func (check *Checker) stmt(ctxt stmtContext, s syntax.Stmt) { if x.mode == invalid { return } - if !isNumeric(x.typ) { + if !allNumeric(x.typ) { check.errorf(lhs[0], invalidOp+"%s%s%s (non-numeric type %s)", lhs[0], s.Op, s.Op, x.typ) return } @@ -556,7 +556,7 @@ func (check *Checker) stmt(ctxt stmtContext, s syntax.Stmt) { check.simpleStmt(s.Init) var x operand check.expr(&x, s.Cond) - if x.mode != invalid && !isBoolean(x.typ) { + if x.mode != invalid && !allBoolean(x.typ) { check.error(s.Cond, "non-boolean condition in if statement") } check.stmt(inner, s.Then) @@ -645,7 +645,7 @@ func (check *Checker) stmt(ctxt stmtContext, s syntax.Stmt) { if s.Cond != nil { var x operand check.expr(&x, s.Cond) - if x.mode != invalid && !isBoolean(x.typ) { + if x.mode != invalid && !allBoolean(x.typ) { check.error(s.Cond, "non-boolean condition in for statement") } } diff --git a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 index 11adb21d95..a1bf6c262f 100644 --- a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 @@ -114,6 +114,14 @@ func _[T interface{ [10]int }](x T, i int) { _ = x[i]; _ = x[9]; _ = x[10 /* ERR func _[T interface{ [10]byte | string }](x T, i int) { _ = x[i]; _ = x[9]; _ = x[10 /* ERROR out of bounds */ ] } func _[T interface{ [10]int | *[20]int | []int }](x T, i int) { _ = x[i]; _ = x[9]; _ = x[10 /* ERROR out of bounds */ ] } +// indexing with strings and non-variable arrays (assignment not permitted) +func _[T string](x T) { _ = x[0]; x /* ERROR cannot assign */ [0] = 0 } +func _[T []byte | string](x T) { x /* ERROR cannot assign */ [0] = 0 } +func _[T [10]byte]() { f := func() (x T) { return }; f /* ERROR cannot assign */ ()[0] = 0 } +func _[T [10]byte]() { f := func() (x *T) { return }; f /* ERROR cannot index */ ()[0] = 0 } +func _[T [10]byte]() { f := func() (x *T) { return }; (*f())[0] = 0 } +func _[T *[10]byte]() { f := func() (x T) { return }; f()[0] = 0 } + // slicing func _[T interface{ ~[10]E }, E any] (x T, i, j, k int) { var _ []E = x[i:j] } diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45985.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45985.go2 index f25b9d2b26..9963d2ee00 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45985.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45985.go2 @@ -5,7 +5,7 @@ package issue45985 // TODO(gri): this error should be on app[int] below. -func app[S /* ERROR "type S = S does not match" */ interface{ ~[]T }, T any](s S, e T) S { +func app[S /* ERROR "S does not match" */ interface{ ~[]T }, T any](s S, e T) S { return append(s, e) } diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48018.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48018.go2 new file mode 100644 index 0000000000..e6ccc6b9be --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48018.go2 @@ -0,0 +1,20 @@ +// Copyright 2021 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 + +type Box[A any] struct { + value A +} + +func Nest[A /* ERROR instantiation cycle */ any](b Box[A], n int) interface{} { + if n == 0 { + return b + } + return Nest(Box[Box[A]]{b}, n-1) +} + +func main() { + Nest(Box[int]{0}, 10) +} diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48974.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48974.go2 index ca4b6d9321..d8ff7c8cf4 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48974.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48974.go2 @@ -8,7 +8,7 @@ type Fooer interface { Foo() } -type Fooable[F Fooer] struct { +type Fooable[F /* ERROR instantiation cycle */ Fooer] struct { ptr F } diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49242.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49242.go2 new file mode 100644 index 0000000000..524a0cbae3 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49242.go2 @@ -0,0 +1,27 @@ +// Copyright 2021 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 + +func _[P int](x P) int { + return x // ERROR cannot use x .* as int value in return statement +} + +func _[P int]() int { + return P /* ERROR cannot use P\(1\) .* as int value in return statement */ (1) +} + +func _[P int](x int) P { + return x // ERROR cannot use x .* as P value in return statement +} + +func _[P, Q any](x P) Q { + return x // ERROR cannot use x .* as Q value in return statement +} + +// test case from issue +func F[G interface{ uint }]() int { + f := func(uint) int { return 0 } + return f(G /* ERROR cannot use G\(1\) .* as uint value in argument to f */ (1)) +} diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49247.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49247.go2 new file mode 100644 index 0000000000..3f25e0ee35 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49247.go2 @@ -0,0 +1,20 @@ +// Copyright 2021 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 + +type integer interface { + ~int | ~int8 | ~int16 | ~int32 | ~int64 | + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr +} + +func Add1024[T integer](s []T) { + for i, v := range s { + s[i] = v + 1024 // ERROR cannot convert 1024 \(untyped int constant\) to T + } +} + +func f[T interface{ int8 }]() { + println(T(1024 /* ERROR cannot convert 1024 \(untyped int value\) to T */)) +} diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49296.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49296.go2 new file mode 100644 index 0000000000..8f52acc8a4 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49296.go2 @@ -0,0 +1,20 @@ +// Copyright 2021 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 + +func _[ + T0 any, + T1 []int, + T2 ~float64 | ~complex128 | chan int, +]() { + _ = T0(nil /* ERROR cannot convert untyped nil to T0 */ ) + _ = T1(1 /* ERROR cannot convert 1 .* to T1 */ ) + _ = T2(2 /* ERROR cannot convert 2 .* to T2 */ ) +} + +// test case from issue +func f[T interface{[]int}]() { + _ = T(1 /* ERROR cannot convert */ ) +} diff --git a/src/cmd/compile/internal/types2/testdata/spec/assignability.go2 b/src/cmd/compile/internal/types2/testdata/spec/assignability.go2 index ab8f9c08b2..fb28358bbb 100644 --- a/src/cmd/compile/internal/types2/testdata/spec/assignability.go2 +++ b/src/cmd/compile/internal/types2/testdata/spec/assignability.go2 @@ -109,20 +109,48 @@ func _[ ) var ( - _ _CC = C - _ _SC = C - _ _RC = C + _ _CC = C // ERROR cannot use C .* as _CC value + _ _SC = C // ERROR cannot use C .* as _SC value + _ _RC = C // ERROR cannot use C .* as _RC value - _ CC = _CC(nil) - _ SC = _CC(nil) - _ RC = _CC(nil) + _ CC = _CC /* ERROR cannot use _CC\(nil\) .* as CC value */ (nil) + _ SC = _CC /* ERROR cannot use _CC\(nil\) .* as SC value */ (nil) + _ RC = _CC /* ERROR cannot use _CC\(nil\) .* as RC value */ (nil) - _ CC = C - _ SC = C // ERROR cannot use C .* as SC value .* cannot assign Chan to SendChan - _ RC = C // ERROR cannot use C .* as RC value .* cannot assign Chan to RecvChan + _ CC = C // ERROR cannot use C .* as CC value + _ SC = C // ERROR cannot use C .* as SC value + _ RC = C // ERROR cannot use C .* as RC value ) } +// "x's type V is not a named type and T is a type parameter, and x is assignable to each specific type in T's type set." +func _[ + TP0 any, + TP1 ~_Chan, + TP2 ~chan int | ~chan byte, +]() { + var ( + _ TP0 = c // ERROR cannot use c .* as TP0 value + _ TP0 = C // ERROR cannot use C .* as TP0 value + _ TP1 = c + _ TP1 = C // ERROR cannot use C .* as TP1 value + _ TP2 = c // ERROR .* cannot assign chan int to chan byte + ) +} + +// "x's type V is a type parameter and T is not a named type, and values x' of each specific type in V's type set are assignable to T." +func _[ + TP0 Interface, + TP1 ~_Chan, + TP2 ~chan int | ~chan byte, +](X0 TP0, X1 TP1, X2 TP2) { + i = X0 + I = X0 + c = X1 + C = X1 // ERROR cannot use X1 .* as Chan value + c = X2 // ERROR .* cannot assign chan byte \(in TP2\) to chan int +} + // "x is the predeclared identifier nil and T is a pointer, function, slice, map, channel, or interface type" func _[TP Interface](X TP) { b = nil // ERROR cannot use untyped nil diff --git a/src/cmd/compile/internal/types2/testdata/spec/conversions.go2 b/src/cmd/compile/internal/types2/testdata/spec/conversions.go2 index 0acd2762a1..fde332f34b 100644 --- a/src/cmd/compile/internal/types2/testdata/spec/conversions.go2 +++ b/src/cmd/compile/internal/types2/testdata/spec/conversions.go2 @@ -6,6 +6,40 @@ package conversions import "unsafe" +// constant conversions + +func _[T ~byte]() T { return 255 } +func _[T ~byte]() T { return 256 /* ERROR cannot use 256 .* as T value */ } + +func _[T ~byte]() { + const _ = T /* ERROR T\(0\) .* is not constant */ (0) + var _ T = 255 + var _ T = 256 // ERROR cannot use 256 .* as T value +} + +func _[T ~string]() T { return T('a') } +func _[T ~int | ~string]() T { return T('a') } +func _[T ~byte | ~int | ~string]() T { return T(256 /* ERROR cannot convert 256 .* to T */ ) } + +// implicit conversions never convert to string +func _[T ~string]() { + var _ string = 0 // ERROR cannot use .* as string value + var _ T = 0 // ERROR cannot use .* as T value +} + +// failing const conversions of constants to type parameters report a cause +func _[ + T1 any, + T2 interface{ m() }, + T3 ~int | ~float64 | ~bool, + T4 ~int | ~string, +]() { + _ = T1(0 /* ERROR cannot convert 0 .* to T1\n\tT1 does not contain specific types */ ) + _ = T2(1 /* ERROR cannot convert 1 .* to T2\n\tT2 does not contain specific types */ ) + _ = T3(2 /* ERROR cannot convert 2 .* to T3\n\tcannot convert 2 .* to bool \(in T3\) */ ) + _ = T4(3.14 /* ERROR cannot convert 3.14 .* to T4\n\tcannot convert 3.14 .* to int \(in T4\) */ ) +} + // "x is assignable to T" // - tested via assignability tests diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index 33d3d3642c..300c81f5fa 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -81,10 +81,32 @@ func asTypeParam(t Type) *TypeParam { return u } -// Exported for the compiler. +// Helper functions exported for the compiler. +// These functions assume type checking has completed +// and Type.Underlying() is returning the fully set up +// underlying type. Do not use internally. -func AsPointer(t Type) *Pointer { return asPointer(t) } -func AsNamed(t Type) *Named { return asNamed(t) } -func AsSignature(t Type) *Signature { return asSignature(t) } -func AsInterface(t Type) *Interface { return asInterface(t) } -func AsTypeParam(t Type) *TypeParam { return asTypeParam(t) } +func AsPointer(t Type) *Pointer { + u, _ := t.Underlying().(*Pointer) + return u +} + +func AsNamed(t Type) *Named { + u, _ := t.(*Named) + return u +} + +func AsSignature(t Type) *Signature { + u, _ := t.Underlying().(*Signature) + return u +} + +func AsInterface(t Type) *Interface { + u, _ := t.Underlying().(*Interface) + return u +} + +func AsTypeParam(t Type) *TypeParam { + u, _ := t.Underlying().(*TypeParam) + return u +} diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index 709499792b..f18a32016f 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -43,8 +43,14 @@ func RelativeTo(pkg *Package) Qualifier { // The Qualifier controls the printing of // package-level objects, and may be nil. func TypeString(typ Type, qf Qualifier) string { + return typeString(typ, qf, false) +} + +func typeString(typ Type, qf Qualifier, debug bool) string { var buf bytes.Buffer - WriteType(&buf, typ, qf) + w := newTypeWriter(&buf, qf) + w.debug = debug + w.typ(typ) return buf.String() } @@ -64,19 +70,20 @@ func WriteSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier) { } type typeWriter struct { - buf *bytes.Buffer - seen map[Type]bool - qf Qualifier - ctxt *Context // if non-nil, we are type hashing + buf *bytes.Buffer + seen map[Type]bool + qf Qualifier + ctxt *Context // if non-nil, we are type hashing + debug bool // if true, write debug annotations } func newTypeWriter(buf *bytes.Buffer, qf Qualifier) *typeWriter { - return &typeWriter{buf, make(map[Type]bool), qf, nil} + return &typeWriter{buf, make(map[Type]bool), qf, nil, false} } func newTypeHasher(buf *bytes.Buffer, ctxt *Context) *typeWriter { assert(ctxt != nil) - return &typeWriter{buf, make(map[Type]bool), nil, ctxt} + return &typeWriter{buf, make(map[Type]bool), nil, ctxt, false} } func (w *typeWriter) byte(b byte) { @@ -266,11 +273,10 @@ func (w *typeWriter) typ(typ Type) { w.error("unnamed type parameter") break } - // Optionally write out package for typeparams (like Named). - if t.obj.pkg != nil { - writePackage(w.buf, t.obj.pkg, w.qf) + w.string(t.obj.name) + if w.debug || w.ctxt != nil { + w.string(subscript(t.id)) } - w.string(t.obj.name + subscript(t.id)) default: // For externally defined implementations of Type. diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index d8183bfd9c..95893fd1e1 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -481,6 +481,8 @@ func (check *Checker) instantiatedType(x syntax.Expr, targsx []syntax.Expr, def pos = posList[i] } check.softErrorf(pos, err.Error()) + } else { + check.mono.recordInstance(check.pkg, x.Pos(), inst.tparams.list(), inst.targs.list(), posList) } } diff --git a/src/cmd/cover/cover.go b/src/cmd/cover/cover.go index 7ee000861b..9c8529f7eb 100644 --- a/src/cmd/cover/cover.go +++ b/src/cmd/cover/cover.go @@ -40,8 +40,8 @@ Finally, to generate modified source code with coverage annotations ` func usage() { - fmt.Fprintln(os.Stderr, usageMessage) - fmt.Fprintln(os.Stderr, "Flags:") + fmt.Fprint(os.Stderr, usageMessage) + fmt.Fprintln(os.Stderr, "\nFlags:") flag.PrintDefaults() fmt.Fprintln(os.Stderr, "\n Only one of -html, -func, or -mode may be set.") os.Exit(2) diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go index 5935011e19..98e30a158f 100644 --- a/src/cmd/dist/test.go +++ b/src/cmd/dist/test.go @@ -1013,7 +1013,7 @@ func (t *tester) internalLink() bool { func (t *tester) internalLinkPIE() bool { switch goos + "-" + goarch { case "darwin-amd64", "darwin-arm64", - "linux-amd64", "linux-arm64", + "linux-amd64", "linux-arm64", "linux-ppc64le", "android-arm64", "windows-amd64", "windows-386", "windows-arm": return true @@ -1031,7 +1031,7 @@ func (t *tester) supportedBuildmode(mode string) bool { switch pair { case "aix-ppc64", "darwin-amd64", "darwin-arm64", "ios-arm64", - "linux-amd64", "linux-386", "linux-ppc64le", "linux-s390x", + "linux-amd64", "linux-386", "linux-ppc64le", "linux-riscv64", "linux-s390x", "freebsd-amd64", "windows-amd64", "windows-386": return true @@ -1039,7 +1039,7 @@ func (t *tester) supportedBuildmode(mode string) bool { return false case "c-shared": switch pair { - case "linux-386", "linux-amd64", "linux-arm", "linux-arm64", "linux-ppc64le", "linux-s390x", + case "linux-386", "linux-amd64", "linux-arm", "linux-arm64", "linux-ppc64le", "linux-riscv64", "linux-s390x", "darwin-amd64", "darwin-arm64", "freebsd-amd64", "android-arm", "android-arm64", "android-386", diff --git a/src/cmd/doc/pkg.go b/src/cmd/doc/pkg.go index 822c9e16f8..2257c5c0eb 100644 --- a/src/cmd/doc/pkg.go +++ b/src/cmd/doc/pkg.go @@ -323,7 +323,8 @@ func (pkg *Package) oneLineNodeDepth(node ast.Node, depth int) string { if n.Assign.IsValid() { sep = " = " } - return fmt.Sprintf("type %s%s%s", n.Name.Name, sep, pkg.oneLineNodeDepth(n.Type, depth)) + tparams := pkg.formatTypeParams(n.TypeParams, depth) + return fmt.Sprintf("type %s%s%s%s", n.Name.Name, tparams, sep, pkg.oneLineNodeDepth(n.Type, depth)) case *ast.FuncType: var params []string @@ -342,15 +343,16 @@ func (pkg *Package) oneLineNodeDepth(node ast.Node, depth int) string { } } + tparam := pkg.formatTypeParams(n.TypeParams, depth) param := joinStrings(params) if len(results) == 0 { - return fmt.Sprintf("func(%s)", param) + return fmt.Sprintf("func%s(%s)", tparam, param) } result := joinStrings(results) if !needParens { - return fmt.Sprintf("func(%s) %s", param, result) + return fmt.Sprintf("func%s(%s) %s", tparam, param, result) } - return fmt.Sprintf("func(%s) (%s)", param, result) + return fmt.Sprintf("func%s(%s) (%s)", tparam, param, result) case *ast.StructType: if n.Fields == nil || len(n.Fields.List) == 0 { @@ -419,6 +421,17 @@ func (pkg *Package) oneLineNodeDepth(node ast.Node, depth int) string { } } +func (pkg *Package) formatTypeParams(list *ast.FieldList, depth int) string { + if list.NumFields() == 0 { + return "" + } + var tparams []string + for _, field := range list.List { + tparams = append(tparams, pkg.oneLineField(field, depth)) + } + return "[" + joinStrings(tparams) + "]" +} + // oneLineField returns a one-line summary of the field. func (pkg *Package) oneLineField(field *ast.Field, depth int) string { var names []string diff --git a/src/cmd/go.mod b/src/cmd/go.mod index e6fdc902dd..f7802a1675 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -3,7 +3,7 @@ module cmd go 1.18 require ( - github.com/google/pprof v0.0.0-20211001005136-7fe48b4c820b + github.com/google/pprof v0.0.0-20211104044539-f987b9c94b31 golang.org/x/arch v0.0.0-20210901143047-ebb09ed340f1 golang.org/x/mod v0.5.1-0.20210913215816-37dd6891021a golang.org/x/sync v0.0.0-20210220032951-036812b2e83c @@ -12,8 +12,8 @@ require ( ) require ( - github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639 // indirect + github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d // indirect golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect - golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e // indirect + golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect ) diff --git a/src/cmd/go.sum b/src/cmd/go.sum index 4993128d1a..25c25d81bd 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -1,10 +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-20211001005136-7fe48b4c820b h1:GX4+fGLMW5XTmDXB3R6UhTwZIYqgAOdA19+Ea0+3CU4= -github.com/google/pprof v0.0.0-20211001005136-7fe48b4c820b/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/google/pprof v0.0.0-20211104044539-f987b9c94b31 h1:YvpxjnjGhf/vDEeYOysNbsrtB///PKS8lqkFNSDm1p8= +github.com/google/pprof v0.0.0-20211104044539-f987b9c94b31/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= +github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d h1:uGg2frlt3IcT7kbV6LEp5ONv4vmoO2FW4qSO+my/aoM= +github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= golang.org/x/arch v0.0.0-20210901143047-ebb09ed340f1 h1:MwxAfiDvuwX8Nnnc6iRDhzyMyyc2tz5tYyCP/pZcPCg= golang.org/x/arch v0.0.0-20210901143047-ebb09ed340f1/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= @@ -13,9 +13,8 @@ golang.org/x/mod v0.5.1-0.20210913215816-37dd6891021a h1:55PVa91KndtPGH2lus5l2gD golang.org/x/mod v0.5.1-0.20210913215816-37dd6891021a/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e h1:XMgFehsDnnLGtjvjOfqWSUzt0alpTR1RSEuznObga2c= -golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac h1:oN6lz7iLW/YC7un8pq+9bOLyXrprv2+DKfkJY+2LJJw= +golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b h1:9zKuko04nR4gjZ4+DNjHqRlAJqbJETHwiNKDqTfOjfE= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/tools v0.1.8-0.20211025211149-f916b54a1784 h1:+xP+QoP2SEPgbn+07I/yJTzP+gavj0XKGS6+JU5tlck= diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index 0dcb317995..c9426801c5 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -1074,8 +1074,11 @@ // // Download downloads the named modules, which can be module patterns selecting // dependencies of the main module or module queries of the form path@version. -// With no arguments, download applies to all dependencies of the main module -// (equivalent to 'go mod download all'). +// +// With no arguments, download applies to the modules needed to build and test +// the packages in the main module: the modules explicitly required by the main +// module if it is at 'go 1.17' or higher, or all transitively-required modules +// if at 'go 1.16' or lower. // // The go command will automatically download modules as needed during ordinary // execution. The "go mod download" command is useful mainly for pre-filling @@ -2851,11 +2854,11 @@ // exhaustive tests. // // -shuffle off,on,N -// Randomize the execution order of tests and benchmarks. -// It is off by default. If -shuffle is set to on, then it will seed -// the randomizer using the system clock. If -shuffle is set to an -// integer N, then N will be used as the seed value. In both cases, -// the seed will be reported for reproducibility. +// Randomize the execution order of tests and benchmarks. +// It is off by default. If -shuffle is set to on, then it will seed +// the randomizer using the system clock. If -shuffle is set to an +// integer N, then N will be used as the seed value. In both cases, +// the seed will be reported for reproducibility. // // -timeout d // If a test binary runs longer than duration d, panic. diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go index c13d77a1af..d8bed1dac0 100644 --- a/src/cmd/go/go_test.go +++ b/src/cmd/go/go_test.go @@ -13,6 +13,7 @@ import ( "flag" "fmt" "go/format" + "internal/godebug" "internal/race" "internal/testenv" "io" @@ -2281,7 +2282,7 @@ func TestUpxCompression(t *testing.T) { func TestCacheListStale(t *testing.T) { tooSlow(t) - if strings.Contains(os.Getenv("GODEBUG"), "gocacheverify") { + if godebug.Get("gocacheverify") == "1" { t.Skip("GODEBUG gocacheverify") } tg := testgo(t) @@ -2304,7 +2305,7 @@ func TestCacheListStale(t *testing.T) { func TestCacheCoverage(t *testing.T) { tooSlow(t) - if strings.Contains(os.Getenv("GODEBUG"), "gocacheverify") { + if godebug.Get("gocacheverify") == "1" { t.Skip("GODEBUG gocacheverify") } @@ -2336,7 +2337,7 @@ func TestIssue22588(t *testing.T) { func TestIssue22531(t *testing.T) { tooSlow(t) - if strings.Contains(os.Getenv("GODEBUG"), "gocacheverify") { + if godebug.Get("gocacheverify") == "1" { t.Skip("GODEBUG gocacheverify") } tg := testgo(t) @@ -2365,7 +2366,7 @@ func TestIssue22531(t *testing.T) { func TestIssue22596(t *testing.T) { tooSlow(t) - if strings.Contains(os.Getenv("GODEBUG"), "gocacheverify") { + if godebug.Get("gocacheverify") == "1" { t.Skip("GODEBUG gocacheverify") } tg := testgo(t) @@ -2395,7 +2396,7 @@ func TestIssue22596(t *testing.T) { func TestTestCache(t *testing.T) { tooSlow(t) - if strings.Contains(os.Getenv("GODEBUG"), "gocacheverify") { + if godebug.Get("gocacheverify") == "1" { t.Skip("GODEBUG gocacheverify") } tg := testgo(t) diff --git a/src/cmd/go/internal/modcmd/download.go b/src/cmd/go/internal/modcmd/download.go index 5ea56c34bd..f252133762 100644 --- a/src/cmd/go/internal/modcmd/download.go +++ b/src/cmd/go/internal/modcmd/download.go @@ -16,6 +16,7 @@ import ( "cmd/go/internal/modload" "golang.org/x/mod/module" + "golang.org/x/mod/semver" ) var cmdDownload = &base.Command{ @@ -24,8 +25,11 @@ var cmdDownload = &base.Command{ Long: ` Download downloads the named modules, which can be module patterns selecting dependencies of the main module or module queries of the form path@version. -With no arguments, download applies to all dependencies of the main module -(equivalent to 'go mod download all'). + +With no arguments, download applies to the modules needed to build and test +the packages in the main module: the modules explicitly required by the main +module if it is at 'go 1.17' or higher, or all transitively-required modules +if at 'go 1.16' or lower. The go command will automatically download modules as needed during ordinary execution. The "go mod download" command is useful mainly for pre-filling @@ -87,13 +91,8 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) { // Check whether modules are enabled and whether we're in a module. modload.ForceUseModules = true modload.ExplicitWriteGoMod = true - if !modload.HasModRoot() && len(args) == 0 { - base.Fatalf("go: no modules specified (see 'go help mod download')") - } haveExplicitArgs := len(args) > 0 - if !haveExplicitArgs { - args = []string{"all"} - } + if modload.HasModRoot() { modload.LoadModFile(ctx) // to fill MainModules @@ -102,16 +101,50 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) { } mainModule := modload.MainModules.Versions()[0] - targetAtUpgrade := mainModule.Path + "@upgrade" - targetAtPatch := mainModule.Path + "@patch" - for _, arg := range args { - switch arg { - case mainModule.Path, targetAtUpgrade, targetAtPatch: - os.Stderr.WriteString("go: skipping download of " + arg + " that resolves to the main module\n") + if haveExplicitArgs { + targetAtUpgrade := mainModule.Path + "@upgrade" + targetAtPatch := mainModule.Path + "@patch" + for _, arg := range args { + switch arg { + case mainModule.Path, targetAtUpgrade, targetAtPatch: + os.Stderr.WriteString("go: skipping download of " + arg + " that resolves to the main module\n") + } + } + } else { + modFile := modload.MainModules.ModFile(mainModule) + if modFile.Go == nil || semver.Compare("v"+modFile.Go.Version, modload.ExplicitIndirectVersionV) < 0 { + if len(modFile.Require) > 0 { + args = []string{"all"} + } + } else { + // As of Go 1.17, the go.mod file explicitly requires every module + // that provides any package imported by the main module. + // 'go mod download' is typically run before testing packages in the + // main module, so by default we shouldn't download the others + // (which are presumed irrelevant to the packages in the main module). + // See https://golang.org/issue/44435. + // + // However, we also need to load the full module graph, to ensure that + // we have downloaded enough of the module graph to run 'go list all', + // 'go mod graph', and similar commands. + _ = modload.LoadModGraph(ctx, "") + + for _, m := range modFile.Require { + args = append(args, m.Mod.Path) + } } } } + if len(args) == 0 { + if modload.HasModRoot() { + os.Stderr.WriteString("go: no module dependencies to download\n") + } else { + base.Errorf("go: no modules specified (see 'go help mod download')") + } + base.Exit() + } + downloadModule := func(m *moduleJSON) { var err error m.Info, err = modfetch.InfoFile(m.Path, m.Version) diff --git a/src/cmd/go/internal/modfetch/coderepo.go b/src/cmd/go/internal/modfetch/coderepo.go index dfef9f73c2..df835c3d7e 100644 --- a/src/cmd/go/internal/modfetch/coderepo.go +++ b/src/cmd/go/internal/modfetch/coderepo.go @@ -567,11 +567,11 @@ func (r *codeRepo) validatePseudoVersion(info *codehost.RevInfo, version string) if rev != info.Short { switch { case strings.HasPrefix(rev, info.Short): - return fmt.Errorf("revision is longer than canonical (%s)", info.Short) + return fmt.Errorf("revision is longer than canonical (expected %s)", info.Short) case strings.HasPrefix(info.Short, rev): - return fmt.Errorf("revision is shorter than canonical (%s)", info.Short) + return fmt.Errorf("revision is shorter than canonical (expected %s)", info.Short) default: - return fmt.Errorf("does not match short name of revision (%s)", info.Short) + return fmt.Errorf("does not match short name of revision (expected %s)", info.Short) } } diff --git a/src/cmd/go/internal/modload/buildlist.go b/src/cmd/go/internal/modload/buildlist.go index 4634ad009d..27cab0b9c8 100644 --- a/src/cmd/go/internal/modload/buildlist.go +++ b/src/cmd/go/internal/modload/buildlist.go @@ -236,7 +236,7 @@ func (rs *Requirements) IsDirect(path string) bool { // A ModuleGraph represents the complete graph of module dependencies // of a main module. // -// If the main module is lazily loaded, the graph does not include +// If the main module supports module graph pruning, the graph does not include // transitive dependencies of non-root (implicit) dependencies. type ModuleGraph struct { g *mvs.Graph diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go index 0602aee0cc..9aef5a7c33 100644 --- a/src/cmd/go/internal/modload/init.go +++ b/src/cmd/go/internal/modload/init.go @@ -968,7 +968,7 @@ func makeMainModules(ms []module.Version, rootDirs []string, modFiles []*modfile for _, r := range modFiles[i].Replace { if replacedByWorkFile[r.Old.Path] { continue - } else if prev, ok := replacements[r.Old]; ok && !curModuleReplaces[r.Old] { + } else if prev, ok := replacements[r.Old]; ok && !curModuleReplaces[r.Old] && prev != r.New { base.Fatalf("go: conflicting replacements for %v:\n\t%v\n\t%v\nuse \"go mod editwork -replace %v=[override]\" to resolve", r.Old, prev, r.New, r.Old) } curModuleReplaces[r.Old] = true diff --git a/src/cmd/go/internal/modload/modfile.go b/src/cmd/go/internal/modload/modfile.go index 87e8a5e83d..a7e92222a1 100644 --- a/src/cmd/go/internal/modload/modfile.go +++ b/src/cmd/go/internal/modload/modfile.go @@ -33,13 +33,13 @@ const ( // tests outside of the main module. narrowAllVersionV = "v1.16" - // explicitIndirectVersionV is the Go version (plus leading "v") at which a + // ExplicitIndirectVersionV is the Go version (plus leading "v") at which a // module's go.mod file is expected to list explicit requirements on every // module that provides any package transitively imported by that module. // // Other indirect dependencies of such a module can be safely pruned out of // the module graph; see https://golang.org/ref/mod#graph-pruning. - explicitIndirectVersionV = "v1.17" + ExplicitIndirectVersionV = "v1.17" // separateIndirectVersionV is the Go version (plus leading "v") at which // "// indirect" dependencies are added in a block separate from the direct @@ -123,7 +123,7 @@ const ( ) func pruningForGoVersion(goVersion string) modPruning { - if semver.Compare("v"+goVersion, explicitIndirectVersionV) < 0 { + if semver.Compare("v"+goVersion, ExplicitIndirectVersionV) < 0 { // The go.mod file does not duplicate relevant information about transitive // dependencies, so they cannot be pruned out. return unpruned @@ -378,7 +378,7 @@ func canonicalizeReplacePath(r module.Version, modRoot string) module.Version { return r } abs := filepath.Join(modRoot, r.Path) - if rel, err := filepath.Rel(workFilePath, abs); err == nil { + if rel, err := filepath.Rel(filepath.Dir(workFilePath), abs); err == nil { return module.Version{Path: rel, Version: r.Version} } // We couldn't make the version's path relative to the workspace's path, diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index cfb0a1465f..7361c11786 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -307,11 +307,11 @@ control the execution of any test: exhaustive tests. -shuffle off,on,N - Randomize the execution order of tests and benchmarks. - It is off by default. If -shuffle is set to on, then it will seed - the randomizer using the system clock. If -shuffle is set to an - integer N, then N will be used as the seed value. In both cases, - the seed will be reported for reproducibility. + Randomize the execution order of tests and benchmarks. + It is off by default. If -shuffle is set to on, then it will seed + the randomizer using the system clock. If -shuffle is set to an + integer N, then N will be used as the seed value. In both cases, + the seed will be reported for reproducibility. -timeout d If a test binary runs longer than duration d, panic. @@ -666,6 +666,12 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) { if len(pkgs) != 1 { base.Fatalf("cannot use -fuzz flag with multiple packages") } + if testCoverProfile != "" { + base.Fatalf("cannot use -coverprofile flag with -fuzz flag") + } + if profileFlag := testProfile(); profileFlag != "" { + base.Fatalf("cannot use %s flag with -fuzz flag", profileFlag) + } // Reject the '-fuzz' flag if the package is outside the main module. // Otherwise, if fuzzing identifies a failure it could corrupt checksums in @@ -1399,15 +1405,25 @@ func (c *runCache) builderRunTest(b *work.Builder, ctx context.Context, a *work. if bytes.HasPrefix(out, tooManyTargetsToFuzz[1:]) || bytes.Contains(out, tooManyTargetsToFuzz) { norun = " [will not fuzz, -fuzz matches more than one target]" } + if len(out) > 0 && !bytes.HasSuffix(out, []byte("\n")) { + // Ensure that the output ends with a newline before the "ok" + // line we're about to print (https://golang.org/issue/49317). + cmd.Stdout.Write([]byte("\n")) + } fmt.Fprintf(cmd.Stdout, "ok \t%s\t%s%s%s\n", a.Package.ImportPath, t, coveragePercentage(out), norun) c.saveOutput(a) } else { base.SetExitStatus(1) - // If there was test output, assume we don't need to print the exit status. - // Buf there's no test output, do print the exit status. if len(out) == 0 { + // If there was no test output, print the exit status so that the reason + // for failure is clear. fmt.Fprintf(cmd.Stdout, "%s\n", err) + } else if !bytes.HasSuffix(out, []byte("\n")) { + // Otherwise, ensure that the output ends with a newline before the FAIL + // line we're about to print (https://golang.org/issue/49317). + cmd.Stdout.Write([]byte("\n")) } + // NOTE(golang.org/issue/37555): test2json reports that a test passes // unless "FAIL" is printed at the beginning of a line. The test may not // actually print that if it panics, exits, or terminates abnormally, diff --git a/src/cmd/go/testdata/script/gcflags_patterns.txt b/src/cmd/go/testdata/script/gcflags_patterns.txt index 5b81e9481a..24ec5aa11b 100644 --- a/src/cmd/go/testdata/script/gcflags_patterns.txt +++ b/src/cmd/go/testdata/script/gcflags_patterns.txt @@ -58,8 +58,7 @@ go build -n -ldflags=-X=math.pi=3 stderr 'link.* -X=math.pi=3' # -ldflags applies to current directory even if GOPATH is funny -[windows] cd $WORK/GoPath/src/my/cmd/prog -[darwin] cd $WORK/GoPath/src/my/cmd/prog +[!case-sensitive] cd $WORK/GoPath/src/my/cmd/prog go build -n -ldflags=-X=math.pi=3 stderr 'link.* -X=math.pi=3' diff --git a/src/cmd/go/testdata/script/mod_download.txt b/src/cmd/go/testdata/script/mod_download.txt index 89e58a2cfd..154e68338b 100644 --- a/src/cmd/go/testdata/script/mod_download.txt +++ b/src/cmd/go/testdata/script/mod_download.txt @@ -128,6 +128,50 @@ rm go.sum go mod download all cmp go.mod.update go.mod grep '^rsc.io/sampler v1.3.0 ' go.sum + +# https://golang.org/issue/44435: At go 1.17 or higher, 'go mod download' +# (without arguments) should only download the modules explicitly required in +# the go.mod file, not (presumed-irrelevant) transitive dependencies. +# +# (If the go.mod file is inconsistent, the version downloaded should be the +# selected version from the broader graph, but the go.mod file will also be +# updated to list the correct versions. If at some point we change 'go mod +# download' to stop updating for consistency, then it should fail if the +# requirements are inconsistent.) + +rm go.sum +cp go.mod.orig go.mod +go mod edit -go=1.17 +cp go.mod.update go.mod.go117 +go mod edit -go=1.17 go.mod.go117 + +go clean -modcache +go mod download +cmp go.mod go.mod.go117 + +go list -e -m all +stdout '^rsc.io/quote v1.5.2$' +exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.zip +stdout '^rsc.io/sampler v1.3.0$' +! exists $GOPATH/pkg/mod/cache/download/rsc.io/sampler/@v/v1.2.1.zip +exists $GOPATH/pkg/mod/cache/download/rsc.io/sampler/@v/v1.3.0.zip +stdout '^golang\.org/x/text v0.0.0-20170915032832-14c0d48ead0c$' +! exists $GOPATH/pkg/mod/cache/download/golang.org/x/text/@v/v0.0.0-20170915032832-14c0d48ead0c.zip +cmp go.mod go.mod.go117 + +# However, 'go mod download all' continues to download the selected version +# of every module reported by 'go list -m all'. + +cp go.mod.orig go.mod +go mod edit -go=1.17 +go clean -modcache +go mod download all +exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.zip +! exists $GOPATH/pkg/mod/cache/download/rsc.io/sampler/@v/v1.2.1.zip +exists $GOPATH/pkg/mod/cache/download/rsc.io/sampler/@v/v1.3.0.zip +exists $GOPATH/pkg/mod/cache/download/golang.org/x/text/@v/v0.0.0-20170915032832-14c0d48ead0c.zip +cmp go.mod go.mod.go117 + cd .. # allow go mod download without go.mod diff --git a/src/cmd/go/testdata/script/mod_invalid_version.txt b/src/cmd/go/testdata/script/mod_invalid_version.txt index f9317b676d..428b8aa60e 100644 --- a/src/cmd/go/testdata/script/mod_invalid_version.txt +++ b/src/cmd/go/testdata/script/mod_invalid_version.txt @@ -57,20 +57,20 @@ cp go.mod.orig go.mod go mod edit -require golang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0 cd outside ! go list -m golang.org/x/text -stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0: invalid pseudo-version: revision is shorter than canonical \(14c0d48ead0c\)' +stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0: invalid pseudo-version: revision is shorter than canonical \(expected 14c0d48ead0c\)' cd .. ! go list -m golang.org/x/text -stderr 'golang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0: invalid pseudo-version: revision is shorter than canonical \(14c0d48ead0c\)' +stderr 'golang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0: invalid pseudo-version: revision is shorter than canonical \(expected 14c0d48ead0c\)' # A pseudo-version with more than 12 digits of SHA-1 prefix is invalid. cp go.mod.orig go.mod go mod edit -require golang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0cd47e3104ada247d91be04afc7a5a cd outside ! go list -m golang.org/x/text -stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0cd47e3104ada247d91be04afc7a5a: invalid pseudo-version: revision is longer than canonical \(14c0d48ead0c\)' +stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0cd47e3104ada247d91be04afc7a5a: invalid pseudo-version: revision is longer than canonical \(expected 14c0d48ead0c\)' cd .. ! go list -m golang.org/x/text -stderr 'golang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0cd47e3104ada247d91be04afc7a5a: invalid pseudo-version: revision is longer than canonical \(14c0d48ead0c\)' +stderr 'golang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0cd47e3104ada247d91be04afc7a5a: invalid pseudo-version: revision is longer than canonical \(expected 14c0d48ead0c\)' # A pseudo-version that does not match the commit timestamp is invalid. cp go.mod.orig go.mod diff --git a/src/cmd/go/testdata/script/test_fail_newline.txt b/src/cmd/go/testdata/script/test_fail_newline.txt new file mode 100644 index 0000000000..43cee565a1 --- /dev/null +++ b/src/cmd/go/testdata/script/test_fail_newline.txt @@ -0,0 +1,65 @@ +[short] skip + +# In package list mode, output is buffered. +# Check that a newline is printed after the buffer's contents. +cd fail +! go test . +! stderr . +stdout '^exitcode=1\n' +stdout '^FAIL\s+example/fail' + +# In local directory mode output is streamed, so we don't know +# whether the test printed anything at all, so we print the exit code +# (just in case it failed without emitting any output at all), +# and that happens to add the needed newline as well. +! go test +! stderr . +stdout '^exitcode=1exit status 1\n' +stdout '^FAIL\s+example/fail' + +# In package list mode, if the test passes the 'ok' message appears +# on its own line. +cd ../skip +go test -v . +! stderr . +stdout '^skipping\n' +stdout '^ok\s+example/skip' + +# If the output is streamed and the test passes, we can't tell whether it ended +# in a partial line, and don't want to emit any extra output in the +# overwhelmingly common case that it did not. +# (In theory we could hook the 'os' package to report whether output +# was emitted and whether it ended in a newline, but that seems too invasive.) +go test +! stderr . +stdout '^skippingok\s+example/skip' + + +-- go.mod -- +module example + +go 1.18 +-- fail/fail_test.go -- +package fail + +import ( + "os" + "testing" +) + +func TestMain(m *testing.M) { + os.Stderr.WriteString("exitcode=1") + os.Exit(1) +} +-- skip/skip_test.go -- +package skip + +import ( + "os" + "testing" +) + +func TestMain(m *testing.M) { + os.Stderr.WriteString("skipping") + os.Exit(0) +} diff --git a/src/cmd/go/testdata/script/test_fuzz.txt b/src/cmd/go/testdata/script/test_fuzz.txt index 020012d73e..150491be04 100644 --- a/src/cmd/go/testdata/script/test_fuzz.txt +++ b/src/cmd/go/testdata/script/test_fuzz.txt @@ -152,6 +152,7 @@ stdout FAIL # Test that the wrong type given with f.Add will fail. ! go test -run FuzzWrongType fuzz_add_test.go ! stdout ^ok +stdout '\[string int\], want \[\[\]uint8 int8\]' stdout FAIL # Test fatal with testdata seed corpus @@ -435,8 +436,8 @@ func FuzzAddDifferentType(f *testing.F) { } func FuzzWrongType(f *testing.F) { - f.Add("hello") - f.Fuzz(func(*testing.T, []byte) {}) + f.Add("hello", 50) + f.Fuzz(func(*testing.T, []byte, int8) {}) } -- corpustesting/fuzz_testdata_corpus_test.go -- diff --git a/src/cmd/go/testdata/script/test_fuzz_profile_flags.txt b/src/cmd/go/testdata/script/test_fuzz_profile_flags.txt new file mode 100644 index 0000000000..5434c723ad --- /dev/null +++ b/src/cmd/go/testdata/script/test_fuzz_profile_flags.txt @@ -0,0 +1,38 @@ +[!fuzz] skip + +! go test -fuzz=FuzzTrivial -coverprofile=prof +! stdout . +stderr '^cannot use -coverprofile flag with -fuzz flag$' + +! go test -fuzz=FuzzTrivial -blockprofile=prof +! stdout . +stderr '^cannot use -blockprofile flag with -fuzz flag$' + +! go test -fuzz=FuzzTrivial -cpuprofile=prof +! stdout . +stderr '^cannot use -cpuprofile flag with -fuzz flag$' + +! go test -fuzz=FuzzTrivial -memprofile=prof +! stdout . +stderr '^cannot use -memprofile flag with -fuzz flag$' + +! go test -fuzz=FuzzTrivial -mutexprofile=prof +! stdout . +stderr '^cannot use -mutexprofile flag with -fuzz flag$' + +! go test -fuzz=FuzzTrivial -trace=prof +! stdout . +stderr '^cannot use -trace flag with -fuzz flag$' + +-- go.mod -- +module example + +go 1.18 +-- fuzz_test.go -- +package example + +import "testing" + +func FuzzTrivial(f *testing.F) { + f.Fuzz(func(t *testing.T, _ []byte) {}) +} diff --git a/src/cmd/internal/obj/arm/obj5.go b/src/cmd/internal/obj/arm/obj5.go index 1454d8a7c9..38aa11cde9 100644 --- a/src/cmd/internal/obj/arm/obj5.go +++ b/src/cmd/internal/obj/arm/obj5.go @@ -634,6 +634,61 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { } func (c *ctxt5) stacksplit(p *obj.Prog, framesize int32) *obj.Prog { + if c.ctxt.Flag_maymorestack != "" { + // Save LR and make room for REGCTXT. + const frameSize = 8 + // MOVW.W R14,$-8(SP) + p = obj.Appendp(p, c.newprog) + p.As = AMOVW + p.Scond |= C_WBIT + p.From.Type = obj.TYPE_REG + p.From.Reg = REGLINK + p.To.Type = obj.TYPE_MEM + p.To.Offset = -frameSize + p.To.Reg = REGSP + p.Spadj = frameSize + + // MOVW REGCTXT, 4(SP) + p = obj.Appendp(p, c.newprog) + p.As = AMOVW + p.From.Type = obj.TYPE_REG + p.From.Reg = REGCTXT + p.To.Type = obj.TYPE_MEM + p.To.Offset = 4 + p.To.Reg = REGSP + + // CALL maymorestack + p = obj.Appendp(p, c.newprog) + p.As = obj.ACALL + p.To.Type = obj.TYPE_BRANCH + // See ../x86/obj6.go + p.To.Sym = c.ctxt.LookupABI(c.ctxt.Flag_maymorestack, c.cursym.ABI()) + + // Restore REGCTXT and LR. + + // MOVW 4(SP), REGCTXT + p = obj.Appendp(p, c.newprog) + p.As = AMOVW + p.From.Type = obj.TYPE_MEM + p.From.Offset = 4 + p.From.Reg = REGSP + p.To.Type = obj.TYPE_REG + p.To.Reg = REGCTXT + + // MOVW.P 8(SP), R14 + p.As = AMOVW + p.Scond |= C_PBIT + p.From.Type = obj.TYPE_MEM + p.From.Offset = frameSize + p.From.Reg = REGSP + p.To.Type = obj.TYPE_REG + p.To.Reg = REGLINK + p.Spadj = -frameSize + } + + // Jump back to here after morestack returns. + startPred := p + // MOVW g_stackguard(g), R1 p = obj.Appendp(p, c.newprog) @@ -761,7 +816,7 @@ func (c *ctxt5) stacksplit(p *obj.Prog, framesize int32) *obj.Prog { b := obj.Appendp(pcdata, c.newprog) b.As = obj.AJMP b.To.Type = obj.TYPE_BRANCH - b.To.SetTarget(c.cursym.Func().Text.Link) + b.To.SetTarget(startPred.Link) b.Spadj = +framesize return end diff --git a/src/cmd/internal/obj/arm64/obj7.go b/src/cmd/internal/obj/arm64/obj7.go index ae8deede3a..e9eb786cb2 100644 --- a/src/cmd/internal/obj/arm64/obj7.go +++ b/src/cmd/internal/obj/arm64/obj7.go @@ -58,6 +58,91 @@ var noZRreplace = map[obj.As]bool{ } func (c *ctxt7) stacksplit(p *obj.Prog, framesize int32) *obj.Prog { + if c.ctxt.Flag_maymorestack != "" { + p = c.cursym.Func().SpillRegisterArgs(p, c.newprog) + + // Save LR and make room for FP, REGCTXT. Leave room + // for caller's saved FP. + const frameSize = 32 + p = obj.Appendp(p, c.newprog) + p.As = AMOVD + p.From.Type = obj.TYPE_REG + p.From.Reg = REGLINK + p.To.Type = obj.TYPE_MEM + p.Scond = C_XPRE + p.To.Offset = -frameSize + p.To.Reg = REGSP + p.Spadj = frameSize + + // Save FP. + p = obj.Appendp(p, c.newprog) + p.As = AMOVD + p.From.Type = obj.TYPE_REG + p.From.Reg = REGFP + p.To.Type = obj.TYPE_MEM + p.To.Reg = REGSP + p.To.Offset = -8 + + p = obj.Appendp(p, c.newprog) + p.As = ASUB + p.From.Type = obj.TYPE_CONST + p.From.Offset = 8 + p.Reg = REGSP + p.To.Type = obj.TYPE_REG + p.To.Reg = REGFP + + // Save REGCTXT (for simplicity we do this whether or + // not we need it.) + p = obj.Appendp(p, c.newprog) + p.As = AMOVD + p.From.Type = obj.TYPE_REG + p.From.Reg = REGCTXT + p.To.Type = obj.TYPE_MEM + p.To.Reg = REGSP + p.To.Offset = 8 + + // BL maymorestack + p = obj.Appendp(p, c.newprog) + p.As = ABL + p.To.Type = obj.TYPE_BRANCH + // See ../x86/obj6.go + p.To.Sym = c.ctxt.LookupABI(c.ctxt.Flag_maymorestack, c.cursym.ABI()) + + // Restore REGCTXT. + p = obj.Appendp(p, c.newprog) + p.As = AMOVD + p.From.Type = obj.TYPE_MEM + p.From.Reg = REGSP + p.From.Offset = 8 + p.To.Type = obj.TYPE_REG + p.To.Reg = REGCTXT + + // Restore FP. + p = obj.Appendp(p, c.newprog) + p.As = AMOVD + p.From.Type = obj.TYPE_MEM + p.From.Reg = REGSP + p.From.Offset = -8 + p.To.Type = obj.TYPE_REG + p.To.Reg = REGFP + + // Restore LR and SP. + p = obj.Appendp(p, c.newprog) + p.As = AMOVD + p.From.Type = obj.TYPE_MEM + p.Scond = C_XPOST + p.From.Offset = frameSize + p.From.Reg = REGSP + p.To.Type = obj.TYPE_REG + p.To.Reg = REGLINK + p.Spadj = -frameSize + + p = c.cursym.Func().UnspillRegisterArgs(p, c.newprog) + } + + // Jump back to here after morestack returns. + startPred := p + // MOV g_stackguard(g), RT1 p = obj.Appendp(p, c.newprog) @@ -212,7 +297,7 @@ func (c *ctxt7) stacksplit(p *obj.Prog, framesize int32) *obj.Prog { jmp := obj.Appendp(pcdata, c.newprog) jmp.As = AB jmp.To.Type = obj.TYPE_BRANCH - jmp.To.SetTarget(c.cursym.Func().Text.Link) + jmp.To.SetTarget(startPred.Link) jmp.Spadj = +framesize return end diff --git a/src/cmd/internal/obj/link.go b/src/cmd/internal/obj/link.go index 4bcfb05a5e..11af143f22 100644 --- a/src/cmd/internal/obj/link.go +++ b/src/cmd/internal/obj/link.go @@ -880,7 +880,8 @@ type Link struct { Flag_linkshared bool Flag_optimize bool Flag_locationlists bool - Retpoline bool // emit use of retpoline stubs for indirect jmp/call + Retpoline bool // emit use of retpoline stubs for indirect jmp/call + Flag_maymorestack string // If not "", call this function before stack checks Bso *bufio.Writer Pathname string Pkgpath string // the current package's import path, "" if unknown diff --git a/src/cmd/internal/obj/mips/obj0.go b/src/cmd/internal/obj/mips/obj0.go index 1f31d0c4cd..9e2ccc1929 100644 --- a/src/cmd/internal/obj/mips/obj0.go +++ b/src/cmd/internal/obj/mips/obj0.go @@ -658,6 +658,82 @@ func (c *ctxt0) stacksplit(p *obj.Prog, framesize int32) *obj.Prog { mov = AMOVW } + if c.ctxt.Flag_maymorestack != "" { + // Save LR and REGCTXT. + frameSize := 2 * c.ctxt.Arch.PtrSize + + p = c.ctxt.StartUnsafePoint(p, c.newprog) + + // MOV REGLINK, -8/-16(SP) + p = obj.Appendp(p, c.newprog) + p.As = mov + p.From.Type = obj.TYPE_REG + p.From.Reg = REGLINK + p.To.Type = obj.TYPE_MEM + p.To.Offset = int64(-frameSize) + p.To.Reg = REGSP + + // MOV REGCTXT, -4/-8(SP) + p = obj.Appendp(p, c.newprog) + p.As = mov + p.From.Type = obj.TYPE_REG + p.From.Reg = REGCTXT + p.To.Type = obj.TYPE_MEM + p.To.Offset = -int64(c.ctxt.Arch.PtrSize) + p.To.Reg = REGSP + + // ADD $-8/$-16, SP + p = obj.Appendp(p, c.newprog) + p.As = add + p.From.Type = obj.TYPE_CONST + p.From.Offset = int64(-frameSize) + p.To.Type = obj.TYPE_REG + p.To.Reg = REGSP + p.Spadj = int32(frameSize) + + // JAL maymorestack + p = obj.Appendp(p, c.newprog) + p.As = AJAL + p.To.Type = obj.TYPE_BRANCH + // See ../x86/obj6.go + p.To.Sym = c.ctxt.LookupABI(c.ctxt.Flag_maymorestack, c.cursym.ABI()) + p.Mark |= BRANCH + + // Restore LR and REGCTXT. + + // MOV 0(SP), REGLINK + p = obj.Appendp(p, c.newprog) + p.As = mov + p.From.Type = obj.TYPE_MEM + p.From.Offset = 0 + p.From.Reg = REGSP + p.To.Type = obj.TYPE_REG + p.To.Reg = REGLINK + + // MOV 4/8(SP), REGCTXT + p = obj.Appendp(p, c.newprog) + p.As = mov + p.From.Type = obj.TYPE_MEM + p.From.Offset = int64(c.ctxt.Arch.PtrSize) + p.From.Reg = REGSP + p.To.Type = obj.TYPE_REG + p.To.Reg = REGCTXT + + // ADD $8/$16, SP + p = obj.Appendp(p, c.newprog) + p.As = add + p.From.Type = obj.TYPE_CONST + p.From.Offset = int64(frameSize) + p.To.Type = obj.TYPE_REG + p.To.Reg = REGSP + p.Spadj = int32(-frameSize) + + p = c.ctxt.EndUnsafePoint(p, c.newprog, -1) + } + + // Jump back to here after morestack returns. + startPred := p + // MOV g_stackguard(g), R1 p = obj.Appendp(p, c.newprog) @@ -787,7 +863,8 @@ func (c *ctxt0) stacksplit(p *obj.Prog, framesize int32) *obj.Prog { p.As = AJMP p.To.Type = obj.TYPE_BRANCH - p.To.SetTarget(c.cursym.Func().Text.Link) + p.To.SetTarget(startPred.Link) + startPred.Link.Mark |= LABEL p.Mark |= BRANCH // placeholder for q1's jump target diff --git a/src/cmd/internal/obj/ppc64/obj9.go b/src/cmd/internal/obj/ppc64/obj9.go index ee93fe048b..7ac6465a72 100644 --- a/src/cmd/internal/obj/ppc64/obj9.go +++ b/src/cmd/internal/obj/ppc64/obj9.go @@ -1048,7 +1048,96 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { } */ func (c *ctxt9) stacksplit(p *obj.Prog, framesize int32) *obj.Prog { - p0 := p // save entry point, but skipping the two instructions setting R2 in shared mode + if c.ctxt.Flag_maymorestack != "" { + if c.ctxt.Flag_shared || c.ctxt.Flag_dynlink { + // See the call to morestack for why these are + // complicated to support. + c.ctxt.Diag("maymorestack with -shared or -dynlink is not supported") + } + + // Spill arguments. This has to happen before we open + // any more frame space. + p = c.cursym.Func().SpillRegisterArgs(p, c.newprog) + + // Save LR and REGCTXT + frameSize := 8 + c.ctxt.FixedFrameSize() + + // MOVD LR, REGTMP + p = obj.Appendp(p, c.newprog) + p.As = AMOVD + p.From.Type = obj.TYPE_REG + p.From.Reg = REG_LR + p.To.Type = obj.TYPE_REG + p.To.Reg = REGTMP + // MOVDU REGTMP, -16(SP) + p = obj.Appendp(p, c.newprog) + p.As = AMOVDU + p.From.Type = obj.TYPE_REG + p.From.Reg = REGTMP + p.To.Type = obj.TYPE_MEM + p.To.Offset = -frameSize + p.To.Reg = REGSP + p.Spadj = int32(frameSize) + + // MOVD REGCTXT, 8(SP) + p = obj.Appendp(p, c.newprog) + p.As = AMOVD + p.From.Type = obj.TYPE_REG + p.From.Reg = REGCTXT + p.To.Type = obj.TYPE_MEM + p.To.Offset = 8 + p.To.Reg = REGSP + + // BL maymorestack + p = obj.Appendp(p, c.newprog) + p.As = ABL + p.To.Type = obj.TYPE_BRANCH + // See ../x86/obj6.go + p.To.Sym = c.ctxt.LookupABI(c.ctxt.Flag_maymorestack, c.cursym.ABI()) + + // Restore LR and REGCTXT + + // MOVD 8(SP), REGCTXT + p = obj.Appendp(p, c.newprog) + p.As = AMOVD + p.From.Type = obj.TYPE_MEM + p.From.Offset = 8 + p.From.Reg = REGSP + p.To.Type = obj.TYPE_REG + p.To.Reg = REGCTXT + + // MOVD 0(SP), REGTMP + p = obj.Appendp(p, c.newprog) + p.As = AMOVD + p.From.Type = obj.TYPE_MEM + p.From.Offset = 0 + p.From.Reg = REGSP + p.To.Type = obj.TYPE_REG + p.To.Reg = REGTMP + + // MOVD REGTMP, LR + p = obj.Appendp(p, c.newprog) + p.As = AMOVD + p.From.Type = obj.TYPE_REG + p.From.Reg = REGTMP + p.To.Type = obj.TYPE_REG + p.To.Reg = REG_LR + + // ADD $16, SP + p = obj.Appendp(p, c.newprog) + p.As = AADD + p.From.Type = obj.TYPE_CONST + p.From.Offset = frameSize + p.To.Type = obj.TYPE_REG + p.To.Reg = REGSP + p.Spadj = -int32(frameSize) + + // Unspill arguments. + p = c.cursym.Func().UnspillRegisterArgs(p, c.newprog) + } + + // save entry point, but skipping the two instructions setting R2 in shared mode and maymorestack + startPred := p // MOVD g_stackguard(g), R22 p = obj.Appendp(p, c.newprog) @@ -1262,7 +1351,7 @@ func (c *ctxt9) stacksplit(p *obj.Prog, framesize int32) *obj.Prog { p = obj.Appendp(p, c.newprog) p.As = ABR p.To.Type = obj.TYPE_BRANCH - p.To.SetTarget(p0.Link) + p.To.SetTarget(startPred.Link) // placeholder for q1's jump target p = obj.Appendp(p, c.newprog) diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go index c27ad99b2d..5755b118db 100644 --- a/src/cmd/internal/obj/riscv/obj.go +++ b/src/cmd/internal/obj/riscv/obj.go @@ -722,6 +722,62 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, cursym *obj.LSym, newprog obj.ProgA return p } + if ctxt.Flag_maymorestack != "" { + // Save LR and REGCTXT + const frameSize = 16 + p = ctxt.StartUnsafePoint(p, newprog) + // MOV LR, -16(SP) + p = obj.Appendp(p, newprog) + p.As = AMOV + p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR} + p.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: -frameSize} + // ADDI $-16, SP + p = obj.Appendp(p, newprog) + p.As = AADDI + p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: -frameSize} + p.Reg = REG_SP + p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_SP} + p.Spadj = frameSize + // MOV REGCTXT, 8(SP) + p = obj.Appendp(p, newprog) + p.As = AMOV + p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_CTXT} + p.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: 8} + + // CALL maymorestack + p = obj.Appendp(p, newprog) + p.As = obj.ACALL + p.To.Type = obj.TYPE_BRANCH + // See ../x86/obj6.go + p.To.Sym = ctxt.LookupABI(ctxt.Flag_maymorestack, cursym.ABI()) + jalToSym(ctxt, p, REG_X5) + + // Restore LR and REGCTXT + + // MOV 8(SP), REGCTXT + p = obj.Appendp(p, newprog) + p.As = AMOV + p.From = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: 8} + p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_CTXT} + // MOV (SP), LR + p = obj.Appendp(p, newprog) + p.As = AMOV + p.From = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: 0} + p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR} + // ADDI $16, SP + p = obj.Appendp(p, newprog) + p.As = AADDI + p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: frameSize} + p.Reg = REG_SP + p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_SP} + p.Spadj = -frameSize + + p = ctxt.EndUnsafePoint(p, newprog, -1) + } + + // Jump back to here after morestack returns. + startPred := p + // MOV g_stackguard(g), X10 p = obj.Appendp(p, newprog) p.As = AMOV @@ -821,7 +877,7 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, cursym *obj.LSym, newprog obj.ProgA p.As = AJAL p.To = obj.Addr{Type: obj.TYPE_BRANCH} p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_ZERO} - p.To.SetTarget(cursym.Func().Text.Link) + p.To.SetTarget(startPred.Link) // placeholder for to_done's jump target p = obj.Appendp(p, newprog) diff --git a/src/cmd/internal/obj/s390x/objz.go b/src/cmd/internal/obj/s390x/objz.go index 201163b015..de40ff05af 100644 --- a/src/cmd/internal/obj/s390x/objz.go +++ b/src/cmd/internal/obj/s390x/objz.go @@ -294,6 +294,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { var pLast *obj.Prog var pPre *obj.Prog var pPreempt *obj.Prog + var pCheck *obj.Prog wasSplit := false for p := c.cursym.Func().Text; p != nil; p = p.Link { pLast = p @@ -323,7 +324,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { q := p if !p.From.Sym.NoSplit() { - p, pPreempt = c.stacksplitPre(p, autosize) // emit pre part of split check + p, pPreempt, pCheck = c.stacksplitPre(p, autosize) // emit pre part of split check pPre = p p = c.ctxt.EndUnsafePoint(p, c.newprog, -1) wasSplit = true //need post part of split @@ -563,14 +564,69 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { } } if wasSplit { - c.stacksplitPost(pLast, pPre, pPreempt, autosize) // emit post part of split check + c.stacksplitPost(pLast, pPre, pPreempt, pCheck, autosize) // emit post part of split check } } -func (c *ctxtz) stacksplitPre(p *obj.Prog, framesize int32) (*obj.Prog, *obj.Prog) { +// stacksplitPre generates the function stack check prologue following +// Prog p (which should be the TEXT Prog). It returns one or two +// branch Progs that must be patched to jump to the morestack epilogue, +// and the Prog that starts the morestack check. +func (c *ctxtz) stacksplitPre(p *obj.Prog, framesize int32) (pPre, pPreempt, pCheck *obj.Prog) { + if c.ctxt.Flag_maymorestack != "" { + // Save LR and REGCTXT + const frameSize = 16 + p = c.ctxt.StartUnsafePoint(p, c.newprog) + // MOVD LR, -16(SP) + p = obj.Appendp(p, c.newprog) + p.As = AMOVD + p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR} + p.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REGSP, Offset: -frameSize} + // MOVD $-16(SP), SP + p = obj.Appendp(p, c.newprog) + p.As = AMOVD + p.From = obj.Addr{Type: obj.TYPE_ADDR, Offset: -frameSize, Reg: REGSP} + p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REGSP} + p.Spadj = frameSize + // MOVD REGCTXT, 8(SP) + p = obj.Appendp(p, c.newprog) + p.As = AMOVD + p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REGCTXT} + p.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REGSP, Offset: 8} + + // BL maymorestack + p = obj.Appendp(p, c.newprog) + p.As = ABL + // See ../x86/obj6.go + sym := c.ctxt.LookupABI(c.ctxt.Flag_maymorestack, c.cursym.ABI()) + p.To = obj.Addr{Type: obj.TYPE_BRANCH, Sym: sym} + + // Restore LR and REGCTXT + + // MOVD REGCTXT, 8(SP) + p = obj.Appendp(p, c.newprog) + p.As = AMOVD + p.From = obj.Addr{Type: obj.TYPE_MEM, Reg: REGSP, Offset: 8} + p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REGCTXT} + // MOVD (SP), LR + p = obj.Appendp(p, c.newprog) + p.As = AMOVD + p.From = obj.Addr{Type: obj.TYPE_MEM, Reg: REGSP, Offset: 0} + p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR} + // MOVD $16(SP), SP + p = obj.Appendp(p, c.newprog) + p.As = AMOVD + p.From = obj.Addr{Type: obj.TYPE_CONST, Reg: REGSP, Offset: frameSize} + p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REGSP} + p.Spadj = -frameSize + + p = c.ctxt.EndUnsafePoint(p, c.newprog, -1) + } // MOVD g_stackguard(g), R3 p = obj.Appendp(p, c.newprog) + // Jump back to here after morestack returns. + pCheck = p p.As = AMOVD p.From.Type = obj.TYPE_MEM @@ -599,12 +655,11 @@ func (c *ctxtz) stacksplitPre(p *obj.Prog, framesize int32) (*obj.Prog, *obj.Pro p.As = ACMPUBGE p.To.Type = obj.TYPE_BRANCH - return p, nil + return p, nil, pCheck } // large stack: SP-framesize < stackguard-StackSmall - var q *obj.Prog offset := int64(framesize) - objabi.StackSmall if framesize > objabi.StackBig { // Such a large stack we need to protect against underflow. @@ -625,7 +680,7 @@ func (c *ctxtz) stacksplitPre(p *obj.Prog, framesize int32) (*obj.Prog, *obj.Pro p.To.Reg = REG_R4 p = obj.Appendp(p, c.newprog) - q = p + pPreempt = p p.As = ACMPUBLT p.From.Type = obj.TYPE_REG p.From.Reg = REGSP @@ -651,10 +706,16 @@ func (c *ctxtz) stacksplitPre(p *obj.Prog, framesize int32) (*obj.Prog, *obj.Pro p.As = ACMPUBGE p.To.Type = obj.TYPE_BRANCH - return p, q + return p, pPreempt, pCheck } -func (c *ctxtz) stacksplitPost(p *obj.Prog, pPre *obj.Prog, pPreempt *obj.Prog, framesize int32) *obj.Prog { +// stacksplitPost generates the function epilogue that calls morestack +// and returns the new last instruction in the function. +// +// p is the last Prog in the function. pPre and pPreempt, if non-nil, +// are the instructions that branch to the epilogue. This will fill in +// their branch targets. pCheck is the Prog that begins the stack check. +func (c *ctxtz) stacksplitPost(p *obj.Prog, pPre, pPreempt, pCheck *obj.Prog, framesize int32) *obj.Prog { // Now we are at the end of the function, but logically // we are still in function prologue. We need to fix the // SP data and PCDATA. @@ -692,12 +753,12 @@ func (c *ctxtz) stacksplitPost(p *obj.Prog, pPre *obj.Prog, pPreempt *obj.Prog, p = c.ctxt.EndUnsafePoint(p, c.newprog, -1) - // BR start + // BR pCheck p = obj.Appendp(p, c.newprog) p.As = ABR p.To.Type = obj.TYPE_BRANCH - p.To.SetTarget(c.cursym.Func().Text.Link) + p.To.SetTarget(pCheck) return p } diff --git a/src/cmd/internal/obj/wasm/wasmobj.go b/src/cmd/internal/obj/wasm/wasmobj.go index 4d276db678..1c726f77d3 100644 --- a/src/cmd/internal/obj/wasm/wasmobj.go +++ b/src/cmd/internal/obj/wasm/wasmobj.go @@ -243,6 +243,51 @@ func preprocess(ctxt *obj.Link, s *obj.LSym, newprog obj.ProgAlloc) { p.Spadj = int32(framesize) } + needMoreStack := !s.Func().Text.From.Sym.NoSplit() + + // If the maymorestack debug option is enabled, insert the + // call to maymorestack *before* processing resume points so + // we can construct a resume point after maymorestack for + // morestack to resume at. + var pMorestack = s.Func().Text + if needMoreStack && ctxt.Flag_maymorestack != "" { + p := pMorestack + + // Save REGCTXT on the stack. + const tempFrame = 8 + p = appendp(p, AGet, regAddr(REG_SP)) + p = appendp(p, AI32Const, constAddr(tempFrame)) + p = appendp(p, AI32Sub) + p = appendp(p, ASet, regAddr(REG_SP)) + p.Spadj = tempFrame + ctxtp := obj.Addr{ + Type: obj.TYPE_MEM, + Reg: REG_SP, + Offset: 0, + } + p = appendp(p, AMOVD, regAddr(REGCTXT), ctxtp) + + // maymorestack must not itself preempt because we + // don't have full stack information, so this can be + // ACALLNORESUME. + p = appendp(p, ACALLNORESUME, constAddr(0)) + // See ../x86/obj6.go + sym := ctxt.LookupABI(ctxt.Flag_maymorestack, s.ABI()) + p.To = obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_EXTERN, Sym: sym} + + // Restore REGCTXT. + p = appendp(p, AMOVD, ctxtp, regAddr(REGCTXT)) + p = appendp(p, AGet, regAddr(REG_SP)) + p = appendp(p, AI32Const, constAddr(tempFrame)) + p = appendp(p, AI32Add) + p = appendp(p, ASet, regAddr(REG_SP)) + p.Spadj = -tempFrame + + // Add an explicit ARESUMEPOINT after maymorestack for + // morestack to resume at. + pMorestack = appendp(p, ARESUMEPOINT) + } + // Introduce resume points for CALL instructions // and collect other explicit resume points. numResumePoints := 0 @@ -303,8 +348,8 @@ func preprocess(ctxt *obj.Link, s *obj.LSym, newprog obj.ProgAlloc) { tableIdxs = append(tableIdxs, uint64(numResumePoints)) s.Size = pc + 1 - if !s.Func().Text.From.Sym.NoSplit() { - p := s.Func().Text + if needMoreStack { + p := pMorestack if framesize <= objabi.StackSmall { // small stack: SP <= stackguard @@ -341,6 +386,13 @@ func preprocess(ctxt *obj.Link, s *obj.LSym, newprog obj.ProgAlloc) { // TODO(neelance): handle wraparound case p = appendp(p, AIf) + // This CALL does *not* have a resume point after it + // (we already inserted all of the resume points). As + // a result, morestack will resume at the *previous* + // resume point (typically, the beginning of the + // function) and perform the morestack check again. + // This is why we don't need an explicit loop like + // other architectures. p = appendp(p, obj.ACALL, constAddr(0)) if s.Func().Text.From.Sym.NeedCtxt() { p.To = obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_EXTERN, Sym: morestack} diff --git a/src/cmd/internal/obj/x86/obj6.go b/src/cmd/internal/obj/x86/obj6.go index 183ca2ebe9..a82285a0d3 100644 --- a/src/cmd/internal/obj/x86/obj6.go +++ b/src/cmd/internal/obj/x86/obj6.go @@ -644,19 +644,6 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { } } - var regg int16 - if !p.From.Sym.NoSplit() || p.From.Sym.Wrapper() { - if ctxt.Arch.Family == sys.AMD64 && cursym.ABI() == obj.ABIInternal { - regg = REGG // use the g register directly in ABIInternal - } else { - p = obj.Appendp(p, newprog) - regg = REG_CX - if ctxt.Arch.Family == sys.AMD64 { - regg = REGG // == REG_R14 - } - p = load_g(ctxt, p, newprog, regg) // load g into regg - } - } var regEntryTmp0, regEntryTmp1 int16 if ctxt.Arch.Family == sys.AMD64 { regEntryTmp0, regEntryTmp1 = REGENTRYTMP0, REGENTRYTMP1 @@ -664,8 +651,13 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { regEntryTmp0, regEntryTmp1 = REG_BX, REG_DI } - if !cursym.Func().Text.From.Sym.NoSplit() { - p = stacksplit(ctxt, cursym, p, newprog, autoffset, int32(textarg), regg) // emit split check + var regg int16 + if !p.From.Sym.NoSplit() { + // Emit split check and load G register + p, regg = stacksplit(ctxt, cursym, p, newprog, autoffset, int32(textarg)) + } else if p.From.Sym.Wrapper() { + // Load G register for the wrapper code + p, regg = loadG(ctxt, cursym, p, newprog) } // Delve debugger would like the next instruction to be noted as the end of the function prologue. @@ -973,12 +965,21 @@ func indir_cx(ctxt *obj.Link, a *obj.Addr) { a.Reg = REG_CX } -// Append code to p to load g into cx. -// Overwrites p with the first instruction (no first appendp). -// Overwriting p is unusual but it lets use this in both the -// prologue (caller must call appendp first) and in the epilogue. -// Returns last new instruction. -func load_g(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, rg int16) *obj.Prog { +// loadG ensures the G is loaded into a register (either CX or REGG), +// appending instructions to p if necessary. It returns the new last +// instruction and the G register. +func loadG(ctxt *obj.Link, cursym *obj.LSym, p *obj.Prog, newprog obj.ProgAlloc) (*obj.Prog, int16) { + if ctxt.Arch.Family == sys.AMD64 && cursym.ABI() == obj.ABIInternal { + // Use the G register directly in ABIInternal + return p, REGG + } + + var regg int16 = REG_CX + if ctxt.Arch.Family == sys.AMD64 { + regg = REGG // == REG_R14 + } + + p = obj.Appendp(p, newprog) p.As = AMOVQ if ctxt.Arch.PtrSize == 4 { p.As = AMOVL @@ -987,8 +988,9 @@ func load_g(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, rg int16) *obj.P p.From.Reg = REG_TLS p.From.Offset = 0 p.To.Type = obj.TYPE_REG - p.To.Reg = rg + p.To.Reg = regg + // Rewrite TLS instruction if necessary. next := p.Link progedit(ctxt, p, newprog) for p.Link != next { @@ -1000,24 +1002,26 @@ func load_g(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, rg int16) *obj.P p.From.Scale = 2 } - return p + return p, regg } // Append code to p to check for stack split. // Appends to (does not overwrite) p. // Assumes g is in rg. -// Returns last new instruction. -func stacksplit(ctxt *obj.Link, cursym *obj.LSym, p *obj.Prog, newprog obj.ProgAlloc, framesize int32, textarg int32, rg int16) *obj.Prog { +// Returns last new instruction and G register. +func stacksplit(ctxt *obj.Link, cursym *obj.LSym, p *obj.Prog, newprog obj.ProgAlloc, framesize int32, textarg int32) (*obj.Prog, int16) { cmp := ACMPQ lea := ALEAQ mov := AMOVQ sub := ASUBQ + push, pop := APUSHQ, APOPQ if ctxt.Arch.Family == sys.I386 { cmp = ACMPL lea = ALEAL mov = AMOVL sub = ASUBL + push, pop = APUSHL, APOPL } tmp := int16(REG_AX) // use AX for 32-bit @@ -1026,6 +1030,45 @@ func stacksplit(ctxt *obj.Link, cursym *obj.LSym, p *obj.Prog, newprog obj.ProgA tmp = int16(REGENTRYTMP0) } + if ctxt.Flag_maymorestack != "" { + p = cursym.Func().SpillRegisterArgs(p, newprog) + + if cursym.Func().Text.From.Sym.NeedCtxt() { + p = obj.Appendp(p, newprog) + p.As = push + p.From.Type = obj.TYPE_REG + p.From.Reg = REGCTXT + } + + // We call maymorestack with an ABI matching the + // caller's ABI. Since this is the first thing that + // happens in the function, we have to be consistent + // with the caller about CPU state (notably, + // fixed-meaning registers). + + p = obj.Appendp(p, newprog) + p.As = obj.ACALL + p.To.Type = obj.TYPE_BRANCH + p.To.Name = obj.NAME_EXTERN + p.To.Sym = ctxt.LookupABI(ctxt.Flag_maymorestack, cursym.ABI()) + + if cursym.Func().Text.From.Sym.NeedCtxt() { + p = obj.Appendp(p, newprog) + p.As = pop + p.To.Type = obj.TYPE_REG + p.To.Reg = REGCTXT + } + + p = cursym.Func().UnspillRegisterArgs(p, newprog) + } + + // Jump back to here after morestack returns. + startPred := p + + // Load G register + var rg int16 + p, rg = loadG(ctxt, cursym, p, newprog) + var q1 *obj.Prog if framesize <= objabi.StackSmall { // small stack: SP <= stackguard @@ -1171,7 +1214,7 @@ func stacksplit(ctxt *obj.Link, cursym *obj.LSym, p *obj.Prog, newprog obj.ProgA jmp := obj.Appendp(pcdata, newprog) jmp.As = obj.AJMP jmp.To.Type = obj.TYPE_BRANCH - jmp.To.SetTarget(cursym.Func().Text.Link) + jmp.To.SetTarget(startPred.Link) jmp.Spadj = +framesize jls.To.SetTarget(spill) @@ -1179,7 +1222,7 @@ func stacksplit(ctxt *obj.Link, cursym *obj.LSym, p *obj.Prog, newprog obj.ProgA q1.To.SetTarget(spill) } - return end + return end, rg } func isR15(r int16) bool { diff --git a/src/cmd/internal/objabi/flag.go b/src/cmd/internal/objabi/flag.go index e41fc570b0..f75c054fcb 100644 --- a/src/cmd/internal/objabi/flag.go +++ b/src/cmd/internal/objabi/flag.go @@ -13,6 +13,8 @@ import ( "io/ioutil" "log" "os" + "reflect" + "sort" "strconv" "strings" ) @@ -202,3 +204,165 @@ func DecodeArg(arg string) string { } return b.String() } + +type debugField struct { + name string + help string + val interface{} // *int or *string +} + +type DebugFlag struct { + tab map[string]debugField + any *bool + + debugSSA DebugSSA +} + +// A DebugSSA function is called to set a -d ssa/... option. +// If nil, those options are reported as invalid options. +// If DebugSSA returns a non-empty string, that text is reported as a compiler error. +// If phase is "help", it should print usage information and terminate the process. +type DebugSSA func(phase, flag string, val int, valString string) string + +// NewDebugFlag constructs a DebugFlag for the fields of debug, which +// must be a pointer to a struct. +// +// Each field of *debug is a different value, named for the lower-case of the field name. +// Each field must be an int or string and must have a `help` struct tag. +// There may be an "Any bool" field, which will be set if any debug flags are set. +// +// The returned flag takes a comma-separated list of settings. +// Each setting is name=value; for ints, name is short for name=1. +// +// If debugSSA is non-nil, any debug flags of the form ssa/... will be +// passed to debugSSA for processing. +func NewDebugFlag(debug interface{}, debugSSA DebugSSA) *DebugFlag { + flag := &DebugFlag{ + tab: make(map[string]debugField), + debugSSA: debugSSA, + } + + v := reflect.ValueOf(debug).Elem() + t := v.Type() + for i := 0; i < t.NumField(); i++ { + f := t.Field(i) + ptr := v.Field(i).Addr().Interface() + if f.Name == "Any" { + switch ptr := ptr.(type) { + default: + panic("debug.Any must have type bool") + case *bool: + flag.any = ptr + } + continue + } + name := strings.ToLower(f.Name) + help := f.Tag.Get("help") + if help == "" { + panic(fmt.Sprintf("debug.%s is missing help text", f.Name)) + } + switch ptr.(type) { + default: + panic(fmt.Sprintf("debug.%s has invalid type %v (must be int or string)", f.Name, f.Type)) + case *int, *string: + // ok + } + flag.tab[name] = debugField{name, help, ptr} + } + + return flag +} + +func (f *DebugFlag) Set(debugstr string) error { + if debugstr == "" { + return nil + } + if f.any != nil { + *f.any = true + } + for _, name := range strings.Split(debugstr, ",") { + if name == "" { + continue + } + // display help about the debug option itself and quit + if name == "help" { + fmt.Print(debugHelpHeader) + maxLen, names := 0, []string{} + if f.debugSSA != nil { + maxLen = len("ssa/help") + } + for name := range f.tab { + if len(name) > maxLen { + maxLen = len(name) + } + names = append(names, name) + } + sort.Strings(names) + // Indent multi-line help messages. + nl := fmt.Sprintf("\n\t%-*s\t", maxLen, "") + for _, name := range names { + help := f.tab[name].help + fmt.Printf("\t%-*s\t%s\n", maxLen, name, strings.Replace(help, "\n", nl, -1)) + } + if f.debugSSA != nil { + // ssa options have their own help + fmt.Printf("\t%-*s\t%s\n", maxLen, "ssa/help", "print help about SSA debugging") + } + os.Exit(0) + } + + val, valstring, haveInt := 1, "", true + if i := strings.IndexAny(name, "=:"); i >= 0 { + var err error + name, valstring = name[:i], name[i+1:] + val, err = strconv.Atoi(valstring) + if err != nil { + val, haveInt = 1, false + } + } + + if t, ok := f.tab[name]; ok { + switch vp := t.val.(type) { + case nil: + // Ignore + case *string: + *vp = valstring + case *int: + if !haveInt { + log.Fatalf("invalid debug value %v", name) + } + *vp = val + default: + panic("bad debugtab type") + } + } else if f.debugSSA != nil && strings.HasPrefix(name, "ssa/") { + // expect form ssa/phase/flag + // e.g. -d=ssa/generic_cse/time + // _ in phase name also matches space + phase := name[4:] + flag := "debug" // default flag is debug + if i := strings.Index(phase, "/"); i >= 0 { + flag = phase[i+1:] + phase = phase[:i] + } + err := f.debugSSA(phase, flag, val, valstring) + if err != "" { + log.Fatalf(err) + } + } else { + return fmt.Errorf("unknown debug key %s\n", name) + } + } + + return nil +} + +const debugHelpHeader = `usage: -d arg[,arg]* and arg is [=] + + is one of: + +` + +func (f *DebugFlag) String() string { + return "" +} diff --git a/src/cmd/internal/sys/supported.go b/src/cmd/internal/sys/supported.go index 4fa5aa495e..f25aaabddd 100644 --- a/src/cmd/internal/sys/supported.go +++ b/src/cmd/internal/sys/supported.go @@ -36,6 +36,7 @@ func MSanSupported(goos, goarch string) bool { // ASanSupported reports whether goos/goarch supports the address // sanitizer option. +// There is a copy of this function in misc/cgo/testsanitizers/cc_test.go. func ASanSupported(goos, goarch string) bool { switch goos { case "linux": @@ -104,7 +105,7 @@ func BuildModeSupported(compiler, buildmode, goos, goarch string) bool { case "c-shared": switch platform { - case "linux/amd64", "linux/arm", "linux/arm64", "linux/386", "linux/ppc64le", "linux/s390x", + case "linux/amd64", "linux/arm", "linux/arm64", "linux/386", "linux/ppc64le", "linux/riscv64", "linux/s390x", "android/amd64", "android/arm", "android/arm64", "android/386", "freebsd/amd64", "darwin/amd64", "darwin/arm64", @@ -157,7 +158,7 @@ func BuildModeSupported(compiler, buildmode, goos, goarch string) bool { func InternalLinkPIESupported(goos, goarch string) bool { switch goos + "/" + goarch { case "darwin/amd64", "darwin/arm64", - "linux/amd64", "linux/arm64", + "linux/amd64", "linux/arm64", "linux/ppc64le", "android/arm64", "windows-amd64", "windows-386", "windows-arm": return true diff --git a/src/cmd/link/internal/arm64/asm.go b/src/cmd/link/internal/arm64/asm.go index f56c9c1222..abae0f87bc 100644 --- a/src/cmd/link/internal/arm64/asm.go +++ b/src/cmd/link/internal/arm64/asm.go @@ -602,7 +602,7 @@ func pereloc1(arch *sys.Arch, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, rs := r.Xsym rt := r.Type - if r.Xadd != signext21(r.Xadd) { + if rt == objabi.R_ADDRARM64 && r.Xadd != signext21(r.Xadd) { // If the relocation target would overflow the addend, then target // a linker-manufactured label symbol with a smaller addend instead. label := ldr.Lookup(offsetLabelName(ldr, rs, r.Xadd/peRelocLimit*peRelocLimit), ldr.SymVersion(rs)) diff --git a/src/cmd/link/internal/ld/config.go b/src/cmd/link/internal/ld/config.go index 72616ff62f..33ab7c3df3 100644 --- a/src/cmd/link/internal/ld/config.go +++ b/src/cmd/link/internal/ld/config.go @@ -74,7 +74,7 @@ func (mode *BuildMode) Set(s string) error { *mode = BuildModeCArchive case "c-shared": switch buildcfg.GOARCH { - case "386", "amd64", "arm", "arm64", "ppc64le", "s390x": + case "386", "amd64", "arm", "arm64", "ppc64le", "riscv64", "s390x": default: return badmode() } @@ -225,7 +225,8 @@ func mustLinkExternal(ctxt *Link) (res bool, reason string) { return true, "buildmode=c-shared" case BuildModePIE: switch buildcfg.GOOS + "/" + buildcfg.GOARCH { - case "linux/amd64", "linux/arm64", "android/arm64": + case "android/arm64": + case "linux/amd64", "linux/arm64", "linux/ppc64le": case "windows/386", "windows/amd64", "windows/arm", "windows/arm64": case "darwin/amd64", "darwin/arm64": default: diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go index 0513a0d10b..4d85977d43 100644 --- a/src/cmd/link/internal/ld/data.go +++ b/src/cmd/link/internal/ld/data.go @@ -227,6 +227,8 @@ func (st *relocSymState) relocsym(s loader.Sym, P []byte) { // DWARF info between the compiler and linker. continue } + } else if target.IsPPC64() && target.IsPIE() && ldr.SymName(rs) == ".TOC." { + // This is a TOC relative relocation generated from a go object. It is safe to resolve. } else { st.err.errorUnresolved(ldr, s, rs) continue diff --git a/src/cmd/link/internal/ppc64/asm.go b/src/cmd/link/internal/ppc64/asm.go index 9507010603..d2b140b45d 100644 --- a/src/cmd/link/internal/ppc64/asm.go +++ b/src/cmd/link/internal/ppc64/asm.go @@ -321,6 +321,11 @@ func addelfdynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s lo rela.AddUint64(target.Arch, elf.R_INFO(uint32(ldr.SymDynid(targ)), uint32(elf.R_PPC64_ADDR64))) rela.AddUint64(target.Arch, uint64(r.Add())) su.SetRelocType(rIdx, objabi.ElfRelocOffset) // ignore during relocsym + } else if target.IsPIE() && target.IsInternal() { + // For internal linking PIE, this R_ADDR relocation cannot + // be resolved statically. We need to generate a dynamic + // relocation. Let the code below handle it. + break } return true @@ -383,12 +388,94 @@ func addelfdynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s lo } // Handle references to ELF symbols from our own object files. - if targType != sym.SDYNIMPORT { + relocs := ldr.Relocs(s) + r = relocs.At(rIdx) + + switch r.Type() { + case objabi.R_ADDR: + if ldr.SymType(s) == sym.STEXT { + log.Fatalf("R_ADDR relocation in text symbol %s is unsupported\n", ldr.SymName(s)) + } + if target.IsPIE() && target.IsInternal() { + // When internally linking, generate dynamic relocations + // for all typical R_ADDR relocations. The exception + // are those R_ADDR that are created as part of generating + // the dynamic relocations and must be resolved statically. + // + // There are three phases relevant to understanding this: + // + // dodata() // we are here + // address() // symbol address assignment + // reloc() // resolution of static R_ADDR relocs + // + // At this point symbol addresses have not been + // assigned yet (as the final size of the .rela section + // will affect the addresses), and so we cannot write + // the Elf64_Rela.r_offset now. Instead we delay it + // until after the 'address' phase of the linker is + // complete. We do this via Addaddrplus, which creates + // a new R_ADDR relocation which will be resolved in + // the 'reloc' phase. + // + // These synthetic static R_ADDR relocs must be skipped + // now, or else we will be caught in an infinite loop + // of generating synthetic relocs for our synthetic + // relocs. + // + // Furthermore, the rela sections contain dynamic + // relocations with R_ADDR relocations on + // Elf64_Rela.r_offset. This field should contain the + // symbol offset as determined by reloc(), not the + // final dynamically linked address as a dynamic + // relocation would provide. + switch ldr.SymName(s) { + case ".dynsym", ".rela", ".rela.plt", ".got.plt", ".dynamic": + return false + } + } else { + // Either internally linking a static executable, + // in which case we can resolve these relocations + // statically in the 'reloc' phase, or externally + // linking, in which case the relocation will be + // prepared in the 'reloc' phase and passed to the + // external linker in the 'asmb' phase. + if ldr.SymType(s) != sym.SDATA && ldr.SymType(s) != sym.SRODATA { + break + } + } + // Generate R_PPC64_RELATIVE relocations for best + // efficiency in the dynamic linker. + // + // As noted above, symbol addresses have not been + // assigned yet, so we can't generate the final reloc + // entry yet. We ultimately want: + // + // r_offset = s + r.Off + // r_info = R_PPC64_RELATIVE + // r_addend = targ + r.Add + // + // The dynamic linker will set *offset = base address + + // addend. + // + // AddAddrPlus is used for r_offset and r_addend to + // generate new R_ADDR relocations that will update + // these fields in the 'reloc' phase. + rela := ldr.MakeSymbolUpdater(syms.Rela) + rela.AddAddrPlus(target.Arch, s, int64(r.Off())) + if r.Siz() == 8 { + rela.AddUint64(target.Arch, elf.R_INFO(0, uint32(elf.R_PPC64_RELATIVE))) + } else { + ldr.Errorf(s, "unexpected relocation for dynamic symbol %s", ldr.SymName(targ)) + } + rela.AddAddrPlus(target.Arch, targ, int64(r.Add())) + + // Not mark r done here. So we still apply it statically, + // so in the file content we'll also have the right offset + // to the relocation target. So it can be examined statically + // (e.g. go version). return true } - // TODO(austin): Translate our relocations to ELF - return false } @@ -542,35 +629,40 @@ func symtoc(ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) int64 { } // archreloctoc relocates a TOC relative symbol. -// If the symbol pointed by this TOC relative symbol is in .data or .bss, the -// default load instruction can be changed to an addi instruction and the -// symbol address can be used directly. -// This code is for AIX only. func archreloctoc(ldr *loader.Loader, target *ld.Target, syms *ld.ArchSyms, r loader.Reloc, s loader.Sym, val int64) int64 { rs := r.Sym() - if target.IsLinux() { - ldr.Errorf(s, "archrelocaddr called for %s relocation\n", ldr.SymName(rs)) - } var o1, o2 uint32 - - o1 = uint32(val >> 32) - o2 = uint32(val) - - if !strings.HasPrefix(ldr.SymName(rs), "TOC.") { - ldr.Errorf(s, "archreloctoc called for a symbol without TOC anchor") - } var t int64 useAddi := false - relocs := ldr.Relocs(rs) - tarSym := relocs.At(0).Sym() - if target.IsInternal() && tarSym != 0 && ldr.AttrReachable(tarSym) && ldr.SymSect(tarSym).Seg == &ld.Segdata { - t = ldr.SymValue(tarSym) + r.Add() - ldr.SymValue(syms.TOC) - // change ld to addi in the second instruction - o2 = (o2 & 0x03FF0000) | 0xE<<26 - useAddi = true + if target.IsBigEndian() { + o1 = uint32(val >> 32) + o2 = uint32(val) } else { - t = ldr.SymValue(rs) + r.Add() - ldr.SymValue(syms.TOC) + o1 = uint32(val) + o2 = uint32(val >> 32) + } + + // On AIX, TOC data accesses are always made indirectly against R2 (a sequence of addis+ld+load/store). If the + // The target of the load is known, the sequence can be written into addis+addi+load/store. On Linux, + // TOC data accesses are always made directly against R2 (e.g addis+load/store). + if target.IsAIX() { + if !strings.HasPrefix(ldr.SymName(rs), "TOC.") { + ldr.Errorf(s, "archreloctoc called for a symbol without TOC anchor") + } + relocs := ldr.Relocs(rs) + tarSym := relocs.At(0).Sym() + + if target.IsInternal() && tarSym != 0 && ldr.AttrReachable(tarSym) && ldr.SymSect(tarSym).Seg == &ld.Segdata { + t = ldr.SymValue(tarSym) + r.Add() - ldr.SymValue(syms.TOC) + // change ld to addi in the second instruction + o2 = (o2 & 0x03FF0000) | 0xE<<26 + useAddi = true + } else { + t = ldr.SymValue(rs) + r.Add() - ldr.SymValue(syms.TOC) + } + } else { + t = ldr.SymValue(rs) + r.Add() - symtoc(ldr, syms, s) } if t != int64(int32(t)) { @@ -593,15 +685,20 @@ func archreloctoc(ldr *loader.Loader, target *ld.Target, syms *ld.ArchSyms, r lo } o2 |= uint32(t) & 0xFFFC } + case objabi.R_ADDRPOWER_TOCREL: + o2 |= uint32(t) & 0xffff default: return -1 } - return int64(o1)<<32 | int64(o2) + if target.IsBigEndian() { + return int64(o1)<<32 | int64(o2) + } + return int64(o2)<<32 | int64(o1) } // archrelocaddr relocates a symbol address. -// This code is for AIX only. +// This code is for linux only. func archrelocaddr(ldr *loader.Loader, target *ld.Target, syms *ld.ArchSyms, r loader.Reloc, s loader.Sym, val int64) int64 { rs := r.Sym() if target.IsAIX() { @@ -860,6 +957,18 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade t := ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off())) + tgtName := ldr.SymName(rs) + + // If we are linking PIE or shared code, all golang generated object files have an extra 2 instruction prologue + // to regenerate the TOC pointer from R12. The exception are two special case functions tested below. Note, + // local call offsets for externally generated objects are accounted for when converting into golang relocs. + if !ldr.IsExternal(rs) && ldr.AttrShared(rs) && tgtName != "runtime.duffzero" && tgtName != "runtime.duffcopy" { + // Furthermore, only apply the offset if the target looks like the start of a function call. + if r.Add() == 0 && ldr.SymType(rs) == sym.STEXT { + t += 8 + } + } + if t&3 != 0 { ldr.Errorf(s, "relocation for %s+%d is not aligned: %d", ldr.SymName(rs), r.Off(), t) } @@ -872,6 +981,62 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade case objabi.R_POWER_TOC: // S + A - .TOC. return ldr.SymValue(rs) + r.Add() - symtoc(ldr, syms, s), nExtReloc, true + case objabi.R_ADDRPOWER_PCREL: // S + A - P + t := ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off())) + ha := uint16(((t + 0x8000) >> 16) & 0xFFFF) + l := uint16(t) + if target.IsBigEndian() { + val |= int64(l) + val |= int64(ha) << 32 + } else { + val |= int64(ha) + val |= int64(l) << 32 + } + return val, nExtReloc, true + + case objabi.R_POWER_TLS: + const OP_ADD = 31<<26 | 266<<1 + const MASK_OP_ADD = 0x3F<<26 | 0x1FF<<1 + if val&MASK_OP_ADD != OP_ADD { + ldr.Errorf(s, "R_POWER_TLS reloc only supports XO form ADD, not %08X", val) + } + // Verify RB is R13 in ADD RA,RB,RT. + if (val>>11)&0x1F != 13 { + // If external linking is made to support this, it may expect the linker to rewrite RB. + ldr.Errorf(s, "R_POWER_TLS reloc requires R13 in RB (%08X).", uint32(val)) + } + return val, nExtReloc, true + + case objabi.R_POWER_TLS_IE: + // Convert TLS_IE relocation to TLS_LE if supported. + if !(target.IsPIE() && target.IsElf()) { + log.Fatalf("cannot handle R_POWER_TLS_IE (sym %s) when linking non-PIE, non-ELF binaries internally", ldr.SymName(s)) + } + + // We are an ELF binary, we can safely convert to TLS_LE from: + // addis to, r2, x@got@tprel@ha + // ld to, to, x@got@tprel@l(to) + // + // to TLS_LE by converting to: + // addis to, r0, x@tprel@ha + // addi to, to, x@tprel@l(to) + + const OP_ADDI = 14 << 26 + const OP_MASK = 0x3F << 26 + const OP_RA_MASK = 0x1F << 16 + uval := uint64(val) + // convert r2 to r0, and ld to addi + if target.IsBigEndian() { + uval = uval &^ (OP_RA_MASK << 32) + uval = (uval &^ OP_MASK) | OP_ADDI + } else { + uval = uval &^ (OP_RA_MASK) + uval = (uval &^ (OP_MASK << 32)) | (OP_ADDI << 32) + } + val = int64(uval) + // Treat this like an R_POWER_TLS_LE relocation now. + fallthrough + case objabi.R_POWER_TLS_LE: // The thread pointer points 0x7000 bytes after the start of the // thread local storage area as documented in section "3.7.2 TLS @@ -1067,35 +1232,31 @@ func ensureglinkresolver(ctxt *ld.Link, ldr *loader.Loader) *loader.SymbolBuilde return glink } - // This is essentially the resolver from the ppc64 ELF ABI. + // This is essentially the resolver from the ppc64 ELFv2 ABI. // At entry, r12 holds the address of the symbol resolver stub // for the target routine and the argument registers hold the // arguments for the target routine. // + // PC-rel offsets are computed once the final codesize of the + // resolver is known. + // // This stub is PIC, so first get the PC of label 1 into r11. - // Other things will be relative to this. glink.AddUint32(ctxt.Arch, 0x7c0802a6) // mflr r0 glink.AddUint32(ctxt.Arch, 0x429f0005) // bcl 20,31,1f glink.AddUint32(ctxt.Arch, 0x7d6802a6) // 1: mflr r11 - glink.AddUint32(ctxt.Arch, 0x7c0803a6) // mtlf r0 + glink.AddUint32(ctxt.Arch, 0x7c0803a6) // mtlr r0 - // Compute the .plt array index from the entry point address. - // Because this is PIC, everything is relative to label 1b (in - // r11): - // r0 = ((r12 - r11) - (res_0 - r11)) / 4 = (r12 - res_0) / 4 - glink.AddUint32(ctxt.Arch, 0x3800ffd0) // li r0,-(res_0-1b)=-48 + // Compute the .plt array index from the entry point address + // into r0. This is computed relative to label 1 above. + glink.AddUint32(ctxt.Arch, 0x38000000) // li r0,-(res_0-1b) glink.AddUint32(ctxt.Arch, 0x7c006214) // add r0,r0,r12 glink.AddUint32(ctxt.Arch, 0x7c0b0050) // sub r0,r0,r11 glink.AddUint32(ctxt.Arch, 0x7800f082) // srdi r0,r0,2 - // r11 = address of the first byte of the PLT - r, _ := glink.AddRel(objabi.R_ADDRPOWER) - r.SetSym(ctxt.PLT) - r.SetSiz(8) - r.SetOff(int32(glink.Size())) - r.SetAdd(0) - glink.AddUint32(ctxt.Arch, 0x3d600000) // addis r11,0,.plt@ha - glink.AddUint32(ctxt.Arch, 0x396b0000) // addi r11,r11,.plt@l + // Load the PC-rel offset of ".plt - 1b", and add it to 1b. + // This is stored after this stub and before the resolvers. + glink.AddUint32(ctxt.Arch, 0xe98b0000) // ld r12,res_0-1b-8(r11) + glink.AddUint32(ctxt.Arch, 0x7d6b6214) // add r11,r11,r12 // Load r12 = dynamic resolver address and r11 = DSO // identifier from the first two doublewords of the PLT. @@ -1106,6 +1267,19 @@ func ensureglinkresolver(ctxt *ld.Link, ldr *loader.Loader) *loader.SymbolBuilde glink.AddUint32(ctxt.Arch, 0x7d8903a6) // mtctr r12 glink.AddUint32(ctxt.Arch, 0x4e800420) // bctr + // Store the PC-rel offset to the PLT + r, _ := glink.AddRel(objabi.R_PCREL) + r.SetSym(ctxt.PLT) + r.SetSiz(8) + r.SetOff(int32(glink.Size())) + r.SetAdd(glink.Size()) // Adjust the offset to be relative to label 1 above. + glink.AddUint64(ctxt.Arch, 0) // The offset to the PLT. + + // Resolve PC-rel offsets above now the final size of the stub is known. + res0m1b := glink.Size() - 8 // res_0 - 1b + glink.SetUint32(ctxt.Arch, 16, 0x38000000|uint32(uint16(-res0m1b))) + glink.SetUint32(ctxt.Arch, 32, 0xe98b0000|uint32(uint16(res0m1b-8))) + // The symbol resolvers must immediately follow. // res_0: diff --git a/src/cmd/link/link_test.go b/src/cmd/link/link_test.go index 2b0b2dc4a1..ad7658bb25 100644 --- a/src/cmd/link/link_test.go +++ b/src/cmd/link/link_test.go @@ -997,13 +997,31 @@ package main var x = [1<<25]byte{1<<23: 23, 1<<24: 24} +var addr = [...]*byte{ + &x[1<<23-1], + &x[1<<23], + &x[1<<23+1], + &x[1<<24-1], + &x[1<<24], + &x[1<<24+1], +} + func main() { + // check relocations in instructions check(x[1<<23-1], 0) check(x[1<<23], 23) check(x[1<<23+1], 0) check(x[1<<24-1], 0) check(x[1<<24], 24) check(x[1<<24+1], 0) + + // check absolute address relocations in data + check(*addr[0], 0) + check(*addr[1], 23) + check(*addr[2], 0) + check(*addr[3], 0) + check(*addr[4], 24) + check(*addr[5], 0) } func check(x, y byte) { diff --git a/src/cmd/trace/main.go b/src/cmd/trace/main.go index f94586abf3..3aeba223ee 100644 --- a/src/cmd/trace/main.go +++ b/src/cmd/trace/main.go @@ -66,7 +66,7 @@ var ( func main() { flag.Usage = func() { - fmt.Fprintln(os.Stderr, usageMessage) + fmt.Fprint(os.Stderr, usageMessage) os.Exit(2) } flag.Parse() diff --git a/src/cmd/vendor/github.com/google/pprof/internal/elfexec/elfexec.go b/src/cmd/vendor/github.com/google/pprof/internal/elfexec/elfexec.go index 4f11645185..6447092d3d 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/elfexec/elfexec.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/elfexec/elfexec.go @@ -165,18 +165,60 @@ func GetBuildID(binary io.ReaderAt) ([]byte, error) { return nil, nil } +// kernelBase caluclates the base for kernel mappings, which usually require +// special handling. For kernel mappings, tools (like perf) use the address of +// the kernel relocation symbol (_text or _stext) as the mmap start. Additionaly, +// for obfuscation, ChromeOS profiles have the kernel image remapped to the 0-th page. +func kernelBase(loadSegment *elf.ProgHeader, stextOffset *uint64, start, limit, offset uint64) (uint64, bool) { + const ( + // PAGE_OFFSET for PowerPC64, see arch/powerpc/Kconfig in the kernel sources. + pageOffsetPpc64 = 0xc000000000000000 + pageSize = 4096 + ) + + if loadSegment.Vaddr == start-offset { + return offset, true + } + if start == 0 && limit != 0 && stextOffset != nil { + // ChromeOS remaps its kernel to 0. Nothing else should come + // down this path. Empirical values: + // VADDR=0xffffffff80200000 + // stextOffset=0xffffffff80200198 + return start - *stextOffset, true + } + if start >= loadSegment.Vaddr && limit > start && (offset == 0 || offset == pageOffsetPpc64 || offset == start) { + // Some kernels look like: + // VADDR=0xffffffff80200000 + // stextOffset=0xffffffff80200198 + // Start=0xffffffff83200000 + // Limit=0xffffffff84200000 + // Offset=0 (0xc000000000000000 for PowerPC64) (== Start for ASLR kernel) + // So the base should be: + if stextOffset != nil && (start%pageSize) == (*stextOffset%pageSize) { + // perf uses the address of _stext as start. Some tools may + // adjust for this before calling GetBase, in which case the page + // alignment should be different from that of stextOffset. + return start - *stextOffset, true + } + + return start - loadSegment.Vaddr, true + } + if start%pageSize != 0 && stextOffset != nil && *stextOffset%pageSize == start%pageSize { + // ChromeOS remaps its kernel to 0 + start%pageSize. Nothing + // else should come down this path. Empirical values: + // start=0x198 limit=0x2f9fffff offset=0 + // VADDR=0xffffffff81000000 + // stextOffset=0xffffffff81000198 + return start - *stextOffset, true + } + return 0, false +} + // GetBase determines the base address to subtract from virtual // address to get symbol table address. For an executable, the base // is 0. Otherwise, it's a shared library, and the base is the -// address where the mapping starts. The kernel is special, and may -// use the address of the _stext symbol as the mmap start. _stext -// offset can be obtained with `nm vmlinux | grep _stext` +// address where the mapping starts. The kernel needs special hanldling. func GetBase(fh *elf.FileHeader, loadSegment *elf.ProgHeader, stextOffset *uint64, start, limit, offset uint64) (uint64, error) { - const ( - pageSize = 4096 - // PAGE_OFFSET for PowerPC64, see arch/powerpc/Kconfig in the kernel sources. - pageOffsetPpc64 = 0xc000000000000000 - ) if start == 0 && offset == 0 && (limit == ^uint64(0) || limit == 0) { // Some tools may introduce a fake mapping that spans the entire @@ -202,43 +244,15 @@ func GetBase(fh *elf.FileHeader, loadSegment *elf.ProgHeader, stextOffset *uint6 // the 64-bit address space. return start - offset + loadSegment.Off - loadSegment.Vaddr, nil } - // Various kernel heuristics and cases follow. - if loadSegment.Vaddr == start-offset { - return offset, nil + // Various kernel heuristics and cases are handled separately. + if base, match := kernelBase(loadSegment, stextOffset, start, limit, offset); match { + return base, nil } - if start == 0 && limit != 0 { - // ChromeOS remaps its kernel to 0. Nothing else should come - // down this path. Empirical values: - // VADDR=0xffffffff80200000 - // stextOffset=0xffffffff80200198 - if stextOffset != nil { - return -*stextOffset, nil - } - return -loadSegment.Vaddr, nil - } - if start >= loadSegment.Vaddr && limit > start && (offset == 0 || offset == pageOffsetPpc64 || offset == start) { - // Some kernels look like: - // VADDR=0xffffffff80200000 - // stextOffset=0xffffffff80200198 - // Start=0xffffffff83200000 - // Limit=0xffffffff84200000 - // Offset=0 (0xc000000000000000 for PowerPC64) (== Start for ASLR kernel) - // So the base should be: - if stextOffset != nil && (start%pageSize) == (*stextOffset%pageSize) { - // perf uses the address of _stext as start. Some tools may - // adjust for this before calling GetBase, in which case the page - // alignment should be different from that of stextOffset. - return start - *stextOffset, nil - } - + // ChromeOS can remap its kernel to 0, and the caller might have not found + // the _stext symbol. Split this case from kernelBase() above, since we don't + // want to apply it to an ET_DYN user-mode executable. + if start == 0 && limit != 0 && stextOffset == nil { return start - loadSegment.Vaddr, nil - } else if start%pageSize != 0 && stextOffset != nil && *stextOffset%pageSize == start%pageSize { - // ChromeOS remaps its kernel to 0 + start%pageSize. Nothing - // else should come down this path. Empirical values: - // start=0x198 limit=0x2f9fffff offset=0 - // VADDR=0xffffffff81000000 - // stextOffset=0xffffffff81000198 - return start - *stextOffset, nil } return 0, fmt.Errorf("don't know how to handle EXEC segment: %v start=0x%x limit=0x%x offset=0x%x", *loadSegment, start, limit, offset) @@ -255,6 +269,11 @@ func GetBase(fh *elf.FileHeader, loadSegment *elf.ProgHeader, stextOffset *uint6 if loadSegment == nil { return start - offset, nil } + // Kernels compiled as PIE can be ET_DYN as well. Use heuristic, similar to + // the ET_EXEC case above. + if base, match := kernelBase(loadSegment, stextOffset, start, limit, offset); match { + return base, nil + } // The program header, if not nil, indicates the offset in the file where // the executable segment is located (loadSegment.Off), and the base virtual // address where the first byte of the segment is loaded diff --git a/src/cmd/vendor/github.com/google/pprof/internal/report/source_html.go b/src/cmd/vendor/github.com/google/pprof/internal/report/source_html.go index 17c9f6eb94..851693f1d0 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/report/source_html.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/report/source_html.go @@ -72,5 +72,4 @@ function pprof_toggle_asm(e) { const weblistPageClosing = ` - -` +` diff --git a/src/cmd/vendor/github.com/ianlancetaylor/demangle/README.md b/src/cmd/vendor/github.com/ianlancetaylor/demangle/README.md index ef3f94a63d..2c01cae088 100644 --- a/src/cmd/vendor/github.com/ianlancetaylor/demangle/README.md +++ b/src/cmd/vendor/github.com/ianlancetaylor/demangle/README.md @@ -1,3 +1,3 @@ # github.com/ianlancetaylor/demangle -A Go package that can be used to demangle C++ symbol names. +A Go package that can be used to demangle C++ and Rust symbol names. diff --git a/src/cmd/vendor/github.com/ianlancetaylor/demangle/ast.go b/src/cmd/vendor/github.com/ianlancetaylor/demangle/ast.go index ccbe5b3559..7b9178f1bb 100644 --- a/src/cmd/vendor/github.com/ianlancetaylor/demangle/ast.go +++ b/src/cmd/vendor/github.com/ianlancetaylor/demangle/ast.go @@ -11,6 +11,7 @@ import ( // AST is an abstract syntax tree representing a C++ declaration. // This is sufficient for the demangler but is by no means a general C++ AST. +// This abstract syntax tree is only used for C++ symbols, not Rust symbols. type AST interface { // Internal method to convert to demangled string. print(*printState) @@ -37,21 +38,25 @@ type AST interface { // ASTToString returns the demangled name of the AST. func ASTToString(a AST, options ...Option) string { tparams := true + llvmStyle := false for _, o := range options { switch o { case NoTemplateParams: tparams = false + case LLVMStyle: + llvmStyle = true } } - ps := printState{tparams: tparams} + ps := printState{tparams: tparams, llvmStyle: llvmStyle} a.print(&ps) return ps.buf.String() } // The printState type holds information needed to print an AST. type printState struct { - tparams bool // whether to print template parameters + tparams bool // whether to print template parameters + llvmStyle bool buf strings.Builder last byte // Last byte written to buffer. @@ -408,7 +413,11 @@ type LambdaAuto struct { 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) + if ps.llvmStyle { + ps.writeString("auto") + } else { + fmt.Fprintf(&ps.buf, "auto:%d", la.Index+1) + } } func (la *LambdaAuto) Traverse(fn func(AST) bool) { @@ -504,6 +513,9 @@ func (q *Qualifier) print(ps *printState) { ps.writeByte('(') first := true for _, e := range q.Exprs { + if el, ok := e.(*ExprList); ok && len(el.Exprs) == 0 { + continue + } if !first { ps.writeString(", ") } @@ -715,7 +727,11 @@ type BuiltinType struct { } func (bt *BuiltinType) print(ps *printState) { - ps.writeString(bt.Name) + name := bt.Name + if ps.llvmStyle && name == "decltype(nullptr)" { + name = "std::nullptr_t" + } + ps.writeString(name) } func (bt *BuiltinType) Traverse(fn func(AST) bool) { @@ -970,10 +986,15 @@ type VendorQualifier struct { } func (vq *VendorQualifier) print(ps *printState) { - ps.inner = append(ps.inner, vq) - ps.print(vq.Type) - if len(ps.inner) > 0 { - ps.printOneInner(nil) + if ps.llvmStyle { + ps.print(vq.Type) + vq.printInner(ps) + } else { + ps.inner = append(ps.inner, vq) + ps.print(vq.Type) + if len(ps.inner) > 0 { + ps.printOneInner(nil) + } } } @@ -1110,19 +1131,27 @@ func (at *ArrayType) goString(indent int, field string) string { at.Element.goString(indent+2, "Element: ")) } -// FunctionType is a function type. The Return field may be nil for -// cases where the return type is not part of the mangled name. +// FunctionType is a function type. type FunctionType struct { Return AST Args []AST + + // The forLocalName field reports whether this FunctionType + // was created for a local name. With the default GNU demangling + // output we don't print the return type in that case. + ForLocalName bool } func (ft *FunctionType) print(ps *printState) { - if ft.Return != nil { + retType := ft.Return + if ft.ForLocalName && !ps.llvmStyle { + retType = nil + } + if retType != nil { // Pass the return type as an inner type in order to // print the arguments in the right location. ps.inner = append(ps.inner, ft) - ps.print(ft.Return) + ps.print(retType) if len(ps.inner) == 0 { // Everything was printed. return @@ -1227,7 +1256,11 @@ func (ft *FunctionType) Copy(fn func(AST) AST, skip func(AST) bool) AST { if !changed { return fn(ft) } - ft = &FunctionType{Return: ret, Args: args} + ft = &FunctionType{ + Return: ret, + Args: args, + ForLocalName: ft.ForLocalName, + } if r := fn(ft); r != nil { return r } @@ -1239,6 +1272,10 @@ func (ft *FunctionType) GoString() string { } func (ft *FunctionType) goString(indent int, field string) string { + var forLocalName string + if ft.ForLocalName { + forLocalName = " ForLocalName: true" + } var r string if ft.Return == nil { r = fmt.Sprintf("%*sReturn: nil", indent+2, "") @@ -1255,7 +1292,8 @@ func (ft *FunctionType) goString(indent int, field string) string { args += a.goString(indent+4, fmt.Sprintf("%d: ", i)) } } - return fmt.Sprintf("%*s%sFunctionType:\n%s\n%s", indent, "", field, r, args) + return fmt.Sprintf("%*s%sFunctionType:%s\n%s\n%s", indent, "", field, + forLocalName, r, args) } // FunctionParam is a parameter of a function, used for last-specified @@ -1267,6 +1305,12 @@ type FunctionParam struct { func (fp *FunctionParam) print(ps *printState) { if fp.Index == 0 { ps.writeString("this") + } else if ps.llvmStyle { + if fp.Index == 1 { + ps.writeString("fp") + } else { + fmt.Fprintf(&ps.buf, "fp%d", fp.Index-2) + } } else { fmt.Fprintf(&ps.buf, "{parm#%d}", fp.Index) } @@ -1422,9 +1466,15 @@ func (vt *VectorType) print(ps *printState) { } func (vt *VectorType) printInner(ps *printState) { - ps.writeString(" __vector(") + end := byte(')') + if ps.llvmStyle { + ps.writeString(" vector[") + end = ']' + } else { + ps.writeString(" __vector(") + } ps.print(vt.Dimension) - ps.writeByte(')') + ps.writeByte(end) } func (vt *VectorType) Traverse(fn func(AST) bool) { @@ -1466,13 +1516,59 @@ func (vt *VectorType) goString(indent int, field string) string { vt.Base.goString(indent+2, "Base: ")) } +// ElaboratedType is an elaborated struct/union/enum type. +type ElaboratedType struct { + Kind string + Type AST +} + +func (et *ElaboratedType) print(ps *printState) { + ps.writeString(et.Kind) + ps.writeString(" ") + et.Type.print(ps) +} + +func (et *ElaboratedType) Traverse(fn func(AST) bool) { + if fn(et) { + et.Type.Traverse(fn) + } +} + +func (et *ElaboratedType) Copy(fn func(AST) AST, skip func(AST) bool) AST { + if skip(et) { + return nil + } + typ := et.Type.Copy(fn, skip) + if typ == nil { + return fn(et) + } + et = &ElaboratedType{Kind: et.Kind, Type: typ} + if r := fn(et); r != nil { + return r + } + return et +} + +func (et *ElaboratedType) GoString() string { + return et.goString(0, "") +} + +func (et *ElaboratedType) goString(indent int, field string) string { + return fmt.Sprintf("%*s%sElaboratedtype: Kind: %s\n%s", indent, "", field, + et.Kind, et.Type.goString(indent+2, "Expr: ")) +} + // Decltype is the decltype operator. type Decltype struct { Expr AST } func (dt *Decltype) print(ps *printState) { - ps.writeString("decltype (") + ps.writeString("decltype") + if !ps.llvmStyle { + ps.writeString(" ") + } + ps.writeString("(") ps.print(dt.Expr) ps.writeByte(')') } @@ -1544,15 +1640,20 @@ func (op *Operator) goString(indent int, field string) string { // Constructor is a constructor. type Constructor struct { Name AST + Base AST // base class of inheriting constructor } func (c *Constructor) print(ps *printState) { ps.print(c.Name) + // We don't include the base class in the demangled string. } func (c *Constructor) Traverse(fn func(AST) bool) { if fn(c) { c.Name.Traverse(fn) + if c.Base != nil { + c.Base.Traverse(fn) + } } } @@ -1561,10 +1662,20 @@ func (c *Constructor) Copy(fn func(AST) AST, skip func(AST) bool) AST { return nil } name := c.Name.Copy(fn, skip) - if name == nil { + var base AST + if c.Base != nil { + base = c.Base.Copy(fn, skip) + } + if name == nil && base == nil { return fn(c) } - c = &Constructor{Name: name} + if name == nil { + name = c.Name + } + if base == nil { + base = c.Base + } + c = &Constructor{Name: name, Base: base} if r := fn(c); r != nil { return r } @@ -1576,7 +1687,13 @@ func (c *Constructor) GoString() string { } func (c *Constructor) goString(indent int, field string) string { - return fmt.Sprintf("%*s%sConstructor:\n%s", indent, "", field, c.Name.goString(indent+2, "Name: ")) + var sb strings.Builder + fmt.Fprintf(&sb, "%*s%sConstructor:\n", indent, "", field) + if c.Base != nil { + fmt.Fprintf(&sb, "%s\n", c.Base.goString(indent+2, "Base: ")) + } + fmt.Fprintf(&sb, "%s", c.Name.goString(indent+2, "Name: ")) + return sb.String() } // Destructor is a destructor. @@ -1727,8 +1844,12 @@ func (pe *PackExpansion) print(ps *printState) { // We normally only get here if the simplify function was // unable to locate and expand the pack. if pe.Pack == nil { - parenthesize(ps, pe.Base) - ps.writeString("...") + if ps.llvmStyle { + ps.print(pe.Base) + } else { + parenthesize(ps, pe.Base) + ps.writeString("...") + } } else { ps.print(pe.Base) } @@ -1834,7 +1955,13 @@ type SizeofPack struct { } func (sp *SizeofPack) print(ps *printState) { - ps.writeString(fmt.Sprintf("%d", len(sp.Pack.Args))) + if ps.llvmStyle { + ps.writeString("sizeof...(") + ps.print(sp.Pack) + ps.writeByte(')') + } else { + ps.writeString(fmt.Sprintf("%d", len(sp.Pack.Args))) + } } func (sp *SizeofPack) Traverse(fn func(AST) bool) { @@ -1932,6 +2059,287 @@ func (sa *SizeofArgs) goString(indent int, field string) string { return fmt.Sprintf("%*s%sSizeofArgs:\n%s", indent, "", field, args) } +// TemplateParamName is the name of a template parameter that the +// demangler introduced for a lambda that has explicit template +// parameters. This is a prefix with an index. +type TemplateParamName struct { + Prefix string + Index int +} + +func (tpn *TemplateParamName) print(ps *printState) { + ps.writeString(tpn.Prefix) + if tpn.Index > 0 { + ps.writeString(fmt.Sprintf("%d", tpn.Index-1)) + } +} + +func (tpn *TemplateParamName) Traverse(fn func(AST) bool) { + fn(tpn) +} + +func (tpn *TemplateParamName) Copy(fn func(AST) AST, skip func(AST) bool) AST { + if skip(tpn) { + return nil + } + return fn(tpn) +} + +func (tpn *TemplateParamName) GoString() string { + return tpn.goString(0, "") +} + +func (tpn *TemplateParamName) goString(indent int, field string) string { + name := tpn.Prefix + if tpn.Index > 0 { + name += fmt.Sprintf("%d", tpn.Index-1) + } + return fmt.Sprintf("%*s%sTemplateParamName: %s", indent, "", field, name) +} + +// TypeTemplateParam is a type template parameter that appears in a +// lambda with explicit template parameters. +type TypeTemplateParam struct { + Name AST +} + +func (ttp *TypeTemplateParam) print(ps *printState) { + ps.writeString("typename ") + ps.printInner(false) + ps.print(ttp.Name) +} + +func (ttp *TypeTemplateParam) Traverse(fn func(AST) bool) { + if fn(ttp) { + ttp.Name.Traverse(fn) + } +} + +func (ttp *TypeTemplateParam) Copy(fn func(AST) AST, skip func(AST) bool) AST { + if skip(ttp) { + return nil + } + name := ttp.Name.Copy(fn, skip) + if name == nil { + return fn(ttp) + } + ttp = &TypeTemplateParam{Name: name} + if r := fn(ttp); r != nil { + return r + } + return ttp +} + +func (ttp *TypeTemplateParam) GoString() string { + return ttp.goString(0, "") +} + +func (ttp *TypeTemplateParam) goString(indent int, field string) string { + return fmt.Sprintf("%*s%sTypeTemplateParam:\n%s", indent, "", field, + ttp.Name.goString(indent+2, "Name")) +} + +// NonTypeTemplateParam is a non-type template parameter that appears +// in a lambda with explicit template parameters. +type NonTypeTemplateParam struct { + Name AST + Type AST +} + +func (nttp *NonTypeTemplateParam) print(ps *printState) { + ps.inner = append(ps.inner, nttp) + ps.print(nttp.Type) + if len(ps.inner) > 0 { + ps.writeByte(' ') + ps.print(nttp.Name) + ps.inner = ps.inner[:len(ps.inner)-1] + } +} + +func (nttp *NonTypeTemplateParam) printInner(ps *printState) { + ps.print(nttp.Name) +} + +func (nttp *NonTypeTemplateParam) Traverse(fn func(AST) bool) { + if fn(nttp) { + nttp.Name.Traverse(fn) + nttp.Type.Traverse(fn) + } +} + +func (nttp *NonTypeTemplateParam) Copy(fn func(AST) AST, skip func(AST) bool) AST { + if skip(nttp) { + return nil + } + name := nttp.Name.Copy(fn, skip) + typ := nttp.Type.Copy(fn, skip) + if name == nil && typ == nil { + return fn(nttp) + } + if name == nil { + name = nttp.Name + } + if typ == nil { + typ = nttp.Type + } + nttp = &NonTypeTemplateParam{Name: name, Type: typ} + if r := fn(nttp); r != nil { + return r + } + return nttp +} + +func (nttp *NonTypeTemplateParam) GoString() string { + return nttp.goString(0, "") +} + +func (nttp *NonTypeTemplateParam) goString(indent int, field string) string { + return fmt.Sprintf("%*s%sNonTypeTemplateParam:\n%s\n%s", indent, "", field, + nttp.Name.goString(indent+2, "Name: "), + nttp.Type.goString(indent+2, "Type: ")) +} + +// TemplateTemplateParam is a template template parameter that appears +// in a lambda with explicit template parameters. +type TemplateTemplateParam struct { + Name AST + Params []AST +} + +func (ttp *TemplateTemplateParam) print(ps *printState) { + ps.writeString("template<") + for i, param := range ttp.Params { + if i > 0 { + ps.writeString(", ") + } + ps.print(param) + } + ps.writeString("> typename ") + ps.print(ttp.Name) +} + +func (ttp *TemplateTemplateParam) Traverse(fn func(AST) bool) { + if fn(ttp) { + ttp.Name.Traverse(fn) + for _, param := range ttp.Params { + param.Traverse(fn) + } + } +} + +func (ttp *TemplateTemplateParam) Copy(fn func(AST) AST, skip func(AST) bool) AST { + if skip(ttp) { + return nil + } + + changed := false + + name := ttp.Name.Copy(fn, skip) + if name == nil { + name = ttp.Name + } else { + changed = true + } + + params := make([]AST, len(ttp.Params)) + for i, p := range ttp.Params { + pc := p.Copy(fn, skip) + if pc == nil { + params[i] = p + } else { + params[i] = pc + changed = true + } + } + + if !changed { + return fn(ttp) + } + + ttp = &TemplateTemplateParam{ + Name: name, + Params: params, + } + if r := fn(ttp); r != nil { + return r + } + return ttp +} + +func (ttp *TemplateTemplateParam) GoString() string { + return ttp.goString(0, "") +} + +func (ttp *TemplateTemplateParam) goString(indent int, field string) string { + var params strings.Builder + fmt.Fprintf(¶ms, "%*sParams:", indent+2, "") + for i, p := range ttp.Params { + params.WriteByte('\n') + params.WriteString(p.goString(indent+4, fmt.Sprintf("%d: ", i))) + } + return fmt.Sprintf("%*s%sTemplateTemplateParam:\n%s\n%s", indent, "", field, + ttp.Name.goString(indent+2, "Name: "), + params.String()) +} + +// TemplateParamPack is a template parameter pack that appears in a +// lambda with explicit template parameters. +type TemplateParamPack struct { + Param AST +} + +func (tpp *TemplateParamPack) print(ps *printState) { + holdInner := ps.inner + defer func() { ps.inner = holdInner }() + + ps.inner = []AST{tpp} + if nttp, ok := tpp.Param.(*NonTypeTemplateParam); ok { + ps.print(nttp.Type) + } else { + ps.print(tpp.Param) + } + if len(ps.inner) > 0 { + ps.writeString("...") + } +} + +func (tpp *TemplateParamPack) printInner(ps *printState) { + ps.writeString("...") + if nttp, ok := tpp.Param.(*NonTypeTemplateParam); ok { + ps.print(nttp.Name) + } +} + +func (tpp *TemplateParamPack) Traverse(fn func(AST) bool) { + if fn(tpp) { + tpp.Param.Traverse(fn) + } +} + +func (tpp *TemplateParamPack) Copy(fn func(AST) AST, skip func(AST) bool) AST { + if skip(tpp) { + return nil + } + param := tpp.Param.Copy(fn, skip) + if param == nil { + return fn(tpp) + } + tpp = &TemplateParamPack{Param: param} + if r := fn(tpp); r != nil { + return r + } + return tpp +} + +func (tpp *TemplateParamPack) GoString() string { + return tpp.goString(0, "") +} + +func (tpp *TemplateParamPack) goString(indent int, field string) string { + return fmt.Sprintf("%*s%sTemplateParamPack:\n%s", indent, "", field, + tpp.Param.goString(indent+2, "Param: ")) +} + // Cast is a type cast. type Cast struct { To AST @@ -1977,7 +2385,11 @@ func (c *Cast) goString(indent int, field string) string { func parenthesize(ps *printState, val AST) { paren := false switch v := val.(type) { - case *Name, *InitializerList, *FunctionParam: + case *Name, *InitializerList: + case *FunctionParam: + if ps.llvmStyle { + paren = true + } case *Qualified: if v.LocalName { paren = true @@ -2047,14 +2459,17 @@ type Unary struct { } func (u *Unary) print(ps *printState) { + op, _ := u.Op.(*Operator) expr := u.Expr // Don't print the argument list when taking the address of a // function. - if op, ok := u.Op.(*Operator); ok && op.Name == "&" { - if t, ok := expr.(*Typed); ok { - if _, ok := t.Type.(*FunctionType); ok { - expr = t.Name + if !ps.llvmStyle { + if op != nil && op.Name == "&" { + if t, ok := expr.(*Typed); ok { + if _, ok := t.Type.(*FunctionType); ok { + expr = t.Name + } } } } @@ -2063,8 +2478,11 @@ func (u *Unary) print(ps *printState) { parenthesize(ps, expr) } - if op, ok := u.Op.(*Operator); ok { + if op != nil { ps.writeString(op.Name) + if ps.llvmStyle && op.Name == "noexcept" { + ps.writeByte(' ') + } } else if c, ok := u.Op.(*Cast); ok { ps.writeByte('(') ps.print(c.To) @@ -2074,7 +2492,7 @@ func (u *Unary) print(ps *printState) { } if !u.Suffix { - if op, ok := u.Op.(*Operator); ok && op.Name == "::" { + if op != nil && op.Name == "::" { // Don't use parentheses after ::. ps.print(expr) } else if u.SizeofType { @@ -2082,6 +2500,19 @@ func (u *Unary) print(ps *printState) { ps.writeByte('(') ps.print(expr) ps.writeByte(')') + } else if op != nil && op.Name == "__alignof__" { + // Always use parentheses for __alignof__ argument. + ps.writeByte('(') + ps.print(expr) + ps.writeByte(')') + } else if ps.llvmStyle { + if op == nil || op.Name != `operator"" ` { + ps.writeByte('(') + } + ps.print(expr) + if op == nil || op.Name != `operator"" ` { + ps.writeByte(')') + } } else { parenthesize(ps, expr) } @@ -2140,7 +2571,16 @@ func isDesignatedInitializer(x AST) bool { switch x := x.(type) { case *Binary: if op, ok := x.Op.(*Operator); ok { - return op.Name == "=" || op.Name == "]=" + if op.Name == "]=" { + return true + } + if op.Name != "=" { + return false + } + if _, ok := x.Left.(*Literal); ok { + return false + } + return true } case *Trinary: if op, ok := x.Op.(*Operator); ok { @@ -2185,8 +2625,13 @@ func (b *Binary) print(ps *printState) { // initializer chains. ps.print(b.Right) } else { - ps.writeByte('=') - parenthesize(ps, b.Right) + if ps.llvmStyle { + ps.writeString(" = ") + ps.print(b.Right) + } else { + ps.writeByte('=') + parenthesize(ps, b.Right) + } } return } @@ -2200,9 +2645,19 @@ func (b *Binary) print(ps *printState) { left := b.Left + skipParens := false + skipBothParens := false + addSpaces := ps.llvmStyle + if ps.llvmStyle && op != nil { + switch op.Name { + case ".", "->": + skipBothParens = true + addSpaces = false + } + } + // 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 { if ft, ok := ty.Type.(*FunctionType); ok { @@ -2215,10 +2670,17 @@ func (b *Binary) print(ps *printState) { left = ty.Name } } + if ps.llvmStyle { + skipParens = true + } } - if skipParens { + if skipParens || skipBothParens { ps.print(left) + } else if ps.llvmStyle { + ps.writeByte('(') + ps.print(left) + ps.writeByte(')') } else { parenthesize(ps, left) } @@ -2232,13 +2694,27 @@ func (b *Binary) print(ps *printState) { if op != nil { if op.Name != "()" { + if addSpaces { + ps.writeByte(' ') + } ps.writeString(op.Name) + if addSpaces { + ps.writeByte(' ') + } } } else { ps.print(b.Op) } - parenthesize(ps, b.Right) + if skipBothParens { + ps.print(b.Right) + } else if ps.llvmStyle { + ps.writeByte('(') + ps.print(b.Right) + ps.writeByte(')') + } else { + parenthesize(ps, b.Right) + } if op != nil && op.Name == ">" { ps.writeByte(')') @@ -2310,14 +2786,23 @@ func (t *Trinary) print(ps *printState) { // initializer chains. ps.print(t.Third) } else { - ps.writeByte('=') - parenthesize(ps, t.Third) + if ps.llvmStyle { + ps.writeString(" = ") + ps.print(t.Third) + } else { + ps.writeByte('=') + parenthesize(ps, t.Third) + } } return } parenthesize(ps, t.First) - ps.writeByte('?') + if ps.llvmStyle { + ps.writeString(" ? ") + } else { + ps.writeByte('?') + } parenthesize(ps, t.Second) ps.writeString(" : ") parenthesize(ps, t.Third) @@ -2386,31 +2871,44 @@ func (f *Fold) print(ps *printState) { op, _ := f.Op.(*Operator) printOp := func() { if op != nil { + if ps.llvmStyle { + ps.writeByte(' ') + } ps.writeString(op.Name) + if ps.llvmStyle { + ps.writeByte(' ') + } } else { ps.print(f.Op) } } + foldParenthesize := func(a AST) { + if _, ok := a.(*ArgumentPack); ok || !ps.llvmStyle { + parenthesize(ps, a) + } else { + ps.print(a) + } + } if f.Arg2 == nil { if f.Left { ps.writeString("(...") printOp() - parenthesize(ps, f.Arg1) + foldParenthesize(f.Arg1) ps.writeString(")") } else { ps.writeString("(") - parenthesize(ps, f.Arg1) + foldParenthesize(f.Arg1) printOp() ps.writeString("...)") } } else { ps.writeString("(") - parenthesize(ps, f.Arg1) + foldParenthesize(f.Arg1) printOp() ps.writeString("...") printOp() - parenthesize(ps, f.Arg2) + foldParenthesize(f.Arg2) ps.writeString(")") } } @@ -2471,6 +2969,143 @@ func (f *Fold) goString(indent int, field string) string { } } +// Subobject is a a reference to an offset in an expression. This is +// used for C++20 manglings of class types used as the type of +// non-type template arguments. +// +// See https://github.com/itanium-cxx-abi/cxx-abi/issues/47. +type Subobject struct { + Type AST + SubExpr AST + Offset int + Selectors []int + PastEnd bool +} + +func (so *Subobject) print(ps *printState) { + ps.print(so.SubExpr) + ps.writeString(".<") + ps.print(so.Type) + ps.writeString(fmt.Sprintf(" at offset %d>", so.Offset)) +} + +func (so *Subobject) Traverse(fn func(AST) bool) { + if fn(so) { + so.Type.Traverse(fn) + so.SubExpr.Traverse(fn) + } +} + +func (so *Subobject) Copy(fn func(AST) AST, skip func(AST) bool) AST { + if skip(so) { + return nil + } + typ := so.Type.Copy(fn, skip) + subExpr := so.SubExpr.Copy(fn, skip) + if typ == nil && subExpr == nil { + return nil + } + if typ == nil { + typ = so.Type + } + if subExpr == nil { + subExpr = so.SubExpr + } + so = &Subobject{ + Type: typ, + SubExpr: subExpr, + Offset: so.Offset, + Selectors: so.Selectors, + PastEnd: so.PastEnd, + } + if r := fn(so); r != nil { + return r + } + return so +} + +func (so *Subobject) GoString() string { + return so.goString(0, "") +} + +func (so *Subobject) goString(indent int, field string) string { + var selectors string + for _, s := range so.Selectors { + selectors += fmt.Sprintf(" %d", s) + } + return fmt.Sprintf("%*s%sSubobject:\n%s\n%s\n%*sOffset: %d\n%*sSelectors:%s\n%*sPastEnd: %t", + indent, "", field, + so.Type.goString(indent+2, "Type: "), + so.SubExpr.goString(indent+2, "SubExpr: "), + indent+2, "", so.Offset, + indent+2, "", selectors, + indent+2, "", so.PastEnd) +} + +// PtrMemCast is a conversion of an expression to a pointer-to-member +// type. This is used for C++20 manglings of class types used as the +// type of non-type template arguments. +// +// See https://github.com/itanium-cxx-abi/cxx-abi/issues/47. +type PtrMemCast struct { + Type AST + Expr AST + Offset int +} + +func (pmc *PtrMemCast) print(ps *printState) { + ps.writeString("(") + ps.print(pmc.Type) + ps.writeString(")(") + ps.print(pmc.Expr) + ps.writeString(")") +} + +func (pmc *PtrMemCast) Traverse(fn func(AST) bool) { + if fn(pmc) { + pmc.Type.Traverse(fn) + pmc.Expr.Traverse(fn) + } +} + +func (pmc *PtrMemCast) Copy(fn func(AST) AST, skip func(AST) bool) AST { + if skip(pmc) { + return nil + } + typ := pmc.Type.Copy(fn, skip) + expr := pmc.Expr.Copy(fn, skip) + if typ == nil && expr == nil { + return nil + } + if typ == nil { + typ = pmc.Type + } + if expr == nil { + expr = pmc.Expr + } + pmc = &PtrMemCast{ + Type: typ, + Expr: expr, + Offset: pmc.Offset, + } + if r := fn(pmc); r != nil { + return r + } + return pmc +} + +func (pmc *PtrMemCast) GoString() string { + return pmc.goString(0, "") +} + +func (pmc *PtrMemCast) goString(indent int, field string) string { + return fmt.Sprintf("%*s%sPtrMemCast:\n%s\n%s\n%*sOffset: %d", + indent, "", field, + pmc.Type.goString(indent+2, "Type: "), + pmc.Expr.goString(indent+2, "Expr: "), + indent+2, "", pmc.Offset) +} + // New is a use of operator new in an expression. type New struct { Op AST @@ -2609,7 +3244,11 @@ func (l *Literal) print(ps *printState) { return } } else if b.Name == "decltype(nullptr)" && l.Val == "" { - ps.print(l.Type) + if ps.llvmStyle { + ps.writeString("nullptr") + } else { + ps.print(l.Type) + } return } else { isFloat = builtinTypeFloat[b.Name] @@ -2667,6 +3306,90 @@ func (l *Literal) goString(indent int, field string) string { indent+2, "", l.Val) } +// StringLiteral is a string literal. +type StringLiteral struct { + Type AST +} + +func (sl *StringLiteral) print(ps *printState) { + ps.writeString(`"<`) + sl.Type.print(ps) + ps.writeString(`>"`) +} + +func (sl *StringLiteral) Traverse(fn func(AST) bool) { + if fn(sl) { + sl.Type.Traverse(fn) + } +} + +func (sl *StringLiteral) Copy(fn func(AST) AST, skip func(AST) bool) AST { + if skip(sl) { + return nil + } + typ := sl.Type.Copy(fn, skip) + if typ == nil { + return fn(sl) + } + sl = &StringLiteral{Type: typ} + if r := fn(sl); r != nil { + return r + } + return sl +} + +func (sl *StringLiteral) GoString() string { + return sl.goString(0, "") +} + +func (sl *StringLiteral) goString(indent int, field string) string { + return fmt.Sprintf("%*s%sStringLiteral:\n%s", indent, "", field, + sl.Type.goString(indent+2, "")) +} + +// LambdaExpr is a literal that is a lambda expression. +type LambdaExpr struct { + Type AST +} + +func (le *LambdaExpr) print(ps *printState) { + ps.writeString("[]") + if cl, ok := le.Type.(*Closure); ok { + cl.printTypes(ps) + } + ps.writeString("{...}") +} + +func (le *LambdaExpr) Traverse(fn func(AST) bool) { + if fn(le) { + le.Type.Traverse(fn) + } +} + +func (le *LambdaExpr) Copy(fn func(AST) AST, skip func(AST) bool) AST { + if skip(le) { + return nil + } + typ := le.Type.Copy(fn, skip) + if typ == nil { + return fn(le) + } + le = &LambdaExpr{Type: typ} + if r := fn(le); r != nil { + return r + } + return le +} + +func (le *LambdaExpr) GoString() string { + return le.goString(0, "") +} + +func (le *LambdaExpr) goString(indent int, field string) string { + return fmt.Sprintf("%*s%sLambdaExpr:\n%s", indent, "", field, + le.Type.goString(indent+2, "")) +} + // ExprList is a list of expressions, typically arguments to a // function call in an expression. type ExprList struct { @@ -2803,7 +3526,9 @@ type DefaultArg struct { } func (da *DefaultArg) print(ps *printState) { - fmt.Fprintf(&ps.buf, "{default arg#%d}::", da.Num+1) + if !ps.llvmStyle { + fmt.Fprintf(&ps.buf, "{default arg#%d}::", da.Num+1) + } ps.print(da.Arg) } @@ -2839,23 +3564,53 @@ func (da *DefaultArg) goString(indent int, field string) string { // Closure is a closure, or lambda expression. type Closure struct { - Types []AST - Num int + TemplateArgs []AST + Types []AST + Num int } func (cl *Closure) print(ps *printState) { - ps.writeString("{lambda(") + if ps.llvmStyle { + if cl.Num == 0 { + ps.writeString("'lambda'") + } else { + ps.writeString(fmt.Sprintf("'lambda%d'", cl.Num-1)) + } + } else { + ps.writeString("{lambda") + } + cl.printTypes(ps) + if !ps.llvmStyle { + ps.writeString(fmt.Sprintf("#%d}", cl.Num+1)) + } +} + +func (cl *Closure) printTypes(ps *printState) { + if len(cl.TemplateArgs) > 0 { + ps.writeString("<") + for i, a := range cl.TemplateArgs { + if i > 0 { + ps.writeString(", ") + } + ps.print(a) + } + ps.writeString(">") + } + ps.writeString("(") for i, t := range cl.Types { if i > 0 { ps.writeString(", ") } ps.print(t) } - ps.writeString(fmt.Sprintf(")#%d}", cl.Num+1)) + ps.writeString(")") } func (cl *Closure) Traverse(fn func(AST) bool) { if fn(cl) { + for _, a := range cl.TemplateArgs { + a.Traverse(fn) + } for _, t := range cl.Types { t.Traverse(fn) } @@ -2866,8 +3621,20 @@ func (cl *Closure) Copy(fn func(AST) AST, skip func(AST) bool) AST { if skip(cl) { return nil } - types := make([]AST, len(cl.Types)) changed := false + + args := make([]AST, len(cl.TemplateArgs)) + for i, a := range cl.TemplateArgs { + ac := a.Copy(fn, skip) + if ac == nil { + args[i] = a + } else { + args[i] = ac + changed = true + } + } + + types := make([]AST, len(cl.Types)) for i, t := range cl.Types { tc := t.Copy(fn, skip) if tc == nil { @@ -2877,10 +3644,11 @@ func (cl *Closure) Copy(fn func(AST) AST, skip func(AST) bool) AST { changed = true } } + if !changed { return fn(cl) } - cl = &Closure{Types: types, Num: cl.Num} + cl = &Closure{TemplateArgs: args, Types: types, Num: cl.Num} if r := fn(cl); r != nil { return r } @@ -2892,6 +3660,16 @@ func (cl *Closure) GoString() string { } func (cl *Closure) goString(indent int, field string) string { + var args string + if len(cl.TemplateArgs) == 0 { + args = fmt.Sprintf("%*sTemplateArgs: nil", indent+2, "") + } else { + args = fmt.Sprintf("%*sTemplateArgs:", indent+2, "") + for i, a := range cl.TemplateArgs { + args += "\n" + args += a.goString(indent+4, fmt.Sprintf("%d: ", i)) + } + } var types string if len(cl.Types) == 0 { types = fmt.Sprintf("%*sTypes: nil", indent+2, "") @@ -2902,7 +3680,71 @@ func (cl *Closure) goString(indent int, field string) string { types += t.goString(indent+4, fmt.Sprintf("%d: ", i)) } } - return fmt.Sprintf("%*s%sClosure: Num: %d\n%s", indent, "", field, cl.Num, types) + return fmt.Sprintf("%*s%sClosure: Num: %d\n%s\n%s", indent, "", field, + cl.Num, args, types) +} + +// StructuredBindings is a structured binding declaration. +type StructuredBindings struct { + Bindings []AST +} + +func (sb *StructuredBindings) print(ps *printState) { + ps.writeString("[") + for i, b := range sb.Bindings { + if i > 0 { + ps.writeString(", ") + } + b.print(ps) + } + ps.writeString("]") +} + +func (sb *StructuredBindings) Traverse(fn func(AST) bool) { + if fn(sb) { + for _, b := range sb.Bindings { + b.Traverse(fn) + } + } +} + +func (sb *StructuredBindings) Copy(fn func(AST) AST, skip func(AST) bool) AST { + if skip(sb) { + return nil + } + changed := false + bindings := make([]AST, len(sb.Bindings)) + for i, b := range sb.Bindings { + bc := b.Copy(fn, skip) + if bc == nil { + bindings[i] = b + } else { + bindings[i] = bc + changed = true + } + } + if !changed { + return fn(sb) + } + sb = &StructuredBindings{Bindings: bindings} + if r := fn(sb); r != nil { + return r + } + return sb +} + +func (sb *StructuredBindings) GoString() string { + return sb.goString(0, "") +} + +func (sb *StructuredBindings) goString(indent int, field string) string { + var strb strings.Builder + fmt.Fprintf(&strb, "%*s%sStructuredBinding:", indent, "", field) + for _, b := range sb.Bindings { + strb.WriteByte('\n') + strb.WriteString(b.goString(indent+2, "")) + } + return strb.String() } // UnnamedType is an unnamed type, that just has an index. @@ -2911,7 +3753,15 @@ type UnnamedType struct { } func (ut *UnnamedType) print(ps *printState) { - ps.writeString(fmt.Sprintf("{unnamed type#%d}", ut.Num+1)) + if ps.llvmStyle { + if ut.Num == 0 { + ps.writeString("'unnamed'") + } else { + ps.writeString(fmt.Sprintf("'unnamed%d'", ut.Num-1)) + } + } else { + ps.writeString(fmt.Sprintf("{unnamed type#%d}", ut.Num+1)) + } } func (ut *UnnamedType) Traverse(fn func(AST) bool) { @@ -2941,7 +3791,13 @@ type Clone struct { func (c *Clone) print(ps *printState) { ps.print(c.Base) - ps.writeString(fmt.Sprintf(" [clone %s]", c.Suffix)) + if ps.llvmStyle { + ps.writeString(" (") + ps.writeString(c.Suffix) + ps.writeByte(')') + } else { + ps.writeString(fmt.Sprintf(" [clone %s]", c.Suffix)) + } } func (c *Clone) Traverse(fn func(AST) bool) { @@ -2982,7 +3838,16 @@ type Special struct { } func (s *Special) print(ps *printState) { - ps.writeString(s.Prefix) + prefix := s.Prefix + if ps.llvmStyle { + switch prefix { + case "TLS wrapper function for ": + prefix = "thread-local wrapper routine for " + case "TLS init function for ": + prefix = "thread-local initialization routine for " + } + } + ps.writeString(prefix) ps.print(s.Val) } @@ -3194,7 +4059,12 @@ func (ps *printState) printOneInner(save *[]AST) { func (ps *printState) isEmpty(a AST) bool { switch a := a.(type) { case *ArgumentPack: - return len(a.Args) == 0 + for _, a := range a.Args { + if !ps.isEmpty(a) { + return false + } + } + return true case *ExprList: return len(a.Exprs) == 0 case *PackExpansion: diff --git a/src/cmd/vendor/github.com/ianlancetaylor/demangle/demangle.go b/src/cmd/vendor/github.com/ianlancetaylor/demangle/demangle.go index c2667446df..9eec0aa3c8 100644 --- a/src/cmd/vendor/github.com/ianlancetaylor/demangle/demangle.go +++ b/src/cmd/vendor/github.com/ianlancetaylor/demangle/demangle.go @@ -2,9 +2,12 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Package demangle defines functions that demangle GCC/LLVM C++ symbol names. +// Package demangle defines functions that demangle GCC/LLVM +// C++ and Rust symbol names. // This package recognizes names that were mangled according to the C++ ABI -// defined at http://codesourcery.com/cxx-abi/. +// defined at http://codesourcery.com/cxx-abi/ and the Rust ABI +// defined at +// https://rust-lang.github.io/rfcs/2603-rust-symbol-name-mangling-v0.html // // Most programs will want to call Filter or ToString. package demangle @@ -17,7 +20,7 @@ import ( // ErrNotMangledName is returned by CheckedDemangle if the string does // not appear to be a C++ symbol name. -var ErrNotMangledName = errors.New("not a C++ mangled name") +var ErrNotMangledName = errors.New("not a C++ or Rust mangled name") // Option is the type of demangler options. type Option int @@ -33,11 +36,23 @@ const ( // NoParams implies NoClones. NoClones + // The NoRust option disables demangling of old-style Rust + // mangled names, which can be confused with C++ style mangled + // names. New style Rust mangled names are still recognized. + NoRust + // The Verbose option turns on more verbose demangling. Verbose + + // LLVMStyle tries to translate an AST to a string in the + // style of the LLVM demangler. This does not affect + // the parsing of the AST, only the conversion of the AST + // to a string. + LLVMStyle ) -// Filter demangles a C++ symbol name, returning the human-readable C++ name. +// Filter demangles a C++ or Rust symbol name, +// returning the human-readable C++ or Rust name. // If any error occurs during demangling, the input string is returned. func Filter(name string, options ...Option) string { ret, err := ToString(name, options...) @@ -47,11 +62,34 @@ func Filter(name string, options ...Option) string { return ret } -// 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. +// ToString demangles a C++ or Rust symbol name, +// returning a human-readable C++ or Rust name or an error. +// If the name does not appear to be a C++ or Rust symbol name at all, +// the error will be ErrNotMangledName. func ToString(name string, options ...Option) (string, error) { + if strings.HasPrefix(name, "_R") { + return rustToString(name, options) + } + + // Check for an old-style Rust mangled name. + // It starts with _ZN and ends with "17h" followed by 16 hex digits + // followed by "E". + if strings.HasPrefix(name, "_ZN") && strings.HasSuffix(name, "E") && len(name) > 23 && name[len(name)-20:len(name)-17] == "17h" { + noRust := false + for _, o := range options { + if o == NoRust { + noRust = true + break + } + } + if !noRust { + s, ok := oldRustToString(name, options) + if ok { + return s, nil + } + } + } + a, err := ToAST(name, options...) if err != nil { return "", err @@ -65,12 +103,37 @@ func ToString(name string, options ...Option) (string, error) { // the parameter types are not demangled. // If the name does not appear to be a C++ symbol name at all, the // error will be ErrNotMangledName. +// This function does not currently support Rust symbol names. func ToAST(name string, options ...Option) (AST, error) { if strings.HasPrefix(name, "_Z") { a, err := doDemangle(name[2:], options...) return a, adjustErr(err, 2) } + if strings.HasPrefix(name, "___Z") { + // clang extensions + block := strings.LastIndex(name, "_block_invoke") + if block == -1 { + return nil, ErrNotMangledName + } + a, err := doDemangle(name[4:block], options...) + if err != nil { + return a, adjustErr(err, 4) + } + name = strings.TrimPrefix(name[block:], "_block_invoke") + if len(name) > 0 && name[0] == '_' { + name = name[1:] + } + for len(name) > 0 && isDigit(name[0]) { + name = name[1:] + } + if len(name) > 0 && name[0] != '.' { + return nil, errors.New("unparsed characters at end of mangled name") + } + a = &Special{Prefix: "invocation function for block in ", Val: a} + return a, nil + } + const prefix = "_GLOBAL_" if strings.HasPrefix(name, prefix) { // The standard demangler ignores NoParams for global @@ -150,12 +213,13 @@ func doDemangle(name string, options ...Option) (ret AST, err error) { case NoParams: params = false clones = false - case NoTemplateParams: - // This is a valid option but only affect printing of the AST. case NoClones: clones = false case Verbose: verbose = true + case NoTemplateParams, LLVMStyle: + // These are valid options but only affect + // printing of the AST. default: return nil, fmt.Errorf("unrecognized demangler option %v", o) } @@ -185,7 +249,16 @@ 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 + + // The number of entries in templates when we started parsing + // a lambda, plus 1 so that 0 means not parsing a lambda. + lambdaTemplateLevel int + + // Counts of template parameters without template arguments, + // for lambdas. + typeTemplateParamCount int + nonTypeTemplateParamCount int + templateTemplateParamCount int } // copy returns a copy of the current state. @@ -308,35 +381,40 @@ func (st *state) encoding(params bool, local forLocalNameType) AST { return a } - check := a - mwq, _ := check.(*MethodWithQualifiers) - if mwq != nil { - check = mwq.Method + mwq, _ := a.(*MethodWithQualifiers) + + var findTemplate func(AST) *Template + findTemplate = func(check AST) *Template { + switch check := check.(type) { + case *Template: + return check + case *Qualified: + if check.LocalName { + return findTemplate(check.Name) + } else if _, ok := check.Name.(*Constructor); ok { + return findTemplate(check.Name) + } + case *MethodWithQualifiers: + return findTemplate(check.Method) + case *Constructor: + if check.Base != nil { + return findTemplate(check.Base) + } + } + return nil } - 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 + template := findTemplate(a) + var oldLambdaTemplateLevel int if template != nil { st.templates = append(st.templates, template) - oldInLambda = st.inLambda - st.inLambda = 0 + oldLambdaTemplateLevel = st.lambdaTemplateLevel + st.lambdaTemplateLevel = 0 } // Checking for the enable_if attribute here is what the LLVM // demangler does. This is not very general but perhaps it is - // sufficent. + // sufficient. const enableIfPrefix = "Ua9enable_ifI" var enableIfArgs []AST if strings.HasPrefix(st.str, enableIfPrefix) { @@ -348,7 +426,7 @@ func (st *state) encoding(params bool, local forLocalNameType) AST { if template != nil { st.templates = st.templates[:len(st.templates)-1] - st.inLambda = oldInLambda + st.lambdaTemplateLevel = oldLambdaTemplateLevel } ft = simplify(ft) @@ -357,7 +435,7 @@ func (st *state) encoding(params bool, local forLocalNameType) AST { // doesn't get confused with the top level return type. if local == forLocalName { if functype, ok := ft.(*FunctionType); ok { - functype.Return = nil + functype.ForLocalName = true } } @@ -573,7 +651,7 @@ func (st *state) prefix() AST { var next AST c := st.str[0] - if isDigit(c) || isLower(c) || c == 'U' || c == 'L' { + if isDigit(c) || isLower(c) || c == 'U' || c == 'L' || (c == 'D' && len(st.str) > 1 && st.str[1] == 'C') { un, isUnCast := st.unqualifiedName() next = un if isUnCast { @@ -595,10 +673,17 @@ func (st *state) prefix() AST { st.fail("constructor before name is seen") } st.advance(1) + var base AST if inheriting { - last = st.demangleType(false) + base = st.demangleType(false) + } + next = &Constructor{ + Name: getLast(last), + Base: base, + } + if len(st.str) > 0 && st.str[0] == 'B' { + next = st.taggedName(next) } - next = &Constructor{Name: getLast(last)} case 'D': if len(st.str) > 1 && (st.str[1] == 'T' || st.str[1] == 't') { next = st.demangleType(false) @@ -611,6 +696,9 @@ func (st *state) prefix() AST { } st.advance(2) next = &Destructor{Name: getLast(last)} + if len(st.str) > 0 && st.str[0] == 'B' { + next = st.taggedName(next) + } } case 'S': next = st.substitution(true) @@ -713,6 +801,18 @@ func (st *state) unqualifiedName() (r AST, isCast bool) { n := st.sourceName() a = &Unary{Op: op, Expr: n, Suffix: false, SizeofType: false} } + } else if c == 'D' && len(st.str) > 1 && st.str[1] == 'C' { + var bindings []AST + st.advance(2) + for { + binding := st.sourceName() + bindings = append(bindings, binding) + if len(st.str) > 0 && st.str[0] == 'E' { + st.advance(1) + break + } + } + a = &StructuredBindings{Bindings: bindings} } else { switch c { case 'C', 'D': @@ -728,6 +828,10 @@ func (st *state) unqualifiedName() (r AST, isCast bool) { } c := st.str[1] switch c { + case 'b': + st.advance(2) + st.compactNumber() + a = &Name{Name: "'block-literal'"} case 'l': a = st.closureTypeName() case 't': @@ -802,6 +906,42 @@ func (st *state) number() int { return val } +// ::= <0-9A-Z>+ +// +// We expect this to be followed by an underscore. +func (st *state) seqID(eofOK bool) int { + if len(st.str) > 0 && st.str[0] == '_' { + st.advance(1) + return 0 + } + id := 0 + for { + if len(st.str) == 0 { + if eofOK { + return id + 1 + } + st.fail("missing end to sequence ID") + } + // Don't overflow a 32-bit int. + if id >= 0x80000000/36-36 { + st.fail("sequence ID overflow") + } + c := st.str[0] + if c == '_' { + st.advance(1) + return id + 1 + } + if isDigit(c) { + id = id*36 + int(c-'0') + } else if isUpper(c) { + id = id*36 + int(c-'A') + 10 + } else { + st.fail("invalid character in sequence ID") + } + st.advance(1) + } +} + // An operator is the demangled name, and the number of arguments it // takes in an expression. type operator struct { @@ -864,6 +1004,7 @@ var operators = map[string]operator{ "ng": {"-", 1}, "nt": {"!", 1}, "nw": {"new", 3}, + "nx": {"noexcept", 1}, "oR": {"|=", 2}, "oo": {"||", 2}, "or": {"|", 2}, @@ -1094,8 +1235,8 @@ func (st *state) specialName() AST { return &Special{Prefix: "guard variable for ", Val: n} case 'R': n := st.name() - i := st.number() - return &Special{Prefix: fmt.Sprintf("reference temporary #%d for ", i), Val: n} + st.seqID(true) + return &Special{Prefix: "reference temporary for ", Val: n} case 'A': v := st.encoding(true, notForLocalName) return &Special{Prefix: "hidden alias for ", Val: v} @@ -1257,6 +1398,23 @@ func (st *state) demangleType(isCast bool) AST { case 'M': ret = st.pointerToMemberType(isCast) case 'T': + if len(st.str) > 1 && (st.str[1] == 's' || st.str[1] == 'u' || st.str[1] == 'e') { + c = st.str[1] + st.advance(2) + ret = st.name() + var kind string + switch c { + case 's': + kind = "struct" + case 'u': + kind = "union" + case 'e': + kind = "enum" + } + ret = &ElaboratedType{Kind: kind, Type: ret} + break + } + ret = st.templateParam() if len(st.str) > 0 && st.str[0] == 'I' { // See the function comment to explain this. @@ -1681,7 +1839,11 @@ func (st *state) bareFunctionType(hasReturnType bool) AST { returnType = st.demangleType(false) } types := st.parmlist() - return &FunctionType{Return: returnType, Args: types} + return &FunctionType{ + Return: returnType, + Args: types, + ForLocalName: false, // may be set later in encoding + } } // ::= A <(positive dimension) number> _ <(element) type> @@ -1798,6 +1960,8 @@ func (st *state) compactNumber() int { // ::= T_ // ::= T <(parameter-2 non-negative) number> _ +// ::= TL __ +// ::= TL _ _ // // When a template parameter is a substitution candidate, any // reference to that substitution refers to the template parameter @@ -1805,22 +1969,27 @@ 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 && st.inLambda == 0 { - st.fail("template parameter not in scope of template") - } off := st.off - st.checkChar('T') + + level := 0 + if len(st.str) > 0 && st.str[0] == 'L' { + st.advance(1) + level = st.compactNumber() + } + 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} + if level >= len(st.templates) { + if st.lambdaTemplateLevel > 0 && level == st.lambdaTemplateLevel-1 { + // Lambda auto params are mangled as template params. + // See https://gcc.gnu.org/PR78252. + return &LambdaAuto{Index: n} + } + st.failEarlier(fmt.Sprintf("template parameter is not in scope of template (level %d >= %d)", level, len(st.templates)), st.off-off) } - template := st.templates[len(st.templates)-1] + template := st.templates[level] if template == nil { // We are parsing a cast operator. If the cast is @@ -1830,6 +1999,11 @@ func (st *state) templateParam() AST { } if n >= len(template.Args) { + if st.lambdaTemplateLevel > 0 && level == st.lambdaTemplateLevel-1 { + // Lambda auto params are mangled as template params. + // See https://gcc.gnu.org/PR78252. + return &LambdaAuto{Index: n} + } st.failEarlier(fmt.Sprintf("template index out of range (%d >= %d)", n, len(template.Args)), st.off-off) } @@ -1968,9 +2142,11 @@ func (st *state) exprList(stop byte) AST { // ::= dc // ::= sc // ::= cc +// ::= mc [] E // ::= rc // ::= ti // ::= te +// ::= so [] * [p] E // ::= st // ::= sz // ::= at @@ -1991,6 +2167,7 @@ func (st *state) exprList(stop byte) AST { // ::= fR // ::= tw // ::= tr +// ::= u * E // ::= // ::= // @@ -2013,6 +2190,9 @@ func (st *state) expression() AST { return st.exprPrimary() } else if st.str[0] == 'T' { return st.templateParam() + } else if st.str[0] == 's' && len(st.str) > 1 && st.str[1] == 'o' { + st.advance(2) + return st.subobject() } else if st.str[0] == 's' && len(st.str) > 1 && st.str[1] == 'r' { return st.unresolvedName() } else if st.str[0] == 's' && len(st.str) > 1 && st.str[1] == 'p' { @@ -2063,6 +2243,23 @@ func (st *state) expression() AST { st.cvQualifiers() index := st.compactNumber() return &FunctionParam{Index: index + 1} + } else if st.str[0] == 'm' && len(st.str) > 1 && st.str[1] == 'c' { + st.advance(2) + typ := st.demangleType(false) + expr := st.expression() + offset := 0 + if len(st.str) > 0 && (st.str[0] == 'n' || isDigit(st.str[0])) { + offset = st.number() + } + if len(st.str) == 0 || st.str[0] != 'E' { + st.fail("expected E after pointer-to-member conversion") + } + st.advance(1) + return &PtrMemCast{ + Type: typ, + Expr: expr, + Offset: offset, + } } 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. @@ -2088,6 +2285,50 @@ func (st *state) expression() AST { o, _ := st.operatorName(true) t := st.demangleType(false) return &Unary{Op: o, Expr: t, Suffix: false, SizeofType: true} + } else if st.str[0] == 'u' { + st.advance(1) + name := st.sourceName() + // Special case __uuidof followed by type or + // expression, as used by LLVM. + if n, ok := name.(*Name); ok && n.Name == "__uuidof" { + if len(st.str) < 2 { + st.fail("missing uuidof argument") + } + var operand AST + if st.str[0] == 't' { + st.advance(1) + operand = st.demangleType(false) + } else if st.str[0] == 'z' { + st.advance(1) + operand = st.expression() + } + if operand != nil { + return &Binary{ + Op: &Operator{Name: "()"}, + Left: name, + Right: &ExprList{ + Exprs: []AST{operand}, + }, + } + } + } + var args []AST + for { + if len(st.str) == 0 { + st.fail("missing argument in vendor extended expressoin") + } + if st.str[0] == 'E' { + st.advance(1) + break + } + arg := st.templateArg() + args = append(args, arg) + } + return &Binary{ + Op: &Operator{Name: "()"}, + Left: name, + Right: &ExprList{Exprs: args}, + } } else { if len(st.str) < 2 { st.fail("missing operator code") @@ -2185,6 +2426,42 @@ func (st *state) expression() AST { } } +// ::= so [] * [p] E +// ::= _ [] +func (st *state) subobject() AST { + typ := st.demangleType(false) + expr := st.expression() + offset := 0 + if len(st.str) > 0 && (st.str[0] == 'n' || isDigit(st.str[0])) { + offset = st.number() + } + var selectors []int + for len(st.str) > 0 && st.str[0] == '_' { + st.advance(1) + selector := 0 + if len(st.str) > 0 && (st.str[0] == 'n' || isDigit(st.str[0])) { + selector = st.number() + } + selectors = append(selectors, selector) + } + pastEnd := false + if len(st.str) > 0 && st.str[0] == 'p' { + st.advance(1) + pastEnd = true + } + if len(st.str) == 0 || st.str[0] != 'E' { + st.fail("expected E after subobject") + } + st.advance(1) + return &Subobject{ + Type: typ, + SubExpr: expr, + Offset: offset, + Selectors: selectors, + PastEnd: pastEnd, + } +} + // ::= [gs] // ::= sr // ::= srN + E @@ -2320,6 +2597,14 @@ func (st *state) exprPrimary() AST { } else { t := st.demangleType(false) + isArrayType := func(typ AST) bool { + if twq, ok := typ.(*TypeWithQualifiers); ok { + typ = twq.Base + } + _, ok := typ.(*ArrayType) + return ok + } + neg := false if len(st.str) > 0 && st.str[0] == 'n' { neg = true @@ -2331,6 +2616,13 @@ func (st *state) exprPrimary() AST { // We accept one if present because GCC // used to generate one. // https://gcc.gnu.org/PR91979. + } else if cl, ok := t.(*Closure); ok { + // A closure doesn't have a value. + st.advance(1) + return &LambdaExpr{Type: cl} + } else if isArrayType(t) { + st.advance(1) + return &StringLiteral{Type: t} } else { st.fail("missing literal value") } @@ -2354,6 +2646,15 @@ func (st *state) exprPrimary() AST { // __ <(non-negative) number> _ (when number >= 10) func (st *state) discriminator(a AST) AST { if len(st.str) == 0 || st.str[0] != '_' { + // clang can generate a discriminator at the end of + // the string with no underscore. + for i := 0; i < len(st.str); i++ { + if !isDigit(st.str[i]) { + return a + } + } + // Skip the trailing digits. + st.advance(len(st.str)) return a } off := st.off @@ -2379,18 +2680,131 @@ func (st *state) discriminator(a AST) AST { } // ::= Ul E [ ] _ +// ::= + func (st *state) closureTypeName() AST { st.checkChar('U') st.checkChar('l') - st.inLambda++ + + oldLambdaTemplateLevel := st.lambdaTemplateLevel + st.lambdaTemplateLevel = len(st.templates) + 1 + + var templateArgs []AST + var template *Template + for len(st.str) > 1 && st.str[0] == 'T' { + arg, templateVal := st.templateParamDecl() + if arg == nil { + break + } + templateArgs = append(templateArgs, arg) + if template == nil { + template = &Template{ + Name: &Name{Name: "lambda"}, + } + st.templates = append(st.templates, template) + } + template.Args = append(template.Args, templateVal) + } + types := st.parmlist() - st.inLambda-- + + st.lambdaTemplateLevel = oldLambdaTemplateLevel + + if template != nil { + st.templates = st.templates[:len(st.templates)-1] + } + if len(st.str) == 0 || st.str[0] != 'E' { st.fail("expected E after closure type name") } st.advance(1) num := st.compactNumber() - return &Closure{Types: types, Num: num} + return &Closure{TemplateArgs: templateArgs, Types: types, Num: num} +} + +// ::= Ty # type parameter +// ::= Tn # non-type parameter +// ::= Tt * E # template parameter +// ::= Tp # parameter pack +// +// Returns the new AST to include in the AST we are building and the +// new AST to add to the list of template parameters. +// +// Returns nil, nil if not looking at a template-param-decl. +func (st *state) templateParamDecl() (AST, AST) { + if len(st.str) < 2 || st.str[0] != 'T' { + return nil, nil + } + mk := func(prefix string, p *int) AST { + idx := *p + (*p)++ + return &TemplateParamName{ + Prefix: prefix, + Index: idx, + } + } + switch st.str[1] { + case 'y': + st.advance(2) + name := mk("$T", &st.typeTemplateParamCount) + tp := &TypeTemplateParam{ + Name: name, + } + return tp, name + case 'n': + st.advance(2) + name := mk("$N", &st.nonTypeTemplateParamCount) + typ := st.demangleType(false) + tp := &NonTypeTemplateParam{ + Name: name, + Type: typ, + } + return tp, name + case 't': + st.advance(2) + name := mk("$TT", &st.templateTemplateParamCount) + var params []AST + var template *Template + for { + if len(st.str) == 0 { + st.fail("expected closure template parameter") + } + if st.str[0] == 'E' { + st.advance(1) + break + } + off := st.off + param, templateVal := st.templateParamDecl() + if param == nil { + st.failEarlier("expected closure template parameter", st.off-off) + } + params = append(params, param) + if template == nil { + template = &Template{ + Name: &Name{Name: "template_template"}, + } + st.templates = append(st.templates, template) + } + template.Args = append(template.Args, templateVal) + } + if template != nil { + st.templates = st.templates[:len(st.templates)-1] + } + tp := &TemplateTemplateParam{ + Name: name, + Params: params, + } + return tp, name + case 'p': + st.advance(2) + off := st.off + param, templateVal := st.templateParamDecl() + if param == nil { + st.failEarlier("expected lambda template parameter", st.off-off) + } + return &TemplateParamPack{Param: param}, templateVal + default: + return nil, nil + } } // ::= Ut [ ] _ @@ -2504,36 +2918,11 @@ func (st *state) substitution(forPrefix bool) AST { st.fail("missing substitution index") } c := st.str[0] - st.advance(1) - dec := 1 + off := st.off if c == '_' || isDigit(c) || isUpper(c) { - id := 0 - if c != '_' { - for c != '_' { - // Don't overflow a 32-bit int. - if id >= 0x80000000/36-36 { - st.fail("substitution index overflow") - } - if isDigit(c) { - id = id*36 + int(c-'0') - } else if isUpper(c) { - id = id*36 + int(c-'A') + 10 - } else { - st.fail("invalid character in substitution index") - } - - if len(st.str) == 0 { - st.fail("missing end to substitution index") - } - c = st.str[0] - st.advance(1) - dec++ - } - id++ - } - + id := st.seqID(false) if id >= len(st.subs) { - st.failEarlier(fmt.Sprintf("substitution index out of range (%d >= %d)", id, len(st.subs)), dec) + st.failEarlier(fmt.Sprintf("substitution index out of range (%d >= %d)", id, len(st.subs)), st.off-off) } ret := st.subs[id] @@ -2545,18 +2934,18 @@ func (st *state) substitution(forPrefix bool) AST { // When copying a Typed we may need to adjust // the templates. copyTemplates := st.templates - var oldInLambda []int + var oldLambdaTemplateLevel []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 + oldLambdaTemplateLevel = append(oldLambdaTemplateLevel, st.lambdaTemplateLevel) + st.lambdaTemplateLevel = 0 } popTemplate := func() { copyTemplates = copyTemplates[:len(copyTemplates)-1] - st.inLambda = oldInLambda[len(oldInLambda)-1] - oldInLambda = oldInLambda[:len(oldInLambda)-1] + st.lambdaTemplateLevel = oldLambdaTemplateLevel[len(oldLambdaTemplateLevel)-1] + oldLambdaTemplateLevel = oldLambdaTemplateLevel[:len(oldLambdaTemplateLevel)-1] } copy := func(a AST) AST { @@ -2569,8 +2958,9 @@ func (st *state) substitution(forPrefix bool) AST { } return nil case *Closure: - // Undo the decrement in skip. - st.inLambda-- + // Undo the save in skip. + st.lambdaTemplateLevel = oldLambdaTemplateLevel[len(oldLambdaTemplateLevel)-1] + oldLambdaTemplateLevel = oldLambdaTemplateLevel[:len(oldLambdaTemplateLevel)-1] return nil case *TemplateParam: index = a.Index @@ -2582,7 +2972,7 @@ func (st *state) substitution(forPrefix bool) AST { default: return nil } - if st.inLambda > 0 { + if st.lambdaTemplateLevel > 0 { if _, ok := a.(*LambdaAuto); ok { return nil } @@ -2598,7 +2988,7 @@ func (st *state) substitution(forPrefix bool) AST { // here. template = rt } else { - st.failEarlier("substituted template parameter not in scope of template", dec) + st.failEarlier("substituted template parameter not in scope of template", st.off-off) } if template == nil { // This template parameter is within @@ -2607,7 +2997,7 @@ func (st *state) substitution(forPrefix bool) AST { } if index >= len(template.Args) { - st.failEarlier(fmt.Sprintf("substituted template index out of range (%d >= %d)", index, len(template.Args)), dec) + st.failEarlier(fmt.Sprintf("substituted template index out of range (%d >= %d)", index, len(template.Args)), st.off-off) } return &TemplateParam{Index: index, Template: template} @@ -2622,8 +3012,9 @@ func (st *state) substitution(forPrefix bool) AST { } return false case *Closure: - // This is decremented in copy. - st.inLambda++ + // This is undone in copy. + oldLambdaTemplateLevel = append(oldLambdaTemplateLevel, st.lambdaTemplateLevel) + st.lambdaTemplateLevel = len(copyTemplates) + 1 return false case *TemplateParam, *LambdaAuto: return false @@ -2643,6 +3034,7 @@ func (st *state) substitution(forPrefix bool) AST { return ret } else { + st.advance(1) m := subAST if st.verbose { m = verboseAST diff --git a/src/cmd/vendor/github.com/ianlancetaylor/demangle/rust.go b/src/cmd/vendor/github.com/ianlancetaylor/demangle/rust.go new file mode 100644 index 0000000000..140b631644 --- /dev/null +++ b/src/cmd/vendor/github.com/ianlancetaylor/demangle/rust.go @@ -0,0 +1,1069 @@ +// Copyright 2021 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 demangle + +import ( + "fmt" + "math" + "math/bits" + "strings" + "unicode/utf8" +) + +// rustToString demangles a Rust symbol. +func rustToString(name string, options []Option) (ret string, err error) { + if !strings.HasPrefix(name, "_R") { + return "", ErrNotMangledName + } + + // When the demangling routines encounter an error, they panic + // with a value of type demangleErr. + defer func() { + if r := recover(); r != nil { + if de, ok := r.(demangleErr); ok { + ret = "" + err = de + return + } + panic(r) + } + }() + + suffix := "" + dot := strings.Index(name, ".") + if dot >= 0 { + suffix = name[dot:] + name = name[:dot] + } + + name = name[2:] + rst := &rustState{orig: name, str: name} + rst.symbolName() + + if len(rst.str) > 0 { + rst.fail("unparsed characters at end of mangled name") + } + + if suffix != "" { + rst.skip = false + rst.writeString(" (") + rst.writeString(suffix) + rst.writeByte(')') + } + + return rst.buf.String(), nil +} + +// A rustState holds the current state of demangling a Rust string. +type rustState struct { + orig string // the original string being demangled + str string // remainder of string to demangle + off int // offset of str within original string + buf strings.Builder // demangled string being built + skip bool // don't print, just skip + lifetimes int64 // number of bound lifetimes + last byte // last byte written to buffer +} + +// fail panics with demangleErr, to be caught in rustToString. +func (rst *rustState) fail(err string) { + panic(demangleErr{err: err, off: rst.off}) +} + +// advance advances the current string offset. +func (rst *rustState) advance(add int) { + if len(rst.str) < add { + panic("internal error") + } + rst.str = rst.str[add:] + rst.off += add +} + +// checkChar requires that the next character in the string be c, +// and advances past it. +func (rst *rustState) checkChar(c byte) { + if len(rst.str) == 0 || rst.str[0] != c { + rst.fail("expected " + string(c)) + } + rst.advance(1) +} + +// writeByte writes a byte to the buffer. +func (rst *rustState) writeByte(c byte) { + if rst.skip { + return + } + rst.last = c + rst.buf.WriteByte(c) +} + +// writeString writes a string to the buffer. +func (rst *rustState) writeString(s string) { + if rst.skip { + return + } + if len(s) > 0 { + rst.last = s[len(s)-1] + rst.buf.WriteString(s) + } +} + +// = "_R" [] [] +// = +// +// We've already skipped the "_R". +func (rst *rustState) symbolName() { + if len(rst.str) < 1 { + rst.fail("expected symbol-name") + } + + if isDigit(rst.str[0]) { + rst.fail("unsupported Rust encoding version") + } + + rst.path(true) + + if len(rst.str) > 0 { + rst.skip = true + rst.path(false) + } +} + +// = "C" // crate root +// | "M" // (inherent impl) +// | "X" // (trait impl) +// | "Y" // (trait definition) +// | "N" // ...::ident (nested path) +// | "I" {} "E" // ... (generic args) +// | +// = "C" // closure +// | "S" // shim +// | // other special namespaces +// | // internal namespaces +// +// needsSeparator is true if we need to write out :: for a generic; +// it is passed as false if we are in the middle of a type. +func (rst *rustState) path(needsSeparator bool) { + if len(rst.str) < 1 { + rst.fail("expected path") + } + switch c := rst.str[0]; c { + case 'C': + rst.advance(1) + _, ident := rst.identifier() + rst.writeString(ident) + case 'M', 'X': + rst.advance(1) + rst.implPath() + rst.writeByte('<') + rst.demangleType() + if c == 'X' { + rst.writeString(" as ") + rst.path(false) + } + rst.writeByte('>') + case 'Y': + rst.advance(1) + rst.writeByte('<') + rst.demangleType() + rst.writeString(" as ") + rst.path(false) + rst.writeByte('>') + case 'N': + rst.advance(1) + + if len(rst.str) < 1 { + rst.fail("expected namespace") + } + ns := rst.str[0] + switch { + case ns >= 'a' && ns <= 'z': + case ns >= 'A' && ns <= 'Z': + default: + rst.fail("invalid namespace character") + } + rst.advance(1) + + rst.path(needsSeparator) + + dis, ident := rst.identifier() + + if ns >= 'A' && ns <= 'Z' { + rst.writeString("::{") + switch ns { + case 'C': + rst.writeString("closure") + case 'S': + rst.writeString("shim") + default: + rst.writeByte(ns) + } + if len(ident) > 0 { + rst.writeByte(':') + rst.writeString(ident) + } + if !rst.skip { + fmt.Fprintf(&rst.buf, "#%d}", dis) + rst.last = '}' + } + } else { + rst.writeString("::") + rst.writeString(ident) + } + case 'I': + rst.advance(1) + rst.path(needsSeparator) + if needsSeparator { + rst.writeString("::") + } + rst.writeByte('<') + first := true + for len(rst.str) > 0 && rst.str[0] != 'E' { + if first { + first = false + } else { + rst.writeString(", ") + } + rst.genericArg() + } + rst.writeByte('>') + rst.checkChar('E') + case 'B': + rst.backref(func() { rst.path(needsSeparator) }) + default: + rst.fail("unrecognized letter in path") + } +} + +// = [] +func (rst *rustState) implPath() { + // This path is not part of the demangled string. + hold := rst.skip + rst.skip = true + defer func() { + rst.skip = hold + }() + + rst.disambiguator() + rst.path(false) +} + +// = [] +// Returns the disambiguator and the identifier. +func (rst *rustState) identifier() (int64, string) { + dis := rst.disambiguator() + ident := rst.undisambiguatedIdentifier() + return dis, ident +} + +// = "s" +// This is optional. +func (rst *rustState) disambiguator() int64 { + if len(rst.str) == 0 || rst.str[0] != 's' { + return 0 + } + rst.advance(1) + return rst.base62Number() + 1 +} + +// = ["u"] ["_"] +func (rst *rustState) undisambiguatedIdentifier() string { + punycode := false + if len(rst.str) > 0 && rst.str[0] == 'u' { + rst.advance(1) + punycode = true + } + + val := rst.decimalNumber() + + if len(rst.str) > 0 && rst.str[0] == '_' { + rst.advance(1) + } + + if len(rst.str) < val { + rst.fail("not enough characters for identifier") + } + id := rst.str[:val] + rst.advance(val) + + for i := 0; i < len(id); i++ { + c := id[i] + switch { + case c >= '0' && c <= '9': + case c >= 'A' && c <= 'Z': + case c >= 'a' && c <= 'z': + case c == '_': + default: + rst.fail("invalid character in identifier") + } + } + + if punycode { + id = rst.expandPunycode(id) + } + + return id +} + +// expandPunycode decodes the Rust version of punycode. +// This algorithm is taken from RFC 3492 section 6.2. +func (rst *rustState) expandPunycode(s string) string { + const ( + base = 36 + tmin = 1 + tmax = 26 + skew = 38 + damp = 700 + initialBias = 72 + initialN = 128 + ) + + idx := strings.LastIndex(s, "_") + if idx < 0 { + rst.fail("missing underscore in punycode string") + } + + output := []rune(s[:idx]) + encoding := s[idx+1:] + + i := 0 + n := initialN + bias := initialBias + + pos := 0 + for pos < len(encoding) { + oldI := i + w := 1 + for k := base; ; k += base { + if pos == len(encoding) { + rst.fail("unterminated punycode") + } + + var digit byte + d := encoding[pos] + pos++ + switch { + case '0' <= d && d <= '9': + digit = d - '0' + 26 + case 'A' <= d && d <= 'Z': + digit = d - 'A' + case 'a' <= d && d <= 'z': + digit = d - 'a' + default: + rst.fail("invalid punycode digit") + } + + i += int(digit) * w + if i < 0 { + rst.fail("punycode number overflow") + } + + var t int + if k <= bias { + t = tmin + } else if k > bias+tmax { + t = tmax + } else { + t = k - bias + } + + if int(digit) < t { + break + } + + if w >= math.MaxInt32/base { + rst.fail("punycode number overflow") + } + w *= base - t + } + + delta := i - oldI + numPoints := len(output) + 1 + firstTime := oldI == 0 + if firstTime { + delta /= damp + } else { + delta /= 2 + } + delta += delta / numPoints + k := 0 + for delta > ((base-tmin)*tmax)/2 { + delta /= base - tmin + k += base + } + bias = k + ((base-tmin+1)*delta)/(delta+skew) + + n += i / (len(output) + 1) + if n > utf8.MaxRune { + rst.fail("punycode rune overflow") + } + i %= len(output) + 1 + output = append(output, 0) + copy(output[i+1:], output[i:]) + output[i] = rune(n) + i++ + } + + return string(output) +} + +// = +// | +// | "K" // forward-compat for const generics +// = "L" +func (rst *rustState) genericArg() { + if len(rst.str) < 1 { + rst.fail("expected generic-arg") + } + if rst.str[0] == 'L' { + rst.advance(1) + rst.writeLifetime(rst.base62Number()) + } else if rst.str[0] == 'K' { + rst.advance(1) + rst.demangleConst() + } else { + rst.demangleType() + } +} + +// = "G" +// This is optional. +func (rst *rustState) binder() { + if len(rst.str) < 1 || rst.str[0] != 'G' { + return + } + rst.advance(1) + + binderLifetimes := rst.base62Number() + 1 + + // Every bound lifetime should be referenced later. + if binderLifetimes >= int64(len(rst.str))-rst.lifetimes { + rst.fail("binder lifetimes overflow") + } + + rst.writeString("for<") + for i := int64(0); i < binderLifetimes; i++ { + if i > 0 { + rst.writeString(", ") + } + rst.lifetimes++ + rst.writeLifetime(1) + } + rst.writeString("> ") +} + +// = +// | // named type +// | "A" // [T; N] +// | "S" // [T] +// | "T" {} "E" // (T1, T2, T3, ...) +// | "R" [] // &T +// | "Q" [] // &mut T +// | "P" // *const T +// | "O" // *mut T +// | "F" // fn(...) -> ... +// | "D" // dyn Trait + Send + 'a +// | +func (rst *rustState) demangleType() { + if len(rst.str) < 1 { + rst.fail("expected type") + } + c := rst.str[0] + if c >= 'a' && c <= 'z' { + rst.basicType() + return + } + switch c { + case 'C', 'M', 'X', 'Y', 'N', 'I': + rst.path(false) + case 'A', 'S': + rst.advance(1) + rst.writeByte('[') + rst.demangleType() + if c == 'A' { + rst.writeString("; ") + rst.demangleConst() + } + rst.writeByte(']') + case 'T': + rst.advance(1) + rst.writeByte('(') + c := 0 + for len(rst.str) > 0 && rst.str[0] != 'E' { + if c > 0 { + rst.writeString(", ") + } + c++ + rst.demangleType() + } + if c == 1 { + rst.writeByte(',') + } + rst.writeByte(')') + rst.checkChar('E') + case 'R', 'Q': + rst.advance(1) + rst.writeByte('&') + if len(rst.str) > 0 && rst.str[0] == 'L' { + rst.advance(1) + if lifetime := rst.base62Number(); lifetime > 0 { + rst.writeLifetime(lifetime) + rst.writeByte(' ') + } + } + if c == 'Q' { + rst.writeString("mut ") + } + rst.demangleType() + case 'P': + rst.advance(1) + rst.writeString("*const ") + rst.demangleType() + case 'O': + rst.advance(1) + rst.writeString("*mut ") + rst.demangleType() + case 'F': + rst.advance(1) + hold := rst.lifetimes + rst.fnSig() + rst.lifetimes = hold + case 'D': + rst.advance(1) + hold := rst.lifetimes + rst.dynBounds() + rst.lifetimes = hold + if len(rst.str) == 0 || rst.str[0] != 'L' { + rst.fail("expected L") + } + rst.advance(1) + if lifetime := rst.base62Number(); lifetime > 0 { + if rst.last != ' ' { + rst.writeByte(' ') + } + rst.writeString("+ ") + rst.writeLifetime(lifetime) + } + case 'B': + rst.backref(rst.demangleType) + default: + rst.fail("unrecognized character in type") + } +} + +var rustBasicTypes = map[byte]string{ + 'a': "i8", + 'b': "bool", + 'c': "char", + 'd': "f64", + 'e': "str", + 'f': "f32", + 'h': "u8", + 'i': "isize", + 'j': "usize", + 'l': "i32", + 'm': "u32", + 'n': "i128", + 'o': "u128", + 'p': "_", + 's': "i16", + 't': "u16", + 'u': "()", + 'v': "...", + 'x': "i64", + 'y': "u64", + 'z': "!", +} + +// +func (rst *rustState) basicType() { + if len(rst.str) < 1 { + rst.fail("expected basic type") + } + str, ok := rustBasicTypes[rst.str[0]] + if !ok { + rst.fail("unrecognized basic type character") + } + rst.advance(1) + rst.writeString(str) +} + +// = [] ["U"] ["K" ] {} "E" +// = "C" +// | +func (rst *rustState) fnSig() { + rst.binder() + if len(rst.str) > 0 && rst.str[0] == 'U' { + rst.advance(1) + rst.writeString("unsafe ") + } + if len(rst.str) > 0 && rst.str[0] == 'K' { + rst.advance(1) + if len(rst.str) > 0 && rst.str[0] == 'C' { + rst.advance(1) + rst.writeString(`extern "C" `) + } else { + rst.writeString(`extern "`) + id := rst.undisambiguatedIdentifier() + id = strings.ReplaceAll(id, "_", "-") + rst.writeString(id) + rst.writeString(`" `) + } + } + rst.writeString("fn(") + first := true + for len(rst.str) > 0 && rst.str[0] != 'E' { + if first { + first = false + } else { + rst.writeString(", ") + } + rst.demangleType() + } + rst.checkChar('E') + rst.writeByte(')') + if len(rst.str) > 0 && rst.str[0] == 'u' { + rst.advance(1) + } else { + rst.writeString(" -> ") + rst.demangleType() + } +} + +// = [] {} "E" +func (rst *rustState) dynBounds() { + rst.writeString("dyn ") + rst.binder() + first := true + for len(rst.str) > 0 && rst.str[0] != 'E' { + if first { + first = false + } else { + rst.writeString(" + ") + } + rst.dynTrait() + } + rst.checkChar('E') +} + +// = {} +// = "p" +func (rst *rustState) dynTrait() { + started := rst.pathStartGenerics() + for len(rst.str) > 0 && rst.str[0] == 'p' { + rst.advance(1) + if started { + rst.writeString(", ") + } else { + rst.writeByte('<') + started = true + } + rst.writeString(rst.undisambiguatedIdentifier()) + rst.writeString(" = ") + rst.demangleType() + } + if started { + rst.writeByte('>') + } +} + +// pathStartGenerics is like path but if it sees an I to start generic +// arguments it won't close them. It reports whether it started generics. +func (rst *rustState) pathStartGenerics() bool { + if len(rst.str) < 1 { + rst.fail("expected path") + } + switch rst.str[0] { + case 'I': + rst.advance(1) + rst.path(false) + rst.writeByte('<') + first := true + for len(rst.str) > 0 && rst.str[0] != 'E' { + if first { + first = false + } else { + rst.writeString(", ") + } + rst.genericArg() + } + rst.checkChar('E') + return true + case 'B': + var started bool + rst.backref(func() { started = rst.pathStartGenerics() }) + return started + default: + rst.path(false) + return false + } +} + +// writeLifetime writes out a lifetime binding. +func (rst *rustState) writeLifetime(lifetime int64) { + rst.writeByte('\'') + if lifetime == 0 { + rst.writeByte('_') + return + } + depth := rst.lifetimes - lifetime + if depth < 0 { + rst.fail("invalid lifetime") + } else if depth < 26 { + rst.writeByte('a' + byte(depth)) + } else { + rst.writeByte('z') + if !rst.skip { + fmt.Fprintf(&rst.buf, "%d", depth-26+1) + rst.last = '0' + } + } +} + +// = +// | "p" // placeholder, shown as _ +// | +// = ["n"] {} "_" +func (rst *rustState) demangleConst() { + if len(rst.str) < 1 { + rst.fail("expected constant") + } + + if rst.str[0] == 'B' { + rst.backref(rst.demangleConst) + return + } + + if rst.str[0] == 'p' { + rst.advance(1) + rst.writeByte('_') + return + } + + typ := rst.str[0] + + const ( + invalid = iota + signedInt + unsignedInt + boolean + character + ) + + var kind int + switch typ { + case 'a', 's', 'l', 'x', 'n', 'i': + kind = signedInt + case 'h', 't', 'm', 'y', 'o', 'j': + kind = unsignedInt + case 'b': + kind = boolean + case 'c': + kind = character + default: + rst.fail("unrecognized constant type") + } + + rst.advance(1) + + if kind == signedInt && len(rst.str) > 0 && rst.str[0] == 'n' { + rst.advance(1) + rst.writeByte('-') + } + + start := rst.str + digits := 0 + val := uint64(0) +digitLoop: + for len(rst.str) > 0 { + c := rst.str[0] + var digit uint64 + switch { + case c >= '0' && c <= '9': + digit = uint64(c - '0') + case c >= 'a' && c <= 'f': + digit = uint64(c - 'a' + 10) + case c == '_': + rst.advance(1) + break digitLoop + default: + rst.fail("expected hex digit or _") + } + rst.advance(1) + if val == 0 && digit == 0 && (len(rst.str) == 0 || rst.str[0] != '_') { + rst.fail("invalid leading 0 in constant") + } + val *= 16 + val += digit + digits++ + } + + if digits == 0 { + rst.fail("expected constant") + } + + switch kind { + case signedInt, unsignedInt: + if digits > 16 { + // Value too big, just write out the string. + rst.writeString("0x") + rst.writeString(start[:digits]) + } else { + if !rst.skip { + fmt.Fprintf(&rst.buf, "%d", val) + rst.last = '0' + } + } + case boolean: + if digits > 1 { + rst.fail("boolean value too large") + } else if val == 0 { + rst.writeString("false") + } else if val == 1 { + rst.writeString("true") + } else { + rst.fail("invalid boolean value") + } + case character: + if digits > 6 { + rst.fail("character value too large") + } + rst.writeByte('\'') + if val == '\t' { + rst.writeString(`\t`) + } else if val == '\r' { + rst.writeString(`\r`) + } else if val == '\n' { + rst.writeString(`\n`) + } else if val == '\\' { + rst.writeString(`\\`) + } else if val == '\'' { + rst.writeString(`\'`) + } else if val >= ' ' && val <= '~' { + // printable ASCII character + rst.writeByte(byte(val)) + } else { + if !rst.skip { + fmt.Fprintf(&rst.buf, `\u{%x}`, val) + rst.last = '}' + } + } + rst.writeByte('\'') + default: + panic("internal error") + } +} + +// = {<0-9a-zA-Z>} "_" +func (rst *rustState) base62Number() int64 { + if len(rst.str) > 0 && rst.str[0] == '_' { + rst.advance(1) + return 0 + } + val := int64(0) + for len(rst.str) > 0 { + c := rst.str[0] + rst.advance(1) + if c == '_' { + return val + 1 + } + val *= 62 + if c >= '0' && c <= '9' { + val += int64(c - '0') + } else if c >= 'a' && c <= 'z' { + val += int64(c - 'a' + 10) + } else if c >= 'A' && c <= 'Z' { + val += int64(c - 'A' + 36) + } else { + rst.fail("invalid digit in base 62 number") + } + } + rst.fail("expected _ after base 62 number") + return 0 +} + +// = "B" +func (rst *rustState) backref(demangle func()) { + backoff := rst.off + + rst.checkChar('B') + idx64 := rst.base62Number() + + if rst.skip { + return + } + + idx := int(idx64) + if int64(idx) != idx64 { + rst.fail("backref index overflow") + } + if idx < 0 || idx >= backoff { + rst.fail("invalid backref index") + } + + holdStr := rst.str + holdOff := rst.off + rst.str = rst.orig[idx:backoff] + rst.off = idx + defer func() { + rst.str = holdStr + rst.off = holdOff + }() + + demangle() +} + +func (rst *rustState) decimalNumber() int { + if len(rst.str) == 0 { + rst.fail("expected number") + } + + val := 0 + for len(rst.str) > 0 && isDigit(rst.str[0]) { + add := int(rst.str[0] - '0') + if val >= math.MaxInt32/10-add { + rst.fail("decimal number overflow") + } + val *= 10 + val += add + rst.advance(1) + } + return val +} + +// oldRustToString demangles a Rust symbol using the old demangling. +// The second result reports whether this is a valid Rust mangled name. +func oldRustToString(name string, options []Option) (string, bool) { + // We know that the string starts with _ZN. + name = name[3:] + + hexDigit := func(c byte) (byte, bool) { + switch { + case c >= '0' && c <= '9': + return c - '0', true + case c >= 'a' && c <= 'f': + return c - 'a' + 10, true + default: + return 0, false + } + } + + // We know that the strings end with "17h" followed by 16 characters + // followed by "E". We check that the 16 characters are all hex digits. + // Also the hex digits must contain at least 5 distinct digits. + seen := uint16(0) + for i := len(name) - 17; i < len(name) - 1; i++ { + digit, ok := hexDigit(name[i]) + if !ok { + return "", false + } + seen |= 1 << digit + } + if bits.OnesCount16(seen) < 5 { + return "", false + } + name = name[:len(name)-20] + + // The name is a sequence of length-preceded identifiers. + var sb strings.Builder + for len(name) > 0 { + if !isDigit(name[0]) { + return "", false + } + + val := 0 + for len(name) > 0 && isDigit(name[0]) { + add := int(name[0] - '0') + if val >= math.MaxInt32/10-add { + return "", false + } + val *= 10 + val += add + name = name[1:] + } + + // An optional trailing underscore can separate the + // length from the identifier. + if len(name) > 0 && name[0] == '_' { + name = name[1:] + val-- + } + + if len(name) < val { + return "", false + } + + id := name[:val] + name = name[val:] + + if sb.Len() > 0 { + sb.WriteString("::") + } + + // Ignore leading underscores preceding escape sequences. + if strings.HasPrefix(id, "_$") { + id = id[1:] + } + + // The identifier can have escape sequences. + escape: + for len(id) > 0 { + switch c := id[0]; c { + case '$': + codes := map[string]byte { + "SP": '@', + "BP": '*', + "RF": '&', + "LT": '<', + "GT": '>', + "LP": '(', + "RP": ')', + } + + valid := true + if len(id) > 2 && id[1] == 'C' && id[2] == '$' { + sb.WriteByte(',') + id = id[3:] + } else if len(id) > 4 && id[1] == 'u' && id[4] == '$' { + dig1, ok1 := hexDigit(id[2]) + dig2, ok2 := hexDigit(id[3]) + val := (dig1 << 4) | dig2 + if !ok1 || !ok2 || dig1 > 7 || val < ' ' { + valid = false + } else { + sb.WriteByte(val) + id = id[5:] + } + } else if len(id) > 3 && id[3] == '$' { + if code, ok := codes[id[1:3]]; !ok { + valid = false + } else { + sb.WriteByte(code) + id = id[4:] + } + } else { + valid = false + } + if !valid { + sb.WriteString(id) + break escape + } + case '.': + if strings.HasPrefix(id, "..") { + sb.WriteString("::") + id = id[2:] + } else { + sb.WriteByte(c) + id = id[1:] + } + default: + sb.WriteByte(c) + id = id[1:] + } + } + } + + return sb.String(), true +} 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 0bcb8c3226..a74ef58f8c 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/mkerrors.sh +++ b/src/cmd/vendor/golang.org/x/sys/unix/mkerrors.sh @@ -54,7 +54,7 @@ includes_AIX=' includes_Darwin=' #define _DARWIN_C_SOURCE -#define KERNEL +#define KERNEL 1 #define _DARWIN_USE_64_BIT_INODE #define __APPLE_USE_RFC_3542 #include @@ -75,6 +75,7 @@ includes_Darwin=' #include #include #include +#include #include #include #include @@ -82,6 +83,9 @@ includes_Darwin=' #include #include #include + +// for backwards compatibility because moved TIOCREMOTE to Kernel.framework after MacOSX12.0.sdk. +#define TIOCREMOTE 0x80047469 ' includes_DragonFly=' @@ -229,6 +233,7 @@ struct ltchars { #include #include #include +#include #include #include #include @@ -465,7 +470,6 @@ ccflags="$@" $2 !~ /^EQUIV_/ && $2 !~ /^EXPR_/ && $2 !~ /^EVIOC/ && - $2 !~ /^EV_/ && $2 ~ /^E[A-Z0-9_]+$/ || $2 ~ /^B[0-9_]+$/ || $2 ~ /^(OLD|NEW)DEV$/ || @@ -497,6 +501,7 @@ ccflags="$@" $2 ~ /^O?XTABS$/ || $2 ~ /^TC[IO](ON|OFF)$/ || $2 ~ /^IN_/ || + $2 ~ /^LANDLOCK_/ || $2 ~ /^LOCK_(SH|EX|NB|UN)$/ || $2 ~ /^LO_(KEY|NAME)_SIZE$/ || $2 ~ /^LOOP_(CLR|CTL|GET|SET)_/ || diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin.go index 23f6b57606..a8c13317d7 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin.go @@ -48,6 +48,30 @@ func (sa *SockaddrCtl) sockaddr() (unsafe.Pointer, _Socklen, error) { return unsafe.Pointer(&sa.raw), SizeofSockaddrCtl, nil } +// SockaddrVM implements the Sockaddr interface for AF_VSOCK type sockets. +// SockaddrVM provides access to Darwin VM sockets: a mechanism that enables +// bidirectional communication between a hypervisor and its guest virtual +// machines. +type SockaddrVM struct { + // CID and Port specify a context ID and port address for a VM socket. + // Guests have a unique CID, and hosts may have a well-known CID of: + // - VMADDR_CID_HYPERVISOR: refers to the hypervisor process. + // - VMADDR_CID_LOCAL: refers to local communication (loopback). + // - VMADDR_CID_HOST: refers to other processes on the host. + CID uint32 + Port uint32 + raw RawSockaddrVM +} + +func (sa *SockaddrVM) sockaddr() (unsafe.Pointer, _Socklen, error) { + sa.raw.Len = SizeofSockaddrVM + sa.raw.Family = AF_VSOCK + sa.raw.Port = sa.Port + sa.raw.Cid = sa.CID + + return unsafe.Pointer(&sa.raw), SizeofSockaddrVM, nil +} + func anyToSockaddrGOOS(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { switch rsa.Addr.Family { case AF_SYSTEM: @@ -58,6 +82,13 @@ func anyToSockaddrGOOS(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { sa.Unit = pp.Sc_unit return sa, nil } + case AF_VSOCK: + pp := (*RawSockaddrVM)(unsafe.Pointer(rsa)) + sa := &SockaddrVM{ + CID: pp.Cid, + Port: pp.Port, + } + return sa, nil } return nil, EAFNOSUPPORT } @@ -433,6 +464,11 @@ func SysctlKinfoProcSlice(name string) ([]KinfoProc, error) { //sys sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) +//sys shmat(id int, addr uintptr, flag int) (ret uintptr, err error) +//sys shmctl(id int, cmd int, buf *SysvShmDesc) (result int, err error) +//sys shmdt(addr uintptr) (err error) +//sys shmget(key int, size int, flag int) (id int, err error) + /* * Exposed directly */ @@ -590,10 +626,6 @@ func SysctlKinfoProcSlice(name string) ([]KinfoProc, error) { // Msgget // Msgsnd // Msgrcv -// Shmat -// Shmctl -// Shmdt -// Shmget // Shm_open // Shm_unlink // Sem_open diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_illumos.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_illumos.go index 8c53576835..8d5f294c42 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_illumos.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_illumos.go @@ -162,6 +162,14 @@ func (l *Lifreq) GetLifruInt() int { return *(*int)(unsafe.Pointer(&l.Lifru[0])) } +func (l *Lifreq) SetLifruUint(d uint) { + *(*uint)(unsafe.Pointer(&l.Lifru[0])) = d +} + +func (l *Lifreq) GetLifruUint() uint { + return *(*uint)(unsafe.Pointer(&l.Lifru[0])) +} + func IoctlLifreq(fd int, req uint, l *Lifreq) error { return ioctl(fd, req, uintptr(unsafe.Pointer(l))) } 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 2839435e3d..fff38a84c9 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 @@ -13,7 +13,6 @@ package unix import ( "encoding/binary" - "runtime" "syscall" "unsafe" ) @@ -38,6 +37,13 @@ func Creat(path string, mode uint32) (fd int, err error) { return Open(path, O_CREAT|O_WRONLY|O_TRUNC, mode) } +func EpollCreate(size int) (fd int, err error) { + if size <= 0 { + return -1, EINVAL + } + return EpollCreate1(0) +} + //sys FanotifyInit(flags uint, event_f_flags uint) (fd int, err error) //sys fanotifyMark(fd int, flags uint, mask uint64, dirFd int, pathname *byte) (err error) @@ -66,6 +72,10 @@ func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { return fchmodat(dirfd, path, mode) } +func InotifyInit() (fd int, err error) { + return InotifyInit1(0) +} + //sys ioctl(fd int, req uint, arg uintptr) (err error) = SYS_IOCTL //sys ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) = SYS_IOCTL @@ -109,6 +119,23 @@ func Openat2(dirfd int, path string, how *OpenHow) (fd int, err error) { return openat2(dirfd, path, how, SizeofOpenHow) } +func Pipe(p []int) error { + return Pipe2(p, 0) +} + +//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 ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) func Ppoll(fds []PollFd, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { @@ -118,6 +145,15 @@ func Ppoll(fds []PollFd, timeout *Timespec, sigmask *Sigset_t) (n int, err error return ppoll(&fds[0], len(fds), timeout, sigmask) } +func Poll(fds []PollFd, timeout int) (n int, err error) { + var ts *Timespec + if timeout >= 0 { + ts = new(Timespec) + *ts = NsecToTimespec(int64(timeout) * 1e6) + } + return Ppoll(fds, ts, nil) +} + //sys Readlinkat(dirfd int, path string, buf []byte) (n int, err error) func Readlink(path string, buf []byte) (n int, err error) { @@ -168,27 +204,7 @@ func Utimes(path string, tv []Timeval) error { //sys utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) func UtimesNano(path string, ts []Timespec) error { - if ts == nil { - err := utimensat(AT_FDCWD, path, nil, 0) - if err != ENOSYS { - return err - } - return utimes(path, nil) - } - if len(ts) != 2 { - return EINVAL - } - err := utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0) - if err != ENOSYS { - return err - } - // If the utimensat syscall isn't available (utimensat was added to Linux - // in 2.6.22, Released, 8 July 2007) then fall back to utimes - var tv [2]Timeval - for i := 0; i < 2; i++ { - tv[i] = NsecToTimeval(TimespecToNsec(ts[i])) - } - return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0]))) + return UtimesNanoAt(AT_FDCWD, path, ts, 0) } func UtimesNanoAt(dirfd int, path string, ts []Timespec, flags int) error { @@ -1229,11 +1245,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { func Accept(fd int) (nfd int, sa Sockaddr, err error) { var rsa RawSockaddrAny var len _Socklen = SizeofSockaddrAny - // Try accept4 first for Android, then try accept for kernel older than 2.6.28 nfd, err = accept4(fd, &rsa, &len, 0) - if err == ENOSYS { - nfd, err = accept(fd, &rsa, &len) - } if err != nil { return } @@ -1816,11 +1828,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e //sys Dup(oldfd int) (fd int, err error) func Dup2(oldfd, newfd int) error { - // Android O and newer blocks dup2; riscv and arm64 don't implement dup2. - if runtime.GOOS == "android" || runtime.GOARCH == "riscv64" || runtime.GOARCH == "arm64" { - return Dup3(oldfd, newfd, 0) - } - return dup2(oldfd, newfd) + return Dup3(oldfd, newfd, 0) } //sys Dup3(oldfd int, newfd int, flags int) (err error) @@ -2308,6 +2316,14 @@ type RemoteIovec struct { //sys ProcessVMReadv(pid int, localIov []Iovec, remoteIov []RemoteIovec, flags uint) (n int, err error) = SYS_PROCESS_VM_READV //sys ProcessVMWritev(pid int, localIov []Iovec, remoteIov []RemoteIovec, flags uint) (n int, err error) = SYS_PROCESS_VM_WRITEV +//sys PidfdOpen(pid int, flags int) (fd int, err error) = SYS_PIDFD_OPEN +//sys PidfdGetfd(pidfd int, targetfd int, flags int) (fd int, err error) = SYS_PIDFD_GETFD + +//sys shmat(id int, addr uintptr, flag int) (ret uintptr, err error) +//sys shmctl(id int, cmd int, buf *SysvShmDesc) (result int, err error) +//sys shmdt(addr uintptr) (err error) +//sys shmget(key int, size int, flag int) (id int, err error) + /* * Unimplemented */ @@ -2389,10 +2405,6 @@ type RemoteIovec struct { // SetRobustList // SetThreadArea // SetTidAddress -// Shmat -// Shmctl -// Shmdt -// Shmget // Sigaltstack // Swapoff // Swapon diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_386.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_386.go index 91317d749a..5f757e8aa7 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_386.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_386.go @@ -19,36 +19,8 @@ func setTimeval(sec, usec int64) Timeval { return Timeval{Sec: int32(sec), Usec: int32(usec)} } -//sysnb pipe(p *[2]_C_int) (err error) - -func Pipe(p []int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe(&pp) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -//sysnb pipe2(p *[2]_C_int, flags int) (err error) - -func Pipe2(p []int, flags int) (err 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 -} - // 64-bit file system and 32-bit uid calls // (386 default is 32-bit file system and 16-bit uid). -//sys dup2(oldfd int, newfd int) (err error) -//sysnb EpollCreate(size int) (fd int, err error) //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) //sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64_64 //sys Fchown(fd int, uid int, gid int) (err error) = SYS_FCHOWN32 @@ -59,7 +31,6 @@ func Pipe2(p []int, flags int) (err error) { //sysnb Geteuid() (euid int) = SYS_GETEUID32 //sysnb Getgid() (gid int) = SYS_GETGID32 //sysnb Getuid() (uid int) = SYS_GETUID32 -//sysnb InotifyInit() (fd int, err error) //sys Ioperm(from int, num int, on int) (err error) //sys Iopl(level int) (err error) //sys Lchown(path string, uid int, gid int) (err error) = SYS_LCHOWN32 @@ -381,12 +352,3 @@ func (cmsg *Cmsghdr) SetLen(length int) { func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { rsa.Service_name_len = uint32(length) } - -//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) - -func Poll(fds []PollFd, timeout int) (n int, err error) { - if len(fds) == 0 { - return poll(nil, 0, timeout) - } - return poll(&fds[0], len(fds), timeout) -} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go index 85cd97da09..4299125aa7 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go @@ -7,8 +7,6 @@ package unix -//sys dup2(oldfd int, newfd int) (err error) -//sysnb EpollCreate(size int) (fd int, err error) //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) //sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64 //sys Fchown(fd int, uid int, gid int) (err error) @@ -21,17 +19,6 @@ package unix //sysnb Getgid() (gid int) //sysnb Getrlimit(resource int, rlim *Rlimit) (err error) //sysnb Getuid() (uid int) -//sysnb inotifyInit() (fd int, err error) - -func InotifyInit() (fd int, err error) { - // First try inotify_init1, because Android's seccomp policy blocks the latter. - fd, err = InotifyInit1(0) - if err == ENOSYS { - fd, err = inotifyInit() - } - return -} - //sys Ioperm(from int, num int, on int) (err error) //sys Iopl(level int) (err error) //sys Lchown(path string, uid int, gid int) (err error) @@ -126,32 +113,6 @@ func setTimeval(sec, usec int64) Timeval { return Timeval{Sec: sec, Usec: usec} } -//sysnb pipe(p *[2]_C_int) (err error) - -func Pipe(p []int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe(&pp) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -//sysnb pipe2(p *[2]_C_int, flags int) (err error) - -func Pipe2(p []int, flags int) (err 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 -} - func (r *PtraceRegs) PC() uint64 { return r.Rip } func (r *PtraceRegs) SetPC(pc uint64) { r.Rip = pc } @@ -176,15 +137,6 @@ func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { rsa.Service_name_len = uint64(length) } -//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) - -func Poll(fds []PollFd, timeout int) (n int, err error) { - if len(fds) == 0 { - return poll(nil, 0, timeout) - } - return poll(&fds[0], len(fds), timeout) -} - //sys kexecFileLoad(kernelFd int, initrdFd int, cmdlineLen int, cmdline string, flags int) (err error) func KexecFileLoad(kernelFd int, initrdFd int, cmdline string, flags int) error { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_arm.go index b961a620e9..79edeb9cb1 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_arm.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_arm.go @@ -19,36 +19,6 @@ func setTimeval(sec, usec int64) Timeval { return Timeval{Sec: int32(sec), Usec: int32(usec)} } -//sysnb pipe(p *[2]_C_int) (err error) - -func Pipe(p []int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - // Try pipe2 first for Android O, then try pipe for kernel 2.6.23. - err = pipe2(&pp, 0) - if err == ENOSYS { - err = pipe(&pp) - } - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -//sysnb pipe2(p *[2]_C_int, flags int) (err error) - -func Pipe2(p []int, flags int) (err 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 -} - func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { newoffset, errno := seek(fd, offset, whence) if errno != 0 { @@ -76,8 +46,6 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { // 64-bit file system and 32-bit uid calls // (16-bit uid calls are not always supported in newer kernels) -//sys dup2(oldfd int, newfd int) (err error) -//sysnb EpollCreate(size int) (fd int, err error) //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) //sys Fchown(fd int, uid int, gid int) (err error) = SYS_FCHOWN32 //sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64 @@ -86,7 +54,6 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { //sysnb Geteuid() (euid int) = SYS_GETEUID32 //sysnb Getgid() (gid int) = SYS_GETGID32 //sysnb Getuid() (uid int) = SYS_GETUID32 -//sysnb InotifyInit() (fd int, err error) //sys Lchown(path string, uid int, gid int) (err error) = SYS_LCHOWN32 //sys Listen(s int, n int) (err error) //sys Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64 @@ -260,15 +227,6 @@ func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { rsa.Service_name_len = uint32(length) } -//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) - -func Poll(fds []PollFd, timeout int) (n int, err error) { - if len(fds) == 0 { - return poll(nil, 0, timeout) - } - return poll(&fds[0], len(fds), timeout) -} - //sys armSyncFileRange(fd int, flags int, off int64, n int64) (err error) = SYS_ARM_SYNC_FILE_RANGE func SyncFileRange(fd int, off int64, n int64, flags int) error { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go index 4b977ba44b..862890de29 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go @@ -9,13 +9,6 @@ package unix import "unsafe" -func EpollCreate(size int) (fd int, err error) { - if size <= 0 { - return -1, EINVAL - } - return EpollCreate1(0) -} - //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) = SYS_EPOLL_PWAIT //sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64 //sys Fchown(fd int, uid int, gid int) (err error) @@ -145,30 +138,6 @@ func utimes(path string, tv *[2]Timeval) (err error) { return utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0) } -func Pipe(p []int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, 0) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -//sysnb pipe2(p *[2]_C_int, flags int) (err error) - -func Pipe2(p []int, flags int) (err 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 -} - // Getrlimit prefers the prlimit64 system call. See issue 38604. func Getrlimit(resource int, rlim *Rlimit) error { err := Prlimit(0, resource, nil, rlim) @@ -211,31 +180,11 @@ func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { rsa.Service_name_len = uint64(length) } -func InotifyInit() (fd int, err error) { - return InotifyInit1(0) -} - -// dup2 exists because func Dup3 in syscall_linux.go references -// it in an unreachable path. dup2 isn't available on arm64. -func dup2(oldfd int, newfd int) error - func Pause() error { _, err := ppoll(nil, 0, nil, nil) return err } -func Poll(fds []PollFd, timeout int) (n int, err error) { - var ts *Timespec - if timeout >= 0 { - ts = new(Timespec) - *ts = NsecToTimespec(int64(timeout) * 1e6) - } - if len(fds) == 0 { - return ppoll(nil, 0, ts, nil) - } - return ppoll(&fds[0], len(fds), ts, nil) -} - //sys kexecFileLoad(kernelFd int, initrdFd int, cmdlineLen int, cmdline string, flags int) (err error) func KexecFileLoad(kernelFd int, initrdFd int, cmdline string, flags int) error { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go index 27aee81d97..8932e34ad2 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go @@ -8,8 +8,6 @@ package unix -//sys dup2(oldfd int, newfd int) (err error) -//sysnb EpollCreate(size int) (fd int, err error) //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) //sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64 //sys Fchown(fd int, uid int, gid int) (err error) @@ -94,30 +92,6 @@ func setTimeval(sec, usec int64) Timeval { return Timeval{Sec: sec, Usec: usec} } -func Pipe(p []int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, 0) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -//sysnb pipe2(p *[2]_C_int, flags int) (err error) - -func Pipe2(p []int, flags int) (err 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 -} - func Ioperm(from int, num int, on int) (err error) { return ENOSYS } @@ -220,16 +194,3 @@ func (cmsg *Cmsghdr) SetLen(length int) { func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { rsa.Service_name_len = uint64(length) } - -func InotifyInit() (fd int, err error) { - return InotifyInit1(0) -} - -//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) - -func Poll(fds []PollFd, timeout int) (n int, err error) { - if len(fds) == 0 { - return poll(nil, 0, timeout) - } - return poll(&fds[0], len(fds), timeout) -} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go index 21d74e2fbe..7821c25d9f 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go @@ -15,8 +15,6 @@ import ( func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) -//sys dup2(oldfd int, newfd int) (err error) -//sysnb EpollCreate(size int) (fd int, err error) //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) //sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64 //sys Fchown(fd int, uid int, gid int) (err error) @@ -60,7 +58,6 @@ func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, //sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error) //sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error) -//sysnb InotifyInit() (fd int, err error) //sys Ioperm(from int, num int, on int) (err error) //sys Iopl(level int) (err error) @@ -113,29 +110,6 @@ func setTimeval(sec, usec int64) Timeval { return Timeval{Sec: int32(sec), Usec: int32(usec)} } -//sysnb pipe2(p *[2]_C_int, flags int) (err error) - -func Pipe2(p []int, flags int) (err 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 -} - -//sysnb pipe() (p1 int, p2 int, err error) - -func Pipe(p []int) (err error) { - if len(p) != 2 { - return EINVAL - } - p[0], p[1], err = pipe() - return -} - //sys mmap2(addr uintptr, length uintptr, prot int, flags int, fd int, pageOffset uintptr) (xaddr uintptr, err error) func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) { @@ -232,12 +206,3 @@ func (cmsg *Cmsghdr) SetLen(length int) { func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { rsa.Service_name_len = uint32(length) } - -//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) - -func Poll(fds []PollFd, timeout int) (n int, err error) { - if len(fds) == 0 { - return poll(nil, 0, timeout) - } - return poll(&fds[0], len(fds), timeout) -} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_ppc.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_ppc.go index 6f1fc581ed..c5053a0f03 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_ppc.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_ppc.go @@ -12,8 +12,6 @@ import ( "unsafe" ) -//sys dup2(oldfd int, newfd int) (err error) -//sysnb EpollCreate(size int) (fd int, err error) //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) //sys Fchown(fd int, uid int, gid int) (err error) //sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64 @@ -23,7 +21,6 @@ import ( //sysnb Geteuid() (euid int) //sysnb Getgid() (gid int) //sysnb Getuid() (uid int) -//sysnb InotifyInit() (fd int, err error) //sys Ioperm(from int, num int, on int) (err error) //sys Iopl(level int) (err error) //sys Lchown(path string, uid int, gid int) (err error) @@ -218,41 +215,6 @@ func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { rsa.Service_name_len = uint32(length) } -//sysnb pipe(p *[2]_C_int) (err error) - -func Pipe(p []int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe(&pp) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -//sysnb pipe2(p *[2]_C_int, flags int) (err error) - -func Pipe2(p []int, flags int) (err 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 -} - -//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) - -func Poll(fds []PollFd, timeout int) (n int, err error) { - if len(fds) == 0 { - return poll(nil, 0, timeout) - } - return poll(&fds[0], len(fds), timeout) -} - //sys syncFileRange2(fd int, flags int, off int64, n int64) (err error) = SYS_SYNC_FILE_RANGE2 func SyncFileRange(fd int, off int64, n int64, flags int) error { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go index 5259a5feaf..25786c4216 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go @@ -8,8 +8,6 @@ package unix -//sys dup2(oldfd int, newfd int) (err error) -//sysnb EpollCreate(size int) (fd int, err error) //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) //sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64 //sys Fchown(fd int, uid int, gid int) (err error) @@ -22,7 +20,6 @@ package unix //sysnb Getgid() (gid int) //sysnb Getrlimit(resource int, rlim *Rlimit) (err error) = SYS_UGETRLIMIT //sysnb Getuid() (uid int) -//sysnb InotifyInit() (fd int, err error) //sys Ioperm(from int, num int, on int) (err error) //sys Iopl(level int) (err error) //sys Lchown(path string, uid int, gid int) (err error) @@ -104,41 +101,6 @@ func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { rsa.Service_name_len = uint64(length) } -//sysnb pipe(p *[2]_C_int) (err error) - -func Pipe(p []int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe(&pp) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -//sysnb pipe2(p *[2]_C_int, flags int) (err error) - -func Pipe2(p []int, flags int) (err 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 -} - -//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) - -func Poll(fds []PollFd, timeout int) (n int, err error) { - if len(fds) == 0 { - return poll(nil, 0, timeout) - } - return poll(&fds[0], len(fds), timeout) -} - //sys syncFileRange2(fd int, flags int, off int64, n int64) (err error) = SYS_SYNC_FILE_RANGE2 func SyncFileRange(fd int, off int64, n int64, flags int) error { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go index 8ef821e5da..6f9f710414 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go @@ -9,13 +9,6 @@ package unix import "unsafe" -func EpollCreate(size int) (fd int, err error) { - if size <= 0 { - return -1, EINVAL - } - return EpollCreate1(0) -} - //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) = SYS_EPOLL_PWAIT //sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64 //sys Fchown(fd int, uid int, gid int) (err error) @@ -144,30 +137,6 @@ func utimes(path string, tv *[2]Timeval) (err error) { return utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0) } -func Pipe(p []int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, 0) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -//sysnb pipe2(p *[2]_C_int, flags int) (err error) - -func Pipe2(p []int, flags int) (err 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 -} - func (r *PtraceRegs) PC() uint64 { return r.Pc } func (r *PtraceRegs) SetPC(pc uint64) { r.Pc = pc } @@ -192,27 +161,11 @@ func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { rsa.Service_name_len = uint64(length) } -func InotifyInit() (fd int, err error) { - return InotifyInit1(0) -} - func Pause() error { _, err := ppoll(nil, 0, nil, nil) return err } -func Poll(fds []PollFd, timeout int) (n int, err error) { - var ts *Timespec - if timeout >= 0 { - ts = new(Timespec) - *ts = NsecToTimespec(int64(timeout) * 1e6) - } - if len(fds) == 0 { - return ppoll(nil, 0, ts, nil) - } - return ppoll(&fds[0], len(fds), ts, nil) -} - func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) { return Renameat2(olddirfd, oldpath, newdirfd, newpath, 0) } @@ -229,7 +182,3 @@ func KexecFileLoad(kernelFd int, initrdFd int, cmdline string, flags int) error } return kexecFileLoad(kernelFd, initrdFd, cmdlineLen, cmdline, flags) } - -// dup2 exists because func Dup3 in syscall_linux.go references -// it in an unreachable path. dup2 isn't available on arm64. -func dup2(oldfd int, newfd int) error diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go index a1c0574b58..6aa59cb270 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go @@ -11,8 +11,6 @@ import ( "unsafe" ) -//sys dup2(oldfd int, newfd int) (err error) -//sysnb EpollCreate(size int) (fd int, err error) //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) //sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64 //sys Fchown(fd int, uid int, gid int) (err error) @@ -25,7 +23,6 @@ import ( //sysnb Getgid() (gid int) //sysnb Getrlimit(resource int, rlim *Rlimit) (err error) //sysnb Getuid() (uid int) -//sysnb InotifyInit() (fd int, err error) //sys Lchown(path string, uid int, gid int) (err error) //sys Lstat(path string, stat *Stat_t) (err error) //sys Pause() (err error) @@ -77,30 +74,6 @@ func setTimeval(sec, usec int64) Timeval { return Timeval{Sec: sec, Usec: usec} } -//sysnb pipe2(p *[2]_C_int, flags int) (err error) - -func Pipe(p []int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, 0) // pipe2 is the same as pipe when flags are set to 0. - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -func Pipe2(p []int, flags int) (err 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 -} - func Ioperm(from int, num int, on int) (err error) { return ENOSYS } @@ -324,15 +297,6 @@ func Shutdown(s, how int) error { return nil } -//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) - -func Poll(fds []PollFd, timeout int) (n int, err error) { - if len(fds) == 0 { - return poll(nil, 0, timeout) - } - return poll(&fds[0], len(fds), timeout) -} - //sys kexecFileLoad(kernelFd int, initrdFd int, cmdlineLen int, cmdline string, flags int) (err error) func KexecFileLoad(kernelFd int, initrdFd int, cmdline string, flags int) error { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go index de14b88983..bbe8d174f8 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go @@ -9,7 +9,6 @@ package unix //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) //sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64 -//sys dup2(oldfd int, newfd int) (err error) //sys Fchown(fd int, uid int, gid int) (err error) //sys Fstat(fd int, stat *Stat_t) (err error) //sys Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) = SYS_FSTATAT64 @@ -20,7 +19,6 @@ package unix //sysnb Getgid() (gid int) //sysnb Getrlimit(resource int, rlim *Rlimit) (err error) //sysnb Getuid() (uid int) -//sysnb InotifyInit() (fd int, err error) //sys Lchown(path string, uid int, gid int) (err error) //sys Listen(s int, n int) (err error) //sys Lstat(path string, stat *Stat_t) (err error) @@ -119,38 +117,3 @@ func (cmsg *Cmsghdr) SetLen(length int) { func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { rsa.Service_name_len = uint64(length) } - -//sysnb pipe(p *[2]_C_int) (err error) - -func Pipe(p []int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe(&pp) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -//sysnb pipe2(p *[2]_C_int, flags int) (err error) - -func Pipe2(p []int, flags int) (err 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 -} - -//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) - -func Poll(fds []PollFd, timeout int) (n int, err error) { - if len(fds) == 0 { - return poll(nil, 0, timeout) - } - return poll(&fds[0], len(fds), timeout) -} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/sysvshm_linux.go b/src/cmd/vendor/golang.org/x/sys/unix/sysvshm_linux.go new file mode 100644 index 0000000000..2c3a4437f0 --- /dev/null +++ b/src/cmd/vendor/golang.org/x/sys/unix/sysvshm_linux.go @@ -0,0 +1,21 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build linux +// +build linux + +package unix + +import "runtime" + +// SysvShmCtl performs control operations on the shared memory segment +// specified by id. +func SysvShmCtl(id, cmd int, desc *SysvShmDesc) (result int, err error) { + if runtime.GOARCH == "arm" || + runtime.GOARCH == "mips64" || runtime.GOARCH == "mips64le" { + cmd |= ipc_64 + } + + return shmctl(id, cmd, desc) +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/sysvshm_unix.go b/src/cmd/vendor/golang.org/x/sys/unix/sysvshm_unix.go new file mode 100644 index 0000000000..0bb4c8de55 --- /dev/null +++ b/src/cmd/vendor/golang.org/x/sys/unix/sysvshm_unix.go @@ -0,0 +1,61 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (darwin && !ios) || linux +// +build darwin,!ios linux + +package unix + +import ( + "unsafe" + + "golang.org/x/sys/internal/unsafeheader" +) + +// SysvShmAttach attaches the Sysv shared memory segment associated with the +// shared memory identifier id. +func SysvShmAttach(id int, addr uintptr, flag int) ([]byte, error) { + addr, errno := shmat(id, addr, flag) + if errno != nil { + return nil, errno + } + + // Retrieve the size of the shared memory to enable slice creation + var info SysvShmDesc + + _, err := SysvShmCtl(id, IPC_STAT, &info) + if err != nil { + // release the shared memory if we can't find the size + + // ignoring error from shmdt as there's nothing sensible to return here + shmdt(addr) + return nil, err + } + + // Use unsafe to convert addr into a []byte. + // TODO: convert to unsafe.Slice once we can assume Go 1.17 + var b []byte + hdr := (*unsafeheader.Slice)(unsafe.Pointer(&b)) + hdr.Data = unsafe.Pointer(addr) + hdr.Cap = int(info.Segsz) + hdr.Len = int(info.Segsz) + return b, nil +} + +// SysvShmDetach unmaps the shared memory slice returned from SysvShmAttach. +// +// It is not safe to use the slice after calling this function. +func SysvShmDetach(data []byte) error { + if len(data) == 0 { + return EINVAL + } + + return shmdt(uintptr(unsafe.Pointer(&data[0]))) +} + +// SysvShmGet returns the Sysv shared memory identifier associated with key. +// If the IPC_CREAT flag is specified a new segment is created. +func SysvShmGet(key, size, flag int) (id int, err error) { + return shmget(key, size, flag) +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/sysvshm_unix_other.go b/src/cmd/vendor/golang.org/x/sys/unix/sysvshm_unix_other.go new file mode 100644 index 0000000000..71bddefdb8 --- /dev/null +++ b/src/cmd/vendor/golang.org/x/sys/unix/sysvshm_unix_other.go @@ -0,0 +1,14 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build darwin && !ios +// +build darwin,!ios + +package unix + +// SysvShmCtl performs control operations on the shared memory segment +// specified by id. +func SysvShmCtl(id, cmd int, desc *SysvShmDesc) (result int, err error) { + return shmctl(id, cmd, desc) +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go index a3a45fec59..476a1c7e77 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go @@ -12,1556 +12,1582 @@ package unix import "syscall" const ( - AF_APPLETALK = 0x10 - AF_CCITT = 0xa - AF_CHAOS = 0x5 - AF_CNT = 0x15 - AF_COIP = 0x14 - AF_DATAKIT = 0x9 - AF_DECnet = 0xc - AF_DLI = 0xd - AF_E164 = 0x1c - AF_ECMA = 0x8 - AF_HYLINK = 0xf - AF_IEEE80211 = 0x25 - AF_IMPLINK = 0x3 - AF_INET = 0x2 - AF_INET6 = 0x1e - AF_IPX = 0x17 - AF_ISDN = 0x1c - AF_ISO = 0x7 - AF_LAT = 0xe - AF_LINK = 0x12 - AF_LOCAL = 0x1 - AF_MAX = 0x29 - AF_NATM = 0x1f - AF_NDRV = 0x1b - AF_NETBIOS = 0x21 - AF_NS = 0x6 - AF_OSI = 0x7 - AF_PPP = 0x22 - AF_PUP = 0x4 - AF_RESERVED_36 = 0x24 - AF_ROUTE = 0x11 - AF_SIP = 0x18 - AF_SNA = 0xb - AF_SYSTEM = 0x20 - AF_SYS_CONTROL = 0x2 - AF_UNIX = 0x1 - AF_UNSPEC = 0x0 - AF_UTUN = 0x26 - AF_VSOCK = 0x28 - ALTWERASE = 0x200 - ATTR_BIT_MAP_COUNT = 0x5 - ATTR_CMN_ACCESSMASK = 0x20000 - ATTR_CMN_ACCTIME = 0x1000 - ATTR_CMN_ADDEDTIME = 0x10000000 - ATTR_CMN_BKUPTIME = 0x2000 - ATTR_CMN_CHGTIME = 0x800 - ATTR_CMN_CRTIME = 0x200 - ATTR_CMN_DATA_PROTECT_FLAGS = 0x40000000 - ATTR_CMN_DEVID = 0x2 - ATTR_CMN_DOCUMENT_ID = 0x100000 - ATTR_CMN_ERROR = 0x20000000 - ATTR_CMN_EXTENDED_SECURITY = 0x400000 - ATTR_CMN_FILEID = 0x2000000 - ATTR_CMN_FLAGS = 0x40000 - ATTR_CMN_FNDRINFO = 0x4000 - ATTR_CMN_FSID = 0x4 - ATTR_CMN_FULLPATH = 0x8000000 - ATTR_CMN_GEN_COUNT = 0x80000 - ATTR_CMN_GRPID = 0x10000 - ATTR_CMN_GRPUUID = 0x1000000 - ATTR_CMN_MODTIME = 0x400 - ATTR_CMN_NAME = 0x1 - ATTR_CMN_NAMEDATTRCOUNT = 0x80000 - ATTR_CMN_NAMEDATTRLIST = 0x100000 - ATTR_CMN_OBJID = 0x20 - ATTR_CMN_OBJPERMANENTID = 0x40 - ATTR_CMN_OBJTAG = 0x10 - ATTR_CMN_OBJTYPE = 0x8 - ATTR_CMN_OWNERID = 0x8000 - ATTR_CMN_PARENTID = 0x4000000 - ATTR_CMN_PAROBJID = 0x80 - ATTR_CMN_RETURNED_ATTRS = 0x80000000 - ATTR_CMN_SCRIPT = 0x100 - ATTR_CMN_SETMASK = 0x51c7ff00 - ATTR_CMN_USERACCESS = 0x200000 - ATTR_CMN_UUID = 0x800000 - ATTR_CMN_VALIDMASK = 0xffffffff - ATTR_CMN_VOLSETMASK = 0x6700 - ATTR_FILE_ALLOCSIZE = 0x4 - ATTR_FILE_CLUMPSIZE = 0x10 - ATTR_FILE_DATAALLOCSIZE = 0x400 - ATTR_FILE_DATAEXTENTS = 0x800 - ATTR_FILE_DATALENGTH = 0x200 - ATTR_FILE_DEVTYPE = 0x20 - ATTR_FILE_FILETYPE = 0x40 - ATTR_FILE_FORKCOUNT = 0x80 - ATTR_FILE_FORKLIST = 0x100 - ATTR_FILE_IOBLOCKSIZE = 0x8 - ATTR_FILE_LINKCOUNT = 0x1 - ATTR_FILE_RSRCALLOCSIZE = 0x2000 - ATTR_FILE_RSRCEXTENTS = 0x4000 - ATTR_FILE_RSRCLENGTH = 0x1000 - ATTR_FILE_SETMASK = 0x20 - ATTR_FILE_TOTALSIZE = 0x2 - ATTR_FILE_VALIDMASK = 0x37ff - ATTR_VOL_ALLOCATIONCLUMP = 0x40 - ATTR_VOL_ATTRIBUTES = 0x40000000 - ATTR_VOL_CAPABILITIES = 0x20000 - ATTR_VOL_DIRCOUNT = 0x400 - ATTR_VOL_ENCODINGSUSED = 0x10000 - ATTR_VOL_FILECOUNT = 0x200 - ATTR_VOL_FSTYPE = 0x1 - ATTR_VOL_INFO = 0x80000000 - ATTR_VOL_IOBLOCKSIZE = 0x80 - ATTR_VOL_MAXOBJCOUNT = 0x800 - ATTR_VOL_MINALLOCATION = 0x20 - ATTR_VOL_MOUNTEDDEVICE = 0x8000 - ATTR_VOL_MOUNTFLAGS = 0x4000 - ATTR_VOL_MOUNTPOINT = 0x1000 - ATTR_VOL_NAME = 0x2000 - ATTR_VOL_OBJCOUNT = 0x100 - ATTR_VOL_QUOTA_SIZE = 0x10000000 - ATTR_VOL_RESERVED_SIZE = 0x20000000 - ATTR_VOL_SETMASK = 0x80002000 - ATTR_VOL_SIGNATURE = 0x2 - ATTR_VOL_SIZE = 0x4 - ATTR_VOL_SPACEAVAIL = 0x10 - ATTR_VOL_SPACEFREE = 0x8 - ATTR_VOL_UUID = 0x40000 - ATTR_VOL_VALIDMASK = 0xf007ffff - B0 = 0x0 - B110 = 0x6e - B115200 = 0x1c200 - B1200 = 0x4b0 - B134 = 0x86 - B14400 = 0x3840 - B150 = 0x96 - B1800 = 0x708 - B19200 = 0x4b00 - B200 = 0xc8 - B230400 = 0x38400 - B2400 = 0x960 - B28800 = 0x7080 - B300 = 0x12c - B38400 = 0x9600 - B4800 = 0x12c0 - B50 = 0x32 - B57600 = 0xe100 - B600 = 0x258 - B7200 = 0x1c20 - B75 = 0x4b - B76800 = 0x12c00 - B9600 = 0x2580 - BIOCFLUSH = 0x20004268 - BIOCGBLEN = 0x40044266 - BIOCGDLT = 0x4004426a - BIOCGDLTLIST = 0xc00c4279 - BIOCGETIF = 0x4020426b - BIOCGHDRCMPLT = 0x40044274 - BIOCGRSIG = 0x40044272 - BIOCGRTIMEOUT = 0x4010426e - BIOCGSEESENT = 0x40044276 - BIOCGSTATS = 0x4008426f - BIOCIMMEDIATE = 0x80044270 - BIOCPROMISC = 0x20004269 - BIOCSBLEN = 0xc0044266 - BIOCSDLT = 0x80044278 - BIOCSETF = 0x80104267 - BIOCSETFNR = 0x8010427e - BIOCSETIF = 0x8020426c - BIOCSHDRCMPLT = 0x80044275 - BIOCSRSIG = 0x80044273 - BIOCSRTIMEOUT = 0x8010426d - BIOCSSEESENT = 0x80044277 - BIOCVERSION = 0x40044271 - BPF_A = 0x10 - BPF_ABS = 0x20 - BPF_ADD = 0x0 - BPF_ALIGNMENT = 0x4 - BPF_ALU = 0x4 - BPF_AND = 0x50 - BPF_B = 0x10 - BPF_DIV = 0x30 - BPF_H = 0x8 - BPF_IMM = 0x0 - BPF_IND = 0x40 - BPF_JA = 0x0 - BPF_JEQ = 0x10 - BPF_JGE = 0x30 - BPF_JGT = 0x20 - BPF_JMP = 0x5 - BPF_JSET = 0x40 - BPF_K = 0x0 - BPF_LD = 0x0 - BPF_LDX = 0x1 - BPF_LEN = 0x80 - BPF_LSH = 0x60 - BPF_MAJOR_VERSION = 0x1 - BPF_MAXBUFSIZE = 0x80000 - BPF_MAXINSNS = 0x200 - BPF_MEM = 0x60 - BPF_MEMWORDS = 0x10 - BPF_MINBUFSIZE = 0x20 - BPF_MINOR_VERSION = 0x1 - BPF_MISC = 0x7 - BPF_MSH = 0xa0 - BPF_MUL = 0x20 - BPF_NEG = 0x80 - BPF_OR = 0x40 - BPF_RELEASE = 0x30bb6 - BPF_RET = 0x6 - BPF_RSH = 0x70 - BPF_ST = 0x2 - BPF_STX = 0x3 - BPF_SUB = 0x10 - BPF_TAX = 0x0 - BPF_TXA = 0x80 - BPF_W = 0x0 - BPF_X = 0x8 - BRKINT = 0x2 - BS0 = 0x0 - BS1 = 0x8000 - BSDLY = 0x8000 - CFLUSH = 0xf - CLOCAL = 0x8000 - CLOCK_MONOTONIC = 0x6 - CLOCK_MONOTONIC_RAW = 0x4 - CLOCK_MONOTONIC_RAW_APPROX = 0x5 - CLOCK_PROCESS_CPUTIME_ID = 0xc - CLOCK_REALTIME = 0x0 - CLOCK_THREAD_CPUTIME_ID = 0x10 - CLOCK_UPTIME_RAW = 0x8 - CLOCK_UPTIME_RAW_APPROX = 0x9 - CLONE_NOFOLLOW = 0x1 - CLONE_NOOWNERCOPY = 0x2 - CR0 = 0x0 - CR1 = 0x1000 - CR2 = 0x2000 - CR3 = 0x3000 - CRDLY = 0x3000 - CREAD = 0x800 - CRTSCTS = 0x30000 - CS5 = 0x0 - CS6 = 0x100 - CS7 = 0x200 - CS8 = 0x300 - CSIZE = 0x300 - CSTART = 0x11 - CSTATUS = 0x14 - CSTOP = 0x13 - CSTOPB = 0x400 - CSUSP = 0x1a - CTLIOCGINFO = 0xc0644e03 - CTL_HW = 0x6 - CTL_KERN = 0x1 - CTL_MAXNAME = 0xc - CTL_NET = 0x4 - DLT_A429 = 0xb8 - DLT_A653_ICM = 0xb9 - DLT_AIRONET_HEADER = 0x78 - DLT_AOS = 0xde - DLT_APPLE_IP_OVER_IEEE1394 = 0x8a - DLT_ARCNET = 0x7 - DLT_ARCNET_LINUX = 0x81 - DLT_ATM_CLIP = 0x13 - DLT_ATM_RFC1483 = 0xb - DLT_AURORA = 0x7e - DLT_AX25 = 0x3 - DLT_AX25_KISS = 0xca - DLT_BACNET_MS_TP = 0xa5 - DLT_BLUETOOTH_HCI_H4 = 0xbb - DLT_BLUETOOTH_HCI_H4_WITH_PHDR = 0xc9 - DLT_CAN20B = 0xbe - DLT_CAN_SOCKETCAN = 0xe3 - DLT_CHAOS = 0x5 - DLT_CHDLC = 0x68 - DLT_CISCO_IOS = 0x76 - DLT_C_HDLC = 0x68 - DLT_C_HDLC_WITH_DIR = 0xcd - DLT_DBUS = 0xe7 - DLT_DECT = 0xdd - DLT_DOCSIS = 0x8f - DLT_DVB_CI = 0xeb - DLT_ECONET = 0x73 - DLT_EN10MB = 0x1 - DLT_EN3MB = 0x2 - DLT_ENC = 0x6d - DLT_ERF = 0xc5 - DLT_ERF_ETH = 0xaf - DLT_ERF_POS = 0xb0 - DLT_FC_2 = 0xe0 - DLT_FC_2_WITH_FRAME_DELIMS = 0xe1 - DLT_FDDI = 0xa - DLT_FLEXRAY = 0xd2 - DLT_FRELAY = 0x6b - DLT_FRELAY_WITH_DIR = 0xce - DLT_GCOM_SERIAL = 0xad - DLT_GCOM_T1E1 = 0xac - DLT_GPF_F = 0xab - DLT_GPF_T = 0xaa - DLT_GPRS_LLC = 0xa9 - DLT_GSMTAP_ABIS = 0xda - DLT_GSMTAP_UM = 0xd9 - DLT_HHDLC = 0x79 - DLT_IBM_SN = 0x92 - DLT_IBM_SP = 0x91 - DLT_IEEE802 = 0x6 - DLT_IEEE802_11 = 0x69 - DLT_IEEE802_11_RADIO = 0x7f - DLT_IEEE802_11_RADIO_AVS = 0xa3 - DLT_IEEE802_15_4 = 0xc3 - DLT_IEEE802_15_4_LINUX = 0xbf - DLT_IEEE802_15_4_NOFCS = 0xe6 - DLT_IEEE802_15_4_NONASK_PHY = 0xd7 - DLT_IEEE802_16_MAC_CPS = 0xbc - DLT_IEEE802_16_MAC_CPS_RADIO = 0xc1 - DLT_IPFILTER = 0x74 - DLT_IPMB = 0xc7 - DLT_IPMB_LINUX = 0xd1 - DLT_IPNET = 0xe2 - DLT_IPOIB = 0xf2 - DLT_IPV4 = 0xe4 - DLT_IPV6 = 0xe5 - DLT_IP_OVER_FC = 0x7a - DLT_JUNIPER_ATM1 = 0x89 - DLT_JUNIPER_ATM2 = 0x87 - DLT_JUNIPER_ATM_CEMIC = 0xee - DLT_JUNIPER_CHDLC = 0xb5 - DLT_JUNIPER_ES = 0x84 - DLT_JUNIPER_ETHER = 0xb2 - DLT_JUNIPER_FIBRECHANNEL = 0xea - DLT_JUNIPER_FRELAY = 0xb4 - DLT_JUNIPER_GGSN = 0x85 - DLT_JUNIPER_ISM = 0xc2 - DLT_JUNIPER_MFR = 0x86 - DLT_JUNIPER_MLFR = 0x83 - DLT_JUNIPER_MLPPP = 0x82 - DLT_JUNIPER_MONITOR = 0xa4 - DLT_JUNIPER_PIC_PEER = 0xae - DLT_JUNIPER_PPP = 0xb3 - DLT_JUNIPER_PPPOE = 0xa7 - DLT_JUNIPER_PPPOE_ATM = 0xa8 - DLT_JUNIPER_SERVICES = 0x88 - DLT_JUNIPER_SRX_E2E = 0xe9 - DLT_JUNIPER_ST = 0xc8 - DLT_JUNIPER_VP = 0xb7 - DLT_JUNIPER_VS = 0xe8 - DLT_LAPB_WITH_DIR = 0xcf - DLT_LAPD = 0xcb - DLT_LIN = 0xd4 - DLT_LINUX_EVDEV = 0xd8 - DLT_LINUX_IRDA = 0x90 - DLT_LINUX_LAPD = 0xb1 - DLT_LINUX_PPP_WITHDIRECTION = 0xa6 - DLT_LINUX_SLL = 0x71 - DLT_LOOP = 0x6c - DLT_LTALK = 0x72 - DLT_MATCHING_MAX = 0x10a - DLT_MATCHING_MIN = 0x68 - DLT_MFR = 0xb6 - DLT_MOST = 0xd3 - DLT_MPEG_2_TS = 0xf3 - DLT_MPLS = 0xdb - DLT_MTP2 = 0x8c - DLT_MTP2_WITH_PHDR = 0x8b - DLT_MTP3 = 0x8d - DLT_MUX27010 = 0xec - DLT_NETANALYZER = 0xf0 - DLT_NETANALYZER_TRANSPARENT = 0xf1 - DLT_NFC_LLCP = 0xf5 - DLT_NFLOG = 0xef - DLT_NG40 = 0xf4 - DLT_NULL = 0x0 - DLT_PCI_EXP = 0x7d - DLT_PFLOG = 0x75 - DLT_PFSYNC = 0x12 - DLT_PPI = 0xc0 - DLT_PPP = 0x9 - DLT_PPP_BSDOS = 0x10 - DLT_PPP_ETHER = 0x33 - DLT_PPP_PPPD = 0xa6 - DLT_PPP_SERIAL = 0x32 - DLT_PPP_WITH_DIR = 0xcc - DLT_PPP_WITH_DIRECTION = 0xa6 - DLT_PRISM_HEADER = 0x77 - DLT_PRONET = 0x4 - DLT_RAIF1 = 0xc6 - DLT_RAW = 0xc - DLT_RIO = 0x7c - DLT_SCCP = 0x8e - DLT_SITA = 0xc4 - DLT_SLIP = 0x8 - DLT_SLIP_BSDOS = 0xf - DLT_STANAG_5066_D_PDU = 0xed - DLT_SUNATM = 0x7b - DLT_SYMANTEC_FIREWALL = 0x63 - DLT_TZSP = 0x80 - DLT_USB = 0xba - DLT_USB_DARWIN = 0x10a - DLT_USB_LINUX = 0xbd - DLT_USB_LINUX_MMAPPED = 0xdc - DLT_USER0 = 0x93 - DLT_USER1 = 0x94 - DLT_USER10 = 0x9d - DLT_USER11 = 0x9e - DLT_USER12 = 0x9f - DLT_USER13 = 0xa0 - DLT_USER14 = 0xa1 - DLT_USER15 = 0xa2 - DLT_USER2 = 0x95 - DLT_USER3 = 0x96 - DLT_USER4 = 0x97 - DLT_USER5 = 0x98 - DLT_USER6 = 0x99 - DLT_USER7 = 0x9a - DLT_USER8 = 0x9b - DLT_USER9 = 0x9c - DLT_WIHART = 0xdf - DLT_X2E_SERIAL = 0xd5 - DLT_X2E_XORAYA = 0xd6 - DT_BLK = 0x6 - DT_CHR = 0x2 - DT_DIR = 0x4 - DT_FIFO = 0x1 - DT_LNK = 0xa - DT_REG = 0x8 - DT_SOCK = 0xc - DT_UNKNOWN = 0x0 - DT_WHT = 0xe - ECHO = 0x8 - ECHOCTL = 0x40 - ECHOE = 0x2 - ECHOK = 0x4 - ECHOKE = 0x1 - ECHONL = 0x10 - ECHOPRT = 0x20 - EVFILT_AIO = -0x3 - EVFILT_EXCEPT = -0xf - EVFILT_FS = -0x9 - EVFILT_MACHPORT = -0x8 - EVFILT_PROC = -0x5 - EVFILT_READ = -0x1 - EVFILT_SIGNAL = -0x6 - EVFILT_SYSCOUNT = 0x11 - EVFILT_THREADMARKER = 0x11 - EVFILT_TIMER = -0x7 - EVFILT_USER = -0xa - EVFILT_VM = -0xc - EVFILT_VNODE = -0x4 - EVFILT_WRITE = -0x2 - EV_ADD = 0x1 - EV_CLEAR = 0x20 - EV_DELETE = 0x2 - EV_DISABLE = 0x8 - EV_DISPATCH = 0x80 - EV_DISPATCH2 = 0x180 - EV_ENABLE = 0x4 - EV_EOF = 0x8000 - EV_ERROR = 0x4000 - EV_FLAG0 = 0x1000 - EV_FLAG1 = 0x2000 - EV_ONESHOT = 0x10 - EV_OOBAND = 0x2000 - EV_POLL = 0x1000 - EV_RECEIPT = 0x40 - EV_SYSFLAGS = 0xf000 - EV_UDATA_SPECIFIC = 0x100 - EV_VANISHED = 0x200 - EXTA = 0x4b00 - EXTB = 0x9600 - EXTPROC = 0x800 - FD_CLOEXEC = 0x1 - FD_SETSIZE = 0x400 - FF0 = 0x0 - FF1 = 0x4000 - FFDLY = 0x4000 - FLUSHO = 0x800000 - FSOPT_ATTR_CMN_EXTENDED = 0x20 - FSOPT_NOFOLLOW = 0x1 - FSOPT_NOINMEMUPDATE = 0x2 - FSOPT_PACK_INVAL_ATTRS = 0x8 - FSOPT_REPORT_FULLSIZE = 0x4 - FSOPT_RETURN_REALDEV = 0x200 - F_ADDFILESIGS = 0x3d - F_ADDFILESIGS_FOR_DYLD_SIM = 0x53 - F_ADDFILESIGS_INFO = 0x67 - F_ADDFILESIGS_RETURN = 0x61 - F_ADDFILESUPPL = 0x68 - F_ADDSIGS = 0x3b - F_ALLOCATEALL = 0x4 - F_ALLOCATECONTIG = 0x2 - F_BARRIERFSYNC = 0x55 - F_CHECK_LV = 0x62 - F_CHKCLEAN = 0x29 - F_DUPFD = 0x0 - F_DUPFD_CLOEXEC = 0x43 - F_FINDSIGS = 0x4e - F_FLUSH_DATA = 0x28 - F_FREEZE_FS = 0x35 - F_FULLFSYNC = 0x33 - F_GETCODEDIR = 0x48 - F_GETFD = 0x1 - F_GETFL = 0x3 - F_GETLK = 0x7 - F_GETLKPID = 0x42 - F_GETNOSIGPIPE = 0x4a - F_GETOWN = 0x5 - F_GETPATH = 0x32 - F_GETPATH_MTMINFO = 0x47 - F_GETPATH_NOFIRMLINK = 0x66 - F_GETPROTECTIONCLASS = 0x3f - F_GETPROTECTIONLEVEL = 0x4d - F_GETSIGSINFO = 0x69 - F_GLOBAL_NOCACHE = 0x37 - F_LOG2PHYS = 0x31 - F_LOG2PHYS_EXT = 0x41 - F_NOCACHE = 0x30 - F_NODIRECT = 0x3e - F_OK = 0x0 - F_PATHPKG_CHECK = 0x34 - F_PEOFPOSMODE = 0x3 - F_PREALLOCATE = 0x2a - F_PUNCHHOLE = 0x63 - F_RDADVISE = 0x2c - F_RDAHEAD = 0x2d - F_RDLCK = 0x1 - F_SETBACKINGSTORE = 0x46 - F_SETFD = 0x2 - F_SETFL = 0x4 - F_SETLK = 0x8 - F_SETLKW = 0x9 - F_SETLKWTIMEOUT = 0xa - F_SETNOSIGPIPE = 0x49 - F_SETOWN = 0x6 - F_SETPROTECTIONCLASS = 0x40 - F_SETSIZE = 0x2b - F_SINGLE_WRITER = 0x4c - F_SPECULATIVE_READ = 0x65 - F_THAW_FS = 0x36 - F_TRANSCODEKEY = 0x4b - F_TRIM_ACTIVE_FILE = 0x64 - F_UNLCK = 0x2 - F_VOLPOSMODE = 0x4 - F_WRLCK = 0x3 - HUPCL = 0x4000 - HW_MACHINE = 0x1 - ICANON = 0x100 - ICMP6_FILTER = 0x12 - ICRNL = 0x100 - IEXTEN = 0x400 - IFF_ALLMULTI = 0x200 - IFF_ALTPHYS = 0x4000 - IFF_BROADCAST = 0x2 - IFF_DEBUG = 0x4 - IFF_LINK0 = 0x1000 - IFF_LINK1 = 0x2000 - IFF_LINK2 = 0x4000 - IFF_LOOPBACK = 0x8 - IFF_MULTICAST = 0x8000 - IFF_NOARP = 0x80 - IFF_NOTRAILERS = 0x20 - IFF_OACTIVE = 0x400 - IFF_POINTOPOINT = 0x10 - IFF_PROMISC = 0x100 - IFF_RUNNING = 0x40 - IFF_SIMPLEX = 0x800 - IFF_UP = 0x1 - IFNAMSIZ = 0x10 - IFT_1822 = 0x2 - IFT_6LOWPAN = 0x40 - IFT_AAL5 = 0x31 - IFT_ARCNET = 0x23 - IFT_ARCNETPLUS = 0x24 - IFT_ATM = 0x25 - IFT_BRIDGE = 0xd1 - IFT_CARP = 0xf8 - IFT_CELLULAR = 0xff - IFT_CEPT = 0x13 - IFT_DS3 = 0x1e - IFT_ENC = 0xf4 - IFT_EON = 0x19 - IFT_ETHER = 0x6 - IFT_FAITH = 0x38 - IFT_FDDI = 0xf - IFT_FRELAY = 0x20 - IFT_FRELAYDCE = 0x2c - IFT_GIF = 0x37 - IFT_HDH1822 = 0x3 - IFT_HIPPI = 0x2f - IFT_HSSI = 0x2e - IFT_HY = 0xe - IFT_IEEE1394 = 0x90 - IFT_IEEE8023ADLAG = 0x88 - IFT_ISDNBASIC = 0x14 - IFT_ISDNPRIMARY = 0x15 - IFT_ISO88022LLC = 0x29 - IFT_ISO88023 = 0x7 - IFT_ISO88024 = 0x8 - IFT_ISO88025 = 0x9 - IFT_ISO88026 = 0xa - IFT_L2VLAN = 0x87 - IFT_LAPB = 0x10 - IFT_LOCALTALK = 0x2a - IFT_LOOP = 0x18 - IFT_MIOX25 = 0x26 - IFT_MODEM = 0x30 - IFT_NSIP = 0x1b - IFT_OTHER = 0x1 - IFT_P10 = 0xc - IFT_P80 = 0xd - IFT_PARA = 0x22 - IFT_PDP = 0xff - IFT_PFLOG = 0xf5 - IFT_PFSYNC = 0xf6 - IFT_PKTAP = 0xfe - IFT_PPP = 0x17 - IFT_PROPMUX = 0x36 - IFT_PROPVIRTUAL = 0x35 - IFT_PTPSERIAL = 0x16 - IFT_RS232 = 0x21 - IFT_SDLC = 0x11 - IFT_SIP = 0x1f - IFT_SLIP = 0x1c - IFT_SMDSDXI = 0x2b - IFT_SMDSICIP = 0x34 - IFT_SONET = 0x27 - IFT_SONETPATH = 0x32 - IFT_SONETVT = 0x33 - IFT_STARLAN = 0xb - IFT_STF = 0x39 - IFT_T1 = 0x12 - IFT_ULTRA = 0x1d - IFT_V35 = 0x2d - IFT_X25 = 0x5 - IFT_X25DDN = 0x4 - IFT_X25PLE = 0x28 - IFT_XETHER = 0x1a - IGNBRK = 0x1 - IGNCR = 0x80 - IGNPAR = 0x4 - IMAXBEL = 0x2000 - INLCR = 0x40 - INPCK = 0x10 - IN_CLASSA_HOST = 0xffffff - IN_CLASSA_MAX = 0x80 - IN_CLASSA_NET = 0xff000000 - IN_CLASSA_NSHIFT = 0x18 - IN_CLASSB_HOST = 0xffff - IN_CLASSB_MAX = 0x10000 - IN_CLASSB_NET = 0xffff0000 - IN_CLASSB_NSHIFT = 0x10 - IN_CLASSC_HOST = 0xff - IN_CLASSC_NET = 0xffffff00 - IN_CLASSC_NSHIFT = 0x8 - IN_CLASSD_HOST = 0xfffffff - IN_CLASSD_NET = 0xf0000000 - IN_CLASSD_NSHIFT = 0x1c - IN_LINKLOCALNETNUM = 0xa9fe0000 - IN_LOOPBACKNET = 0x7f - IPPROTO_3PC = 0x22 - IPPROTO_ADFS = 0x44 - IPPROTO_AH = 0x33 - IPPROTO_AHIP = 0x3d - IPPROTO_APES = 0x63 - IPPROTO_ARGUS = 0xd - IPPROTO_AX25 = 0x5d - IPPROTO_BHA = 0x31 - IPPROTO_BLT = 0x1e - IPPROTO_BRSATMON = 0x4c - IPPROTO_CFTP = 0x3e - IPPROTO_CHAOS = 0x10 - IPPROTO_CMTP = 0x26 - IPPROTO_CPHB = 0x49 - IPPROTO_CPNX = 0x48 - IPPROTO_DDP = 0x25 - IPPROTO_DGP = 0x56 - IPPROTO_DIVERT = 0xfe - IPPROTO_DONE = 0x101 - IPPROTO_DSTOPTS = 0x3c - IPPROTO_EGP = 0x8 - IPPROTO_EMCON = 0xe - IPPROTO_ENCAP = 0x62 - IPPROTO_EON = 0x50 - IPPROTO_ESP = 0x32 - IPPROTO_ETHERIP = 0x61 - IPPROTO_FRAGMENT = 0x2c - IPPROTO_GGP = 0x3 - IPPROTO_GMTP = 0x64 - IPPROTO_GRE = 0x2f - IPPROTO_HELLO = 0x3f - IPPROTO_HMP = 0x14 - IPPROTO_HOPOPTS = 0x0 - IPPROTO_ICMP = 0x1 - IPPROTO_ICMPV6 = 0x3a - IPPROTO_IDP = 0x16 - IPPROTO_IDPR = 0x23 - IPPROTO_IDRP = 0x2d - IPPROTO_IGMP = 0x2 - IPPROTO_IGP = 0x55 - IPPROTO_IGRP = 0x58 - IPPROTO_IL = 0x28 - IPPROTO_INLSP = 0x34 - IPPROTO_INP = 0x20 - IPPROTO_IP = 0x0 - IPPROTO_IPCOMP = 0x6c - IPPROTO_IPCV = 0x47 - IPPROTO_IPEIP = 0x5e - IPPROTO_IPIP = 0x4 - IPPROTO_IPPC = 0x43 - IPPROTO_IPV4 = 0x4 - IPPROTO_IPV6 = 0x29 - IPPROTO_IRTP = 0x1c - IPPROTO_KRYPTOLAN = 0x41 - IPPROTO_LARP = 0x5b - IPPROTO_LEAF1 = 0x19 - IPPROTO_LEAF2 = 0x1a - IPPROTO_MAX = 0x100 - IPPROTO_MAXID = 0x34 - IPPROTO_MEAS = 0x13 - IPPROTO_MHRP = 0x30 - IPPROTO_MICP = 0x5f - IPPROTO_MTP = 0x5c - IPPROTO_MUX = 0x12 - IPPROTO_ND = 0x4d - IPPROTO_NHRP = 0x36 - IPPROTO_NONE = 0x3b - IPPROTO_NSP = 0x1f - IPPROTO_NVPII = 0xb - IPPROTO_OSPFIGP = 0x59 - IPPROTO_PGM = 0x71 - IPPROTO_PIGP = 0x9 - IPPROTO_PIM = 0x67 - IPPROTO_PRM = 0x15 - IPPROTO_PUP = 0xc - IPPROTO_PVP = 0x4b - IPPROTO_RAW = 0xff - IPPROTO_RCCMON = 0xa - IPPROTO_RDP = 0x1b - IPPROTO_ROUTING = 0x2b - IPPROTO_RSVP = 0x2e - IPPROTO_RVD = 0x42 - IPPROTO_SATEXPAK = 0x40 - IPPROTO_SATMON = 0x45 - IPPROTO_SCCSP = 0x60 - IPPROTO_SCTP = 0x84 - IPPROTO_SDRP = 0x2a - IPPROTO_SEP = 0x21 - IPPROTO_SRPC = 0x5a - IPPROTO_ST = 0x7 - IPPROTO_SVMTP = 0x52 - IPPROTO_SWIPE = 0x35 - IPPROTO_TCF = 0x57 - IPPROTO_TCP = 0x6 - IPPROTO_TP = 0x1d - IPPROTO_TPXX = 0x27 - IPPROTO_TRUNK1 = 0x17 - IPPROTO_TRUNK2 = 0x18 - IPPROTO_TTP = 0x54 - IPPROTO_UDP = 0x11 - IPPROTO_VINES = 0x53 - IPPROTO_VISA = 0x46 - IPPROTO_VMTP = 0x51 - IPPROTO_WBEXPAK = 0x4f - IPPROTO_WBMON = 0x4e - IPPROTO_WSN = 0x4a - IPPROTO_XNET = 0xf - IPPROTO_XTP = 0x24 - IPV6_2292DSTOPTS = 0x17 - IPV6_2292HOPLIMIT = 0x14 - IPV6_2292HOPOPTS = 0x16 - IPV6_2292NEXTHOP = 0x15 - IPV6_2292PKTINFO = 0x13 - IPV6_2292PKTOPTIONS = 0x19 - IPV6_2292RTHDR = 0x18 - IPV6_3542DSTOPTS = 0x32 - IPV6_3542HOPLIMIT = 0x2f - IPV6_3542HOPOPTS = 0x31 - IPV6_3542NEXTHOP = 0x30 - IPV6_3542PKTINFO = 0x2e - IPV6_3542RTHDR = 0x33 - IPV6_ADDR_MC_FLAGS_PREFIX = 0x20 - IPV6_ADDR_MC_FLAGS_TRANSIENT = 0x10 - IPV6_ADDR_MC_FLAGS_UNICAST_BASED = 0x30 - IPV6_AUTOFLOWLABEL = 0x3b - IPV6_BINDV6ONLY = 0x1b - IPV6_BOUND_IF = 0x7d - IPV6_CHECKSUM = 0x1a - IPV6_DEFAULT_MULTICAST_HOPS = 0x1 - IPV6_DEFAULT_MULTICAST_LOOP = 0x1 - IPV6_DEFHLIM = 0x40 - IPV6_DONTFRAG = 0x3e - IPV6_DSTOPTS = 0x32 - IPV6_FAITH = 0x1d - IPV6_FLOWINFO_MASK = 0xffffff0f - IPV6_FLOWLABEL_MASK = 0xffff0f00 - IPV6_FLOW_ECN_MASK = 0x3000 - IPV6_FRAGTTL = 0x3c - IPV6_FW_ADD = 0x1e - IPV6_FW_DEL = 0x1f - IPV6_FW_FLUSH = 0x20 - IPV6_FW_GET = 0x22 - IPV6_FW_ZERO = 0x21 - IPV6_HLIMDEC = 0x1 - IPV6_HOPLIMIT = 0x2f - IPV6_HOPOPTS = 0x31 - IPV6_IPSEC_POLICY = 0x1c - IPV6_JOIN_GROUP = 0xc - IPV6_LEAVE_GROUP = 0xd - IPV6_MAXHLIM = 0xff - IPV6_MAXOPTHDR = 0x800 - IPV6_MAXPACKET = 0xffff - IPV6_MAX_GROUP_SRC_FILTER = 0x200 - IPV6_MAX_MEMBERSHIPS = 0xfff - IPV6_MAX_SOCK_SRC_FILTER = 0x80 - IPV6_MIN_MEMBERSHIPS = 0x1f - IPV6_MMTU = 0x500 - IPV6_MSFILTER = 0x4a - IPV6_MULTICAST_HOPS = 0xa - IPV6_MULTICAST_IF = 0x9 - IPV6_MULTICAST_LOOP = 0xb - IPV6_NEXTHOP = 0x30 - IPV6_PATHMTU = 0x2c - IPV6_PKTINFO = 0x2e - IPV6_PORTRANGE = 0xe - IPV6_PORTRANGE_DEFAULT = 0x0 - IPV6_PORTRANGE_HIGH = 0x1 - IPV6_PORTRANGE_LOW = 0x2 - IPV6_PREFER_TEMPADDR = 0x3f - IPV6_RECVDSTOPTS = 0x28 - IPV6_RECVHOPLIMIT = 0x25 - IPV6_RECVHOPOPTS = 0x27 - IPV6_RECVPATHMTU = 0x2b - IPV6_RECVPKTINFO = 0x3d - IPV6_RECVRTHDR = 0x26 - IPV6_RECVTCLASS = 0x23 - IPV6_RTHDR = 0x33 - IPV6_RTHDRDSTOPTS = 0x39 - IPV6_RTHDR_LOOSE = 0x0 - IPV6_RTHDR_STRICT = 0x1 - IPV6_RTHDR_TYPE_0 = 0x0 - IPV6_SOCKOPT_RESERVED1 = 0x3 - IPV6_TCLASS = 0x24 - IPV6_UNICAST_HOPS = 0x4 - IPV6_USE_MIN_MTU = 0x2a - IPV6_V6ONLY = 0x1b - IPV6_VERSION = 0x60 - IPV6_VERSION_MASK = 0xf0 - IP_ADD_MEMBERSHIP = 0xc - IP_ADD_SOURCE_MEMBERSHIP = 0x46 - IP_BLOCK_SOURCE = 0x48 - IP_BOUND_IF = 0x19 - IP_DEFAULT_MULTICAST_LOOP = 0x1 - IP_DEFAULT_MULTICAST_TTL = 0x1 - IP_DF = 0x4000 - IP_DONTFRAG = 0x1c - IP_DROP_MEMBERSHIP = 0xd - IP_DROP_SOURCE_MEMBERSHIP = 0x47 - IP_DUMMYNET_CONFIGURE = 0x3c - IP_DUMMYNET_DEL = 0x3d - IP_DUMMYNET_FLUSH = 0x3e - IP_DUMMYNET_GET = 0x40 - IP_FAITH = 0x16 - IP_FW_ADD = 0x28 - IP_FW_DEL = 0x29 - IP_FW_FLUSH = 0x2a - IP_FW_GET = 0x2c - IP_FW_RESETLOG = 0x2d - IP_FW_ZERO = 0x2b - IP_HDRINCL = 0x2 - IP_IPSEC_POLICY = 0x15 - IP_MAXPACKET = 0xffff - IP_MAX_GROUP_SRC_FILTER = 0x200 - IP_MAX_MEMBERSHIPS = 0xfff - IP_MAX_SOCK_MUTE_FILTER = 0x80 - IP_MAX_SOCK_SRC_FILTER = 0x80 - IP_MF = 0x2000 - IP_MIN_MEMBERSHIPS = 0x1f - IP_MSFILTER = 0x4a - IP_MSS = 0x240 - IP_MULTICAST_IF = 0x9 - IP_MULTICAST_IFINDEX = 0x42 - IP_MULTICAST_LOOP = 0xb - IP_MULTICAST_TTL = 0xa - IP_MULTICAST_VIF = 0xe - IP_NAT__XXX = 0x37 - IP_OFFMASK = 0x1fff - IP_OLD_FW_ADD = 0x32 - IP_OLD_FW_DEL = 0x33 - IP_OLD_FW_FLUSH = 0x34 - IP_OLD_FW_GET = 0x36 - IP_OLD_FW_RESETLOG = 0x38 - IP_OLD_FW_ZERO = 0x35 - IP_OPTIONS = 0x1 - IP_PKTINFO = 0x1a - IP_PORTRANGE = 0x13 - IP_PORTRANGE_DEFAULT = 0x0 - IP_PORTRANGE_HIGH = 0x1 - IP_PORTRANGE_LOW = 0x2 - IP_RECVDSTADDR = 0x7 - IP_RECVIF = 0x14 - IP_RECVOPTS = 0x5 - IP_RECVPKTINFO = 0x1a - IP_RECVRETOPTS = 0x6 - IP_RECVTOS = 0x1b - IP_RECVTTL = 0x18 - IP_RETOPTS = 0x8 - IP_RF = 0x8000 - IP_RSVP_OFF = 0x10 - IP_RSVP_ON = 0xf - IP_RSVP_VIF_OFF = 0x12 - IP_RSVP_VIF_ON = 0x11 - IP_STRIPHDR = 0x17 - IP_TOS = 0x3 - IP_TRAFFIC_MGT_BACKGROUND = 0x41 - IP_TTL = 0x4 - IP_UNBLOCK_SOURCE = 0x49 - ISIG = 0x80 - ISTRIP = 0x20 - IUTF8 = 0x4000 - IXANY = 0x800 - IXOFF = 0x400 - IXON = 0x200 - KERN_HOSTNAME = 0xa - KERN_OSRELEASE = 0x2 - KERN_OSTYPE = 0x1 - KERN_VERSION = 0x4 - LOCAL_PEERCRED = 0x1 - LOCAL_PEEREPID = 0x3 - LOCAL_PEEREUUID = 0x5 - LOCAL_PEERPID = 0x2 - LOCAL_PEERTOKEN = 0x6 - LOCAL_PEERUUID = 0x4 - LOCK_EX = 0x2 - LOCK_NB = 0x4 - LOCK_SH = 0x1 - LOCK_UN = 0x8 - MADV_CAN_REUSE = 0x9 - MADV_DONTNEED = 0x4 - MADV_FREE = 0x5 - MADV_FREE_REUSABLE = 0x7 - MADV_FREE_REUSE = 0x8 - MADV_NORMAL = 0x0 - MADV_PAGEOUT = 0xa - MADV_RANDOM = 0x1 - MADV_SEQUENTIAL = 0x2 - MADV_WILLNEED = 0x3 - MADV_ZERO_WIRED_PAGES = 0x6 - MAP_32BIT = 0x8000 - MAP_ANON = 0x1000 - MAP_ANONYMOUS = 0x1000 - MAP_COPY = 0x2 - MAP_FILE = 0x0 - MAP_FIXED = 0x10 - MAP_HASSEMAPHORE = 0x200 - MAP_JIT = 0x800 - MAP_NOCACHE = 0x400 - MAP_NOEXTEND = 0x100 - MAP_NORESERVE = 0x40 - MAP_PRIVATE = 0x2 - MAP_RENAME = 0x20 - MAP_RESERVED0080 = 0x80 - MAP_RESILIENT_CODESIGN = 0x2000 - MAP_RESILIENT_MEDIA = 0x4000 - MAP_SHARED = 0x1 - MAP_TRANSLATED_ALLOW_EXECUTE = 0x20000 - MAP_UNIX03 = 0x40000 - MCAST_BLOCK_SOURCE = 0x54 - MCAST_EXCLUDE = 0x2 - MCAST_INCLUDE = 0x1 - MCAST_JOIN_GROUP = 0x50 - MCAST_JOIN_SOURCE_GROUP = 0x52 - MCAST_LEAVE_GROUP = 0x51 - MCAST_LEAVE_SOURCE_GROUP = 0x53 - MCAST_UNBLOCK_SOURCE = 0x55 - MCAST_UNDEFINED = 0x0 - MCL_CURRENT = 0x1 - MCL_FUTURE = 0x2 - MNT_ASYNC = 0x40 - MNT_AUTOMOUNTED = 0x400000 - MNT_CMDFLAGS = 0xf0000 - MNT_CPROTECT = 0x80 - MNT_DEFWRITE = 0x2000000 - MNT_DONTBROWSE = 0x100000 - MNT_DOVOLFS = 0x8000 - MNT_DWAIT = 0x4 - MNT_EXPORTED = 0x100 - MNT_EXT_ROOT_DATA_VOL = 0x1 - MNT_FORCE = 0x80000 - MNT_IGNORE_OWNERSHIP = 0x200000 - MNT_JOURNALED = 0x800000 - MNT_LOCAL = 0x1000 - MNT_MULTILABEL = 0x4000000 - MNT_NOATIME = 0x10000000 - MNT_NOBLOCK = 0x20000 - MNT_NODEV = 0x10 - MNT_NOEXEC = 0x4 - MNT_NOSUID = 0x8 - MNT_NOUSERXATTR = 0x1000000 - MNT_NOWAIT = 0x2 - MNT_QUARANTINE = 0x400 - MNT_QUOTA = 0x2000 - MNT_RDONLY = 0x1 - MNT_RELOAD = 0x40000 - MNT_REMOVABLE = 0x200 - MNT_ROOTFS = 0x4000 - MNT_SNAPSHOT = 0x40000000 - MNT_STRICTATIME = 0x80000000 - MNT_SYNCHRONOUS = 0x2 - MNT_UNION = 0x20 - MNT_UNKNOWNPERMISSIONS = 0x200000 - MNT_UPDATE = 0x10000 - MNT_VISFLAGMASK = 0xd7f0f7ff - MNT_WAIT = 0x1 - MSG_CTRUNC = 0x20 - MSG_DONTROUTE = 0x4 - MSG_DONTWAIT = 0x80 - MSG_EOF = 0x100 - MSG_EOR = 0x8 - MSG_FLUSH = 0x400 - MSG_HAVEMORE = 0x2000 - MSG_HOLD = 0x800 - MSG_NEEDSA = 0x10000 - MSG_NOSIGNAL = 0x80000 - MSG_OOB = 0x1 - MSG_PEEK = 0x2 - MSG_RCVMORE = 0x4000 - MSG_SEND = 0x1000 - MSG_TRUNC = 0x10 - MSG_WAITALL = 0x40 - MSG_WAITSTREAM = 0x200 - MS_ASYNC = 0x1 - MS_DEACTIVATE = 0x8 - MS_INVALIDATE = 0x2 - MS_KILLPAGES = 0x4 - MS_SYNC = 0x10 - NAME_MAX = 0xff - NET_RT_DUMP = 0x1 - NET_RT_DUMP2 = 0x7 - NET_RT_FLAGS = 0x2 - NET_RT_FLAGS_PRIV = 0xa - NET_RT_IFLIST = 0x3 - NET_RT_IFLIST2 = 0x6 - NET_RT_MAXID = 0xb - NET_RT_STAT = 0x4 - NET_RT_TRASH = 0x5 - NFDBITS = 0x20 - NL0 = 0x0 - NL1 = 0x100 - NL2 = 0x200 - NL3 = 0x300 - NLDLY = 0x300 - NOFLSH = 0x80000000 - NOKERNINFO = 0x2000000 - NOTE_ABSOLUTE = 0x8 - NOTE_ATTRIB = 0x8 - NOTE_BACKGROUND = 0x40 - NOTE_CHILD = 0x4 - NOTE_CRITICAL = 0x20 - NOTE_DELETE = 0x1 - NOTE_EXEC = 0x20000000 - NOTE_EXIT = 0x80000000 - NOTE_EXITSTATUS = 0x4000000 - NOTE_EXIT_CSERROR = 0x40000 - NOTE_EXIT_DECRYPTFAIL = 0x10000 - NOTE_EXIT_DETAIL = 0x2000000 - NOTE_EXIT_DETAIL_MASK = 0x70000 - NOTE_EXIT_MEMORY = 0x20000 - NOTE_EXIT_REPARENTED = 0x80000 - NOTE_EXTEND = 0x4 - NOTE_FFAND = 0x40000000 - NOTE_FFCOPY = 0xc0000000 - NOTE_FFCTRLMASK = 0xc0000000 - NOTE_FFLAGSMASK = 0xffffff - NOTE_FFNOP = 0x0 - NOTE_FFOR = 0x80000000 - NOTE_FORK = 0x40000000 - NOTE_FUNLOCK = 0x100 - NOTE_LEEWAY = 0x10 - NOTE_LINK = 0x10 - NOTE_LOWAT = 0x1 - NOTE_MACHTIME = 0x100 - NOTE_MACH_CONTINUOUS_TIME = 0x80 - NOTE_NONE = 0x80 - NOTE_NSECONDS = 0x4 - NOTE_OOB = 0x2 - NOTE_PCTRLMASK = -0x100000 - NOTE_PDATAMASK = 0xfffff - NOTE_REAP = 0x10000000 - NOTE_RENAME = 0x20 - NOTE_REVOKE = 0x40 - NOTE_SECONDS = 0x1 - NOTE_SIGNAL = 0x8000000 - NOTE_TRACK = 0x1 - NOTE_TRACKERR = 0x2 - NOTE_TRIGGER = 0x1000000 - NOTE_USECONDS = 0x2 - NOTE_VM_ERROR = 0x10000000 - NOTE_VM_PRESSURE = 0x80000000 - NOTE_VM_PRESSURE_SUDDEN_TERMINATE = 0x20000000 - NOTE_VM_PRESSURE_TERMINATE = 0x40000000 - NOTE_WRITE = 0x2 - OCRNL = 0x10 - OFDEL = 0x20000 - OFILL = 0x80 - ONLCR = 0x2 - ONLRET = 0x40 - ONOCR = 0x20 - ONOEOT = 0x8 - OPOST = 0x1 - OXTABS = 0x4 - O_ACCMODE = 0x3 - O_ALERT = 0x20000000 - O_APPEND = 0x8 - O_ASYNC = 0x40 - O_CLOEXEC = 0x1000000 - O_CREAT = 0x200 - O_DIRECTORY = 0x100000 - O_DP_GETRAWENCRYPTED = 0x1 - O_DP_GETRAWUNENCRYPTED = 0x2 - O_DSYNC = 0x400000 - O_EVTONLY = 0x8000 - O_EXCL = 0x800 - O_EXLOCK = 0x20 - O_FSYNC = 0x80 - O_NDELAY = 0x4 - O_NOCTTY = 0x20000 - O_NOFOLLOW = 0x100 - O_NOFOLLOW_ANY = 0x20000000 - O_NONBLOCK = 0x4 - O_POPUP = 0x80000000 - O_RDONLY = 0x0 - O_RDWR = 0x2 - O_SHLOCK = 0x10 - O_SYMLINK = 0x200000 - O_SYNC = 0x80 - O_TRUNC = 0x400 - O_WRONLY = 0x1 - PARENB = 0x1000 - PARMRK = 0x8 - PARODD = 0x2000 - PENDIN = 0x20000000 - PRIO_PGRP = 0x1 - PRIO_PROCESS = 0x0 - PRIO_USER = 0x2 - PROT_EXEC = 0x4 - PROT_NONE = 0x0 - PROT_READ = 0x1 - PROT_WRITE = 0x2 - PT_ATTACH = 0xa - PT_ATTACHEXC = 0xe - PT_CONTINUE = 0x7 - PT_DENY_ATTACH = 0x1f - PT_DETACH = 0xb - PT_FIRSTMACH = 0x20 - PT_FORCEQUOTA = 0x1e - PT_KILL = 0x8 - PT_READ_D = 0x2 - PT_READ_I = 0x1 - PT_READ_U = 0x3 - PT_SIGEXC = 0xc - PT_STEP = 0x9 - PT_THUPDATE = 0xd - PT_TRACE_ME = 0x0 - PT_WRITE_D = 0x5 - PT_WRITE_I = 0x4 - PT_WRITE_U = 0x6 - RLIMIT_AS = 0x5 - RLIMIT_CORE = 0x4 - RLIMIT_CPU = 0x0 - RLIMIT_CPU_USAGE_MONITOR = 0x2 - RLIMIT_DATA = 0x2 - RLIMIT_FSIZE = 0x1 - RLIMIT_MEMLOCK = 0x6 - RLIMIT_NOFILE = 0x8 - RLIMIT_NPROC = 0x7 - RLIMIT_RSS = 0x5 - RLIMIT_STACK = 0x3 - RLIM_INFINITY = 0x7fffffffffffffff - RTAX_AUTHOR = 0x6 - RTAX_BRD = 0x7 - RTAX_DST = 0x0 - RTAX_GATEWAY = 0x1 - RTAX_GENMASK = 0x3 - RTAX_IFA = 0x5 - RTAX_IFP = 0x4 - RTAX_MAX = 0x8 - RTAX_NETMASK = 0x2 - RTA_AUTHOR = 0x40 - RTA_BRD = 0x80 - RTA_DST = 0x1 - RTA_GATEWAY = 0x2 - RTA_GENMASK = 0x8 - RTA_IFA = 0x20 - RTA_IFP = 0x10 - RTA_NETMASK = 0x4 - RTF_BLACKHOLE = 0x1000 - RTF_BROADCAST = 0x400000 - RTF_CLONING = 0x100 - RTF_CONDEMNED = 0x2000000 - RTF_DEAD = 0x20000000 - RTF_DELCLONE = 0x80 - RTF_DONE = 0x40 - RTF_DYNAMIC = 0x10 - RTF_GATEWAY = 0x2 - RTF_GLOBAL = 0x40000000 - RTF_HOST = 0x4 - RTF_IFREF = 0x4000000 - RTF_IFSCOPE = 0x1000000 - RTF_LLDATA = 0x400 - RTF_LLINFO = 0x400 - RTF_LOCAL = 0x200000 - RTF_MODIFIED = 0x20 - RTF_MULTICAST = 0x800000 - RTF_NOIFREF = 0x2000 - RTF_PINNED = 0x100000 - RTF_PRCLONING = 0x10000 - RTF_PROTO1 = 0x8000 - RTF_PROTO2 = 0x4000 - RTF_PROTO3 = 0x40000 - RTF_PROXY = 0x8000000 - RTF_REJECT = 0x8 - RTF_ROUTER = 0x10000000 - RTF_STATIC = 0x800 - RTF_UP = 0x1 - RTF_WASCLONED = 0x20000 - RTF_XRESOLVE = 0x200 - RTM_ADD = 0x1 - RTM_CHANGE = 0x3 - RTM_DELADDR = 0xd - RTM_DELETE = 0x2 - RTM_DELMADDR = 0x10 - RTM_GET = 0x4 - RTM_GET2 = 0x14 - RTM_IFINFO = 0xe - RTM_IFINFO2 = 0x12 - RTM_LOCK = 0x8 - RTM_LOSING = 0x5 - RTM_MISS = 0x7 - RTM_NEWADDR = 0xc - RTM_NEWMADDR = 0xf - RTM_NEWMADDR2 = 0x13 - RTM_OLDADD = 0x9 - RTM_OLDDEL = 0xa - RTM_REDIRECT = 0x6 - RTM_RESOLVE = 0xb - RTM_RTTUNIT = 0xf4240 - RTM_VERSION = 0x5 - RTV_EXPIRE = 0x4 - RTV_HOPCOUNT = 0x2 - RTV_MTU = 0x1 - RTV_RPIPE = 0x8 - RTV_RTT = 0x40 - RTV_RTTVAR = 0x80 - RTV_SPIPE = 0x10 - RTV_SSTHRESH = 0x20 - RUSAGE_CHILDREN = -0x1 - RUSAGE_SELF = 0x0 - SCM_CREDS = 0x3 - SCM_RIGHTS = 0x1 - SCM_TIMESTAMP = 0x2 - SCM_TIMESTAMP_MONOTONIC = 0x4 - SEEK_CUR = 0x1 - SEEK_DATA = 0x4 - SEEK_END = 0x2 - SEEK_HOLE = 0x3 - SEEK_SET = 0x0 - SHUT_RD = 0x0 - SHUT_RDWR = 0x2 - SHUT_WR = 0x1 - SIOCADDMULTI = 0x80206931 - SIOCAIFADDR = 0x8040691a - SIOCARPIPLL = 0xc0206928 - SIOCATMARK = 0x40047307 - SIOCAUTOADDR = 0xc0206926 - SIOCAUTONETMASK = 0x80206927 - SIOCDELMULTI = 0x80206932 - SIOCDIFADDR = 0x80206919 - SIOCDIFPHYADDR = 0x80206941 - SIOCGDRVSPEC = 0xc028697b - SIOCGETVLAN = 0xc020697f - SIOCGHIWAT = 0x40047301 - SIOCGIF6LOWPAN = 0xc02069c5 - SIOCGIFADDR = 0xc0206921 - SIOCGIFALTMTU = 0xc0206948 - SIOCGIFASYNCMAP = 0xc020697c - SIOCGIFBOND = 0xc0206947 - SIOCGIFBRDADDR = 0xc0206923 - SIOCGIFCAP = 0xc020695b - SIOCGIFCONF = 0xc00c6924 - SIOCGIFDEVMTU = 0xc0206944 - SIOCGIFDSTADDR = 0xc0206922 - SIOCGIFFLAGS = 0xc0206911 - SIOCGIFFUNCTIONALTYPE = 0xc02069ad - SIOCGIFGENERIC = 0xc020693a - SIOCGIFKPI = 0xc0206987 - SIOCGIFMAC = 0xc0206982 - SIOCGIFMEDIA = 0xc02c6938 - SIOCGIFMETRIC = 0xc0206917 - SIOCGIFMTU = 0xc0206933 - SIOCGIFNETMASK = 0xc0206925 - SIOCGIFPDSTADDR = 0xc0206940 - SIOCGIFPHYS = 0xc0206935 - SIOCGIFPSRCADDR = 0xc020693f - SIOCGIFSTATUS = 0xc331693d - SIOCGIFVLAN = 0xc020697f - SIOCGIFWAKEFLAGS = 0xc0206988 - SIOCGIFXMEDIA = 0xc02c6948 - SIOCGLOWAT = 0x40047303 - SIOCGPGRP = 0x40047309 - SIOCIFCREATE = 0xc0206978 - SIOCIFCREATE2 = 0xc020697a - SIOCIFDESTROY = 0x80206979 - SIOCIFGCLONERS = 0xc0106981 - SIOCRSLVMULTI = 0xc010693b - SIOCSDRVSPEC = 0x8028697b - SIOCSETVLAN = 0x8020697e - SIOCSHIWAT = 0x80047300 - SIOCSIF6LOWPAN = 0x802069c4 - SIOCSIFADDR = 0x8020690c - SIOCSIFALTMTU = 0x80206945 - SIOCSIFASYNCMAP = 0x8020697d - SIOCSIFBOND = 0x80206946 - SIOCSIFBRDADDR = 0x80206913 - SIOCSIFCAP = 0x8020695a - SIOCSIFDSTADDR = 0x8020690e - SIOCSIFFLAGS = 0x80206910 - SIOCSIFGENERIC = 0x80206939 - SIOCSIFKPI = 0x80206986 - SIOCSIFLLADDR = 0x8020693c - SIOCSIFMAC = 0x80206983 - SIOCSIFMEDIA = 0xc0206937 - SIOCSIFMETRIC = 0x80206918 - SIOCSIFMTU = 0x80206934 - SIOCSIFNETMASK = 0x80206916 - SIOCSIFPHYADDR = 0x8040693e - SIOCSIFPHYS = 0x80206936 - SIOCSIFVLAN = 0x8020697e - SIOCSLOWAT = 0x80047302 - SIOCSPGRP = 0x80047308 - SOCK_DGRAM = 0x2 - SOCK_MAXADDRLEN = 0xff - SOCK_RAW = 0x3 - SOCK_RDM = 0x4 - SOCK_SEQPACKET = 0x5 - SOCK_STREAM = 0x1 - SOL_LOCAL = 0x0 - SOL_SOCKET = 0xffff - SOMAXCONN = 0x80 - SO_ACCEPTCONN = 0x2 - SO_BROADCAST = 0x20 - SO_DEBUG = 0x1 - SO_DONTROUTE = 0x10 - SO_DONTTRUNC = 0x2000 - SO_ERROR = 0x1007 - SO_KEEPALIVE = 0x8 - SO_LABEL = 0x1010 - SO_LINGER = 0x80 - SO_LINGER_SEC = 0x1080 - SO_NETSVC_MARKING_LEVEL = 0x1119 - SO_NET_SERVICE_TYPE = 0x1116 - SO_NKE = 0x1021 - SO_NOADDRERR = 0x1023 - SO_NOSIGPIPE = 0x1022 - SO_NOTIFYCONFLICT = 0x1026 - SO_NP_EXTENSIONS = 0x1083 - SO_NREAD = 0x1020 - SO_NUMRCVPKT = 0x1112 - SO_NWRITE = 0x1024 - SO_OOBINLINE = 0x100 - SO_PEERLABEL = 0x1011 - SO_RANDOMPORT = 0x1082 - SO_RCVBUF = 0x1002 - SO_RCVLOWAT = 0x1004 - SO_RCVTIMEO = 0x1006 - SO_REUSEADDR = 0x4 - SO_REUSEPORT = 0x200 - SO_REUSESHAREUID = 0x1025 - SO_SNDBUF = 0x1001 - SO_SNDLOWAT = 0x1003 - SO_SNDTIMEO = 0x1005 - SO_TIMESTAMP = 0x400 - SO_TIMESTAMP_MONOTONIC = 0x800 - SO_TYPE = 0x1008 - SO_UPCALLCLOSEWAIT = 0x1027 - SO_USELOOPBACK = 0x40 - SO_WANTMORE = 0x4000 - SO_WANTOOBFLAG = 0x8000 - S_IEXEC = 0x40 - S_IFBLK = 0x6000 - S_IFCHR = 0x2000 - S_IFDIR = 0x4000 - S_IFIFO = 0x1000 - S_IFLNK = 0xa000 - S_IFMT = 0xf000 - S_IFREG = 0x8000 - S_IFSOCK = 0xc000 - S_IFWHT = 0xe000 - S_IREAD = 0x100 - S_IRGRP = 0x20 - S_IROTH = 0x4 - S_IRUSR = 0x100 - S_IRWXG = 0x38 - S_IRWXO = 0x7 - S_IRWXU = 0x1c0 - S_ISGID = 0x400 - S_ISTXT = 0x200 - S_ISUID = 0x800 - S_ISVTX = 0x200 - S_IWGRP = 0x10 - S_IWOTH = 0x2 - S_IWRITE = 0x80 - S_IWUSR = 0x80 - S_IXGRP = 0x8 - S_IXOTH = 0x1 - S_IXUSR = 0x40 - TAB0 = 0x0 - TAB1 = 0x400 - TAB2 = 0x800 - TAB3 = 0x4 - TABDLY = 0xc04 - TCIFLUSH = 0x1 - TCIOFF = 0x3 - TCIOFLUSH = 0x3 - TCION = 0x4 - TCOFLUSH = 0x2 - TCOOFF = 0x1 - TCOON = 0x2 - TCP_CONNECTIONTIMEOUT = 0x20 - TCP_CONNECTION_INFO = 0x106 - TCP_ENABLE_ECN = 0x104 - TCP_FASTOPEN = 0x105 - TCP_KEEPALIVE = 0x10 - TCP_KEEPCNT = 0x102 - TCP_KEEPINTVL = 0x101 - TCP_MAXHLEN = 0x3c - TCP_MAXOLEN = 0x28 - TCP_MAXSEG = 0x2 - TCP_MAXWIN = 0xffff - TCP_MAX_SACK = 0x4 - TCP_MAX_WINSHIFT = 0xe - TCP_MINMSS = 0xd8 - TCP_MSS = 0x200 - TCP_NODELAY = 0x1 - TCP_NOOPT = 0x8 - TCP_NOPUSH = 0x4 - TCP_NOTSENT_LOWAT = 0x201 - TCP_RXT_CONNDROPTIME = 0x80 - TCP_RXT_FINDROP = 0x100 - TCP_SENDMOREACKS = 0x103 - TCSAFLUSH = 0x2 - TIOCCBRK = 0x2000747a - TIOCCDTR = 0x20007478 - TIOCCONS = 0x80047462 - TIOCDCDTIMESTAMP = 0x40107458 - TIOCDRAIN = 0x2000745e - TIOCDSIMICROCODE = 0x20007455 - TIOCEXCL = 0x2000740d - TIOCEXT = 0x80047460 - TIOCFLUSH = 0x80047410 - TIOCGDRAINWAIT = 0x40047456 - TIOCGETA = 0x40487413 - TIOCGETD = 0x4004741a - TIOCGPGRP = 0x40047477 - TIOCGWINSZ = 0x40087468 - TIOCIXOFF = 0x20007480 - TIOCIXON = 0x20007481 - TIOCMBIC = 0x8004746b - TIOCMBIS = 0x8004746c - TIOCMGDTRWAIT = 0x4004745a - TIOCMGET = 0x4004746a - TIOCMODG = 0x40047403 - TIOCMODS = 0x80047404 - TIOCMSDTRWAIT = 0x8004745b - TIOCMSET = 0x8004746d - TIOCM_CAR = 0x40 - TIOCM_CD = 0x40 - TIOCM_CTS = 0x20 - TIOCM_DSR = 0x100 - TIOCM_DTR = 0x2 - TIOCM_LE = 0x1 - TIOCM_RI = 0x80 - TIOCM_RNG = 0x80 - TIOCM_RTS = 0x4 - TIOCM_SR = 0x10 - TIOCM_ST = 0x8 - TIOCNOTTY = 0x20007471 - TIOCNXCL = 0x2000740e - TIOCOUTQ = 0x40047473 - TIOCPKT = 0x80047470 - TIOCPKT_DATA = 0x0 - TIOCPKT_DOSTOP = 0x20 - TIOCPKT_FLUSHREAD = 0x1 - TIOCPKT_FLUSHWRITE = 0x2 - TIOCPKT_IOCTL = 0x40 - TIOCPKT_NOSTOP = 0x10 - TIOCPKT_START = 0x8 - TIOCPKT_STOP = 0x4 - TIOCPTYGNAME = 0x40807453 - TIOCPTYGRANT = 0x20007454 - TIOCPTYUNLK = 0x20007452 - TIOCREMOTE = 0x80047469 - TIOCSBRK = 0x2000747b - TIOCSCONS = 0x20007463 - TIOCSCTTY = 0x20007461 - TIOCSDRAINWAIT = 0x80047457 - TIOCSDTR = 0x20007479 - TIOCSETA = 0x80487414 - TIOCSETAF = 0x80487416 - TIOCSETAW = 0x80487415 - TIOCSETD = 0x8004741b - TIOCSIG = 0x2000745f - TIOCSPGRP = 0x80047476 - TIOCSTART = 0x2000746e - TIOCSTAT = 0x20007465 - TIOCSTI = 0x80017472 - TIOCSTOP = 0x2000746f - TIOCSWINSZ = 0x80087467 - TIOCTIMESTAMP = 0x40107459 - TIOCUCNTL = 0x80047466 - TOSTOP = 0x400000 - VDISCARD = 0xf - VDSUSP = 0xb - VEOF = 0x0 - VEOL = 0x1 - VEOL2 = 0x2 - VERASE = 0x3 - VINTR = 0x8 - VKILL = 0x5 - VLNEXT = 0xe - VMIN = 0x10 - VM_LOADAVG = 0x2 - VM_MACHFACTOR = 0x4 - VM_MAXID = 0x6 - VM_METER = 0x1 - VM_SWAPUSAGE = 0x5 - VQUIT = 0x9 - VREPRINT = 0x6 - VSTART = 0xc - VSTATUS = 0x12 - VSTOP = 0xd - VSUSP = 0xa - VT0 = 0x0 - VT1 = 0x10000 - VTDLY = 0x10000 - VTIME = 0x11 - VWERASE = 0x4 - WCONTINUED = 0x10 - WCOREFLAG = 0x80 - WEXITED = 0x4 - WNOHANG = 0x1 - WNOWAIT = 0x20 - WORDSIZE = 0x40 - WSTOPPED = 0x8 - WUNTRACED = 0x2 - XATTR_CREATE = 0x2 - XATTR_NODEFAULT = 0x10 - XATTR_NOFOLLOW = 0x1 - XATTR_NOSECURITY = 0x8 - XATTR_REPLACE = 0x4 - XATTR_SHOWCOMPRESSION = 0x20 + AF_APPLETALK = 0x10 + AF_CCITT = 0xa + AF_CHAOS = 0x5 + AF_CNT = 0x15 + AF_COIP = 0x14 + AF_DATAKIT = 0x9 + AF_DECnet = 0xc + AF_DLI = 0xd + AF_E164 = 0x1c + AF_ECMA = 0x8 + AF_HYLINK = 0xf + AF_IEEE80211 = 0x25 + AF_IMPLINK = 0x3 + AF_INET = 0x2 + AF_INET6 = 0x1e + AF_IPX = 0x17 + AF_ISDN = 0x1c + AF_ISO = 0x7 + AF_LAT = 0xe + AF_LINK = 0x12 + AF_LOCAL = 0x1 + AF_MAX = 0x29 + AF_NATM = 0x1f + AF_NDRV = 0x1b + AF_NETBIOS = 0x21 + AF_NS = 0x6 + AF_OSI = 0x7 + AF_PPP = 0x22 + AF_PUP = 0x4 + AF_RESERVED_36 = 0x24 + AF_ROUTE = 0x11 + AF_SIP = 0x18 + AF_SNA = 0xb + AF_SYSTEM = 0x20 + AF_SYS_CONTROL = 0x2 + AF_UNIX = 0x1 + AF_UNSPEC = 0x0 + AF_UTUN = 0x26 + AF_VSOCK = 0x28 + ALTWERASE = 0x200 + ATTR_BIT_MAP_COUNT = 0x5 + ATTR_CMN_ACCESSMASK = 0x20000 + ATTR_CMN_ACCTIME = 0x1000 + ATTR_CMN_ADDEDTIME = 0x10000000 + ATTR_CMN_BKUPTIME = 0x2000 + ATTR_CMN_CHGTIME = 0x800 + ATTR_CMN_CRTIME = 0x200 + ATTR_CMN_DATA_PROTECT_FLAGS = 0x40000000 + ATTR_CMN_DEVID = 0x2 + ATTR_CMN_DOCUMENT_ID = 0x100000 + ATTR_CMN_ERROR = 0x20000000 + ATTR_CMN_EXTENDED_SECURITY = 0x400000 + ATTR_CMN_FILEID = 0x2000000 + ATTR_CMN_FLAGS = 0x40000 + ATTR_CMN_FNDRINFO = 0x4000 + ATTR_CMN_FSID = 0x4 + ATTR_CMN_FULLPATH = 0x8000000 + ATTR_CMN_GEN_COUNT = 0x80000 + ATTR_CMN_GRPID = 0x10000 + ATTR_CMN_GRPUUID = 0x1000000 + ATTR_CMN_MODTIME = 0x400 + ATTR_CMN_NAME = 0x1 + ATTR_CMN_NAMEDATTRCOUNT = 0x80000 + ATTR_CMN_NAMEDATTRLIST = 0x100000 + ATTR_CMN_OBJID = 0x20 + ATTR_CMN_OBJPERMANENTID = 0x40 + ATTR_CMN_OBJTAG = 0x10 + ATTR_CMN_OBJTYPE = 0x8 + ATTR_CMN_OWNERID = 0x8000 + ATTR_CMN_PARENTID = 0x4000000 + ATTR_CMN_PAROBJID = 0x80 + ATTR_CMN_RETURNED_ATTRS = 0x80000000 + ATTR_CMN_SCRIPT = 0x100 + ATTR_CMN_SETMASK = 0x51c7ff00 + ATTR_CMN_USERACCESS = 0x200000 + ATTR_CMN_UUID = 0x800000 + ATTR_CMN_VALIDMASK = 0xffffffff + ATTR_CMN_VOLSETMASK = 0x6700 + ATTR_FILE_ALLOCSIZE = 0x4 + ATTR_FILE_CLUMPSIZE = 0x10 + ATTR_FILE_DATAALLOCSIZE = 0x400 + ATTR_FILE_DATAEXTENTS = 0x800 + ATTR_FILE_DATALENGTH = 0x200 + ATTR_FILE_DEVTYPE = 0x20 + ATTR_FILE_FILETYPE = 0x40 + ATTR_FILE_FORKCOUNT = 0x80 + ATTR_FILE_FORKLIST = 0x100 + ATTR_FILE_IOBLOCKSIZE = 0x8 + ATTR_FILE_LINKCOUNT = 0x1 + ATTR_FILE_RSRCALLOCSIZE = 0x2000 + ATTR_FILE_RSRCEXTENTS = 0x4000 + ATTR_FILE_RSRCLENGTH = 0x1000 + ATTR_FILE_SETMASK = 0x20 + ATTR_FILE_TOTALSIZE = 0x2 + ATTR_FILE_VALIDMASK = 0x37ff + ATTR_VOL_ALLOCATIONCLUMP = 0x40 + ATTR_VOL_ATTRIBUTES = 0x40000000 + ATTR_VOL_CAPABILITIES = 0x20000 + ATTR_VOL_DIRCOUNT = 0x400 + ATTR_VOL_ENCODINGSUSED = 0x10000 + ATTR_VOL_FILECOUNT = 0x200 + ATTR_VOL_FSTYPE = 0x1 + ATTR_VOL_INFO = 0x80000000 + ATTR_VOL_IOBLOCKSIZE = 0x80 + ATTR_VOL_MAXOBJCOUNT = 0x800 + ATTR_VOL_MINALLOCATION = 0x20 + ATTR_VOL_MOUNTEDDEVICE = 0x8000 + ATTR_VOL_MOUNTFLAGS = 0x4000 + ATTR_VOL_MOUNTPOINT = 0x1000 + ATTR_VOL_NAME = 0x2000 + ATTR_VOL_OBJCOUNT = 0x100 + ATTR_VOL_QUOTA_SIZE = 0x10000000 + ATTR_VOL_RESERVED_SIZE = 0x20000000 + ATTR_VOL_SETMASK = 0x80002000 + ATTR_VOL_SIGNATURE = 0x2 + ATTR_VOL_SIZE = 0x4 + ATTR_VOL_SPACEAVAIL = 0x10 + ATTR_VOL_SPACEFREE = 0x8 + ATTR_VOL_SPACEUSED = 0x800000 + ATTR_VOL_UUID = 0x40000 + ATTR_VOL_VALIDMASK = 0xf087ffff + B0 = 0x0 + B110 = 0x6e + B115200 = 0x1c200 + B1200 = 0x4b0 + B134 = 0x86 + B14400 = 0x3840 + B150 = 0x96 + B1800 = 0x708 + B19200 = 0x4b00 + B200 = 0xc8 + B230400 = 0x38400 + B2400 = 0x960 + B28800 = 0x7080 + B300 = 0x12c + B38400 = 0x9600 + B4800 = 0x12c0 + B50 = 0x32 + B57600 = 0xe100 + B600 = 0x258 + B7200 = 0x1c20 + B75 = 0x4b + B76800 = 0x12c00 + B9600 = 0x2580 + BIOCFLUSH = 0x20004268 + BIOCGBLEN = 0x40044266 + BIOCGDLT = 0x4004426a + BIOCGDLTLIST = 0xc00c4279 + BIOCGETIF = 0x4020426b + BIOCGHDRCMPLT = 0x40044274 + BIOCGRSIG = 0x40044272 + BIOCGRTIMEOUT = 0x4010426e + BIOCGSEESENT = 0x40044276 + BIOCGSTATS = 0x4008426f + BIOCIMMEDIATE = 0x80044270 + BIOCPROMISC = 0x20004269 + BIOCSBLEN = 0xc0044266 + BIOCSDLT = 0x80044278 + BIOCSETF = 0x80104267 + BIOCSETFNR = 0x8010427e + BIOCSETIF = 0x8020426c + BIOCSHDRCMPLT = 0x80044275 + BIOCSRSIG = 0x80044273 + BIOCSRTIMEOUT = 0x8010426d + BIOCSSEESENT = 0x80044277 + BIOCVERSION = 0x40044271 + BPF_A = 0x10 + BPF_ABS = 0x20 + BPF_ADD = 0x0 + BPF_ALIGNMENT = 0x4 + BPF_ALU = 0x4 + BPF_AND = 0x50 + BPF_B = 0x10 + BPF_DIV = 0x30 + BPF_H = 0x8 + BPF_IMM = 0x0 + BPF_IND = 0x40 + BPF_JA = 0x0 + BPF_JEQ = 0x10 + BPF_JGE = 0x30 + BPF_JGT = 0x20 + BPF_JMP = 0x5 + BPF_JSET = 0x40 + BPF_K = 0x0 + BPF_LD = 0x0 + BPF_LDX = 0x1 + BPF_LEN = 0x80 + BPF_LSH = 0x60 + BPF_MAJOR_VERSION = 0x1 + BPF_MAXBUFSIZE = 0x80000 + BPF_MAXINSNS = 0x200 + BPF_MEM = 0x60 + BPF_MEMWORDS = 0x10 + BPF_MINBUFSIZE = 0x20 + BPF_MINOR_VERSION = 0x1 + BPF_MISC = 0x7 + BPF_MSH = 0xa0 + BPF_MUL = 0x20 + BPF_NEG = 0x80 + BPF_OR = 0x40 + BPF_RELEASE = 0x30bb6 + BPF_RET = 0x6 + BPF_RSH = 0x70 + BPF_ST = 0x2 + BPF_STX = 0x3 + BPF_SUB = 0x10 + BPF_TAX = 0x0 + BPF_TXA = 0x80 + BPF_W = 0x0 + BPF_X = 0x8 + BRKINT = 0x2 + BS0 = 0x0 + BS1 = 0x8000 + BSDLY = 0x8000 + CFLUSH = 0xf + CLOCAL = 0x8000 + CLOCK_MONOTONIC = 0x6 + CLOCK_MONOTONIC_RAW = 0x4 + CLOCK_MONOTONIC_RAW_APPROX = 0x5 + CLOCK_PROCESS_CPUTIME_ID = 0xc + CLOCK_REALTIME = 0x0 + CLOCK_THREAD_CPUTIME_ID = 0x10 + CLOCK_UPTIME_RAW = 0x8 + CLOCK_UPTIME_RAW_APPROX = 0x9 + CLONE_NOFOLLOW = 0x1 + CLONE_NOOWNERCOPY = 0x2 + CR0 = 0x0 + CR1 = 0x1000 + CR2 = 0x2000 + CR3 = 0x3000 + CRDLY = 0x3000 + CREAD = 0x800 + CRTSCTS = 0x30000 + CS5 = 0x0 + CS6 = 0x100 + CS7 = 0x200 + CS8 = 0x300 + CSIZE = 0x300 + CSTART = 0x11 + CSTATUS = 0x14 + CSTOP = 0x13 + CSTOPB = 0x400 + CSUSP = 0x1a + CTLIOCGINFO = 0xc0644e03 + CTL_HW = 0x6 + CTL_KERN = 0x1 + CTL_MAXNAME = 0xc + CTL_NET = 0x4 + DLT_A429 = 0xb8 + DLT_A653_ICM = 0xb9 + DLT_AIRONET_HEADER = 0x78 + DLT_AOS = 0xde + DLT_APPLE_IP_OVER_IEEE1394 = 0x8a + DLT_ARCNET = 0x7 + DLT_ARCNET_LINUX = 0x81 + DLT_ATM_CLIP = 0x13 + DLT_ATM_RFC1483 = 0xb + DLT_AURORA = 0x7e + DLT_AX25 = 0x3 + DLT_AX25_KISS = 0xca + DLT_BACNET_MS_TP = 0xa5 + DLT_BLUETOOTH_HCI_H4 = 0xbb + DLT_BLUETOOTH_HCI_H4_WITH_PHDR = 0xc9 + DLT_CAN20B = 0xbe + DLT_CAN_SOCKETCAN = 0xe3 + DLT_CHAOS = 0x5 + DLT_CHDLC = 0x68 + DLT_CISCO_IOS = 0x76 + DLT_C_HDLC = 0x68 + DLT_C_HDLC_WITH_DIR = 0xcd + DLT_DBUS = 0xe7 + DLT_DECT = 0xdd + DLT_DOCSIS = 0x8f + DLT_DVB_CI = 0xeb + DLT_ECONET = 0x73 + DLT_EN10MB = 0x1 + DLT_EN3MB = 0x2 + DLT_ENC = 0x6d + DLT_ERF = 0xc5 + DLT_ERF_ETH = 0xaf + DLT_ERF_POS = 0xb0 + DLT_FC_2 = 0xe0 + DLT_FC_2_WITH_FRAME_DELIMS = 0xe1 + DLT_FDDI = 0xa + DLT_FLEXRAY = 0xd2 + DLT_FRELAY = 0x6b + DLT_FRELAY_WITH_DIR = 0xce + DLT_GCOM_SERIAL = 0xad + DLT_GCOM_T1E1 = 0xac + DLT_GPF_F = 0xab + DLT_GPF_T = 0xaa + DLT_GPRS_LLC = 0xa9 + DLT_GSMTAP_ABIS = 0xda + DLT_GSMTAP_UM = 0xd9 + DLT_HHDLC = 0x79 + DLT_IBM_SN = 0x92 + DLT_IBM_SP = 0x91 + DLT_IEEE802 = 0x6 + DLT_IEEE802_11 = 0x69 + DLT_IEEE802_11_RADIO = 0x7f + DLT_IEEE802_11_RADIO_AVS = 0xa3 + DLT_IEEE802_15_4 = 0xc3 + DLT_IEEE802_15_4_LINUX = 0xbf + DLT_IEEE802_15_4_NOFCS = 0xe6 + DLT_IEEE802_15_4_NONASK_PHY = 0xd7 + DLT_IEEE802_16_MAC_CPS = 0xbc + DLT_IEEE802_16_MAC_CPS_RADIO = 0xc1 + DLT_IPFILTER = 0x74 + DLT_IPMB = 0xc7 + DLT_IPMB_LINUX = 0xd1 + DLT_IPNET = 0xe2 + DLT_IPOIB = 0xf2 + DLT_IPV4 = 0xe4 + DLT_IPV6 = 0xe5 + DLT_IP_OVER_FC = 0x7a + DLT_JUNIPER_ATM1 = 0x89 + DLT_JUNIPER_ATM2 = 0x87 + DLT_JUNIPER_ATM_CEMIC = 0xee + DLT_JUNIPER_CHDLC = 0xb5 + DLT_JUNIPER_ES = 0x84 + DLT_JUNIPER_ETHER = 0xb2 + DLT_JUNIPER_FIBRECHANNEL = 0xea + DLT_JUNIPER_FRELAY = 0xb4 + DLT_JUNIPER_GGSN = 0x85 + DLT_JUNIPER_ISM = 0xc2 + DLT_JUNIPER_MFR = 0x86 + DLT_JUNIPER_MLFR = 0x83 + DLT_JUNIPER_MLPPP = 0x82 + DLT_JUNIPER_MONITOR = 0xa4 + DLT_JUNIPER_PIC_PEER = 0xae + DLT_JUNIPER_PPP = 0xb3 + DLT_JUNIPER_PPPOE = 0xa7 + DLT_JUNIPER_PPPOE_ATM = 0xa8 + DLT_JUNIPER_SERVICES = 0x88 + DLT_JUNIPER_SRX_E2E = 0xe9 + DLT_JUNIPER_ST = 0xc8 + DLT_JUNIPER_VP = 0xb7 + DLT_JUNIPER_VS = 0xe8 + DLT_LAPB_WITH_DIR = 0xcf + DLT_LAPD = 0xcb + DLT_LIN = 0xd4 + DLT_LINUX_EVDEV = 0xd8 + DLT_LINUX_IRDA = 0x90 + DLT_LINUX_LAPD = 0xb1 + DLT_LINUX_PPP_WITHDIRECTION = 0xa6 + DLT_LINUX_SLL = 0x71 + DLT_LOOP = 0x6c + DLT_LTALK = 0x72 + DLT_MATCHING_MAX = 0x10a + DLT_MATCHING_MIN = 0x68 + DLT_MFR = 0xb6 + DLT_MOST = 0xd3 + DLT_MPEG_2_TS = 0xf3 + DLT_MPLS = 0xdb + DLT_MTP2 = 0x8c + DLT_MTP2_WITH_PHDR = 0x8b + DLT_MTP3 = 0x8d + DLT_MUX27010 = 0xec + DLT_NETANALYZER = 0xf0 + DLT_NETANALYZER_TRANSPARENT = 0xf1 + DLT_NFC_LLCP = 0xf5 + DLT_NFLOG = 0xef + DLT_NG40 = 0xf4 + DLT_NULL = 0x0 + DLT_PCI_EXP = 0x7d + DLT_PFLOG = 0x75 + DLT_PFSYNC = 0x12 + DLT_PPI = 0xc0 + DLT_PPP = 0x9 + DLT_PPP_BSDOS = 0x10 + DLT_PPP_ETHER = 0x33 + DLT_PPP_PPPD = 0xa6 + DLT_PPP_SERIAL = 0x32 + DLT_PPP_WITH_DIR = 0xcc + DLT_PPP_WITH_DIRECTION = 0xa6 + DLT_PRISM_HEADER = 0x77 + DLT_PRONET = 0x4 + DLT_RAIF1 = 0xc6 + DLT_RAW = 0xc + DLT_RIO = 0x7c + DLT_SCCP = 0x8e + DLT_SITA = 0xc4 + DLT_SLIP = 0x8 + DLT_SLIP_BSDOS = 0xf + DLT_STANAG_5066_D_PDU = 0xed + DLT_SUNATM = 0x7b + DLT_SYMANTEC_FIREWALL = 0x63 + DLT_TZSP = 0x80 + DLT_USB = 0xba + DLT_USB_DARWIN = 0x10a + DLT_USB_LINUX = 0xbd + DLT_USB_LINUX_MMAPPED = 0xdc + DLT_USER0 = 0x93 + DLT_USER1 = 0x94 + DLT_USER10 = 0x9d + DLT_USER11 = 0x9e + DLT_USER12 = 0x9f + DLT_USER13 = 0xa0 + DLT_USER14 = 0xa1 + DLT_USER15 = 0xa2 + DLT_USER2 = 0x95 + DLT_USER3 = 0x96 + DLT_USER4 = 0x97 + DLT_USER5 = 0x98 + DLT_USER6 = 0x99 + DLT_USER7 = 0x9a + DLT_USER8 = 0x9b + DLT_USER9 = 0x9c + DLT_WIHART = 0xdf + DLT_X2E_SERIAL = 0xd5 + DLT_X2E_XORAYA = 0xd6 + DT_BLK = 0x6 + DT_CHR = 0x2 + DT_DIR = 0x4 + DT_FIFO = 0x1 + DT_LNK = 0xa + DT_REG = 0x8 + DT_SOCK = 0xc + DT_UNKNOWN = 0x0 + DT_WHT = 0xe + ECHO = 0x8 + ECHOCTL = 0x40 + ECHOE = 0x2 + ECHOK = 0x4 + ECHOKE = 0x1 + ECHONL = 0x10 + ECHOPRT = 0x20 + EVFILT_AIO = -0x3 + EVFILT_EXCEPT = -0xf + EVFILT_FS = -0x9 + EVFILT_MACHPORT = -0x8 + EVFILT_PROC = -0x5 + EVFILT_READ = -0x1 + EVFILT_SIGNAL = -0x6 + EVFILT_SYSCOUNT = 0x11 + EVFILT_THREADMARKER = 0x11 + EVFILT_TIMER = -0x7 + EVFILT_USER = -0xa + EVFILT_VM = -0xc + EVFILT_VNODE = -0x4 + EVFILT_WRITE = -0x2 + EV_ADD = 0x1 + EV_CLEAR = 0x20 + EV_DELETE = 0x2 + EV_DISABLE = 0x8 + EV_DISPATCH = 0x80 + EV_DISPATCH2 = 0x180 + EV_ENABLE = 0x4 + EV_EOF = 0x8000 + EV_ERROR = 0x4000 + EV_FLAG0 = 0x1000 + EV_FLAG1 = 0x2000 + EV_ONESHOT = 0x10 + EV_OOBAND = 0x2000 + EV_POLL = 0x1000 + EV_RECEIPT = 0x40 + EV_SYSFLAGS = 0xf000 + EV_UDATA_SPECIFIC = 0x100 + EV_VANISHED = 0x200 + EXTA = 0x4b00 + EXTB = 0x9600 + EXTPROC = 0x800 + FD_CLOEXEC = 0x1 + FD_SETSIZE = 0x400 + FF0 = 0x0 + FF1 = 0x4000 + FFDLY = 0x4000 + FLUSHO = 0x800000 + FSOPT_ATTR_CMN_EXTENDED = 0x20 + FSOPT_NOFOLLOW = 0x1 + FSOPT_NOINMEMUPDATE = 0x2 + FSOPT_PACK_INVAL_ATTRS = 0x8 + FSOPT_REPORT_FULLSIZE = 0x4 + FSOPT_RETURN_REALDEV = 0x200 + F_ADDFILESIGS = 0x3d + F_ADDFILESIGS_FOR_DYLD_SIM = 0x53 + F_ADDFILESIGS_INFO = 0x67 + F_ADDFILESIGS_RETURN = 0x61 + F_ADDFILESUPPL = 0x68 + F_ADDSIGS = 0x3b + F_ALLOCATEALL = 0x4 + F_ALLOCATECONTIG = 0x2 + F_BARRIERFSYNC = 0x55 + F_CHECK_LV = 0x62 + F_CHKCLEAN = 0x29 + F_DUPFD = 0x0 + F_DUPFD_CLOEXEC = 0x43 + F_FINDSIGS = 0x4e + F_FLUSH_DATA = 0x28 + F_FREEZE_FS = 0x35 + F_FULLFSYNC = 0x33 + F_GETCODEDIR = 0x48 + F_GETFD = 0x1 + F_GETFL = 0x3 + F_GETLK = 0x7 + F_GETLKPID = 0x42 + F_GETNOSIGPIPE = 0x4a + F_GETOWN = 0x5 + F_GETPATH = 0x32 + F_GETPATH_MTMINFO = 0x47 + F_GETPATH_NOFIRMLINK = 0x66 + F_GETPROTECTIONCLASS = 0x3f + F_GETPROTECTIONLEVEL = 0x4d + F_GETSIGSINFO = 0x69 + F_GLOBAL_NOCACHE = 0x37 + F_LOG2PHYS = 0x31 + F_LOG2PHYS_EXT = 0x41 + F_NOCACHE = 0x30 + F_NODIRECT = 0x3e + F_OK = 0x0 + F_PATHPKG_CHECK = 0x34 + F_PEOFPOSMODE = 0x3 + F_PREALLOCATE = 0x2a + F_PUNCHHOLE = 0x63 + F_RDADVISE = 0x2c + F_RDAHEAD = 0x2d + F_RDLCK = 0x1 + F_SETBACKINGSTORE = 0x46 + F_SETFD = 0x2 + F_SETFL = 0x4 + F_SETLK = 0x8 + F_SETLKW = 0x9 + F_SETLKWTIMEOUT = 0xa + F_SETNOSIGPIPE = 0x49 + F_SETOWN = 0x6 + F_SETPROTECTIONCLASS = 0x40 + F_SETSIZE = 0x2b + F_SINGLE_WRITER = 0x4c + F_SPECULATIVE_READ = 0x65 + F_THAW_FS = 0x36 + F_TRANSCODEKEY = 0x4b + F_TRIM_ACTIVE_FILE = 0x64 + F_UNLCK = 0x2 + F_VOLPOSMODE = 0x4 + F_WRLCK = 0x3 + HUPCL = 0x4000 + HW_MACHINE = 0x1 + ICANON = 0x100 + ICMP6_FILTER = 0x12 + ICRNL = 0x100 + IEXTEN = 0x400 + IFF_ALLMULTI = 0x200 + IFF_ALTPHYS = 0x4000 + IFF_BROADCAST = 0x2 + IFF_DEBUG = 0x4 + IFF_LINK0 = 0x1000 + IFF_LINK1 = 0x2000 + IFF_LINK2 = 0x4000 + IFF_LOOPBACK = 0x8 + IFF_MULTICAST = 0x8000 + IFF_NOARP = 0x80 + IFF_NOTRAILERS = 0x20 + IFF_OACTIVE = 0x400 + IFF_POINTOPOINT = 0x10 + IFF_PROMISC = 0x100 + IFF_RUNNING = 0x40 + IFF_SIMPLEX = 0x800 + IFF_UP = 0x1 + IFNAMSIZ = 0x10 + IFT_1822 = 0x2 + IFT_6LOWPAN = 0x40 + IFT_AAL5 = 0x31 + IFT_ARCNET = 0x23 + IFT_ARCNETPLUS = 0x24 + IFT_ATM = 0x25 + IFT_BRIDGE = 0xd1 + IFT_CARP = 0xf8 + IFT_CELLULAR = 0xff + IFT_CEPT = 0x13 + IFT_DS3 = 0x1e + IFT_ENC = 0xf4 + IFT_EON = 0x19 + IFT_ETHER = 0x6 + IFT_FAITH = 0x38 + IFT_FDDI = 0xf + IFT_FRELAY = 0x20 + IFT_FRELAYDCE = 0x2c + IFT_GIF = 0x37 + IFT_HDH1822 = 0x3 + IFT_HIPPI = 0x2f + IFT_HSSI = 0x2e + IFT_HY = 0xe + IFT_IEEE1394 = 0x90 + IFT_IEEE8023ADLAG = 0x88 + IFT_ISDNBASIC = 0x14 + IFT_ISDNPRIMARY = 0x15 + IFT_ISO88022LLC = 0x29 + IFT_ISO88023 = 0x7 + IFT_ISO88024 = 0x8 + IFT_ISO88025 = 0x9 + IFT_ISO88026 = 0xa + IFT_L2VLAN = 0x87 + IFT_LAPB = 0x10 + IFT_LOCALTALK = 0x2a + IFT_LOOP = 0x18 + IFT_MIOX25 = 0x26 + IFT_MODEM = 0x30 + IFT_NSIP = 0x1b + IFT_OTHER = 0x1 + IFT_P10 = 0xc + IFT_P80 = 0xd + IFT_PARA = 0x22 + IFT_PDP = 0xff + IFT_PFLOG = 0xf5 + IFT_PFSYNC = 0xf6 + IFT_PKTAP = 0xfe + IFT_PPP = 0x17 + IFT_PROPMUX = 0x36 + IFT_PROPVIRTUAL = 0x35 + IFT_PTPSERIAL = 0x16 + IFT_RS232 = 0x21 + IFT_SDLC = 0x11 + IFT_SIP = 0x1f + IFT_SLIP = 0x1c + IFT_SMDSDXI = 0x2b + IFT_SMDSICIP = 0x34 + IFT_SONET = 0x27 + IFT_SONETPATH = 0x32 + IFT_SONETVT = 0x33 + IFT_STARLAN = 0xb + IFT_STF = 0x39 + IFT_T1 = 0x12 + IFT_ULTRA = 0x1d + IFT_V35 = 0x2d + IFT_X25 = 0x5 + IFT_X25DDN = 0x4 + IFT_X25PLE = 0x28 + IFT_XETHER = 0x1a + IGNBRK = 0x1 + IGNCR = 0x80 + IGNPAR = 0x4 + IMAXBEL = 0x2000 + INLCR = 0x40 + INPCK = 0x10 + IN_CLASSA_HOST = 0xffffff + IN_CLASSA_MAX = 0x80 + IN_CLASSA_NET = 0xff000000 + IN_CLASSA_NSHIFT = 0x18 + IN_CLASSB_HOST = 0xffff + IN_CLASSB_MAX = 0x10000 + IN_CLASSB_NET = 0xffff0000 + IN_CLASSB_NSHIFT = 0x10 + IN_CLASSC_HOST = 0xff + IN_CLASSC_NET = 0xffffff00 + IN_CLASSC_NSHIFT = 0x8 + IN_CLASSD_HOST = 0xfffffff + IN_CLASSD_NET = 0xf0000000 + IN_CLASSD_NSHIFT = 0x1c + IN_LINKLOCALNETNUM = 0xa9fe0000 + IN_LOOPBACKNET = 0x7f + IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x400473d1 + IPPROTO_3PC = 0x22 + IPPROTO_ADFS = 0x44 + IPPROTO_AH = 0x33 + IPPROTO_AHIP = 0x3d + IPPROTO_APES = 0x63 + IPPROTO_ARGUS = 0xd + IPPROTO_AX25 = 0x5d + IPPROTO_BHA = 0x31 + IPPROTO_BLT = 0x1e + IPPROTO_BRSATMON = 0x4c + IPPROTO_CFTP = 0x3e + IPPROTO_CHAOS = 0x10 + IPPROTO_CMTP = 0x26 + IPPROTO_CPHB = 0x49 + IPPROTO_CPNX = 0x48 + IPPROTO_DDP = 0x25 + IPPROTO_DGP = 0x56 + IPPROTO_DIVERT = 0xfe + IPPROTO_DONE = 0x101 + IPPROTO_DSTOPTS = 0x3c + IPPROTO_EGP = 0x8 + IPPROTO_EMCON = 0xe + IPPROTO_ENCAP = 0x62 + IPPROTO_EON = 0x50 + IPPROTO_ESP = 0x32 + IPPROTO_ETHERIP = 0x61 + IPPROTO_FRAGMENT = 0x2c + IPPROTO_GGP = 0x3 + IPPROTO_GMTP = 0x64 + IPPROTO_GRE = 0x2f + IPPROTO_HELLO = 0x3f + IPPROTO_HMP = 0x14 + IPPROTO_HOPOPTS = 0x0 + IPPROTO_ICMP = 0x1 + IPPROTO_ICMPV6 = 0x3a + IPPROTO_IDP = 0x16 + IPPROTO_IDPR = 0x23 + IPPROTO_IDRP = 0x2d + IPPROTO_IGMP = 0x2 + IPPROTO_IGP = 0x55 + IPPROTO_IGRP = 0x58 + IPPROTO_IL = 0x28 + IPPROTO_INLSP = 0x34 + IPPROTO_INP = 0x20 + IPPROTO_IP = 0x0 + IPPROTO_IPCOMP = 0x6c + IPPROTO_IPCV = 0x47 + IPPROTO_IPEIP = 0x5e + IPPROTO_IPIP = 0x4 + IPPROTO_IPPC = 0x43 + IPPROTO_IPV4 = 0x4 + IPPROTO_IPV6 = 0x29 + IPPROTO_IRTP = 0x1c + IPPROTO_KRYPTOLAN = 0x41 + IPPROTO_LARP = 0x5b + IPPROTO_LEAF1 = 0x19 + IPPROTO_LEAF2 = 0x1a + IPPROTO_MAX = 0x100 + IPPROTO_MAXID = 0x34 + IPPROTO_MEAS = 0x13 + IPPROTO_MHRP = 0x30 + IPPROTO_MICP = 0x5f + IPPROTO_MTP = 0x5c + IPPROTO_MUX = 0x12 + IPPROTO_ND = 0x4d + IPPROTO_NHRP = 0x36 + IPPROTO_NONE = 0x3b + IPPROTO_NSP = 0x1f + IPPROTO_NVPII = 0xb + IPPROTO_OSPFIGP = 0x59 + IPPROTO_PGM = 0x71 + IPPROTO_PIGP = 0x9 + IPPROTO_PIM = 0x67 + IPPROTO_PRM = 0x15 + IPPROTO_PUP = 0xc + IPPROTO_PVP = 0x4b + IPPROTO_RAW = 0xff + IPPROTO_RCCMON = 0xa + IPPROTO_RDP = 0x1b + IPPROTO_ROUTING = 0x2b + IPPROTO_RSVP = 0x2e + IPPROTO_RVD = 0x42 + IPPROTO_SATEXPAK = 0x40 + IPPROTO_SATMON = 0x45 + IPPROTO_SCCSP = 0x60 + IPPROTO_SCTP = 0x84 + IPPROTO_SDRP = 0x2a + IPPROTO_SEP = 0x21 + IPPROTO_SRPC = 0x5a + IPPROTO_ST = 0x7 + IPPROTO_SVMTP = 0x52 + IPPROTO_SWIPE = 0x35 + IPPROTO_TCF = 0x57 + IPPROTO_TCP = 0x6 + IPPROTO_TP = 0x1d + IPPROTO_TPXX = 0x27 + IPPROTO_TRUNK1 = 0x17 + IPPROTO_TRUNK2 = 0x18 + IPPROTO_TTP = 0x54 + IPPROTO_UDP = 0x11 + IPPROTO_VINES = 0x53 + IPPROTO_VISA = 0x46 + IPPROTO_VMTP = 0x51 + IPPROTO_WBEXPAK = 0x4f + IPPROTO_WBMON = 0x4e + IPPROTO_WSN = 0x4a + IPPROTO_XNET = 0xf + IPPROTO_XTP = 0x24 + IPV6_2292DSTOPTS = 0x17 + IPV6_2292HOPLIMIT = 0x14 + IPV6_2292HOPOPTS = 0x16 + IPV6_2292NEXTHOP = 0x15 + IPV6_2292PKTINFO = 0x13 + IPV6_2292PKTOPTIONS = 0x19 + IPV6_2292RTHDR = 0x18 + IPV6_3542DSTOPTS = 0x32 + IPV6_3542HOPLIMIT = 0x2f + IPV6_3542HOPOPTS = 0x31 + IPV6_3542NEXTHOP = 0x30 + IPV6_3542PKTINFO = 0x2e + IPV6_3542RTHDR = 0x33 + IPV6_ADDR_MC_FLAGS_PREFIX = 0x20 + IPV6_ADDR_MC_FLAGS_TRANSIENT = 0x10 + IPV6_ADDR_MC_FLAGS_UNICAST_BASED = 0x30 + IPV6_AUTOFLOWLABEL = 0x3b + IPV6_BINDV6ONLY = 0x1b + IPV6_BOUND_IF = 0x7d + IPV6_CHECKSUM = 0x1a + IPV6_DEFAULT_MULTICAST_HOPS = 0x1 + IPV6_DEFAULT_MULTICAST_LOOP = 0x1 + IPV6_DEFHLIM = 0x40 + IPV6_DONTFRAG = 0x3e + IPV6_DSTOPTS = 0x32 + IPV6_FAITH = 0x1d + IPV6_FLOWINFO_MASK = 0xffffff0f + IPV6_FLOWLABEL_MASK = 0xffff0f00 + IPV6_FLOW_ECN_MASK = 0x3000 + IPV6_FRAGTTL = 0x3c + IPV6_FW_ADD = 0x1e + IPV6_FW_DEL = 0x1f + IPV6_FW_FLUSH = 0x20 + IPV6_FW_GET = 0x22 + IPV6_FW_ZERO = 0x21 + IPV6_HLIMDEC = 0x1 + IPV6_HOPLIMIT = 0x2f + IPV6_HOPOPTS = 0x31 + IPV6_IPSEC_POLICY = 0x1c + IPV6_JOIN_GROUP = 0xc + IPV6_LEAVE_GROUP = 0xd + IPV6_MAXHLIM = 0xff + IPV6_MAXOPTHDR = 0x800 + IPV6_MAXPACKET = 0xffff + IPV6_MAX_GROUP_SRC_FILTER = 0x200 + IPV6_MAX_MEMBERSHIPS = 0xfff + IPV6_MAX_SOCK_SRC_FILTER = 0x80 + IPV6_MIN_MEMBERSHIPS = 0x1f + IPV6_MMTU = 0x500 + IPV6_MSFILTER = 0x4a + IPV6_MULTICAST_HOPS = 0xa + IPV6_MULTICAST_IF = 0x9 + IPV6_MULTICAST_LOOP = 0xb + IPV6_NEXTHOP = 0x30 + IPV6_PATHMTU = 0x2c + IPV6_PKTINFO = 0x2e + IPV6_PORTRANGE = 0xe + IPV6_PORTRANGE_DEFAULT = 0x0 + IPV6_PORTRANGE_HIGH = 0x1 + IPV6_PORTRANGE_LOW = 0x2 + IPV6_PREFER_TEMPADDR = 0x3f + IPV6_RECVDSTOPTS = 0x28 + IPV6_RECVHOPLIMIT = 0x25 + IPV6_RECVHOPOPTS = 0x27 + IPV6_RECVPATHMTU = 0x2b + IPV6_RECVPKTINFO = 0x3d + IPV6_RECVRTHDR = 0x26 + IPV6_RECVTCLASS = 0x23 + IPV6_RTHDR = 0x33 + IPV6_RTHDRDSTOPTS = 0x39 + IPV6_RTHDR_LOOSE = 0x0 + IPV6_RTHDR_STRICT = 0x1 + IPV6_RTHDR_TYPE_0 = 0x0 + IPV6_SOCKOPT_RESERVED1 = 0x3 + IPV6_TCLASS = 0x24 + IPV6_UNICAST_HOPS = 0x4 + IPV6_USE_MIN_MTU = 0x2a + IPV6_V6ONLY = 0x1b + IPV6_VERSION = 0x60 + IPV6_VERSION_MASK = 0xf0 + IP_ADD_MEMBERSHIP = 0xc + IP_ADD_SOURCE_MEMBERSHIP = 0x46 + IP_BLOCK_SOURCE = 0x48 + IP_BOUND_IF = 0x19 + IP_DEFAULT_MULTICAST_LOOP = 0x1 + IP_DEFAULT_MULTICAST_TTL = 0x1 + IP_DF = 0x4000 + IP_DONTFRAG = 0x1c + IP_DROP_MEMBERSHIP = 0xd + IP_DROP_SOURCE_MEMBERSHIP = 0x47 + IP_DUMMYNET_CONFIGURE = 0x3c + IP_DUMMYNET_DEL = 0x3d + IP_DUMMYNET_FLUSH = 0x3e + IP_DUMMYNET_GET = 0x40 + IP_FAITH = 0x16 + IP_FW_ADD = 0x28 + IP_FW_DEL = 0x29 + IP_FW_FLUSH = 0x2a + IP_FW_GET = 0x2c + IP_FW_RESETLOG = 0x2d + IP_FW_ZERO = 0x2b + IP_HDRINCL = 0x2 + IP_IPSEC_POLICY = 0x15 + IP_MAXPACKET = 0xffff + IP_MAX_GROUP_SRC_FILTER = 0x200 + IP_MAX_MEMBERSHIPS = 0xfff + IP_MAX_SOCK_MUTE_FILTER = 0x80 + IP_MAX_SOCK_SRC_FILTER = 0x80 + IP_MF = 0x2000 + IP_MIN_MEMBERSHIPS = 0x1f + IP_MSFILTER = 0x4a + IP_MSS = 0x240 + IP_MULTICAST_IF = 0x9 + IP_MULTICAST_IFINDEX = 0x42 + IP_MULTICAST_LOOP = 0xb + IP_MULTICAST_TTL = 0xa + IP_MULTICAST_VIF = 0xe + IP_NAT__XXX = 0x37 + IP_OFFMASK = 0x1fff + IP_OLD_FW_ADD = 0x32 + IP_OLD_FW_DEL = 0x33 + IP_OLD_FW_FLUSH = 0x34 + IP_OLD_FW_GET = 0x36 + IP_OLD_FW_RESETLOG = 0x38 + IP_OLD_FW_ZERO = 0x35 + IP_OPTIONS = 0x1 + IP_PKTINFO = 0x1a + IP_PORTRANGE = 0x13 + IP_PORTRANGE_DEFAULT = 0x0 + IP_PORTRANGE_HIGH = 0x1 + IP_PORTRANGE_LOW = 0x2 + IP_RECVDSTADDR = 0x7 + IP_RECVIF = 0x14 + IP_RECVOPTS = 0x5 + IP_RECVPKTINFO = 0x1a + IP_RECVRETOPTS = 0x6 + IP_RECVTOS = 0x1b + IP_RECVTTL = 0x18 + IP_RETOPTS = 0x8 + IP_RF = 0x8000 + IP_RSVP_OFF = 0x10 + IP_RSVP_ON = 0xf + IP_RSVP_VIF_OFF = 0x12 + IP_RSVP_VIF_ON = 0x11 + IP_STRIPHDR = 0x17 + IP_TOS = 0x3 + IP_TRAFFIC_MGT_BACKGROUND = 0x41 + IP_TTL = 0x4 + IP_UNBLOCK_SOURCE = 0x49 + ISIG = 0x80 + ISTRIP = 0x20 + IUTF8 = 0x4000 + IXANY = 0x800 + IXOFF = 0x400 + IXON = 0x200 + KERN_HOSTNAME = 0xa + KERN_OSRELEASE = 0x2 + KERN_OSTYPE = 0x1 + KERN_VERSION = 0x4 + LOCAL_PEERCRED = 0x1 + LOCAL_PEEREPID = 0x3 + LOCAL_PEEREUUID = 0x5 + LOCAL_PEERPID = 0x2 + LOCAL_PEERTOKEN = 0x6 + LOCAL_PEERUUID = 0x4 + LOCK_EX = 0x2 + LOCK_NB = 0x4 + LOCK_SH = 0x1 + LOCK_UN = 0x8 + MADV_CAN_REUSE = 0x9 + MADV_DONTNEED = 0x4 + MADV_FREE = 0x5 + MADV_FREE_REUSABLE = 0x7 + MADV_FREE_REUSE = 0x8 + MADV_NORMAL = 0x0 + MADV_PAGEOUT = 0xa + MADV_RANDOM = 0x1 + MADV_SEQUENTIAL = 0x2 + MADV_WILLNEED = 0x3 + MADV_ZERO_WIRED_PAGES = 0x6 + MAP_32BIT = 0x8000 + MAP_ANON = 0x1000 + MAP_ANONYMOUS = 0x1000 + MAP_COPY = 0x2 + MAP_FILE = 0x0 + MAP_FIXED = 0x10 + MAP_HASSEMAPHORE = 0x200 + MAP_JIT = 0x800 + MAP_NOCACHE = 0x400 + MAP_NOEXTEND = 0x100 + MAP_NORESERVE = 0x40 + MAP_PRIVATE = 0x2 + MAP_RENAME = 0x20 + MAP_RESERVED0080 = 0x80 + MAP_RESILIENT_CODESIGN = 0x2000 + MAP_RESILIENT_MEDIA = 0x4000 + MAP_SHARED = 0x1 + MAP_TRANSLATED_ALLOW_EXECUTE = 0x20000 + MAP_UNIX03 = 0x40000 + MCAST_BLOCK_SOURCE = 0x54 + MCAST_EXCLUDE = 0x2 + MCAST_INCLUDE = 0x1 + MCAST_JOIN_GROUP = 0x50 + MCAST_JOIN_SOURCE_GROUP = 0x52 + MCAST_LEAVE_GROUP = 0x51 + MCAST_LEAVE_SOURCE_GROUP = 0x53 + MCAST_UNBLOCK_SOURCE = 0x55 + MCAST_UNDEFINED = 0x0 + MCL_CURRENT = 0x1 + MCL_FUTURE = 0x2 + MNT_ASYNC = 0x40 + MNT_AUTOMOUNTED = 0x400000 + MNT_CMDFLAGS = 0xf0000 + MNT_CPROTECT = 0x80 + MNT_DEFWRITE = 0x2000000 + MNT_DONTBROWSE = 0x100000 + MNT_DOVOLFS = 0x8000 + MNT_DWAIT = 0x4 + MNT_EXPORTED = 0x100 + MNT_EXT_ROOT_DATA_VOL = 0x1 + MNT_FORCE = 0x80000 + MNT_IGNORE_OWNERSHIP = 0x200000 + MNT_JOURNALED = 0x800000 + MNT_LOCAL = 0x1000 + MNT_MULTILABEL = 0x4000000 + MNT_NOATIME = 0x10000000 + MNT_NOBLOCK = 0x20000 + MNT_NODEV = 0x10 + MNT_NOEXEC = 0x4 + MNT_NOSUID = 0x8 + MNT_NOUSERXATTR = 0x1000000 + MNT_NOWAIT = 0x2 + MNT_QUARANTINE = 0x400 + MNT_QUOTA = 0x2000 + MNT_RDONLY = 0x1 + MNT_RELOAD = 0x40000 + MNT_REMOVABLE = 0x200 + MNT_ROOTFS = 0x4000 + MNT_SNAPSHOT = 0x40000000 + MNT_STRICTATIME = 0x80000000 + MNT_SYNCHRONOUS = 0x2 + MNT_UNION = 0x20 + MNT_UNKNOWNPERMISSIONS = 0x200000 + MNT_UPDATE = 0x10000 + MNT_VISFLAGMASK = 0xd7f0f7ff + MNT_WAIT = 0x1 + MSG_CTRUNC = 0x20 + MSG_DONTROUTE = 0x4 + MSG_DONTWAIT = 0x80 + MSG_EOF = 0x100 + MSG_EOR = 0x8 + MSG_FLUSH = 0x400 + MSG_HAVEMORE = 0x2000 + MSG_HOLD = 0x800 + MSG_NEEDSA = 0x10000 + MSG_NOSIGNAL = 0x80000 + MSG_OOB = 0x1 + MSG_PEEK = 0x2 + MSG_RCVMORE = 0x4000 + MSG_SEND = 0x1000 + MSG_TRUNC = 0x10 + MSG_WAITALL = 0x40 + MSG_WAITSTREAM = 0x200 + MS_ASYNC = 0x1 + MS_DEACTIVATE = 0x8 + MS_INVALIDATE = 0x2 + MS_KILLPAGES = 0x4 + MS_SYNC = 0x10 + NAME_MAX = 0xff + NET_RT_DUMP = 0x1 + NET_RT_DUMP2 = 0x7 + NET_RT_FLAGS = 0x2 + NET_RT_FLAGS_PRIV = 0xa + NET_RT_IFLIST = 0x3 + NET_RT_IFLIST2 = 0x6 + NET_RT_MAXID = 0xb + NET_RT_STAT = 0x4 + NET_RT_TRASH = 0x5 + NFDBITS = 0x20 + NL0 = 0x0 + NL1 = 0x100 + NL2 = 0x200 + NL3 = 0x300 + NLDLY = 0x300 + NOFLSH = 0x80000000 + NOKERNINFO = 0x2000000 + NOTE_ABSOLUTE = 0x8 + NOTE_ATTRIB = 0x8 + NOTE_BACKGROUND = 0x40 + NOTE_CHILD = 0x4 + NOTE_CRITICAL = 0x20 + NOTE_DELETE = 0x1 + NOTE_EXEC = 0x20000000 + NOTE_EXIT = 0x80000000 + NOTE_EXITSTATUS = 0x4000000 + NOTE_EXIT_CSERROR = 0x40000 + NOTE_EXIT_DECRYPTFAIL = 0x10000 + NOTE_EXIT_DETAIL = 0x2000000 + NOTE_EXIT_DETAIL_MASK = 0x70000 + NOTE_EXIT_MEMORY = 0x20000 + NOTE_EXIT_REPARENTED = 0x80000 + NOTE_EXTEND = 0x4 + NOTE_FFAND = 0x40000000 + NOTE_FFCOPY = 0xc0000000 + NOTE_FFCTRLMASK = 0xc0000000 + NOTE_FFLAGSMASK = 0xffffff + NOTE_FFNOP = 0x0 + NOTE_FFOR = 0x80000000 + NOTE_FORK = 0x40000000 + NOTE_FUNLOCK = 0x100 + NOTE_LEEWAY = 0x10 + NOTE_LINK = 0x10 + NOTE_LOWAT = 0x1 + NOTE_MACHTIME = 0x100 + NOTE_MACH_CONTINUOUS_TIME = 0x80 + NOTE_NONE = 0x80 + NOTE_NSECONDS = 0x4 + NOTE_OOB = 0x2 + NOTE_PCTRLMASK = -0x100000 + NOTE_PDATAMASK = 0xfffff + NOTE_REAP = 0x10000000 + NOTE_RENAME = 0x20 + NOTE_REVOKE = 0x40 + NOTE_SECONDS = 0x1 + NOTE_SIGNAL = 0x8000000 + NOTE_TRACK = 0x1 + NOTE_TRACKERR = 0x2 + NOTE_TRIGGER = 0x1000000 + NOTE_USECONDS = 0x2 + NOTE_VM_ERROR = 0x10000000 + NOTE_VM_PRESSURE = 0x80000000 + NOTE_VM_PRESSURE_SUDDEN_TERMINATE = 0x20000000 + NOTE_VM_PRESSURE_TERMINATE = 0x40000000 + NOTE_WRITE = 0x2 + OCRNL = 0x10 + OFDEL = 0x20000 + OFILL = 0x80 + ONLCR = 0x2 + ONLRET = 0x40 + ONOCR = 0x20 + ONOEOT = 0x8 + OPOST = 0x1 + OXTABS = 0x4 + O_ACCMODE = 0x3 + O_ALERT = 0x20000000 + O_APPEND = 0x8 + O_ASYNC = 0x40 + O_CLOEXEC = 0x1000000 + O_CREAT = 0x200 + O_DIRECTORY = 0x100000 + O_DP_GETRAWENCRYPTED = 0x1 + O_DP_GETRAWUNENCRYPTED = 0x2 + O_DSYNC = 0x400000 + O_EVTONLY = 0x8000 + O_EXCL = 0x800 + O_EXLOCK = 0x20 + O_FSYNC = 0x80 + O_NDELAY = 0x4 + O_NOCTTY = 0x20000 + O_NOFOLLOW = 0x100 + O_NOFOLLOW_ANY = 0x20000000 + O_NONBLOCK = 0x4 + O_POPUP = 0x80000000 + O_RDONLY = 0x0 + O_RDWR = 0x2 + O_SHLOCK = 0x10 + O_SYMLINK = 0x200000 + O_SYNC = 0x80 + O_TRUNC = 0x400 + O_WRONLY = 0x1 + PARENB = 0x1000 + PARMRK = 0x8 + PARODD = 0x2000 + PENDIN = 0x20000000 + PRIO_PGRP = 0x1 + PRIO_PROCESS = 0x0 + PRIO_USER = 0x2 + PROT_EXEC = 0x4 + PROT_NONE = 0x0 + PROT_READ = 0x1 + PROT_WRITE = 0x2 + PT_ATTACH = 0xa + PT_ATTACHEXC = 0xe + PT_CONTINUE = 0x7 + PT_DENY_ATTACH = 0x1f + PT_DETACH = 0xb + PT_FIRSTMACH = 0x20 + PT_FORCEQUOTA = 0x1e + PT_KILL = 0x8 + PT_READ_D = 0x2 + PT_READ_I = 0x1 + PT_READ_U = 0x3 + PT_SIGEXC = 0xc + PT_STEP = 0x9 + PT_THUPDATE = 0xd + PT_TRACE_ME = 0x0 + PT_WRITE_D = 0x5 + PT_WRITE_I = 0x4 + PT_WRITE_U = 0x6 + RLIMIT_AS = 0x5 + RLIMIT_CORE = 0x4 + RLIMIT_CPU = 0x0 + RLIMIT_CPU_USAGE_MONITOR = 0x2 + RLIMIT_DATA = 0x2 + RLIMIT_FSIZE = 0x1 + RLIMIT_MEMLOCK = 0x6 + RLIMIT_NOFILE = 0x8 + RLIMIT_NPROC = 0x7 + RLIMIT_RSS = 0x5 + RLIMIT_STACK = 0x3 + RLIM_INFINITY = 0x7fffffffffffffff + RTAX_AUTHOR = 0x6 + RTAX_BRD = 0x7 + RTAX_DST = 0x0 + RTAX_GATEWAY = 0x1 + RTAX_GENMASK = 0x3 + RTAX_IFA = 0x5 + RTAX_IFP = 0x4 + RTAX_MAX = 0x8 + RTAX_NETMASK = 0x2 + RTA_AUTHOR = 0x40 + RTA_BRD = 0x80 + RTA_DST = 0x1 + RTA_GATEWAY = 0x2 + RTA_GENMASK = 0x8 + RTA_IFA = 0x20 + RTA_IFP = 0x10 + RTA_NETMASK = 0x4 + RTF_BLACKHOLE = 0x1000 + RTF_BROADCAST = 0x400000 + RTF_CLONING = 0x100 + RTF_CONDEMNED = 0x2000000 + RTF_DEAD = 0x20000000 + RTF_DELCLONE = 0x80 + RTF_DONE = 0x40 + RTF_DYNAMIC = 0x10 + RTF_GATEWAY = 0x2 + RTF_GLOBAL = 0x40000000 + RTF_HOST = 0x4 + RTF_IFREF = 0x4000000 + RTF_IFSCOPE = 0x1000000 + RTF_LLDATA = 0x400 + RTF_LLINFO = 0x400 + RTF_LOCAL = 0x200000 + RTF_MODIFIED = 0x20 + RTF_MULTICAST = 0x800000 + RTF_NOIFREF = 0x2000 + RTF_PINNED = 0x100000 + RTF_PRCLONING = 0x10000 + RTF_PROTO1 = 0x8000 + RTF_PROTO2 = 0x4000 + RTF_PROTO3 = 0x40000 + RTF_PROXY = 0x8000000 + RTF_REJECT = 0x8 + RTF_ROUTER = 0x10000000 + RTF_STATIC = 0x800 + RTF_UP = 0x1 + RTF_WASCLONED = 0x20000 + RTF_XRESOLVE = 0x200 + RTM_ADD = 0x1 + RTM_CHANGE = 0x3 + RTM_DELADDR = 0xd + RTM_DELETE = 0x2 + RTM_DELMADDR = 0x10 + RTM_GET = 0x4 + RTM_GET2 = 0x14 + RTM_IFINFO = 0xe + RTM_IFINFO2 = 0x12 + RTM_LOCK = 0x8 + RTM_LOSING = 0x5 + RTM_MISS = 0x7 + RTM_NEWADDR = 0xc + RTM_NEWMADDR = 0xf + RTM_NEWMADDR2 = 0x13 + RTM_OLDADD = 0x9 + RTM_OLDDEL = 0xa + RTM_REDIRECT = 0x6 + RTM_RESOLVE = 0xb + RTM_RTTUNIT = 0xf4240 + RTM_VERSION = 0x5 + RTV_EXPIRE = 0x4 + RTV_HOPCOUNT = 0x2 + RTV_MTU = 0x1 + RTV_RPIPE = 0x8 + RTV_RTT = 0x40 + RTV_RTTVAR = 0x80 + RTV_SPIPE = 0x10 + RTV_SSTHRESH = 0x20 + RUSAGE_CHILDREN = -0x1 + RUSAGE_SELF = 0x0 + SCM_CREDS = 0x3 + SCM_RIGHTS = 0x1 + SCM_TIMESTAMP = 0x2 + SCM_TIMESTAMP_MONOTONIC = 0x4 + SEEK_CUR = 0x1 + SEEK_DATA = 0x4 + SEEK_END = 0x2 + SEEK_HOLE = 0x3 + SEEK_SET = 0x0 + SHUT_RD = 0x0 + SHUT_RDWR = 0x2 + SHUT_WR = 0x1 + SIOCADDMULTI = 0x80206931 + SIOCAIFADDR = 0x8040691a + SIOCARPIPLL = 0xc0206928 + SIOCATMARK = 0x40047307 + SIOCAUTOADDR = 0xc0206926 + SIOCAUTONETMASK = 0x80206927 + SIOCDELMULTI = 0x80206932 + SIOCDIFADDR = 0x80206919 + SIOCDIFPHYADDR = 0x80206941 + SIOCGDRVSPEC = 0xc028697b + SIOCGETVLAN = 0xc020697f + SIOCGHIWAT = 0x40047301 + SIOCGIF6LOWPAN = 0xc02069c5 + SIOCGIFADDR = 0xc0206921 + SIOCGIFALTMTU = 0xc0206948 + SIOCGIFASYNCMAP = 0xc020697c + SIOCGIFBOND = 0xc0206947 + SIOCGIFBRDADDR = 0xc0206923 + SIOCGIFCAP = 0xc020695b + SIOCGIFCONF = 0xc00c6924 + SIOCGIFDEVMTU = 0xc0206944 + SIOCGIFDSTADDR = 0xc0206922 + SIOCGIFFLAGS = 0xc0206911 + SIOCGIFFUNCTIONALTYPE = 0xc02069ad + SIOCGIFGENERIC = 0xc020693a + SIOCGIFKPI = 0xc0206987 + SIOCGIFMAC = 0xc0206982 + SIOCGIFMEDIA = 0xc02c6938 + SIOCGIFMETRIC = 0xc0206917 + SIOCGIFMTU = 0xc0206933 + SIOCGIFNETMASK = 0xc0206925 + SIOCGIFPDSTADDR = 0xc0206940 + SIOCGIFPHYS = 0xc0206935 + SIOCGIFPSRCADDR = 0xc020693f + SIOCGIFSTATUS = 0xc331693d + SIOCGIFVLAN = 0xc020697f + SIOCGIFWAKEFLAGS = 0xc0206988 + SIOCGIFXMEDIA = 0xc02c6948 + SIOCGLOWAT = 0x40047303 + SIOCGPGRP = 0x40047309 + SIOCIFCREATE = 0xc0206978 + SIOCIFCREATE2 = 0xc020697a + SIOCIFDESTROY = 0x80206979 + SIOCIFGCLONERS = 0xc0106981 + SIOCRSLVMULTI = 0xc010693b + SIOCSDRVSPEC = 0x8028697b + SIOCSETVLAN = 0x8020697e + SIOCSHIWAT = 0x80047300 + SIOCSIF6LOWPAN = 0x802069c4 + SIOCSIFADDR = 0x8020690c + SIOCSIFALTMTU = 0x80206945 + SIOCSIFASYNCMAP = 0x8020697d + SIOCSIFBOND = 0x80206946 + SIOCSIFBRDADDR = 0x80206913 + SIOCSIFCAP = 0x8020695a + SIOCSIFDSTADDR = 0x8020690e + SIOCSIFFLAGS = 0x80206910 + SIOCSIFGENERIC = 0x80206939 + SIOCSIFKPI = 0x80206986 + SIOCSIFLLADDR = 0x8020693c + SIOCSIFMAC = 0x80206983 + SIOCSIFMEDIA = 0xc0206937 + SIOCSIFMETRIC = 0x80206918 + SIOCSIFMTU = 0x80206934 + SIOCSIFNETMASK = 0x80206916 + SIOCSIFPHYADDR = 0x8040693e + SIOCSIFPHYS = 0x80206936 + SIOCSIFVLAN = 0x8020697e + SIOCSLOWAT = 0x80047302 + SIOCSPGRP = 0x80047308 + SOCK_DGRAM = 0x2 + SOCK_MAXADDRLEN = 0xff + SOCK_RAW = 0x3 + SOCK_RDM = 0x4 + SOCK_SEQPACKET = 0x5 + SOCK_STREAM = 0x1 + SOL_LOCAL = 0x0 + SOL_SOCKET = 0xffff + SOMAXCONN = 0x80 + SO_ACCEPTCONN = 0x2 + SO_BROADCAST = 0x20 + SO_DEBUG = 0x1 + SO_DONTROUTE = 0x10 + SO_DONTTRUNC = 0x2000 + SO_ERROR = 0x1007 + SO_KEEPALIVE = 0x8 + SO_LABEL = 0x1010 + SO_LINGER = 0x80 + SO_LINGER_SEC = 0x1080 + SO_NETSVC_MARKING_LEVEL = 0x1119 + SO_NET_SERVICE_TYPE = 0x1116 + SO_NKE = 0x1021 + SO_NOADDRERR = 0x1023 + SO_NOSIGPIPE = 0x1022 + SO_NOTIFYCONFLICT = 0x1026 + SO_NP_EXTENSIONS = 0x1083 + SO_NREAD = 0x1020 + SO_NUMRCVPKT = 0x1112 + SO_NWRITE = 0x1024 + SO_OOBINLINE = 0x100 + SO_PEERLABEL = 0x1011 + SO_RANDOMPORT = 0x1082 + SO_RCVBUF = 0x1002 + SO_RCVLOWAT = 0x1004 + SO_RCVTIMEO = 0x1006 + SO_REUSEADDR = 0x4 + SO_REUSEPORT = 0x200 + SO_REUSESHAREUID = 0x1025 + SO_SNDBUF = 0x1001 + SO_SNDLOWAT = 0x1003 + SO_SNDTIMEO = 0x1005 + SO_TIMESTAMP = 0x400 + SO_TIMESTAMP_MONOTONIC = 0x800 + SO_TRACKER_ATTRIBUTE_FLAGS_APP_APPROVED = 0x1 + SO_TRACKER_ATTRIBUTE_FLAGS_DOMAIN_SHORT = 0x4 + SO_TRACKER_ATTRIBUTE_FLAGS_TRACKER = 0x2 + SO_TRACKER_TRANSPARENCY_VERSION = 0x3 + SO_TYPE = 0x1008 + SO_UPCALLCLOSEWAIT = 0x1027 + SO_USELOOPBACK = 0x40 + SO_WANTMORE = 0x4000 + SO_WANTOOBFLAG = 0x8000 + S_IEXEC = 0x40 + S_IFBLK = 0x6000 + S_IFCHR = 0x2000 + S_IFDIR = 0x4000 + S_IFIFO = 0x1000 + S_IFLNK = 0xa000 + S_IFMT = 0xf000 + S_IFREG = 0x8000 + S_IFSOCK = 0xc000 + S_IFWHT = 0xe000 + S_IREAD = 0x100 + S_IRGRP = 0x20 + S_IROTH = 0x4 + S_IRUSR = 0x100 + S_IRWXG = 0x38 + S_IRWXO = 0x7 + S_IRWXU = 0x1c0 + S_ISGID = 0x400 + S_ISTXT = 0x200 + S_ISUID = 0x800 + S_ISVTX = 0x200 + S_IWGRP = 0x10 + S_IWOTH = 0x2 + S_IWRITE = 0x80 + S_IWUSR = 0x80 + S_IXGRP = 0x8 + S_IXOTH = 0x1 + S_IXUSR = 0x40 + TAB0 = 0x0 + TAB1 = 0x400 + TAB2 = 0x800 + TAB3 = 0x4 + TABDLY = 0xc04 + TCIFLUSH = 0x1 + TCIOFF = 0x3 + TCIOFLUSH = 0x3 + TCION = 0x4 + TCOFLUSH = 0x2 + TCOOFF = 0x1 + TCOON = 0x2 + TCPOPT_CC = 0xb + TCPOPT_CCECHO = 0xd + TCPOPT_CCNEW = 0xc + TCPOPT_EOL = 0x0 + TCPOPT_FASTOPEN = 0x22 + TCPOPT_MAXSEG = 0x2 + TCPOPT_NOP = 0x1 + TCPOPT_SACK = 0x5 + TCPOPT_SACK_HDR = 0x1010500 + TCPOPT_SACK_PERMITTED = 0x4 + TCPOPT_SACK_PERMIT_HDR = 0x1010402 + TCPOPT_SIGNATURE = 0x13 + TCPOPT_TIMESTAMP = 0x8 + TCPOPT_TSTAMP_HDR = 0x101080a + TCPOPT_WINDOW = 0x3 + TCP_CONNECTIONTIMEOUT = 0x20 + TCP_CONNECTION_INFO = 0x106 + TCP_ENABLE_ECN = 0x104 + TCP_FASTOPEN = 0x105 + TCP_KEEPALIVE = 0x10 + TCP_KEEPCNT = 0x102 + TCP_KEEPINTVL = 0x101 + TCP_MAXHLEN = 0x3c + TCP_MAXOLEN = 0x28 + TCP_MAXSEG = 0x2 + TCP_MAXWIN = 0xffff + TCP_MAX_SACK = 0x4 + TCP_MAX_WINSHIFT = 0xe + TCP_MINMSS = 0xd8 + TCP_MSS = 0x200 + TCP_NODELAY = 0x1 + TCP_NOOPT = 0x8 + TCP_NOPUSH = 0x4 + TCP_NOTSENT_LOWAT = 0x201 + TCP_RXT_CONNDROPTIME = 0x80 + TCP_RXT_FINDROP = 0x100 + TCP_SENDMOREACKS = 0x103 + TCSAFLUSH = 0x2 + TIOCCBRK = 0x2000747a + TIOCCDTR = 0x20007478 + TIOCCONS = 0x80047462 + TIOCDCDTIMESTAMP = 0x40107458 + TIOCDRAIN = 0x2000745e + TIOCDSIMICROCODE = 0x20007455 + TIOCEXCL = 0x2000740d + TIOCEXT = 0x80047460 + TIOCFLUSH = 0x80047410 + TIOCGDRAINWAIT = 0x40047456 + TIOCGETA = 0x40487413 + TIOCGETD = 0x4004741a + TIOCGPGRP = 0x40047477 + TIOCGWINSZ = 0x40087468 + TIOCIXOFF = 0x20007480 + TIOCIXON = 0x20007481 + TIOCMBIC = 0x8004746b + TIOCMBIS = 0x8004746c + TIOCMGDTRWAIT = 0x4004745a + TIOCMGET = 0x4004746a + TIOCMODG = 0x40047403 + TIOCMODS = 0x80047404 + TIOCMSDTRWAIT = 0x8004745b + TIOCMSET = 0x8004746d + TIOCM_CAR = 0x40 + TIOCM_CD = 0x40 + TIOCM_CTS = 0x20 + TIOCM_DSR = 0x100 + TIOCM_DTR = 0x2 + TIOCM_LE = 0x1 + TIOCM_RI = 0x80 + TIOCM_RNG = 0x80 + TIOCM_RTS = 0x4 + TIOCM_SR = 0x10 + TIOCM_ST = 0x8 + TIOCNOTTY = 0x20007471 + TIOCNXCL = 0x2000740e + TIOCOUTQ = 0x40047473 + TIOCPKT = 0x80047470 + TIOCPKT_DATA = 0x0 + TIOCPKT_DOSTOP = 0x20 + TIOCPKT_FLUSHREAD = 0x1 + TIOCPKT_FLUSHWRITE = 0x2 + TIOCPKT_IOCTL = 0x40 + TIOCPKT_NOSTOP = 0x10 + TIOCPKT_START = 0x8 + TIOCPKT_STOP = 0x4 + TIOCPTYGNAME = 0x40807453 + TIOCPTYGRANT = 0x20007454 + TIOCPTYUNLK = 0x20007452 + TIOCREMOTE = 0x80047469 + TIOCSBRK = 0x2000747b + TIOCSCONS = 0x20007463 + TIOCSCTTY = 0x20007461 + TIOCSDRAINWAIT = 0x80047457 + TIOCSDTR = 0x20007479 + TIOCSETA = 0x80487414 + TIOCSETAF = 0x80487416 + TIOCSETAW = 0x80487415 + TIOCSETD = 0x8004741b + TIOCSIG = 0x2000745f + TIOCSPGRP = 0x80047476 + TIOCSTART = 0x2000746e + TIOCSTAT = 0x20007465 + TIOCSTI = 0x80017472 + TIOCSTOP = 0x2000746f + TIOCSWINSZ = 0x80087467 + TIOCTIMESTAMP = 0x40107459 + TIOCUCNTL = 0x80047466 + TOSTOP = 0x400000 + VDISCARD = 0xf + VDSUSP = 0xb + VEOF = 0x0 + VEOL = 0x1 + VEOL2 = 0x2 + VERASE = 0x3 + VINTR = 0x8 + VKILL = 0x5 + VLNEXT = 0xe + VMADDR_CID_ANY = 0xffffffff + VMADDR_CID_HOST = 0x2 + VMADDR_CID_HYPERVISOR = 0x0 + VMADDR_CID_RESERVED = 0x1 + VMADDR_PORT_ANY = 0xffffffff + VMIN = 0x10 + VM_LOADAVG = 0x2 + VM_MACHFACTOR = 0x4 + VM_MAXID = 0x6 + VM_METER = 0x1 + VM_SWAPUSAGE = 0x5 + VQUIT = 0x9 + VREPRINT = 0x6 + VSTART = 0xc + VSTATUS = 0x12 + VSTOP = 0xd + VSUSP = 0xa + VT0 = 0x0 + VT1 = 0x10000 + VTDLY = 0x10000 + VTIME = 0x11 + VWERASE = 0x4 + WCONTINUED = 0x10 + WCOREFLAG = 0x80 + WEXITED = 0x4 + WNOHANG = 0x1 + WNOWAIT = 0x20 + WORDSIZE = 0x40 + WSTOPPED = 0x8 + WUNTRACED = 0x2 + XATTR_CREATE = 0x2 + XATTR_NODEFAULT = 0x10 + XATTR_NOFOLLOW = 0x1 + XATTR_NOSECURITY = 0x8 + XATTR_REPLACE = 0x4 + XATTR_SHOWCOMPRESSION = 0x20 ) // Errors diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go index 31009d7f05..e36f5178d6 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go @@ -12,1556 +12,1582 @@ package unix import "syscall" const ( - AF_APPLETALK = 0x10 - AF_CCITT = 0xa - AF_CHAOS = 0x5 - AF_CNT = 0x15 - AF_COIP = 0x14 - AF_DATAKIT = 0x9 - AF_DECnet = 0xc - AF_DLI = 0xd - AF_E164 = 0x1c - AF_ECMA = 0x8 - AF_HYLINK = 0xf - AF_IEEE80211 = 0x25 - AF_IMPLINK = 0x3 - AF_INET = 0x2 - AF_INET6 = 0x1e - AF_IPX = 0x17 - AF_ISDN = 0x1c - AF_ISO = 0x7 - AF_LAT = 0xe - AF_LINK = 0x12 - AF_LOCAL = 0x1 - AF_MAX = 0x29 - AF_NATM = 0x1f - AF_NDRV = 0x1b - AF_NETBIOS = 0x21 - AF_NS = 0x6 - AF_OSI = 0x7 - AF_PPP = 0x22 - AF_PUP = 0x4 - AF_RESERVED_36 = 0x24 - AF_ROUTE = 0x11 - AF_SIP = 0x18 - AF_SNA = 0xb - AF_SYSTEM = 0x20 - AF_SYS_CONTROL = 0x2 - AF_UNIX = 0x1 - AF_UNSPEC = 0x0 - AF_UTUN = 0x26 - AF_VSOCK = 0x28 - ALTWERASE = 0x200 - ATTR_BIT_MAP_COUNT = 0x5 - ATTR_CMN_ACCESSMASK = 0x20000 - ATTR_CMN_ACCTIME = 0x1000 - ATTR_CMN_ADDEDTIME = 0x10000000 - ATTR_CMN_BKUPTIME = 0x2000 - ATTR_CMN_CHGTIME = 0x800 - ATTR_CMN_CRTIME = 0x200 - ATTR_CMN_DATA_PROTECT_FLAGS = 0x40000000 - ATTR_CMN_DEVID = 0x2 - ATTR_CMN_DOCUMENT_ID = 0x100000 - ATTR_CMN_ERROR = 0x20000000 - ATTR_CMN_EXTENDED_SECURITY = 0x400000 - ATTR_CMN_FILEID = 0x2000000 - ATTR_CMN_FLAGS = 0x40000 - ATTR_CMN_FNDRINFO = 0x4000 - ATTR_CMN_FSID = 0x4 - ATTR_CMN_FULLPATH = 0x8000000 - ATTR_CMN_GEN_COUNT = 0x80000 - ATTR_CMN_GRPID = 0x10000 - ATTR_CMN_GRPUUID = 0x1000000 - ATTR_CMN_MODTIME = 0x400 - ATTR_CMN_NAME = 0x1 - ATTR_CMN_NAMEDATTRCOUNT = 0x80000 - ATTR_CMN_NAMEDATTRLIST = 0x100000 - ATTR_CMN_OBJID = 0x20 - ATTR_CMN_OBJPERMANENTID = 0x40 - ATTR_CMN_OBJTAG = 0x10 - ATTR_CMN_OBJTYPE = 0x8 - ATTR_CMN_OWNERID = 0x8000 - ATTR_CMN_PARENTID = 0x4000000 - ATTR_CMN_PAROBJID = 0x80 - ATTR_CMN_RETURNED_ATTRS = 0x80000000 - ATTR_CMN_SCRIPT = 0x100 - ATTR_CMN_SETMASK = 0x51c7ff00 - ATTR_CMN_USERACCESS = 0x200000 - ATTR_CMN_UUID = 0x800000 - ATTR_CMN_VALIDMASK = 0xffffffff - ATTR_CMN_VOLSETMASK = 0x6700 - ATTR_FILE_ALLOCSIZE = 0x4 - ATTR_FILE_CLUMPSIZE = 0x10 - ATTR_FILE_DATAALLOCSIZE = 0x400 - ATTR_FILE_DATAEXTENTS = 0x800 - ATTR_FILE_DATALENGTH = 0x200 - ATTR_FILE_DEVTYPE = 0x20 - ATTR_FILE_FILETYPE = 0x40 - ATTR_FILE_FORKCOUNT = 0x80 - ATTR_FILE_FORKLIST = 0x100 - ATTR_FILE_IOBLOCKSIZE = 0x8 - ATTR_FILE_LINKCOUNT = 0x1 - ATTR_FILE_RSRCALLOCSIZE = 0x2000 - ATTR_FILE_RSRCEXTENTS = 0x4000 - ATTR_FILE_RSRCLENGTH = 0x1000 - ATTR_FILE_SETMASK = 0x20 - ATTR_FILE_TOTALSIZE = 0x2 - ATTR_FILE_VALIDMASK = 0x37ff - ATTR_VOL_ALLOCATIONCLUMP = 0x40 - ATTR_VOL_ATTRIBUTES = 0x40000000 - ATTR_VOL_CAPABILITIES = 0x20000 - ATTR_VOL_DIRCOUNT = 0x400 - ATTR_VOL_ENCODINGSUSED = 0x10000 - ATTR_VOL_FILECOUNT = 0x200 - ATTR_VOL_FSTYPE = 0x1 - ATTR_VOL_INFO = 0x80000000 - ATTR_VOL_IOBLOCKSIZE = 0x80 - ATTR_VOL_MAXOBJCOUNT = 0x800 - ATTR_VOL_MINALLOCATION = 0x20 - ATTR_VOL_MOUNTEDDEVICE = 0x8000 - ATTR_VOL_MOUNTFLAGS = 0x4000 - ATTR_VOL_MOUNTPOINT = 0x1000 - ATTR_VOL_NAME = 0x2000 - ATTR_VOL_OBJCOUNT = 0x100 - ATTR_VOL_QUOTA_SIZE = 0x10000000 - ATTR_VOL_RESERVED_SIZE = 0x20000000 - ATTR_VOL_SETMASK = 0x80002000 - ATTR_VOL_SIGNATURE = 0x2 - ATTR_VOL_SIZE = 0x4 - ATTR_VOL_SPACEAVAIL = 0x10 - ATTR_VOL_SPACEFREE = 0x8 - ATTR_VOL_UUID = 0x40000 - ATTR_VOL_VALIDMASK = 0xf007ffff - B0 = 0x0 - B110 = 0x6e - B115200 = 0x1c200 - B1200 = 0x4b0 - B134 = 0x86 - B14400 = 0x3840 - B150 = 0x96 - B1800 = 0x708 - B19200 = 0x4b00 - B200 = 0xc8 - B230400 = 0x38400 - B2400 = 0x960 - B28800 = 0x7080 - B300 = 0x12c - B38400 = 0x9600 - B4800 = 0x12c0 - B50 = 0x32 - B57600 = 0xe100 - B600 = 0x258 - B7200 = 0x1c20 - B75 = 0x4b - B76800 = 0x12c00 - B9600 = 0x2580 - BIOCFLUSH = 0x20004268 - BIOCGBLEN = 0x40044266 - BIOCGDLT = 0x4004426a - BIOCGDLTLIST = 0xc00c4279 - BIOCGETIF = 0x4020426b - BIOCGHDRCMPLT = 0x40044274 - BIOCGRSIG = 0x40044272 - BIOCGRTIMEOUT = 0x4010426e - BIOCGSEESENT = 0x40044276 - BIOCGSTATS = 0x4008426f - BIOCIMMEDIATE = 0x80044270 - BIOCPROMISC = 0x20004269 - BIOCSBLEN = 0xc0044266 - BIOCSDLT = 0x80044278 - BIOCSETF = 0x80104267 - BIOCSETFNR = 0x8010427e - BIOCSETIF = 0x8020426c - BIOCSHDRCMPLT = 0x80044275 - BIOCSRSIG = 0x80044273 - BIOCSRTIMEOUT = 0x8010426d - BIOCSSEESENT = 0x80044277 - BIOCVERSION = 0x40044271 - BPF_A = 0x10 - BPF_ABS = 0x20 - BPF_ADD = 0x0 - BPF_ALIGNMENT = 0x4 - BPF_ALU = 0x4 - BPF_AND = 0x50 - BPF_B = 0x10 - BPF_DIV = 0x30 - BPF_H = 0x8 - BPF_IMM = 0x0 - BPF_IND = 0x40 - BPF_JA = 0x0 - BPF_JEQ = 0x10 - BPF_JGE = 0x30 - BPF_JGT = 0x20 - BPF_JMP = 0x5 - BPF_JSET = 0x40 - BPF_K = 0x0 - BPF_LD = 0x0 - BPF_LDX = 0x1 - BPF_LEN = 0x80 - BPF_LSH = 0x60 - BPF_MAJOR_VERSION = 0x1 - BPF_MAXBUFSIZE = 0x80000 - BPF_MAXINSNS = 0x200 - BPF_MEM = 0x60 - BPF_MEMWORDS = 0x10 - BPF_MINBUFSIZE = 0x20 - BPF_MINOR_VERSION = 0x1 - BPF_MISC = 0x7 - BPF_MSH = 0xa0 - BPF_MUL = 0x20 - BPF_NEG = 0x80 - BPF_OR = 0x40 - BPF_RELEASE = 0x30bb6 - BPF_RET = 0x6 - BPF_RSH = 0x70 - BPF_ST = 0x2 - BPF_STX = 0x3 - BPF_SUB = 0x10 - BPF_TAX = 0x0 - BPF_TXA = 0x80 - BPF_W = 0x0 - BPF_X = 0x8 - BRKINT = 0x2 - BS0 = 0x0 - BS1 = 0x8000 - BSDLY = 0x8000 - CFLUSH = 0xf - CLOCAL = 0x8000 - CLOCK_MONOTONIC = 0x6 - CLOCK_MONOTONIC_RAW = 0x4 - CLOCK_MONOTONIC_RAW_APPROX = 0x5 - CLOCK_PROCESS_CPUTIME_ID = 0xc - CLOCK_REALTIME = 0x0 - CLOCK_THREAD_CPUTIME_ID = 0x10 - CLOCK_UPTIME_RAW = 0x8 - CLOCK_UPTIME_RAW_APPROX = 0x9 - CLONE_NOFOLLOW = 0x1 - CLONE_NOOWNERCOPY = 0x2 - CR0 = 0x0 - CR1 = 0x1000 - CR2 = 0x2000 - CR3 = 0x3000 - CRDLY = 0x3000 - CREAD = 0x800 - CRTSCTS = 0x30000 - CS5 = 0x0 - CS6 = 0x100 - CS7 = 0x200 - CS8 = 0x300 - CSIZE = 0x300 - CSTART = 0x11 - CSTATUS = 0x14 - CSTOP = 0x13 - CSTOPB = 0x400 - CSUSP = 0x1a - CTLIOCGINFO = 0xc0644e03 - CTL_HW = 0x6 - CTL_KERN = 0x1 - CTL_MAXNAME = 0xc - CTL_NET = 0x4 - DLT_A429 = 0xb8 - DLT_A653_ICM = 0xb9 - DLT_AIRONET_HEADER = 0x78 - DLT_AOS = 0xde - DLT_APPLE_IP_OVER_IEEE1394 = 0x8a - DLT_ARCNET = 0x7 - DLT_ARCNET_LINUX = 0x81 - DLT_ATM_CLIP = 0x13 - DLT_ATM_RFC1483 = 0xb - DLT_AURORA = 0x7e - DLT_AX25 = 0x3 - DLT_AX25_KISS = 0xca - DLT_BACNET_MS_TP = 0xa5 - DLT_BLUETOOTH_HCI_H4 = 0xbb - DLT_BLUETOOTH_HCI_H4_WITH_PHDR = 0xc9 - DLT_CAN20B = 0xbe - DLT_CAN_SOCKETCAN = 0xe3 - DLT_CHAOS = 0x5 - DLT_CHDLC = 0x68 - DLT_CISCO_IOS = 0x76 - DLT_C_HDLC = 0x68 - DLT_C_HDLC_WITH_DIR = 0xcd - DLT_DBUS = 0xe7 - DLT_DECT = 0xdd - DLT_DOCSIS = 0x8f - DLT_DVB_CI = 0xeb - DLT_ECONET = 0x73 - DLT_EN10MB = 0x1 - DLT_EN3MB = 0x2 - DLT_ENC = 0x6d - DLT_ERF = 0xc5 - DLT_ERF_ETH = 0xaf - DLT_ERF_POS = 0xb0 - DLT_FC_2 = 0xe0 - DLT_FC_2_WITH_FRAME_DELIMS = 0xe1 - DLT_FDDI = 0xa - DLT_FLEXRAY = 0xd2 - DLT_FRELAY = 0x6b - DLT_FRELAY_WITH_DIR = 0xce - DLT_GCOM_SERIAL = 0xad - DLT_GCOM_T1E1 = 0xac - DLT_GPF_F = 0xab - DLT_GPF_T = 0xaa - DLT_GPRS_LLC = 0xa9 - DLT_GSMTAP_ABIS = 0xda - DLT_GSMTAP_UM = 0xd9 - DLT_HHDLC = 0x79 - DLT_IBM_SN = 0x92 - DLT_IBM_SP = 0x91 - DLT_IEEE802 = 0x6 - DLT_IEEE802_11 = 0x69 - DLT_IEEE802_11_RADIO = 0x7f - DLT_IEEE802_11_RADIO_AVS = 0xa3 - DLT_IEEE802_15_4 = 0xc3 - DLT_IEEE802_15_4_LINUX = 0xbf - DLT_IEEE802_15_4_NOFCS = 0xe6 - DLT_IEEE802_15_4_NONASK_PHY = 0xd7 - DLT_IEEE802_16_MAC_CPS = 0xbc - DLT_IEEE802_16_MAC_CPS_RADIO = 0xc1 - DLT_IPFILTER = 0x74 - DLT_IPMB = 0xc7 - DLT_IPMB_LINUX = 0xd1 - DLT_IPNET = 0xe2 - DLT_IPOIB = 0xf2 - DLT_IPV4 = 0xe4 - DLT_IPV6 = 0xe5 - DLT_IP_OVER_FC = 0x7a - DLT_JUNIPER_ATM1 = 0x89 - DLT_JUNIPER_ATM2 = 0x87 - DLT_JUNIPER_ATM_CEMIC = 0xee - DLT_JUNIPER_CHDLC = 0xb5 - DLT_JUNIPER_ES = 0x84 - DLT_JUNIPER_ETHER = 0xb2 - DLT_JUNIPER_FIBRECHANNEL = 0xea - DLT_JUNIPER_FRELAY = 0xb4 - DLT_JUNIPER_GGSN = 0x85 - DLT_JUNIPER_ISM = 0xc2 - DLT_JUNIPER_MFR = 0x86 - DLT_JUNIPER_MLFR = 0x83 - DLT_JUNIPER_MLPPP = 0x82 - DLT_JUNIPER_MONITOR = 0xa4 - DLT_JUNIPER_PIC_PEER = 0xae - DLT_JUNIPER_PPP = 0xb3 - DLT_JUNIPER_PPPOE = 0xa7 - DLT_JUNIPER_PPPOE_ATM = 0xa8 - DLT_JUNIPER_SERVICES = 0x88 - DLT_JUNIPER_SRX_E2E = 0xe9 - DLT_JUNIPER_ST = 0xc8 - DLT_JUNIPER_VP = 0xb7 - DLT_JUNIPER_VS = 0xe8 - DLT_LAPB_WITH_DIR = 0xcf - DLT_LAPD = 0xcb - DLT_LIN = 0xd4 - DLT_LINUX_EVDEV = 0xd8 - DLT_LINUX_IRDA = 0x90 - DLT_LINUX_LAPD = 0xb1 - DLT_LINUX_PPP_WITHDIRECTION = 0xa6 - DLT_LINUX_SLL = 0x71 - DLT_LOOP = 0x6c - DLT_LTALK = 0x72 - DLT_MATCHING_MAX = 0x10a - DLT_MATCHING_MIN = 0x68 - DLT_MFR = 0xb6 - DLT_MOST = 0xd3 - DLT_MPEG_2_TS = 0xf3 - DLT_MPLS = 0xdb - DLT_MTP2 = 0x8c - DLT_MTP2_WITH_PHDR = 0x8b - DLT_MTP3 = 0x8d - DLT_MUX27010 = 0xec - DLT_NETANALYZER = 0xf0 - DLT_NETANALYZER_TRANSPARENT = 0xf1 - DLT_NFC_LLCP = 0xf5 - DLT_NFLOG = 0xef - DLT_NG40 = 0xf4 - DLT_NULL = 0x0 - DLT_PCI_EXP = 0x7d - DLT_PFLOG = 0x75 - DLT_PFSYNC = 0x12 - DLT_PPI = 0xc0 - DLT_PPP = 0x9 - DLT_PPP_BSDOS = 0x10 - DLT_PPP_ETHER = 0x33 - DLT_PPP_PPPD = 0xa6 - DLT_PPP_SERIAL = 0x32 - DLT_PPP_WITH_DIR = 0xcc - DLT_PPP_WITH_DIRECTION = 0xa6 - DLT_PRISM_HEADER = 0x77 - DLT_PRONET = 0x4 - DLT_RAIF1 = 0xc6 - DLT_RAW = 0xc - DLT_RIO = 0x7c - DLT_SCCP = 0x8e - DLT_SITA = 0xc4 - DLT_SLIP = 0x8 - DLT_SLIP_BSDOS = 0xf - DLT_STANAG_5066_D_PDU = 0xed - DLT_SUNATM = 0x7b - DLT_SYMANTEC_FIREWALL = 0x63 - DLT_TZSP = 0x80 - DLT_USB = 0xba - DLT_USB_DARWIN = 0x10a - DLT_USB_LINUX = 0xbd - DLT_USB_LINUX_MMAPPED = 0xdc - DLT_USER0 = 0x93 - DLT_USER1 = 0x94 - DLT_USER10 = 0x9d - DLT_USER11 = 0x9e - DLT_USER12 = 0x9f - DLT_USER13 = 0xa0 - DLT_USER14 = 0xa1 - DLT_USER15 = 0xa2 - DLT_USER2 = 0x95 - DLT_USER3 = 0x96 - DLT_USER4 = 0x97 - DLT_USER5 = 0x98 - DLT_USER6 = 0x99 - DLT_USER7 = 0x9a - DLT_USER8 = 0x9b - DLT_USER9 = 0x9c - DLT_WIHART = 0xdf - DLT_X2E_SERIAL = 0xd5 - DLT_X2E_XORAYA = 0xd6 - DT_BLK = 0x6 - DT_CHR = 0x2 - DT_DIR = 0x4 - DT_FIFO = 0x1 - DT_LNK = 0xa - DT_REG = 0x8 - DT_SOCK = 0xc - DT_UNKNOWN = 0x0 - DT_WHT = 0xe - ECHO = 0x8 - ECHOCTL = 0x40 - ECHOE = 0x2 - ECHOK = 0x4 - ECHOKE = 0x1 - ECHONL = 0x10 - ECHOPRT = 0x20 - EVFILT_AIO = -0x3 - EVFILT_EXCEPT = -0xf - EVFILT_FS = -0x9 - EVFILT_MACHPORT = -0x8 - EVFILT_PROC = -0x5 - EVFILT_READ = -0x1 - EVFILT_SIGNAL = -0x6 - EVFILT_SYSCOUNT = 0x11 - EVFILT_THREADMARKER = 0x11 - EVFILT_TIMER = -0x7 - EVFILT_USER = -0xa - EVFILT_VM = -0xc - EVFILT_VNODE = -0x4 - EVFILT_WRITE = -0x2 - EV_ADD = 0x1 - EV_CLEAR = 0x20 - EV_DELETE = 0x2 - EV_DISABLE = 0x8 - EV_DISPATCH = 0x80 - EV_DISPATCH2 = 0x180 - EV_ENABLE = 0x4 - EV_EOF = 0x8000 - EV_ERROR = 0x4000 - EV_FLAG0 = 0x1000 - EV_FLAG1 = 0x2000 - EV_ONESHOT = 0x10 - EV_OOBAND = 0x2000 - EV_POLL = 0x1000 - EV_RECEIPT = 0x40 - EV_SYSFLAGS = 0xf000 - EV_UDATA_SPECIFIC = 0x100 - EV_VANISHED = 0x200 - EXTA = 0x4b00 - EXTB = 0x9600 - EXTPROC = 0x800 - FD_CLOEXEC = 0x1 - FD_SETSIZE = 0x400 - FF0 = 0x0 - FF1 = 0x4000 - FFDLY = 0x4000 - FLUSHO = 0x800000 - FSOPT_ATTR_CMN_EXTENDED = 0x20 - FSOPT_NOFOLLOW = 0x1 - FSOPT_NOINMEMUPDATE = 0x2 - FSOPT_PACK_INVAL_ATTRS = 0x8 - FSOPT_REPORT_FULLSIZE = 0x4 - FSOPT_RETURN_REALDEV = 0x200 - F_ADDFILESIGS = 0x3d - F_ADDFILESIGS_FOR_DYLD_SIM = 0x53 - F_ADDFILESIGS_INFO = 0x67 - F_ADDFILESIGS_RETURN = 0x61 - F_ADDFILESUPPL = 0x68 - F_ADDSIGS = 0x3b - F_ALLOCATEALL = 0x4 - F_ALLOCATECONTIG = 0x2 - F_BARRIERFSYNC = 0x55 - F_CHECK_LV = 0x62 - F_CHKCLEAN = 0x29 - F_DUPFD = 0x0 - F_DUPFD_CLOEXEC = 0x43 - F_FINDSIGS = 0x4e - F_FLUSH_DATA = 0x28 - F_FREEZE_FS = 0x35 - F_FULLFSYNC = 0x33 - F_GETCODEDIR = 0x48 - F_GETFD = 0x1 - F_GETFL = 0x3 - F_GETLK = 0x7 - F_GETLKPID = 0x42 - F_GETNOSIGPIPE = 0x4a - F_GETOWN = 0x5 - F_GETPATH = 0x32 - F_GETPATH_MTMINFO = 0x47 - F_GETPATH_NOFIRMLINK = 0x66 - F_GETPROTECTIONCLASS = 0x3f - F_GETPROTECTIONLEVEL = 0x4d - F_GETSIGSINFO = 0x69 - F_GLOBAL_NOCACHE = 0x37 - F_LOG2PHYS = 0x31 - F_LOG2PHYS_EXT = 0x41 - F_NOCACHE = 0x30 - F_NODIRECT = 0x3e - F_OK = 0x0 - F_PATHPKG_CHECK = 0x34 - F_PEOFPOSMODE = 0x3 - F_PREALLOCATE = 0x2a - F_PUNCHHOLE = 0x63 - F_RDADVISE = 0x2c - F_RDAHEAD = 0x2d - F_RDLCK = 0x1 - F_SETBACKINGSTORE = 0x46 - F_SETFD = 0x2 - F_SETFL = 0x4 - F_SETLK = 0x8 - F_SETLKW = 0x9 - F_SETLKWTIMEOUT = 0xa - F_SETNOSIGPIPE = 0x49 - F_SETOWN = 0x6 - F_SETPROTECTIONCLASS = 0x40 - F_SETSIZE = 0x2b - F_SINGLE_WRITER = 0x4c - F_SPECULATIVE_READ = 0x65 - F_THAW_FS = 0x36 - F_TRANSCODEKEY = 0x4b - F_TRIM_ACTIVE_FILE = 0x64 - F_UNLCK = 0x2 - F_VOLPOSMODE = 0x4 - F_WRLCK = 0x3 - HUPCL = 0x4000 - HW_MACHINE = 0x1 - ICANON = 0x100 - ICMP6_FILTER = 0x12 - ICRNL = 0x100 - IEXTEN = 0x400 - IFF_ALLMULTI = 0x200 - IFF_ALTPHYS = 0x4000 - IFF_BROADCAST = 0x2 - IFF_DEBUG = 0x4 - IFF_LINK0 = 0x1000 - IFF_LINK1 = 0x2000 - IFF_LINK2 = 0x4000 - IFF_LOOPBACK = 0x8 - IFF_MULTICAST = 0x8000 - IFF_NOARP = 0x80 - IFF_NOTRAILERS = 0x20 - IFF_OACTIVE = 0x400 - IFF_POINTOPOINT = 0x10 - IFF_PROMISC = 0x100 - IFF_RUNNING = 0x40 - IFF_SIMPLEX = 0x800 - IFF_UP = 0x1 - IFNAMSIZ = 0x10 - IFT_1822 = 0x2 - IFT_6LOWPAN = 0x40 - IFT_AAL5 = 0x31 - IFT_ARCNET = 0x23 - IFT_ARCNETPLUS = 0x24 - IFT_ATM = 0x25 - IFT_BRIDGE = 0xd1 - IFT_CARP = 0xf8 - IFT_CELLULAR = 0xff - IFT_CEPT = 0x13 - IFT_DS3 = 0x1e - IFT_ENC = 0xf4 - IFT_EON = 0x19 - IFT_ETHER = 0x6 - IFT_FAITH = 0x38 - IFT_FDDI = 0xf - IFT_FRELAY = 0x20 - IFT_FRELAYDCE = 0x2c - IFT_GIF = 0x37 - IFT_HDH1822 = 0x3 - IFT_HIPPI = 0x2f - IFT_HSSI = 0x2e - IFT_HY = 0xe - IFT_IEEE1394 = 0x90 - IFT_IEEE8023ADLAG = 0x88 - IFT_ISDNBASIC = 0x14 - IFT_ISDNPRIMARY = 0x15 - IFT_ISO88022LLC = 0x29 - IFT_ISO88023 = 0x7 - IFT_ISO88024 = 0x8 - IFT_ISO88025 = 0x9 - IFT_ISO88026 = 0xa - IFT_L2VLAN = 0x87 - IFT_LAPB = 0x10 - IFT_LOCALTALK = 0x2a - IFT_LOOP = 0x18 - IFT_MIOX25 = 0x26 - IFT_MODEM = 0x30 - IFT_NSIP = 0x1b - IFT_OTHER = 0x1 - IFT_P10 = 0xc - IFT_P80 = 0xd - IFT_PARA = 0x22 - IFT_PDP = 0xff - IFT_PFLOG = 0xf5 - IFT_PFSYNC = 0xf6 - IFT_PKTAP = 0xfe - IFT_PPP = 0x17 - IFT_PROPMUX = 0x36 - IFT_PROPVIRTUAL = 0x35 - IFT_PTPSERIAL = 0x16 - IFT_RS232 = 0x21 - IFT_SDLC = 0x11 - IFT_SIP = 0x1f - IFT_SLIP = 0x1c - IFT_SMDSDXI = 0x2b - IFT_SMDSICIP = 0x34 - IFT_SONET = 0x27 - IFT_SONETPATH = 0x32 - IFT_SONETVT = 0x33 - IFT_STARLAN = 0xb - IFT_STF = 0x39 - IFT_T1 = 0x12 - IFT_ULTRA = 0x1d - IFT_V35 = 0x2d - IFT_X25 = 0x5 - IFT_X25DDN = 0x4 - IFT_X25PLE = 0x28 - IFT_XETHER = 0x1a - IGNBRK = 0x1 - IGNCR = 0x80 - IGNPAR = 0x4 - IMAXBEL = 0x2000 - INLCR = 0x40 - INPCK = 0x10 - IN_CLASSA_HOST = 0xffffff - IN_CLASSA_MAX = 0x80 - IN_CLASSA_NET = 0xff000000 - IN_CLASSA_NSHIFT = 0x18 - IN_CLASSB_HOST = 0xffff - IN_CLASSB_MAX = 0x10000 - IN_CLASSB_NET = 0xffff0000 - IN_CLASSB_NSHIFT = 0x10 - IN_CLASSC_HOST = 0xff - IN_CLASSC_NET = 0xffffff00 - IN_CLASSC_NSHIFT = 0x8 - IN_CLASSD_HOST = 0xfffffff - IN_CLASSD_NET = 0xf0000000 - IN_CLASSD_NSHIFT = 0x1c - IN_LINKLOCALNETNUM = 0xa9fe0000 - IN_LOOPBACKNET = 0x7f - IPPROTO_3PC = 0x22 - IPPROTO_ADFS = 0x44 - IPPROTO_AH = 0x33 - IPPROTO_AHIP = 0x3d - IPPROTO_APES = 0x63 - IPPROTO_ARGUS = 0xd - IPPROTO_AX25 = 0x5d - IPPROTO_BHA = 0x31 - IPPROTO_BLT = 0x1e - IPPROTO_BRSATMON = 0x4c - IPPROTO_CFTP = 0x3e - IPPROTO_CHAOS = 0x10 - IPPROTO_CMTP = 0x26 - IPPROTO_CPHB = 0x49 - IPPROTO_CPNX = 0x48 - IPPROTO_DDP = 0x25 - IPPROTO_DGP = 0x56 - IPPROTO_DIVERT = 0xfe - IPPROTO_DONE = 0x101 - IPPROTO_DSTOPTS = 0x3c - IPPROTO_EGP = 0x8 - IPPROTO_EMCON = 0xe - IPPROTO_ENCAP = 0x62 - IPPROTO_EON = 0x50 - IPPROTO_ESP = 0x32 - IPPROTO_ETHERIP = 0x61 - IPPROTO_FRAGMENT = 0x2c - IPPROTO_GGP = 0x3 - IPPROTO_GMTP = 0x64 - IPPROTO_GRE = 0x2f - IPPROTO_HELLO = 0x3f - IPPROTO_HMP = 0x14 - IPPROTO_HOPOPTS = 0x0 - IPPROTO_ICMP = 0x1 - IPPROTO_ICMPV6 = 0x3a - IPPROTO_IDP = 0x16 - IPPROTO_IDPR = 0x23 - IPPROTO_IDRP = 0x2d - IPPROTO_IGMP = 0x2 - IPPROTO_IGP = 0x55 - IPPROTO_IGRP = 0x58 - IPPROTO_IL = 0x28 - IPPROTO_INLSP = 0x34 - IPPROTO_INP = 0x20 - IPPROTO_IP = 0x0 - IPPROTO_IPCOMP = 0x6c - IPPROTO_IPCV = 0x47 - IPPROTO_IPEIP = 0x5e - IPPROTO_IPIP = 0x4 - IPPROTO_IPPC = 0x43 - IPPROTO_IPV4 = 0x4 - IPPROTO_IPV6 = 0x29 - IPPROTO_IRTP = 0x1c - IPPROTO_KRYPTOLAN = 0x41 - IPPROTO_LARP = 0x5b - IPPROTO_LEAF1 = 0x19 - IPPROTO_LEAF2 = 0x1a - IPPROTO_MAX = 0x100 - IPPROTO_MAXID = 0x34 - IPPROTO_MEAS = 0x13 - IPPROTO_MHRP = 0x30 - IPPROTO_MICP = 0x5f - IPPROTO_MTP = 0x5c - IPPROTO_MUX = 0x12 - IPPROTO_ND = 0x4d - IPPROTO_NHRP = 0x36 - IPPROTO_NONE = 0x3b - IPPROTO_NSP = 0x1f - IPPROTO_NVPII = 0xb - IPPROTO_OSPFIGP = 0x59 - IPPROTO_PGM = 0x71 - IPPROTO_PIGP = 0x9 - IPPROTO_PIM = 0x67 - IPPROTO_PRM = 0x15 - IPPROTO_PUP = 0xc - IPPROTO_PVP = 0x4b - IPPROTO_RAW = 0xff - IPPROTO_RCCMON = 0xa - IPPROTO_RDP = 0x1b - IPPROTO_ROUTING = 0x2b - IPPROTO_RSVP = 0x2e - IPPROTO_RVD = 0x42 - IPPROTO_SATEXPAK = 0x40 - IPPROTO_SATMON = 0x45 - IPPROTO_SCCSP = 0x60 - IPPROTO_SCTP = 0x84 - IPPROTO_SDRP = 0x2a - IPPROTO_SEP = 0x21 - IPPROTO_SRPC = 0x5a - IPPROTO_ST = 0x7 - IPPROTO_SVMTP = 0x52 - IPPROTO_SWIPE = 0x35 - IPPROTO_TCF = 0x57 - IPPROTO_TCP = 0x6 - IPPROTO_TP = 0x1d - IPPROTO_TPXX = 0x27 - IPPROTO_TRUNK1 = 0x17 - IPPROTO_TRUNK2 = 0x18 - IPPROTO_TTP = 0x54 - IPPROTO_UDP = 0x11 - IPPROTO_VINES = 0x53 - IPPROTO_VISA = 0x46 - IPPROTO_VMTP = 0x51 - IPPROTO_WBEXPAK = 0x4f - IPPROTO_WBMON = 0x4e - IPPROTO_WSN = 0x4a - IPPROTO_XNET = 0xf - IPPROTO_XTP = 0x24 - IPV6_2292DSTOPTS = 0x17 - IPV6_2292HOPLIMIT = 0x14 - IPV6_2292HOPOPTS = 0x16 - IPV6_2292NEXTHOP = 0x15 - IPV6_2292PKTINFO = 0x13 - IPV6_2292PKTOPTIONS = 0x19 - IPV6_2292RTHDR = 0x18 - IPV6_3542DSTOPTS = 0x32 - IPV6_3542HOPLIMIT = 0x2f - IPV6_3542HOPOPTS = 0x31 - IPV6_3542NEXTHOP = 0x30 - IPV6_3542PKTINFO = 0x2e - IPV6_3542RTHDR = 0x33 - IPV6_ADDR_MC_FLAGS_PREFIX = 0x20 - IPV6_ADDR_MC_FLAGS_TRANSIENT = 0x10 - IPV6_ADDR_MC_FLAGS_UNICAST_BASED = 0x30 - IPV6_AUTOFLOWLABEL = 0x3b - IPV6_BINDV6ONLY = 0x1b - IPV6_BOUND_IF = 0x7d - IPV6_CHECKSUM = 0x1a - IPV6_DEFAULT_MULTICAST_HOPS = 0x1 - IPV6_DEFAULT_MULTICAST_LOOP = 0x1 - IPV6_DEFHLIM = 0x40 - IPV6_DONTFRAG = 0x3e - IPV6_DSTOPTS = 0x32 - IPV6_FAITH = 0x1d - IPV6_FLOWINFO_MASK = 0xffffff0f - IPV6_FLOWLABEL_MASK = 0xffff0f00 - IPV6_FLOW_ECN_MASK = 0x3000 - IPV6_FRAGTTL = 0x3c - IPV6_FW_ADD = 0x1e - IPV6_FW_DEL = 0x1f - IPV6_FW_FLUSH = 0x20 - IPV6_FW_GET = 0x22 - IPV6_FW_ZERO = 0x21 - IPV6_HLIMDEC = 0x1 - IPV6_HOPLIMIT = 0x2f - IPV6_HOPOPTS = 0x31 - IPV6_IPSEC_POLICY = 0x1c - IPV6_JOIN_GROUP = 0xc - IPV6_LEAVE_GROUP = 0xd - IPV6_MAXHLIM = 0xff - IPV6_MAXOPTHDR = 0x800 - IPV6_MAXPACKET = 0xffff - IPV6_MAX_GROUP_SRC_FILTER = 0x200 - IPV6_MAX_MEMBERSHIPS = 0xfff - IPV6_MAX_SOCK_SRC_FILTER = 0x80 - IPV6_MIN_MEMBERSHIPS = 0x1f - IPV6_MMTU = 0x500 - IPV6_MSFILTER = 0x4a - IPV6_MULTICAST_HOPS = 0xa - IPV6_MULTICAST_IF = 0x9 - IPV6_MULTICAST_LOOP = 0xb - IPV6_NEXTHOP = 0x30 - IPV6_PATHMTU = 0x2c - IPV6_PKTINFO = 0x2e - IPV6_PORTRANGE = 0xe - IPV6_PORTRANGE_DEFAULT = 0x0 - IPV6_PORTRANGE_HIGH = 0x1 - IPV6_PORTRANGE_LOW = 0x2 - IPV6_PREFER_TEMPADDR = 0x3f - IPV6_RECVDSTOPTS = 0x28 - IPV6_RECVHOPLIMIT = 0x25 - IPV6_RECVHOPOPTS = 0x27 - IPV6_RECVPATHMTU = 0x2b - IPV6_RECVPKTINFO = 0x3d - IPV6_RECVRTHDR = 0x26 - IPV6_RECVTCLASS = 0x23 - IPV6_RTHDR = 0x33 - IPV6_RTHDRDSTOPTS = 0x39 - IPV6_RTHDR_LOOSE = 0x0 - IPV6_RTHDR_STRICT = 0x1 - IPV6_RTHDR_TYPE_0 = 0x0 - IPV6_SOCKOPT_RESERVED1 = 0x3 - IPV6_TCLASS = 0x24 - IPV6_UNICAST_HOPS = 0x4 - IPV6_USE_MIN_MTU = 0x2a - IPV6_V6ONLY = 0x1b - IPV6_VERSION = 0x60 - IPV6_VERSION_MASK = 0xf0 - IP_ADD_MEMBERSHIP = 0xc - IP_ADD_SOURCE_MEMBERSHIP = 0x46 - IP_BLOCK_SOURCE = 0x48 - IP_BOUND_IF = 0x19 - IP_DEFAULT_MULTICAST_LOOP = 0x1 - IP_DEFAULT_MULTICAST_TTL = 0x1 - IP_DF = 0x4000 - IP_DONTFRAG = 0x1c - IP_DROP_MEMBERSHIP = 0xd - IP_DROP_SOURCE_MEMBERSHIP = 0x47 - IP_DUMMYNET_CONFIGURE = 0x3c - IP_DUMMYNET_DEL = 0x3d - IP_DUMMYNET_FLUSH = 0x3e - IP_DUMMYNET_GET = 0x40 - IP_FAITH = 0x16 - IP_FW_ADD = 0x28 - IP_FW_DEL = 0x29 - IP_FW_FLUSH = 0x2a - IP_FW_GET = 0x2c - IP_FW_RESETLOG = 0x2d - IP_FW_ZERO = 0x2b - IP_HDRINCL = 0x2 - IP_IPSEC_POLICY = 0x15 - IP_MAXPACKET = 0xffff - IP_MAX_GROUP_SRC_FILTER = 0x200 - IP_MAX_MEMBERSHIPS = 0xfff - IP_MAX_SOCK_MUTE_FILTER = 0x80 - IP_MAX_SOCK_SRC_FILTER = 0x80 - IP_MF = 0x2000 - IP_MIN_MEMBERSHIPS = 0x1f - IP_MSFILTER = 0x4a - IP_MSS = 0x240 - IP_MULTICAST_IF = 0x9 - IP_MULTICAST_IFINDEX = 0x42 - IP_MULTICAST_LOOP = 0xb - IP_MULTICAST_TTL = 0xa - IP_MULTICAST_VIF = 0xe - IP_NAT__XXX = 0x37 - IP_OFFMASK = 0x1fff - IP_OLD_FW_ADD = 0x32 - IP_OLD_FW_DEL = 0x33 - IP_OLD_FW_FLUSH = 0x34 - IP_OLD_FW_GET = 0x36 - IP_OLD_FW_RESETLOG = 0x38 - IP_OLD_FW_ZERO = 0x35 - IP_OPTIONS = 0x1 - IP_PKTINFO = 0x1a - IP_PORTRANGE = 0x13 - IP_PORTRANGE_DEFAULT = 0x0 - IP_PORTRANGE_HIGH = 0x1 - IP_PORTRANGE_LOW = 0x2 - IP_RECVDSTADDR = 0x7 - IP_RECVIF = 0x14 - IP_RECVOPTS = 0x5 - IP_RECVPKTINFO = 0x1a - IP_RECVRETOPTS = 0x6 - IP_RECVTOS = 0x1b - IP_RECVTTL = 0x18 - IP_RETOPTS = 0x8 - IP_RF = 0x8000 - IP_RSVP_OFF = 0x10 - IP_RSVP_ON = 0xf - IP_RSVP_VIF_OFF = 0x12 - IP_RSVP_VIF_ON = 0x11 - IP_STRIPHDR = 0x17 - IP_TOS = 0x3 - IP_TRAFFIC_MGT_BACKGROUND = 0x41 - IP_TTL = 0x4 - IP_UNBLOCK_SOURCE = 0x49 - ISIG = 0x80 - ISTRIP = 0x20 - IUTF8 = 0x4000 - IXANY = 0x800 - IXOFF = 0x400 - IXON = 0x200 - KERN_HOSTNAME = 0xa - KERN_OSRELEASE = 0x2 - KERN_OSTYPE = 0x1 - KERN_VERSION = 0x4 - LOCAL_PEERCRED = 0x1 - LOCAL_PEEREPID = 0x3 - LOCAL_PEEREUUID = 0x5 - LOCAL_PEERPID = 0x2 - LOCAL_PEERTOKEN = 0x6 - LOCAL_PEERUUID = 0x4 - LOCK_EX = 0x2 - LOCK_NB = 0x4 - LOCK_SH = 0x1 - LOCK_UN = 0x8 - MADV_CAN_REUSE = 0x9 - MADV_DONTNEED = 0x4 - MADV_FREE = 0x5 - MADV_FREE_REUSABLE = 0x7 - MADV_FREE_REUSE = 0x8 - MADV_NORMAL = 0x0 - MADV_PAGEOUT = 0xa - MADV_RANDOM = 0x1 - MADV_SEQUENTIAL = 0x2 - MADV_WILLNEED = 0x3 - MADV_ZERO_WIRED_PAGES = 0x6 - MAP_32BIT = 0x8000 - MAP_ANON = 0x1000 - MAP_ANONYMOUS = 0x1000 - MAP_COPY = 0x2 - MAP_FILE = 0x0 - MAP_FIXED = 0x10 - MAP_HASSEMAPHORE = 0x200 - MAP_JIT = 0x800 - MAP_NOCACHE = 0x400 - MAP_NOEXTEND = 0x100 - MAP_NORESERVE = 0x40 - MAP_PRIVATE = 0x2 - MAP_RENAME = 0x20 - MAP_RESERVED0080 = 0x80 - MAP_RESILIENT_CODESIGN = 0x2000 - MAP_RESILIENT_MEDIA = 0x4000 - MAP_SHARED = 0x1 - MAP_TRANSLATED_ALLOW_EXECUTE = 0x20000 - MAP_UNIX03 = 0x40000 - MCAST_BLOCK_SOURCE = 0x54 - MCAST_EXCLUDE = 0x2 - MCAST_INCLUDE = 0x1 - MCAST_JOIN_GROUP = 0x50 - MCAST_JOIN_SOURCE_GROUP = 0x52 - MCAST_LEAVE_GROUP = 0x51 - MCAST_LEAVE_SOURCE_GROUP = 0x53 - MCAST_UNBLOCK_SOURCE = 0x55 - MCAST_UNDEFINED = 0x0 - MCL_CURRENT = 0x1 - MCL_FUTURE = 0x2 - MNT_ASYNC = 0x40 - MNT_AUTOMOUNTED = 0x400000 - MNT_CMDFLAGS = 0xf0000 - MNT_CPROTECT = 0x80 - MNT_DEFWRITE = 0x2000000 - MNT_DONTBROWSE = 0x100000 - MNT_DOVOLFS = 0x8000 - MNT_DWAIT = 0x4 - MNT_EXPORTED = 0x100 - MNT_EXT_ROOT_DATA_VOL = 0x1 - MNT_FORCE = 0x80000 - MNT_IGNORE_OWNERSHIP = 0x200000 - MNT_JOURNALED = 0x800000 - MNT_LOCAL = 0x1000 - MNT_MULTILABEL = 0x4000000 - MNT_NOATIME = 0x10000000 - MNT_NOBLOCK = 0x20000 - MNT_NODEV = 0x10 - MNT_NOEXEC = 0x4 - MNT_NOSUID = 0x8 - MNT_NOUSERXATTR = 0x1000000 - MNT_NOWAIT = 0x2 - MNT_QUARANTINE = 0x400 - MNT_QUOTA = 0x2000 - MNT_RDONLY = 0x1 - MNT_RELOAD = 0x40000 - MNT_REMOVABLE = 0x200 - MNT_ROOTFS = 0x4000 - MNT_SNAPSHOT = 0x40000000 - MNT_STRICTATIME = 0x80000000 - MNT_SYNCHRONOUS = 0x2 - MNT_UNION = 0x20 - MNT_UNKNOWNPERMISSIONS = 0x200000 - MNT_UPDATE = 0x10000 - MNT_VISFLAGMASK = 0xd7f0f7ff - MNT_WAIT = 0x1 - MSG_CTRUNC = 0x20 - MSG_DONTROUTE = 0x4 - MSG_DONTWAIT = 0x80 - MSG_EOF = 0x100 - MSG_EOR = 0x8 - MSG_FLUSH = 0x400 - MSG_HAVEMORE = 0x2000 - MSG_HOLD = 0x800 - MSG_NEEDSA = 0x10000 - MSG_NOSIGNAL = 0x80000 - MSG_OOB = 0x1 - MSG_PEEK = 0x2 - MSG_RCVMORE = 0x4000 - MSG_SEND = 0x1000 - MSG_TRUNC = 0x10 - MSG_WAITALL = 0x40 - MSG_WAITSTREAM = 0x200 - MS_ASYNC = 0x1 - MS_DEACTIVATE = 0x8 - MS_INVALIDATE = 0x2 - MS_KILLPAGES = 0x4 - MS_SYNC = 0x10 - NAME_MAX = 0xff - NET_RT_DUMP = 0x1 - NET_RT_DUMP2 = 0x7 - NET_RT_FLAGS = 0x2 - NET_RT_FLAGS_PRIV = 0xa - NET_RT_IFLIST = 0x3 - NET_RT_IFLIST2 = 0x6 - NET_RT_MAXID = 0xb - NET_RT_STAT = 0x4 - NET_RT_TRASH = 0x5 - NFDBITS = 0x20 - NL0 = 0x0 - NL1 = 0x100 - NL2 = 0x200 - NL3 = 0x300 - NLDLY = 0x300 - NOFLSH = 0x80000000 - NOKERNINFO = 0x2000000 - NOTE_ABSOLUTE = 0x8 - NOTE_ATTRIB = 0x8 - NOTE_BACKGROUND = 0x40 - NOTE_CHILD = 0x4 - NOTE_CRITICAL = 0x20 - NOTE_DELETE = 0x1 - NOTE_EXEC = 0x20000000 - NOTE_EXIT = 0x80000000 - NOTE_EXITSTATUS = 0x4000000 - NOTE_EXIT_CSERROR = 0x40000 - NOTE_EXIT_DECRYPTFAIL = 0x10000 - NOTE_EXIT_DETAIL = 0x2000000 - NOTE_EXIT_DETAIL_MASK = 0x70000 - NOTE_EXIT_MEMORY = 0x20000 - NOTE_EXIT_REPARENTED = 0x80000 - NOTE_EXTEND = 0x4 - NOTE_FFAND = 0x40000000 - NOTE_FFCOPY = 0xc0000000 - NOTE_FFCTRLMASK = 0xc0000000 - NOTE_FFLAGSMASK = 0xffffff - NOTE_FFNOP = 0x0 - NOTE_FFOR = 0x80000000 - NOTE_FORK = 0x40000000 - NOTE_FUNLOCK = 0x100 - NOTE_LEEWAY = 0x10 - NOTE_LINK = 0x10 - NOTE_LOWAT = 0x1 - NOTE_MACHTIME = 0x100 - NOTE_MACH_CONTINUOUS_TIME = 0x80 - NOTE_NONE = 0x80 - NOTE_NSECONDS = 0x4 - NOTE_OOB = 0x2 - NOTE_PCTRLMASK = -0x100000 - NOTE_PDATAMASK = 0xfffff - NOTE_REAP = 0x10000000 - NOTE_RENAME = 0x20 - NOTE_REVOKE = 0x40 - NOTE_SECONDS = 0x1 - NOTE_SIGNAL = 0x8000000 - NOTE_TRACK = 0x1 - NOTE_TRACKERR = 0x2 - NOTE_TRIGGER = 0x1000000 - NOTE_USECONDS = 0x2 - NOTE_VM_ERROR = 0x10000000 - NOTE_VM_PRESSURE = 0x80000000 - NOTE_VM_PRESSURE_SUDDEN_TERMINATE = 0x20000000 - NOTE_VM_PRESSURE_TERMINATE = 0x40000000 - NOTE_WRITE = 0x2 - OCRNL = 0x10 - OFDEL = 0x20000 - OFILL = 0x80 - ONLCR = 0x2 - ONLRET = 0x40 - ONOCR = 0x20 - ONOEOT = 0x8 - OPOST = 0x1 - OXTABS = 0x4 - O_ACCMODE = 0x3 - O_ALERT = 0x20000000 - O_APPEND = 0x8 - O_ASYNC = 0x40 - O_CLOEXEC = 0x1000000 - O_CREAT = 0x200 - O_DIRECTORY = 0x100000 - O_DP_GETRAWENCRYPTED = 0x1 - O_DP_GETRAWUNENCRYPTED = 0x2 - O_DSYNC = 0x400000 - O_EVTONLY = 0x8000 - O_EXCL = 0x800 - O_EXLOCK = 0x20 - O_FSYNC = 0x80 - O_NDELAY = 0x4 - O_NOCTTY = 0x20000 - O_NOFOLLOW = 0x100 - O_NOFOLLOW_ANY = 0x20000000 - O_NONBLOCK = 0x4 - O_POPUP = 0x80000000 - O_RDONLY = 0x0 - O_RDWR = 0x2 - O_SHLOCK = 0x10 - O_SYMLINK = 0x200000 - O_SYNC = 0x80 - O_TRUNC = 0x400 - O_WRONLY = 0x1 - PARENB = 0x1000 - PARMRK = 0x8 - PARODD = 0x2000 - PENDIN = 0x20000000 - PRIO_PGRP = 0x1 - PRIO_PROCESS = 0x0 - PRIO_USER = 0x2 - PROT_EXEC = 0x4 - PROT_NONE = 0x0 - PROT_READ = 0x1 - PROT_WRITE = 0x2 - PT_ATTACH = 0xa - PT_ATTACHEXC = 0xe - PT_CONTINUE = 0x7 - PT_DENY_ATTACH = 0x1f - PT_DETACH = 0xb - PT_FIRSTMACH = 0x20 - PT_FORCEQUOTA = 0x1e - PT_KILL = 0x8 - PT_READ_D = 0x2 - PT_READ_I = 0x1 - PT_READ_U = 0x3 - PT_SIGEXC = 0xc - PT_STEP = 0x9 - PT_THUPDATE = 0xd - PT_TRACE_ME = 0x0 - PT_WRITE_D = 0x5 - PT_WRITE_I = 0x4 - PT_WRITE_U = 0x6 - RLIMIT_AS = 0x5 - RLIMIT_CORE = 0x4 - RLIMIT_CPU = 0x0 - RLIMIT_CPU_USAGE_MONITOR = 0x2 - RLIMIT_DATA = 0x2 - RLIMIT_FSIZE = 0x1 - RLIMIT_MEMLOCK = 0x6 - RLIMIT_NOFILE = 0x8 - RLIMIT_NPROC = 0x7 - RLIMIT_RSS = 0x5 - RLIMIT_STACK = 0x3 - RLIM_INFINITY = 0x7fffffffffffffff - RTAX_AUTHOR = 0x6 - RTAX_BRD = 0x7 - RTAX_DST = 0x0 - RTAX_GATEWAY = 0x1 - RTAX_GENMASK = 0x3 - RTAX_IFA = 0x5 - RTAX_IFP = 0x4 - RTAX_MAX = 0x8 - RTAX_NETMASK = 0x2 - RTA_AUTHOR = 0x40 - RTA_BRD = 0x80 - RTA_DST = 0x1 - RTA_GATEWAY = 0x2 - RTA_GENMASK = 0x8 - RTA_IFA = 0x20 - RTA_IFP = 0x10 - RTA_NETMASK = 0x4 - RTF_BLACKHOLE = 0x1000 - RTF_BROADCAST = 0x400000 - RTF_CLONING = 0x100 - RTF_CONDEMNED = 0x2000000 - RTF_DEAD = 0x20000000 - RTF_DELCLONE = 0x80 - RTF_DONE = 0x40 - RTF_DYNAMIC = 0x10 - RTF_GATEWAY = 0x2 - RTF_GLOBAL = 0x40000000 - RTF_HOST = 0x4 - RTF_IFREF = 0x4000000 - RTF_IFSCOPE = 0x1000000 - RTF_LLDATA = 0x400 - RTF_LLINFO = 0x400 - RTF_LOCAL = 0x200000 - RTF_MODIFIED = 0x20 - RTF_MULTICAST = 0x800000 - RTF_NOIFREF = 0x2000 - RTF_PINNED = 0x100000 - RTF_PRCLONING = 0x10000 - RTF_PROTO1 = 0x8000 - RTF_PROTO2 = 0x4000 - RTF_PROTO3 = 0x40000 - RTF_PROXY = 0x8000000 - RTF_REJECT = 0x8 - RTF_ROUTER = 0x10000000 - RTF_STATIC = 0x800 - RTF_UP = 0x1 - RTF_WASCLONED = 0x20000 - RTF_XRESOLVE = 0x200 - RTM_ADD = 0x1 - RTM_CHANGE = 0x3 - RTM_DELADDR = 0xd - RTM_DELETE = 0x2 - RTM_DELMADDR = 0x10 - RTM_GET = 0x4 - RTM_GET2 = 0x14 - RTM_IFINFO = 0xe - RTM_IFINFO2 = 0x12 - RTM_LOCK = 0x8 - RTM_LOSING = 0x5 - RTM_MISS = 0x7 - RTM_NEWADDR = 0xc - RTM_NEWMADDR = 0xf - RTM_NEWMADDR2 = 0x13 - RTM_OLDADD = 0x9 - RTM_OLDDEL = 0xa - RTM_REDIRECT = 0x6 - RTM_RESOLVE = 0xb - RTM_RTTUNIT = 0xf4240 - RTM_VERSION = 0x5 - RTV_EXPIRE = 0x4 - RTV_HOPCOUNT = 0x2 - RTV_MTU = 0x1 - RTV_RPIPE = 0x8 - RTV_RTT = 0x40 - RTV_RTTVAR = 0x80 - RTV_SPIPE = 0x10 - RTV_SSTHRESH = 0x20 - RUSAGE_CHILDREN = -0x1 - RUSAGE_SELF = 0x0 - SCM_CREDS = 0x3 - SCM_RIGHTS = 0x1 - SCM_TIMESTAMP = 0x2 - SCM_TIMESTAMP_MONOTONIC = 0x4 - SEEK_CUR = 0x1 - SEEK_DATA = 0x4 - SEEK_END = 0x2 - SEEK_HOLE = 0x3 - SEEK_SET = 0x0 - SHUT_RD = 0x0 - SHUT_RDWR = 0x2 - SHUT_WR = 0x1 - SIOCADDMULTI = 0x80206931 - SIOCAIFADDR = 0x8040691a - SIOCARPIPLL = 0xc0206928 - SIOCATMARK = 0x40047307 - SIOCAUTOADDR = 0xc0206926 - SIOCAUTONETMASK = 0x80206927 - SIOCDELMULTI = 0x80206932 - SIOCDIFADDR = 0x80206919 - SIOCDIFPHYADDR = 0x80206941 - SIOCGDRVSPEC = 0xc028697b - SIOCGETVLAN = 0xc020697f - SIOCGHIWAT = 0x40047301 - SIOCGIF6LOWPAN = 0xc02069c5 - SIOCGIFADDR = 0xc0206921 - SIOCGIFALTMTU = 0xc0206948 - SIOCGIFASYNCMAP = 0xc020697c - SIOCGIFBOND = 0xc0206947 - SIOCGIFBRDADDR = 0xc0206923 - SIOCGIFCAP = 0xc020695b - SIOCGIFCONF = 0xc00c6924 - SIOCGIFDEVMTU = 0xc0206944 - SIOCGIFDSTADDR = 0xc0206922 - SIOCGIFFLAGS = 0xc0206911 - SIOCGIFFUNCTIONALTYPE = 0xc02069ad - SIOCGIFGENERIC = 0xc020693a - SIOCGIFKPI = 0xc0206987 - SIOCGIFMAC = 0xc0206982 - SIOCGIFMEDIA = 0xc02c6938 - SIOCGIFMETRIC = 0xc0206917 - SIOCGIFMTU = 0xc0206933 - SIOCGIFNETMASK = 0xc0206925 - SIOCGIFPDSTADDR = 0xc0206940 - SIOCGIFPHYS = 0xc0206935 - SIOCGIFPSRCADDR = 0xc020693f - SIOCGIFSTATUS = 0xc331693d - SIOCGIFVLAN = 0xc020697f - SIOCGIFWAKEFLAGS = 0xc0206988 - SIOCGIFXMEDIA = 0xc02c6948 - SIOCGLOWAT = 0x40047303 - SIOCGPGRP = 0x40047309 - SIOCIFCREATE = 0xc0206978 - SIOCIFCREATE2 = 0xc020697a - SIOCIFDESTROY = 0x80206979 - SIOCIFGCLONERS = 0xc0106981 - SIOCRSLVMULTI = 0xc010693b - SIOCSDRVSPEC = 0x8028697b - SIOCSETVLAN = 0x8020697e - SIOCSHIWAT = 0x80047300 - SIOCSIF6LOWPAN = 0x802069c4 - SIOCSIFADDR = 0x8020690c - SIOCSIFALTMTU = 0x80206945 - SIOCSIFASYNCMAP = 0x8020697d - SIOCSIFBOND = 0x80206946 - SIOCSIFBRDADDR = 0x80206913 - SIOCSIFCAP = 0x8020695a - SIOCSIFDSTADDR = 0x8020690e - SIOCSIFFLAGS = 0x80206910 - SIOCSIFGENERIC = 0x80206939 - SIOCSIFKPI = 0x80206986 - SIOCSIFLLADDR = 0x8020693c - SIOCSIFMAC = 0x80206983 - SIOCSIFMEDIA = 0xc0206937 - SIOCSIFMETRIC = 0x80206918 - SIOCSIFMTU = 0x80206934 - SIOCSIFNETMASK = 0x80206916 - SIOCSIFPHYADDR = 0x8040693e - SIOCSIFPHYS = 0x80206936 - SIOCSIFVLAN = 0x8020697e - SIOCSLOWAT = 0x80047302 - SIOCSPGRP = 0x80047308 - SOCK_DGRAM = 0x2 - SOCK_MAXADDRLEN = 0xff - SOCK_RAW = 0x3 - SOCK_RDM = 0x4 - SOCK_SEQPACKET = 0x5 - SOCK_STREAM = 0x1 - SOL_LOCAL = 0x0 - SOL_SOCKET = 0xffff - SOMAXCONN = 0x80 - SO_ACCEPTCONN = 0x2 - SO_BROADCAST = 0x20 - SO_DEBUG = 0x1 - SO_DONTROUTE = 0x10 - SO_DONTTRUNC = 0x2000 - SO_ERROR = 0x1007 - SO_KEEPALIVE = 0x8 - SO_LABEL = 0x1010 - SO_LINGER = 0x80 - SO_LINGER_SEC = 0x1080 - SO_NETSVC_MARKING_LEVEL = 0x1119 - SO_NET_SERVICE_TYPE = 0x1116 - SO_NKE = 0x1021 - SO_NOADDRERR = 0x1023 - SO_NOSIGPIPE = 0x1022 - SO_NOTIFYCONFLICT = 0x1026 - SO_NP_EXTENSIONS = 0x1083 - SO_NREAD = 0x1020 - SO_NUMRCVPKT = 0x1112 - SO_NWRITE = 0x1024 - SO_OOBINLINE = 0x100 - SO_PEERLABEL = 0x1011 - SO_RANDOMPORT = 0x1082 - SO_RCVBUF = 0x1002 - SO_RCVLOWAT = 0x1004 - SO_RCVTIMEO = 0x1006 - SO_REUSEADDR = 0x4 - SO_REUSEPORT = 0x200 - SO_REUSESHAREUID = 0x1025 - SO_SNDBUF = 0x1001 - SO_SNDLOWAT = 0x1003 - SO_SNDTIMEO = 0x1005 - SO_TIMESTAMP = 0x400 - SO_TIMESTAMP_MONOTONIC = 0x800 - SO_TYPE = 0x1008 - SO_UPCALLCLOSEWAIT = 0x1027 - SO_USELOOPBACK = 0x40 - SO_WANTMORE = 0x4000 - SO_WANTOOBFLAG = 0x8000 - S_IEXEC = 0x40 - S_IFBLK = 0x6000 - S_IFCHR = 0x2000 - S_IFDIR = 0x4000 - S_IFIFO = 0x1000 - S_IFLNK = 0xa000 - S_IFMT = 0xf000 - S_IFREG = 0x8000 - S_IFSOCK = 0xc000 - S_IFWHT = 0xe000 - S_IREAD = 0x100 - S_IRGRP = 0x20 - S_IROTH = 0x4 - S_IRUSR = 0x100 - S_IRWXG = 0x38 - S_IRWXO = 0x7 - S_IRWXU = 0x1c0 - S_ISGID = 0x400 - S_ISTXT = 0x200 - S_ISUID = 0x800 - S_ISVTX = 0x200 - S_IWGRP = 0x10 - S_IWOTH = 0x2 - S_IWRITE = 0x80 - S_IWUSR = 0x80 - S_IXGRP = 0x8 - S_IXOTH = 0x1 - S_IXUSR = 0x40 - TAB0 = 0x0 - TAB1 = 0x400 - TAB2 = 0x800 - TAB3 = 0x4 - TABDLY = 0xc04 - TCIFLUSH = 0x1 - TCIOFF = 0x3 - TCIOFLUSH = 0x3 - TCION = 0x4 - TCOFLUSH = 0x2 - TCOOFF = 0x1 - TCOON = 0x2 - TCP_CONNECTIONTIMEOUT = 0x20 - TCP_CONNECTION_INFO = 0x106 - TCP_ENABLE_ECN = 0x104 - TCP_FASTOPEN = 0x105 - TCP_KEEPALIVE = 0x10 - TCP_KEEPCNT = 0x102 - TCP_KEEPINTVL = 0x101 - TCP_MAXHLEN = 0x3c - TCP_MAXOLEN = 0x28 - TCP_MAXSEG = 0x2 - TCP_MAXWIN = 0xffff - TCP_MAX_SACK = 0x4 - TCP_MAX_WINSHIFT = 0xe - TCP_MINMSS = 0xd8 - TCP_MSS = 0x200 - TCP_NODELAY = 0x1 - TCP_NOOPT = 0x8 - TCP_NOPUSH = 0x4 - TCP_NOTSENT_LOWAT = 0x201 - TCP_RXT_CONNDROPTIME = 0x80 - TCP_RXT_FINDROP = 0x100 - TCP_SENDMOREACKS = 0x103 - TCSAFLUSH = 0x2 - TIOCCBRK = 0x2000747a - TIOCCDTR = 0x20007478 - TIOCCONS = 0x80047462 - TIOCDCDTIMESTAMP = 0x40107458 - TIOCDRAIN = 0x2000745e - TIOCDSIMICROCODE = 0x20007455 - TIOCEXCL = 0x2000740d - TIOCEXT = 0x80047460 - TIOCFLUSH = 0x80047410 - TIOCGDRAINWAIT = 0x40047456 - TIOCGETA = 0x40487413 - TIOCGETD = 0x4004741a - TIOCGPGRP = 0x40047477 - TIOCGWINSZ = 0x40087468 - TIOCIXOFF = 0x20007480 - TIOCIXON = 0x20007481 - TIOCMBIC = 0x8004746b - TIOCMBIS = 0x8004746c - TIOCMGDTRWAIT = 0x4004745a - TIOCMGET = 0x4004746a - TIOCMODG = 0x40047403 - TIOCMODS = 0x80047404 - TIOCMSDTRWAIT = 0x8004745b - TIOCMSET = 0x8004746d - TIOCM_CAR = 0x40 - TIOCM_CD = 0x40 - TIOCM_CTS = 0x20 - TIOCM_DSR = 0x100 - TIOCM_DTR = 0x2 - TIOCM_LE = 0x1 - TIOCM_RI = 0x80 - TIOCM_RNG = 0x80 - TIOCM_RTS = 0x4 - TIOCM_SR = 0x10 - TIOCM_ST = 0x8 - TIOCNOTTY = 0x20007471 - TIOCNXCL = 0x2000740e - TIOCOUTQ = 0x40047473 - TIOCPKT = 0x80047470 - TIOCPKT_DATA = 0x0 - TIOCPKT_DOSTOP = 0x20 - TIOCPKT_FLUSHREAD = 0x1 - TIOCPKT_FLUSHWRITE = 0x2 - TIOCPKT_IOCTL = 0x40 - TIOCPKT_NOSTOP = 0x10 - TIOCPKT_START = 0x8 - TIOCPKT_STOP = 0x4 - TIOCPTYGNAME = 0x40807453 - TIOCPTYGRANT = 0x20007454 - TIOCPTYUNLK = 0x20007452 - TIOCREMOTE = 0x80047469 - TIOCSBRK = 0x2000747b - TIOCSCONS = 0x20007463 - TIOCSCTTY = 0x20007461 - TIOCSDRAINWAIT = 0x80047457 - TIOCSDTR = 0x20007479 - TIOCSETA = 0x80487414 - TIOCSETAF = 0x80487416 - TIOCSETAW = 0x80487415 - TIOCSETD = 0x8004741b - TIOCSIG = 0x2000745f - TIOCSPGRP = 0x80047476 - TIOCSTART = 0x2000746e - TIOCSTAT = 0x20007465 - TIOCSTI = 0x80017472 - TIOCSTOP = 0x2000746f - TIOCSWINSZ = 0x80087467 - TIOCTIMESTAMP = 0x40107459 - TIOCUCNTL = 0x80047466 - TOSTOP = 0x400000 - VDISCARD = 0xf - VDSUSP = 0xb - VEOF = 0x0 - VEOL = 0x1 - VEOL2 = 0x2 - VERASE = 0x3 - VINTR = 0x8 - VKILL = 0x5 - VLNEXT = 0xe - VMIN = 0x10 - VM_LOADAVG = 0x2 - VM_MACHFACTOR = 0x4 - VM_MAXID = 0x6 - VM_METER = 0x1 - VM_SWAPUSAGE = 0x5 - VQUIT = 0x9 - VREPRINT = 0x6 - VSTART = 0xc - VSTATUS = 0x12 - VSTOP = 0xd - VSUSP = 0xa - VT0 = 0x0 - VT1 = 0x10000 - VTDLY = 0x10000 - VTIME = 0x11 - VWERASE = 0x4 - WCONTINUED = 0x10 - WCOREFLAG = 0x80 - WEXITED = 0x4 - WNOHANG = 0x1 - WNOWAIT = 0x20 - WORDSIZE = 0x40 - WSTOPPED = 0x8 - WUNTRACED = 0x2 - XATTR_CREATE = 0x2 - XATTR_NODEFAULT = 0x10 - XATTR_NOFOLLOW = 0x1 - XATTR_NOSECURITY = 0x8 - XATTR_REPLACE = 0x4 - XATTR_SHOWCOMPRESSION = 0x20 + AF_APPLETALK = 0x10 + AF_CCITT = 0xa + AF_CHAOS = 0x5 + AF_CNT = 0x15 + AF_COIP = 0x14 + AF_DATAKIT = 0x9 + AF_DECnet = 0xc + AF_DLI = 0xd + AF_E164 = 0x1c + AF_ECMA = 0x8 + AF_HYLINK = 0xf + AF_IEEE80211 = 0x25 + AF_IMPLINK = 0x3 + AF_INET = 0x2 + AF_INET6 = 0x1e + AF_IPX = 0x17 + AF_ISDN = 0x1c + AF_ISO = 0x7 + AF_LAT = 0xe + AF_LINK = 0x12 + AF_LOCAL = 0x1 + AF_MAX = 0x29 + AF_NATM = 0x1f + AF_NDRV = 0x1b + AF_NETBIOS = 0x21 + AF_NS = 0x6 + AF_OSI = 0x7 + AF_PPP = 0x22 + AF_PUP = 0x4 + AF_RESERVED_36 = 0x24 + AF_ROUTE = 0x11 + AF_SIP = 0x18 + AF_SNA = 0xb + AF_SYSTEM = 0x20 + AF_SYS_CONTROL = 0x2 + AF_UNIX = 0x1 + AF_UNSPEC = 0x0 + AF_UTUN = 0x26 + AF_VSOCK = 0x28 + ALTWERASE = 0x200 + ATTR_BIT_MAP_COUNT = 0x5 + ATTR_CMN_ACCESSMASK = 0x20000 + ATTR_CMN_ACCTIME = 0x1000 + ATTR_CMN_ADDEDTIME = 0x10000000 + ATTR_CMN_BKUPTIME = 0x2000 + ATTR_CMN_CHGTIME = 0x800 + ATTR_CMN_CRTIME = 0x200 + ATTR_CMN_DATA_PROTECT_FLAGS = 0x40000000 + ATTR_CMN_DEVID = 0x2 + ATTR_CMN_DOCUMENT_ID = 0x100000 + ATTR_CMN_ERROR = 0x20000000 + ATTR_CMN_EXTENDED_SECURITY = 0x400000 + ATTR_CMN_FILEID = 0x2000000 + ATTR_CMN_FLAGS = 0x40000 + ATTR_CMN_FNDRINFO = 0x4000 + ATTR_CMN_FSID = 0x4 + ATTR_CMN_FULLPATH = 0x8000000 + ATTR_CMN_GEN_COUNT = 0x80000 + ATTR_CMN_GRPID = 0x10000 + ATTR_CMN_GRPUUID = 0x1000000 + ATTR_CMN_MODTIME = 0x400 + ATTR_CMN_NAME = 0x1 + ATTR_CMN_NAMEDATTRCOUNT = 0x80000 + ATTR_CMN_NAMEDATTRLIST = 0x100000 + ATTR_CMN_OBJID = 0x20 + ATTR_CMN_OBJPERMANENTID = 0x40 + ATTR_CMN_OBJTAG = 0x10 + ATTR_CMN_OBJTYPE = 0x8 + ATTR_CMN_OWNERID = 0x8000 + ATTR_CMN_PARENTID = 0x4000000 + ATTR_CMN_PAROBJID = 0x80 + ATTR_CMN_RETURNED_ATTRS = 0x80000000 + ATTR_CMN_SCRIPT = 0x100 + ATTR_CMN_SETMASK = 0x51c7ff00 + ATTR_CMN_USERACCESS = 0x200000 + ATTR_CMN_UUID = 0x800000 + ATTR_CMN_VALIDMASK = 0xffffffff + ATTR_CMN_VOLSETMASK = 0x6700 + ATTR_FILE_ALLOCSIZE = 0x4 + ATTR_FILE_CLUMPSIZE = 0x10 + ATTR_FILE_DATAALLOCSIZE = 0x400 + ATTR_FILE_DATAEXTENTS = 0x800 + ATTR_FILE_DATALENGTH = 0x200 + ATTR_FILE_DEVTYPE = 0x20 + ATTR_FILE_FILETYPE = 0x40 + ATTR_FILE_FORKCOUNT = 0x80 + ATTR_FILE_FORKLIST = 0x100 + ATTR_FILE_IOBLOCKSIZE = 0x8 + ATTR_FILE_LINKCOUNT = 0x1 + ATTR_FILE_RSRCALLOCSIZE = 0x2000 + ATTR_FILE_RSRCEXTENTS = 0x4000 + ATTR_FILE_RSRCLENGTH = 0x1000 + ATTR_FILE_SETMASK = 0x20 + ATTR_FILE_TOTALSIZE = 0x2 + ATTR_FILE_VALIDMASK = 0x37ff + ATTR_VOL_ALLOCATIONCLUMP = 0x40 + ATTR_VOL_ATTRIBUTES = 0x40000000 + ATTR_VOL_CAPABILITIES = 0x20000 + ATTR_VOL_DIRCOUNT = 0x400 + ATTR_VOL_ENCODINGSUSED = 0x10000 + ATTR_VOL_FILECOUNT = 0x200 + ATTR_VOL_FSTYPE = 0x1 + ATTR_VOL_INFO = 0x80000000 + ATTR_VOL_IOBLOCKSIZE = 0x80 + ATTR_VOL_MAXOBJCOUNT = 0x800 + ATTR_VOL_MINALLOCATION = 0x20 + ATTR_VOL_MOUNTEDDEVICE = 0x8000 + ATTR_VOL_MOUNTFLAGS = 0x4000 + ATTR_VOL_MOUNTPOINT = 0x1000 + ATTR_VOL_NAME = 0x2000 + ATTR_VOL_OBJCOUNT = 0x100 + ATTR_VOL_QUOTA_SIZE = 0x10000000 + ATTR_VOL_RESERVED_SIZE = 0x20000000 + ATTR_VOL_SETMASK = 0x80002000 + ATTR_VOL_SIGNATURE = 0x2 + ATTR_VOL_SIZE = 0x4 + ATTR_VOL_SPACEAVAIL = 0x10 + ATTR_VOL_SPACEFREE = 0x8 + ATTR_VOL_SPACEUSED = 0x800000 + ATTR_VOL_UUID = 0x40000 + ATTR_VOL_VALIDMASK = 0xf087ffff + B0 = 0x0 + B110 = 0x6e + B115200 = 0x1c200 + B1200 = 0x4b0 + B134 = 0x86 + B14400 = 0x3840 + B150 = 0x96 + B1800 = 0x708 + B19200 = 0x4b00 + B200 = 0xc8 + B230400 = 0x38400 + B2400 = 0x960 + B28800 = 0x7080 + B300 = 0x12c + B38400 = 0x9600 + B4800 = 0x12c0 + B50 = 0x32 + B57600 = 0xe100 + B600 = 0x258 + B7200 = 0x1c20 + B75 = 0x4b + B76800 = 0x12c00 + B9600 = 0x2580 + BIOCFLUSH = 0x20004268 + BIOCGBLEN = 0x40044266 + BIOCGDLT = 0x4004426a + BIOCGDLTLIST = 0xc00c4279 + BIOCGETIF = 0x4020426b + BIOCGHDRCMPLT = 0x40044274 + BIOCGRSIG = 0x40044272 + BIOCGRTIMEOUT = 0x4010426e + BIOCGSEESENT = 0x40044276 + BIOCGSTATS = 0x4008426f + BIOCIMMEDIATE = 0x80044270 + BIOCPROMISC = 0x20004269 + BIOCSBLEN = 0xc0044266 + BIOCSDLT = 0x80044278 + BIOCSETF = 0x80104267 + BIOCSETFNR = 0x8010427e + BIOCSETIF = 0x8020426c + BIOCSHDRCMPLT = 0x80044275 + BIOCSRSIG = 0x80044273 + BIOCSRTIMEOUT = 0x8010426d + BIOCSSEESENT = 0x80044277 + BIOCVERSION = 0x40044271 + BPF_A = 0x10 + BPF_ABS = 0x20 + BPF_ADD = 0x0 + BPF_ALIGNMENT = 0x4 + BPF_ALU = 0x4 + BPF_AND = 0x50 + BPF_B = 0x10 + BPF_DIV = 0x30 + BPF_H = 0x8 + BPF_IMM = 0x0 + BPF_IND = 0x40 + BPF_JA = 0x0 + BPF_JEQ = 0x10 + BPF_JGE = 0x30 + BPF_JGT = 0x20 + BPF_JMP = 0x5 + BPF_JSET = 0x40 + BPF_K = 0x0 + BPF_LD = 0x0 + BPF_LDX = 0x1 + BPF_LEN = 0x80 + BPF_LSH = 0x60 + BPF_MAJOR_VERSION = 0x1 + BPF_MAXBUFSIZE = 0x80000 + BPF_MAXINSNS = 0x200 + BPF_MEM = 0x60 + BPF_MEMWORDS = 0x10 + BPF_MINBUFSIZE = 0x20 + BPF_MINOR_VERSION = 0x1 + BPF_MISC = 0x7 + BPF_MSH = 0xa0 + BPF_MUL = 0x20 + BPF_NEG = 0x80 + BPF_OR = 0x40 + BPF_RELEASE = 0x30bb6 + BPF_RET = 0x6 + BPF_RSH = 0x70 + BPF_ST = 0x2 + BPF_STX = 0x3 + BPF_SUB = 0x10 + BPF_TAX = 0x0 + BPF_TXA = 0x80 + BPF_W = 0x0 + BPF_X = 0x8 + BRKINT = 0x2 + BS0 = 0x0 + BS1 = 0x8000 + BSDLY = 0x8000 + CFLUSH = 0xf + CLOCAL = 0x8000 + CLOCK_MONOTONIC = 0x6 + CLOCK_MONOTONIC_RAW = 0x4 + CLOCK_MONOTONIC_RAW_APPROX = 0x5 + CLOCK_PROCESS_CPUTIME_ID = 0xc + CLOCK_REALTIME = 0x0 + CLOCK_THREAD_CPUTIME_ID = 0x10 + CLOCK_UPTIME_RAW = 0x8 + CLOCK_UPTIME_RAW_APPROX = 0x9 + CLONE_NOFOLLOW = 0x1 + CLONE_NOOWNERCOPY = 0x2 + CR0 = 0x0 + CR1 = 0x1000 + CR2 = 0x2000 + CR3 = 0x3000 + CRDLY = 0x3000 + CREAD = 0x800 + CRTSCTS = 0x30000 + CS5 = 0x0 + CS6 = 0x100 + CS7 = 0x200 + CS8 = 0x300 + CSIZE = 0x300 + CSTART = 0x11 + CSTATUS = 0x14 + CSTOP = 0x13 + CSTOPB = 0x400 + CSUSP = 0x1a + CTLIOCGINFO = 0xc0644e03 + CTL_HW = 0x6 + CTL_KERN = 0x1 + CTL_MAXNAME = 0xc + CTL_NET = 0x4 + DLT_A429 = 0xb8 + DLT_A653_ICM = 0xb9 + DLT_AIRONET_HEADER = 0x78 + DLT_AOS = 0xde + DLT_APPLE_IP_OVER_IEEE1394 = 0x8a + DLT_ARCNET = 0x7 + DLT_ARCNET_LINUX = 0x81 + DLT_ATM_CLIP = 0x13 + DLT_ATM_RFC1483 = 0xb + DLT_AURORA = 0x7e + DLT_AX25 = 0x3 + DLT_AX25_KISS = 0xca + DLT_BACNET_MS_TP = 0xa5 + DLT_BLUETOOTH_HCI_H4 = 0xbb + DLT_BLUETOOTH_HCI_H4_WITH_PHDR = 0xc9 + DLT_CAN20B = 0xbe + DLT_CAN_SOCKETCAN = 0xe3 + DLT_CHAOS = 0x5 + DLT_CHDLC = 0x68 + DLT_CISCO_IOS = 0x76 + DLT_C_HDLC = 0x68 + DLT_C_HDLC_WITH_DIR = 0xcd + DLT_DBUS = 0xe7 + DLT_DECT = 0xdd + DLT_DOCSIS = 0x8f + DLT_DVB_CI = 0xeb + DLT_ECONET = 0x73 + DLT_EN10MB = 0x1 + DLT_EN3MB = 0x2 + DLT_ENC = 0x6d + DLT_ERF = 0xc5 + DLT_ERF_ETH = 0xaf + DLT_ERF_POS = 0xb0 + DLT_FC_2 = 0xe0 + DLT_FC_2_WITH_FRAME_DELIMS = 0xe1 + DLT_FDDI = 0xa + DLT_FLEXRAY = 0xd2 + DLT_FRELAY = 0x6b + DLT_FRELAY_WITH_DIR = 0xce + DLT_GCOM_SERIAL = 0xad + DLT_GCOM_T1E1 = 0xac + DLT_GPF_F = 0xab + DLT_GPF_T = 0xaa + DLT_GPRS_LLC = 0xa9 + DLT_GSMTAP_ABIS = 0xda + DLT_GSMTAP_UM = 0xd9 + DLT_HHDLC = 0x79 + DLT_IBM_SN = 0x92 + DLT_IBM_SP = 0x91 + DLT_IEEE802 = 0x6 + DLT_IEEE802_11 = 0x69 + DLT_IEEE802_11_RADIO = 0x7f + DLT_IEEE802_11_RADIO_AVS = 0xa3 + DLT_IEEE802_15_4 = 0xc3 + DLT_IEEE802_15_4_LINUX = 0xbf + DLT_IEEE802_15_4_NOFCS = 0xe6 + DLT_IEEE802_15_4_NONASK_PHY = 0xd7 + DLT_IEEE802_16_MAC_CPS = 0xbc + DLT_IEEE802_16_MAC_CPS_RADIO = 0xc1 + DLT_IPFILTER = 0x74 + DLT_IPMB = 0xc7 + DLT_IPMB_LINUX = 0xd1 + DLT_IPNET = 0xe2 + DLT_IPOIB = 0xf2 + DLT_IPV4 = 0xe4 + DLT_IPV6 = 0xe5 + DLT_IP_OVER_FC = 0x7a + DLT_JUNIPER_ATM1 = 0x89 + DLT_JUNIPER_ATM2 = 0x87 + DLT_JUNIPER_ATM_CEMIC = 0xee + DLT_JUNIPER_CHDLC = 0xb5 + DLT_JUNIPER_ES = 0x84 + DLT_JUNIPER_ETHER = 0xb2 + DLT_JUNIPER_FIBRECHANNEL = 0xea + DLT_JUNIPER_FRELAY = 0xb4 + DLT_JUNIPER_GGSN = 0x85 + DLT_JUNIPER_ISM = 0xc2 + DLT_JUNIPER_MFR = 0x86 + DLT_JUNIPER_MLFR = 0x83 + DLT_JUNIPER_MLPPP = 0x82 + DLT_JUNIPER_MONITOR = 0xa4 + DLT_JUNIPER_PIC_PEER = 0xae + DLT_JUNIPER_PPP = 0xb3 + DLT_JUNIPER_PPPOE = 0xa7 + DLT_JUNIPER_PPPOE_ATM = 0xa8 + DLT_JUNIPER_SERVICES = 0x88 + DLT_JUNIPER_SRX_E2E = 0xe9 + DLT_JUNIPER_ST = 0xc8 + DLT_JUNIPER_VP = 0xb7 + DLT_JUNIPER_VS = 0xe8 + DLT_LAPB_WITH_DIR = 0xcf + DLT_LAPD = 0xcb + DLT_LIN = 0xd4 + DLT_LINUX_EVDEV = 0xd8 + DLT_LINUX_IRDA = 0x90 + DLT_LINUX_LAPD = 0xb1 + DLT_LINUX_PPP_WITHDIRECTION = 0xa6 + DLT_LINUX_SLL = 0x71 + DLT_LOOP = 0x6c + DLT_LTALK = 0x72 + DLT_MATCHING_MAX = 0x10a + DLT_MATCHING_MIN = 0x68 + DLT_MFR = 0xb6 + DLT_MOST = 0xd3 + DLT_MPEG_2_TS = 0xf3 + DLT_MPLS = 0xdb + DLT_MTP2 = 0x8c + DLT_MTP2_WITH_PHDR = 0x8b + DLT_MTP3 = 0x8d + DLT_MUX27010 = 0xec + DLT_NETANALYZER = 0xf0 + DLT_NETANALYZER_TRANSPARENT = 0xf1 + DLT_NFC_LLCP = 0xf5 + DLT_NFLOG = 0xef + DLT_NG40 = 0xf4 + DLT_NULL = 0x0 + DLT_PCI_EXP = 0x7d + DLT_PFLOG = 0x75 + DLT_PFSYNC = 0x12 + DLT_PPI = 0xc0 + DLT_PPP = 0x9 + DLT_PPP_BSDOS = 0x10 + DLT_PPP_ETHER = 0x33 + DLT_PPP_PPPD = 0xa6 + DLT_PPP_SERIAL = 0x32 + DLT_PPP_WITH_DIR = 0xcc + DLT_PPP_WITH_DIRECTION = 0xa6 + DLT_PRISM_HEADER = 0x77 + DLT_PRONET = 0x4 + DLT_RAIF1 = 0xc6 + DLT_RAW = 0xc + DLT_RIO = 0x7c + DLT_SCCP = 0x8e + DLT_SITA = 0xc4 + DLT_SLIP = 0x8 + DLT_SLIP_BSDOS = 0xf + DLT_STANAG_5066_D_PDU = 0xed + DLT_SUNATM = 0x7b + DLT_SYMANTEC_FIREWALL = 0x63 + DLT_TZSP = 0x80 + DLT_USB = 0xba + DLT_USB_DARWIN = 0x10a + DLT_USB_LINUX = 0xbd + DLT_USB_LINUX_MMAPPED = 0xdc + DLT_USER0 = 0x93 + DLT_USER1 = 0x94 + DLT_USER10 = 0x9d + DLT_USER11 = 0x9e + DLT_USER12 = 0x9f + DLT_USER13 = 0xa0 + DLT_USER14 = 0xa1 + DLT_USER15 = 0xa2 + DLT_USER2 = 0x95 + DLT_USER3 = 0x96 + DLT_USER4 = 0x97 + DLT_USER5 = 0x98 + DLT_USER6 = 0x99 + DLT_USER7 = 0x9a + DLT_USER8 = 0x9b + DLT_USER9 = 0x9c + DLT_WIHART = 0xdf + DLT_X2E_SERIAL = 0xd5 + DLT_X2E_XORAYA = 0xd6 + DT_BLK = 0x6 + DT_CHR = 0x2 + DT_DIR = 0x4 + DT_FIFO = 0x1 + DT_LNK = 0xa + DT_REG = 0x8 + DT_SOCK = 0xc + DT_UNKNOWN = 0x0 + DT_WHT = 0xe + ECHO = 0x8 + ECHOCTL = 0x40 + ECHOE = 0x2 + ECHOK = 0x4 + ECHOKE = 0x1 + ECHONL = 0x10 + ECHOPRT = 0x20 + EVFILT_AIO = -0x3 + EVFILT_EXCEPT = -0xf + EVFILT_FS = -0x9 + EVFILT_MACHPORT = -0x8 + EVFILT_PROC = -0x5 + EVFILT_READ = -0x1 + EVFILT_SIGNAL = -0x6 + EVFILT_SYSCOUNT = 0x11 + EVFILT_THREADMARKER = 0x11 + EVFILT_TIMER = -0x7 + EVFILT_USER = -0xa + EVFILT_VM = -0xc + EVFILT_VNODE = -0x4 + EVFILT_WRITE = -0x2 + EV_ADD = 0x1 + EV_CLEAR = 0x20 + EV_DELETE = 0x2 + EV_DISABLE = 0x8 + EV_DISPATCH = 0x80 + EV_DISPATCH2 = 0x180 + EV_ENABLE = 0x4 + EV_EOF = 0x8000 + EV_ERROR = 0x4000 + EV_FLAG0 = 0x1000 + EV_FLAG1 = 0x2000 + EV_ONESHOT = 0x10 + EV_OOBAND = 0x2000 + EV_POLL = 0x1000 + EV_RECEIPT = 0x40 + EV_SYSFLAGS = 0xf000 + EV_UDATA_SPECIFIC = 0x100 + EV_VANISHED = 0x200 + EXTA = 0x4b00 + EXTB = 0x9600 + EXTPROC = 0x800 + FD_CLOEXEC = 0x1 + FD_SETSIZE = 0x400 + FF0 = 0x0 + FF1 = 0x4000 + FFDLY = 0x4000 + FLUSHO = 0x800000 + FSOPT_ATTR_CMN_EXTENDED = 0x20 + FSOPT_NOFOLLOW = 0x1 + FSOPT_NOINMEMUPDATE = 0x2 + FSOPT_PACK_INVAL_ATTRS = 0x8 + FSOPT_REPORT_FULLSIZE = 0x4 + FSOPT_RETURN_REALDEV = 0x200 + F_ADDFILESIGS = 0x3d + F_ADDFILESIGS_FOR_DYLD_SIM = 0x53 + F_ADDFILESIGS_INFO = 0x67 + F_ADDFILESIGS_RETURN = 0x61 + F_ADDFILESUPPL = 0x68 + F_ADDSIGS = 0x3b + F_ALLOCATEALL = 0x4 + F_ALLOCATECONTIG = 0x2 + F_BARRIERFSYNC = 0x55 + F_CHECK_LV = 0x62 + F_CHKCLEAN = 0x29 + F_DUPFD = 0x0 + F_DUPFD_CLOEXEC = 0x43 + F_FINDSIGS = 0x4e + F_FLUSH_DATA = 0x28 + F_FREEZE_FS = 0x35 + F_FULLFSYNC = 0x33 + F_GETCODEDIR = 0x48 + F_GETFD = 0x1 + F_GETFL = 0x3 + F_GETLK = 0x7 + F_GETLKPID = 0x42 + F_GETNOSIGPIPE = 0x4a + F_GETOWN = 0x5 + F_GETPATH = 0x32 + F_GETPATH_MTMINFO = 0x47 + F_GETPATH_NOFIRMLINK = 0x66 + F_GETPROTECTIONCLASS = 0x3f + F_GETPROTECTIONLEVEL = 0x4d + F_GETSIGSINFO = 0x69 + F_GLOBAL_NOCACHE = 0x37 + F_LOG2PHYS = 0x31 + F_LOG2PHYS_EXT = 0x41 + F_NOCACHE = 0x30 + F_NODIRECT = 0x3e + F_OK = 0x0 + F_PATHPKG_CHECK = 0x34 + F_PEOFPOSMODE = 0x3 + F_PREALLOCATE = 0x2a + F_PUNCHHOLE = 0x63 + F_RDADVISE = 0x2c + F_RDAHEAD = 0x2d + F_RDLCK = 0x1 + F_SETBACKINGSTORE = 0x46 + F_SETFD = 0x2 + F_SETFL = 0x4 + F_SETLK = 0x8 + F_SETLKW = 0x9 + F_SETLKWTIMEOUT = 0xa + F_SETNOSIGPIPE = 0x49 + F_SETOWN = 0x6 + F_SETPROTECTIONCLASS = 0x40 + F_SETSIZE = 0x2b + F_SINGLE_WRITER = 0x4c + F_SPECULATIVE_READ = 0x65 + F_THAW_FS = 0x36 + F_TRANSCODEKEY = 0x4b + F_TRIM_ACTIVE_FILE = 0x64 + F_UNLCK = 0x2 + F_VOLPOSMODE = 0x4 + F_WRLCK = 0x3 + HUPCL = 0x4000 + HW_MACHINE = 0x1 + ICANON = 0x100 + ICMP6_FILTER = 0x12 + ICRNL = 0x100 + IEXTEN = 0x400 + IFF_ALLMULTI = 0x200 + IFF_ALTPHYS = 0x4000 + IFF_BROADCAST = 0x2 + IFF_DEBUG = 0x4 + IFF_LINK0 = 0x1000 + IFF_LINK1 = 0x2000 + IFF_LINK2 = 0x4000 + IFF_LOOPBACK = 0x8 + IFF_MULTICAST = 0x8000 + IFF_NOARP = 0x80 + IFF_NOTRAILERS = 0x20 + IFF_OACTIVE = 0x400 + IFF_POINTOPOINT = 0x10 + IFF_PROMISC = 0x100 + IFF_RUNNING = 0x40 + IFF_SIMPLEX = 0x800 + IFF_UP = 0x1 + IFNAMSIZ = 0x10 + IFT_1822 = 0x2 + IFT_6LOWPAN = 0x40 + IFT_AAL5 = 0x31 + IFT_ARCNET = 0x23 + IFT_ARCNETPLUS = 0x24 + IFT_ATM = 0x25 + IFT_BRIDGE = 0xd1 + IFT_CARP = 0xf8 + IFT_CELLULAR = 0xff + IFT_CEPT = 0x13 + IFT_DS3 = 0x1e + IFT_ENC = 0xf4 + IFT_EON = 0x19 + IFT_ETHER = 0x6 + IFT_FAITH = 0x38 + IFT_FDDI = 0xf + IFT_FRELAY = 0x20 + IFT_FRELAYDCE = 0x2c + IFT_GIF = 0x37 + IFT_HDH1822 = 0x3 + IFT_HIPPI = 0x2f + IFT_HSSI = 0x2e + IFT_HY = 0xe + IFT_IEEE1394 = 0x90 + IFT_IEEE8023ADLAG = 0x88 + IFT_ISDNBASIC = 0x14 + IFT_ISDNPRIMARY = 0x15 + IFT_ISO88022LLC = 0x29 + IFT_ISO88023 = 0x7 + IFT_ISO88024 = 0x8 + IFT_ISO88025 = 0x9 + IFT_ISO88026 = 0xa + IFT_L2VLAN = 0x87 + IFT_LAPB = 0x10 + IFT_LOCALTALK = 0x2a + IFT_LOOP = 0x18 + IFT_MIOX25 = 0x26 + IFT_MODEM = 0x30 + IFT_NSIP = 0x1b + IFT_OTHER = 0x1 + IFT_P10 = 0xc + IFT_P80 = 0xd + IFT_PARA = 0x22 + IFT_PDP = 0xff + IFT_PFLOG = 0xf5 + IFT_PFSYNC = 0xf6 + IFT_PKTAP = 0xfe + IFT_PPP = 0x17 + IFT_PROPMUX = 0x36 + IFT_PROPVIRTUAL = 0x35 + IFT_PTPSERIAL = 0x16 + IFT_RS232 = 0x21 + IFT_SDLC = 0x11 + IFT_SIP = 0x1f + IFT_SLIP = 0x1c + IFT_SMDSDXI = 0x2b + IFT_SMDSICIP = 0x34 + IFT_SONET = 0x27 + IFT_SONETPATH = 0x32 + IFT_SONETVT = 0x33 + IFT_STARLAN = 0xb + IFT_STF = 0x39 + IFT_T1 = 0x12 + IFT_ULTRA = 0x1d + IFT_V35 = 0x2d + IFT_X25 = 0x5 + IFT_X25DDN = 0x4 + IFT_X25PLE = 0x28 + IFT_XETHER = 0x1a + IGNBRK = 0x1 + IGNCR = 0x80 + IGNPAR = 0x4 + IMAXBEL = 0x2000 + INLCR = 0x40 + INPCK = 0x10 + IN_CLASSA_HOST = 0xffffff + IN_CLASSA_MAX = 0x80 + IN_CLASSA_NET = 0xff000000 + IN_CLASSA_NSHIFT = 0x18 + IN_CLASSB_HOST = 0xffff + IN_CLASSB_MAX = 0x10000 + IN_CLASSB_NET = 0xffff0000 + IN_CLASSB_NSHIFT = 0x10 + IN_CLASSC_HOST = 0xff + IN_CLASSC_NET = 0xffffff00 + IN_CLASSC_NSHIFT = 0x8 + IN_CLASSD_HOST = 0xfffffff + IN_CLASSD_NET = 0xf0000000 + IN_CLASSD_NSHIFT = 0x1c + IN_LINKLOCALNETNUM = 0xa9fe0000 + IN_LOOPBACKNET = 0x7f + IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x400473d1 + IPPROTO_3PC = 0x22 + IPPROTO_ADFS = 0x44 + IPPROTO_AH = 0x33 + IPPROTO_AHIP = 0x3d + IPPROTO_APES = 0x63 + IPPROTO_ARGUS = 0xd + IPPROTO_AX25 = 0x5d + IPPROTO_BHA = 0x31 + IPPROTO_BLT = 0x1e + IPPROTO_BRSATMON = 0x4c + IPPROTO_CFTP = 0x3e + IPPROTO_CHAOS = 0x10 + IPPROTO_CMTP = 0x26 + IPPROTO_CPHB = 0x49 + IPPROTO_CPNX = 0x48 + IPPROTO_DDP = 0x25 + IPPROTO_DGP = 0x56 + IPPROTO_DIVERT = 0xfe + IPPROTO_DONE = 0x101 + IPPROTO_DSTOPTS = 0x3c + IPPROTO_EGP = 0x8 + IPPROTO_EMCON = 0xe + IPPROTO_ENCAP = 0x62 + IPPROTO_EON = 0x50 + IPPROTO_ESP = 0x32 + IPPROTO_ETHERIP = 0x61 + IPPROTO_FRAGMENT = 0x2c + IPPROTO_GGP = 0x3 + IPPROTO_GMTP = 0x64 + IPPROTO_GRE = 0x2f + IPPROTO_HELLO = 0x3f + IPPROTO_HMP = 0x14 + IPPROTO_HOPOPTS = 0x0 + IPPROTO_ICMP = 0x1 + IPPROTO_ICMPV6 = 0x3a + IPPROTO_IDP = 0x16 + IPPROTO_IDPR = 0x23 + IPPROTO_IDRP = 0x2d + IPPROTO_IGMP = 0x2 + IPPROTO_IGP = 0x55 + IPPROTO_IGRP = 0x58 + IPPROTO_IL = 0x28 + IPPROTO_INLSP = 0x34 + IPPROTO_INP = 0x20 + IPPROTO_IP = 0x0 + IPPROTO_IPCOMP = 0x6c + IPPROTO_IPCV = 0x47 + IPPROTO_IPEIP = 0x5e + IPPROTO_IPIP = 0x4 + IPPROTO_IPPC = 0x43 + IPPROTO_IPV4 = 0x4 + IPPROTO_IPV6 = 0x29 + IPPROTO_IRTP = 0x1c + IPPROTO_KRYPTOLAN = 0x41 + IPPROTO_LARP = 0x5b + IPPROTO_LEAF1 = 0x19 + IPPROTO_LEAF2 = 0x1a + IPPROTO_MAX = 0x100 + IPPROTO_MAXID = 0x34 + IPPROTO_MEAS = 0x13 + IPPROTO_MHRP = 0x30 + IPPROTO_MICP = 0x5f + IPPROTO_MTP = 0x5c + IPPROTO_MUX = 0x12 + IPPROTO_ND = 0x4d + IPPROTO_NHRP = 0x36 + IPPROTO_NONE = 0x3b + IPPROTO_NSP = 0x1f + IPPROTO_NVPII = 0xb + IPPROTO_OSPFIGP = 0x59 + IPPROTO_PGM = 0x71 + IPPROTO_PIGP = 0x9 + IPPROTO_PIM = 0x67 + IPPROTO_PRM = 0x15 + IPPROTO_PUP = 0xc + IPPROTO_PVP = 0x4b + IPPROTO_RAW = 0xff + IPPROTO_RCCMON = 0xa + IPPROTO_RDP = 0x1b + IPPROTO_ROUTING = 0x2b + IPPROTO_RSVP = 0x2e + IPPROTO_RVD = 0x42 + IPPROTO_SATEXPAK = 0x40 + IPPROTO_SATMON = 0x45 + IPPROTO_SCCSP = 0x60 + IPPROTO_SCTP = 0x84 + IPPROTO_SDRP = 0x2a + IPPROTO_SEP = 0x21 + IPPROTO_SRPC = 0x5a + IPPROTO_ST = 0x7 + IPPROTO_SVMTP = 0x52 + IPPROTO_SWIPE = 0x35 + IPPROTO_TCF = 0x57 + IPPROTO_TCP = 0x6 + IPPROTO_TP = 0x1d + IPPROTO_TPXX = 0x27 + IPPROTO_TRUNK1 = 0x17 + IPPROTO_TRUNK2 = 0x18 + IPPROTO_TTP = 0x54 + IPPROTO_UDP = 0x11 + IPPROTO_VINES = 0x53 + IPPROTO_VISA = 0x46 + IPPROTO_VMTP = 0x51 + IPPROTO_WBEXPAK = 0x4f + IPPROTO_WBMON = 0x4e + IPPROTO_WSN = 0x4a + IPPROTO_XNET = 0xf + IPPROTO_XTP = 0x24 + IPV6_2292DSTOPTS = 0x17 + IPV6_2292HOPLIMIT = 0x14 + IPV6_2292HOPOPTS = 0x16 + IPV6_2292NEXTHOP = 0x15 + IPV6_2292PKTINFO = 0x13 + IPV6_2292PKTOPTIONS = 0x19 + IPV6_2292RTHDR = 0x18 + IPV6_3542DSTOPTS = 0x32 + IPV6_3542HOPLIMIT = 0x2f + IPV6_3542HOPOPTS = 0x31 + IPV6_3542NEXTHOP = 0x30 + IPV6_3542PKTINFO = 0x2e + IPV6_3542RTHDR = 0x33 + IPV6_ADDR_MC_FLAGS_PREFIX = 0x20 + IPV6_ADDR_MC_FLAGS_TRANSIENT = 0x10 + IPV6_ADDR_MC_FLAGS_UNICAST_BASED = 0x30 + IPV6_AUTOFLOWLABEL = 0x3b + IPV6_BINDV6ONLY = 0x1b + IPV6_BOUND_IF = 0x7d + IPV6_CHECKSUM = 0x1a + IPV6_DEFAULT_MULTICAST_HOPS = 0x1 + IPV6_DEFAULT_MULTICAST_LOOP = 0x1 + IPV6_DEFHLIM = 0x40 + IPV6_DONTFRAG = 0x3e + IPV6_DSTOPTS = 0x32 + IPV6_FAITH = 0x1d + IPV6_FLOWINFO_MASK = 0xffffff0f + IPV6_FLOWLABEL_MASK = 0xffff0f00 + IPV6_FLOW_ECN_MASK = 0x3000 + IPV6_FRAGTTL = 0x3c + IPV6_FW_ADD = 0x1e + IPV6_FW_DEL = 0x1f + IPV6_FW_FLUSH = 0x20 + IPV6_FW_GET = 0x22 + IPV6_FW_ZERO = 0x21 + IPV6_HLIMDEC = 0x1 + IPV6_HOPLIMIT = 0x2f + IPV6_HOPOPTS = 0x31 + IPV6_IPSEC_POLICY = 0x1c + IPV6_JOIN_GROUP = 0xc + IPV6_LEAVE_GROUP = 0xd + IPV6_MAXHLIM = 0xff + IPV6_MAXOPTHDR = 0x800 + IPV6_MAXPACKET = 0xffff + IPV6_MAX_GROUP_SRC_FILTER = 0x200 + IPV6_MAX_MEMBERSHIPS = 0xfff + IPV6_MAX_SOCK_SRC_FILTER = 0x80 + IPV6_MIN_MEMBERSHIPS = 0x1f + IPV6_MMTU = 0x500 + IPV6_MSFILTER = 0x4a + IPV6_MULTICAST_HOPS = 0xa + IPV6_MULTICAST_IF = 0x9 + IPV6_MULTICAST_LOOP = 0xb + IPV6_NEXTHOP = 0x30 + IPV6_PATHMTU = 0x2c + IPV6_PKTINFO = 0x2e + IPV6_PORTRANGE = 0xe + IPV6_PORTRANGE_DEFAULT = 0x0 + IPV6_PORTRANGE_HIGH = 0x1 + IPV6_PORTRANGE_LOW = 0x2 + IPV6_PREFER_TEMPADDR = 0x3f + IPV6_RECVDSTOPTS = 0x28 + IPV6_RECVHOPLIMIT = 0x25 + IPV6_RECVHOPOPTS = 0x27 + IPV6_RECVPATHMTU = 0x2b + IPV6_RECVPKTINFO = 0x3d + IPV6_RECVRTHDR = 0x26 + IPV6_RECVTCLASS = 0x23 + IPV6_RTHDR = 0x33 + IPV6_RTHDRDSTOPTS = 0x39 + IPV6_RTHDR_LOOSE = 0x0 + IPV6_RTHDR_STRICT = 0x1 + IPV6_RTHDR_TYPE_0 = 0x0 + IPV6_SOCKOPT_RESERVED1 = 0x3 + IPV6_TCLASS = 0x24 + IPV6_UNICAST_HOPS = 0x4 + IPV6_USE_MIN_MTU = 0x2a + IPV6_V6ONLY = 0x1b + IPV6_VERSION = 0x60 + IPV6_VERSION_MASK = 0xf0 + IP_ADD_MEMBERSHIP = 0xc + IP_ADD_SOURCE_MEMBERSHIP = 0x46 + IP_BLOCK_SOURCE = 0x48 + IP_BOUND_IF = 0x19 + IP_DEFAULT_MULTICAST_LOOP = 0x1 + IP_DEFAULT_MULTICAST_TTL = 0x1 + IP_DF = 0x4000 + IP_DONTFRAG = 0x1c + IP_DROP_MEMBERSHIP = 0xd + IP_DROP_SOURCE_MEMBERSHIP = 0x47 + IP_DUMMYNET_CONFIGURE = 0x3c + IP_DUMMYNET_DEL = 0x3d + IP_DUMMYNET_FLUSH = 0x3e + IP_DUMMYNET_GET = 0x40 + IP_FAITH = 0x16 + IP_FW_ADD = 0x28 + IP_FW_DEL = 0x29 + IP_FW_FLUSH = 0x2a + IP_FW_GET = 0x2c + IP_FW_RESETLOG = 0x2d + IP_FW_ZERO = 0x2b + IP_HDRINCL = 0x2 + IP_IPSEC_POLICY = 0x15 + IP_MAXPACKET = 0xffff + IP_MAX_GROUP_SRC_FILTER = 0x200 + IP_MAX_MEMBERSHIPS = 0xfff + IP_MAX_SOCK_MUTE_FILTER = 0x80 + IP_MAX_SOCK_SRC_FILTER = 0x80 + IP_MF = 0x2000 + IP_MIN_MEMBERSHIPS = 0x1f + IP_MSFILTER = 0x4a + IP_MSS = 0x240 + IP_MULTICAST_IF = 0x9 + IP_MULTICAST_IFINDEX = 0x42 + IP_MULTICAST_LOOP = 0xb + IP_MULTICAST_TTL = 0xa + IP_MULTICAST_VIF = 0xe + IP_NAT__XXX = 0x37 + IP_OFFMASK = 0x1fff + IP_OLD_FW_ADD = 0x32 + IP_OLD_FW_DEL = 0x33 + IP_OLD_FW_FLUSH = 0x34 + IP_OLD_FW_GET = 0x36 + IP_OLD_FW_RESETLOG = 0x38 + IP_OLD_FW_ZERO = 0x35 + IP_OPTIONS = 0x1 + IP_PKTINFO = 0x1a + IP_PORTRANGE = 0x13 + IP_PORTRANGE_DEFAULT = 0x0 + IP_PORTRANGE_HIGH = 0x1 + IP_PORTRANGE_LOW = 0x2 + IP_RECVDSTADDR = 0x7 + IP_RECVIF = 0x14 + IP_RECVOPTS = 0x5 + IP_RECVPKTINFO = 0x1a + IP_RECVRETOPTS = 0x6 + IP_RECVTOS = 0x1b + IP_RECVTTL = 0x18 + IP_RETOPTS = 0x8 + IP_RF = 0x8000 + IP_RSVP_OFF = 0x10 + IP_RSVP_ON = 0xf + IP_RSVP_VIF_OFF = 0x12 + IP_RSVP_VIF_ON = 0x11 + IP_STRIPHDR = 0x17 + IP_TOS = 0x3 + IP_TRAFFIC_MGT_BACKGROUND = 0x41 + IP_TTL = 0x4 + IP_UNBLOCK_SOURCE = 0x49 + ISIG = 0x80 + ISTRIP = 0x20 + IUTF8 = 0x4000 + IXANY = 0x800 + IXOFF = 0x400 + IXON = 0x200 + KERN_HOSTNAME = 0xa + KERN_OSRELEASE = 0x2 + KERN_OSTYPE = 0x1 + KERN_VERSION = 0x4 + LOCAL_PEERCRED = 0x1 + LOCAL_PEEREPID = 0x3 + LOCAL_PEEREUUID = 0x5 + LOCAL_PEERPID = 0x2 + LOCAL_PEERTOKEN = 0x6 + LOCAL_PEERUUID = 0x4 + LOCK_EX = 0x2 + LOCK_NB = 0x4 + LOCK_SH = 0x1 + LOCK_UN = 0x8 + MADV_CAN_REUSE = 0x9 + MADV_DONTNEED = 0x4 + MADV_FREE = 0x5 + MADV_FREE_REUSABLE = 0x7 + MADV_FREE_REUSE = 0x8 + MADV_NORMAL = 0x0 + MADV_PAGEOUT = 0xa + MADV_RANDOM = 0x1 + MADV_SEQUENTIAL = 0x2 + MADV_WILLNEED = 0x3 + MADV_ZERO_WIRED_PAGES = 0x6 + MAP_32BIT = 0x8000 + MAP_ANON = 0x1000 + MAP_ANONYMOUS = 0x1000 + MAP_COPY = 0x2 + MAP_FILE = 0x0 + MAP_FIXED = 0x10 + MAP_HASSEMAPHORE = 0x200 + MAP_JIT = 0x800 + MAP_NOCACHE = 0x400 + MAP_NOEXTEND = 0x100 + MAP_NORESERVE = 0x40 + MAP_PRIVATE = 0x2 + MAP_RENAME = 0x20 + MAP_RESERVED0080 = 0x80 + MAP_RESILIENT_CODESIGN = 0x2000 + MAP_RESILIENT_MEDIA = 0x4000 + MAP_SHARED = 0x1 + MAP_TRANSLATED_ALLOW_EXECUTE = 0x20000 + MAP_UNIX03 = 0x40000 + MCAST_BLOCK_SOURCE = 0x54 + MCAST_EXCLUDE = 0x2 + MCAST_INCLUDE = 0x1 + MCAST_JOIN_GROUP = 0x50 + MCAST_JOIN_SOURCE_GROUP = 0x52 + MCAST_LEAVE_GROUP = 0x51 + MCAST_LEAVE_SOURCE_GROUP = 0x53 + MCAST_UNBLOCK_SOURCE = 0x55 + MCAST_UNDEFINED = 0x0 + MCL_CURRENT = 0x1 + MCL_FUTURE = 0x2 + MNT_ASYNC = 0x40 + MNT_AUTOMOUNTED = 0x400000 + MNT_CMDFLAGS = 0xf0000 + MNT_CPROTECT = 0x80 + MNT_DEFWRITE = 0x2000000 + MNT_DONTBROWSE = 0x100000 + MNT_DOVOLFS = 0x8000 + MNT_DWAIT = 0x4 + MNT_EXPORTED = 0x100 + MNT_EXT_ROOT_DATA_VOL = 0x1 + MNT_FORCE = 0x80000 + MNT_IGNORE_OWNERSHIP = 0x200000 + MNT_JOURNALED = 0x800000 + MNT_LOCAL = 0x1000 + MNT_MULTILABEL = 0x4000000 + MNT_NOATIME = 0x10000000 + MNT_NOBLOCK = 0x20000 + MNT_NODEV = 0x10 + MNT_NOEXEC = 0x4 + MNT_NOSUID = 0x8 + MNT_NOUSERXATTR = 0x1000000 + MNT_NOWAIT = 0x2 + MNT_QUARANTINE = 0x400 + MNT_QUOTA = 0x2000 + MNT_RDONLY = 0x1 + MNT_RELOAD = 0x40000 + MNT_REMOVABLE = 0x200 + MNT_ROOTFS = 0x4000 + MNT_SNAPSHOT = 0x40000000 + MNT_STRICTATIME = 0x80000000 + MNT_SYNCHRONOUS = 0x2 + MNT_UNION = 0x20 + MNT_UNKNOWNPERMISSIONS = 0x200000 + MNT_UPDATE = 0x10000 + MNT_VISFLAGMASK = 0xd7f0f7ff + MNT_WAIT = 0x1 + MSG_CTRUNC = 0x20 + MSG_DONTROUTE = 0x4 + MSG_DONTWAIT = 0x80 + MSG_EOF = 0x100 + MSG_EOR = 0x8 + MSG_FLUSH = 0x400 + MSG_HAVEMORE = 0x2000 + MSG_HOLD = 0x800 + MSG_NEEDSA = 0x10000 + MSG_NOSIGNAL = 0x80000 + MSG_OOB = 0x1 + MSG_PEEK = 0x2 + MSG_RCVMORE = 0x4000 + MSG_SEND = 0x1000 + MSG_TRUNC = 0x10 + MSG_WAITALL = 0x40 + MSG_WAITSTREAM = 0x200 + MS_ASYNC = 0x1 + MS_DEACTIVATE = 0x8 + MS_INVALIDATE = 0x2 + MS_KILLPAGES = 0x4 + MS_SYNC = 0x10 + NAME_MAX = 0xff + NET_RT_DUMP = 0x1 + NET_RT_DUMP2 = 0x7 + NET_RT_FLAGS = 0x2 + NET_RT_FLAGS_PRIV = 0xa + NET_RT_IFLIST = 0x3 + NET_RT_IFLIST2 = 0x6 + NET_RT_MAXID = 0xb + NET_RT_STAT = 0x4 + NET_RT_TRASH = 0x5 + NFDBITS = 0x20 + NL0 = 0x0 + NL1 = 0x100 + NL2 = 0x200 + NL3 = 0x300 + NLDLY = 0x300 + NOFLSH = 0x80000000 + NOKERNINFO = 0x2000000 + NOTE_ABSOLUTE = 0x8 + NOTE_ATTRIB = 0x8 + NOTE_BACKGROUND = 0x40 + NOTE_CHILD = 0x4 + NOTE_CRITICAL = 0x20 + NOTE_DELETE = 0x1 + NOTE_EXEC = 0x20000000 + NOTE_EXIT = 0x80000000 + NOTE_EXITSTATUS = 0x4000000 + NOTE_EXIT_CSERROR = 0x40000 + NOTE_EXIT_DECRYPTFAIL = 0x10000 + NOTE_EXIT_DETAIL = 0x2000000 + NOTE_EXIT_DETAIL_MASK = 0x70000 + NOTE_EXIT_MEMORY = 0x20000 + NOTE_EXIT_REPARENTED = 0x80000 + NOTE_EXTEND = 0x4 + NOTE_FFAND = 0x40000000 + NOTE_FFCOPY = 0xc0000000 + NOTE_FFCTRLMASK = 0xc0000000 + NOTE_FFLAGSMASK = 0xffffff + NOTE_FFNOP = 0x0 + NOTE_FFOR = 0x80000000 + NOTE_FORK = 0x40000000 + NOTE_FUNLOCK = 0x100 + NOTE_LEEWAY = 0x10 + NOTE_LINK = 0x10 + NOTE_LOWAT = 0x1 + NOTE_MACHTIME = 0x100 + NOTE_MACH_CONTINUOUS_TIME = 0x80 + NOTE_NONE = 0x80 + NOTE_NSECONDS = 0x4 + NOTE_OOB = 0x2 + NOTE_PCTRLMASK = -0x100000 + NOTE_PDATAMASK = 0xfffff + NOTE_REAP = 0x10000000 + NOTE_RENAME = 0x20 + NOTE_REVOKE = 0x40 + NOTE_SECONDS = 0x1 + NOTE_SIGNAL = 0x8000000 + NOTE_TRACK = 0x1 + NOTE_TRACKERR = 0x2 + NOTE_TRIGGER = 0x1000000 + NOTE_USECONDS = 0x2 + NOTE_VM_ERROR = 0x10000000 + NOTE_VM_PRESSURE = 0x80000000 + NOTE_VM_PRESSURE_SUDDEN_TERMINATE = 0x20000000 + NOTE_VM_PRESSURE_TERMINATE = 0x40000000 + NOTE_WRITE = 0x2 + OCRNL = 0x10 + OFDEL = 0x20000 + OFILL = 0x80 + ONLCR = 0x2 + ONLRET = 0x40 + ONOCR = 0x20 + ONOEOT = 0x8 + OPOST = 0x1 + OXTABS = 0x4 + O_ACCMODE = 0x3 + O_ALERT = 0x20000000 + O_APPEND = 0x8 + O_ASYNC = 0x40 + O_CLOEXEC = 0x1000000 + O_CREAT = 0x200 + O_DIRECTORY = 0x100000 + O_DP_GETRAWENCRYPTED = 0x1 + O_DP_GETRAWUNENCRYPTED = 0x2 + O_DSYNC = 0x400000 + O_EVTONLY = 0x8000 + O_EXCL = 0x800 + O_EXLOCK = 0x20 + O_FSYNC = 0x80 + O_NDELAY = 0x4 + O_NOCTTY = 0x20000 + O_NOFOLLOW = 0x100 + O_NOFOLLOW_ANY = 0x20000000 + O_NONBLOCK = 0x4 + O_POPUP = 0x80000000 + O_RDONLY = 0x0 + O_RDWR = 0x2 + O_SHLOCK = 0x10 + O_SYMLINK = 0x200000 + O_SYNC = 0x80 + O_TRUNC = 0x400 + O_WRONLY = 0x1 + PARENB = 0x1000 + PARMRK = 0x8 + PARODD = 0x2000 + PENDIN = 0x20000000 + PRIO_PGRP = 0x1 + PRIO_PROCESS = 0x0 + PRIO_USER = 0x2 + PROT_EXEC = 0x4 + PROT_NONE = 0x0 + PROT_READ = 0x1 + PROT_WRITE = 0x2 + PT_ATTACH = 0xa + PT_ATTACHEXC = 0xe + PT_CONTINUE = 0x7 + PT_DENY_ATTACH = 0x1f + PT_DETACH = 0xb + PT_FIRSTMACH = 0x20 + PT_FORCEQUOTA = 0x1e + PT_KILL = 0x8 + PT_READ_D = 0x2 + PT_READ_I = 0x1 + PT_READ_U = 0x3 + PT_SIGEXC = 0xc + PT_STEP = 0x9 + PT_THUPDATE = 0xd + PT_TRACE_ME = 0x0 + PT_WRITE_D = 0x5 + PT_WRITE_I = 0x4 + PT_WRITE_U = 0x6 + RLIMIT_AS = 0x5 + RLIMIT_CORE = 0x4 + RLIMIT_CPU = 0x0 + RLIMIT_CPU_USAGE_MONITOR = 0x2 + RLIMIT_DATA = 0x2 + RLIMIT_FSIZE = 0x1 + RLIMIT_MEMLOCK = 0x6 + RLIMIT_NOFILE = 0x8 + RLIMIT_NPROC = 0x7 + RLIMIT_RSS = 0x5 + RLIMIT_STACK = 0x3 + RLIM_INFINITY = 0x7fffffffffffffff + RTAX_AUTHOR = 0x6 + RTAX_BRD = 0x7 + RTAX_DST = 0x0 + RTAX_GATEWAY = 0x1 + RTAX_GENMASK = 0x3 + RTAX_IFA = 0x5 + RTAX_IFP = 0x4 + RTAX_MAX = 0x8 + RTAX_NETMASK = 0x2 + RTA_AUTHOR = 0x40 + RTA_BRD = 0x80 + RTA_DST = 0x1 + RTA_GATEWAY = 0x2 + RTA_GENMASK = 0x8 + RTA_IFA = 0x20 + RTA_IFP = 0x10 + RTA_NETMASK = 0x4 + RTF_BLACKHOLE = 0x1000 + RTF_BROADCAST = 0x400000 + RTF_CLONING = 0x100 + RTF_CONDEMNED = 0x2000000 + RTF_DEAD = 0x20000000 + RTF_DELCLONE = 0x80 + RTF_DONE = 0x40 + RTF_DYNAMIC = 0x10 + RTF_GATEWAY = 0x2 + RTF_GLOBAL = 0x40000000 + RTF_HOST = 0x4 + RTF_IFREF = 0x4000000 + RTF_IFSCOPE = 0x1000000 + RTF_LLDATA = 0x400 + RTF_LLINFO = 0x400 + RTF_LOCAL = 0x200000 + RTF_MODIFIED = 0x20 + RTF_MULTICAST = 0x800000 + RTF_NOIFREF = 0x2000 + RTF_PINNED = 0x100000 + RTF_PRCLONING = 0x10000 + RTF_PROTO1 = 0x8000 + RTF_PROTO2 = 0x4000 + RTF_PROTO3 = 0x40000 + RTF_PROXY = 0x8000000 + RTF_REJECT = 0x8 + RTF_ROUTER = 0x10000000 + RTF_STATIC = 0x800 + RTF_UP = 0x1 + RTF_WASCLONED = 0x20000 + RTF_XRESOLVE = 0x200 + RTM_ADD = 0x1 + RTM_CHANGE = 0x3 + RTM_DELADDR = 0xd + RTM_DELETE = 0x2 + RTM_DELMADDR = 0x10 + RTM_GET = 0x4 + RTM_GET2 = 0x14 + RTM_IFINFO = 0xe + RTM_IFINFO2 = 0x12 + RTM_LOCK = 0x8 + RTM_LOSING = 0x5 + RTM_MISS = 0x7 + RTM_NEWADDR = 0xc + RTM_NEWMADDR = 0xf + RTM_NEWMADDR2 = 0x13 + RTM_OLDADD = 0x9 + RTM_OLDDEL = 0xa + RTM_REDIRECT = 0x6 + RTM_RESOLVE = 0xb + RTM_RTTUNIT = 0xf4240 + RTM_VERSION = 0x5 + RTV_EXPIRE = 0x4 + RTV_HOPCOUNT = 0x2 + RTV_MTU = 0x1 + RTV_RPIPE = 0x8 + RTV_RTT = 0x40 + RTV_RTTVAR = 0x80 + RTV_SPIPE = 0x10 + RTV_SSTHRESH = 0x20 + RUSAGE_CHILDREN = -0x1 + RUSAGE_SELF = 0x0 + SCM_CREDS = 0x3 + SCM_RIGHTS = 0x1 + SCM_TIMESTAMP = 0x2 + SCM_TIMESTAMP_MONOTONIC = 0x4 + SEEK_CUR = 0x1 + SEEK_DATA = 0x4 + SEEK_END = 0x2 + SEEK_HOLE = 0x3 + SEEK_SET = 0x0 + SHUT_RD = 0x0 + SHUT_RDWR = 0x2 + SHUT_WR = 0x1 + SIOCADDMULTI = 0x80206931 + SIOCAIFADDR = 0x8040691a + SIOCARPIPLL = 0xc0206928 + SIOCATMARK = 0x40047307 + SIOCAUTOADDR = 0xc0206926 + SIOCAUTONETMASK = 0x80206927 + SIOCDELMULTI = 0x80206932 + SIOCDIFADDR = 0x80206919 + SIOCDIFPHYADDR = 0x80206941 + SIOCGDRVSPEC = 0xc028697b + SIOCGETVLAN = 0xc020697f + SIOCGHIWAT = 0x40047301 + SIOCGIF6LOWPAN = 0xc02069c5 + SIOCGIFADDR = 0xc0206921 + SIOCGIFALTMTU = 0xc0206948 + SIOCGIFASYNCMAP = 0xc020697c + SIOCGIFBOND = 0xc0206947 + SIOCGIFBRDADDR = 0xc0206923 + SIOCGIFCAP = 0xc020695b + SIOCGIFCONF = 0xc00c6924 + SIOCGIFDEVMTU = 0xc0206944 + SIOCGIFDSTADDR = 0xc0206922 + SIOCGIFFLAGS = 0xc0206911 + SIOCGIFFUNCTIONALTYPE = 0xc02069ad + SIOCGIFGENERIC = 0xc020693a + SIOCGIFKPI = 0xc0206987 + SIOCGIFMAC = 0xc0206982 + SIOCGIFMEDIA = 0xc02c6938 + SIOCGIFMETRIC = 0xc0206917 + SIOCGIFMTU = 0xc0206933 + SIOCGIFNETMASK = 0xc0206925 + SIOCGIFPDSTADDR = 0xc0206940 + SIOCGIFPHYS = 0xc0206935 + SIOCGIFPSRCADDR = 0xc020693f + SIOCGIFSTATUS = 0xc331693d + SIOCGIFVLAN = 0xc020697f + SIOCGIFWAKEFLAGS = 0xc0206988 + SIOCGIFXMEDIA = 0xc02c6948 + SIOCGLOWAT = 0x40047303 + SIOCGPGRP = 0x40047309 + SIOCIFCREATE = 0xc0206978 + SIOCIFCREATE2 = 0xc020697a + SIOCIFDESTROY = 0x80206979 + SIOCIFGCLONERS = 0xc0106981 + SIOCRSLVMULTI = 0xc010693b + SIOCSDRVSPEC = 0x8028697b + SIOCSETVLAN = 0x8020697e + SIOCSHIWAT = 0x80047300 + SIOCSIF6LOWPAN = 0x802069c4 + SIOCSIFADDR = 0x8020690c + SIOCSIFALTMTU = 0x80206945 + SIOCSIFASYNCMAP = 0x8020697d + SIOCSIFBOND = 0x80206946 + SIOCSIFBRDADDR = 0x80206913 + SIOCSIFCAP = 0x8020695a + SIOCSIFDSTADDR = 0x8020690e + SIOCSIFFLAGS = 0x80206910 + SIOCSIFGENERIC = 0x80206939 + SIOCSIFKPI = 0x80206986 + SIOCSIFLLADDR = 0x8020693c + SIOCSIFMAC = 0x80206983 + SIOCSIFMEDIA = 0xc0206937 + SIOCSIFMETRIC = 0x80206918 + SIOCSIFMTU = 0x80206934 + SIOCSIFNETMASK = 0x80206916 + SIOCSIFPHYADDR = 0x8040693e + SIOCSIFPHYS = 0x80206936 + SIOCSIFVLAN = 0x8020697e + SIOCSLOWAT = 0x80047302 + SIOCSPGRP = 0x80047308 + SOCK_DGRAM = 0x2 + SOCK_MAXADDRLEN = 0xff + SOCK_RAW = 0x3 + SOCK_RDM = 0x4 + SOCK_SEQPACKET = 0x5 + SOCK_STREAM = 0x1 + SOL_LOCAL = 0x0 + SOL_SOCKET = 0xffff + SOMAXCONN = 0x80 + SO_ACCEPTCONN = 0x2 + SO_BROADCAST = 0x20 + SO_DEBUG = 0x1 + SO_DONTROUTE = 0x10 + SO_DONTTRUNC = 0x2000 + SO_ERROR = 0x1007 + SO_KEEPALIVE = 0x8 + SO_LABEL = 0x1010 + SO_LINGER = 0x80 + SO_LINGER_SEC = 0x1080 + SO_NETSVC_MARKING_LEVEL = 0x1119 + SO_NET_SERVICE_TYPE = 0x1116 + SO_NKE = 0x1021 + SO_NOADDRERR = 0x1023 + SO_NOSIGPIPE = 0x1022 + SO_NOTIFYCONFLICT = 0x1026 + SO_NP_EXTENSIONS = 0x1083 + SO_NREAD = 0x1020 + SO_NUMRCVPKT = 0x1112 + SO_NWRITE = 0x1024 + SO_OOBINLINE = 0x100 + SO_PEERLABEL = 0x1011 + SO_RANDOMPORT = 0x1082 + SO_RCVBUF = 0x1002 + SO_RCVLOWAT = 0x1004 + SO_RCVTIMEO = 0x1006 + SO_REUSEADDR = 0x4 + SO_REUSEPORT = 0x200 + SO_REUSESHAREUID = 0x1025 + SO_SNDBUF = 0x1001 + SO_SNDLOWAT = 0x1003 + SO_SNDTIMEO = 0x1005 + SO_TIMESTAMP = 0x400 + SO_TIMESTAMP_MONOTONIC = 0x800 + SO_TRACKER_ATTRIBUTE_FLAGS_APP_APPROVED = 0x1 + SO_TRACKER_ATTRIBUTE_FLAGS_DOMAIN_SHORT = 0x4 + SO_TRACKER_ATTRIBUTE_FLAGS_TRACKER = 0x2 + SO_TRACKER_TRANSPARENCY_VERSION = 0x3 + SO_TYPE = 0x1008 + SO_UPCALLCLOSEWAIT = 0x1027 + SO_USELOOPBACK = 0x40 + SO_WANTMORE = 0x4000 + SO_WANTOOBFLAG = 0x8000 + S_IEXEC = 0x40 + S_IFBLK = 0x6000 + S_IFCHR = 0x2000 + S_IFDIR = 0x4000 + S_IFIFO = 0x1000 + S_IFLNK = 0xa000 + S_IFMT = 0xf000 + S_IFREG = 0x8000 + S_IFSOCK = 0xc000 + S_IFWHT = 0xe000 + S_IREAD = 0x100 + S_IRGRP = 0x20 + S_IROTH = 0x4 + S_IRUSR = 0x100 + S_IRWXG = 0x38 + S_IRWXO = 0x7 + S_IRWXU = 0x1c0 + S_ISGID = 0x400 + S_ISTXT = 0x200 + S_ISUID = 0x800 + S_ISVTX = 0x200 + S_IWGRP = 0x10 + S_IWOTH = 0x2 + S_IWRITE = 0x80 + S_IWUSR = 0x80 + S_IXGRP = 0x8 + S_IXOTH = 0x1 + S_IXUSR = 0x40 + TAB0 = 0x0 + TAB1 = 0x400 + TAB2 = 0x800 + TAB3 = 0x4 + TABDLY = 0xc04 + TCIFLUSH = 0x1 + TCIOFF = 0x3 + TCIOFLUSH = 0x3 + TCION = 0x4 + TCOFLUSH = 0x2 + TCOOFF = 0x1 + TCOON = 0x2 + TCPOPT_CC = 0xb + TCPOPT_CCECHO = 0xd + TCPOPT_CCNEW = 0xc + TCPOPT_EOL = 0x0 + TCPOPT_FASTOPEN = 0x22 + TCPOPT_MAXSEG = 0x2 + TCPOPT_NOP = 0x1 + TCPOPT_SACK = 0x5 + TCPOPT_SACK_HDR = 0x1010500 + TCPOPT_SACK_PERMITTED = 0x4 + TCPOPT_SACK_PERMIT_HDR = 0x1010402 + TCPOPT_SIGNATURE = 0x13 + TCPOPT_TIMESTAMP = 0x8 + TCPOPT_TSTAMP_HDR = 0x101080a + TCPOPT_WINDOW = 0x3 + TCP_CONNECTIONTIMEOUT = 0x20 + TCP_CONNECTION_INFO = 0x106 + TCP_ENABLE_ECN = 0x104 + TCP_FASTOPEN = 0x105 + TCP_KEEPALIVE = 0x10 + TCP_KEEPCNT = 0x102 + TCP_KEEPINTVL = 0x101 + TCP_MAXHLEN = 0x3c + TCP_MAXOLEN = 0x28 + TCP_MAXSEG = 0x2 + TCP_MAXWIN = 0xffff + TCP_MAX_SACK = 0x4 + TCP_MAX_WINSHIFT = 0xe + TCP_MINMSS = 0xd8 + TCP_MSS = 0x200 + TCP_NODELAY = 0x1 + TCP_NOOPT = 0x8 + TCP_NOPUSH = 0x4 + TCP_NOTSENT_LOWAT = 0x201 + TCP_RXT_CONNDROPTIME = 0x80 + TCP_RXT_FINDROP = 0x100 + TCP_SENDMOREACKS = 0x103 + TCSAFLUSH = 0x2 + TIOCCBRK = 0x2000747a + TIOCCDTR = 0x20007478 + TIOCCONS = 0x80047462 + TIOCDCDTIMESTAMP = 0x40107458 + TIOCDRAIN = 0x2000745e + TIOCDSIMICROCODE = 0x20007455 + TIOCEXCL = 0x2000740d + TIOCEXT = 0x80047460 + TIOCFLUSH = 0x80047410 + TIOCGDRAINWAIT = 0x40047456 + TIOCGETA = 0x40487413 + TIOCGETD = 0x4004741a + TIOCGPGRP = 0x40047477 + TIOCGWINSZ = 0x40087468 + TIOCIXOFF = 0x20007480 + TIOCIXON = 0x20007481 + TIOCMBIC = 0x8004746b + TIOCMBIS = 0x8004746c + TIOCMGDTRWAIT = 0x4004745a + TIOCMGET = 0x4004746a + TIOCMODG = 0x40047403 + TIOCMODS = 0x80047404 + TIOCMSDTRWAIT = 0x8004745b + TIOCMSET = 0x8004746d + TIOCM_CAR = 0x40 + TIOCM_CD = 0x40 + TIOCM_CTS = 0x20 + TIOCM_DSR = 0x100 + TIOCM_DTR = 0x2 + TIOCM_LE = 0x1 + TIOCM_RI = 0x80 + TIOCM_RNG = 0x80 + TIOCM_RTS = 0x4 + TIOCM_SR = 0x10 + TIOCM_ST = 0x8 + TIOCNOTTY = 0x20007471 + TIOCNXCL = 0x2000740e + TIOCOUTQ = 0x40047473 + TIOCPKT = 0x80047470 + TIOCPKT_DATA = 0x0 + TIOCPKT_DOSTOP = 0x20 + TIOCPKT_FLUSHREAD = 0x1 + TIOCPKT_FLUSHWRITE = 0x2 + TIOCPKT_IOCTL = 0x40 + TIOCPKT_NOSTOP = 0x10 + TIOCPKT_START = 0x8 + TIOCPKT_STOP = 0x4 + TIOCPTYGNAME = 0x40807453 + TIOCPTYGRANT = 0x20007454 + TIOCPTYUNLK = 0x20007452 + TIOCREMOTE = 0x80047469 + TIOCSBRK = 0x2000747b + TIOCSCONS = 0x20007463 + TIOCSCTTY = 0x20007461 + TIOCSDRAINWAIT = 0x80047457 + TIOCSDTR = 0x20007479 + TIOCSETA = 0x80487414 + TIOCSETAF = 0x80487416 + TIOCSETAW = 0x80487415 + TIOCSETD = 0x8004741b + TIOCSIG = 0x2000745f + TIOCSPGRP = 0x80047476 + TIOCSTART = 0x2000746e + TIOCSTAT = 0x20007465 + TIOCSTI = 0x80017472 + TIOCSTOP = 0x2000746f + TIOCSWINSZ = 0x80087467 + TIOCTIMESTAMP = 0x40107459 + TIOCUCNTL = 0x80047466 + TOSTOP = 0x400000 + VDISCARD = 0xf + VDSUSP = 0xb + VEOF = 0x0 + VEOL = 0x1 + VEOL2 = 0x2 + VERASE = 0x3 + VINTR = 0x8 + VKILL = 0x5 + VLNEXT = 0xe + VMADDR_CID_ANY = 0xffffffff + VMADDR_CID_HOST = 0x2 + VMADDR_CID_HYPERVISOR = 0x0 + VMADDR_CID_RESERVED = 0x1 + VMADDR_PORT_ANY = 0xffffffff + VMIN = 0x10 + VM_LOADAVG = 0x2 + VM_MACHFACTOR = 0x4 + VM_MAXID = 0x6 + VM_METER = 0x1 + VM_SWAPUSAGE = 0x5 + VQUIT = 0x9 + VREPRINT = 0x6 + VSTART = 0xc + VSTATUS = 0x12 + VSTOP = 0xd + VSUSP = 0xa + VT0 = 0x0 + VT1 = 0x10000 + VTDLY = 0x10000 + VTIME = 0x11 + VWERASE = 0x4 + WCONTINUED = 0x10 + WCOREFLAG = 0x80 + WEXITED = 0x4 + WNOHANG = 0x1 + WNOWAIT = 0x20 + WORDSIZE = 0x40 + WSTOPPED = 0x8 + WUNTRACED = 0x2 + XATTR_CREATE = 0x2 + XATTR_NODEFAULT = 0x10 + XATTR_NOFOLLOW = 0x1 + XATTR_NOSECURITY = 0x8 + XATTR_REPLACE = 0x4 + XATTR_SHOWCOMPRESSION = 0x20 ) // Errors 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 8894c4af44..78d4b85ece 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 @@ -1333,6 +1333,20 @@ const ( KEY_SPEC_THREAD_KEYRING = -0x1 KEY_SPEC_USER_KEYRING = -0x4 KEY_SPEC_USER_SESSION_KEYRING = -0x5 + LANDLOCK_ACCESS_FS_EXECUTE = 0x1 + LANDLOCK_ACCESS_FS_MAKE_BLOCK = 0x800 + LANDLOCK_ACCESS_FS_MAKE_CHAR = 0x40 + LANDLOCK_ACCESS_FS_MAKE_DIR = 0x80 + LANDLOCK_ACCESS_FS_MAKE_FIFO = 0x400 + LANDLOCK_ACCESS_FS_MAKE_REG = 0x100 + LANDLOCK_ACCESS_FS_MAKE_SOCK = 0x200 + LANDLOCK_ACCESS_FS_MAKE_SYM = 0x1000 + LANDLOCK_ACCESS_FS_READ_DIR = 0x8 + LANDLOCK_ACCESS_FS_READ_FILE = 0x4 + LANDLOCK_ACCESS_FS_REMOVE_DIR = 0x10 + LANDLOCK_ACCESS_FS_REMOVE_FILE = 0x20 + LANDLOCK_ACCESS_FS_WRITE_FILE = 0x2 + LANDLOCK_CREATE_RULESET_VERSION = 0x1 LINUX_REBOOT_CMD_CAD_OFF = 0x0 LINUX_REBOOT_CMD_CAD_ON = 0x89abcdef LINUX_REBOOT_CMD_HALT = 0xcdef0123 @@ -1383,6 +1397,8 @@ const ( MADV_NOHUGEPAGE = 0xf MADV_NORMAL = 0x0 MADV_PAGEOUT = 0x15 + MADV_POPULATE_READ = 0x16 + MADV_POPULATE_WRITE = 0x17 MADV_RANDOM = 0x1 MADV_REMOVE = 0x9 MADV_SEQUENTIAL = 0x2 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 d4efe8d457..0ae0ed4cb8 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 @@ -734,6 +734,65 @@ var libc_sendfile_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func shmat(id int, addr uintptr, flag int) (ret uintptr, err error) { + r0, _, e1 := syscall_syscall(libc_shmat_trampoline_addr, uintptr(id), uintptr(addr), uintptr(flag)) + ret = uintptr(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_shmat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_shmat shmat "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func shmctl(id int, cmd int, buf *SysvShmDesc) (result int, err error) { + r0, _, e1 := syscall_syscall(libc_shmctl_trampoline_addr, uintptr(id), uintptr(cmd), uintptr(unsafe.Pointer(buf))) + result = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_shmctl_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_shmctl shmctl "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func shmdt(addr uintptr) (err error) { + _, _, e1 := syscall_syscall(libc_shmdt_trampoline_addr, uintptr(addr), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_shmdt_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_shmdt shmdt "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func shmget(key int, size int, flag int) (id int, err error) { + r0, _, e1 := syscall_syscall(libc_shmget_trampoline_addr, uintptr(key), uintptr(size), uintptr(flag)) + id = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_shmget_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_shmget shmget "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Access(path string, mode uint32) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s index bc169c2ab9..eac6ca806f 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s @@ -264,6 +264,30 @@ TEXT libc_sendfile_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_sendfile_trampoline_addr(SB), RODATA, $8 DATA ·libc_sendfile_trampoline_addr(SB)/8, $libc_sendfile_trampoline<>(SB) +TEXT libc_shmat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_shmat(SB) + +GLOBL ·libc_shmat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_shmat_trampoline_addr(SB)/8, $libc_shmat_trampoline<>(SB) + +TEXT libc_shmctl_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_shmctl(SB) + +GLOBL ·libc_shmctl_trampoline_addr(SB), RODATA, $8 +DATA ·libc_shmctl_trampoline_addr(SB)/8, $libc_shmctl_trampoline<>(SB) + +TEXT libc_shmdt_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_shmdt(SB) + +GLOBL ·libc_shmdt_trampoline_addr(SB), RODATA, $8 +DATA ·libc_shmdt_trampoline_addr(SB)/8, $libc_shmdt_trampoline<>(SB) + +TEXT libc_shmget_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_shmget(SB) + +GLOBL ·libc_shmget_trampoline_addr(SB), RODATA, $8 +DATA ·libc_shmget_trampoline_addr(SB)/8, $libc_shmget_trampoline<>(SB) + TEXT libc_access_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_access(SB) 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 f2ee2bd33b..cf71be3edb 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 @@ -734,6 +734,65 @@ var libc_sendfile_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func shmat(id int, addr uintptr, flag int) (ret uintptr, err error) { + r0, _, e1 := syscall_syscall(libc_shmat_trampoline_addr, uintptr(id), uintptr(addr), uintptr(flag)) + ret = uintptr(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_shmat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_shmat shmat "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func shmctl(id int, cmd int, buf *SysvShmDesc) (result int, err error) { + r0, _, e1 := syscall_syscall(libc_shmctl_trampoline_addr, uintptr(id), uintptr(cmd), uintptr(unsafe.Pointer(buf))) + result = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_shmctl_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_shmctl shmctl "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func shmdt(addr uintptr) (err error) { + _, _, e1 := syscall_syscall(libc_shmdt_trampoline_addr, uintptr(addr), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_shmdt_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_shmdt shmdt "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func shmget(key int, size int, flag int) (id int, err error) { + r0, _, e1 := syscall_syscall(libc_shmget_trampoline_addr, uintptr(key), uintptr(size), uintptr(flag)) + id = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_shmget_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_shmget shmget "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Access(path string, mode uint32) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s index 33e19776db..4ebcf21758 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s @@ -264,6 +264,30 @@ TEXT libc_sendfile_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_sendfile_trampoline_addr(SB), RODATA, $8 DATA ·libc_sendfile_trampoline_addr(SB)/8, $libc_sendfile_trampoline<>(SB) +TEXT libc_shmat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_shmat(SB) + +GLOBL ·libc_shmat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_shmat_trampoline_addr(SB)/8, $libc_shmat_trampoline<>(SB) + +TEXT libc_shmctl_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_shmctl(SB) + +GLOBL ·libc_shmctl_trampoline_addr(SB), RODATA, $8 +DATA ·libc_shmctl_trampoline_addr(SB)/8, $libc_shmctl_trampoline<>(SB) + +TEXT libc_shmdt_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_shmdt(SB) + +GLOBL ·libc_shmdt_trampoline_addr(SB), RODATA, $8 +DATA ·libc_shmdt_trampoline_addr(SB)/8, $libc_shmdt_trampoline<>(SB) + +TEXT libc_shmget_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_shmget(SB) + +GLOBL ·libc_shmget_trampoline_addr(SB), RODATA, $8 +DATA ·libc_shmget_trampoline_addr(SB)/8, $libc_shmget_trampoline<>(SB) + TEXT libc_access_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_access(SB) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux.go index 2dbe3da7a0..4f5da1f54f 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux.go @@ -110,6 +110,16 @@ func openat2(dirfd int, path string, open_how *OpenHow, size int) (fd int, err e // 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 ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { r0, _, e1 := Syscall6(SYS_PPOLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0) n = int(r0) @@ -1945,8 +1955,63 @@ func ProcessVMWritev(pid int, localIov []Iovec, remoteIov []RemoteIovec, flags u // 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) +func PidfdOpen(pid int, flags int) (fd int, err error) { + r0, _, e1 := Syscall(SYS_PIDFD_OPEN, uintptr(pid), uintptr(flags), 0) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func PidfdGetfd(pidfd int, targetfd int, flags int) (fd int, err error) { + r0, _, e1 := Syscall(SYS_PIDFD_GETFD, uintptr(pidfd), uintptr(targetfd), uintptr(flags)) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func shmat(id int, addr uintptr, flag int) (ret uintptr, err error) { + r0, _, e1 := Syscall(SYS_SHMAT, uintptr(id), uintptr(addr), uintptr(flag)) + ret = uintptr(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func shmctl(id int, cmd int, buf *SysvShmDesc) (result int, err error) { + r0, _, e1 := Syscall(SYS_SHMCTL, uintptr(id), uintptr(cmd), uintptr(unsafe.Pointer(buf))) + result = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func shmdt(addr uintptr) (err error) { + _, _, e1 := Syscall(SYS_SHMDT, uintptr(addr), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func shmget(key int, size int, flag int) (id int, err error) { + r0, _, e1 := Syscall(SYS_SHMGET, uintptr(key), uintptr(size), uintptr(flag)) + id = int(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go index e37096e4de..ff90c81e73 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go @@ -46,37 +46,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe(p *[2]_C_int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func dup2(oldfd int, newfd int) (err error) { - _, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func EpollCreate(size int) (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE, uintptr(size), 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { var _p0 unsafe.Pointer if len(events) > 0 { @@ -181,17 +150,6 @@ func Getuid() (uid int) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func InotifyInit() (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT, 0, 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Ioperm(from int, num int, on int) (err error) { _, _, e1 := Syscall(SYS_IOPERM, uintptr(from), uintptr(num), uintptr(on)) if e1 != 0 { @@ -566,14 +524,3 @@ func utimes(path string, times *[2]Timeval) (err error) { } return } - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go index 9919d8486d..fa7d3dbe4e 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go @@ -46,27 +46,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func dup2(oldfd int, newfd int) (err error) { - _, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func EpollCreate(size int) (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE, uintptr(size), 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { var _p0 unsafe.Pointer if len(events) > 0 { @@ -191,17 +170,6 @@ func Getuid() (uid int) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func inotifyInit() (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT, 0, 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Ioperm(from int, num int, on int) (err error) { _, _, e1 := Syscall(SYS_IOPERM, uintptr(from), uintptr(num), uintptr(on)) if e1 != 0 { @@ -711,27 +679,6 @@ func utimes(path string, times *[2]Timeval) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe(p *[2]_C_int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func kexecFileLoad(kernelFd int, initrdFd int, cmdlineLen int, cmdline string, flags int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(cmdline) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go index 076754d48d..654f91530f 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go @@ -46,16 +46,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe(p *[2]_C_int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) fd = int(r0) @@ -235,27 +225,6 @@ func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func dup2(oldfd int, newfd int) (err error) { - _, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func EpollCreate(size int) (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE, uintptr(size), 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { var _p0 unsafe.Pointer if len(events) > 0 { @@ -340,17 +309,6 @@ func Getuid() (uid int) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func InotifyInit() (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT, 0, 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Lchown(path string, uid int, gid int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -681,17 +639,6 @@ func setrlimit(resource int, rlim *rlimit32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func armSyncFileRange(fd int, flags int, off int64, n int64) (err error) { _, _, e1 := Syscall6(SYS_ARM_SYNC_FILE_RANGE, uintptr(fd), uintptr(flags), uintptr(off), uintptr(off>>32), uintptr(n), uintptr(n>>32)) if e1 != 0 { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go index 4703cf3c33..6d15528853 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go @@ -46,27 +46,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func dup2(oldfd int, newfd int) (err error) { - _, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func EpollCreate(size int) (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE, uintptr(size), 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { var _p0 unsafe.Pointer if len(events) > 0 { @@ -544,17 +523,6 @@ func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func InotifyInit() (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT, 0, 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Ioperm(from int, num int, on int) (err error) { _, _, e1 := Syscall(SYS_IOPERM, uintptr(from), uintptr(num), uintptr(on)) if e1 != 0 { @@ -706,18 +674,6 @@ func Pause() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe() (p1 int, p2 int, err error) { - r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0) - p1 = int(r0) - p2 = int(r1) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func mmap2(addr uintptr, length uintptr, prot int, flags int, fd int, pageOffset uintptr) (xaddr uintptr, err error) { r0, _, e1 := Syscall6(SYS_MMAP2, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flags), uintptr(fd), uintptr(pageOffset)) xaddr = uintptr(r0) @@ -746,14 +702,3 @@ func setrlimit(resource int, rlim *rlimit32) (err error) { } return } - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go index a134f9a4d2..1e20d72df2 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go @@ -46,27 +46,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func dup2(oldfd int, newfd int) (err error) { - _, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func EpollCreate(size int) (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE, uintptr(size), 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { var _p0 unsafe.Pointer if len(events) > 0 { @@ -717,14 +696,3 @@ func stat(path string, st *stat_t) (err error) { } return } - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go index b1fff2d946..82b5e2d9ed 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go @@ -46,27 +46,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func dup2(oldfd int, newfd int) (err error) { - _, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func EpollCreate(size int) (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE, uintptr(size), 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { var _p0 unsafe.Pointer if len(events) > 0 { @@ -717,14 +696,3 @@ func stat(path string, st *stat_t) (err error) { } return } - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go index d13d6da01e..a0440c1d43 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go @@ -46,27 +46,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func dup2(oldfd int, newfd int) (err error) { - _, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func EpollCreate(size int) (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE, uintptr(size), 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { var _p0 unsafe.Pointer if len(events) > 0 { @@ -544,17 +523,6 @@ func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func InotifyInit() (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT, 0, 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Ioperm(from int, num int, on int) (err error) { _, _, e1 := Syscall(SYS_IOPERM, uintptr(from), uintptr(num), uintptr(on)) if e1 != 0 { @@ -706,18 +674,6 @@ func Pause() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe() (p1 int, p2 int, err error) { - r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0) - p1 = int(r0) - p2 = int(r1) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func mmap2(addr uintptr, length uintptr, prot int, flags int, fd int, pageOffset uintptr) (xaddr uintptr, err error) { r0, _, e1 := Syscall6(SYS_MMAP2, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flags), uintptr(fd), uintptr(pageOffset)) xaddr = uintptr(r0) @@ -746,14 +702,3 @@ func setrlimit(resource int, rlim *rlimit32) (err error) { } return } - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc.go index 927cf1a00f..5864b9ca64 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc.go @@ -46,27 +46,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func dup2(oldfd int, newfd int) (err error) { - _, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func EpollCreate(size int) (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE, uintptr(size), 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { var _p0 unsafe.Pointer if len(events) > 0 { @@ -161,17 +140,6 @@ func Getuid() (uid int) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func InotifyInit() (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT, 0, 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Ioperm(from int, num int, on int) (err error) { _, _, e1 := Syscall(SYS_IOPERM, uintptr(from), uintptr(num), uintptr(on)) if e1 != 0 { @@ -717,27 +685,6 @@ func setrlimit(resource int, rlim *rlimit32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe(p *[2]_C_int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func syncFileRange2(fd int, flags int, off int64, n int64) (err error) { _, _, e1 := Syscall6(SYS_SYNC_FILE_RANGE2, uintptr(fd), uintptr(flags), uintptr(off>>32), uintptr(off), uintptr(n>>32), uintptr(n)) if e1 != 0 { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go index da8ec03966..beeb49e342 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go @@ -46,27 +46,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func dup2(oldfd int, newfd int) (err error) { - _, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func EpollCreate(size int) (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE, uintptr(size), 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { var _p0 unsafe.Pointer if len(events) > 0 { @@ -191,17 +170,6 @@ func Getuid() (uid int) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func InotifyInit() (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT, 0, 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Ioperm(from int, num int, on int) (err error) { _, _, e1 := Syscall(SYS_IOPERM, uintptr(from), uintptr(num), uintptr(on)) if e1 != 0 { @@ -763,27 +731,6 @@ func utimes(path string, times *[2]Timeval) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe(p *[2]_C_int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func syncFileRange2(fd int, flags int, off int64, n int64) (err error) { _, _, e1 := Syscall6(SYS_SYNC_FILE_RANGE2, uintptr(fd), uintptr(flags), uintptr(off), uintptr(n), 0, 0) if e1 != 0 { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go index 083f493bb6..53139b82c7 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go @@ -46,27 +46,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func dup2(oldfd int, newfd int) (err error) { - _, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func EpollCreate(size int) (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE, uintptr(size), 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { var _p0 unsafe.Pointer if len(events) > 0 { @@ -191,17 +170,6 @@ func Getuid() (uid int) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func InotifyInit() (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT, 0, 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Ioperm(from int, num int, on int) (err error) { _, _, e1 := Syscall(SYS_IOPERM, uintptr(from), uintptr(num), uintptr(on)) if e1 != 0 { @@ -763,27 +731,6 @@ func utimes(path string, times *[2]Timeval) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe(p *[2]_C_int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func syncFileRange2(fd int, flags int, off int64, n int64) (err error) { _, _, e1 := Syscall6(SYS_SYNC_FILE_RANGE2, uintptr(fd), uintptr(flags), uintptr(off), uintptr(n), 0, 0) if e1 != 0 { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go index bb347407d3..202add37d1 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go @@ -46,27 +46,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func dup2(oldfd int, newfd int) (err error) { - _, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func EpollCreate(size int) (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE, uintptr(size), 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { var _p0 unsafe.Pointer if len(events) > 0 { @@ -191,17 +170,6 @@ func Getuid() (uid int) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func InotifyInit() (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT, 0, 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Lchown(path string, uid int, gid int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -553,17 +521,6 @@ func utimes(path string, times *[2]Timeval) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func kexecFileLoad(kernelFd int, initrdFd int, cmdlineLen int, cmdline string, flags int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(cmdline) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_sparc64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_sparc64.go index 8edc517e1e..2ab268c343 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_sparc64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_sparc64.go @@ -73,16 +73,6 @@ func Fadvise(fd int, offset int64, length int64, advice int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func dup2(oldfd int, newfd int) (err error) { - _, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Fchown(fd int, uid int, gid int) (err error) { _, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid)) if e1 != 0 { @@ -180,17 +170,6 @@ func Getuid() (uid int) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func InotifyInit() (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT, 0, 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Lchown(path string, uid int, gid int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -718,24 +697,3 @@ func utimes(path string, times *[2]Timeval) (err error) { } return } - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func pipe(p *[2]_C_int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} 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 4c8dc0ba2e..7efe5ccba3 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 @@ -209,6 +209,92 @@ type RawSockaddrCtl struct { Sc_reserved [5]uint32 } +type RawSockaddrVM struct { + Len uint8 + Family uint8 + Reserved1 uint16 + Port uint32 + Cid uint32 +} + +type XVSockPCB struct { + Xv_len uint32 + Xv_vsockpp uint64 + Xvp_local_cid uint32 + Xvp_local_port uint32 + Xvp_remote_cid uint32 + Xvp_remote_port uint32 + Xvp_rxcnt uint32 + Xvp_txcnt uint32 + Xvp_peer_rxhiwat uint32 + Xvp_peer_rxcnt uint32 + Xvp_last_pid int32 + Xvp_gencnt uint64 + Xv_socket XSocket + _ [4]byte +} + +type XSocket struct { + Xso_len uint32 + Xso_so uint32 + So_type int16 + So_options int16 + So_linger int16 + So_state int16 + So_pcb uint32 + Xso_protocol int32 + Xso_family int32 + So_qlen int16 + So_incqlen int16 + So_qlimit int16 + So_timeo int16 + So_error uint16 + So_pgid int32 + So_oobmark uint32 + So_rcv XSockbuf + So_snd XSockbuf + So_uid uint32 +} + +type XSocket64 struct { + Xso_len uint32 + _ [8]byte + So_type int16 + So_options int16 + So_linger int16 + So_state int16 + _ [8]byte + Xso_protocol int32 + Xso_family int32 + So_qlen int16 + So_incqlen int16 + So_qlimit int16 + So_timeo int16 + So_error uint16 + So_pgid int32 + So_oobmark uint32 + So_rcv XSockbuf + So_snd XSockbuf + So_uid uint32 +} + +type XSockbuf struct { + Cc uint32 + Hiwat uint32 + Mbcnt uint32 + Mbmax uint32 + Lowat int32 + Flags int16 + Timeo int16 +} + +type XVSockPgen struct { + Len uint32 + Count uint64 + Gen uint64 + Sogen uint64 +} + type _Socklen uint32 type Xucred struct { @@ -287,6 +373,11 @@ const ( SizeofSockaddrUnix = 0x6a SizeofSockaddrDatalink = 0x14 SizeofSockaddrCtl = 0x20 + SizeofSockaddrVM = 0xc + SizeofXvsockpcb = 0xa8 + SizeofXSocket = 0x64 + SizeofXSockbuf = 0x18 + SizeofXVSockPgen = 0x20 SizeofXucred = 0x4c SizeofLinger = 0x8 SizeofIovec = 0x10 @@ -639,3 +730,39 @@ type Ucred struct { Ngroups int16 Groups [16]uint32 } + +type SysvIpcPerm struct { + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint16 + _ uint16 + _ int32 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Segsz uint64 + Lpid int32 + Cpid int32 + Nattch uint16 + _ [34]byte +} + +const ( + IPC_CREAT = 0x200 + IPC_EXCL = 0x400 + IPC_NOWAIT = 0x800 + IPC_PRIVATE = 0x0 +) + +const ( + IPC_RMID = 0x0 + IPC_SET = 0x1 + IPC_STAT = 0x2 +) + +const ( + SHM_RDONLY = 0x1000 + SHM_RND = 0x2000 +) 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 96f0e6ae2a..b23a2efe81 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 @@ -209,6 +209,92 @@ type RawSockaddrCtl struct { Sc_reserved [5]uint32 } +type RawSockaddrVM struct { + Len uint8 + Family uint8 + Reserved1 uint16 + Port uint32 + Cid uint32 +} + +type XVSockPCB struct { + Xv_len uint32 + Xv_vsockpp uint64 + Xvp_local_cid uint32 + Xvp_local_port uint32 + Xvp_remote_cid uint32 + Xvp_remote_port uint32 + Xvp_rxcnt uint32 + Xvp_txcnt uint32 + Xvp_peer_rxhiwat uint32 + Xvp_peer_rxcnt uint32 + Xvp_last_pid int32 + Xvp_gencnt uint64 + Xv_socket XSocket + _ [4]byte +} + +type XSocket struct { + Xso_len uint32 + Xso_so uint32 + So_type int16 + So_options int16 + So_linger int16 + So_state int16 + So_pcb uint32 + Xso_protocol int32 + Xso_family int32 + So_qlen int16 + So_incqlen int16 + So_qlimit int16 + So_timeo int16 + So_error uint16 + So_pgid int32 + So_oobmark uint32 + So_rcv XSockbuf + So_snd XSockbuf + So_uid uint32 +} + +type XSocket64 struct { + Xso_len uint32 + _ [8]byte + So_type int16 + So_options int16 + So_linger int16 + So_state int16 + _ [8]byte + Xso_protocol int32 + Xso_family int32 + So_qlen int16 + So_incqlen int16 + So_qlimit int16 + So_timeo int16 + So_error uint16 + So_pgid int32 + So_oobmark uint32 + So_rcv XSockbuf + So_snd XSockbuf + So_uid uint32 +} + +type XSockbuf struct { + Cc uint32 + Hiwat uint32 + Mbcnt uint32 + Mbmax uint32 + Lowat int32 + Flags int16 + Timeo int16 +} + +type XVSockPgen struct { + Len uint32 + Count uint64 + Gen uint64 + Sogen uint64 +} + type _Socklen uint32 type Xucred struct { @@ -287,6 +373,11 @@ const ( SizeofSockaddrUnix = 0x6a SizeofSockaddrDatalink = 0x14 SizeofSockaddrCtl = 0x20 + SizeofSockaddrVM = 0xc + SizeofXvsockpcb = 0xa8 + SizeofXSocket = 0x64 + SizeofXSockbuf = 0x18 + SizeofXVSockPgen = 0x20 SizeofXucred = 0x4c SizeofLinger = 0x8 SizeofIovec = 0x10 @@ -639,3 +730,39 @@ type Ucred struct { Ngroups int16 Groups [16]uint32 } + +type SysvIpcPerm struct { + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint16 + _ uint16 + _ int32 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Segsz uint64 + Lpid int32 + Cpid int32 + Nattch uint16 + _ [34]byte +} + +const ( + IPC_CREAT = 0x200 + IPC_EXCL = 0x400 + IPC_NOWAIT = 0x800 + IPC_PRIVATE = 0x0 +) + +const ( + IPC_RMID = 0x0 + IPC_SET = 0x1 + IPC_STAT = 0x2 +) + +const ( + SHM_RDONLY = 0x1000 + SHM_RND = 0x2000 +) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go index 1f99c024af..4eec078e52 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go @@ -31,6 +31,8 @@ type Timeval struct { Usec int32 } +type Time_t int32 + type Rusage struct { Utime Timeval Stime Timeval diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go index ddf0305a5d..7622904a53 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go @@ -31,6 +31,8 @@ type Timeval struct { Usec int64 } +type Time_t int64 + type Rusage struct { Utime Timeval Stime Timeval diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go index dce0a5c80c..19223ce8ec 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go @@ -33,6 +33,8 @@ type Timeval struct { _ [4]byte } +type Time_t int32 + type Rusage struct { Utime Timeval Stime Timeval diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm64.go index e232447025..8e3e33f679 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm64.go @@ -31,6 +31,8 @@ type Timeval struct { Usec int64 } +type Time_t int64 + type Rusage struct { Utime Timeval Stime Timeval diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_illumos_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_illumos_amd64.go index 236f37ef6f..4c485261d6 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_illumos_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_illumos_amd64.go @@ -13,6 +13,8 @@ const ( I_STR = 0x5308 I_POP = 0x5303 I_PUSH = 0x5302 + I_LINK = 0x530c + I_UNLINK = 0x530d I_PLINK = 0x5316 I_PUNLINK = 0x5317 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 4b73bb3b63..249ecfcd4c 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 @@ -3923,3 +3923,36 @@ const ( NFC_SDP_ATTR_URI = 0x1 NFC_SDP_ATTR_SAP = 0x2 ) + +type LandlockRulesetAttr struct { + Access_fs uint64 +} + +type LandlockPathBeneathAttr struct { + Allowed_access uint64 + Parent_fd int32 +} + +const ( + LANDLOCK_RULE_PATH_BENEATH = 0x1 +) + +const ( + IPC_CREAT = 0x200 + IPC_EXCL = 0x400 + IPC_NOWAIT = 0x800 + IPC_PRIVATE = 0x0 + + ipc_64 = 0x100 +) + +const ( + IPC_RMID = 0x0 + IPC_SET = 0x1 + IPC_STAT = 0x2 +) + +const ( + SHM_RDONLY = 0x1000 + SHM_RND = 0x2000 +) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_386.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_386.go index 72f2e96f32..eeeb9aa39a 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_386.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_386.go @@ -635,3 +635,36 @@ const ( PPS_GETCAP = 0x800470a3 PPS_FETCH = 0xc00470a4 ) + +const ( + PIDFD_NONBLOCK = 0x800 +) + +type SysvIpcPerm struct { + Key int32 + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint16 + _ [2]uint8 + Seq uint16 + _ uint16 + _ uint32 + _ uint32 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Segsz uint32 + Atime uint32 + Atime_high uint32 + Dtime uint32 + Dtime_high uint32 + Ctime uint32 + Ctime_high uint32 + Cpid int32 + Lpid int32 + Nattch uint32 + _ uint32 + _ uint32 +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go index d5f018d13d..d30e1155cc 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go @@ -653,3 +653,33 @@ const ( PPS_GETCAP = 0x800870a3 PPS_FETCH = 0xc00870a4 ) + +const ( + PIDFD_NONBLOCK = 0x800 +) + +type SysvIpcPerm struct { + Key int32 + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint32 + _ [0]uint8 + Seq uint16 + _ uint16 + _ uint64 + _ uint64 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Segsz uint64 + Atime int64 + Dtime int64 + Ctime int64 + Cpid int32 + Lpid int32 + Nattch uint64 + _ uint64 + _ uint64 +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go index 675446d936..69d0297520 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go @@ -630,3 +630,36 @@ const ( PPS_GETCAP = 0x800470a3 PPS_FETCH = 0xc00470a4 ) + +const ( + PIDFD_NONBLOCK = 0x800 +) + +type SysvIpcPerm struct { + Key int32 + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint16 + _ [2]uint8 + Seq uint16 + _ uint16 + _ uint32 + _ uint32 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Segsz uint32 + Atime uint32 + Atime_high uint32 + Dtime uint32 + Dtime_high uint32 + Ctime uint32 + Ctime_high uint32 + Cpid int32 + Lpid int32 + Nattch uint32 + _ uint32 + _ uint32 +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go index 711d0711cd..28a0455bc9 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go @@ -632,3 +632,33 @@ const ( PPS_GETCAP = 0x800870a3 PPS_FETCH = 0xc00870a4 ) + +const ( + PIDFD_NONBLOCK = 0x800 +) + +type SysvIpcPerm struct { + Key int32 + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint32 + _ [0]uint8 + Seq uint16 + _ uint16 + _ uint64 + _ uint64 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Segsz uint64 + Atime int64 + Dtime int64 + Ctime int64 + Cpid int32 + Lpid int32 + Nattch uint64 + _ uint64 + _ uint64 +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go index c1131c7411..64a845483d 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go @@ -636,3 +636,35 @@ const ( PPS_GETCAP = 0x400470a3 PPS_FETCH = 0xc00470a4 ) + +const ( + PIDFD_NONBLOCK = 0x80 +) + +type SysvIpcPerm struct { + Key int32 + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint32 + _ [0]uint8 + Seq uint16 + _ uint16 + _ uint32 + _ uint32 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Segsz uint32 + Atime uint32 + Dtime uint32 + Ctime uint32 + Cpid int32 + Lpid int32 + Nattch uint32 + Atime_high uint16 + Dtime_high uint16 + Ctime_high uint16 + _ uint16 +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go index 91d5574ff9..a1b7dee412 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go @@ -635,3 +635,33 @@ const ( PPS_GETCAP = 0x400870a3 PPS_FETCH = 0xc00870a4 ) + +const ( + PIDFD_NONBLOCK = 0x80 +) + +type SysvIpcPerm struct { + Key int32 + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint32 + _ [0]uint8 + Seq uint16 + _ uint16 + _ uint64 + _ uint64 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Segsz uint64 + Atime int64 + Dtime int64 + Ctime int64 + Cpid int32 + Lpid int32 + Nattch uint64 + _ uint64 + _ uint64 +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go index 5d721497b7..936fa6a266 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go @@ -635,3 +635,33 @@ const ( PPS_GETCAP = 0x400870a3 PPS_FETCH = 0xc00870a4 ) + +const ( + PIDFD_NONBLOCK = 0x80 +) + +type SysvIpcPerm struct { + Key int32 + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint32 + _ [0]uint8 + Seq uint16 + _ uint16 + _ uint64 + _ uint64 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Segsz uint64 + Atime int64 + Dtime int64 + Ctime int64 + Cpid int32 + Lpid int32 + Nattch uint64 + _ uint64 + _ uint64 +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go index a5addd06aa..5dd546fbf0 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go @@ -636,3 +636,35 @@ const ( PPS_GETCAP = 0x400470a3 PPS_FETCH = 0xc00470a4 ) + +const ( + PIDFD_NONBLOCK = 0x80 +) + +type SysvIpcPerm struct { + Key int32 + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint32 + _ [0]uint8 + Seq uint16 + _ uint16 + _ uint32 + _ uint32 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Segsz uint32 + Atime uint32 + Dtime uint32 + Ctime uint32 + Cpid int32 + Lpid int32 + Nattch uint32 + Atime_high uint16 + Dtime_high uint16 + Ctime_high uint16 + _ uint16 +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go index bb6b03dfcb..947b32e434 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go @@ -642,3 +642,37 @@ const ( PPS_GETCAP = 0x400470a3 PPS_FETCH = 0xc00470a4 ) + +const ( + PIDFD_NONBLOCK = 0x800 +) + +type SysvIpcPerm struct { + Key int32 + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint32 + Seq uint32 + _ uint32 + _ uint64 + _ uint64 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Atime_high uint32 + Atime uint32 + Dtime_high uint32 + Dtime uint32 + Ctime_high uint32 + Ctime uint32 + _ uint32 + Segsz uint32 + Cpid int32 + Lpid int32 + Nattch uint32 + _ uint32 + _ uint32 + _ [4]byte +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go index 7637243b7b..2a606151b0 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go @@ -642,3 +642,32 @@ const ( PPS_GETCAP = 0x400870a3 PPS_FETCH = 0xc00870a4 ) + +const ( + PIDFD_NONBLOCK = 0x800 +) + +type SysvIpcPerm struct { + Key int32 + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint32 + Seq uint32 + _ uint32 + _ uint64 + _ uint64 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Atime int64 + Dtime int64 + Ctime int64 + Segsz uint64 + Cpid int32 + Lpid int32 + Nattch uint64 + _ uint64 + _ uint64 +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go index a1a28e525f..d0d735d02c 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go @@ -642,3 +642,32 @@ const ( PPS_GETCAP = 0x400870a3 PPS_FETCH = 0xc00870a4 ) + +const ( + PIDFD_NONBLOCK = 0x800 +) + +type SysvIpcPerm struct { + Key int32 + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint32 + Seq uint32 + _ uint32 + _ uint64 + _ uint64 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Atime int64 + Dtime int64 + Ctime int64 + Segsz uint64 + Cpid int32 + Lpid int32 + Nattch uint64 + _ uint64 + _ uint64 +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go index e0a8a13622..95e3d6d06f 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go @@ -660,3 +660,33 @@ const ( PPS_GETCAP = 0x800870a3 PPS_FETCH = 0xc00870a4 ) + +const ( + PIDFD_NONBLOCK = 0x800 +) + +type SysvIpcPerm struct { + Key int32 + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint32 + _ [0]uint8 + Seq uint16 + _ uint16 + _ uint64 + _ uint64 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Segsz uint64 + Atime int64 + Dtime int64 + Ctime int64 + Cpid int32 + Lpid int32 + Nattch uint64 + _ uint64 + _ uint64 +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go index 21d6e56c70..cccf1ef26a 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go @@ -656,3 +656,32 @@ const ( PPS_GETCAP = 0x800870a3 PPS_FETCH = 0xc00870a4 ) + +const ( + PIDFD_NONBLOCK = 0x800 +) + +type SysvIpcPerm struct { + Key int32 + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint32 + _ uint16 + Seq uint16 + _ uint64 + _ uint64 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Segsz uint64 + Atime int64 + Dtime int64 + Ctime int64 + Cpid int32 + Lpid int32 + Nattch uint64 + _ uint64 + _ uint64 +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go index 0531e98f64..44fcbe4e9a 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go @@ -637,3 +637,32 @@ const ( PPS_GETCAP = 0x400870a3 PPS_FETCH = 0xc00870a4 ) + +const ( + PIDFD_NONBLOCK = 0x4000 +) + +type SysvIpcPerm struct { + Key int32 + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint32 + _ uint16 + Seq uint16 + _ uint64 + _ uint64 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Atime int64 + Dtime int64 + Ctime int64 + Segsz uint64 + Cpid int32 + Lpid int32 + Nattch uint64 + _ uint64 + _ uint64 +} diff --git a/src/cmd/vendor/golang.org/x/sys/windows/memory_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/memory_windows.go index 1adb60739a..6dc0920a84 100644 --- a/src/cmd/vendor/golang.org/x/sys/windows/memory_windows.go +++ b/src/cmd/vendor/golang.org/x/sys/windows/memory_windows.go @@ -35,3 +35,14 @@ const ( QUOTA_LIMITS_HARDWS_MAX_DISABLE = 0x00000008 QUOTA_LIMITS_HARDWS_MAX_ENABLE = 0x00000004 ) + +type MemoryBasicInformation struct { + BaseAddress uintptr + AllocationBase uintptr + AllocationProtect uint32 + PartitionId uint16 + RegionSize uintptr + State uint32 + Protect uint32 + Type uint32 +} 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 1215b2ae20..d3b59ae69c 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 @@ -274,6 +274,11 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys VirtualAlloc(address uintptr, size uintptr, alloctype uint32, protect uint32) (value uintptr, err error) = kernel32.VirtualAlloc //sys VirtualFree(address uintptr, size uintptr, freetype uint32) (err error) = kernel32.VirtualFree //sys VirtualProtect(address uintptr, size uintptr, newprotect uint32, oldprotect *uint32) (err error) = kernel32.VirtualProtect +//sys VirtualProtectEx(process Handle, address uintptr, size uintptr, newProtect uint32, oldProtect *uint32) (err error) = kernel32.VirtualProtectEx +//sys VirtualQuery(address uintptr, buffer *MemoryBasicInformation, length uintptr) (err error) = kernel32.VirtualQuery +//sys VirtualQueryEx(process Handle, address uintptr, buffer *MemoryBasicInformation, length uintptr) (err error) = kernel32.VirtualQueryEx +//sys ReadProcessMemory(process Handle, baseAddress uintptr, buffer *byte, size uintptr, numberOfBytesRead *uintptr) (err error) = kernel32.ReadProcessMemory +//sys WriteProcessMemory(process Handle, baseAddress uintptr, buffer *byte, size uintptr, numberOfBytesWritten *uintptr) (err error) = kernel32.WriteProcessMemory //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 FindFirstChangeNotification(path string, watchSubtree bool, notifyFilter uint32) (handle Handle, err error) [failretval==InvalidHandle] = kernel32.FindFirstChangeNotificationW @@ -398,6 +403,11 @@ func NewCallbackCDecl(fn interface{}) uintptr { // Process Status API (PSAPI) //sys EnumProcesses(processIds []uint32, bytesReturned *uint32) (err error) = psapi.EnumProcesses +//sys EnumProcessModules(process Handle, module *Handle, cb uint32, cbNeeded *uint32) (err error) = psapi.EnumProcessModules +//sys EnumProcessModulesEx(process Handle, module *Handle, cb uint32, cbNeeded *uint32, filterFlag uint32) (err error) = psapi.EnumProcessModulesEx +//sys GetModuleInformation(process Handle, module Handle, modinfo *ModuleInfo, cb uint32) (err error) = psapi.GetModuleInformation +//sys GetModuleFileNameEx(process Handle, module Handle, filename *uint16, size uint32) (err error) = psapi.GetModuleFileNameExW +//sys GetModuleBaseName(process Handle, module Handle, baseName *uint16, size uint32) (err error) = psapi.GetModuleBaseNameW // NT Native APIs //sys rtlNtStatusToDosErrorNoTeb(ntstatus NTStatus) (ret syscall.Errno) = ntdll.RtlNtStatusToDosErrorNoTeb 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 17f03312df..88e0ce5d0d 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 @@ -242,6 +242,14 @@ const ( TH32CS_INHERIT = 0x80000000 ) +const ( + // flags for EnumProcessModulesEx + LIST_MODULES_32BIT = 0x01 + LIST_MODULES_64BIT = 0x02 + LIST_MODULES_ALL = 0x03 + LIST_MODULES_DEFAULT = 0x00 +) + const ( // filters for ReadDirectoryChangesW and FindFirstChangeNotificationW FILE_NOTIFY_CHANGE_FILE_NAME = 0x001 @@ -2773,3 +2781,9 @@ const ( // Flag for QueryFullProcessImageName. const PROCESS_NAME_NATIVE = 1 + +type ModuleInfo struct { + BaseOfDll uintptr + SizeOfImage uint32 + EntryPoint uintptr +} 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 2083ec376e..4ea788e4c4 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 @@ -303,6 +303,7 @@ var ( procReadConsoleW = modkernel32.NewProc("ReadConsoleW") procReadDirectoryChangesW = modkernel32.NewProc("ReadDirectoryChangesW") procReadFile = modkernel32.NewProc("ReadFile") + procReadProcessMemory = modkernel32.NewProc("ReadProcessMemory") procReleaseMutex = modkernel32.NewProc("ReleaseMutex") procRemoveDirectoryW = modkernel32.NewProc("RemoveDirectoryW") procResetEvent = modkernel32.NewProc("ResetEvent") @@ -345,12 +346,16 @@ var ( procVirtualFree = modkernel32.NewProc("VirtualFree") procVirtualLock = modkernel32.NewProc("VirtualLock") procVirtualProtect = modkernel32.NewProc("VirtualProtect") + procVirtualProtectEx = modkernel32.NewProc("VirtualProtectEx") + procVirtualQuery = modkernel32.NewProc("VirtualQuery") + procVirtualQueryEx = modkernel32.NewProc("VirtualQueryEx") procVirtualUnlock = modkernel32.NewProc("VirtualUnlock") procWTSGetActiveConsoleSessionId = modkernel32.NewProc("WTSGetActiveConsoleSessionId") procWaitForMultipleObjects = modkernel32.NewProc("WaitForMultipleObjects") procWaitForSingleObject = modkernel32.NewProc("WaitForSingleObject") procWriteConsoleW = modkernel32.NewProc("WriteConsoleW") procWriteFile = modkernel32.NewProc("WriteFile") + procWriteProcessMemory = modkernel32.NewProc("WriteProcessMemory") procAcceptEx = modmswsock.NewProc("AcceptEx") procGetAcceptExSockaddrs = modmswsock.NewProc("GetAcceptExSockaddrs") procTransmitFile = modmswsock.NewProc("TransmitFile") @@ -377,7 +382,12 @@ var ( procCoTaskMemFree = modole32.NewProc("CoTaskMemFree") procCoUninitialize = modole32.NewProc("CoUninitialize") procStringFromGUID2 = modole32.NewProc("StringFromGUID2") + procEnumProcessModules = modpsapi.NewProc("EnumProcessModules") + procEnumProcessModulesEx = modpsapi.NewProc("EnumProcessModulesEx") procEnumProcesses = modpsapi.NewProc("EnumProcesses") + procGetModuleBaseNameW = modpsapi.NewProc("GetModuleBaseNameW") + procGetModuleFileNameExW = modpsapi.NewProc("GetModuleFileNameExW") + procGetModuleInformation = modpsapi.NewProc("GetModuleInformation") procSubscribeServiceChangeNotifications = modsechost.NewProc("SubscribeServiceChangeNotifications") procUnsubscribeServiceChangeNotifications = modsechost.NewProc("UnsubscribeServiceChangeNotifications") procGetUserNameExW = modsecur32.NewProc("GetUserNameExW") @@ -2631,6 +2641,14 @@ func ReadFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) ( return } +func ReadProcessMemory(process Handle, baseAddress uintptr, buffer *byte, size uintptr, numberOfBytesRead *uintptr) (err error) { + r1, _, e1 := syscall.Syscall6(procReadProcessMemory.Addr(), 5, uintptr(process), uintptr(baseAddress), uintptr(unsafe.Pointer(buffer)), uintptr(size), uintptr(unsafe.Pointer(numberOfBytesRead)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func ReleaseMutex(mutex Handle) (err error) { r1, _, e1 := syscall.Syscall(procReleaseMutex.Addr(), 1, uintptr(mutex), 0, 0) if r1 == 0 { @@ -2985,6 +3003,30 @@ func VirtualProtect(address uintptr, size uintptr, newprotect uint32, oldprotect return } +func VirtualProtectEx(process Handle, address uintptr, size uintptr, newProtect uint32, oldProtect *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procVirtualProtectEx.Addr(), 5, uintptr(process), uintptr(address), uintptr(size), uintptr(newProtect), uintptr(unsafe.Pointer(oldProtect)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func VirtualQuery(address uintptr, buffer *MemoryBasicInformation, length uintptr) (err error) { + r1, _, e1 := syscall.Syscall(procVirtualQuery.Addr(), 3, uintptr(address), uintptr(unsafe.Pointer(buffer)), uintptr(length)) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func VirtualQueryEx(process Handle, address uintptr, buffer *MemoryBasicInformation, length uintptr) (err error) { + r1, _, e1 := syscall.Syscall6(procVirtualQueryEx.Addr(), 4, uintptr(process), uintptr(address), uintptr(unsafe.Pointer(buffer)), uintptr(length), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func VirtualUnlock(addr uintptr, length uintptr) (err error) { r1, _, e1 := syscall.Syscall(procVirtualUnlock.Addr(), 2, uintptr(addr), uintptr(length), 0) if r1 == 0 { @@ -3041,6 +3083,14 @@ func WriteFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) return } +func WriteProcessMemory(process Handle, baseAddress uintptr, buffer *byte, size uintptr, numberOfBytesWritten *uintptr) (err error) { + r1, _, e1 := syscall.Syscall6(procWriteProcessMemory.Addr(), 5, uintptr(process), uintptr(baseAddress), uintptr(unsafe.Pointer(buffer)), uintptr(size), uintptr(unsafe.Pointer(numberOfBytesWritten)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func AcceptEx(ls Handle, as Handle, buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, recvd *uint32, overlapped *Overlapped) (err error) { r1, _, e1 := syscall.Syscall9(procAcceptEx.Addr(), 8, uintptr(ls), uintptr(as), uintptr(unsafe.Pointer(buf)), uintptr(rxdatalen), uintptr(laddrlen), uintptr(raddrlen), uintptr(unsafe.Pointer(recvd)), uintptr(unsafe.Pointer(overlapped)), 0) if r1 == 0 { @@ -3225,6 +3275,22 @@ func stringFromGUID2(rguid *GUID, lpsz *uint16, cchMax int32) (chars int32) { return } +func EnumProcessModules(process Handle, module *Handle, cb uint32, cbNeeded *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procEnumProcessModules.Addr(), 4, uintptr(process), uintptr(unsafe.Pointer(module)), uintptr(cb), uintptr(unsafe.Pointer(cbNeeded)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func EnumProcessModulesEx(process Handle, module *Handle, cb uint32, cbNeeded *uint32, filterFlag uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procEnumProcessModulesEx.Addr(), 5, uintptr(process), uintptr(unsafe.Pointer(module)), uintptr(cb), uintptr(unsafe.Pointer(cbNeeded)), uintptr(filterFlag), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func EnumProcesses(processIds []uint32, bytesReturned *uint32) (err error) { var _p0 *uint32 if len(processIds) > 0 { @@ -3237,6 +3303,30 @@ func EnumProcesses(processIds []uint32, bytesReturned *uint32) (err error) { return } +func GetModuleBaseName(process Handle, module Handle, baseName *uint16, size uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procGetModuleBaseNameW.Addr(), 4, uintptr(process), uintptr(module), uintptr(unsafe.Pointer(baseName)), uintptr(size), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetModuleFileNameEx(process Handle, module Handle, filename *uint16, size uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procGetModuleFileNameExW.Addr(), 4, uintptr(process), uintptr(module), uintptr(unsafe.Pointer(filename)), uintptr(size), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetModuleInformation(process Handle, module Handle, modinfo *ModuleInfo, cb uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procGetModuleInformation.Addr(), 4, uintptr(process), uintptr(module), uintptr(unsafe.Pointer(modinfo)), uintptr(cb), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func SubscribeServiceChangeNotifications(service Handle, eventType uint32, callback uintptr, callbackCtx uintptr, subscription *uintptr) (ret error) { ret = procSubscribeServiceChangeNotifications.Find() if ret != nil { diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index ecb170d290..ad08e583fb 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -1,4 +1,4 @@ -# github.com/google/pprof v0.0.0-20211001005136-7fe48b4c820b +# github.com/google/pprof v0.0.0-20211104044539-f987b9c94b31 ## explicit; go 1.14 github.com/google/pprof/driver github.com/google/pprof/internal/binutils @@ -15,8 +15,8 @@ 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-20200824232613-28f6c0f3b639 -## explicit +# github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d +## explicit; go 1.12 github.com/ianlancetaylor/demangle # golang.org/x/arch v0.0.0-20210901143047-ebb09ed340f1 ## explicit; go 1.17 @@ -42,7 +42,7 @@ golang.org/x/mod/zip # golang.org/x/sync v0.0.0-20210220032951-036812b2e83c ## explicit golang.org/x/sync/semaphore -# golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e +# golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac ## explicit; go 1.17 golang.org/x/sys/internal/unsafeheader golang.org/x/sys/plan9 diff --git a/src/crypto/aes/asm_ppc64le.s b/src/crypto/aes/asm_ppc64le.s index a69cb78c8b..f3a96a3a17 100644 --- a/src/crypto/aes/asm_ppc64le.s +++ b/src/crypto/aes/asm_ppc64le.s @@ -13,8 +13,8 @@ // Original code can be found at the link below: // https://github.com/dot-asm/cryptogams/blob/master/ppc/aesp8-ppc.pl -// I changed some function names in order to be more likely to go standards. -// For instance, function aes_p8_set_{en,de}crypt_key become +// Some function names were changed to be consistent with Go function +// names. For instance, function aes_p8_set_{en,de}crypt_key become // set{En,De}cryptKeyAsm. I also split setEncryptKeyAsm in two parts // and a new session was created (doEncryptKeyAsm). This was necessary to // avoid arguments overwriting when setDecryptKeyAsm calls setEncryptKeyAsm. @@ -50,452 +50,451 @@ #define BLK_ROUNDS R6 #define BLK_IDX R7 -DATA ·rcon+0x00(SB)/8, $0x0100000001000000 // RCON -DATA ·rcon+0x08(SB)/8, $0x0100000001000000 // RCON -DATA ·rcon+0x10(SB)/8, $0x1b0000001b000000 -DATA ·rcon+0x18(SB)/8, $0x1b0000001b000000 -DATA ·rcon+0x20(SB)/8, $0x0d0e0f0c0d0e0f0c // MASK -DATA ·rcon+0x28(SB)/8, $0x0d0e0f0c0d0e0f0c // MASK -DATA ·rcon+0x30(SB)/8, $0x0000000000000000 -DATA ·rcon+0x38(SB)/8, $0x0000000000000000 +DATA ·rcon+0x00(SB)/8, $0x0100000001000000 // RCON +DATA ·rcon+0x08(SB)/8, $0x0100000001000000 // RCON +DATA ·rcon+0x10(SB)/8, $0x1b0000001b000000 +DATA ·rcon+0x18(SB)/8, $0x1b0000001b000000 +DATA ·rcon+0x20(SB)/8, $0x0d0e0f0c0d0e0f0c // MASK +DATA ·rcon+0x28(SB)/8, $0x0d0e0f0c0d0e0f0c // MASK +DATA ·rcon+0x30(SB)/8, $0x0000000000000000 +DATA ·rcon+0x38(SB)/8, $0x0000000000000000 GLOBL ·rcon(SB), RODATA, $64 // func setEncryptKeyAsm(key *byte, keylen int, enc *uint32) int -TEXT ·setEncryptKeyAsm(SB),NOSPLIT|NOFRAME,$0 +TEXT ·setEncryptKeyAsm(SB), NOSPLIT|NOFRAME, $0 // Load the arguments inside the registers - MOVD key+0(FP), INP - MOVD keylen+8(FP), BITS - MOVD enc+16(FP), OUT - JMP ·doEncryptKeyAsm(SB) + MOVD key+0(FP), INP + MOVD keylen+8(FP), BITS + MOVD enc+16(FP), OUT + JMP ·doEncryptKeyAsm(SB) // This text is used both setEncryptKeyAsm and setDecryptKeyAsm -TEXT ·doEncryptKeyAsm(SB),NOSPLIT|NOFRAME,$0 +TEXT ·doEncryptKeyAsm(SB), NOSPLIT|NOFRAME, $0 // Do not change R10 since it's storing the LR value in setDecryptKeyAsm // Check arguments - MOVD $-1, PTR // li 6,-1 exit code to -1 (255) - CMPU INP, $0 // cmpldi r3,0 input key pointer set? - BC 0x0E, 2, enc_key_abort // beq- .Lenc_key_abort - CMPU OUT, $0 // cmpldi r5,0 output key pointer set? - BC 0x0E, 2, enc_key_abort // beq- .Lenc_key_abort - MOVD $-2, PTR // li 6,-2 exit code to -2 (254) - CMPW BITS, $128 // cmpwi 4,128 greater or equal to 128 - BC 0x0E, 0, enc_key_abort // blt- .Lenc_key_abort - CMPW BITS, $256 // cmpwi 4,256 lesser or equal to 256 - BC 0x0E, 1, enc_key_abort // bgt- .Lenc_key_abort - ANDCC $0x3f, BITS, TEMP // andi. 0,4,0x3f multiple of 64 - BC 0x06, 2, enc_key_abort // bne- .Lenc_key_abort + MOVD $-1, PTR // li 6,-1 exit code to -1 (255) + CMPU INP, $0 // cmpldi r3,0 input key pointer set? + BC 0x0E, 2, enc_key_abort // beq- .Lenc_key_abort + CMPU OUT, $0 // cmpldi r5,0 output key pointer set? + BC 0x0E, 2, enc_key_abort // beq- .Lenc_key_abort + MOVD $-2, PTR // li 6,-2 exit code to -2 (254) + CMPW BITS, $128 // cmpwi 4,128 greater or equal to 128 + BC 0x0E, 0, enc_key_abort // blt- .Lenc_key_abort + CMPW BITS, $256 // cmpwi 4,256 lesser or equal to 256 + BC 0x0E, 1, enc_key_abort // bgt- .Lenc_key_abort + ANDCC $0x3f, BITS, TEMP // andi. 0,4,0x3f multiple of 64 + BC 0x06, 2, enc_key_abort // bne- .Lenc_key_abort - MOVD $·rcon(SB), PTR // PTR point to rcon addr + MOVD $·rcon(SB), PTR // PTR point to rcon addr // Get key from memory and write aligned into VR - NEG INP, R9 // neg 9,3 R9 is ~INP + 1 - LVX (INP)(R0), IN0 // lvx 1,0,3 Load key inside IN0 - ADD $15, INP, INP // addi 3,3,15 Add 15B to INP addr - LVSR (R9)(R0), KEY // lvsr 3,0,9 - MOVD $0x20, R8 // li 8,0x20 R8 = 32 - CMPW BITS, $192 // cmpwi 4,192 Key size == 192? - LVX (INP)(R0), IN1 // lvx 2,0,3 - VSPLTISB $0x0f, MASK // vspltisb 5,0x0f 0x0f0f0f0f... mask - LVX (PTR)(R0), RCON // lvx 4,0,6 Load first 16 bytes into RCON - VXOR KEY, MASK, KEY // vxor 3,3,5 Adjust for byte swap - LVX (PTR)(R8), MASK // lvx 5,8,6 - ADD $0x10, PTR, PTR // addi 6,6,0x10 PTR to next 16 bytes of RCON - VPERM IN0, IN1, KEY, IN0 // vperm 1,1,2,3 Align - MOVD $8, CNT // li 7,8 CNT = 8 - VXOR ZERO, ZERO, ZERO // vxor 0,0,0 Zero to be zero :) - MOVD CNT, CTR // mtctr 7 Set the counter to 8 (rounds) + NEG INP, R9 // neg 9,3 R9 is ~INP + 1 + LVX (INP)(R0), IN0 // lvx 1,0,3 Load key inside IN0 + ADD $15, INP, INP // addi 3,3,15 Add 15B to INP addr + LVSR (R9)(R0), KEY // lvsr 3,0,9 + MOVD $0x20, R8 // li 8,0x20 R8 = 32 + CMPW BITS, $192 // cmpwi 4,192 Key size == 192? + LVX (INP)(R0), IN1 // lvx 2,0,3 + VSPLTISB $0x0f, MASK// vspltisb 5,0x0f 0x0f0f0f0f... mask + LVX (PTR)(R0), RCON // lvx 4,0,6 Load first 16 bytes into RCON + VXOR KEY, MASK, KEY // vxor 3,3,5 Adjust for byte swap + LVX (PTR)(R8), MASK // lvx 5,8,6 + ADD $0x10, PTR, PTR // addi 6,6,0x10 PTR to next 16 bytes of RCON + VPERM IN0, IN1, KEY, IN0 // vperm 1,1,2,3 Align + MOVD $8, CNT // li 7,8 CNT = 8 + VXOR ZERO, ZERO, ZERO // vxor 0,0,0 Zero to be zero :) + MOVD CNT, CTR // mtctr 7 Set the counter to 8 (rounds) - LVSL (OUT)(R0), OUTPERM // lvsl 8,0,5 - VSPLTISB $-1, OUTMASK // vspltisb 9,-1 - LVX (OUT)(R0), OUTHEAD // lvx 10,0,5 - VPERM OUTMASK, ZERO, OUTPERM, OUTMASK // vperm 9,9,0,8 + LVSL (OUT)(R0), OUTPERM // lvsl 8,0,5 + VSPLTISB $-1, OUTMASK // vspltisb 9,-1 + LVX (OUT)(R0), OUTHEAD // lvx 10,0,5 + VPERM OUTMASK, ZERO, OUTPERM, OUTMASK // vperm 9,9,0,8 - BLT loop128 // blt .Loop128 - ADD $8, INP, INP // addi 3,3,8 - BEQ l192 // beq .L192 - ADD $8, INP, INP // addi 3,3,8 - JMP l256 // b .L256 + BLT loop128 // blt .Loop128 + ADD $8, INP, INP // addi 3,3,8 + BEQ l192 // beq .L192 + ADD $8, INP, INP // addi 3,3,8 + JMP l256 // b .L256 loop128: // Key schedule (Round 1 to 8) - VPERM IN0, IN0, MASK, KEY // vperm 3,1,1,5 Rotate-n-splat - VSLDOI $12, ZERO, IN0, TMP // vsldoi 6,0,1,12 - VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8 Rotate - VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 - VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 - VCIPHERLAST KEY, RCON, KEY // vcipherlast 3,3,4 - STVX STAGE, (OUT+R0) // stvx 7,0,5 Write to output - ADD $16, OUT, OUT // addi 5,5,16 Point to the next round + VPERM IN0, IN0, MASK, KEY // vperm 3,1,1,5 Rotate-n-splat + VSLDOI $12, ZERO, IN0, TMP // vsldoi 6,0,1,12 + VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8 Rotate + VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 + VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 + VCIPHERLAST KEY, RCON, KEY // vcipherlast 3,3,4 + STVX STAGE, (OUT+R0) // stvx 7,0,5 Write to output + ADD $16, OUT, OUT // addi 5,5,16 Point to the next round - VXOR IN0, TMP, IN0 // vxor 1,1,6 - VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 - VXOR IN0, TMP, IN0 // vxor 1,1,6 - VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 - VXOR IN0, TMP, IN0 // vxor 1,1,6 - VADDUWM RCON, RCON, RCON // vadduwm 4,4,4 - VXOR IN0, KEY, IN0 // vxor 1,1,3 - BC 0x10, 0, loop128 // bdnz .Loop128 + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VADDUWM RCON, RCON, RCON // vadduwm 4,4,4 + VXOR IN0, KEY, IN0 // vxor 1,1,3 + BC 0x10, 0, loop128 // bdnz .Loop128 - LVX (PTR)(R0), RCON // lvx 4,0,6 Last two round keys + LVX (PTR)(R0), RCON // lvx 4,0,6 Last two round keys // Key schedule (Round 9) - VPERM IN0, IN0, MASK, KEY // vperm 3,1,1,5 Rotate-n-spat - VSLDOI $12, ZERO, IN0, TMP // vsldoi 6,0,1,12 - VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8 Rotate - VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 - VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 - VCIPHERLAST KEY, RCON, KEY // vcipherlast 3,3,4 - STVX STAGE, (OUT+R0) // stvx 7,0,5 Round 9 - ADD $16, OUT, OUT // addi 5,5,16 + VPERM IN0, IN0, MASK, KEY // vperm 3,1,1,5 Rotate-n-spat + VSLDOI $12, ZERO, IN0, TMP // vsldoi 6,0,1,12 + VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8 Rotate + VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 + VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 + VCIPHERLAST KEY, RCON, KEY // vcipherlast 3,3,4 + STVX STAGE, (OUT+R0) // stvx 7,0,5 Round 9 + ADD $16, OUT, OUT // addi 5,5,16 // Key schedule (Round 10) - VXOR IN0, TMP, IN0 // vxor 1,1,6 - VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 - VXOR IN0, TMP, IN0 // vxor 1,1,6 - VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 - VXOR IN0, TMP, IN0 // vxor 1,1,6 - VADDUWM RCON, RCON, RCON // vadduwm 4,4,4 - VXOR IN0, KEY, IN0 // vxor 1,1,3 + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VADDUWM RCON, RCON, RCON // vadduwm 4,4,4 + VXOR IN0, KEY, IN0 // vxor 1,1,3 - VPERM IN0, IN0, MASK, KEY // vperm 3,1,1,5 Rotate-n-splat - VSLDOI $12, ZERO, IN0, TMP // vsldoi 6,0,1,12 - VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8 Rotate - VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 - VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 - VCIPHERLAST KEY, RCON, KEY // vcipherlast 3,3,4 - STVX STAGE, (OUT+R0) // stvx 7,0,5 Round 10 - ADD $16, OUT, OUT // addi 5,5,16 + VPERM IN0, IN0, MASK, KEY // vperm 3,1,1,5 Rotate-n-splat + VSLDOI $12, ZERO, IN0, TMP // vsldoi 6,0,1,12 + VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8 Rotate + VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 + VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 + VCIPHERLAST KEY, RCON, KEY // vcipherlast 3,3,4 + STVX STAGE, (OUT+R0) // stvx 7,0,5 Round 10 + ADD $16, OUT, OUT // addi 5,5,16 // Key schedule (Round 11) - VXOR IN0, TMP, IN0 // vxor 1,1,6 - VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 - VXOR IN0, TMP, IN0 // vxor 1,1,6 - VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 - VXOR IN0, TMP, IN0 // vxor 1,1,6 - VXOR IN0, KEY, IN0 // vxor 1,1,3 - VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8 - VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 - VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 - STVX STAGE, (OUT+R0) // stvx 7,0,5 Round 11 + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VXOR IN0, KEY, IN0 // vxor 1,1,3 + VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8 + VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 + VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 + STVX STAGE, (OUT+R0) // stvx 7,0,5 Round 11 - ADD $15, OUT, INP // addi 3,5,15 - ADD $0x50, OUT, OUT // addi 5,5,0x50 + ADD $15, OUT, INP // addi 3,5,15 + ADD $0x50, OUT, OUT // addi 5,5,0x50 - MOVD $10, ROUNDS // li 8,10 - JMP done // b .Ldone + MOVD $10, ROUNDS // li 8,10 + JMP done // b .Ldone l192: - LVX (INP)(R0), TMP // lvx 6,0,3 - MOVD $4, CNT // li 7,4 - VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8 - VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 - VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 - STVX STAGE, (OUT+R0) // stvx 7,0,5 - ADD $16, OUT, OUT // addi 5,5,16 - VPERM IN1, TMP, KEY, IN1 // vperm 2,2,6,3 - VSPLTISB $8, KEY // vspltisb 3,8 - MOVD CNT, CTR // mtctr 7 - VSUBUBM MASK, KEY, MASK // vsububm 5,5,3 + LVX (INP)(R0), TMP // lvx 6,0,3 + MOVD $4, CNT // li 7,4 + VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8 + VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 + VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 + STVX STAGE, (OUT+R0) // stvx 7,0,5 + ADD $16, OUT, OUT // addi 5,5,16 + VPERM IN1, TMP, KEY, IN1 // vperm 2,2,6,3 + VSPLTISB $8, KEY // vspltisb 3,8 + MOVD CNT, CTR // mtctr 7 + VSUBUBM MASK, KEY, MASK // vsububm 5,5,3 loop192: - VPERM IN1, IN1, MASK, KEY // vperm 3,2,2,5 - VSLDOI $12, ZERO, IN0, TMP // vsldoi 6,0,1,12 - VCIPHERLAST KEY, RCON, KEY // vcipherlast 3,3,4 + VPERM IN1, IN1, MASK, KEY // vperm 3,2,2,5 + VSLDOI $12, ZERO, IN0, TMP // vsldoi 6,0,1,12 + VCIPHERLAST KEY, RCON, KEY // vcipherlast 3,3,4 - VXOR IN0, TMP, IN0 // vxor 1,1,6 - VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 - VXOR IN0, TMP, IN0 // vxor 1,1,6 - VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 - VXOR IN0, TMP, IN0 // vxor 1,1,6 + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 + VXOR IN0, TMP, IN0 // vxor 1,1,6 - VSLDOI $8, ZERO, IN1, STAGE // vsldoi 7,0,2,8 - VSPLTW $3, IN0, TMP // vspltw 6,1,3 - VXOR TMP, IN1, TMP // vxor 6,6,2 - VSLDOI $12, ZERO, IN1, IN1 // vsldoi 2,0,2,12 - VADDUWM RCON, RCON, RCON // vadduwm 4,4,4 - VXOR IN1, TMP, IN1 // vxor 2,2,6 - VXOR IN0, KEY, IN0 // vxor 1,1,3 - VXOR IN1, KEY, IN1 // vxor 2,2,3 - VSLDOI $8, STAGE, IN0, STAGE // vsldoi 7,7,1,8 + VSLDOI $8, ZERO, IN1, STAGE // vsldoi 7,0,2,8 + VSPLTW $3, IN0, TMP // vspltw 6,1,3 + VXOR TMP, IN1, TMP // vxor 6,6,2 + VSLDOI $12, ZERO, IN1, IN1 // vsldoi 2,0,2,12 + VADDUWM RCON, RCON, RCON // vadduwm 4,4,4 + VXOR IN1, TMP, IN1 // vxor 2,2,6 + VXOR IN0, KEY, IN0 // vxor 1,1,3 + VXOR IN1, KEY, IN1 // vxor 2,2,3 + VSLDOI $8, STAGE, IN0, STAGE // vsldoi 7,7,1,8 - VPERM IN1, IN1, MASK, KEY // vperm 3,2,2,5 - VSLDOI $12, ZERO, IN0, TMP // vsldoi 6,0,1,12 - VPERM STAGE, STAGE, OUTPERM, OUTTAIL // vperm 11,7,7,8 - VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 - VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 - VCIPHERLAST KEY, RCON, KEY // vcipherlast 3,3,4 - STVX STAGE, (OUT+R0) // stvx 7,0,5 - ADD $16, OUT, OUT // addi 5,5,16 + VPERM IN1, IN1, MASK, KEY // vperm 3,2,2,5 + VSLDOI $12, ZERO, IN0, TMP // vsldoi 6,0,1,12 + VPERM STAGE, STAGE, OUTPERM, OUTTAIL // vperm 11,7,7,8 + VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 + VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 + VCIPHERLAST KEY, RCON, KEY // vcipherlast 3,3,4 + STVX STAGE, (OUT+R0) // stvx 7,0,5 + ADD $16, OUT, OUT // addi 5,5,16 - VSLDOI $8, IN0, IN1, STAGE // vsldoi 7,1,2,8 - VXOR IN0, TMP, IN0 // vxor 1,1,6 - VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 - VPERM STAGE, STAGE, OUTPERM, OUTTAIL // vperm 11,7,7,8 - VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 - VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 - VXOR IN0, TMP, IN0 // vxor 1,1,6 - VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 - VXOR IN0, TMP, IN0 // vxor 1,1,6 - STVX STAGE, (OUT+R0) // stvx 7,0,5 - ADD $16, OUT, OUT // addi 5,5,16 + VSLDOI $8, IN0, IN1, STAGE // vsldoi 7,1,2,8 + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 + VPERM STAGE, STAGE, OUTPERM, OUTTAIL // vperm 11,7,7,8 + VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 + VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 + VXOR IN0, TMP, IN0 // vxor 1,1,6 + STVX STAGE, (OUT+R0) // stvx 7,0,5 + ADD $16, OUT, OUT // addi 5,5,16 - VSPLTW $3, IN0, TMP // vspltw 6,1,3 - VXOR TMP, IN1, TMP // vxor 6,6,2 - VSLDOI $12, ZERO, IN1, IN1 // vsldoi 2,0,2,12 - VADDUWM RCON, RCON, RCON // vadduwm 4,4,4 - VXOR IN1, TMP, IN1 // vxor 2,2,6 - VXOR IN0, KEY, IN0 // vxor 1,1,3 - VXOR IN1, KEY, IN1 // vxor 2,2,3 - VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8 - VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 - VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 - STVX STAGE, (OUT+R0) // stvx 7,0,5 - ADD $15, OUT, INP // addi 3,5,15 - ADD $16, OUT, OUT // addi 5,5,16 - BC 0x10, 0, loop192 // bdnz .Loop192 + VSPLTW $3, IN0, TMP // vspltw 6,1,3 + VXOR TMP, IN1, TMP // vxor 6,6,2 + VSLDOI $12, ZERO, IN1, IN1 // vsldoi 2,0,2,12 + VADDUWM RCON, RCON, RCON // vadduwm 4,4,4 + VXOR IN1, TMP, IN1 // vxor 2,2,6 + VXOR IN0, KEY, IN0 // vxor 1,1,3 + VXOR IN1, KEY, IN1 // vxor 2,2,3 + VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8 + VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 + VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 + STVX STAGE, (OUT+R0) // stvx 7,0,5 + ADD $15, OUT, INP // addi 3,5,15 + ADD $16, OUT, OUT // addi 5,5,16 + BC 0x10, 0, loop192 // bdnz .Loop192 - MOVD $12, ROUNDS // li 8,12 - ADD $0x20, OUT, OUT // addi 5,5,0x20 - JMP done // b .Ldone + MOVD $12, ROUNDS // li 8,12 + ADD $0x20, OUT, OUT // addi 5,5,0x20 + BR done // b .Ldone l256: - LVX (INP)(R0), TMP // lvx 6,0,3 - MOVD $7, CNT // li 7,7 - MOVD $14, ROUNDS // li 8,14 - VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8 - VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 - VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 - STVX STAGE, (OUT+R0) // stvx 7,0,5 - ADD $16, OUT, OUT // addi 5,5,16 - VPERM IN1, TMP, KEY, IN1 // vperm 2,2,6,3 - MOVD CNT, CTR // mtctr 7 + LVX (INP)(R0), TMP // lvx 6,0,3 + MOVD $7, CNT // li 7,7 + MOVD $14, ROUNDS // li 8,14 + VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8 + VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 + VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 + STVX STAGE, (OUT+R0) // stvx 7,0,5 + ADD $16, OUT, OUT // addi 5,5,16 + VPERM IN1, TMP, KEY, IN1 // vperm 2,2,6,3 + MOVD CNT, CTR // mtctr 7 loop256: - VPERM IN1, IN1, MASK, KEY // vperm 3,2,2,5 - VSLDOI $12, ZERO, IN0, TMP // vsldoi 6,0,1,12 - VPERM IN1, IN1, OUTPERM, OUTTAIL // vperm 11,2,2,8 - VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 - VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 - VCIPHERLAST KEY, RCON, KEY // vcipherlast 3,3,4 - STVX STAGE, (OUT+R0) // stvx 7,0,5 - ADD $16, OUT, OUT // addi 5,5,16 + VPERM IN1, IN1, MASK, KEY // vperm 3,2,2,5 + VSLDOI $12, ZERO, IN0, TMP // vsldoi 6,0,1,12 + VPERM IN1, IN1, OUTPERM, OUTTAIL // vperm 11,2,2,8 + VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 + VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 + VCIPHERLAST KEY, RCON, KEY // vcipherlast 3,3,4 + STVX STAGE, (OUT+R0) // stvx 7,0,5 + ADD $16, OUT, OUT // addi 5,5,16 - VXOR IN0, TMP, IN0 // vxor 1,1,6 - VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 - VXOR IN0, TMP, IN0 // vxor 1,1,6 - VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 - VXOR IN0, TMP, IN0 // vxor 1,1,6 - VADDUWM RCON, RCON, RCON // vadduwm 4,4,4 - VXOR IN0, KEY, IN0 // vxor 1,1,3 - VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8 - VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 - VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 - STVX STAGE, (OUT+R0) // stvx 7,0,5 - ADD $15, OUT, INP // addi 3,5,15 - ADD $16, OUT, OUT // addi 5,5,16 - BC 0x12, 0, done // bdz .Ldone + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VADDUWM RCON, RCON, RCON // vadduwm 4,4,4 + VXOR IN0, KEY, IN0 // vxor 1,1,3 + VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8 + VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 + VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 + STVX STAGE, (OUT+R0) // stvx 7,0,5 + ADD $15, OUT, INP // addi 3,5,15 + ADD $16, OUT, OUT // addi 5,5,16 + BC 0x12, 0, done // bdz .Ldone - VSPLTW $3, IN0, KEY // vspltw 3,1,3 - VSLDOI $12, ZERO, IN1, TMP // vsldoi 6,0,2,12 - VSBOX KEY, KEY // vsbox 3,3 + VSPLTW $3, IN0, KEY // vspltw 3,1,3 + VSLDOI $12, ZERO, IN1, TMP // vsldoi 6,0,2,12 + VSBOX KEY, KEY // vsbox 3,3 - VXOR IN1, TMP, IN1 // vxor 2,2,6 - VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 - VXOR IN1, TMP, IN1 // vxor 2,2,6 - VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 - VXOR IN1, TMP, IN1 // vxor 2,2,6 + VXOR IN1, TMP, IN1 // vxor 2,2,6 + VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 + VXOR IN1, TMP, IN1 // vxor 2,2,6 + VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 + VXOR IN1, TMP, IN1 // vxor 2,2,6 - VXOR IN1, KEY, IN1 // vxor 2,2,3 - JMP loop256 // b .Loop256 + VXOR IN1, KEY, IN1 // vxor 2,2,3 + JMP loop256 // b .Loop256 done: - LVX (INP)(R0), IN1 // lvx 2,0,3 - VSEL OUTHEAD, IN1, OUTMASK, IN1 // vsel 2,10,2,9 - STVX IN1, (INP+R0) // stvx 2,0,3 - MOVD $0, PTR // li 6,0 set PTR to 0 (exit code 0) - MOVW ROUNDS, 0(OUT) // stw 8,0(5) + LVX (INP)(R0), IN1 // lvx 2,0,3 + VSEL OUTHEAD, IN1, OUTMASK, IN1 // vsel 2,10,2,9 + STVX IN1, (INP+R0) // stvx 2,0,3 + MOVD $0, PTR // li 6,0 set PTR to 0 (exit code 0) + MOVW ROUNDS, 0(OUT) // stw 8,0(5) enc_key_abort: - MOVD PTR, INP // mr 3,6 set exit code with PTR value - MOVD INP, ret+24(FP) // Put return value into the FP - RET // blr + MOVD PTR, INP // mr 3,6 set exit code with PTR value + MOVD INP, ret+24(FP) // Put return value into the FP + RET // blr // func setDecryptKeyAsm(key *byte, keylen int, dec *uint32) int -TEXT ·setDecryptKeyAsm(SB),NOSPLIT|NOFRAME,$0 +TEXT ·setDecryptKeyAsm(SB), NOSPLIT|NOFRAME, $0 // Load the arguments inside the registers - MOVD key+0(FP), INP - MOVD keylen+8(FP), BITS - MOVD dec+16(FP), OUT + MOVD key+0(FP), INP + MOVD keylen+8(FP), BITS + MOVD dec+16(FP), OUT - MOVD LR, R10 // mflr 10 - CALL ·doEncryptKeyAsm(SB) - MOVD R10, LR // mtlr 10 + MOVD LR, R10 // mflr 10 + CALL ·doEncryptKeyAsm(SB) + MOVD R10, LR // mtlr 10 - CMPW INP, $0 // cmpwi 3,0 exit 0 = ok - BC 0x06, 2, dec_key_abort // bne- .Ldec_key_abort + CMPW INP, $0 // cmpwi 3,0 exit 0 = ok + BC 0x06, 2, dec_key_abort // bne- .Ldec_key_abort // doEncryptKeyAsm set ROUNDS (R8) with the proper value for each mode - SLW $4, ROUNDS, CNT // slwi 7,8,4 - SUB $240, OUT, INP // subi 3,5,240 - SRW $1, ROUNDS, ROUNDS // srwi 8,8,1 - ADD R7, INP, OUT // add 5,3,7 - MOVD ROUNDS, CTR // mtctr 8 + SLW $4, ROUNDS, CNT // slwi 7,8,4 + SUB $240, OUT, INP // subi 3,5,240 + SRW $1, ROUNDS, ROUNDS // srwi 8,8,1 + ADD R7, INP, OUT // add 5,3,7 + MOVD ROUNDS, CTR // mtctr 8 -// dec_key will invert the key sequence in order to be used for decrypt + // dec_key will invert the key sequence in order to be used for decrypt dec_key: - MOVWZ 0(INP), TEMP // lwz 0, 0(3) - MOVWZ 4(INP), R6 // lwz 6, 4(3) - MOVWZ 8(INP), R7 // lwz 7, 8(3) - MOVWZ 12(INP), R8 // lwz 8, 12(3) - ADD $16, INP, INP // addi 3,3,16 - MOVWZ 0(OUT), R9 // lwz 9, 0(5) - MOVWZ 4(OUT), R10 // lwz 10,4(5) - MOVWZ 8(OUT), R11 // lwz 11,8(5) - MOVWZ 12(OUT), R12 // lwz 12,12(5) - MOVW TEMP, 0(OUT) // stw 0, 0(5) - MOVW R6, 4(OUT) // stw 6, 4(5) - MOVW R7, 8(OUT) // stw 7, 8(5) - MOVW R8, 12(OUT) // stw 8, 12(5) - SUB $16, OUT, OUT // subi 5,5,16 - MOVW R9, -16(INP) // stw 9, -16(3) - MOVW R10, -12(INP) // stw 10,-12(3) - MOVW R11, -8(INP) // stw 11,-8(3) - MOVW R12, -4(INP) // stw 12,-4(3) - BC 0x10, 0, dec_key // bdnz .Ldeckey + MOVWZ 0(INP), TEMP // lwz 0, 0(3) + MOVWZ 4(INP), R6 // lwz 6, 4(3) + MOVWZ 8(INP), R7 // lwz 7, 8(3) + MOVWZ 12(INP), R8 // lwz 8, 12(3) + ADD $16, INP, INP // addi 3,3,16 + MOVWZ 0(OUT), R9 // lwz 9, 0(5) + MOVWZ 4(OUT), R10 // lwz 10,4(5) + MOVWZ 8(OUT), R11 // lwz 11,8(5) + MOVWZ 12(OUT), R12 // lwz 12,12(5) + MOVW TEMP, 0(OUT) // stw 0, 0(5) + MOVW R6, 4(OUT) // stw 6, 4(5) + MOVW R7, 8(OUT) // stw 7, 8(5) + MOVW R8, 12(OUT) // stw 8, 12(5) + SUB $16, OUT, OUT // subi 5,5,16 + MOVW R9, -16(INP) // stw 9, -16(3) + MOVW R10, -12(INP) // stw 10,-12(3) + MOVW R11, -8(INP) // stw 11,-8(3) + MOVW R12, -4(INP) // stw 12,-4(3) + BC 0x10, 0, dec_key // bdnz .Ldeckey - XOR R3, R3, R3 // xor 3,3,3 Clean R3 + XOR R3, R3, R3 // xor 3,3,3 Clean R3 dec_key_abort: - MOVD R3, ret+24(FP) // Put return value into the FP - RET // blr - + MOVD R3, ret+24(FP) // Put return value into the FP + RET // blr // func encryptBlockAsm(dst, src *byte, enc *uint32) -TEXT ·encryptBlockAsm(SB),NOSPLIT|NOFRAME,$0 +TEXT ·encryptBlockAsm(SB), NOSPLIT|NOFRAME, $0 // Load the arguments inside the registers - MOVD dst+0(FP), BLK_OUT - MOVD src+8(FP), BLK_INP - MOVD enc+16(FP), BLK_KEY + MOVD dst+0(FP), BLK_OUT + MOVD src+8(FP), BLK_INP + MOVD enc+16(FP), BLK_KEY - MOVWZ 240(BLK_KEY), BLK_ROUNDS // lwz 6,240(5) - MOVD $15, BLK_IDX // li 7,15 + MOVWZ 240(BLK_KEY), BLK_ROUNDS // lwz 6,240(5) + MOVD $15, BLK_IDX // li 7,15 - LVX (BLK_INP)(R0), ZERO // lvx 0,0,3 - NEG BLK_OUT, R11 // neg 11,4 - LVX (BLK_INP)(BLK_IDX), IN0 // lvx 1,7,3 - LVSL (BLK_INP)(R0), IN1 // lvsl 2,0,3 - VSPLTISB $0x0f, RCON // vspltisb 4,0x0f - LVSR (R11)(R0), KEY // lvsr 3,0,11 - VXOR IN1, RCON, IN1 // vxor 2,2,4 - MOVD $16, BLK_IDX // li 7,16 - VPERM ZERO, IN0, IN1, ZERO // vperm 0,0,1,2 - LVX (BLK_KEY)(R0), IN0 // lvx 1,0,5 - LVSR (BLK_KEY)(R0), MASK // lvsr 5,0,5 - SRW $1, BLK_ROUNDS, BLK_ROUNDS // srwi 6,6,1 - LVX (BLK_KEY)(BLK_IDX), IN1 // lvx 2,7,5 - ADD $16, BLK_IDX, BLK_IDX // addi 7,7,16 - SUB $1, BLK_ROUNDS, BLK_ROUNDS // subi 6,6,1 - VPERM IN1, IN0, MASK, IN0 // vperm 1,2,1,5 + LVX (BLK_INP)(R0), ZERO // lvx 0,0,3 + NEG BLK_OUT, R11 // neg 11,4 + LVX (BLK_INP)(BLK_IDX), IN0 // lvx 1,7,3 + LVSL (BLK_INP)(R0), IN1 // lvsl 2,0,3 + VSPLTISB $0x0f, RCON // vspltisb 4,0x0f + LVSR (R11)(R0), KEY // lvsr 3,0,11 + VXOR IN1, RCON, IN1 // vxor 2,2,4 + MOVD $16, BLK_IDX // li 7,16 + VPERM ZERO, IN0, IN1, ZERO // vperm 0,0,1,2 + LVX (BLK_KEY)(R0), IN0 // lvx 1,0,5 + LVSR (BLK_KEY)(R0), MASK // lvsr 5,0,5 + SRW $1, BLK_ROUNDS, BLK_ROUNDS // srwi 6,6,1 + LVX (BLK_KEY)(BLK_IDX), IN1 // lvx 2,7,5 + ADD $16, BLK_IDX, BLK_IDX // addi 7,7,16 + SUB $1, BLK_ROUNDS, BLK_ROUNDS // subi 6,6,1 + VPERM IN1, IN0, MASK, IN0 // vperm 1,2,1,5 - VXOR ZERO, IN0, ZERO // vxor 0,0,1 - LVX (BLK_KEY)(BLK_IDX), IN0 // lvx 1,7,5 - ADD $16, BLK_IDX, BLK_IDX // addi 7,7,16 - MOVD BLK_ROUNDS, CTR // mtctr 6 + VXOR ZERO, IN0, ZERO // vxor 0,0,1 + LVX (BLK_KEY)(BLK_IDX), IN0 // lvx 1,7,5 + ADD $16, BLK_IDX, BLK_IDX // addi 7,7,16 + MOVD BLK_ROUNDS, CTR // mtctr 6 loop_enc: - VPERM IN0, IN1, MASK, IN1 // vperm 2,1,2,5 - VCIPHER ZERO, IN1, ZERO // vcipher 0,0,2 - LVX (BLK_KEY)(BLK_IDX), IN1 // lvx 2,7,5 - ADD $16, BLK_IDX, BLK_IDX // addi 7,7,16 - VPERM IN1, IN0, MASK, IN0 // vperm 1,2,1,5 - VCIPHER ZERO, IN0, ZERO // vcipher 0,0,1 - LVX (BLK_KEY)(BLK_IDX), IN0 // lvx 1,7,5 - ADD $16, BLK_IDX, BLK_IDX // addi 7,7,16 - BC 0x10, 0, loop_enc // bdnz .Loop_enc + VPERM IN0, IN1, MASK, IN1 // vperm 2,1,2,5 + VCIPHER ZERO, IN1, ZERO // vcipher 0,0,2 + LVX (BLK_KEY)(BLK_IDX), IN1 // lvx 2,7,5 + ADD $16, BLK_IDX, BLK_IDX // addi 7,7,16 + VPERM IN1, IN0, MASK, IN0 // vperm 1,2,1,5 + VCIPHER ZERO, IN0, ZERO // vcipher 0,0,1 + LVX (BLK_KEY)(BLK_IDX), IN0 // lvx 1,7,5 + ADD $16, BLK_IDX, BLK_IDX // addi 7,7,16 + BC 0x10, 0, loop_enc // bdnz .Loop_enc - VPERM IN0, IN1, MASK, IN1 // vperm 2,1,2,5 - VCIPHER ZERO, IN1, ZERO // vcipher 0,0,2 - LVX (BLK_KEY)(BLK_IDX), IN1 // lvx 2,7,5 - VPERM IN1, IN0, MASK, IN0 // vperm 1,2,1,5 - VCIPHERLAST ZERO, IN0, ZERO // vcipherlast 0,0,1 + VPERM IN0, IN1, MASK, IN1 // vperm 2,1,2,5 + VCIPHER ZERO, IN1, ZERO // vcipher 0,0,2 + LVX (BLK_KEY)(BLK_IDX), IN1 // lvx 2,7,5 + VPERM IN1, IN0, MASK, IN0 // vperm 1,2,1,5 + VCIPHERLAST ZERO, IN0, ZERO // vcipherlast 0,0,1 - VSPLTISB $-1, IN1 // vspltisb 2,-1 - VXOR IN0, IN0, IN0 // vxor 1,1,1 - MOVD $15, BLK_IDX // li 7,15 - VPERM IN1, IN0, KEY, IN1 // vperm 2,2,1,3 - VXOR KEY, RCON, KEY // vxor 3,3,4 - LVX (BLK_OUT)(R0), IN0 // lvx 1,0,4 - VPERM ZERO, ZERO, KEY, ZERO // vperm 0,0,0,3 - VSEL IN0, ZERO, IN1, IN0 // vsel 1,1,0,2 - LVX (BLK_OUT)(BLK_IDX), RCON // lvx 4,7,4 - STVX IN0, (BLK_OUT+R0) // stvx 1,0,4 - VSEL ZERO, RCON, IN1, ZERO // vsel 0,0,4,2 - STVX ZERO, (BLK_OUT+BLK_IDX) // stvx 0,7,4 - - RET // blr + VSPLTISB $-1, IN1 // vspltisb 2,-1 + VXOR IN0, IN0, IN0 // vxor 1,1,1 + MOVD $15, BLK_IDX // li 7,15 + VPERM IN1, IN0, KEY, IN1 // vperm 2,2,1,3 + VXOR KEY, RCON, KEY // vxor 3,3,4 + LVX (BLK_OUT)(R0), IN0 // lvx 1,0,4 + VPERM ZERO, ZERO, KEY, ZERO // vperm 0,0,0,3 + VSEL IN0, ZERO, IN1, IN0 // vsel 1,1,0,2 + LVX (BLK_OUT)(BLK_IDX), RCON // lvx 4,7,4 + STVX IN0, (BLK_OUT+R0) // stvx 1,0,4 + VSEL ZERO, RCON, IN1, ZERO // vsel 0,0,4,2 + STVX ZERO, (BLK_OUT+BLK_IDX) // stvx 0,7,4 + RET // blr // func decryptBlockAsm(dst, src *byte, dec *uint32) -TEXT ·decryptBlockAsm(SB),NOSPLIT|NOFRAME,$0 +TEXT ·decryptBlockAsm(SB), NOSPLIT|NOFRAME, $0 // Load the arguments inside the registers - MOVD dst+0(FP), BLK_OUT - MOVD src+8(FP), BLK_INP - MOVD dec+16(FP), BLK_KEY + MOVD dst+0(FP), BLK_OUT + MOVD src+8(FP), BLK_INP + MOVD dec+16(FP), BLK_KEY - MOVWZ 240(BLK_KEY), BLK_ROUNDS // lwz 6,240(5) - MOVD $15, BLK_IDX // li 7,15 + MOVWZ 240(BLK_KEY), BLK_ROUNDS // lwz 6,240(5) + MOVD $15, BLK_IDX // li 7,15 - LVX (BLK_INP)(R0), ZERO // lvx 0,0,3 - NEG BLK_OUT, R11 // neg 11,4 - LVX (BLK_INP)(BLK_IDX), IN0 // lvx 1,7,3 - LVSL (BLK_INP)(R0), IN1 // lvsl 2,0,3 - VSPLTISB $0x0f, RCON // vspltisb 4,0x0f - LVSR (R11)(R0), KEY // lvsr 3,0,11 - VXOR IN1, RCON, IN1 // vxor 2,2,4 - MOVD $16, BLK_IDX // li 7,16 - VPERM ZERO, IN0, IN1, ZERO // vperm 0,0,1,2 - LVX (BLK_KEY)(R0), IN0 // lvx 1,0,5 - LVSR (BLK_KEY)(R0), MASK // lvsr 5,0,5 - SRW $1, BLK_ROUNDS, BLK_ROUNDS // srwi 6,6,1 - LVX (BLK_KEY)(BLK_IDX), IN1 // lvx 2,7,5 - ADD $16, BLK_IDX, BLK_IDX // addi 7,7,16 - SUB $1, BLK_ROUNDS, BLK_ROUNDS // subi 6,6,1 - VPERM IN1, IN0, MASK, IN0 // vperm 1,2,1,5 + LVX (BLK_INP)(R0), ZERO // lvx 0,0,3 + NEG BLK_OUT, R11 // neg 11,4 + LVX (BLK_INP)(BLK_IDX), IN0 // lvx 1,7,3 + LVSL (BLK_INP)(R0), IN1 // lvsl 2,0,3 + VSPLTISB $0x0f, RCON // vspltisb 4,0x0f + LVSR (R11)(R0), KEY // lvsr 3,0,11 + VXOR IN1, RCON, IN1 // vxor 2,2,4 + MOVD $16, BLK_IDX // li 7,16 + VPERM ZERO, IN0, IN1, ZERO // vperm 0,0,1,2 + LVX (BLK_KEY)(R0), IN0 // lvx 1,0,5 + LVSR (BLK_KEY)(R0), MASK // lvsr 5,0,5 + SRW $1, BLK_ROUNDS, BLK_ROUNDS // srwi 6,6,1 + LVX (BLK_KEY)(BLK_IDX), IN1 // lvx 2,7,5 + ADD $16, BLK_IDX, BLK_IDX // addi 7,7,16 + SUB $1, BLK_ROUNDS, BLK_ROUNDS // subi 6,6,1 + VPERM IN1, IN0, MASK, IN0 // vperm 1,2,1,5 - VXOR ZERO, IN0, ZERO // vxor 0,0,1 - LVX (BLK_KEY)(BLK_IDX), IN0 // lvx 1,7,5 - ADD $16, BLK_IDX, BLK_IDX // addi 7,7,16 - MOVD BLK_ROUNDS, CTR // mtctr 6 + VXOR ZERO, IN0, ZERO // vxor 0,0,1 + LVX (BLK_KEY)(BLK_IDX), IN0 // lvx 1,7,5 + ADD $16, BLK_IDX, BLK_IDX // addi 7,7,16 + MOVD BLK_ROUNDS, CTR // mtctr 6 loop_dec: - VPERM IN0, IN1, MASK, IN1 // vperm 2,1,2,5 - VNCIPHER ZERO, IN1, ZERO // vncipher 0,0,2 - LVX (BLK_KEY)(BLK_IDX), IN1 // lvx 2,7,5 - ADD $16, BLK_IDX, BLK_IDX // addi 7,7,16 - VPERM IN1, IN0, MASK, IN0 // vperm 1,2,1,5 - VNCIPHER ZERO, IN0, ZERO // vncipher 0,0,1 - LVX (BLK_KEY)(BLK_IDX), IN0 // lvx 1,7,5 - ADD $16, BLK_IDX, BLK_IDX // addi 7,7,16 - BC 0x10, 0, loop_dec // bdnz .Loop_dec + VPERM IN0, IN1, MASK, IN1 // vperm 2,1,2,5 + VNCIPHER ZERO, IN1, ZERO // vncipher 0,0,2 + LVX (BLK_KEY)(BLK_IDX), IN1 // lvx 2,7,5 + ADD $16, BLK_IDX, BLK_IDX // addi 7,7,16 + VPERM IN1, IN0, MASK, IN0 // vperm 1,2,1,5 + VNCIPHER ZERO, IN0, ZERO // vncipher 0,0,1 + LVX (BLK_KEY)(BLK_IDX), IN0 // lvx 1,7,5 + ADD $16, BLK_IDX, BLK_IDX // addi 7,7,16 + BC 0x10, 0, loop_dec // bdnz .Loop_dec - VPERM IN0, IN1, MASK, IN1 // vperm 2,1,2,5 - VNCIPHER ZERO, IN1, ZERO // vncipher 0,0,2 - LVX (BLK_KEY)(BLK_IDX), IN1 // lvx 2,7,5 - VPERM IN1, IN0, MASK, IN0 // vperm 1,2,1,5 - VNCIPHERLAST ZERO, IN0, ZERO // vncipherlast 0,0,1 + VPERM IN0, IN1, MASK, IN1 // vperm 2,1,2,5 + VNCIPHER ZERO, IN1, ZERO // vncipher 0,0,2 + LVX (BLK_KEY)(BLK_IDX), IN1 // lvx 2,7,5 + VPERM IN1, IN0, MASK, IN0 // vperm 1,2,1,5 + VNCIPHERLAST ZERO, IN0, ZERO // vncipherlast 0,0,1 - VSPLTISB $-1, IN1 // vspltisb 2,-1 - VXOR IN0, IN0, IN0 // vxor 1,1,1 - MOVD $15, BLK_IDX // li 7,15 - VPERM IN1, IN0, KEY, IN1 // vperm 2,2,1,3 - VXOR KEY, RCON, KEY // vxor 3,3,4 - LVX (BLK_OUT)(R0), IN0 // lvx 1,0,4 - VPERM ZERO, ZERO, KEY, ZERO // vperm 0,0,0,3 - VSEL IN0, ZERO, IN1, IN0 // vsel 1,1,0,2 - LVX (BLK_OUT)(BLK_IDX), RCON // lvx 4,7,4 - STVX IN0, (BLK_OUT+R0) // stvx 1,0,4 - VSEL ZERO, RCON, IN1, ZERO // vsel 0,0,4,2 - STVX ZERO, (BLK_OUT+BLK_IDX) // stvx 0,7,4 + VSPLTISB $-1, IN1 // vspltisb 2,-1 + VXOR IN0, IN0, IN0 // vxor 1,1,1 + MOVD $15, BLK_IDX // li 7,15 + VPERM IN1, IN0, KEY, IN1 // vperm 2,2,1,3 + VXOR KEY, RCON, KEY // vxor 3,3,4 + LVX (BLK_OUT)(R0), IN0 // lvx 1,0,4 + VPERM ZERO, ZERO, KEY, ZERO // vperm 0,0,0,3 + VSEL IN0, ZERO, IN1, IN0 // vsel 1,1,0,2 + LVX (BLK_OUT)(BLK_IDX), RCON // lvx 4,7,4 + STVX IN0, (BLK_OUT+R0) // stvx 1,0,4 + VSEL ZERO, RCON, IN1, ZERO // vsel 0,0,4,2 + STVX ZERO, (BLK_OUT+BLK_IDX) // stvx 0,7,4 + + RET // blr - RET // blr diff --git a/src/crypto/ecdsa/ecdsa.go b/src/crypto/ecdsa/ecdsa.go index 219436935f..282596d2d2 100644 --- a/src/crypto/ecdsa/ecdsa.go +++ b/src/crypto/ecdsa/ecdsa.go @@ -200,12 +200,8 @@ var errZeroParam = errors.New("zero parameter") func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error) { randutil.MaybeReadByte(rand) - // Get min(log2(q) / 2, 256) bits of entropy from rand. - entropylen := (priv.Curve.Params().BitSize + 7) / 16 - if entropylen > 32 { - entropylen = 32 - } - entropy := make([]byte, entropylen) + // Get 256 bits of entropy from rand. + entropy := make([]byte, 32) _, err = io.ReadFull(rand, entropy) if err != nil { return diff --git a/src/crypto/elliptic/elliptic.go b/src/crypto/elliptic/elliptic.go index cdde0c4e60..d06a284154 100644 --- a/src/crypto/elliptic/elliptic.go +++ b/src/crypto/elliptic/elliptic.go @@ -85,7 +85,7 @@ func (curve *CurveParams) polynomial(x *big.Int) *big.Int { func (curve *CurveParams) IsOnCurve(x, y *big.Int) bool { // If there is a dedicated constant-time implementation for this curve operation, // use that instead of the generic one. - if specific, ok := matchesSpecificCurve(curve, p224, p521); ok { + if specific, ok := matchesSpecificCurve(curve, p224, p384, p521); ok { return specific.IsOnCurve(x, y) } @@ -128,7 +128,7 @@ func (curve *CurveParams) affineFromJacobian(x, y, z *big.Int) (xOut, yOut *big. func (curve *CurveParams) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) { // If there is a dedicated constant-time implementation for this curve operation, // use that instead of the generic one. - if specific, ok := matchesSpecificCurve(curve, p224, p521); ok { + if specific, ok := matchesSpecificCurve(curve, p224, p384, p521); ok { return specific.Add(x1, y1, x2, y2) } @@ -218,7 +218,7 @@ func (curve *CurveParams) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int func (curve *CurveParams) Double(x1, y1 *big.Int) (*big.Int, *big.Int) { // If there is a dedicated constant-time implementation for this curve operation, // use that instead of the generic one. - if specific, ok := matchesSpecificCurve(curve, p224, p521); ok { + if specific, ok := matchesSpecificCurve(curve, p224, p384, p521); ok { return specific.Double(x1, y1) } @@ -290,7 +290,7 @@ func (curve *CurveParams) doubleJacobian(x, y, z *big.Int) (*big.Int, *big.Int, func (curve *CurveParams) ScalarMult(Bx, By *big.Int, k []byte) (*big.Int, *big.Int) { // If there is a dedicated constant-time implementation for this curve operation, // use that instead of the generic one. - if specific, ok := matchesSpecificCurve(curve, p224, p256, p521); ok { + if specific, ok := matchesSpecificCurve(curve, p224, p256, p384, p521); ok { return specific.ScalarMult(Bx, By, k) } @@ -313,7 +313,7 @@ func (curve *CurveParams) ScalarMult(Bx, By *big.Int, k []byte) (*big.Int, *big. func (curve *CurveParams) ScalarBaseMult(k []byte) (*big.Int, *big.Int) { // If there is a dedicated constant-time implementation for this curve operation, // use that instead of the generic one. - if specific, ok := matchesSpecificCurve(curve, p224, p256, p521); ok { + if specific, ok := matchesSpecificCurve(curve, p224, p256, p384, p521); ok { return specific.ScalarBaseMult(k) } @@ -431,7 +431,6 @@ func UnmarshalCompressed(curve Curve, data []byte) (x, y *big.Int) { } var initonce sync.Once -var p384 *CurveParams func initAll() { initP224() @@ -440,15 +439,16 @@ func initAll() { initP521() } -func initP384() { - // See FIPS 186-3, section D.2.4 - p384 = &CurveParams{Name: "P-384"} - p384.P, _ = new(big.Int).SetString("39402006196394479212279040100143613805079739270465446667948293404245721771496870329047266088258938001861606973112319", 10) - p384.N, _ = new(big.Int).SetString("39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942643", 10) - p384.B, _ = new(big.Int).SetString("b3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef", 16) - p384.Gx, _ = new(big.Int).SetString("aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7", 16) - p384.Gy, _ = new(big.Int).SetString("3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f", 16) - p384.BitSize = 384 +// P224 returns a Curve which implements NIST P-224 (FIPS 186-3, section D.2.2), +// also known as secp224r1. The CurveParams.Name of this Curve is "P-224". +// +// Multiple invocations of this function will return the same value, so it can +// be used for equality checks and switch statements. +// +// The cryptographic operations are implemented using constant-time algorithms. +func P224() Curve { + initonce.Do(initAll) + return p224 } // P256 returns a Curve which implements NIST P-256 (FIPS 186-3, section D.2.3), @@ -470,7 +470,7 @@ func P256() Curve { // Multiple invocations of this function will return the same value, so it can // be used for equality checks and switch statements. // -// The cryptographic operations do not use constant-time algorithms. +// The cryptographic operations are implemented using constant-time algorithms. func P384() Curve { initonce.Do(initAll) return p384 diff --git a/src/crypto/elliptic/elliptic_test.go b/src/crypto/elliptic/elliptic_test.go index c9744b5a51..f5b36f75ca 100644 --- a/src/crypto/elliptic/elliptic_test.go +++ b/src/crypto/elliptic/elliptic_test.go @@ -14,9 +14,8 @@ import ( // genericParamsForCurve returns the dereferenced CurveParams for // the specified curve. This is used to avoid the logic for -// upgrading a curve to it's specific implementation, forcing -// usage of the generic implementation. This is only relevant -// for the P224, P256, and P521 curves. +// upgrading a curve to its specific implementation, forcing +// usage of the generic implementation. func genericParamsForCurve(c Curve) *CurveParams { d := *(c.Params()) return &d @@ -241,6 +240,16 @@ func testMarshalCompressed(t *testing.T, curve Curve, x, y *big.Int, want []byte } } +func TestLargeIsOnCurve(t *testing.T) { + testAllCurves(t, func(t *testing.T, curve Curve) { + large := big.NewInt(1) + large.Lsh(large, 1000) + if curve.IsOnCurve(large, large) { + t.Errorf("(2^1000, 2^1000) is reported on the curve") + } + }) +} + func benchmarkAllCurves(t *testing.B, f func(*testing.B, Curve)) { tests := []struct { name string diff --git a/src/crypto/elliptic/internal/fiat/Dockerfile b/src/crypto/elliptic/internal/fiat/Dockerfile index 7b5ece0e30..2877e0b2c1 100644 --- a/src/crypto/elliptic/internal/fiat/Dockerfile +++ b/src/crypto/elliptic/internal/fiat/Dockerfile @@ -4,9 +4,9 @@ FROM coqorg/coq:8.13.2 -RUN git clone https://github.com/mit-plv/fiat-crypto -RUN cd fiat-crypto && git checkout c076f3550bea2bb7f4cb5766a32594b9e67694f2 -RUN cd fiat-crypto && git submodule update --init --recursive +RUN git clone https://github.com/mit-plv/fiat-crypto && cd fiat-crypto && \ + git checkout 23d2dbc4ab897d14bde4404f70cd6991635f9c01 && \ + git submodule update --init --recursive RUN cd fiat-crypto && eval $(opam env) && make -j4 standalone-ocaml SKIP_BEDROCK2=1 -ENTRYPOINT ["fiat-crypto/src/ExtractionOCaml/unsaturated_solinas"] +ENV PATH /home/coq/fiat-crypto/src/ExtractionOCaml:$PATH diff --git a/src/crypto/elliptic/internal/fiat/README b/src/crypto/elliptic/internal/fiat/README index 171f57a327..916ebc14ce 100644 --- a/src/crypto/elliptic/internal/fiat/README +++ b/src/crypto/elliptic/internal/fiat/README @@ -1,17 +1,12 @@ The code in this package was autogenerated by the fiat-crypto project -at commit c076f3550 from a formally verified model. +at version v0.0.9 from a formally verified model, and by the addchain +project at a recent tip version. - docker build -t fiat-crypto:c076f3550 . - docker run fiat-crypto:c076f3550 --lang Go --no-wide-int --cmovznz-by-mul \ - --internal-static --public-function-case camelCase --public-type-case camelCase \ - --private-function-case camelCase --private-type-case camelCase \ - --no-prefix-fiat --package-name fiat --doc-text-before-function-name '' \ - --doc-prepend-header 'Code generated by Fiat Cryptography. DO NOT EDIT.' \ - --doc-newline-before-package-declaration p521 64 9 '2^521 - 1' \ - carry_mul carry_square carry add sub to_bytes from_bytes selectznz \ - > p521_fiat64.go + docker build -t fiat-crypto:v0.0.9 . + go install github.com/mmcloughlin/addchain/cmd/addchain@v0.3.1-0.20211027081849-6a7d3decbe08 + ../../../../../bin/go run generate.go -It comes under the following license. +fiat-crypto code comes under the following license. Copyright (c) 2015-2020 The fiat-crypto Authors. All rights reserved. diff --git a/src/crypto/elliptic/internal/fiat/fiat_test.go b/src/crypto/elliptic/internal/fiat/fiat_test.go new file mode 100644 index 0000000000..9ecd863788 --- /dev/null +++ b/src/crypto/elliptic/internal/fiat/fiat_test.go @@ -0,0 +1,64 @@ +// Copyright 2021 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 fiat_test + +import ( + "crypto/elliptic/internal/fiat" + "testing" +) + +func BenchmarkMul(b *testing.B) { + b.Run("P224", func(b *testing.B) { + v := new(fiat.P224Element).One() + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + v.Mul(v, v) + } + }) + b.Run("P384", func(b *testing.B) { + v := new(fiat.P384Element).One() + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + v.Mul(v, v) + } + }) + b.Run("P521", func(b *testing.B) { + v := new(fiat.P521Element).One() + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + v.Mul(v, v) + } + }) +} + +func BenchmarkSquare(b *testing.B) { + b.Run("P224", func(b *testing.B) { + v := new(fiat.P224Element).One() + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + v.Square(v) + } + }) + b.Run("P384", func(b *testing.B) { + v := new(fiat.P384Element).One() + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + v.Square(v) + } + }) + b.Run("P521", func(b *testing.B) { + v := new(fiat.P521Element).One() + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + v.Square(v) + } + }) +} diff --git a/src/crypto/elliptic/internal/fiat/generate.go b/src/crypto/elliptic/internal/fiat/generate.go new file mode 100644 index 0000000000..fd8509de45 --- /dev/null +++ b/src/crypto/elliptic/internal/fiat/generate.go @@ -0,0 +1,330 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build ignore + +package main + +import ( + "bytes" + "go/format" + "io" + "log" + "os" + "os/exec" + "text/template" +) + +var curves = []struct { + Element string + Prime string + Prefix string + FiatType string + BytesLen int +}{ + { + Element: "P224Element", + Prime: "2^224 - 2^96 + 1", + Prefix: "p224", + FiatType: "[4]uint64", + BytesLen: 28, + }, + // The 32-bit pure Go P-256 in crypto/elliptic is still faster than the + // autogenerated code here, regrettably. + // { + // Element: "P256Element", + // Prime: "2^256 - 2^224 + 2^192 + 2^96 - 1", + // Prefix: "p256", + // FiatType: "[4]uint64", + // BytesLen: 32, + // }, + { + Element: "P384Element", + Prime: "2^384 - 2^128 - 2^96 + 2^32 - 1", + Prefix: "p384", + FiatType: "[6]uint64", + BytesLen: 48, + }, + // Note that unsaturated_solinas would be about 2x faster than + // word_by_word_montgomery for P-521, but this curve is used rarely enough + // that it's not worth carrying unsaturated_solinas support for it. + { + Element: "P521Element", + Prime: "2^521 - 1", + Prefix: "p521", + FiatType: "[9]uint64", + BytesLen: 66, + }, +} + +func main() { + t := template.Must(template.New("montgomery").Parse(tmplWrapper)) + + tmplAddchainFile, err := os.CreateTemp("", "addchain-template") + if err != nil { + log.Fatal(err) + } + defer os.Remove(tmplAddchainFile.Name()) + if _, err := io.WriteString(tmplAddchainFile, tmplAddchain); err != nil { + log.Fatal(err) + } + if err := tmplAddchainFile.Close(); err != nil { + log.Fatal(err) + } + + for _, c := range curves { + log.Printf("Generating %s.go...", c.Prefix) + f, err := os.Create(c.Prefix + ".go") + if err != nil { + log.Fatal(err) + } + if err := t.Execute(f, c); err != nil { + log.Fatal(err) + } + if err := f.Close(); err != nil { + log.Fatal(err) + } + + log.Printf("Generating %s_fiat64.go...", c.Prefix) + cmd := exec.Command("docker", "run", "--rm", "--entrypoint", "word_by_word_montgomery", + "fiat-crypto:v0.0.9", "--lang", "Go", "--no-wide-int", "--cmovznz-by-mul", + "--relax-primitive-carry-to-bitwidth", "32,64", "--internal-static", + "--public-function-case", "camelCase", "--public-type-case", "camelCase", + "--private-function-case", "camelCase", "--private-type-case", "camelCase", + "--doc-text-before-function-name", "", "--doc-newline-before-package-declaration", + "--doc-prepend-header", "Code generated by Fiat Cryptography. DO NOT EDIT.", + "--package-name", "fiat", "--no-prefix-fiat", c.Prefix, "64", c.Prime, + "mul", "square", "add", "sub", "one", "from_montgomery", "to_montgomery", + "selectznz", "to_bytes", "from_bytes") + cmd.Stderr = os.Stderr + out, err := cmd.Output() + if err != nil { + log.Fatal(err) + } + out, err = format.Source(out) + if err != nil { + log.Fatal(err) + } + if err := os.WriteFile(c.Prefix+"_fiat64.go", out, 0644); err != nil { + log.Fatal(err) + } + + log.Printf("Generating %s_invert.go...", c.Prefix) + f, err = os.CreateTemp("", "addchain-"+c.Prefix) + if err != nil { + log.Fatal(err) + } + defer os.Remove(f.Name()) + cmd = exec.Command("addchain", "search", c.Prime+" - 2") + cmd.Stderr = os.Stderr + cmd.Stdout = f + if err := cmd.Run(); err != nil { + log.Fatal(err) + } + if err := f.Close(); err != nil { + log.Fatal(err) + } + cmd = exec.Command("addchain", "gen", "-tmpl", tmplAddchainFile.Name(), f.Name()) + cmd.Stderr = os.Stderr + out, err = cmd.Output() + if err != nil { + log.Fatal(err) + } + out = bytes.Replace(out, []byte("Element"), []byte(c.Element), -1) + out, err = format.Source(out) + if err != nil { + log.Fatal(err) + } + if err := os.WriteFile(c.Prefix+"_invert.go", out, 0644); err != nil { + log.Fatal(err) + } + } +} + +const tmplWrapper = `// Copyright 2021 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. + +// Code generated by generate.go. DO NOT EDIT. + +package fiat + +import ( + "crypto/subtle" + "errors" +) + +// {{ .Element }} is an integer modulo {{ .Prime }}. +// +// The zero value is a valid zero element. +type {{ .Element }} struct { + // Values are represented internally always in the Montgomery domain, and + // converted in Bytes and SetBytes. + x {{ .Prefix }}MontgomeryDomainFieldElement +} + +const {{ .Prefix }}ElementLen = {{ .BytesLen }} + +type {{ .Prefix }}UntypedFieldElement = {{ .FiatType }} + +// One sets e = 1, and returns e. +func (e *{{ .Element }}) One() *{{ .Element }} { + {{ .Prefix }}SetOne(&e.x) + return e +} + +// Equal returns 1 if e == t, and zero otherwise. +func (e *{{ .Element }}) Equal(t *{{ .Element }}) int { + eBytes := e.Bytes() + tBytes := t.Bytes() + return subtle.ConstantTimeCompare(eBytes, tBytes) +} + +var {{ .Prefix }}ZeroEncoding = new({{ .Element }}).Bytes() + +// IsZero returns 1 if e == 0, and zero otherwise. +func (e *{{ .Element }}) IsZero() int { + eBytes := e.Bytes() + return subtle.ConstantTimeCompare(eBytes, {{ .Prefix }}ZeroEncoding) +} + +// Set sets e = t, and returns e. +func (e *{{ .Element }}) Set(t *{{ .Element }}) *{{ .Element }} { + e.x = t.x + return e +} + +// Bytes returns the {{ .BytesLen }}-byte big-endian encoding of e. +func (e *{{ .Element }}) Bytes() []byte { + // This function is outlined to make the allocations inline in the caller + // rather than happen on the heap. + var out [{{ .Prefix }}ElementLen]byte + return e.bytes(&out) +} + +func (e *{{ .Element }}) bytes(out *[{{ .Prefix }}ElementLen]byte) []byte { + var tmp {{ .Prefix }}NonMontgomeryDomainFieldElement + {{ .Prefix }}FromMontgomery(&tmp, &e.x) + {{ .Prefix }}ToBytes(out, (*{{ .Prefix }}UntypedFieldElement)(&tmp)) + {{ .Prefix }}InvertEndianness(out[:]) + return out[:] +} + +// {{ .Prefix }}MinusOneEncoding is the encoding of -1 mod p, so p - 1, the +// highest canonical encoding. It is used by SetBytes to check for non-canonical +// encodings such as p + k, 2p + k, etc. +var {{ .Prefix }}MinusOneEncoding = new({{ .Element }}).Sub( + new({{ .Element }}), new({{ .Element }}).One()).Bytes() + +// SetBytes sets e = v, where v is a big-endian {{ .BytesLen }}-byte encoding, and returns e. +// If v is not {{ .BytesLen }} bytes or it encodes a value higher than {{ .Prime }}, +// SetBytes returns nil and an error, and e is unchanged. +func (e *{{ .Element }}) SetBytes(v []byte) (*{{ .Element }}, error) { + if len(v) != {{ .Prefix }}ElementLen { + return nil, errors.New("invalid {{ .Element }} encoding") + } + for i := range v { + if v[i] < {{ .Prefix }}MinusOneEncoding[i] { + break + } + if v[i] > {{ .Prefix }}MinusOneEncoding[i] { + return nil, errors.New("invalid {{ .Element }} encoding") + } + } + var in [{{ .Prefix }}ElementLen]byte + copy(in[:], v) + {{ .Prefix }}InvertEndianness(in[:]) + var tmp {{ .Prefix }}NonMontgomeryDomainFieldElement + {{ .Prefix }}FromBytes((*{{ .Prefix }}UntypedFieldElement)(&tmp), &in) + {{ .Prefix }}ToMontgomery(&e.x, &tmp) + return e, nil +} + +// Add sets e = t1 + t2, and returns e. +func (e *{{ .Element }}) Add(t1, t2 *{{ .Element }}) *{{ .Element }} { + {{ .Prefix }}Add(&e.x, &t1.x, &t2.x) + return e +} + +// Sub sets e = t1 - t2, and returns e. +func (e *{{ .Element }}) Sub(t1, t2 *{{ .Element }}) *{{ .Element }} { + {{ .Prefix }}Sub(&e.x, &t1.x, &t2.x) + return e +} + +// Mul sets e = t1 * t2, and returns e. +func (e *{{ .Element }}) Mul(t1, t2 *{{ .Element }}) *{{ .Element }} { + {{ .Prefix }}Mul(&e.x, &t1.x, &t2.x) + return e +} + +// Square sets e = t * t, and returns e. +func (e *{{ .Element }}) Square(t *{{ .Element }}) *{{ .Element }} { + {{ .Prefix }}Square(&e.x, &t.x) + return e +} + +// Select sets v to a if cond == 1, and to b if cond == 0. +func (v *{{ .Element }}) Select(a, b *{{ .Element }}, cond int) *{{ .Element }} { + {{ .Prefix }}Selectznz((*{{ .Prefix }}UntypedFieldElement)(&v.x), {{ .Prefix }}Uint1(cond), + (*{{ .Prefix }}UntypedFieldElement)(&b.x), (*{{ .Prefix }}UntypedFieldElement)(&a.x)) + return v +} + +func {{ .Prefix }}InvertEndianness(v []byte) { + for i := 0; i < len(v)/2; i++ { + v[i], v[len(v)-1-i] = v[len(v)-1-i], v[i] + } +} +` + +const tmplAddchain = `// Copyright 2021 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. + +// Code generated by {{ .Meta.Name }}. DO NOT EDIT. + +package fiat + +// Invert sets e = 1/x, and returns e. +// +// If x == 0, Invert returns e = 0. +func (e *Element) Invert(x *Element) *Element { + // Inversion is implemented as exponentiation with exponent p − 2. + // The sequence of {{ .Ops.Adds }} multiplications and {{ .Ops.Doubles }} squarings is derived from the + // following addition chain generated with {{ .Meta.Module }} {{ .Meta.ReleaseTag }}. + // + {{- range lines (format .Script) }} + // {{ . }} + {{- end }} + // + + var z = new(Element).Set(e) + {{- range .Program.Temporaries }} + var {{ . }} = new(Element) + {{- end }} + {{ range $i := .Program.Instructions -}} + {{- with add $i.Op }} + {{ $i.Output }}.Mul({{ .X }}, {{ .Y }}) + {{- end -}} + + {{- with double $i.Op }} + {{ $i.Output }}.Square({{ .X }}) + {{- end -}} + + {{- with shift $i.Op -}} + {{- $first := 0 -}} + {{- if ne $i.Output.Identifier .X.Identifier }} + {{ $i.Output }}.Square({{ .X }}) + {{- $first = 1 -}} + {{- end }} + for s := {{ $first }}; s < {{ .S }}; s++ { + {{ $i.Output }}.Square({{ $i.Output }}) + } + {{- end -}} + {{- end }} + + return e.Set(z) +} +` diff --git a/src/crypto/elliptic/internal/fiat/p224.go b/src/crypto/elliptic/internal/fiat/p224.go new file mode 100644 index 0000000000..4dddeb07a4 --- /dev/null +++ b/src/crypto/elliptic/internal/fiat/p224.go @@ -0,0 +1,135 @@ +// Copyright 2021 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. + +// Code generated by generate.go. DO NOT EDIT. + +package fiat + +import ( + "crypto/subtle" + "errors" +) + +// P224Element is an integer modulo 2^224 - 2^96 + 1. +// +// The zero value is a valid zero element. +type P224Element struct { + // Values are represented internally always in the Montgomery domain, and + // converted in Bytes and SetBytes. + x p224MontgomeryDomainFieldElement +} + +const p224ElementLen = 28 + +type p224UntypedFieldElement = [4]uint64 + +// One sets e = 1, and returns e. +func (e *P224Element) One() *P224Element { + p224SetOne(&e.x) + return e +} + +// Equal returns 1 if e == t, and zero otherwise. +func (e *P224Element) Equal(t *P224Element) int { + eBytes := e.Bytes() + tBytes := t.Bytes() + return subtle.ConstantTimeCompare(eBytes, tBytes) +} + +var p224ZeroEncoding = new(P224Element).Bytes() + +// IsZero returns 1 if e == 0, and zero otherwise. +func (e *P224Element) IsZero() int { + eBytes := e.Bytes() + return subtle.ConstantTimeCompare(eBytes, p224ZeroEncoding) +} + +// Set sets e = t, and returns e. +func (e *P224Element) Set(t *P224Element) *P224Element { + e.x = t.x + return e +} + +// Bytes returns the 28-byte big-endian encoding of e. +func (e *P224Element) Bytes() []byte { + // This function is outlined to make the allocations inline in the caller + // rather than happen on the heap. + var out [p224ElementLen]byte + return e.bytes(&out) +} + +func (e *P224Element) bytes(out *[p224ElementLen]byte) []byte { + var tmp p224NonMontgomeryDomainFieldElement + p224FromMontgomery(&tmp, &e.x) + p224ToBytes(out, (*p224UntypedFieldElement)(&tmp)) + p224InvertEndianness(out[:]) + return out[:] +} + +// p224MinusOneEncoding is the encoding of -1 mod p, so p - 1, the +// highest canonical encoding. It is used by SetBytes to check for non-canonical +// encodings such as p + k, 2p + k, etc. +var p224MinusOneEncoding = new(P224Element).Sub( + new(P224Element), new(P224Element).One()).Bytes() + +// SetBytes sets e = v, where v is a big-endian 28-byte encoding, and returns e. +// If v is not 28 bytes or it encodes a value higher than 2^224 - 2^96 + 1, +// SetBytes returns nil and an error, and e is unchanged. +func (e *P224Element) SetBytes(v []byte) (*P224Element, error) { + if len(v) != p224ElementLen { + return nil, errors.New("invalid P224Element encoding") + } + for i := range v { + if v[i] < p224MinusOneEncoding[i] { + break + } + if v[i] > p224MinusOneEncoding[i] { + return nil, errors.New("invalid P224Element encoding") + } + } + var in [p224ElementLen]byte + copy(in[:], v) + p224InvertEndianness(in[:]) + var tmp p224NonMontgomeryDomainFieldElement + p224FromBytes((*p224UntypedFieldElement)(&tmp), &in) + p224ToMontgomery(&e.x, &tmp) + return e, nil +} + +// Add sets e = t1 + t2, and returns e. +func (e *P224Element) Add(t1, t2 *P224Element) *P224Element { + p224Add(&e.x, &t1.x, &t2.x) + return e +} + +// Sub sets e = t1 - t2, and returns e. +func (e *P224Element) Sub(t1, t2 *P224Element) *P224Element { + p224Sub(&e.x, &t1.x, &t2.x) + return e +} + +// Mul sets e = t1 * t2, and returns e. +func (e *P224Element) Mul(t1, t2 *P224Element) *P224Element { + p224Mul(&e.x, &t1.x, &t2.x) + return e +} + +// Square sets e = t * t, and returns e. +func (e *P224Element) Square(t *P224Element) *P224Element { + p224Square(&e.x, &t.x) + return e +} + +// Select sets v to a if cond == 1, and to b if cond == 0. +func (v *P224Element) Select(a, b *P224Element, cond int) *P224Element { + p224Selectznz((*p224UntypedFieldElement)(&v.x), p224Uint1(cond), + (*p224UntypedFieldElement)(&b.x), (*p224UntypedFieldElement)(&a.x)) + return v +} + +func p224InvertEndianness(v []byte) { + for i := 0; i < len(v)/2; i++ { + v[i], v[len(v)-1-i] = v[len(v)-1-i], v[i] + } +} diff --git a/src/crypto/elliptic/internal/fiat/p224_fiat64.go b/src/crypto/elliptic/internal/fiat/p224_fiat64.go new file mode 100644 index 0000000000..4ece3e9220 --- /dev/null +++ b/src/crypto/elliptic/internal/fiat/p224_fiat64.go @@ -0,0 +1,1429 @@ +// Code generated by Fiat Cryptography. DO NOT EDIT. +// +// Autogenerated: word_by_word_montgomery --lang Go --no-wide-int --cmovznz-by-mul --relax-primitive-carry-to-bitwidth 32,64 --internal-static --public-function-case camelCase --public-type-case camelCase --private-function-case camelCase --private-type-case camelCase --doc-text-before-function-name '' --doc-newline-before-package-declaration --doc-prepend-header 'Code generated by Fiat Cryptography. DO NOT EDIT.' --package-name fiat --no-prefix-fiat p224 64 '2^224 - 2^96 + 1' mul square add sub one from_montgomery to_montgomery selectznz to_bytes from_bytes +// +// curve description: p224 +// +// machine_wordsize = 64 (from "64") +// +// requested operations: mul, square, add, sub, one, from_montgomery, to_montgomery, selectznz, to_bytes, from_bytes +// +// m = 0xffffffffffffffffffffffffffffffff000000000000000000000001 (from "2^224 - 2^96 + 1") +// +// +// +// NOTE: In addition to the bounds specified above each function, all +// +// functions synthesized for this Montgomery arithmetic require the +// +// input to be strictly less than the prime modulus (m), and also +// +// require the input to be in the unique saturated representation. +// +// All functions also ensure that these two properties are true of +// +// return values. +// +// +// +// Computed values: +// +// eval z = z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) +// +// bytes_eval z = z[0] + (z[1] << 8) + (z[2] << 16) + (z[3] << 24) + (z[4] << 32) + (z[5] << 40) + (z[6] << 48) + (z[7] << 56) + (z[8] << 64) + (z[9] << 72) + (z[10] << 80) + (z[11] << 88) + (z[12] << 96) + (z[13] << 104) + (z[14] << 112) + (z[15] << 120) + (z[16] << 128) + (z[17] << 136) + (z[18] << 144) + (z[19] << 152) + (z[20] << 160) + (z[21] << 168) + (z[22] << 176) + (z[23] << 184) + (z[24] << 192) + (z[25] << 200) + (z[26] << 208) + (z[27] << 216) +// +// twos_complement_eval z = let x1 := z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) in +// +// if x1 & (2^256-1) < 2^255 then x1 & (2^256-1) else (x1 & (2^256-1)) - 2^256 + +package fiat + +import "math/bits" + +type p224Uint1 uint64 // We use uint64 instead of a more narrow type for performance reasons; see https://github.com/mit-plv/fiat-crypto/pull/1006#issuecomment-892625927 +type p224Int1 int64 // We use uint64 instead of a more narrow type for performance reasons; see https://github.com/mit-plv/fiat-crypto/pull/1006#issuecomment-892625927 + +// The type p224MontgomeryDomainFieldElement is a field element in the Montgomery domain. +// +// Bounds: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +type p224MontgomeryDomainFieldElement [4]uint64 + +// The type p224NonMontgomeryDomainFieldElement is a field element NOT in the Montgomery domain. +// +// Bounds: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +type p224NonMontgomeryDomainFieldElement [4]uint64 + +// p224CmovznzU64 is a single-word conditional move. +// +// Postconditions: +// out1 = (if arg1 = 0 then arg2 else arg3) +// +// Input Bounds: +// arg1: [0x0 ~> 0x1] +// arg2: [0x0 ~> 0xffffffffffffffff] +// arg3: [0x0 ~> 0xffffffffffffffff] +// Output Bounds: +// out1: [0x0 ~> 0xffffffffffffffff] +func p224CmovznzU64(out1 *uint64, arg1 p224Uint1, arg2 uint64, arg3 uint64) { + x1 := (uint64(arg1) * 0xffffffffffffffff) + x2 := ((x1 & arg3) | ((^x1) & arg2)) + *out1 = x2 +} + +// p224Mul multiplies two field elements in the Montgomery domain. +// +// Preconditions: +// 0 ≤ eval arg1 < m +// 0 ≤ eval arg2 < m +// Postconditions: +// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg2)) mod m +// 0 ≤ eval out1 < m +// +func p224Mul(out1 *p224MontgomeryDomainFieldElement, arg1 *p224MontgomeryDomainFieldElement, arg2 *p224MontgomeryDomainFieldElement) { + x1 := arg1[1] + x2 := arg1[2] + x3 := arg1[3] + x4 := arg1[0] + var x5 uint64 + var x6 uint64 + x6, x5 = bits.Mul64(x4, arg2[3]) + var x7 uint64 + var x8 uint64 + x8, x7 = bits.Mul64(x4, arg2[2]) + var x9 uint64 + var x10 uint64 + x10, x9 = bits.Mul64(x4, arg2[1]) + var x11 uint64 + var x12 uint64 + x12, x11 = bits.Mul64(x4, arg2[0]) + var x13 uint64 + var x14 uint64 + x13, x14 = bits.Add64(x12, x9, uint64(0x0)) + var x15 uint64 + var x16 uint64 + x15, x16 = bits.Add64(x10, x7, uint64(p224Uint1(x14))) + var x17 uint64 + var x18 uint64 + x17, x18 = bits.Add64(x8, x5, uint64(p224Uint1(x16))) + x19 := (uint64(p224Uint1(x18)) + x6) + var x20 uint64 + _, x20 = bits.Mul64(x11, 0xffffffffffffffff) + var x22 uint64 + var x23 uint64 + x23, x22 = bits.Mul64(x20, 0xffffffff) + var x24 uint64 + var x25 uint64 + x25, x24 = bits.Mul64(x20, 0xffffffffffffffff) + var x26 uint64 + var x27 uint64 + x27, x26 = bits.Mul64(x20, 0xffffffff00000000) + var x28 uint64 + var x29 uint64 + x28, x29 = bits.Add64(x27, x24, uint64(0x0)) + var x30 uint64 + var x31 uint64 + x30, x31 = bits.Add64(x25, x22, uint64(p224Uint1(x29))) + x32 := (uint64(p224Uint1(x31)) + x23) + var x34 uint64 + _, x34 = bits.Add64(x11, x20, uint64(0x0)) + var x35 uint64 + var x36 uint64 + x35, x36 = bits.Add64(x13, x26, uint64(p224Uint1(x34))) + var x37 uint64 + var x38 uint64 + x37, x38 = bits.Add64(x15, x28, uint64(p224Uint1(x36))) + var x39 uint64 + var x40 uint64 + x39, x40 = bits.Add64(x17, x30, uint64(p224Uint1(x38))) + var x41 uint64 + var x42 uint64 + x41, x42 = bits.Add64(x19, x32, uint64(p224Uint1(x40))) + var x43 uint64 + var x44 uint64 + x44, x43 = bits.Mul64(x1, arg2[3]) + var x45 uint64 + var x46 uint64 + x46, x45 = bits.Mul64(x1, arg2[2]) + var x47 uint64 + var x48 uint64 + x48, x47 = bits.Mul64(x1, arg2[1]) + var x49 uint64 + var x50 uint64 + x50, x49 = bits.Mul64(x1, arg2[0]) + var x51 uint64 + var x52 uint64 + x51, x52 = bits.Add64(x50, x47, uint64(0x0)) + var x53 uint64 + var x54 uint64 + x53, x54 = bits.Add64(x48, x45, uint64(p224Uint1(x52))) + var x55 uint64 + var x56 uint64 + x55, x56 = bits.Add64(x46, x43, uint64(p224Uint1(x54))) + x57 := (uint64(p224Uint1(x56)) + x44) + var x58 uint64 + var x59 uint64 + x58, x59 = bits.Add64(x35, x49, uint64(0x0)) + var x60 uint64 + var x61 uint64 + x60, x61 = bits.Add64(x37, x51, uint64(p224Uint1(x59))) + var x62 uint64 + var x63 uint64 + x62, x63 = bits.Add64(x39, x53, uint64(p224Uint1(x61))) + var x64 uint64 + var x65 uint64 + x64, x65 = bits.Add64(x41, x55, uint64(p224Uint1(x63))) + var x66 uint64 + var x67 uint64 + x66, x67 = bits.Add64(uint64(p224Uint1(x42)), x57, uint64(p224Uint1(x65))) + var x68 uint64 + _, x68 = bits.Mul64(x58, 0xffffffffffffffff) + var x70 uint64 + var x71 uint64 + x71, x70 = bits.Mul64(x68, 0xffffffff) + var x72 uint64 + var x73 uint64 + x73, x72 = bits.Mul64(x68, 0xffffffffffffffff) + var x74 uint64 + var x75 uint64 + x75, x74 = bits.Mul64(x68, 0xffffffff00000000) + var x76 uint64 + var x77 uint64 + x76, x77 = bits.Add64(x75, x72, uint64(0x0)) + var x78 uint64 + var x79 uint64 + x78, x79 = bits.Add64(x73, x70, uint64(p224Uint1(x77))) + x80 := (uint64(p224Uint1(x79)) + x71) + var x82 uint64 + _, x82 = bits.Add64(x58, x68, uint64(0x0)) + var x83 uint64 + var x84 uint64 + x83, x84 = bits.Add64(x60, x74, uint64(p224Uint1(x82))) + var x85 uint64 + var x86 uint64 + x85, x86 = bits.Add64(x62, x76, uint64(p224Uint1(x84))) + var x87 uint64 + var x88 uint64 + x87, x88 = bits.Add64(x64, x78, uint64(p224Uint1(x86))) + var x89 uint64 + var x90 uint64 + x89, x90 = bits.Add64(x66, x80, uint64(p224Uint1(x88))) + x91 := (uint64(p224Uint1(x90)) + uint64(p224Uint1(x67))) + var x92 uint64 + var x93 uint64 + x93, x92 = bits.Mul64(x2, arg2[3]) + var x94 uint64 + var x95 uint64 + x95, x94 = bits.Mul64(x2, arg2[2]) + var x96 uint64 + var x97 uint64 + x97, x96 = bits.Mul64(x2, arg2[1]) + var x98 uint64 + var x99 uint64 + x99, x98 = bits.Mul64(x2, arg2[0]) + var x100 uint64 + var x101 uint64 + x100, x101 = bits.Add64(x99, x96, uint64(0x0)) + var x102 uint64 + var x103 uint64 + x102, x103 = bits.Add64(x97, x94, uint64(p224Uint1(x101))) + var x104 uint64 + var x105 uint64 + x104, x105 = bits.Add64(x95, x92, uint64(p224Uint1(x103))) + x106 := (uint64(p224Uint1(x105)) + x93) + var x107 uint64 + var x108 uint64 + x107, x108 = bits.Add64(x83, x98, uint64(0x0)) + var x109 uint64 + var x110 uint64 + x109, x110 = bits.Add64(x85, x100, uint64(p224Uint1(x108))) + var x111 uint64 + var x112 uint64 + x111, x112 = bits.Add64(x87, x102, uint64(p224Uint1(x110))) + var x113 uint64 + var x114 uint64 + x113, x114 = bits.Add64(x89, x104, uint64(p224Uint1(x112))) + var x115 uint64 + var x116 uint64 + x115, x116 = bits.Add64(x91, x106, uint64(p224Uint1(x114))) + var x117 uint64 + _, x117 = bits.Mul64(x107, 0xffffffffffffffff) + var x119 uint64 + var x120 uint64 + x120, x119 = bits.Mul64(x117, 0xffffffff) + var x121 uint64 + var x122 uint64 + x122, x121 = bits.Mul64(x117, 0xffffffffffffffff) + var x123 uint64 + var x124 uint64 + x124, x123 = bits.Mul64(x117, 0xffffffff00000000) + var x125 uint64 + var x126 uint64 + x125, x126 = bits.Add64(x124, x121, uint64(0x0)) + var x127 uint64 + var x128 uint64 + x127, x128 = bits.Add64(x122, x119, uint64(p224Uint1(x126))) + x129 := (uint64(p224Uint1(x128)) + x120) + var x131 uint64 + _, x131 = bits.Add64(x107, x117, uint64(0x0)) + var x132 uint64 + var x133 uint64 + x132, x133 = bits.Add64(x109, x123, uint64(p224Uint1(x131))) + var x134 uint64 + var x135 uint64 + x134, x135 = bits.Add64(x111, x125, uint64(p224Uint1(x133))) + var x136 uint64 + var x137 uint64 + x136, x137 = bits.Add64(x113, x127, uint64(p224Uint1(x135))) + var x138 uint64 + var x139 uint64 + x138, x139 = bits.Add64(x115, x129, uint64(p224Uint1(x137))) + x140 := (uint64(p224Uint1(x139)) + uint64(p224Uint1(x116))) + var x141 uint64 + var x142 uint64 + x142, x141 = bits.Mul64(x3, arg2[3]) + var x143 uint64 + var x144 uint64 + x144, x143 = bits.Mul64(x3, arg2[2]) + var x145 uint64 + var x146 uint64 + x146, x145 = bits.Mul64(x3, arg2[1]) + var x147 uint64 + var x148 uint64 + x148, x147 = bits.Mul64(x3, arg2[0]) + var x149 uint64 + var x150 uint64 + x149, x150 = bits.Add64(x148, x145, uint64(0x0)) + var x151 uint64 + var x152 uint64 + x151, x152 = bits.Add64(x146, x143, uint64(p224Uint1(x150))) + var x153 uint64 + var x154 uint64 + x153, x154 = bits.Add64(x144, x141, uint64(p224Uint1(x152))) + x155 := (uint64(p224Uint1(x154)) + x142) + var x156 uint64 + var x157 uint64 + x156, x157 = bits.Add64(x132, x147, uint64(0x0)) + var x158 uint64 + var x159 uint64 + x158, x159 = bits.Add64(x134, x149, uint64(p224Uint1(x157))) + var x160 uint64 + var x161 uint64 + x160, x161 = bits.Add64(x136, x151, uint64(p224Uint1(x159))) + var x162 uint64 + var x163 uint64 + x162, x163 = bits.Add64(x138, x153, uint64(p224Uint1(x161))) + var x164 uint64 + var x165 uint64 + x164, x165 = bits.Add64(x140, x155, uint64(p224Uint1(x163))) + var x166 uint64 + _, x166 = bits.Mul64(x156, 0xffffffffffffffff) + var x168 uint64 + var x169 uint64 + x169, x168 = bits.Mul64(x166, 0xffffffff) + var x170 uint64 + var x171 uint64 + x171, x170 = bits.Mul64(x166, 0xffffffffffffffff) + var x172 uint64 + var x173 uint64 + x173, x172 = bits.Mul64(x166, 0xffffffff00000000) + var x174 uint64 + var x175 uint64 + x174, x175 = bits.Add64(x173, x170, uint64(0x0)) + var x176 uint64 + var x177 uint64 + x176, x177 = bits.Add64(x171, x168, uint64(p224Uint1(x175))) + x178 := (uint64(p224Uint1(x177)) + x169) + var x180 uint64 + _, x180 = bits.Add64(x156, x166, uint64(0x0)) + var x181 uint64 + var x182 uint64 + x181, x182 = bits.Add64(x158, x172, uint64(p224Uint1(x180))) + var x183 uint64 + var x184 uint64 + x183, x184 = bits.Add64(x160, x174, uint64(p224Uint1(x182))) + var x185 uint64 + var x186 uint64 + x185, x186 = bits.Add64(x162, x176, uint64(p224Uint1(x184))) + var x187 uint64 + var x188 uint64 + x187, x188 = bits.Add64(x164, x178, uint64(p224Uint1(x186))) + x189 := (uint64(p224Uint1(x188)) + uint64(p224Uint1(x165))) + var x190 uint64 + var x191 uint64 + x190, x191 = bits.Sub64(x181, uint64(0x1), uint64(0x0)) + var x192 uint64 + var x193 uint64 + x192, x193 = bits.Sub64(x183, 0xffffffff00000000, uint64(p224Uint1(x191))) + var x194 uint64 + var x195 uint64 + x194, x195 = bits.Sub64(x185, 0xffffffffffffffff, uint64(p224Uint1(x193))) + var x196 uint64 + var x197 uint64 + x196, x197 = bits.Sub64(x187, 0xffffffff, uint64(p224Uint1(x195))) + var x199 uint64 + _, x199 = bits.Sub64(x189, uint64(0x0), uint64(p224Uint1(x197))) + var x200 uint64 + p224CmovznzU64(&x200, p224Uint1(x199), x190, x181) + var x201 uint64 + p224CmovznzU64(&x201, p224Uint1(x199), x192, x183) + var x202 uint64 + p224CmovznzU64(&x202, p224Uint1(x199), x194, x185) + var x203 uint64 + p224CmovznzU64(&x203, p224Uint1(x199), x196, x187) + out1[0] = x200 + out1[1] = x201 + out1[2] = x202 + out1[3] = x203 +} + +// p224Square squares a field element in the Montgomery domain. +// +// Preconditions: +// 0 ≤ eval arg1 < m +// Postconditions: +// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg1)) mod m +// 0 ≤ eval out1 < m +// +func p224Square(out1 *p224MontgomeryDomainFieldElement, arg1 *p224MontgomeryDomainFieldElement) { + x1 := arg1[1] + x2 := arg1[2] + x3 := arg1[3] + x4 := arg1[0] + var x5 uint64 + var x6 uint64 + x6, x5 = bits.Mul64(x4, arg1[3]) + var x7 uint64 + var x8 uint64 + x8, x7 = bits.Mul64(x4, arg1[2]) + var x9 uint64 + var x10 uint64 + x10, x9 = bits.Mul64(x4, arg1[1]) + var x11 uint64 + var x12 uint64 + x12, x11 = bits.Mul64(x4, arg1[0]) + var x13 uint64 + var x14 uint64 + x13, x14 = bits.Add64(x12, x9, uint64(0x0)) + var x15 uint64 + var x16 uint64 + x15, x16 = bits.Add64(x10, x7, uint64(p224Uint1(x14))) + var x17 uint64 + var x18 uint64 + x17, x18 = bits.Add64(x8, x5, uint64(p224Uint1(x16))) + x19 := (uint64(p224Uint1(x18)) + x6) + var x20 uint64 + _, x20 = bits.Mul64(x11, 0xffffffffffffffff) + var x22 uint64 + var x23 uint64 + x23, x22 = bits.Mul64(x20, 0xffffffff) + var x24 uint64 + var x25 uint64 + x25, x24 = bits.Mul64(x20, 0xffffffffffffffff) + var x26 uint64 + var x27 uint64 + x27, x26 = bits.Mul64(x20, 0xffffffff00000000) + var x28 uint64 + var x29 uint64 + x28, x29 = bits.Add64(x27, x24, uint64(0x0)) + var x30 uint64 + var x31 uint64 + x30, x31 = bits.Add64(x25, x22, uint64(p224Uint1(x29))) + x32 := (uint64(p224Uint1(x31)) + x23) + var x34 uint64 + _, x34 = bits.Add64(x11, x20, uint64(0x0)) + var x35 uint64 + var x36 uint64 + x35, x36 = bits.Add64(x13, x26, uint64(p224Uint1(x34))) + var x37 uint64 + var x38 uint64 + x37, x38 = bits.Add64(x15, x28, uint64(p224Uint1(x36))) + var x39 uint64 + var x40 uint64 + x39, x40 = bits.Add64(x17, x30, uint64(p224Uint1(x38))) + var x41 uint64 + var x42 uint64 + x41, x42 = bits.Add64(x19, x32, uint64(p224Uint1(x40))) + var x43 uint64 + var x44 uint64 + x44, x43 = bits.Mul64(x1, arg1[3]) + var x45 uint64 + var x46 uint64 + x46, x45 = bits.Mul64(x1, arg1[2]) + var x47 uint64 + var x48 uint64 + x48, x47 = bits.Mul64(x1, arg1[1]) + var x49 uint64 + var x50 uint64 + x50, x49 = bits.Mul64(x1, arg1[0]) + var x51 uint64 + var x52 uint64 + x51, x52 = bits.Add64(x50, x47, uint64(0x0)) + var x53 uint64 + var x54 uint64 + x53, x54 = bits.Add64(x48, x45, uint64(p224Uint1(x52))) + var x55 uint64 + var x56 uint64 + x55, x56 = bits.Add64(x46, x43, uint64(p224Uint1(x54))) + x57 := (uint64(p224Uint1(x56)) + x44) + var x58 uint64 + var x59 uint64 + x58, x59 = bits.Add64(x35, x49, uint64(0x0)) + var x60 uint64 + var x61 uint64 + x60, x61 = bits.Add64(x37, x51, uint64(p224Uint1(x59))) + var x62 uint64 + var x63 uint64 + x62, x63 = bits.Add64(x39, x53, uint64(p224Uint1(x61))) + var x64 uint64 + var x65 uint64 + x64, x65 = bits.Add64(x41, x55, uint64(p224Uint1(x63))) + var x66 uint64 + var x67 uint64 + x66, x67 = bits.Add64(uint64(p224Uint1(x42)), x57, uint64(p224Uint1(x65))) + var x68 uint64 + _, x68 = bits.Mul64(x58, 0xffffffffffffffff) + var x70 uint64 + var x71 uint64 + x71, x70 = bits.Mul64(x68, 0xffffffff) + var x72 uint64 + var x73 uint64 + x73, x72 = bits.Mul64(x68, 0xffffffffffffffff) + var x74 uint64 + var x75 uint64 + x75, x74 = bits.Mul64(x68, 0xffffffff00000000) + var x76 uint64 + var x77 uint64 + x76, x77 = bits.Add64(x75, x72, uint64(0x0)) + var x78 uint64 + var x79 uint64 + x78, x79 = bits.Add64(x73, x70, uint64(p224Uint1(x77))) + x80 := (uint64(p224Uint1(x79)) + x71) + var x82 uint64 + _, x82 = bits.Add64(x58, x68, uint64(0x0)) + var x83 uint64 + var x84 uint64 + x83, x84 = bits.Add64(x60, x74, uint64(p224Uint1(x82))) + var x85 uint64 + var x86 uint64 + x85, x86 = bits.Add64(x62, x76, uint64(p224Uint1(x84))) + var x87 uint64 + var x88 uint64 + x87, x88 = bits.Add64(x64, x78, uint64(p224Uint1(x86))) + var x89 uint64 + var x90 uint64 + x89, x90 = bits.Add64(x66, x80, uint64(p224Uint1(x88))) + x91 := (uint64(p224Uint1(x90)) + uint64(p224Uint1(x67))) + var x92 uint64 + var x93 uint64 + x93, x92 = bits.Mul64(x2, arg1[3]) + var x94 uint64 + var x95 uint64 + x95, x94 = bits.Mul64(x2, arg1[2]) + var x96 uint64 + var x97 uint64 + x97, x96 = bits.Mul64(x2, arg1[1]) + var x98 uint64 + var x99 uint64 + x99, x98 = bits.Mul64(x2, arg1[0]) + var x100 uint64 + var x101 uint64 + x100, x101 = bits.Add64(x99, x96, uint64(0x0)) + var x102 uint64 + var x103 uint64 + x102, x103 = bits.Add64(x97, x94, uint64(p224Uint1(x101))) + var x104 uint64 + var x105 uint64 + x104, x105 = bits.Add64(x95, x92, uint64(p224Uint1(x103))) + x106 := (uint64(p224Uint1(x105)) + x93) + var x107 uint64 + var x108 uint64 + x107, x108 = bits.Add64(x83, x98, uint64(0x0)) + var x109 uint64 + var x110 uint64 + x109, x110 = bits.Add64(x85, x100, uint64(p224Uint1(x108))) + var x111 uint64 + var x112 uint64 + x111, x112 = bits.Add64(x87, x102, uint64(p224Uint1(x110))) + var x113 uint64 + var x114 uint64 + x113, x114 = bits.Add64(x89, x104, uint64(p224Uint1(x112))) + var x115 uint64 + var x116 uint64 + x115, x116 = bits.Add64(x91, x106, uint64(p224Uint1(x114))) + var x117 uint64 + _, x117 = bits.Mul64(x107, 0xffffffffffffffff) + var x119 uint64 + var x120 uint64 + x120, x119 = bits.Mul64(x117, 0xffffffff) + var x121 uint64 + var x122 uint64 + x122, x121 = bits.Mul64(x117, 0xffffffffffffffff) + var x123 uint64 + var x124 uint64 + x124, x123 = bits.Mul64(x117, 0xffffffff00000000) + var x125 uint64 + var x126 uint64 + x125, x126 = bits.Add64(x124, x121, uint64(0x0)) + var x127 uint64 + var x128 uint64 + x127, x128 = bits.Add64(x122, x119, uint64(p224Uint1(x126))) + x129 := (uint64(p224Uint1(x128)) + x120) + var x131 uint64 + _, x131 = bits.Add64(x107, x117, uint64(0x0)) + var x132 uint64 + var x133 uint64 + x132, x133 = bits.Add64(x109, x123, uint64(p224Uint1(x131))) + var x134 uint64 + var x135 uint64 + x134, x135 = bits.Add64(x111, x125, uint64(p224Uint1(x133))) + var x136 uint64 + var x137 uint64 + x136, x137 = bits.Add64(x113, x127, uint64(p224Uint1(x135))) + var x138 uint64 + var x139 uint64 + x138, x139 = bits.Add64(x115, x129, uint64(p224Uint1(x137))) + x140 := (uint64(p224Uint1(x139)) + uint64(p224Uint1(x116))) + var x141 uint64 + var x142 uint64 + x142, x141 = bits.Mul64(x3, arg1[3]) + var x143 uint64 + var x144 uint64 + x144, x143 = bits.Mul64(x3, arg1[2]) + var x145 uint64 + var x146 uint64 + x146, x145 = bits.Mul64(x3, arg1[1]) + var x147 uint64 + var x148 uint64 + x148, x147 = bits.Mul64(x3, arg1[0]) + var x149 uint64 + var x150 uint64 + x149, x150 = bits.Add64(x148, x145, uint64(0x0)) + var x151 uint64 + var x152 uint64 + x151, x152 = bits.Add64(x146, x143, uint64(p224Uint1(x150))) + var x153 uint64 + var x154 uint64 + x153, x154 = bits.Add64(x144, x141, uint64(p224Uint1(x152))) + x155 := (uint64(p224Uint1(x154)) + x142) + var x156 uint64 + var x157 uint64 + x156, x157 = bits.Add64(x132, x147, uint64(0x0)) + var x158 uint64 + var x159 uint64 + x158, x159 = bits.Add64(x134, x149, uint64(p224Uint1(x157))) + var x160 uint64 + var x161 uint64 + x160, x161 = bits.Add64(x136, x151, uint64(p224Uint1(x159))) + var x162 uint64 + var x163 uint64 + x162, x163 = bits.Add64(x138, x153, uint64(p224Uint1(x161))) + var x164 uint64 + var x165 uint64 + x164, x165 = bits.Add64(x140, x155, uint64(p224Uint1(x163))) + var x166 uint64 + _, x166 = bits.Mul64(x156, 0xffffffffffffffff) + var x168 uint64 + var x169 uint64 + x169, x168 = bits.Mul64(x166, 0xffffffff) + var x170 uint64 + var x171 uint64 + x171, x170 = bits.Mul64(x166, 0xffffffffffffffff) + var x172 uint64 + var x173 uint64 + x173, x172 = bits.Mul64(x166, 0xffffffff00000000) + var x174 uint64 + var x175 uint64 + x174, x175 = bits.Add64(x173, x170, uint64(0x0)) + var x176 uint64 + var x177 uint64 + x176, x177 = bits.Add64(x171, x168, uint64(p224Uint1(x175))) + x178 := (uint64(p224Uint1(x177)) + x169) + var x180 uint64 + _, x180 = bits.Add64(x156, x166, uint64(0x0)) + var x181 uint64 + var x182 uint64 + x181, x182 = bits.Add64(x158, x172, uint64(p224Uint1(x180))) + var x183 uint64 + var x184 uint64 + x183, x184 = bits.Add64(x160, x174, uint64(p224Uint1(x182))) + var x185 uint64 + var x186 uint64 + x185, x186 = bits.Add64(x162, x176, uint64(p224Uint1(x184))) + var x187 uint64 + var x188 uint64 + x187, x188 = bits.Add64(x164, x178, uint64(p224Uint1(x186))) + x189 := (uint64(p224Uint1(x188)) + uint64(p224Uint1(x165))) + var x190 uint64 + var x191 uint64 + x190, x191 = bits.Sub64(x181, uint64(0x1), uint64(0x0)) + var x192 uint64 + var x193 uint64 + x192, x193 = bits.Sub64(x183, 0xffffffff00000000, uint64(p224Uint1(x191))) + var x194 uint64 + var x195 uint64 + x194, x195 = bits.Sub64(x185, 0xffffffffffffffff, uint64(p224Uint1(x193))) + var x196 uint64 + var x197 uint64 + x196, x197 = bits.Sub64(x187, 0xffffffff, uint64(p224Uint1(x195))) + var x199 uint64 + _, x199 = bits.Sub64(x189, uint64(0x0), uint64(p224Uint1(x197))) + var x200 uint64 + p224CmovznzU64(&x200, p224Uint1(x199), x190, x181) + var x201 uint64 + p224CmovznzU64(&x201, p224Uint1(x199), x192, x183) + var x202 uint64 + p224CmovznzU64(&x202, p224Uint1(x199), x194, x185) + var x203 uint64 + p224CmovznzU64(&x203, p224Uint1(x199), x196, x187) + out1[0] = x200 + out1[1] = x201 + out1[2] = x202 + out1[3] = x203 +} + +// p224Add adds two field elements in the Montgomery domain. +// +// Preconditions: +// 0 ≤ eval arg1 < m +// 0 ≤ eval arg2 < m +// Postconditions: +// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) + eval (from_montgomery arg2)) mod m +// 0 ≤ eval out1 < m +// +func p224Add(out1 *p224MontgomeryDomainFieldElement, arg1 *p224MontgomeryDomainFieldElement, arg2 *p224MontgomeryDomainFieldElement) { + var x1 uint64 + var x2 uint64 + x1, x2 = bits.Add64(arg1[0], arg2[0], uint64(0x0)) + var x3 uint64 + var x4 uint64 + x3, x4 = bits.Add64(arg1[1], arg2[1], uint64(p224Uint1(x2))) + var x5 uint64 + var x6 uint64 + x5, x6 = bits.Add64(arg1[2], arg2[2], uint64(p224Uint1(x4))) + var x7 uint64 + var x8 uint64 + x7, x8 = bits.Add64(arg1[3], arg2[3], uint64(p224Uint1(x6))) + var x9 uint64 + var x10 uint64 + x9, x10 = bits.Sub64(x1, uint64(0x1), uint64(0x0)) + var x11 uint64 + var x12 uint64 + x11, x12 = bits.Sub64(x3, 0xffffffff00000000, uint64(p224Uint1(x10))) + var x13 uint64 + var x14 uint64 + x13, x14 = bits.Sub64(x5, 0xffffffffffffffff, uint64(p224Uint1(x12))) + var x15 uint64 + var x16 uint64 + x15, x16 = bits.Sub64(x7, 0xffffffff, uint64(p224Uint1(x14))) + var x18 uint64 + _, x18 = bits.Sub64(uint64(p224Uint1(x8)), uint64(0x0), uint64(p224Uint1(x16))) + var x19 uint64 + p224CmovznzU64(&x19, p224Uint1(x18), x9, x1) + var x20 uint64 + p224CmovznzU64(&x20, p224Uint1(x18), x11, x3) + var x21 uint64 + p224CmovznzU64(&x21, p224Uint1(x18), x13, x5) + var x22 uint64 + p224CmovznzU64(&x22, p224Uint1(x18), x15, x7) + out1[0] = x19 + out1[1] = x20 + out1[2] = x21 + out1[3] = x22 +} + +// p224Sub subtracts two field elements in the Montgomery domain. +// +// Preconditions: +// 0 ≤ eval arg1 < m +// 0 ≤ eval arg2 < m +// Postconditions: +// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) - eval (from_montgomery arg2)) mod m +// 0 ≤ eval out1 < m +// +func p224Sub(out1 *p224MontgomeryDomainFieldElement, arg1 *p224MontgomeryDomainFieldElement, arg2 *p224MontgomeryDomainFieldElement) { + var x1 uint64 + var x2 uint64 + x1, x2 = bits.Sub64(arg1[0], arg2[0], uint64(0x0)) + var x3 uint64 + var x4 uint64 + x3, x4 = bits.Sub64(arg1[1], arg2[1], uint64(p224Uint1(x2))) + var x5 uint64 + var x6 uint64 + x5, x6 = bits.Sub64(arg1[2], arg2[2], uint64(p224Uint1(x4))) + var x7 uint64 + var x8 uint64 + x7, x8 = bits.Sub64(arg1[3], arg2[3], uint64(p224Uint1(x6))) + var x9 uint64 + p224CmovznzU64(&x9, p224Uint1(x8), uint64(0x0), 0xffffffffffffffff) + var x10 uint64 + var x11 uint64 + x10, x11 = bits.Add64(x1, uint64((p224Uint1(x9) & 0x1)), uint64(0x0)) + var x12 uint64 + var x13 uint64 + x12, x13 = bits.Add64(x3, (x9 & 0xffffffff00000000), uint64(p224Uint1(x11))) + var x14 uint64 + var x15 uint64 + x14, x15 = bits.Add64(x5, x9, uint64(p224Uint1(x13))) + var x16 uint64 + x16, _ = bits.Add64(x7, (x9 & 0xffffffff), uint64(p224Uint1(x15))) + out1[0] = x10 + out1[1] = x12 + out1[2] = x14 + out1[3] = x16 +} + +// p224SetOne returns the field element one in the Montgomery domain. +// +// Postconditions: +// eval (from_montgomery out1) mod m = 1 mod m +// 0 ≤ eval out1 < m +// +func p224SetOne(out1 *p224MontgomeryDomainFieldElement) { + out1[0] = 0xffffffff00000000 + out1[1] = 0xffffffffffffffff + out1[2] = uint64(0x0) + out1[3] = uint64(0x0) +} + +// p224FromMontgomery translates a field element out of the Montgomery domain. +// +// Preconditions: +// 0 ≤ eval arg1 < m +// Postconditions: +// eval out1 mod m = (eval arg1 * ((2^64)⁻¹ mod m)^4) mod m +// 0 ≤ eval out1 < m +// +func p224FromMontgomery(out1 *p224NonMontgomeryDomainFieldElement, arg1 *p224MontgomeryDomainFieldElement) { + x1 := arg1[0] + var x2 uint64 + _, x2 = bits.Mul64(x1, 0xffffffffffffffff) + var x4 uint64 + var x5 uint64 + x5, x4 = bits.Mul64(x2, 0xffffffff) + var x6 uint64 + var x7 uint64 + x7, x6 = bits.Mul64(x2, 0xffffffffffffffff) + var x8 uint64 + var x9 uint64 + x9, x8 = bits.Mul64(x2, 0xffffffff00000000) + var x10 uint64 + var x11 uint64 + x10, x11 = bits.Add64(x9, x6, uint64(0x0)) + var x12 uint64 + var x13 uint64 + x12, x13 = bits.Add64(x7, x4, uint64(p224Uint1(x11))) + var x15 uint64 + _, x15 = bits.Add64(x1, x2, uint64(0x0)) + var x16 uint64 + var x17 uint64 + x16, x17 = bits.Add64(uint64(0x0), x8, uint64(p224Uint1(x15))) + var x18 uint64 + var x19 uint64 + x18, x19 = bits.Add64(uint64(0x0), x10, uint64(p224Uint1(x17))) + var x20 uint64 + var x21 uint64 + x20, x21 = bits.Add64(uint64(0x0), x12, uint64(p224Uint1(x19))) + var x22 uint64 + var x23 uint64 + x22, x23 = bits.Add64(x16, arg1[1], uint64(0x0)) + var x24 uint64 + var x25 uint64 + x24, x25 = bits.Add64(x18, uint64(0x0), uint64(p224Uint1(x23))) + var x26 uint64 + var x27 uint64 + x26, x27 = bits.Add64(x20, uint64(0x0), uint64(p224Uint1(x25))) + var x28 uint64 + _, x28 = bits.Mul64(x22, 0xffffffffffffffff) + var x30 uint64 + var x31 uint64 + x31, x30 = bits.Mul64(x28, 0xffffffff) + var x32 uint64 + var x33 uint64 + x33, x32 = bits.Mul64(x28, 0xffffffffffffffff) + var x34 uint64 + var x35 uint64 + x35, x34 = bits.Mul64(x28, 0xffffffff00000000) + var x36 uint64 + var x37 uint64 + x36, x37 = bits.Add64(x35, x32, uint64(0x0)) + var x38 uint64 + var x39 uint64 + x38, x39 = bits.Add64(x33, x30, uint64(p224Uint1(x37))) + var x41 uint64 + _, x41 = bits.Add64(x22, x28, uint64(0x0)) + var x42 uint64 + var x43 uint64 + x42, x43 = bits.Add64(x24, x34, uint64(p224Uint1(x41))) + var x44 uint64 + var x45 uint64 + x44, x45 = bits.Add64(x26, x36, uint64(p224Uint1(x43))) + var x46 uint64 + var x47 uint64 + x46, x47 = bits.Add64((uint64(p224Uint1(x27)) + (uint64(p224Uint1(x21)) + (uint64(p224Uint1(x13)) + x5))), x38, uint64(p224Uint1(x45))) + var x48 uint64 + var x49 uint64 + x48, x49 = bits.Add64(x42, arg1[2], uint64(0x0)) + var x50 uint64 + var x51 uint64 + x50, x51 = bits.Add64(x44, uint64(0x0), uint64(p224Uint1(x49))) + var x52 uint64 + var x53 uint64 + x52, x53 = bits.Add64(x46, uint64(0x0), uint64(p224Uint1(x51))) + var x54 uint64 + _, x54 = bits.Mul64(x48, 0xffffffffffffffff) + var x56 uint64 + var x57 uint64 + x57, x56 = bits.Mul64(x54, 0xffffffff) + var x58 uint64 + var x59 uint64 + x59, x58 = bits.Mul64(x54, 0xffffffffffffffff) + var x60 uint64 + var x61 uint64 + x61, x60 = bits.Mul64(x54, 0xffffffff00000000) + var x62 uint64 + var x63 uint64 + x62, x63 = bits.Add64(x61, x58, uint64(0x0)) + var x64 uint64 + var x65 uint64 + x64, x65 = bits.Add64(x59, x56, uint64(p224Uint1(x63))) + var x67 uint64 + _, x67 = bits.Add64(x48, x54, uint64(0x0)) + var x68 uint64 + var x69 uint64 + x68, x69 = bits.Add64(x50, x60, uint64(p224Uint1(x67))) + var x70 uint64 + var x71 uint64 + x70, x71 = bits.Add64(x52, x62, uint64(p224Uint1(x69))) + var x72 uint64 + var x73 uint64 + x72, x73 = bits.Add64((uint64(p224Uint1(x53)) + (uint64(p224Uint1(x47)) + (uint64(p224Uint1(x39)) + x31))), x64, uint64(p224Uint1(x71))) + var x74 uint64 + var x75 uint64 + x74, x75 = bits.Add64(x68, arg1[3], uint64(0x0)) + var x76 uint64 + var x77 uint64 + x76, x77 = bits.Add64(x70, uint64(0x0), uint64(p224Uint1(x75))) + var x78 uint64 + var x79 uint64 + x78, x79 = bits.Add64(x72, uint64(0x0), uint64(p224Uint1(x77))) + var x80 uint64 + _, x80 = bits.Mul64(x74, 0xffffffffffffffff) + var x82 uint64 + var x83 uint64 + x83, x82 = bits.Mul64(x80, 0xffffffff) + var x84 uint64 + var x85 uint64 + x85, x84 = bits.Mul64(x80, 0xffffffffffffffff) + var x86 uint64 + var x87 uint64 + x87, x86 = bits.Mul64(x80, 0xffffffff00000000) + var x88 uint64 + var x89 uint64 + x88, x89 = bits.Add64(x87, x84, uint64(0x0)) + var x90 uint64 + var x91 uint64 + x90, x91 = bits.Add64(x85, x82, uint64(p224Uint1(x89))) + var x93 uint64 + _, x93 = bits.Add64(x74, x80, uint64(0x0)) + var x94 uint64 + var x95 uint64 + x94, x95 = bits.Add64(x76, x86, uint64(p224Uint1(x93))) + var x96 uint64 + var x97 uint64 + x96, x97 = bits.Add64(x78, x88, uint64(p224Uint1(x95))) + var x98 uint64 + var x99 uint64 + x98, x99 = bits.Add64((uint64(p224Uint1(x79)) + (uint64(p224Uint1(x73)) + (uint64(p224Uint1(x65)) + x57))), x90, uint64(p224Uint1(x97))) + x100 := (uint64(p224Uint1(x99)) + (uint64(p224Uint1(x91)) + x83)) + var x101 uint64 + var x102 uint64 + x101, x102 = bits.Sub64(x94, uint64(0x1), uint64(0x0)) + var x103 uint64 + var x104 uint64 + x103, x104 = bits.Sub64(x96, 0xffffffff00000000, uint64(p224Uint1(x102))) + var x105 uint64 + var x106 uint64 + x105, x106 = bits.Sub64(x98, 0xffffffffffffffff, uint64(p224Uint1(x104))) + var x107 uint64 + var x108 uint64 + x107, x108 = bits.Sub64(x100, 0xffffffff, uint64(p224Uint1(x106))) + var x110 uint64 + _, x110 = bits.Sub64(uint64(0x0), uint64(0x0), uint64(p224Uint1(x108))) + var x111 uint64 + p224CmovznzU64(&x111, p224Uint1(x110), x101, x94) + var x112 uint64 + p224CmovznzU64(&x112, p224Uint1(x110), x103, x96) + var x113 uint64 + p224CmovznzU64(&x113, p224Uint1(x110), x105, x98) + var x114 uint64 + p224CmovznzU64(&x114, p224Uint1(x110), x107, x100) + out1[0] = x111 + out1[1] = x112 + out1[2] = x113 + out1[3] = x114 +} + +// p224ToMontgomery translates a field element into the Montgomery domain. +// +// Preconditions: +// 0 ≤ eval arg1 < m +// Postconditions: +// eval (from_montgomery out1) mod m = eval arg1 mod m +// 0 ≤ eval out1 < m +// +func p224ToMontgomery(out1 *p224MontgomeryDomainFieldElement, arg1 *p224NonMontgomeryDomainFieldElement) { + x1 := arg1[1] + x2 := arg1[2] + x3 := arg1[3] + x4 := arg1[0] + var x5 uint64 + var x6 uint64 + x6, x5 = bits.Mul64(x4, 0xffffffff) + var x7 uint64 + var x8 uint64 + x8, x7 = bits.Mul64(x4, 0xfffffffe00000000) + var x9 uint64 + var x10 uint64 + x10, x9 = bits.Mul64(x4, 0xffffffff00000000) + var x11 uint64 + var x12 uint64 + x12, x11 = bits.Mul64(x4, 0xffffffff00000001) + var x13 uint64 + var x14 uint64 + x13, x14 = bits.Add64(x12, x9, uint64(0x0)) + var x15 uint64 + var x16 uint64 + x15, x16 = bits.Add64(x10, x7, uint64(p224Uint1(x14))) + var x17 uint64 + var x18 uint64 + x17, x18 = bits.Add64(x8, x5, uint64(p224Uint1(x16))) + var x19 uint64 + _, x19 = bits.Mul64(x11, 0xffffffffffffffff) + var x21 uint64 + var x22 uint64 + x22, x21 = bits.Mul64(x19, 0xffffffff) + var x23 uint64 + var x24 uint64 + x24, x23 = bits.Mul64(x19, 0xffffffffffffffff) + var x25 uint64 + var x26 uint64 + x26, x25 = bits.Mul64(x19, 0xffffffff00000000) + var x27 uint64 + var x28 uint64 + x27, x28 = bits.Add64(x26, x23, uint64(0x0)) + var x29 uint64 + var x30 uint64 + x29, x30 = bits.Add64(x24, x21, uint64(p224Uint1(x28))) + var x32 uint64 + _, x32 = bits.Add64(x11, x19, uint64(0x0)) + var x33 uint64 + var x34 uint64 + x33, x34 = bits.Add64(x13, x25, uint64(p224Uint1(x32))) + var x35 uint64 + var x36 uint64 + x35, x36 = bits.Add64(x15, x27, uint64(p224Uint1(x34))) + var x37 uint64 + var x38 uint64 + x37, x38 = bits.Add64(x17, x29, uint64(p224Uint1(x36))) + var x39 uint64 + var x40 uint64 + x40, x39 = bits.Mul64(x1, 0xffffffff) + var x41 uint64 + var x42 uint64 + x42, x41 = bits.Mul64(x1, 0xfffffffe00000000) + var x43 uint64 + var x44 uint64 + x44, x43 = bits.Mul64(x1, 0xffffffff00000000) + var x45 uint64 + var x46 uint64 + x46, x45 = bits.Mul64(x1, 0xffffffff00000001) + var x47 uint64 + var x48 uint64 + x47, x48 = bits.Add64(x46, x43, uint64(0x0)) + var x49 uint64 + var x50 uint64 + x49, x50 = bits.Add64(x44, x41, uint64(p224Uint1(x48))) + var x51 uint64 + var x52 uint64 + x51, x52 = bits.Add64(x42, x39, uint64(p224Uint1(x50))) + var x53 uint64 + var x54 uint64 + x53, x54 = bits.Add64(x33, x45, uint64(0x0)) + var x55 uint64 + var x56 uint64 + x55, x56 = bits.Add64(x35, x47, uint64(p224Uint1(x54))) + var x57 uint64 + var x58 uint64 + x57, x58 = bits.Add64(x37, x49, uint64(p224Uint1(x56))) + var x59 uint64 + var x60 uint64 + x59, x60 = bits.Add64(((uint64(p224Uint1(x38)) + (uint64(p224Uint1(x18)) + x6)) + (uint64(p224Uint1(x30)) + x22)), x51, uint64(p224Uint1(x58))) + var x61 uint64 + _, x61 = bits.Mul64(x53, 0xffffffffffffffff) + var x63 uint64 + var x64 uint64 + x64, x63 = bits.Mul64(x61, 0xffffffff) + var x65 uint64 + var x66 uint64 + x66, x65 = bits.Mul64(x61, 0xffffffffffffffff) + var x67 uint64 + var x68 uint64 + x68, x67 = bits.Mul64(x61, 0xffffffff00000000) + var x69 uint64 + var x70 uint64 + x69, x70 = bits.Add64(x68, x65, uint64(0x0)) + var x71 uint64 + var x72 uint64 + x71, x72 = bits.Add64(x66, x63, uint64(p224Uint1(x70))) + var x74 uint64 + _, x74 = bits.Add64(x53, x61, uint64(0x0)) + var x75 uint64 + var x76 uint64 + x75, x76 = bits.Add64(x55, x67, uint64(p224Uint1(x74))) + var x77 uint64 + var x78 uint64 + x77, x78 = bits.Add64(x57, x69, uint64(p224Uint1(x76))) + var x79 uint64 + var x80 uint64 + x79, x80 = bits.Add64(x59, x71, uint64(p224Uint1(x78))) + var x81 uint64 + var x82 uint64 + x82, x81 = bits.Mul64(x2, 0xffffffff) + var x83 uint64 + var x84 uint64 + x84, x83 = bits.Mul64(x2, 0xfffffffe00000000) + var x85 uint64 + var x86 uint64 + x86, x85 = bits.Mul64(x2, 0xffffffff00000000) + var x87 uint64 + var x88 uint64 + x88, x87 = bits.Mul64(x2, 0xffffffff00000001) + var x89 uint64 + var x90 uint64 + x89, x90 = bits.Add64(x88, x85, uint64(0x0)) + var x91 uint64 + var x92 uint64 + x91, x92 = bits.Add64(x86, x83, uint64(p224Uint1(x90))) + var x93 uint64 + var x94 uint64 + x93, x94 = bits.Add64(x84, x81, uint64(p224Uint1(x92))) + var x95 uint64 + var x96 uint64 + x95, x96 = bits.Add64(x75, x87, uint64(0x0)) + var x97 uint64 + var x98 uint64 + x97, x98 = bits.Add64(x77, x89, uint64(p224Uint1(x96))) + var x99 uint64 + var x100 uint64 + x99, x100 = bits.Add64(x79, x91, uint64(p224Uint1(x98))) + var x101 uint64 + var x102 uint64 + x101, x102 = bits.Add64(((uint64(p224Uint1(x80)) + (uint64(p224Uint1(x60)) + (uint64(p224Uint1(x52)) + x40))) + (uint64(p224Uint1(x72)) + x64)), x93, uint64(p224Uint1(x100))) + var x103 uint64 + _, x103 = bits.Mul64(x95, 0xffffffffffffffff) + var x105 uint64 + var x106 uint64 + x106, x105 = bits.Mul64(x103, 0xffffffff) + var x107 uint64 + var x108 uint64 + x108, x107 = bits.Mul64(x103, 0xffffffffffffffff) + var x109 uint64 + var x110 uint64 + x110, x109 = bits.Mul64(x103, 0xffffffff00000000) + var x111 uint64 + var x112 uint64 + x111, x112 = bits.Add64(x110, x107, uint64(0x0)) + var x113 uint64 + var x114 uint64 + x113, x114 = bits.Add64(x108, x105, uint64(p224Uint1(x112))) + var x116 uint64 + _, x116 = bits.Add64(x95, x103, uint64(0x0)) + var x117 uint64 + var x118 uint64 + x117, x118 = bits.Add64(x97, x109, uint64(p224Uint1(x116))) + var x119 uint64 + var x120 uint64 + x119, x120 = bits.Add64(x99, x111, uint64(p224Uint1(x118))) + var x121 uint64 + var x122 uint64 + x121, x122 = bits.Add64(x101, x113, uint64(p224Uint1(x120))) + var x123 uint64 + var x124 uint64 + x124, x123 = bits.Mul64(x3, 0xffffffff) + var x125 uint64 + var x126 uint64 + x126, x125 = bits.Mul64(x3, 0xfffffffe00000000) + var x127 uint64 + var x128 uint64 + x128, x127 = bits.Mul64(x3, 0xffffffff00000000) + var x129 uint64 + var x130 uint64 + x130, x129 = bits.Mul64(x3, 0xffffffff00000001) + var x131 uint64 + var x132 uint64 + x131, x132 = bits.Add64(x130, x127, uint64(0x0)) + var x133 uint64 + var x134 uint64 + x133, x134 = bits.Add64(x128, x125, uint64(p224Uint1(x132))) + var x135 uint64 + var x136 uint64 + x135, x136 = bits.Add64(x126, x123, uint64(p224Uint1(x134))) + var x137 uint64 + var x138 uint64 + x137, x138 = bits.Add64(x117, x129, uint64(0x0)) + var x139 uint64 + var x140 uint64 + x139, x140 = bits.Add64(x119, x131, uint64(p224Uint1(x138))) + var x141 uint64 + var x142 uint64 + x141, x142 = bits.Add64(x121, x133, uint64(p224Uint1(x140))) + var x143 uint64 + var x144 uint64 + x143, x144 = bits.Add64(((uint64(p224Uint1(x122)) + (uint64(p224Uint1(x102)) + (uint64(p224Uint1(x94)) + x82))) + (uint64(p224Uint1(x114)) + x106)), x135, uint64(p224Uint1(x142))) + var x145 uint64 + _, x145 = bits.Mul64(x137, 0xffffffffffffffff) + var x147 uint64 + var x148 uint64 + x148, x147 = bits.Mul64(x145, 0xffffffff) + var x149 uint64 + var x150 uint64 + x150, x149 = bits.Mul64(x145, 0xffffffffffffffff) + var x151 uint64 + var x152 uint64 + x152, x151 = bits.Mul64(x145, 0xffffffff00000000) + var x153 uint64 + var x154 uint64 + x153, x154 = bits.Add64(x152, x149, uint64(0x0)) + var x155 uint64 + var x156 uint64 + x155, x156 = bits.Add64(x150, x147, uint64(p224Uint1(x154))) + var x158 uint64 + _, x158 = bits.Add64(x137, x145, uint64(0x0)) + var x159 uint64 + var x160 uint64 + x159, x160 = bits.Add64(x139, x151, uint64(p224Uint1(x158))) + var x161 uint64 + var x162 uint64 + x161, x162 = bits.Add64(x141, x153, uint64(p224Uint1(x160))) + var x163 uint64 + var x164 uint64 + x163, x164 = bits.Add64(x143, x155, uint64(p224Uint1(x162))) + x165 := ((uint64(p224Uint1(x164)) + (uint64(p224Uint1(x144)) + (uint64(p224Uint1(x136)) + x124))) + (uint64(p224Uint1(x156)) + x148)) + var x166 uint64 + var x167 uint64 + x166, x167 = bits.Sub64(x159, uint64(0x1), uint64(0x0)) + var x168 uint64 + var x169 uint64 + x168, x169 = bits.Sub64(x161, 0xffffffff00000000, uint64(p224Uint1(x167))) + var x170 uint64 + var x171 uint64 + x170, x171 = bits.Sub64(x163, 0xffffffffffffffff, uint64(p224Uint1(x169))) + var x172 uint64 + var x173 uint64 + x172, x173 = bits.Sub64(x165, 0xffffffff, uint64(p224Uint1(x171))) + var x175 uint64 + _, x175 = bits.Sub64(uint64(0x0), uint64(0x0), uint64(p224Uint1(x173))) + var x176 uint64 + p224CmovznzU64(&x176, p224Uint1(x175), x166, x159) + var x177 uint64 + p224CmovznzU64(&x177, p224Uint1(x175), x168, x161) + var x178 uint64 + p224CmovznzU64(&x178, p224Uint1(x175), x170, x163) + var x179 uint64 + p224CmovznzU64(&x179, p224Uint1(x175), x172, x165) + out1[0] = x176 + out1[1] = x177 + out1[2] = x178 + out1[3] = x179 +} + +// p224Selectznz is a multi-limb conditional select. +// +// Postconditions: +// eval out1 = (if arg1 = 0 then eval arg2 else eval arg3) +// +// Input Bounds: +// arg1: [0x0 ~> 0x1] +// arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +// arg3: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +// Output Bounds: +// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +func p224Selectznz(out1 *[4]uint64, arg1 p224Uint1, arg2 *[4]uint64, arg3 *[4]uint64) { + var x1 uint64 + p224CmovznzU64(&x1, arg1, arg2[0], arg3[0]) + var x2 uint64 + p224CmovznzU64(&x2, arg1, arg2[1], arg3[1]) + var x3 uint64 + p224CmovznzU64(&x3, arg1, arg2[2], arg3[2]) + var x4 uint64 + p224CmovznzU64(&x4, arg1, arg2[3], arg3[3]) + out1[0] = x1 + out1[1] = x2 + out1[2] = x3 + out1[3] = x4 +} + +// p224ToBytes serializes a field element NOT in the Montgomery domain to bytes in little-endian order. +// +// Preconditions: +// 0 ≤ eval arg1 < m +// Postconditions: +// out1 = map (λ x, ⌊((eval arg1 mod m) mod 2^(8 * (x + 1))) / 2^(8 * x)⌋) [0..27] +// +// Input Bounds: +// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffff]] +// Output Bounds: +// out1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff]] +func p224ToBytes(out1 *[28]uint8, arg1 *[4]uint64) { + x1 := arg1[3] + x2 := arg1[2] + x3 := arg1[1] + x4 := arg1[0] + x5 := (uint8(x4) & 0xff) + x6 := (x4 >> 8) + x7 := (uint8(x6) & 0xff) + x8 := (x6 >> 8) + x9 := (uint8(x8) & 0xff) + x10 := (x8 >> 8) + x11 := (uint8(x10) & 0xff) + x12 := (x10 >> 8) + x13 := (uint8(x12) & 0xff) + x14 := (x12 >> 8) + x15 := (uint8(x14) & 0xff) + x16 := (x14 >> 8) + x17 := (uint8(x16) & 0xff) + x18 := uint8((x16 >> 8)) + x19 := (uint8(x3) & 0xff) + x20 := (x3 >> 8) + x21 := (uint8(x20) & 0xff) + x22 := (x20 >> 8) + x23 := (uint8(x22) & 0xff) + x24 := (x22 >> 8) + x25 := (uint8(x24) & 0xff) + x26 := (x24 >> 8) + x27 := (uint8(x26) & 0xff) + x28 := (x26 >> 8) + x29 := (uint8(x28) & 0xff) + x30 := (x28 >> 8) + x31 := (uint8(x30) & 0xff) + x32 := uint8((x30 >> 8)) + x33 := (uint8(x2) & 0xff) + x34 := (x2 >> 8) + x35 := (uint8(x34) & 0xff) + x36 := (x34 >> 8) + x37 := (uint8(x36) & 0xff) + x38 := (x36 >> 8) + x39 := (uint8(x38) & 0xff) + x40 := (x38 >> 8) + x41 := (uint8(x40) & 0xff) + x42 := (x40 >> 8) + x43 := (uint8(x42) & 0xff) + x44 := (x42 >> 8) + x45 := (uint8(x44) & 0xff) + x46 := uint8((x44 >> 8)) + x47 := (uint8(x1) & 0xff) + x48 := (x1 >> 8) + x49 := (uint8(x48) & 0xff) + x50 := (x48 >> 8) + x51 := (uint8(x50) & 0xff) + x52 := uint8((x50 >> 8)) + out1[0] = x5 + out1[1] = x7 + out1[2] = x9 + out1[3] = x11 + out1[4] = x13 + out1[5] = x15 + out1[6] = x17 + out1[7] = x18 + out1[8] = x19 + out1[9] = x21 + out1[10] = x23 + out1[11] = x25 + out1[12] = x27 + out1[13] = x29 + out1[14] = x31 + out1[15] = x32 + out1[16] = x33 + out1[17] = x35 + out1[18] = x37 + out1[19] = x39 + out1[20] = x41 + out1[21] = x43 + out1[22] = x45 + out1[23] = x46 + out1[24] = x47 + out1[25] = x49 + out1[26] = x51 + out1[27] = x52 +} + +// p224FromBytes deserializes a field element NOT in the Montgomery domain from bytes in little-endian order. +// +// Preconditions: +// 0 ≤ bytes_eval arg1 < m +// Postconditions: +// eval out1 mod m = bytes_eval arg1 mod m +// 0 ≤ eval out1 < m +// +// Input Bounds: +// arg1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff]] +// Output Bounds: +// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffff]] +func p224FromBytes(out1 *[4]uint64, arg1 *[28]uint8) { + x1 := (uint64(arg1[27]) << 24) + x2 := (uint64(arg1[26]) << 16) + x3 := (uint64(arg1[25]) << 8) + x4 := arg1[24] + x5 := (uint64(arg1[23]) << 56) + x6 := (uint64(arg1[22]) << 48) + x7 := (uint64(arg1[21]) << 40) + x8 := (uint64(arg1[20]) << 32) + x9 := (uint64(arg1[19]) << 24) + x10 := (uint64(arg1[18]) << 16) + x11 := (uint64(arg1[17]) << 8) + x12 := arg1[16] + x13 := (uint64(arg1[15]) << 56) + x14 := (uint64(arg1[14]) << 48) + x15 := (uint64(arg1[13]) << 40) + x16 := (uint64(arg1[12]) << 32) + x17 := (uint64(arg1[11]) << 24) + x18 := (uint64(arg1[10]) << 16) + x19 := (uint64(arg1[9]) << 8) + x20 := arg1[8] + x21 := (uint64(arg1[7]) << 56) + x22 := (uint64(arg1[6]) << 48) + x23 := (uint64(arg1[5]) << 40) + x24 := (uint64(arg1[4]) << 32) + x25 := (uint64(arg1[3]) << 24) + x26 := (uint64(arg1[2]) << 16) + x27 := (uint64(arg1[1]) << 8) + x28 := arg1[0] + x29 := (x27 + uint64(x28)) + x30 := (x26 + x29) + x31 := (x25 + x30) + x32 := (x24 + x31) + x33 := (x23 + x32) + x34 := (x22 + x33) + x35 := (x21 + x34) + x36 := (x19 + uint64(x20)) + x37 := (x18 + x36) + x38 := (x17 + x37) + x39 := (x16 + x38) + x40 := (x15 + x39) + x41 := (x14 + x40) + x42 := (x13 + x41) + x43 := (x11 + uint64(x12)) + x44 := (x10 + x43) + x45 := (x9 + x44) + x46 := (x8 + x45) + x47 := (x7 + x46) + x48 := (x6 + x47) + x49 := (x5 + x48) + x50 := (x3 + uint64(x4)) + x51 := (x2 + x50) + x52 := (x1 + x51) + out1[0] = x35 + out1[1] = x42 + out1[2] = x49 + out1[3] = x52 +} diff --git a/src/crypto/elliptic/internal/fiat/p224_invert.go b/src/crypto/elliptic/internal/fiat/p224_invert.go new file mode 100644 index 0000000000..4163ed0c67 --- /dev/null +++ b/src/crypto/elliptic/internal/fiat/p224_invert.go @@ -0,0 +1,87 @@ +// Copyright 2021 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. + +// Code generated by addchain. DO NOT EDIT. + +package fiat + +// Invert sets e = 1/x, and returns e. +// +// If x == 0, Invert returns e = 0. +func (e *P224Element) Invert(x *P224Element) *P224Element { + // Inversion is implemented as exponentiation with exponent p − 2. + // The sequence of 11 multiplications and 223 squarings is derived from the + // following addition chain generated with github.com/mmcloughlin/addchain v0.3.0. + // + // _10 = 2*1 + // _11 = 1 + _10 + // _110 = 2*_11 + // _111 = 1 + _110 + // _111000 = _111 << 3 + // _111111 = _111 + _111000 + // x12 = _111111 << 6 + _111111 + // x14 = x12 << 2 + _11 + // x17 = x14 << 3 + _111 + // x31 = x17 << 14 + x14 + // x48 = x31 << 17 + x17 + // x96 = x48 << 48 + x48 + // x127 = x96 << 31 + x31 + // return x127 << 97 + x96 + // + + var z = new(P224Element).Set(e) + var t0 = new(P224Element) + var t1 = new(P224Element) + var t2 = new(P224Element) + + z.Square(x) + t0.Mul(x, z) + z.Square(t0) + z.Mul(x, z) + t1.Square(z) + for s := 1; s < 3; s++ { + t1.Square(t1) + } + t1.Mul(z, t1) + t2.Square(t1) + for s := 1; s < 6; s++ { + t2.Square(t2) + } + t1.Mul(t1, t2) + for s := 0; s < 2; s++ { + t1.Square(t1) + } + t0.Mul(t0, t1) + t1.Square(t0) + for s := 1; s < 3; s++ { + t1.Square(t1) + } + z.Mul(z, t1) + t1.Square(z) + for s := 1; s < 14; s++ { + t1.Square(t1) + } + t0.Mul(t0, t1) + t1.Square(t0) + for s := 1; s < 17; s++ { + t1.Square(t1) + } + z.Mul(z, t1) + t1.Square(z) + for s := 1; s < 48; s++ { + t1.Square(t1) + } + z.Mul(z, t1) + t1.Square(z) + for s := 1; s < 31; s++ { + t1.Square(t1) + } + t0.Mul(t0, t1) + for s := 0; s < 97; s++ { + t0.Square(t0) + } + z.Mul(z, t0) + + return e.Set(z) +} diff --git a/src/crypto/elliptic/internal/fiat/p384.go b/src/crypto/elliptic/internal/fiat/p384.go new file mode 100644 index 0000000000..5474d77d48 --- /dev/null +++ b/src/crypto/elliptic/internal/fiat/p384.go @@ -0,0 +1,135 @@ +// Copyright 2021 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. + +// Code generated by generate.go. DO NOT EDIT. + +package fiat + +import ( + "crypto/subtle" + "errors" +) + +// P384Element is an integer modulo 2^384 - 2^128 - 2^96 + 2^32 - 1. +// +// The zero value is a valid zero element. +type P384Element struct { + // Values are represented internally always in the Montgomery domain, and + // converted in Bytes and SetBytes. + x p384MontgomeryDomainFieldElement +} + +const p384ElementLen = 48 + +type p384UntypedFieldElement = [6]uint64 + +// One sets e = 1, and returns e. +func (e *P384Element) One() *P384Element { + p384SetOne(&e.x) + return e +} + +// Equal returns 1 if e == t, and zero otherwise. +func (e *P384Element) Equal(t *P384Element) int { + eBytes := e.Bytes() + tBytes := t.Bytes() + return subtle.ConstantTimeCompare(eBytes, tBytes) +} + +var p384ZeroEncoding = new(P384Element).Bytes() + +// IsZero returns 1 if e == 0, and zero otherwise. +func (e *P384Element) IsZero() int { + eBytes := e.Bytes() + return subtle.ConstantTimeCompare(eBytes, p384ZeroEncoding) +} + +// Set sets e = t, and returns e. +func (e *P384Element) Set(t *P384Element) *P384Element { + e.x = t.x + return e +} + +// Bytes returns the 48-byte big-endian encoding of e. +func (e *P384Element) Bytes() []byte { + // This function is outlined to make the allocations inline in the caller + // rather than happen on the heap. + var out [p384ElementLen]byte + return e.bytes(&out) +} + +func (e *P384Element) bytes(out *[p384ElementLen]byte) []byte { + var tmp p384NonMontgomeryDomainFieldElement + p384FromMontgomery(&tmp, &e.x) + p384ToBytes(out, (*p384UntypedFieldElement)(&tmp)) + p384InvertEndianness(out[:]) + return out[:] +} + +// p384MinusOneEncoding is the encoding of -1 mod p, so p - 1, the +// highest canonical encoding. It is used by SetBytes to check for non-canonical +// encodings such as p + k, 2p + k, etc. +var p384MinusOneEncoding = new(P384Element).Sub( + new(P384Element), new(P384Element).One()).Bytes() + +// SetBytes sets e = v, where v is a big-endian 48-byte encoding, and returns e. +// If v is not 48 bytes or it encodes a value higher than 2^384 - 2^128 - 2^96 + 2^32 - 1, +// SetBytes returns nil and an error, and e is unchanged. +func (e *P384Element) SetBytes(v []byte) (*P384Element, error) { + if len(v) != p384ElementLen { + return nil, errors.New("invalid P384Element encoding") + } + for i := range v { + if v[i] < p384MinusOneEncoding[i] { + break + } + if v[i] > p384MinusOneEncoding[i] { + return nil, errors.New("invalid P384Element encoding") + } + } + var in [p384ElementLen]byte + copy(in[:], v) + p384InvertEndianness(in[:]) + var tmp p384NonMontgomeryDomainFieldElement + p384FromBytes((*p384UntypedFieldElement)(&tmp), &in) + p384ToMontgomery(&e.x, &tmp) + return e, nil +} + +// Add sets e = t1 + t2, and returns e. +func (e *P384Element) Add(t1, t2 *P384Element) *P384Element { + p384Add(&e.x, &t1.x, &t2.x) + return e +} + +// Sub sets e = t1 - t2, and returns e. +func (e *P384Element) Sub(t1, t2 *P384Element) *P384Element { + p384Sub(&e.x, &t1.x, &t2.x) + return e +} + +// Mul sets e = t1 * t2, and returns e. +func (e *P384Element) Mul(t1, t2 *P384Element) *P384Element { + p384Mul(&e.x, &t1.x, &t2.x) + return e +} + +// Square sets e = t * t, and returns e. +func (e *P384Element) Square(t *P384Element) *P384Element { + p384Square(&e.x, &t.x) + return e +} + +// Select sets v to a if cond == 1, and to b if cond == 0. +func (v *P384Element) Select(a, b *P384Element, cond int) *P384Element { + p384Selectznz((*p384UntypedFieldElement)(&v.x), p384Uint1(cond), + (*p384UntypedFieldElement)(&b.x), (*p384UntypedFieldElement)(&a.x)) + return v +} + +func p384InvertEndianness(v []byte) { + for i := 0; i < len(v)/2; i++ { + v[i], v[len(v)-1-i] = v[len(v)-1-i], v[i] + } +} diff --git a/src/crypto/elliptic/internal/fiat/p384_fiat64.go b/src/crypto/elliptic/internal/fiat/p384_fiat64.go new file mode 100644 index 0000000000..493bed47e1 --- /dev/null +++ b/src/crypto/elliptic/internal/fiat/p384_fiat64.go @@ -0,0 +1,3004 @@ +// Code generated by Fiat Cryptography. DO NOT EDIT. +// +// Autogenerated: word_by_word_montgomery --lang Go --no-wide-int --cmovznz-by-mul --relax-primitive-carry-to-bitwidth 32,64 --internal-static --public-function-case camelCase --public-type-case camelCase --private-function-case camelCase --private-type-case camelCase --doc-text-before-function-name '' --doc-newline-before-package-declaration --doc-prepend-header 'Code generated by Fiat Cryptography. DO NOT EDIT.' --package-name fiat --no-prefix-fiat p384 64 '2^384 - 2^128 - 2^96 + 2^32 - 1' mul square add sub one from_montgomery to_montgomery selectznz to_bytes from_bytes +// +// curve description: p384 +// +// machine_wordsize = 64 (from "64") +// +// requested operations: mul, square, add, sub, one, from_montgomery, to_montgomery, selectznz, to_bytes, from_bytes +// +// m = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff (from "2^384 - 2^128 - 2^96 + 2^32 - 1") +// +// +// +// NOTE: In addition to the bounds specified above each function, all +// +// functions synthesized for this Montgomery arithmetic require the +// +// input to be strictly less than the prime modulus (m), and also +// +// require the input to be in the unique saturated representation. +// +// All functions also ensure that these two properties are true of +// +// return values. +// +// +// +// Computed values: +// +// eval z = z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) + (z[4] << 256) + (z[5] << 0x140) +// +// bytes_eval z = z[0] + (z[1] << 8) + (z[2] << 16) + (z[3] << 24) + (z[4] << 32) + (z[5] << 40) + (z[6] << 48) + (z[7] << 56) + (z[8] << 64) + (z[9] << 72) + (z[10] << 80) + (z[11] << 88) + (z[12] << 96) + (z[13] << 104) + (z[14] << 112) + (z[15] << 120) + (z[16] << 128) + (z[17] << 136) + (z[18] << 144) + (z[19] << 152) + (z[20] << 160) + (z[21] << 168) + (z[22] << 176) + (z[23] << 184) + (z[24] << 192) + (z[25] << 200) + (z[26] << 208) + (z[27] << 216) + (z[28] << 224) + (z[29] << 232) + (z[30] << 240) + (z[31] << 248) + (z[32] << 256) + (z[33] << 0x108) + (z[34] << 0x110) + (z[35] << 0x118) + (z[36] << 0x120) + (z[37] << 0x128) + (z[38] << 0x130) + (z[39] << 0x138) + (z[40] << 0x140) + (z[41] << 0x148) + (z[42] << 0x150) + (z[43] << 0x158) + (z[44] << 0x160) + (z[45] << 0x168) + (z[46] << 0x170) + (z[47] << 0x178) +// +// twos_complement_eval z = let x1 := z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) + (z[4] << 256) + (z[5] << 0x140) in +// +// if x1 & (2^384-1) < 2^383 then x1 & (2^384-1) else (x1 & (2^384-1)) - 2^384 + +package fiat + +import "math/bits" + +type p384Uint1 uint64 // We use uint64 instead of a more narrow type for performance reasons; see https://github.com/mit-plv/fiat-crypto/pull/1006#issuecomment-892625927 +type p384Int1 int64 // We use uint64 instead of a more narrow type for performance reasons; see https://github.com/mit-plv/fiat-crypto/pull/1006#issuecomment-892625927 + +// The type p384MontgomeryDomainFieldElement is a field element in the Montgomery domain. +// +// Bounds: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +type p384MontgomeryDomainFieldElement [6]uint64 + +// The type p384NonMontgomeryDomainFieldElement is a field element NOT in the Montgomery domain. +// +// Bounds: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +type p384NonMontgomeryDomainFieldElement [6]uint64 + +// p384CmovznzU64 is a single-word conditional move. +// +// Postconditions: +// out1 = (if arg1 = 0 then arg2 else arg3) +// +// Input Bounds: +// arg1: [0x0 ~> 0x1] +// arg2: [0x0 ~> 0xffffffffffffffff] +// arg3: [0x0 ~> 0xffffffffffffffff] +// Output Bounds: +// out1: [0x0 ~> 0xffffffffffffffff] +func p384CmovznzU64(out1 *uint64, arg1 p384Uint1, arg2 uint64, arg3 uint64) { + x1 := (uint64(arg1) * 0xffffffffffffffff) + x2 := ((x1 & arg3) | ((^x1) & arg2)) + *out1 = x2 +} + +// p384Mul multiplies two field elements in the Montgomery domain. +// +// Preconditions: +// 0 ≤ eval arg1 < m +// 0 ≤ eval arg2 < m +// Postconditions: +// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg2)) mod m +// 0 ≤ eval out1 < m +// +func p384Mul(out1 *p384MontgomeryDomainFieldElement, arg1 *p384MontgomeryDomainFieldElement, arg2 *p384MontgomeryDomainFieldElement) { + x1 := arg1[1] + x2 := arg1[2] + x3 := arg1[3] + x4 := arg1[4] + x5 := arg1[5] + x6 := arg1[0] + var x7 uint64 + var x8 uint64 + x8, x7 = bits.Mul64(x6, arg2[5]) + var x9 uint64 + var x10 uint64 + x10, x9 = bits.Mul64(x6, arg2[4]) + var x11 uint64 + var x12 uint64 + x12, x11 = bits.Mul64(x6, arg2[3]) + var x13 uint64 + var x14 uint64 + x14, x13 = bits.Mul64(x6, arg2[2]) + var x15 uint64 + var x16 uint64 + x16, x15 = bits.Mul64(x6, arg2[1]) + var x17 uint64 + var x18 uint64 + x18, x17 = bits.Mul64(x6, arg2[0]) + var x19 uint64 + var x20 uint64 + x19, x20 = bits.Add64(x18, x15, uint64(0x0)) + var x21 uint64 + var x22 uint64 + x21, x22 = bits.Add64(x16, x13, uint64(p384Uint1(x20))) + var x23 uint64 + var x24 uint64 + x23, x24 = bits.Add64(x14, x11, uint64(p384Uint1(x22))) + var x25 uint64 + var x26 uint64 + x25, x26 = bits.Add64(x12, x9, uint64(p384Uint1(x24))) + var x27 uint64 + var x28 uint64 + x27, x28 = bits.Add64(x10, x7, uint64(p384Uint1(x26))) + x29 := (uint64(p384Uint1(x28)) + x8) + var x30 uint64 + _, x30 = bits.Mul64(x17, 0x100000001) + var x32 uint64 + var x33 uint64 + x33, x32 = bits.Mul64(x30, 0xffffffffffffffff) + var x34 uint64 + var x35 uint64 + x35, x34 = bits.Mul64(x30, 0xffffffffffffffff) + var x36 uint64 + var x37 uint64 + x37, x36 = bits.Mul64(x30, 0xffffffffffffffff) + var x38 uint64 + var x39 uint64 + x39, x38 = bits.Mul64(x30, 0xfffffffffffffffe) + var x40 uint64 + var x41 uint64 + x41, x40 = bits.Mul64(x30, 0xffffffff00000000) + var x42 uint64 + var x43 uint64 + x43, x42 = bits.Mul64(x30, 0xffffffff) + var x44 uint64 + var x45 uint64 + x44, x45 = bits.Add64(x43, x40, uint64(0x0)) + var x46 uint64 + var x47 uint64 + x46, x47 = bits.Add64(x41, x38, uint64(p384Uint1(x45))) + var x48 uint64 + var x49 uint64 + x48, x49 = bits.Add64(x39, x36, uint64(p384Uint1(x47))) + var x50 uint64 + var x51 uint64 + x50, x51 = bits.Add64(x37, x34, uint64(p384Uint1(x49))) + var x52 uint64 + var x53 uint64 + x52, x53 = bits.Add64(x35, x32, uint64(p384Uint1(x51))) + x54 := (uint64(p384Uint1(x53)) + x33) + var x56 uint64 + _, x56 = bits.Add64(x17, x42, uint64(0x0)) + var x57 uint64 + var x58 uint64 + x57, x58 = bits.Add64(x19, x44, uint64(p384Uint1(x56))) + var x59 uint64 + var x60 uint64 + x59, x60 = bits.Add64(x21, x46, uint64(p384Uint1(x58))) + var x61 uint64 + var x62 uint64 + x61, x62 = bits.Add64(x23, x48, uint64(p384Uint1(x60))) + var x63 uint64 + var x64 uint64 + x63, x64 = bits.Add64(x25, x50, uint64(p384Uint1(x62))) + var x65 uint64 + var x66 uint64 + x65, x66 = bits.Add64(x27, x52, uint64(p384Uint1(x64))) + var x67 uint64 + var x68 uint64 + x67, x68 = bits.Add64(x29, x54, uint64(p384Uint1(x66))) + var x69 uint64 + var x70 uint64 + x70, x69 = bits.Mul64(x1, arg2[5]) + var x71 uint64 + var x72 uint64 + x72, x71 = bits.Mul64(x1, arg2[4]) + var x73 uint64 + var x74 uint64 + x74, x73 = bits.Mul64(x1, arg2[3]) + var x75 uint64 + var x76 uint64 + x76, x75 = bits.Mul64(x1, arg2[2]) + var x77 uint64 + var x78 uint64 + x78, x77 = bits.Mul64(x1, arg2[1]) + var x79 uint64 + var x80 uint64 + x80, x79 = bits.Mul64(x1, arg2[0]) + var x81 uint64 + var x82 uint64 + x81, x82 = bits.Add64(x80, x77, uint64(0x0)) + var x83 uint64 + var x84 uint64 + x83, x84 = bits.Add64(x78, x75, uint64(p384Uint1(x82))) + var x85 uint64 + var x86 uint64 + x85, x86 = bits.Add64(x76, x73, uint64(p384Uint1(x84))) + var x87 uint64 + var x88 uint64 + x87, x88 = bits.Add64(x74, x71, uint64(p384Uint1(x86))) + var x89 uint64 + var x90 uint64 + x89, x90 = bits.Add64(x72, x69, uint64(p384Uint1(x88))) + x91 := (uint64(p384Uint1(x90)) + x70) + var x92 uint64 + var x93 uint64 + x92, x93 = bits.Add64(x57, x79, uint64(0x0)) + var x94 uint64 + var x95 uint64 + x94, x95 = bits.Add64(x59, x81, uint64(p384Uint1(x93))) + var x96 uint64 + var x97 uint64 + x96, x97 = bits.Add64(x61, x83, uint64(p384Uint1(x95))) + var x98 uint64 + var x99 uint64 + x98, x99 = bits.Add64(x63, x85, uint64(p384Uint1(x97))) + var x100 uint64 + var x101 uint64 + x100, x101 = bits.Add64(x65, x87, uint64(p384Uint1(x99))) + var x102 uint64 + var x103 uint64 + x102, x103 = bits.Add64(x67, x89, uint64(p384Uint1(x101))) + var x104 uint64 + var x105 uint64 + x104, x105 = bits.Add64(uint64(p384Uint1(x68)), x91, uint64(p384Uint1(x103))) + var x106 uint64 + _, x106 = bits.Mul64(x92, 0x100000001) + var x108 uint64 + var x109 uint64 + x109, x108 = bits.Mul64(x106, 0xffffffffffffffff) + var x110 uint64 + var x111 uint64 + x111, x110 = bits.Mul64(x106, 0xffffffffffffffff) + var x112 uint64 + var x113 uint64 + x113, x112 = bits.Mul64(x106, 0xffffffffffffffff) + var x114 uint64 + var x115 uint64 + x115, x114 = bits.Mul64(x106, 0xfffffffffffffffe) + var x116 uint64 + var x117 uint64 + x117, x116 = bits.Mul64(x106, 0xffffffff00000000) + var x118 uint64 + var x119 uint64 + x119, x118 = bits.Mul64(x106, 0xffffffff) + var x120 uint64 + var x121 uint64 + x120, x121 = bits.Add64(x119, x116, uint64(0x0)) + var x122 uint64 + var x123 uint64 + x122, x123 = bits.Add64(x117, x114, uint64(p384Uint1(x121))) + var x124 uint64 + var x125 uint64 + x124, x125 = bits.Add64(x115, x112, uint64(p384Uint1(x123))) + var x126 uint64 + var x127 uint64 + x126, x127 = bits.Add64(x113, x110, uint64(p384Uint1(x125))) + var x128 uint64 + var x129 uint64 + x128, x129 = bits.Add64(x111, x108, uint64(p384Uint1(x127))) + x130 := (uint64(p384Uint1(x129)) + x109) + var x132 uint64 + _, x132 = bits.Add64(x92, x118, uint64(0x0)) + var x133 uint64 + var x134 uint64 + x133, x134 = bits.Add64(x94, x120, uint64(p384Uint1(x132))) + var x135 uint64 + var x136 uint64 + x135, x136 = bits.Add64(x96, x122, uint64(p384Uint1(x134))) + var x137 uint64 + var x138 uint64 + x137, x138 = bits.Add64(x98, x124, uint64(p384Uint1(x136))) + var x139 uint64 + var x140 uint64 + x139, x140 = bits.Add64(x100, x126, uint64(p384Uint1(x138))) + var x141 uint64 + var x142 uint64 + x141, x142 = bits.Add64(x102, x128, uint64(p384Uint1(x140))) + var x143 uint64 + var x144 uint64 + x143, x144 = bits.Add64(x104, x130, uint64(p384Uint1(x142))) + x145 := (uint64(p384Uint1(x144)) + uint64(p384Uint1(x105))) + var x146 uint64 + var x147 uint64 + x147, x146 = bits.Mul64(x2, arg2[5]) + var x148 uint64 + var x149 uint64 + x149, x148 = bits.Mul64(x2, arg2[4]) + var x150 uint64 + var x151 uint64 + x151, x150 = bits.Mul64(x2, arg2[3]) + var x152 uint64 + var x153 uint64 + x153, x152 = bits.Mul64(x2, arg2[2]) + var x154 uint64 + var x155 uint64 + x155, x154 = bits.Mul64(x2, arg2[1]) + var x156 uint64 + var x157 uint64 + x157, x156 = bits.Mul64(x2, arg2[0]) + var x158 uint64 + var x159 uint64 + x158, x159 = bits.Add64(x157, x154, uint64(0x0)) + var x160 uint64 + var x161 uint64 + x160, x161 = bits.Add64(x155, x152, uint64(p384Uint1(x159))) + var x162 uint64 + var x163 uint64 + x162, x163 = bits.Add64(x153, x150, uint64(p384Uint1(x161))) + var x164 uint64 + var x165 uint64 + x164, x165 = bits.Add64(x151, x148, uint64(p384Uint1(x163))) + var x166 uint64 + var x167 uint64 + x166, x167 = bits.Add64(x149, x146, uint64(p384Uint1(x165))) + x168 := (uint64(p384Uint1(x167)) + x147) + var x169 uint64 + var x170 uint64 + x169, x170 = bits.Add64(x133, x156, uint64(0x0)) + var x171 uint64 + var x172 uint64 + x171, x172 = bits.Add64(x135, x158, uint64(p384Uint1(x170))) + var x173 uint64 + var x174 uint64 + x173, x174 = bits.Add64(x137, x160, uint64(p384Uint1(x172))) + var x175 uint64 + var x176 uint64 + x175, x176 = bits.Add64(x139, x162, uint64(p384Uint1(x174))) + var x177 uint64 + var x178 uint64 + x177, x178 = bits.Add64(x141, x164, uint64(p384Uint1(x176))) + var x179 uint64 + var x180 uint64 + x179, x180 = bits.Add64(x143, x166, uint64(p384Uint1(x178))) + var x181 uint64 + var x182 uint64 + x181, x182 = bits.Add64(x145, x168, uint64(p384Uint1(x180))) + var x183 uint64 + _, x183 = bits.Mul64(x169, 0x100000001) + var x185 uint64 + var x186 uint64 + x186, x185 = bits.Mul64(x183, 0xffffffffffffffff) + var x187 uint64 + var x188 uint64 + x188, x187 = bits.Mul64(x183, 0xffffffffffffffff) + var x189 uint64 + var x190 uint64 + x190, x189 = bits.Mul64(x183, 0xffffffffffffffff) + var x191 uint64 + var x192 uint64 + x192, x191 = bits.Mul64(x183, 0xfffffffffffffffe) + var x193 uint64 + var x194 uint64 + x194, x193 = bits.Mul64(x183, 0xffffffff00000000) + var x195 uint64 + var x196 uint64 + x196, x195 = bits.Mul64(x183, 0xffffffff) + var x197 uint64 + var x198 uint64 + x197, x198 = bits.Add64(x196, x193, uint64(0x0)) + var x199 uint64 + var x200 uint64 + x199, x200 = bits.Add64(x194, x191, uint64(p384Uint1(x198))) + var x201 uint64 + var x202 uint64 + x201, x202 = bits.Add64(x192, x189, uint64(p384Uint1(x200))) + var x203 uint64 + var x204 uint64 + x203, x204 = bits.Add64(x190, x187, uint64(p384Uint1(x202))) + var x205 uint64 + var x206 uint64 + x205, x206 = bits.Add64(x188, x185, uint64(p384Uint1(x204))) + x207 := (uint64(p384Uint1(x206)) + x186) + var x209 uint64 + _, x209 = bits.Add64(x169, x195, uint64(0x0)) + var x210 uint64 + var x211 uint64 + x210, x211 = bits.Add64(x171, x197, uint64(p384Uint1(x209))) + var x212 uint64 + var x213 uint64 + x212, x213 = bits.Add64(x173, x199, uint64(p384Uint1(x211))) + var x214 uint64 + var x215 uint64 + x214, x215 = bits.Add64(x175, x201, uint64(p384Uint1(x213))) + var x216 uint64 + var x217 uint64 + x216, x217 = bits.Add64(x177, x203, uint64(p384Uint1(x215))) + var x218 uint64 + var x219 uint64 + x218, x219 = bits.Add64(x179, x205, uint64(p384Uint1(x217))) + var x220 uint64 + var x221 uint64 + x220, x221 = bits.Add64(x181, x207, uint64(p384Uint1(x219))) + x222 := (uint64(p384Uint1(x221)) + uint64(p384Uint1(x182))) + var x223 uint64 + var x224 uint64 + x224, x223 = bits.Mul64(x3, arg2[5]) + var x225 uint64 + var x226 uint64 + x226, x225 = bits.Mul64(x3, arg2[4]) + var x227 uint64 + var x228 uint64 + x228, x227 = bits.Mul64(x3, arg2[3]) + var x229 uint64 + var x230 uint64 + x230, x229 = bits.Mul64(x3, arg2[2]) + var x231 uint64 + var x232 uint64 + x232, x231 = bits.Mul64(x3, arg2[1]) + var x233 uint64 + var x234 uint64 + x234, x233 = bits.Mul64(x3, arg2[0]) + var x235 uint64 + var x236 uint64 + x235, x236 = bits.Add64(x234, x231, uint64(0x0)) + var x237 uint64 + var x238 uint64 + x237, x238 = bits.Add64(x232, x229, uint64(p384Uint1(x236))) + var x239 uint64 + var x240 uint64 + x239, x240 = bits.Add64(x230, x227, uint64(p384Uint1(x238))) + var x241 uint64 + var x242 uint64 + x241, x242 = bits.Add64(x228, x225, uint64(p384Uint1(x240))) + var x243 uint64 + var x244 uint64 + x243, x244 = bits.Add64(x226, x223, uint64(p384Uint1(x242))) + x245 := (uint64(p384Uint1(x244)) + x224) + var x246 uint64 + var x247 uint64 + x246, x247 = bits.Add64(x210, x233, uint64(0x0)) + var x248 uint64 + var x249 uint64 + x248, x249 = bits.Add64(x212, x235, uint64(p384Uint1(x247))) + var x250 uint64 + var x251 uint64 + x250, x251 = bits.Add64(x214, x237, uint64(p384Uint1(x249))) + var x252 uint64 + var x253 uint64 + x252, x253 = bits.Add64(x216, x239, uint64(p384Uint1(x251))) + var x254 uint64 + var x255 uint64 + x254, x255 = bits.Add64(x218, x241, uint64(p384Uint1(x253))) + var x256 uint64 + var x257 uint64 + x256, x257 = bits.Add64(x220, x243, uint64(p384Uint1(x255))) + var x258 uint64 + var x259 uint64 + x258, x259 = bits.Add64(x222, x245, uint64(p384Uint1(x257))) + var x260 uint64 + _, x260 = bits.Mul64(x246, 0x100000001) + var x262 uint64 + var x263 uint64 + x263, x262 = bits.Mul64(x260, 0xffffffffffffffff) + var x264 uint64 + var x265 uint64 + x265, x264 = bits.Mul64(x260, 0xffffffffffffffff) + var x266 uint64 + var x267 uint64 + x267, x266 = bits.Mul64(x260, 0xffffffffffffffff) + var x268 uint64 + var x269 uint64 + x269, x268 = bits.Mul64(x260, 0xfffffffffffffffe) + var x270 uint64 + var x271 uint64 + x271, x270 = bits.Mul64(x260, 0xffffffff00000000) + var x272 uint64 + var x273 uint64 + x273, x272 = bits.Mul64(x260, 0xffffffff) + var x274 uint64 + var x275 uint64 + x274, x275 = bits.Add64(x273, x270, uint64(0x0)) + var x276 uint64 + var x277 uint64 + x276, x277 = bits.Add64(x271, x268, uint64(p384Uint1(x275))) + var x278 uint64 + var x279 uint64 + x278, x279 = bits.Add64(x269, x266, uint64(p384Uint1(x277))) + var x280 uint64 + var x281 uint64 + x280, x281 = bits.Add64(x267, x264, uint64(p384Uint1(x279))) + var x282 uint64 + var x283 uint64 + x282, x283 = bits.Add64(x265, x262, uint64(p384Uint1(x281))) + x284 := (uint64(p384Uint1(x283)) + x263) + var x286 uint64 + _, x286 = bits.Add64(x246, x272, uint64(0x0)) + var x287 uint64 + var x288 uint64 + x287, x288 = bits.Add64(x248, x274, uint64(p384Uint1(x286))) + var x289 uint64 + var x290 uint64 + x289, x290 = bits.Add64(x250, x276, uint64(p384Uint1(x288))) + var x291 uint64 + var x292 uint64 + x291, x292 = bits.Add64(x252, x278, uint64(p384Uint1(x290))) + var x293 uint64 + var x294 uint64 + x293, x294 = bits.Add64(x254, x280, uint64(p384Uint1(x292))) + var x295 uint64 + var x296 uint64 + x295, x296 = bits.Add64(x256, x282, uint64(p384Uint1(x294))) + var x297 uint64 + var x298 uint64 + x297, x298 = bits.Add64(x258, x284, uint64(p384Uint1(x296))) + x299 := (uint64(p384Uint1(x298)) + uint64(p384Uint1(x259))) + var x300 uint64 + var x301 uint64 + x301, x300 = bits.Mul64(x4, arg2[5]) + var x302 uint64 + var x303 uint64 + x303, x302 = bits.Mul64(x4, arg2[4]) + var x304 uint64 + var x305 uint64 + x305, x304 = bits.Mul64(x4, arg2[3]) + var x306 uint64 + var x307 uint64 + x307, x306 = bits.Mul64(x4, arg2[2]) + var x308 uint64 + var x309 uint64 + x309, x308 = bits.Mul64(x4, arg2[1]) + var x310 uint64 + var x311 uint64 + x311, x310 = bits.Mul64(x4, arg2[0]) + var x312 uint64 + var x313 uint64 + x312, x313 = bits.Add64(x311, x308, uint64(0x0)) + var x314 uint64 + var x315 uint64 + x314, x315 = bits.Add64(x309, x306, uint64(p384Uint1(x313))) + var x316 uint64 + var x317 uint64 + x316, x317 = bits.Add64(x307, x304, uint64(p384Uint1(x315))) + var x318 uint64 + var x319 uint64 + x318, x319 = bits.Add64(x305, x302, uint64(p384Uint1(x317))) + var x320 uint64 + var x321 uint64 + x320, x321 = bits.Add64(x303, x300, uint64(p384Uint1(x319))) + x322 := (uint64(p384Uint1(x321)) + x301) + var x323 uint64 + var x324 uint64 + x323, x324 = bits.Add64(x287, x310, uint64(0x0)) + var x325 uint64 + var x326 uint64 + x325, x326 = bits.Add64(x289, x312, uint64(p384Uint1(x324))) + var x327 uint64 + var x328 uint64 + x327, x328 = bits.Add64(x291, x314, uint64(p384Uint1(x326))) + var x329 uint64 + var x330 uint64 + x329, x330 = bits.Add64(x293, x316, uint64(p384Uint1(x328))) + var x331 uint64 + var x332 uint64 + x331, x332 = bits.Add64(x295, x318, uint64(p384Uint1(x330))) + var x333 uint64 + var x334 uint64 + x333, x334 = bits.Add64(x297, x320, uint64(p384Uint1(x332))) + var x335 uint64 + var x336 uint64 + x335, x336 = bits.Add64(x299, x322, uint64(p384Uint1(x334))) + var x337 uint64 + _, x337 = bits.Mul64(x323, 0x100000001) + var x339 uint64 + var x340 uint64 + x340, x339 = bits.Mul64(x337, 0xffffffffffffffff) + var x341 uint64 + var x342 uint64 + x342, x341 = bits.Mul64(x337, 0xffffffffffffffff) + var x343 uint64 + var x344 uint64 + x344, x343 = bits.Mul64(x337, 0xffffffffffffffff) + var x345 uint64 + var x346 uint64 + x346, x345 = bits.Mul64(x337, 0xfffffffffffffffe) + var x347 uint64 + var x348 uint64 + x348, x347 = bits.Mul64(x337, 0xffffffff00000000) + var x349 uint64 + var x350 uint64 + x350, x349 = bits.Mul64(x337, 0xffffffff) + var x351 uint64 + var x352 uint64 + x351, x352 = bits.Add64(x350, x347, uint64(0x0)) + var x353 uint64 + var x354 uint64 + x353, x354 = bits.Add64(x348, x345, uint64(p384Uint1(x352))) + var x355 uint64 + var x356 uint64 + x355, x356 = bits.Add64(x346, x343, uint64(p384Uint1(x354))) + var x357 uint64 + var x358 uint64 + x357, x358 = bits.Add64(x344, x341, uint64(p384Uint1(x356))) + var x359 uint64 + var x360 uint64 + x359, x360 = bits.Add64(x342, x339, uint64(p384Uint1(x358))) + x361 := (uint64(p384Uint1(x360)) + x340) + var x363 uint64 + _, x363 = bits.Add64(x323, x349, uint64(0x0)) + var x364 uint64 + var x365 uint64 + x364, x365 = bits.Add64(x325, x351, uint64(p384Uint1(x363))) + var x366 uint64 + var x367 uint64 + x366, x367 = bits.Add64(x327, x353, uint64(p384Uint1(x365))) + var x368 uint64 + var x369 uint64 + x368, x369 = bits.Add64(x329, x355, uint64(p384Uint1(x367))) + var x370 uint64 + var x371 uint64 + x370, x371 = bits.Add64(x331, x357, uint64(p384Uint1(x369))) + var x372 uint64 + var x373 uint64 + x372, x373 = bits.Add64(x333, x359, uint64(p384Uint1(x371))) + var x374 uint64 + var x375 uint64 + x374, x375 = bits.Add64(x335, x361, uint64(p384Uint1(x373))) + x376 := (uint64(p384Uint1(x375)) + uint64(p384Uint1(x336))) + var x377 uint64 + var x378 uint64 + x378, x377 = bits.Mul64(x5, arg2[5]) + var x379 uint64 + var x380 uint64 + x380, x379 = bits.Mul64(x5, arg2[4]) + var x381 uint64 + var x382 uint64 + x382, x381 = bits.Mul64(x5, arg2[3]) + var x383 uint64 + var x384 uint64 + x384, x383 = bits.Mul64(x5, arg2[2]) + var x385 uint64 + var x386 uint64 + x386, x385 = bits.Mul64(x5, arg2[1]) + var x387 uint64 + var x388 uint64 + x388, x387 = bits.Mul64(x5, arg2[0]) + var x389 uint64 + var x390 uint64 + x389, x390 = bits.Add64(x388, x385, uint64(0x0)) + var x391 uint64 + var x392 uint64 + x391, x392 = bits.Add64(x386, x383, uint64(p384Uint1(x390))) + var x393 uint64 + var x394 uint64 + x393, x394 = bits.Add64(x384, x381, uint64(p384Uint1(x392))) + var x395 uint64 + var x396 uint64 + x395, x396 = bits.Add64(x382, x379, uint64(p384Uint1(x394))) + var x397 uint64 + var x398 uint64 + x397, x398 = bits.Add64(x380, x377, uint64(p384Uint1(x396))) + x399 := (uint64(p384Uint1(x398)) + x378) + var x400 uint64 + var x401 uint64 + x400, x401 = bits.Add64(x364, x387, uint64(0x0)) + var x402 uint64 + var x403 uint64 + x402, x403 = bits.Add64(x366, x389, uint64(p384Uint1(x401))) + var x404 uint64 + var x405 uint64 + x404, x405 = bits.Add64(x368, x391, uint64(p384Uint1(x403))) + var x406 uint64 + var x407 uint64 + x406, x407 = bits.Add64(x370, x393, uint64(p384Uint1(x405))) + var x408 uint64 + var x409 uint64 + x408, x409 = bits.Add64(x372, x395, uint64(p384Uint1(x407))) + var x410 uint64 + var x411 uint64 + x410, x411 = bits.Add64(x374, x397, uint64(p384Uint1(x409))) + var x412 uint64 + var x413 uint64 + x412, x413 = bits.Add64(x376, x399, uint64(p384Uint1(x411))) + var x414 uint64 + _, x414 = bits.Mul64(x400, 0x100000001) + var x416 uint64 + var x417 uint64 + x417, x416 = bits.Mul64(x414, 0xffffffffffffffff) + var x418 uint64 + var x419 uint64 + x419, x418 = bits.Mul64(x414, 0xffffffffffffffff) + var x420 uint64 + var x421 uint64 + x421, x420 = bits.Mul64(x414, 0xffffffffffffffff) + var x422 uint64 + var x423 uint64 + x423, x422 = bits.Mul64(x414, 0xfffffffffffffffe) + var x424 uint64 + var x425 uint64 + x425, x424 = bits.Mul64(x414, 0xffffffff00000000) + var x426 uint64 + var x427 uint64 + x427, x426 = bits.Mul64(x414, 0xffffffff) + var x428 uint64 + var x429 uint64 + x428, x429 = bits.Add64(x427, x424, uint64(0x0)) + var x430 uint64 + var x431 uint64 + x430, x431 = bits.Add64(x425, x422, uint64(p384Uint1(x429))) + var x432 uint64 + var x433 uint64 + x432, x433 = bits.Add64(x423, x420, uint64(p384Uint1(x431))) + var x434 uint64 + var x435 uint64 + x434, x435 = bits.Add64(x421, x418, uint64(p384Uint1(x433))) + var x436 uint64 + var x437 uint64 + x436, x437 = bits.Add64(x419, x416, uint64(p384Uint1(x435))) + x438 := (uint64(p384Uint1(x437)) + x417) + var x440 uint64 + _, x440 = bits.Add64(x400, x426, uint64(0x0)) + var x441 uint64 + var x442 uint64 + x441, x442 = bits.Add64(x402, x428, uint64(p384Uint1(x440))) + var x443 uint64 + var x444 uint64 + x443, x444 = bits.Add64(x404, x430, uint64(p384Uint1(x442))) + var x445 uint64 + var x446 uint64 + x445, x446 = bits.Add64(x406, x432, uint64(p384Uint1(x444))) + var x447 uint64 + var x448 uint64 + x447, x448 = bits.Add64(x408, x434, uint64(p384Uint1(x446))) + var x449 uint64 + var x450 uint64 + x449, x450 = bits.Add64(x410, x436, uint64(p384Uint1(x448))) + var x451 uint64 + var x452 uint64 + x451, x452 = bits.Add64(x412, x438, uint64(p384Uint1(x450))) + x453 := (uint64(p384Uint1(x452)) + uint64(p384Uint1(x413))) + var x454 uint64 + var x455 uint64 + x454, x455 = bits.Sub64(x441, 0xffffffff, uint64(0x0)) + var x456 uint64 + var x457 uint64 + x456, x457 = bits.Sub64(x443, 0xffffffff00000000, uint64(p384Uint1(x455))) + var x458 uint64 + var x459 uint64 + x458, x459 = bits.Sub64(x445, 0xfffffffffffffffe, uint64(p384Uint1(x457))) + var x460 uint64 + var x461 uint64 + x460, x461 = bits.Sub64(x447, 0xffffffffffffffff, uint64(p384Uint1(x459))) + var x462 uint64 + var x463 uint64 + x462, x463 = bits.Sub64(x449, 0xffffffffffffffff, uint64(p384Uint1(x461))) + var x464 uint64 + var x465 uint64 + x464, x465 = bits.Sub64(x451, 0xffffffffffffffff, uint64(p384Uint1(x463))) + var x467 uint64 + _, x467 = bits.Sub64(x453, uint64(0x0), uint64(p384Uint1(x465))) + var x468 uint64 + p384CmovznzU64(&x468, p384Uint1(x467), x454, x441) + var x469 uint64 + p384CmovznzU64(&x469, p384Uint1(x467), x456, x443) + var x470 uint64 + p384CmovznzU64(&x470, p384Uint1(x467), x458, x445) + var x471 uint64 + p384CmovznzU64(&x471, p384Uint1(x467), x460, x447) + var x472 uint64 + p384CmovznzU64(&x472, p384Uint1(x467), x462, x449) + var x473 uint64 + p384CmovznzU64(&x473, p384Uint1(x467), x464, x451) + out1[0] = x468 + out1[1] = x469 + out1[2] = x470 + out1[3] = x471 + out1[4] = x472 + out1[5] = x473 +} + +// p384Square squares a field element in the Montgomery domain. +// +// Preconditions: +// 0 ≤ eval arg1 < m +// Postconditions: +// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg1)) mod m +// 0 ≤ eval out1 < m +// +func p384Square(out1 *p384MontgomeryDomainFieldElement, arg1 *p384MontgomeryDomainFieldElement) { + x1 := arg1[1] + x2 := arg1[2] + x3 := arg1[3] + x4 := arg1[4] + x5 := arg1[5] + x6 := arg1[0] + var x7 uint64 + var x8 uint64 + x8, x7 = bits.Mul64(x6, arg1[5]) + var x9 uint64 + var x10 uint64 + x10, x9 = bits.Mul64(x6, arg1[4]) + var x11 uint64 + var x12 uint64 + x12, x11 = bits.Mul64(x6, arg1[3]) + var x13 uint64 + var x14 uint64 + x14, x13 = bits.Mul64(x6, arg1[2]) + var x15 uint64 + var x16 uint64 + x16, x15 = bits.Mul64(x6, arg1[1]) + var x17 uint64 + var x18 uint64 + x18, x17 = bits.Mul64(x6, arg1[0]) + var x19 uint64 + var x20 uint64 + x19, x20 = bits.Add64(x18, x15, uint64(0x0)) + var x21 uint64 + var x22 uint64 + x21, x22 = bits.Add64(x16, x13, uint64(p384Uint1(x20))) + var x23 uint64 + var x24 uint64 + x23, x24 = bits.Add64(x14, x11, uint64(p384Uint1(x22))) + var x25 uint64 + var x26 uint64 + x25, x26 = bits.Add64(x12, x9, uint64(p384Uint1(x24))) + var x27 uint64 + var x28 uint64 + x27, x28 = bits.Add64(x10, x7, uint64(p384Uint1(x26))) + x29 := (uint64(p384Uint1(x28)) + x8) + var x30 uint64 + _, x30 = bits.Mul64(x17, 0x100000001) + var x32 uint64 + var x33 uint64 + x33, x32 = bits.Mul64(x30, 0xffffffffffffffff) + var x34 uint64 + var x35 uint64 + x35, x34 = bits.Mul64(x30, 0xffffffffffffffff) + var x36 uint64 + var x37 uint64 + x37, x36 = bits.Mul64(x30, 0xffffffffffffffff) + var x38 uint64 + var x39 uint64 + x39, x38 = bits.Mul64(x30, 0xfffffffffffffffe) + var x40 uint64 + var x41 uint64 + x41, x40 = bits.Mul64(x30, 0xffffffff00000000) + var x42 uint64 + var x43 uint64 + x43, x42 = bits.Mul64(x30, 0xffffffff) + var x44 uint64 + var x45 uint64 + x44, x45 = bits.Add64(x43, x40, uint64(0x0)) + var x46 uint64 + var x47 uint64 + x46, x47 = bits.Add64(x41, x38, uint64(p384Uint1(x45))) + var x48 uint64 + var x49 uint64 + x48, x49 = bits.Add64(x39, x36, uint64(p384Uint1(x47))) + var x50 uint64 + var x51 uint64 + x50, x51 = bits.Add64(x37, x34, uint64(p384Uint1(x49))) + var x52 uint64 + var x53 uint64 + x52, x53 = bits.Add64(x35, x32, uint64(p384Uint1(x51))) + x54 := (uint64(p384Uint1(x53)) + x33) + var x56 uint64 + _, x56 = bits.Add64(x17, x42, uint64(0x0)) + var x57 uint64 + var x58 uint64 + x57, x58 = bits.Add64(x19, x44, uint64(p384Uint1(x56))) + var x59 uint64 + var x60 uint64 + x59, x60 = bits.Add64(x21, x46, uint64(p384Uint1(x58))) + var x61 uint64 + var x62 uint64 + x61, x62 = bits.Add64(x23, x48, uint64(p384Uint1(x60))) + var x63 uint64 + var x64 uint64 + x63, x64 = bits.Add64(x25, x50, uint64(p384Uint1(x62))) + var x65 uint64 + var x66 uint64 + x65, x66 = bits.Add64(x27, x52, uint64(p384Uint1(x64))) + var x67 uint64 + var x68 uint64 + x67, x68 = bits.Add64(x29, x54, uint64(p384Uint1(x66))) + var x69 uint64 + var x70 uint64 + x70, x69 = bits.Mul64(x1, arg1[5]) + var x71 uint64 + var x72 uint64 + x72, x71 = bits.Mul64(x1, arg1[4]) + var x73 uint64 + var x74 uint64 + x74, x73 = bits.Mul64(x1, arg1[3]) + var x75 uint64 + var x76 uint64 + x76, x75 = bits.Mul64(x1, arg1[2]) + var x77 uint64 + var x78 uint64 + x78, x77 = bits.Mul64(x1, arg1[1]) + var x79 uint64 + var x80 uint64 + x80, x79 = bits.Mul64(x1, arg1[0]) + var x81 uint64 + var x82 uint64 + x81, x82 = bits.Add64(x80, x77, uint64(0x0)) + var x83 uint64 + var x84 uint64 + x83, x84 = bits.Add64(x78, x75, uint64(p384Uint1(x82))) + var x85 uint64 + var x86 uint64 + x85, x86 = bits.Add64(x76, x73, uint64(p384Uint1(x84))) + var x87 uint64 + var x88 uint64 + x87, x88 = bits.Add64(x74, x71, uint64(p384Uint1(x86))) + var x89 uint64 + var x90 uint64 + x89, x90 = bits.Add64(x72, x69, uint64(p384Uint1(x88))) + x91 := (uint64(p384Uint1(x90)) + x70) + var x92 uint64 + var x93 uint64 + x92, x93 = bits.Add64(x57, x79, uint64(0x0)) + var x94 uint64 + var x95 uint64 + x94, x95 = bits.Add64(x59, x81, uint64(p384Uint1(x93))) + var x96 uint64 + var x97 uint64 + x96, x97 = bits.Add64(x61, x83, uint64(p384Uint1(x95))) + var x98 uint64 + var x99 uint64 + x98, x99 = bits.Add64(x63, x85, uint64(p384Uint1(x97))) + var x100 uint64 + var x101 uint64 + x100, x101 = bits.Add64(x65, x87, uint64(p384Uint1(x99))) + var x102 uint64 + var x103 uint64 + x102, x103 = bits.Add64(x67, x89, uint64(p384Uint1(x101))) + var x104 uint64 + var x105 uint64 + x104, x105 = bits.Add64(uint64(p384Uint1(x68)), x91, uint64(p384Uint1(x103))) + var x106 uint64 + _, x106 = bits.Mul64(x92, 0x100000001) + var x108 uint64 + var x109 uint64 + x109, x108 = bits.Mul64(x106, 0xffffffffffffffff) + var x110 uint64 + var x111 uint64 + x111, x110 = bits.Mul64(x106, 0xffffffffffffffff) + var x112 uint64 + var x113 uint64 + x113, x112 = bits.Mul64(x106, 0xffffffffffffffff) + var x114 uint64 + var x115 uint64 + x115, x114 = bits.Mul64(x106, 0xfffffffffffffffe) + var x116 uint64 + var x117 uint64 + x117, x116 = bits.Mul64(x106, 0xffffffff00000000) + var x118 uint64 + var x119 uint64 + x119, x118 = bits.Mul64(x106, 0xffffffff) + var x120 uint64 + var x121 uint64 + x120, x121 = bits.Add64(x119, x116, uint64(0x0)) + var x122 uint64 + var x123 uint64 + x122, x123 = bits.Add64(x117, x114, uint64(p384Uint1(x121))) + var x124 uint64 + var x125 uint64 + x124, x125 = bits.Add64(x115, x112, uint64(p384Uint1(x123))) + var x126 uint64 + var x127 uint64 + x126, x127 = bits.Add64(x113, x110, uint64(p384Uint1(x125))) + var x128 uint64 + var x129 uint64 + x128, x129 = bits.Add64(x111, x108, uint64(p384Uint1(x127))) + x130 := (uint64(p384Uint1(x129)) + x109) + var x132 uint64 + _, x132 = bits.Add64(x92, x118, uint64(0x0)) + var x133 uint64 + var x134 uint64 + x133, x134 = bits.Add64(x94, x120, uint64(p384Uint1(x132))) + var x135 uint64 + var x136 uint64 + x135, x136 = bits.Add64(x96, x122, uint64(p384Uint1(x134))) + var x137 uint64 + var x138 uint64 + x137, x138 = bits.Add64(x98, x124, uint64(p384Uint1(x136))) + var x139 uint64 + var x140 uint64 + x139, x140 = bits.Add64(x100, x126, uint64(p384Uint1(x138))) + var x141 uint64 + var x142 uint64 + x141, x142 = bits.Add64(x102, x128, uint64(p384Uint1(x140))) + var x143 uint64 + var x144 uint64 + x143, x144 = bits.Add64(x104, x130, uint64(p384Uint1(x142))) + x145 := (uint64(p384Uint1(x144)) + uint64(p384Uint1(x105))) + var x146 uint64 + var x147 uint64 + x147, x146 = bits.Mul64(x2, arg1[5]) + var x148 uint64 + var x149 uint64 + x149, x148 = bits.Mul64(x2, arg1[4]) + var x150 uint64 + var x151 uint64 + x151, x150 = bits.Mul64(x2, arg1[3]) + var x152 uint64 + var x153 uint64 + x153, x152 = bits.Mul64(x2, arg1[2]) + var x154 uint64 + var x155 uint64 + x155, x154 = bits.Mul64(x2, arg1[1]) + var x156 uint64 + var x157 uint64 + x157, x156 = bits.Mul64(x2, arg1[0]) + var x158 uint64 + var x159 uint64 + x158, x159 = bits.Add64(x157, x154, uint64(0x0)) + var x160 uint64 + var x161 uint64 + x160, x161 = bits.Add64(x155, x152, uint64(p384Uint1(x159))) + var x162 uint64 + var x163 uint64 + x162, x163 = bits.Add64(x153, x150, uint64(p384Uint1(x161))) + var x164 uint64 + var x165 uint64 + x164, x165 = bits.Add64(x151, x148, uint64(p384Uint1(x163))) + var x166 uint64 + var x167 uint64 + x166, x167 = bits.Add64(x149, x146, uint64(p384Uint1(x165))) + x168 := (uint64(p384Uint1(x167)) + x147) + var x169 uint64 + var x170 uint64 + x169, x170 = bits.Add64(x133, x156, uint64(0x0)) + var x171 uint64 + var x172 uint64 + x171, x172 = bits.Add64(x135, x158, uint64(p384Uint1(x170))) + var x173 uint64 + var x174 uint64 + x173, x174 = bits.Add64(x137, x160, uint64(p384Uint1(x172))) + var x175 uint64 + var x176 uint64 + x175, x176 = bits.Add64(x139, x162, uint64(p384Uint1(x174))) + var x177 uint64 + var x178 uint64 + x177, x178 = bits.Add64(x141, x164, uint64(p384Uint1(x176))) + var x179 uint64 + var x180 uint64 + x179, x180 = bits.Add64(x143, x166, uint64(p384Uint1(x178))) + var x181 uint64 + var x182 uint64 + x181, x182 = bits.Add64(x145, x168, uint64(p384Uint1(x180))) + var x183 uint64 + _, x183 = bits.Mul64(x169, 0x100000001) + var x185 uint64 + var x186 uint64 + x186, x185 = bits.Mul64(x183, 0xffffffffffffffff) + var x187 uint64 + var x188 uint64 + x188, x187 = bits.Mul64(x183, 0xffffffffffffffff) + var x189 uint64 + var x190 uint64 + x190, x189 = bits.Mul64(x183, 0xffffffffffffffff) + var x191 uint64 + var x192 uint64 + x192, x191 = bits.Mul64(x183, 0xfffffffffffffffe) + var x193 uint64 + var x194 uint64 + x194, x193 = bits.Mul64(x183, 0xffffffff00000000) + var x195 uint64 + var x196 uint64 + x196, x195 = bits.Mul64(x183, 0xffffffff) + var x197 uint64 + var x198 uint64 + x197, x198 = bits.Add64(x196, x193, uint64(0x0)) + var x199 uint64 + var x200 uint64 + x199, x200 = bits.Add64(x194, x191, uint64(p384Uint1(x198))) + var x201 uint64 + var x202 uint64 + x201, x202 = bits.Add64(x192, x189, uint64(p384Uint1(x200))) + var x203 uint64 + var x204 uint64 + x203, x204 = bits.Add64(x190, x187, uint64(p384Uint1(x202))) + var x205 uint64 + var x206 uint64 + x205, x206 = bits.Add64(x188, x185, uint64(p384Uint1(x204))) + x207 := (uint64(p384Uint1(x206)) + x186) + var x209 uint64 + _, x209 = bits.Add64(x169, x195, uint64(0x0)) + var x210 uint64 + var x211 uint64 + x210, x211 = bits.Add64(x171, x197, uint64(p384Uint1(x209))) + var x212 uint64 + var x213 uint64 + x212, x213 = bits.Add64(x173, x199, uint64(p384Uint1(x211))) + var x214 uint64 + var x215 uint64 + x214, x215 = bits.Add64(x175, x201, uint64(p384Uint1(x213))) + var x216 uint64 + var x217 uint64 + x216, x217 = bits.Add64(x177, x203, uint64(p384Uint1(x215))) + var x218 uint64 + var x219 uint64 + x218, x219 = bits.Add64(x179, x205, uint64(p384Uint1(x217))) + var x220 uint64 + var x221 uint64 + x220, x221 = bits.Add64(x181, x207, uint64(p384Uint1(x219))) + x222 := (uint64(p384Uint1(x221)) + uint64(p384Uint1(x182))) + var x223 uint64 + var x224 uint64 + x224, x223 = bits.Mul64(x3, arg1[5]) + var x225 uint64 + var x226 uint64 + x226, x225 = bits.Mul64(x3, arg1[4]) + var x227 uint64 + var x228 uint64 + x228, x227 = bits.Mul64(x3, arg1[3]) + var x229 uint64 + var x230 uint64 + x230, x229 = bits.Mul64(x3, arg1[2]) + var x231 uint64 + var x232 uint64 + x232, x231 = bits.Mul64(x3, arg1[1]) + var x233 uint64 + var x234 uint64 + x234, x233 = bits.Mul64(x3, arg1[0]) + var x235 uint64 + var x236 uint64 + x235, x236 = bits.Add64(x234, x231, uint64(0x0)) + var x237 uint64 + var x238 uint64 + x237, x238 = bits.Add64(x232, x229, uint64(p384Uint1(x236))) + var x239 uint64 + var x240 uint64 + x239, x240 = bits.Add64(x230, x227, uint64(p384Uint1(x238))) + var x241 uint64 + var x242 uint64 + x241, x242 = bits.Add64(x228, x225, uint64(p384Uint1(x240))) + var x243 uint64 + var x244 uint64 + x243, x244 = bits.Add64(x226, x223, uint64(p384Uint1(x242))) + x245 := (uint64(p384Uint1(x244)) + x224) + var x246 uint64 + var x247 uint64 + x246, x247 = bits.Add64(x210, x233, uint64(0x0)) + var x248 uint64 + var x249 uint64 + x248, x249 = bits.Add64(x212, x235, uint64(p384Uint1(x247))) + var x250 uint64 + var x251 uint64 + x250, x251 = bits.Add64(x214, x237, uint64(p384Uint1(x249))) + var x252 uint64 + var x253 uint64 + x252, x253 = bits.Add64(x216, x239, uint64(p384Uint1(x251))) + var x254 uint64 + var x255 uint64 + x254, x255 = bits.Add64(x218, x241, uint64(p384Uint1(x253))) + var x256 uint64 + var x257 uint64 + x256, x257 = bits.Add64(x220, x243, uint64(p384Uint1(x255))) + var x258 uint64 + var x259 uint64 + x258, x259 = bits.Add64(x222, x245, uint64(p384Uint1(x257))) + var x260 uint64 + _, x260 = bits.Mul64(x246, 0x100000001) + var x262 uint64 + var x263 uint64 + x263, x262 = bits.Mul64(x260, 0xffffffffffffffff) + var x264 uint64 + var x265 uint64 + x265, x264 = bits.Mul64(x260, 0xffffffffffffffff) + var x266 uint64 + var x267 uint64 + x267, x266 = bits.Mul64(x260, 0xffffffffffffffff) + var x268 uint64 + var x269 uint64 + x269, x268 = bits.Mul64(x260, 0xfffffffffffffffe) + var x270 uint64 + var x271 uint64 + x271, x270 = bits.Mul64(x260, 0xffffffff00000000) + var x272 uint64 + var x273 uint64 + x273, x272 = bits.Mul64(x260, 0xffffffff) + var x274 uint64 + var x275 uint64 + x274, x275 = bits.Add64(x273, x270, uint64(0x0)) + var x276 uint64 + var x277 uint64 + x276, x277 = bits.Add64(x271, x268, uint64(p384Uint1(x275))) + var x278 uint64 + var x279 uint64 + x278, x279 = bits.Add64(x269, x266, uint64(p384Uint1(x277))) + var x280 uint64 + var x281 uint64 + x280, x281 = bits.Add64(x267, x264, uint64(p384Uint1(x279))) + var x282 uint64 + var x283 uint64 + x282, x283 = bits.Add64(x265, x262, uint64(p384Uint1(x281))) + x284 := (uint64(p384Uint1(x283)) + x263) + var x286 uint64 + _, x286 = bits.Add64(x246, x272, uint64(0x0)) + var x287 uint64 + var x288 uint64 + x287, x288 = bits.Add64(x248, x274, uint64(p384Uint1(x286))) + var x289 uint64 + var x290 uint64 + x289, x290 = bits.Add64(x250, x276, uint64(p384Uint1(x288))) + var x291 uint64 + var x292 uint64 + x291, x292 = bits.Add64(x252, x278, uint64(p384Uint1(x290))) + var x293 uint64 + var x294 uint64 + x293, x294 = bits.Add64(x254, x280, uint64(p384Uint1(x292))) + var x295 uint64 + var x296 uint64 + x295, x296 = bits.Add64(x256, x282, uint64(p384Uint1(x294))) + var x297 uint64 + var x298 uint64 + x297, x298 = bits.Add64(x258, x284, uint64(p384Uint1(x296))) + x299 := (uint64(p384Uint1(x298)) + uint64(p384Uint1(x259))) + var x300 uint64 + var x301 uint64 + x301, x300 = bits.Mul64(x4, arg1[5]) + var x302 uint64 + var x303 uint64 + x303, x302 = bits.Mul64(x4, arg1[4]) + var x304 uint64 + var x305 uint64 + x305, x304 = bits.Mul64(x4, arg1[3]) + var x306 uint64 + var x307 uint64 + x307, x306 = bits.Mul64(x4, arg1[2]) + var x308 uint64 + var x309 uint64 + x309, x308 = bits.Mul64(x4, arg1[1]) + var x310 uint64 + var x311 uint64 + x311, x310 = bits.Mul64(x4, arg1[0]) + var x312 uint64 + var x313 uint64 + x312, x313 = bits.Add64(x311, x308, uint64(0x0)) + var x314 uint64 + var x315 uint64 + x314, x315 = bits.Add64(x309, x306, uint64(p384Uint1(x313))) + var x316 uint64 + var x317 uint64 + x316, x317 = bits.Add64(x307, x304, uint64(p384Uint1(x315))) + var x318 uint64 + var x319 uint64 + x318, x319 = bits.Add64(x305, x302, uint64(p384Uint1(x317))) + var x320 uint64 + var x321 uint64 + x320, x321 = bits.Add64(x303, x300, uint64(p384Uint1(x319))) + x322 := (uint64(p384Uint1(x321)) + x301) + var x323 uint64 + var x324 uint64 + x323, x324 = bits.Add64(x287, x310, uint64(0x0)) + var x325 uint64 + var x326 uint64 + x325, x326 = bits.Add64(x289, x312, uint64(p384Uint1(x324))) + var x327 uint64 + var x328 uint64 + x327, x328 = bits.Add64(x291, x314, uint64(p384Uint1(x326))) + var x329 uint64 + var x330 uint64 + x329, x330 = bits.Add64(x293, x316, uint64(p384Uint1(x328))) + var x331 uint64 + var x332 uint64 + x331, x332 = bits.Add64(x295, x318, uint64(p384Uint1(x330))) + var x333 uint64 + var x334 uint64 + x333, x334 = bits.Add64(x297, x320, uint64(p384Uint1(x332))) + var x335 uint64 + var x336 uint64 + x335, x336 = bits.Add64(x299, x322, uint64(p384Uint1(x334))) + var x337 uint64 + _, x337 = bits.Mul64(x323, 0x100000001) + var x339 uint64 + var x340 uint64 + x340, x339 = bits.Mul64(x337, 0xffffffffffffffff) + var x341 uint64 + var x342 uint64 + x342, x341 = bits.Mul64(x337, 0xffffffffffffffff) + var x343 uint64 + var x344 uint64 + x344, x343 = bits.Mul64(x337, 0xffffffffffffffff) + var x345 uint64 + var x346 uint64 + x346, x345 = bits.Mul64(x337, 0xfffffffffffffffe) + var x347 uint64 + var x348 uint64 + x348, x347 = bits.Mul64(x337, 0xffffffff00000000) + var x349 uint64 + var x350 uint64 + x350, x349 = bits.Mul64(x337, 0xffffffff) + var x351 uint64 + var x352 uint64 + x351, x352 = bits.Add64(x350, x347, uint64(0x0)) + var x353 uint64 + var x354 uint64 + x353, x354 = bits.Add64(x348, x345, uint64(p384Uint1(x352))) + var x355 uint64 + var x356 uint64 + x355, x356 = bits.Add64(x346, x343, uint64(p384Uint1(x354))) + var x357 uint64 + var x358 uint64 + x357, x358 = bits.Add64(x344, x341, uint64(p384Uint1(x356))) + var x359 uint64 + var x360 uint64 + x359, x360 = bits.Add64(x342, x339, uint64(p384Uint1(x358))) + x361 := (uint64(p384Uint1(x360)) + x340) + var x363 uint64 + _, x363 = bits.Add64(x323, x349, uint64(0x0)) + var x364 uint64 + var x365 uint64 + x364, x365 = bits.Add64(x325, x351, uint64(p384Uint1(x363))) + var x366 uint64 + var x367 uint64 + x366, x367 = bits.Add64(x327, x353, uint64(p384Uint1(x365))) + var x368 uint64 + var x369 uint64 + x368, x369 = bits.Add64(x329, x355, uint64(p384Uint1(x367))) + var x370 uint64 + var x371 uint64 + x370, x371 = bits.Add64(x331, x357, uint64(p384Uint1(x369))) + var x372 uint64 + var x373 uint64 + x372, x373 = bits.Add64(x333, x359, uint64(p384Uint1(x371))) + var x374 uint64 + var x375 uint64 + x374, x375 = bits.Add64(x335, x361, uint64(p384Uint1(x373))) + x376 := (uint64(p384Uint1(x375)) + uint64(p384Uint1(x336))) + var x377 uint64 + var x378 uint64 + x378, x377 = bits.Mul64(x5, arg1[5]) + var x379 uint64 + var x380 uint64 + x380, x379 = bits.Mul64(x5, arg1[4]) + var x381 uint64 + var x382 uint64 + x382, x381 = bits.Mul64(x5, arg1[3]) + var x383 uint64 + var x384 uint64 + x384, x383 = bits.Mul64(x5, arg1[2]) + var x385 uint64 + var x386 uint64 + x386, x385 = bits.Mul64(x5, arg1[1]) + var x387 uint64 + var x388 uint64 + x388, x387 = bits.Mul64(x5, arg1[0]) + var x389 uint64 + var x390 uint64 + x389, x390 = bits.Add64(x388, x385, uint64(0x0)) + var x391 uint64 + var x392 uint64 + x391, x392 = bits.Add64(x386, x383, uint64(p384Uint1(x390))) + var x393 uint64 + var x394 uint64 + x393, x394 = bits.Add64(x384, x381, uint64(p384Uint1(x392))) + var x395 uint64 + var x396 uint64 + x395, x396 = bits.Add64(x382, x379, uint64(p384Uint1(x394))) + var x397 uint64 + var x398 uint64 + x397, x398 = bits.Add64(x380, x377, uint64(p384Uint1(x396))) + x399 := (uint64(p384Uint1(x398)) + x378) + var x400 uint64 + var x401 uint64 + x400, x401 = bits.Add64(x364, x387, uint64(0x0)) + var x402 uint64 + var x403 uint64 + x402, x403 = bits.Add64(x366, x389, uint64(p384Uint1(x401))) + var x404 uint64 + var x405 uint64 + x404, x405 = bits.Add64(x368, x391, uint64(p384Uint1(x403))) + var x406 uint64 + var x407 uint64 + x406, x407 = bits.Add64(x370, x393, uint64(p384Uint1(x405))) + var x408 uint64 + var x409 uint64 + x408, x409 = bits.Add64(x372, x395, uint64(p384Uint1(x407))) + var x410 uint64 + var x411 uint64 + x410, x411 = bits.Add64(x374, x397, uint64(p384Uint1(x409))) + var x412 uint64 + var x413 uint64 + x412, x413 = bits.Add64(x376, x399, uint64(p384Uint1(x411))) + var x414 uint64 + _, x414 = bits.Mul64(x400, 0x100000001) + var x416 uint64 + var x417 uint64 + x417, x416 = bits.Mul64(x414, 0xffffffffffffffff) + var x418 uint64 + var x419 uint64 + x419, x418 = bits.Mul64(x414, 0xffffffffffffffff) + var x420 uint64 + var x421 uint64 + x421, x420 = bits.Mul64(x414, 0xffffffffffffffff) + var x422 uint64 + var x423 uint64 + x423, x422 = bits.Mul64(x414, 0xfffffffffffffffe) + var x424 uint64 + var x425 uint64 + x425, x424 = bits.Mul64(x414, 0xffffffff00000000) + var x426 uint64 + var x427 uint64 + x427, x426 = bits.Mul64(x414, 0xffffffff) + var x428 uint64 + var x429 uint64 + x428, x429 = bits.Add64(x427, x424, uint64(0x0)) + var x430 uint64 + var x431 uint64 + x430, x431 = bits.Add64(x425, x422, uint64(p384Uint1(x429))) + var x432 uint64 + var x433 uint64 + x432, x433 = bits.Add64(x423, x420, uint64(p384Uint1(x431))) + var x434 uint64 + var x435 uint64 + x434, x435 = bits.Add64(x421, x418, uint64(p384Uint1(x433))) + var x436 uint64 + var x437 uint64 + x436, x437 = bits.Add64(x419, x416, uint64(p384Uint1(x435))) + x438 := (uint64(p384Uint1(x437)) + x417) + var x440 uint64 + _, x440 = bits.Add64(x400, x426, uint64(0x0)) + var x441 uint64 + var x442 uint64 + x441, x442 = bits.Add64(x402, x428, uint64(p384Uint1(x440))) + var x443 uint64 + var x444 uint64 + x443, x444 = bits.Add64(x404, x430, uint64(p384Uint1(x442))) + var x445 uint64 + var x446 uint64 + x445, x446 = bits.Add64(x406, x432, uint64(p384Uint1(x444))) + var x447 uint64 + var x448 uint64 + x447, x448 = bits.Add64(x408, x434, uint64(p384Uint1(x446))) + var x449 uint64 + var x450 uint64 + x449, x450 = bits.Add64(x410, x436, uint64(p384Uint1(x448))) + var x451 uint64 + var x452 uint64 + x451, x452 = bits.Add64(x412, x438, uint64(p384Uint1(x450))) + x453 := (uint64(p384Uint1(x452)) + uint64(p384Uint1(x413))) + var x454 uint64 + var x455 uint64 + x454, x455 = bits.Sub64(x441, 0xffffffff, uint64(0x0)) + var x456 uint64 + var x457 uint64 + x456, x457 = bits.Sub64(x443, 0xffffffff00000000, uint64(p384Uint1(x455))) + var x458 uint64 + var x459 uint64 + x458, x459 = bits.Sub64(x445, 0xfffffffffffffffe, uint64(p384Uint1(x457))) + var x460 uint64 + var x461 uint64 + x460, x461 = bits.Sub64(x447, 0xffffffffffffffff, uint64(p384Uint1(x459))) + var x462 uint64 + var x463 uint64 + x462, x463 = bits.Sub64(x449, 0xffffffffffffffff, uint64(p384Uint1(x461))) + var x464 uint64 + var x465 uint64 + x464, x465 = bits.Sub64(x451, 0xffffffffffffffff, uint64(p384Uint1(x463))) + var x467 uint64 + _, x467 = bits.Sub64(x453, uint64(0x0), uint64(p384Uint1(x465))) + var x468 uint64 + p384CmovznzU64(&x468, p384Uint1(x467), x454, x441) + var x469 uint64 + p384CmovznzU64(&x469, p384Uint1(x467), x456, x443) + var x470 uint64 + p384CmovznzU64(&x470, p384Uint1(x467), x458, x445) + var x471 uint64 + p384CmovznzU64(&x471, p384Uint1(x467), x460, x447) + var x472 uint64 + p384CmovznzU64(&x472, p384Uint1(x467), x462, x449) + var x473 uint64 + p384CmovznzU64(&x473, p384Uint1(x467), x464, x451) + out1[0] = x468 + out1[1] = x469 + out1[2] = x470 + out1[3] = x471 + out1[4] = x472 + out1[5] = x473 +} + +// p384Add adds two field elements in the Montgomery domain. +// +// Preconditions: +// 0 ≤ eval arg1 < m +// 0 ≤ eval arg2 < m +// Postconditions: +// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) + eval (from_montgomery arg2)) mod m +// 0 ≤ eval out1 < m +// +func p384Add(out1 *p384MontgomeryDomainFieldElement, arg1 *p384MontgomeryDomainFieldElement, arg2 *p384MontgomeryDomainFieldElement) { + var x1 uint64 + var x2 uint64 + x1, x2 = bits.Add64(arg1[0], arg2[0], uint64(0x0)) + var x3 uint64 + var x4 uint64 + x3, x4 = bits.Add64(arg1[1], arg2[1], uint64(p384Uint1(x2))) + var x5 uint64 + var x6 uint64 + x5, x6 = bits.Add64(arg1[2], arg2[2], uint64(p384Uint1(x4))) + var x7 uint64 + var x8 uint64 + x7, x8 = bits.Add64(arg1[3], arg2[3], uint64(p384Uint1(x6))) + var x9 uint64 + var x10 uint64 + x9, x10 = bits.Add64(arg1[4], arg2[4], uint64(p384Uint1(x8))) + var x11 uint64 + var x12 uint64 + x11, x12 = bits.Add64(arg1[5], arg2[5], uint64(p384Uint1(x10))) + var x13 uint64 + var x14 uint64 + x13, x14 = bits.Sub64(x1, 0xffffffff, uint64(0x0)) + var x15 uint64 + var x16 uint64 + x15, x16 = bits.Sub64(x3, 0xffffffff00000000, uint64(p384Uint1(x14))) + var x17 uint64 + var x18 uint64 + x17, x18 = bits.Sub64(x5, 0xfffffffffffffffe, uint64(p384Uint1(x16))) + var x19 uint64 + var x20 uint64 + x19, x20 = bits.Sub64(x7, 0xffffffffffffffff, uint64(p384Uint1(x18))) + var x21 uint64 + var x22 uint64 + x21, x22 = bits.Sub64(x9, 0xffffffffffffffff, uint64(p384Uint1(x20))) + var x23 uint64 + var x24 uint64 + x23, x24 = bits.Sub64(x11, 0xffffffffffffffff, uint64(p384Uint1(x22))) + var x26 uint64 + _, x26 = bits.Sub64(uint64(p384Uint1(x12)), uint64(0x0), uint64(p384Uint1(x24))) + var x27 uint64 + p384CmovznzU64(&x27, p384Uint1(x26), x13, x1) + var x28 uint64 + p384CmovznzU64(&x28, p384Uint1(x26), x15, x3) + var x29 uint64 + p384CmovznzU64(&x29, p384Uint1(x26), x17, x5) + var x30 uint64 + p384CmovznzU64(&x30, p384Uint1(x26), x19, x7) + var x31 uint64 + p384CmovznzU64(&x31, p384Uint1(x26), x21, x9) + var x32 uint64 + p384CmovznzU64(&x32, p384Uint1(x26), x23, x11) + out1[0] = x27 + out1[1] = x28 + out1[2] = x29 + out1[3] = x30 + out1[4] = x31 + out1[5] = x32 +} + +// p384Sub subtracts two field elements in the Montgomery domain. +// +// Preconditions: +// 0 ≤ eval arg1 < m +// 0 ≤ eval arg2 < m +// Postconditions: +// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) - eval (from_montgomery arg2)) mod m +// 0 ≤ eval out1 < m +// +func p384Sub(out1 *p384MontgomeryDomainFieldElement, arg1 *p384MontgomeryDomainFieldElement, arg2 *p384MontgomeryDomainFieldElement) { + var x1 uint64 + var x2 uint64 + x1, x2 = bits.Sub64(arg1[0], arg2[0], uint64(0x0)) + var x3 uint64 + var x4 uint64 + x3, x4 = bits.Sub64(arg1[1], arg2[1], uint64(p384Uint1(x2))) + var x5 uint64 + var x6 uint64 + x5, x6 = bits.Sub64(arg1[2], arg2[2], uint64(p384Uint1(x4))) + var x7 uint64 + var x8 uint64 + x7, x8 = bits.Sub64(arg1[3], arg2[3], uint64(p384Uint1(x6))) + var x9 uint64 + var x10 uint64 + x9, x10 = bits.Sub64(arg1[4], arg2[4], uint64(p384Uint1(x8))) + var x11 uint64 + var x12 uint64 + x11, x12 = bits.Sub64(arg1[5], arg2[5], uint64(p384Uint1(x10))) + var x13 uint64 + p384CmovznzU64(&x13, p384Uint1(x12), uint64(0x0), 0xffffffffffffffff) + var x14 uint64 + var x15 uint64 + x14, x15 = bits.Add64(x1, (x13 & 0xffffffff), uint64(0x0)) + var x16 uint64 + var x17 uint64 + x16, x17 = bits.Add64(x3, (x13 & 0xffffffff00000000), uint64(p384Uint1(x15))) + var x18 uint64 + var x19 uint64 + x18, x19 = bits.Add64(x5, (x13 & 0xfffffffffffffffe), uint64(p384Uint1(x17))) + var x20 uint64 + var x21 uint64 + x20, x21 = bits.Add64(x7, x13, uint64(p384Uint1(x19))) + var x22 uint64 + var x23 uint64 + x22, x23 = bits.Add64(x9, x13, uint64(p384Uint1(x21))) + var x24 uint64 + x24, _ = bits.Add64(x11, x13, uint64(p384Uint1(x23))) + out1[0] = x14 + out1[1] = x16 + out1[2] = x18 + out1[3] = x20 + out1[4] = x22 + out1[5] = x24 +} + +// p384SetOne returns the field element one in the Montgomery domain. +// +// Postconditions: +// eval (from_montgomery out1) mod m = 1 mod m +// 0 ≤ eval out1 < m +// +func p384SetOne(out1 *p384MontgomeryDomainFieldElement) { + out1[0] = 0xffffffff00000001 + out1[1] = 0xffffffff + out1[2] = uint64(0x1) + out1[3] = uint64(0x0) + out1[4] = uint64(0x0) + out1[5] = uint64(0x0) +} + +// p384FromMontgomery translates a field element out of the Montgomery domain. +// +// Preconditions: +// 0 ≤ eval arg1 < m +// Postconditions: +// eval out1 mod m = (eval arg1 * ((2^64)⁻¹ mod m)^6) mod m +// 0 ≤ eval out1 < m +// +func p384FromMontgomery(out1 *p384NonMontgomeryDomainFieldElement, arg1 *p384MontgomeryDomainFieldElement) { + x1 := arg1[0] + var x2 uint64 + _, x2 = bits.Mul64(x1, 0x100000001) + var x4 uint64 + var x5 uint64 + x5, x4 = bits.Mul64(x2, 0xffffffffffffffff) + var x6 uint64 + var x7 uint64 + x7, x6 = bits.Mul64(x2, 0xffffffffffffffff) + var x8 uint64 + var x9 uint64 + x9, x8 = bits.Mul64(x2, 0xffffffffffffffff) + var x10 uint64 + var x11 uint64 + x11, x10 = bits.Mul64(x2, 0xfffffffffffffffe) + var x12 uint64 + var x13 uint64 + x13, x12 = bits.Mul64(x2, 0xffffffff00000000) + var x14 uint64 + var x15 uint64 + x15, x14 = bits.Mul64(x2, 0xffffffff) + var x16 uint64 + var x17 uint64 + x16, x17 = bits.Add64(x15, x12, uint64(0x0)) + var x18 uint64 + var x19 uint64 + x18, x19 = bits.Add64(x13, x10, uint64(p384Uint1(x17))) + var x20 uint64 + var x21 uint64 + x20, x21 = bits.Add64(x11, x8, uint64(p384Uint1(x19))) + var x22 uint64 + var x23 uint64 + x22, x23 = bits.Add64(x9, x6, uint64(p384Uint1(x21))) + var x24 uint64 + var x25 uint64 + x24, x25 = bits.Add64(x7, x4, uint64(p384Uint1(x23))) + var x27 uint64 + _, x27 = bits.Add64(x1, x14, uint64(0x0)) + var x28 uint64 + var x29 uint64 + x28, x29 = bits.Add64(uint64(0x0), x16, uint64(p384Uint1(x27))) + var x30 uint64 + var x31 uint64 + x30, x31 = bits.Add64(uint64(0x0), x18, uint64(p384Uint1(x29))) + var x32 uint64 + var x33 uint64 + x32, x33 = bits.Add64(uint64(0x0), x20, uint64(p384Uint1(x31))) + var x34 uint64 + var x35 uint64 + x34, x35 = bits.Add64(uint64(0x0), x22, uint64(p384Uint1(x33))) + var x36 uint64 + var x37 uint64 + x36, x37 = bits.Add64(uint64(0x0), x24, uint64(p384Uint1(x35))) + var x38 uint64 + var x39 uint64 + x38, x39 = bits.Add64(uint64(0x0), (uint64(p384Uint1(x25)) + x5), uint64(p384Uint1(x37))) + var x40 uint64 + var x41 uint64 + x40, x41 = bits.Add64(x28, arg1[1], uint64(0x0)) + var x42 uint64 + var x43 uint64 + x42, x43 = bits.Add64(x30, uint64(0x0), uint64(p384Uint1(x41))) + var x44 uint64 + var x45 uint64 + x44, x45 = bits.Add64(x32, uint64(0x0), uint64(p384Uint1(x43))) + var x46 uint64 + var x47 uint64 + x46, x47 = bits.Add64(x34, uint64(0x0), uint64(p384Uint1(x45))) + var x48 uint64 + var x49 uint64 + x48, x49 = bits.Add64(x36, uint64(0x0), uint64(p384Uint1(x47))) + var x50 uint64 + var x51 uint64 + x50, x51 = bits.Add64(x38, uint64(0x0), uint64(p384Uint1(x49))) + var x52 uint64 + _, x52 = bits.Mul64(x40, 0x100000001) + var x54 uint64 + var x55 uint64 + x55, x54 = bits.Mul64(x52, 0xffffffffffffffff) + var x56 uint64 + var x57 uint64 + x57, x56 = bits.Mul64(x52, 0xffffffffffffffff) + var x58 uint64 + var x59 uint64 + x59, x58 = bits.Mul64(x52, 0xffffffffffffffff) + var x60 uint64 + var x61 uint64 + x61, x60 = bits.Mul64(x52, 0xfffffffffffffffe) + var x62 uint64 + var x63 uint64 + x63, x62 = bits.Mul64(x52, 0xffffffff00000000) + var x64 uint64 + var x65 uint64 + x65, x64 = bits.Mul64(x52, 0xffffffff) + var x66 uint64 + var x67 uint64 + x66, x67 = bits.Add64(x65, x62, uint64(0x0)) + var x68 uint64 + var x69 uint64 + x68, x69 = bits.Add64(x63, x60, uint64(p384Uint1(x67))) + var x70 uint64 + var x71 uint64 + x70, x71 = bits.Add64(x61, x58, uint64(p384Uint1(x69))) + var x72 uint64 + var x73 uint64 + x72, x73 = bits.Add64(x59, x56, uint64(p384Uint1(x71))) + var x74 uint64 + var x75 uint64 + x74, x75 = bits.Add64(x57, x54, uint64(p384Uint1(x73))) + var x77 uint64 + _, x77 = bits.Add64(x40, x64, uint64(0x0)) + var x78 uint64 + var x79 uint64 + x78, x79 = bits.Add64(x42, x66, uint64(p384Uint1(x77))) + var x80 uint64 + var x81 uint64 + x80, x81 = bits.Add64(x44, x68, uint64(p384Uint1(x79))) + var x82 uint64 + var x83 uint64 + x82, x83 = bits.Add64(x46, x70, uint64(p384Uint1(x81))) + var x84 uint64 + var x85 uint64 + x84, x85 = bits.Add64(x48, x72, uint64(p384Uint1(x83))) + var x86 uint64 + var x87 uint64 + x86, x87 = bits.Add64(x50, x74, uint64(p384Uint1(x85))) + var x88 uint64 + var x89 uint64 + x88, x89 = bits.Add64((uint64(p384Uint1(x51)) + uint64(p384Uint1(x39))), (uint64(p384Uint1(x75)) + x55), uint64(p384Uint1(x87))) + var x90 uint64 + var x91 uint64 + x90, x91 = bits.Add64(x78, arg1[2], uint64(0x0)) + var x92 uint64 + var x93 uint64 + x92, x93 = bits.Add64(x80, uint64(0x0), uint64(p384Uint1(x91))) + var x94 uint64 + var x95 uint64 + x94, x95 = bits.Add64(x82, uint64(0x0), uint64(p384Uint1(x93))) + var x96 uint64 + var x97 uint64 + x96, x97 = bits.Add64(x84, uint64(0x0), uint64(p384Uint1(x95))) + var x98 uint64 + var x99 uint64 + x98, x99 = bits.Add64(x86, uint64(0x0), uint64(p384Uint1(x97))) + var x100 uint64 + var x101 uint64 + x100, x101 = bits.Add64(x88, uint64(0x0), uint64(p384Uint1(x99))) + var x102 uint64 + _, x102 = bits.Mul64(x90, 0x100000001) + var x104 uint64 + var x105 uint64 + x105, x104 = bits.Mul64(x102, 0xffffffffffffffff) + var x106 uint64 + var x107 uint64 + x107, x106 = bits.Mul64(x102, 0xffffffffffffffff) + var x108 uint64 + var x109 uint64 + x109, x108 = bits.Mul64(x102, 0xffffffffffffffff) + var x110 uint64 + var x111 uint64 + x111, x110 = bits.Mul64(x102, 0xfffffffffffffffe) + var x112 uint64 + var x113 uint64 + x113, x112 = bits.Mul64(x102, 0xffffffff00000000) + var x114 uint64 + var x115 uint64 + x115, x114 = bits.Mul64(x102, 0xffffffff) + var x116 uint64 + var x117 uint64 + x116, x117 = bits.Add64(x115, x112, uint64(0x0)) + var x118 uint64 + var x119 uint64 + x118, x119 = bits.Add64(x113, x110, uint64(p384Uint1(x117))) + var x120 uint64 + var x121 uint64 + x120, x121 = bits.Add64(x111, x108, uint64(p384Uint1(x119))) + var x122 uint64 + var x123 uint64 + x122, x123 = bits.Add64(x109, x106, uint64(p384Uint1(x121))) + var x124 uint64 + var x125 uint64 + x124, x125 = bits.Add64(x107, x104, uint64(p384Uint1(x123))) + var x127 uint64 + _, x127 = bits.Add64(x90, x114, uint64(0x0)) + var x128 uint64 + var x129 uint64 + x128, x129 = bits.Add64(x92, x116, uint64(p384Uint1(x127))) + var x130 uint64 + var x131 uint64 + x130, x131 = bits.Add64(x94, x118, uint64(p384Uint1(x129))) + var x132 uint64 + var x133 uint64 + x132, x133 = bits.Add64(x96, x120, uint64(p384Uint1(x131))) + var x134 uint64 + var x135 uint64 + x134, x135 = bits.Add64(x98, x122, uint64(p384Uint1(x133))) + var x136 uint64 + var x137 uint64 + x136, x137 = bits.Add64(x100, x124, uint64(p384Uint1(x135))) + var x138 uint64 + var x139 uint64 + x138, x139 = bits.Add64((uint64(p384Uint1(x101)) + uint64(p384Uint1(x89))), (uint64(p384Uint1(x125)) + x105), uint64(p384Uint1(x137))) + var x140 uint64 + var x141 uint64 + x140, x141 = bits.Add64(x128, arg1[3], uint64(0x0)) + var x142 uint64 + var x143 uint64 + x142, x143 = bits.Add64(x130, uint64(0x0), uint64(p384Uint1(x141))) + var x144 uint64 + var x145 uint64 + x144, x145 = bits.Add64(x132, uint64(0x0), uint64(p384Uint1(x143))) + var x146 uint64 + var x147 uint64 + x146, x147 = bits.Add64(x134, uint64(0x0), uint64(p384Uint1(x145))) + var x148 uint64 + var x149 uint64 + x148, x149 = bits.Add64(x136, uint64(0x0), uint64(p384Uint1(x147))) + var x150 uint64 + var x151 uint64 + x150, x151 = bits.Add64(x138, uint64(0x0), uint64(p384Uint1(x149))) + var x152 uint64 + _, x152 = bits.Mul64(x140, 0x100000001) + var x154 uint64 + var x155 uint64 + x155, x154 = bits.Mul64(x152, 0xffffffffffffffff) + var x156 uint64 + var x157 uint64 + x157, x156 = bits.Mul64(x152, 0xffffffffffffffff) + var x158 uint64 + var x159 uint64 + x159, x158 = bits.Mul64(x152, 0xffffffffffffffff) + var x160 uint64 + var x161 uint64 + x161, x160 = bits.Mul64(x152, 0xfffffffffffffffe) + var x162 uint64 + var x163 uint64 + x163, x162 = bits.Mul64(x152, 0xffffffff00000000) + var x164 uint64 + var x165 uint64 + x165, x164 = bits.Mul64(x152, 0xffffffff) + var x166 uint64 + var x167 uint64 + x166, x167 = bits.Add64(x165, x162, uint64(0x0)) + var x168 uint64 + var x169 uint64 + x168, x169 = bits.Add64(x163, x160, uint64(p384Uint1(x167))) + var x170 uint64 + var x171 uint64 + x170, x171 = bits.Add64(x161, x158, uint64(p384Uint1(x169))) + var x172 uint64 + var x173 uint64 + x172, x173 = bits.Add64(x159, x156, uint64(p384Uint1(x171))) + var x174 uint64 + var x175 uint64 + x174, x175 = bits.Add64(x157, x154, uint64(p384Uint1(x173))) + var x177 uint64 + _, x177 = bits.Add64(x140, x164, uint64(0x0)) + var x178 uint64 + var x179 uint64 + x178, x179 = bits.Add64(x142, x166, uint64(p384Uint1(x177))) + var x180 uint64 + var x181 uint64 + x180, x181 = bits.Add64(x144, x168, uint64(p384Uint1(x179))) + var x182 uint64 + var x183 uint64 + x182, x183 = bits.Add64(x146, x170, uint64(p384Uint1(x181))) + var x184 uint64 + var x185 uint64 + x184, x185 = bits.Add64(x148, x172, uint64(p384Uint1(x183))) + var x186 uint64 + var x187 uint64 + x186, x187 = bits.Add64(x150, x174, uint64(p384Uint1(x185))) + var x188 uint64 + var x189 uint64 + x188, x189 = bits.Add64((uint64(p384Uint1(x151)) + uint64(p384Uint1(x139))), (uint64(p384Uint1(x175)) + x155), uint64(p384Uint1(x187))) + var x190 uint64 + var x191 uint64 + x190, x191 = bits.Add64(x178, arg1[4], uint64(0x0)) + var x192 uint64 + var x193 uint64 + x192, x193 = bits.Add64(x180, uint64(0x0), uint64(p384Uint1(x191))) + var x194 uint64 + var x195 uint64 + x194, x195 = bits.Add64(x182, uint64(0x0), uint64(p384Uint1(x193))) + var x196 uint64 + var x197 uint64 + x196, x197 = bits.Add64(x184, uint64(0x0), uint64(p384Uint1(x195))) + var x198 uint64 + var x199 uint64 + x198, x199 = bits.Add64(x186, uint64(0x0), uint64(p384Uint1(x197))) + var x200 uint64 + var x201 uint64 + x200, x201 = bits.Add64(x188, uint64(0x0), uint64(p384Uint1(x199))) + var x202 uint64 + _, x202 = bits.Mul64(x190, 0x100000001) + var x204 uint64 + var x205 uint64 + x205, x204 = bits.Mul64(x202, 0xffffffffffffffff) + var x206 uint64 + var x207 uint64 + x207, x206 = bits.Mul64(x202, 0xffffffffffffffff) + var x208 uint64 + var x209 uint64 + x209, x208 = bits.Mul64(x202, 0xffffffffffffffff) + var x210 uint64 + var x211 uint64 + x211, x210 = bits.Mul64(x202, 0xfffffffffffffffe) + var x212 uint64 + var x213 uint64 + x213, x212 = bits.Mul64(x202, 0xffffffff00000000) + var x214 uint64 + var x215 uint64 + x215, x214 = bits.Mul64(x202, 0xffffffff) + var x216 uint64 + var x217 uint64 + x216, x217 = bits.Add64(x215, x212, uint64(0x0)) + var x218 uint64 + var x219 uint64 + x218, x219 = bits.Add64(x213, x210, uint64(p384Uint1(x217))) + var x220 uint64 + var x221 uint64 + x220, x221 = bits.Add64(x211, x208, uint64(p384Uint1(x219))) + var x222 uint64 + var x223 uint64 + x222, x223 = bits.Add64(x209, x206, uint64(p384Uint1(x221))) + var x224 uint64 + var x225 uint64 + x224, x225 = bits.Add64(x207, x204, uint64(p384Uint1(x223))) + var x227 uint64 + _, x227 = bits.Add64(x190, x214, uint64(0x0)) + var x228 uint64 + var x229 uint64 + x228, x229 = bits.Add64(x192, x216, uint64(p384Uint1(x227))) + var x230 uint64 + var x231 uint64 + x230, x231 = bits.Add64(x194, x218, uint64(p384Uint1(x229))) + var x232 uint64 + var x233 uint64 + x232, x233 = bits.Add64(x196, x220, uint64(p384Uint1(x231))) + var x234 uint64 + var x235 uint64 + x234, x235 = bits.Add64(x198, x222, uint64(p384Uint1(x233))) + var x236 uint64 + var x237 uint64 + x236, x237 = bits.Add64(x200, x224, uint64(p384Uint1(x235))) + var x238 uint64 + var x239 uint64 + x238, x239 = bits.Add64((uint64(p384Uint1(x201)) + uint64(p384Uint1(x189))), (uint64(p384Uint1(x225)) + x205), uint64(p384Uint1(x237))) + var x240 uint64 + var x241 uint64 + x240, x241 = bits.Add64(x228, arg1[5], uint64(0x0)) + var x242 uint64 + var x243 uint64 + x242, x243 = bits.Add64(x230, uint64(0x0), uint64(p384Uint1(x241))) + var x244 uint64 + var x245 uint64 + x244, x245 = bits.Add64(x232, uint64(0x0), uint64(p384Uint1(x243))) + var x246 uint64 + var x247 uint64 + x246, x247 = bits.Add64(x234, uint64(0x0), uint64(p384Uint1(x245))) + var x248 uint64 + var x249 uint64 + x248, x249 = bits.Add64(x236, uint64(0x0), uint64(p384Uint1(x247))) + var x250 uint64 + var x251 uint64 + x250, x251 = bits.Add64(x238, uint64(0x0), uint64(p384Uint1(x249))) + var x252 uint64 + _, x252 = bits.Mul64(x240, 0x100000001) + var x254 uint64 + var x255 uint64 + x255, x254 = bits.Mul64(x252, 0xffffffffffffffff) + var x256 uint64 + var x257 uint64 + x257, x256 = bits.Mul64(x252, 0xffffffffffffffff) + var x258 uint64 + var x259 uint64 + x259, x258 = bits.Mul64(x252, 0xffffffffffffffff) + var x260 uint64 + var x261 uint64 + x261, x260 = bits.Mul64(x252, 0xfffffffffffffffe) + var x262 uint64 + var x263 uint64 + x263, x262 = bits.Mul64(x252, 0xffffffff00000000) + var x264 uint64 + var x265 uint64 + x265, x264 = bits.Mul64(x252, 0xffffffff) + var x266 uint64 + var x267 uint64 + x266, x267 = bits.Add64(x265, x262, uint64(0x0)) + var x268 uint64 + var x269 uint64 + x268, x269 = bits.Add64(x263, x260, uint64(p384Uint1(x267))) + var x270 uint64 + var x271 uint64 + x270, x271 = bits.Add64(x261, x258, uint64(p384Uint1(x269))) + var x272 uint64 + var x273 uint64 + x272, x273 = bits.Add64(x259, x256, uint64(p384Uint1(x271))) + var x274 uint64 + var x275 uint64 + x274, x275 = bits.Add64(x257, x254, uint64(p384Uint1(x273))) + var x277 uint64 + _, x277 = bits.Add64(x240, x264, uint64(0x0)) + var x278 uint64 + var x279 uint64 + x278, x279 = bits.Add64(x242, x266, uint64(p384Uint1(x277))) + var x280 uint64 + var x281 uint64 + x280, x281 = bits.Add64(x244, x268, uint64(p384Uint1(x279))) + var x282 uint64 + var x283 uint64 + x282, x283 = bits.Add64(x246, x270, uint64(p384Uint1(x281))) + var x284 uint64 + var x285 uint64 + x284, x285 = bits.Add64(x248, x272, uint64(p384Uint1(x283))) + var x286 uint64 + var x287 uint64 + x286, x287 = bits.Add64(x250, x274, uint64(p384Uint1(x285))) + var x288 uint64 + var x289 uint64 + x288, x289 = bits.Add64((uint64(p384Uint1(x251)) + uint64(p384Uint1(x239))), (uint64(p384Uint1(x275)) + x255), uint64(p384Uint1(x287))) + var x290 uint64 + var x291 uint64 + x290, x291 = bits.Sub64(x278, 0xffffffff, uint64(0x0)) + var x292 uint64 + var x293 uint64 + x292, x293 = bits.Sub64(x280, 0xffffffff00000000, uint64(p384Uint1(x291))) + var x294 uint64 + var x295 uint64 + x294, x295 = bits.Sub64(x282, 0xfffffffffffffffe, uint64(p384Uint1(x293))) + var x296 uint64 + var x297 uint64 + x296, x297 = bits.Sub64(x284, 0xffffffffffffffff, uint64(p384Uint1(x295))) + var x298 uint64 + var x299 uint64 + x298, x299 = bits.Sub64(x286, 0xffffffffffffffff, uint64(p384Uint1(x297))) + var x300 uint64 + var x301 uint64 + x300, x301 = bits.Sub64(x288, 0xffffffffffffffff, uint64(p384Uint1(x299))) + var x303 uint64 + _, x303 = bits.Sub64(uint64(p384Uint1(x289)), uint64(0x0), uint64(p384Uint1(x301))) + var x304 uint64 + p384CmovznzU64(&x304, p384Uint1(x303), x290, x278) + var x305 uint64 + p384CmovznzU64(&x305, p384Uint1(x303), x292, x280) + var x306 uint64 + p384CmovznzU64(&x306, p384Uint1(x303), x294, x282) + var x307 uint64 + p384CmovznzU64(&x307, p384Uint1(x303), x296, x284) + var x308 uint64 + p384CmovznzU64(&x308, p384Uint1(x303), x298, x286) + var x309 uint64 + p384CmovznzU64(&x309, p384Uint1(x303), x300, x288) + out1[0] = x304 + out1[1] = x305 + out1[2] = x306 + out1[3] = x307 + out1[4] = x308 + out1[5] = x309 +} + +// p384ToMontgomery translates a field element into the Montgomery domain. +// +// Preconditions: +// 0 ≤ eval arg1 < m +// Postconditions: +// eval (from_montgomery out1) mod m = eval arg1 mod m +// 0 ≤ eval out1 < m +// +func p384ToMontgomery(out1 *p384MontgomeryDomainFieldElement, arg1 *p384NonMontgomeryDomainFieldElement) { + x1 := arg1[1] + x2 := arg1[2] + x3 := arg1[3] + x4 := arg1[4] + x5 := arg1[5] + x6 := arg1[0] + var x7 uint64 + var x8 uint64 + x8, x7 = bits.Mul64(x6, 0x200000000) + var x9 uint64 + var x10 uint64 + x10, x9 = bits.Mul64(x6, 0xfffffffe00000000) + var x11 uint64 + var x12 uint64 + x12, x11 = bits.Mul64(x6, 0x200000000) + var x13 uint64 + var x14 uint64 + x14, x13 = bits.Mul64(x6, 0xfffffffe00000001) + var x15 uint64 + var x16 uint64 + x15, x16 = bits.Add64(x14, x11, uint64(0x0)) + var x17 uint64 + var x18 uint64 + x17, x18 = bits.Add64(x12, x9, uint64(p384Uint1(x16))) + var x19 uint64 + var x20 uint64 + x19, x20 = bits.Add64(x10, x7, uint64(p384Uint1(x18))) + var x21 uint64 + var x22 uint64 + x21, x22 = bits.Add64(x8, x6, uint64(p384Uint1(x20))) + var x23 uint64 + _, x23 = bits.Mul64(x13, 0x100000001) + var x25 uint64 + var x26 uint64 + x26, x25 = bits.Mul64(x23, 0xffffffffffffffff) + var x27 uint64 + var x28 uint64 + x28, x27 = bits.Mul64(x23, 0xffffffffffffffff) + var x29 uint64 + var x30 uint64 + x30, x29 = bits.Mul64(x23, 0xffffffffffffffff) + var x31 uint64 + var x32 uint64 + x32, x31 = bits.Mul64(x23, 0xfffffffffffffffe) + var x33 uint64 + var x34 uint64 + x34, x33 = bits.Mul64(x23, 0xffffffff00000000) + var x35 uint64 + var x36 uint64 + x36, x35 = bits.Mul64(x23, 0xffffffff) + var x37 uint64 + var x38 uint64 + x37, x38 = bits.Add64(x36, x33, uint64(0x0)) + var x39 uint64 + var x40 uint64 + x39, x40 = bits.Add64(x34, x31, uint64(p384Uint1(x38))) + var x41 uint64 + var x42 uint64 + x41, x42 = bits.Add64(x32, x29, uint64(p384Uint1(x40))) + var x43 uint64 + var x44 uint64 + x43, x44 = bits.Add64(x30, x27, uint64(p384Uint1(x42))) + var x45 uint64 + var x46 uint64 + x45, x46 = bits.Add64(x28, x25, uint64(p384Uint1(x44))) + var x48 uint64 + _, x48 = bits.Add64(x13, x35, uint64(0x0)) + var x49 uint64 + var x50 uint64 + x49, x50 = bits.Add64(x15, x37, uint64(p384Uint1(x48))) + var x51 uint64 + var x52 uint64 + x51, x52 = bits.Add64(x17, x39, uint64(p384Uint1(x50))) + var x53 uint64 + var x54 uint64 + x53, x54 = bits.Add64(x19, x41, uint64(p384Uint1(x52))) + var x55 uint64 + var x56 uint64 + x55, x56 = bits.Add64(x21, x43, uint64(p384Uint1(x54))) + var x57 uint64 + var x58 uint64 + x57, x58 = bits.Add64(uint64(p384Uint1(x22)), x45, uint64(p384Uint1(x56))) + var x59 uint64 + var x60 uint64 + x59, x60 = bits.Add64(uint64(0x0), (uint64(p384Uint1(x46)) + x26), uint64(p384Uint1(x58))) + var x61 uint64 + var x62 uint64 + x62, x61 = bits.Mul64(x1, 0x200000000) + var x63 uint64 + var x64 uint64 + x64, x63 = bits.Mul64(x1, 0xfffffffe00000000) + var x65 uint64 + var x66 uint64 + x66, x65 = bits.Mul64(x1, 0x200000000) + var x67 uint64 + var x68 uint64 + x68, x67 = bits.Mul64(x1, 0xfffffffe00000001) + var x69 uint64 + var x70 uint64 + x69, x70 = bits.Add64(x68, x65, uint64(0x0)) + var x71 uint64 + var x72 uint64 + x71, x72 = bits.Add64(x66, x63, uint64(p384Uint1(x70))) + var x73 uint64 + var x74 uint64 + x73, x74 = bits.Add64(x64, x61, uint64(p384Uint1(x72))) + var x75 uint64 + var x76 uint64 + x75, x76 = bits.Add64(x62, x1, uint64(p384Uint1(x74))) + var x77 uint64 + var x78 uint64 + x77, x78 = bits.Add64(x49, x67, uint64(0x0)) + var x79 uint64 + var x80 uint64 + x79, x80 = bits.Add64(x51, x69, uint64(p384Uint1(x78))) + var x81 uint64 + var x82 uint64 + x81, x82 = bits.Add64(x53, x71, uint64(p384Uint1(x80))) + var x83 uint64 + var x84 uint64 + x83, x84 = bits.Add64(x55, x73, uint64(p384Uint1(x82))) + var x85 uint64 + var x86 uint64 + x85, x86 = bits.Add64(x57, x75, uint64(p384Uint1(x84))) + var x87 uint64 + var x88 uint64 + x87, x88 = bits.Add64(x59, uint64(p384Uint1(x76)), uint64(p384Uint1(x86))) + var x89 uint64 + _, x89 = bits.Mul64(x77, 0x100000001) + var x91 uint64 + var x92 uint64 + x92, x91 = bits.Mul64(x89, 0xffffffffffffffff) + var x93 uint64 + var x94 uint64 + x94, x93 = bits.Mul64(x89, 0xffffffffffffffff) + var x95 uint64 + var x96 uint64 + x96, x95 = bits.Mul64(x89, 0xffffffffffffffff) + var x97 uint64 + var x98 uint64 + x98, x97 = bits.Mul64(x89, 0xfffffffffffffffe) + var x99 uint64 + var x100 uint64 + x100, x99 = bits.Mul64(x89, 0xffffffff00000000) + var x101 uint64 + var x102 uint64 + x102, x101 = bits.Mul64(x89, 0xffffffff) + var x103 uint64 + var x104 uint64 + x103, x104 = bits.Add64(x102, x99, uint64(0x0)) + var x105 uint64 + var x106 uint64 + x105, x106 = bits.Add64(x100, x97, uint64(p384Uint1(x104))) + var x107 uint64 + var x108 uint64 + x107, x108 = bits.Add64(x98, x95, uint64(p384Uint1(x106))) + var x109 uint64 + var x110 uint64 + x109, x110 = bits.Add64(x96, x93, uint64(p384Uint1(x108))) + var x111 uint64 + var x112 uint64 + x111, x112 = bits.Add64(x94, x91, uint64(p384Uint1(x110))) + var x114 uint64 + _, x114 = bits.Add64(x77, x101, uint64(0x0)) + var x115 uint64 + var x116 uint64 + x115, x116 = bits.Add64(x79, x103, uint64(p384Uint1(x114))) + var x117 uint64 + var x118 uint64 + x117, x118 = bits.Add64(x81, x105, uint64(p384Uint1(x116))) + var x119 uint64 + var x120 uint64 + x119, x120 = bits.Add64(x83, x107, uint64(p384Uint1(x118))) + var x121 uint64 + var x122 uint64 + x121, x122 = bits.Add64(x85, x109, uint64(p384Uint1(x120))) + var x123 uint64 + var x124 uint64 + x123, x124 = bits.Add64(x87, x111, uint64(p384Uint1(x122))) + var x125 uint64 + var x126 uint64 + x125, x126 = bits.Add64((uint64(p384Uint1(x88)) + uint64(p384Uint1(x60))), (uint64(p384Uint1(x112)) + x92), uint64(p384Uint1(x124))) + var x127 uint64 + var x128 uint64 + x128, x127 = bits.Mul64(x2, 0x200000000) + var x129 uint64 + var x130 uint64 + x130, x129 = bits.Mul64(x2, 0xfffffffe00000000) + var x131 uint64 + var x132 uint64 + x132, x131 = bits.Mul64(x2, 0x200000000) + var x133 uint64 + var x134 uint64 + x134, x133 = bits.Mul64(x2, 0xfffffffe00000001) + var x135 uint64 + var x136 uint64 + x135, x136 = bits.Add64(x134, x131, uint64(0x0)) + var x137 uint64 + var x138 uint64 + x137, x138 = bits.Add64(x132, x129, uint64(p384Uint1(x136))) + var x139 uint64 + var x140 uint64 + x139, x140 = bits.Add64(x130, x127, uint64(p384Uint1(x138))) + var x141 uint64 + var x142 uint64 + x141, x142 = bits.Add64(x128, x2, uint64(p384Uint1(x140))) + var x143 uint64 + var x144 uint64 + x143, x144 = bits.Add64(x115, x133, uint64(0x0)) + var x145 uint64 + var x146 uint64 + x145, x146 = bits.Add64(x117, x135, uint64(p384Uint1(x144))) + var x147 uint64 + var x148 uint64 + x147, x148 = bits.Add64(x119, x137, uint64(p384Uint1(x146))) + var x149 uint64 + var x150 uint64 + x149, x150 = bits.Add64(x121, x139, uint64(p384Uint1(x148))) + var x151 uint64 + var x152 uint64 + x151, x152 = bits.Add64(x123, x141, uint64(p384Uint1(x150))) + var x153 uint64 + var x154 uint64 + x153, x154 = bits.Add64(x125, uint64(p384Uint1(x142)), uint64(p384Uint1(x152))) + var x155 uint64 + _, x155 = bits.Mul64(x143, 0x100000001) + var x157 uint64 + var x158 uint64 + x158, x157 = bits.Mul64(x155, 0xffffffffffffffff) + var x159 uint64 + var x160 uint64 + x160, x159 = bits.Mul64(x155, 0xffffffffffffffff) + var x161 uint64 + var x162 uint64 + x162, x161 = bits.Mul64(x155, 0xffffffffffffffff) + var x163 uint64 + var x164 uint64 + x164, x163 = bits.Mul64(x155, 0xfffffffffffffffe) + var x165 uint64 + var x166 uint64 + x166, x165 = bits.Mul64(x155, 0xffffffff00000000) + var x167 uint64 + var x168 uint64 + x168, x167 = bits.Mul64(x155, 0xffffffff) + var x169 uint64 + var x170 uint64 + x169, x170 = bits.Add64(x168, x165, uint64(0x0)) + var x171 uint64 + var x172 uint64 + x171, x172 = bits.Add64(x166, x163, uint64(p384Uint1(x170))) + var x173 uint64 + var x174 uint64 + x173, x174 = bits.Add64(x164, x161, uint64(p384Uint1(x172))) + var x175 uint64 + var x176 uint64 + x175, x176 = bits.Add64(x162, x159, uint64(p384Uint1(x174))) + var x177 uint64 + var x178 uint64 + x177, x178 = bits.Add64(x160, x157, uint64(p384Uint1(x176))) + var x180 uint64 + _, x180 = bits.Add64(x143, x167, uint64(0x0)) + var x181 uint64 + var x182 uint64 + x181, x182 = bits.Add64(x145, x169, uint64(p384Uint1(x180))) + var x183 uint64 + var x184 uint64 + x183, x184 = bits.Add64(x147, x171, uint64(p384Uint1(x182))) + var x185 uint64 + var x186 uint64 + x185, x186 = bits.Add64(x149, x173, uint64(p384Uint1(x184))) + var x187 uint64 + var x188 uint64 + x187, x188 = bits.Add64(x151, x175, uint64(p384Uint1(x186))) + var x189 uint64 + var x190 uint64 + x189, x190 = bits.Add64(x153, x177, uint64(p384Uint1(x188))) + var x191 uint64 + var x192 uint64 + x191, x192 = bits.Add64((uint64(p384Uint1(x154)) + uint64(p384Uint1(x126))), (uint64(p384Uint1(x178)) + x158), uint64(p384Uint1(x190))) + var x193 uint64 + var x194 uint64 + x194, x193 = bits.Mul64(x3, 0x200000000) + var x195 uint64 + var x196 uint64 + x196, x195 = bits.Mul64(x3, 0xfffffffe00000000) + var x197 uint64 + var x198 uint64 + x198, x197 = bits.Mul64(x3, 0x200000000) + var x199 uint64 + var x200 uint64 + x200, x199 = bits.Mul64(x3, 0xfffffffe00000001) + var x201 uint64 + var x202 uint64 + x201, x202 = bits.Add64(x200, x197, uint64(0x0)) + var x203 uint64 + var x204 uint64 + x203, x204 = bits.Add64(x198, x195, uint64(p384Uint1(x202))) + var x205 uint64 + var x206 uint64 + x205, x206 = bits.Add64(x196, x193, uint64(p384Uint1(x204))) + var x207 uint64 + var x208 uint64 + x207, x208 = bits.Add64(x194, x3, uint64(p384Uint1(x206))) + var x209 uint64 + var x210 uint64 + x209, x210 = bits.Add64(x181, x199, uint64(0x0)) + var x211 uint64 + var x212 uint64 + x211, x212 = bits.Add64(x183, x201, uint64(p384Uint1(x210))) + var x213 uint64 + var x214 uint64 + x213, x214 = bits.Add64(x185, x203, uint64(p384Uint1(x212))) + var x215 uint64 + var x216 uint64 + x215, x216 = bits.Add64(x187, x205, uint64(p384Uint1(x214))) + var x217 uint64 + var x218 uint64 + x217, x218 = bits.Add64(x189, x207, uint64(p384Uint1(x216))) + var x219 uint64 + var x220 uint64 + x219, x220 = bits.Add64(x191, uint64(p384Uint1(x208)), uint64(p384Uint1(x218))) + var x221 uint64 + _, x221 = bits.Mul64(x209, 0x100000001) + var x223 uint64 + var x224 uint64 + x224, x223 = bits.Mul64(x221, 0xffffffffffffffff) + var x225 uint64 + var x226 uint64 + x226, x225 = bits.Mul64(x221, 0xffffffffffffffff) + var x227 uint64 + var x228 uint64 + x228, x227 = bits.Mul64(x221, 0xffffffffffffffff) + var x229 uint64 + var x230 uint64 + x230, x229 = bits.Mul64(x221, 0xfffffffffffffffe) + var x231 uint64 + var x232 uint64 + x232, x231 = bits.Mul64(x221, 0xffffffff00000000) + var x233 uint64 + var x234 uint64 + x234, x233 = bits.Mul64(x221, 0xffffffff) + var x235 uint64 + var x236 uint64 + x235, x236 = bits.Add64(x234, x231, uint64(0x0)) + var x237 uint64 + var x238 uint64 + x237, x238 = bits.Add64(x232, x229, uint64(p384Uint1(x236))) + var x239 uint64 + var x240 uint64 + x239, x240 = bits.Add64(x230, x227, uint64(p384Uint1(x238))) + var x241 uint64 + var x242 uint64 + x241, x242 = bits.Add64(x228, x225, uint64(p384Uint1(x240))) + var x243 uint64 + var x244 uint64 + x243, x244 = bits.Add64(x226, x223, uint64(p384Uint1(x242))) + var x246 uint64 + _, x246 = bits.Add64(x209, x233, uint64(0x0)) + var x247 uint64 + var x248 uint64 + x247, x248 = bits.Add64(x211, x235, uint64(p384Uint1(x246))) + var x249 uint64 + var x250 uint64 + x249, x250 = bits.Add64(x213, x237, uint64(p384Uint1(x248))) + var x251 uint64 + var x252 uint64 + x251, x252 = bits.Add64(x215, x239, uint64(p384Uint1(x250))) + var x253 uint64 + var x254 uint64 + x253, x254 = bits.Add64(x217, x241, uint64(p384Uint1(x252))) + var x255 uint64 + var x256 uint64 + x255, x256 = bits.Add64(x219, x243, uint64(p384Uint1(x254))) + var x257 uint64 + var x258 uint64 + x257, x258 = bits.Add64((uint64(p384Uint1(x220)) + uint64(p384Uint1(x192))), (uint64(p384Uint1(x244)) + x224), uint64(p384Uint1(x256))) + var x259 uint64 + var x260 uint64 + x260, x259 = bits.Mul64(x4, 0x200000000) + var x261 uint64 + var x262 uint64 + x262, x261 = bits.Mul64(x4, 0xfffffffe00000000) + var x263 uint64 + var x264 uint64 + x264, x263 = bits.Mul64(x4, 0x200000000) + var x265 uint64 + var x266 uint64 + x266, x265 = bits.Mul64(x4, 0xfffffffe00000001) + var x267 uint64 + var x268 uint64 + x267, x268 = bits.Add64(x266, x263, uint64(0x0)) + var x269 uint64 + var x270 uint64 + x269, x270 = bits.Add64(x264, x261, uint64(p384Uint1(x268))) + var x271 uint64 + var x272 uint64 + x271, x272 = bits.Add64(x262, x259, uint64(p384Uint1(x270))) + var x273 uint64 + var x274 uint64 + x273, x274 = bits.Add64(x260, x4, uint64(p384Uint1(x272))) + var x275 uint64 + var x276 uint64 + x275, x276 = bits.Add64(x247, x265, uint64(0x0)) + var x277 uint64 + var x278 uint64 + x277, x278 = bits.Add64(x249, x267, uint64(p384Uint1(x276))) + var x279 uint64 + var x280 uint64 + x279, x280 = bits.Add64(x251, x269, uint64(p384Uint1(x278))) + var x281 uint64 + var x282 uint64 + x281, x282 = bits.Add64(x253, x271, uint64(p384Uint1(x280))) + var x283 uint64 + var x284 uint64 + x283, x284 = bits.Add64(x255, x273, uint64(p384Uint1(x282))) + var x285 uint64 + var x286 uint64 + x285, x286 = bits.Add64(x257, uint64(p384Uint1(x274)), uint64(p384Uint1(x284))) + var x287 uint64 + _, x287 = bits.Mul64(x275, 0x100000001) + var x289 uint64 + var x290 uint64 + x290, x289 = bits.Mul64(x287, 0xffffffffffffffff) + var x291 uint64 + var x292 uint64 + x292, x291 = bits.Mul64(x287, 0xffffffffffffffff) + var x293 uint64 + var x294 uint64 + x294, x293 = bits.Mul64(x287, 0xffffffffffffffff) + var x295 uint64 + var x296 uint64 + x296, x295 = bits.Mul64(x287, 0xfffffffffffffffe) + var x297 uint64 + var x298 uint64 + x298, x297 = bits.Mul64(x287, 0xffffffff00000000) + var x299 uint64 + var x300 uint64 + x300, x299 = bits.Mul64(x287, 0xffffffff) + var x301 uint64 + var x302 uint64 + x301, x302 = bits.Add64(x300, x297, uint64(0x0)) + var x303 uint64 + var x304 uint64 + x303, x304 = bits.Add64(x298, x295, uint64(p384Uint1(x302))) + var x305 uint64 + var x306 uint64 + x305, x306 = bits.Add64(x296, x293, uint64(p384Uint1(x304))) + var x307 uint64 + var x308 uint64 + x307, x308 = bits.Add64(x294, x291, uint64(p384Uint1(x306))) + var x309 uint64 + var x310 uint64 + x309, x310 = bits.Add64(x292, x289, uint64(p384Uint1(x308))) + var x312 uint64 + _, x312 = bits.Add64(x275, x299, uint64(0x0)) + var x313 uint64 + var x314 uint64 + x313, x314 = bits.Add64(x277, x301, uint64(p384Uint1(x312))) + var x315 uint64 + var x316 uint64 + x315, x316 = bits.Add64(x279, x303, uint64(p384Uint1(x314))) + var x317 uint64 + var x318 uint64 + x317, x318 = bits.Add64(x281, x305, uint64(p384Uint1(x316))) + var x319 uint64 + var x320 uint64 + x319, x320 = bits.Add64(x283, x307, uint64(p384Uint1(x318))) + var x321 uint64 + var x322 uint64 + x321, x322 = bits.Add64(x285, x309, uint64(p384Uint1(x320))) + var x323 uint64 + var x324 uint64 + x323, x324 = bits.Add64((uint64(p384Uint1(x286)) + uint64(p384Uint1(x258))), (uint64(p384Uint1(x310)) + x290), uint64(p384Uint1(x322))) + var x325 uint64 + var x326 uint64 + x326, x325 = bits.Mul64(x5, 0x200000000) + var x327 uint64 + var x328 uint64 + x328, x327 = bits.Mul64(x5, 0xfffffffe00000000) + var x329 uint64 + var x330 uint64 + x330, x329 = bits.Mul64(x5, 0x200000000) + var x331 uint64 + var x332 uint64 + x332, x331 = bits.Mul64(x5, 0xfffffffe00000001) + var x333 uint64 + var x334 uint64 + x333, x334 = bits.Add64(x332, x329, uint64(0x0)) + var x335 uint64 + var x336 uint64 + x335, x336 = bits.Add64(x330, x327, uint64(p384Uint1(x334))) + var x337 uint64 + var x338 uint64 + x337, x338 = bits.Add64(x328, x325, uint64(p384Uint1(x336))) + var x339 uint64 + var x340 uint64 + x339, x340 = bits.Add64(x326, x5, uint64(p384Uint1(x338))) + var x341 uint64 + var x342 uint64 + x341, x342 = bits.Add64(x313, x331, uint64(0x0)) + var x343 uint64 + var x344 uint64 + x343, x344 = bits.Add64(x315, x333, uint64(p384Uint1(x342))) + var x345 uint64 + var x346 uint64 + x345, x346 = bits.Add64(x317, x335, uint64(p384Uint1(x344))) + var x347 uint64 + var x348 uint64 + x347, x348 = bits.Add64(x319, x337, uint64(p384Uint1(x346))) + var x349 uint64 + var x350 uint64 + x349, x350 = bits.Add64(x321, x339, uint64(p384Uint1(x348))) + var x351 uint64 + var x352 uint64 + x351, x352 = bits.Add64(x323, uint64(p384Uint1(x340)), uint64(p384Uint1(x350))) + var x353 uint64 + _, x353 = bits.Mul64(x341, 0x100000001) + var x355 uint64 + var x356 uint64 + x356, x355 = bits.Mul64(x353, 0xffffffffffffffff) + var x357 uint64 + var x358 uint64 + x358, x357 = bits.Mul64(x353, 0xffffffffffffffff) + var x359 uint64 + var x360 uint64 + x360, x359 = bits.Mul64(x353, 0xffffffffffffffff) + var x361 uint64 + var x362 uint64 + x362, x361 = bits.Mul64(x353, 0xfffffffffffffffe) + var x363 uint64 + var x364 uint64 + x364, x363 = bits.Mul64(x353, 0xffffffff00000000) + var x365 uint64 + var x366 uint64 + x366, x365 = bits.Mul64(x353, 0xffffffff) + var x367 uint64 + var x368 uint64 + x367, x368 = bits.Add64(x366, x363, uint64(0x0)) + var x369 uint64 + var x370 uint64 + x369, x370 = bits.Add64(x364, x361, uint64(p384Uint1(x368))) + var x371 uint64 + var x372 uint64 + x371, x372 = bits.Add64(x362, x359, uint64(p384Uint1(x370))) + var x373 uint64 + var x374 uint64 + x373, x374 = bits.Add64(x360, x357, uint64(p384Uint1(x372))) + var x375 uint64 + var x376 uint64 + x375, x376 = bits.Add64(x358, x355, uint64(p384Uint1(x374))) + var x378 uint64 + _, x378 = bits.Add64(x341, x365, uint64(0x0)) + var x379 uint64 + var x380 uint64 + x379, x380 = bits.Add64(x343, x367, uint64(p384Uint1(x378))) + var x381 uint64 + var x382 uint64 + x381, x382 = bits.Add64(x345, x369, uint64(p384Uint1(x380))) + var x383 uint64 + var x384 uint64 + x383, x384 = bits.Add64(x347, x371, uint64(p384Uint1(x382))) + var x385 uint64 + var x386 uint64 + x385, x386 = bits.Add64(x349, x373, uint64(p384Uint1(x384))) + var x387 uint64 + var x388 uint64 + x387, x388 = bits.Add64(x351, x375, uint64(p384Uint1(x386))) + var x389 uint64 + var x390 uint64 + x389, x390 = bits.Add64((uint64(p384Uint1(x352)) + uint64(p384Uint1(x324))), (uint64(p384Uint1(x376)) + x356), uint64(p384Uint1(x388))) + var x391 uint64 + var x392 uint64 + x391, x392 = bits.Sub64(x379, 0xffffffff, uint64(0x0)) + var x393 uint64 + var x394 uint64 + x393, x394 = bits.Sub64(x381, 0xffffffff00000000, uint64(p384Uint1(x392))) + var x395 uint64 + var x396 uint64 + x395, x396 = bits.Sub64(x383, 0xfffffffffffffffe, uint64(p384Uint1(x394))) + var x397 uint64 + var x398 uint64 + x397, x398 = bits.Sub64(x385, 0xffffffffffffffff, uint64(p384Uint1(x396))) + var x399 uint64 + var x400 uint64 + x399, x400 = bits.Sub64(x387, 0xffffffffffffffff, uint64(p384Uint1(x398))) + var x401 uint64 + var x402 uint64 + x401, x402 = bits.Sub64(x389, 0xffffffffffffffff, uint64(p384Uint1(x400))) + var x404 uint64 + _, x404 = bits.Sub64(uint64(p384Uint1(x390)), uint64(0x0), uint64(p384Uint1(x402))) + var x405 uint64 + p384CmovznzU64(&x405, p384Uint1(x404), x391, x379) + var x406 uint64 + p384CmovznzU64(&x406, p384Uint1(x404), x393, x381) + var x407 uint64 + p384CmovznzU64(&x407, p384Uint1(x404), x395, x383) + var x408 uint64 + p384CmovznzU64(&x408, p384Uint1(x404), x397, x385) + var x409 uint64 + p384CmovznzU64(&x409, p384Uint1(x404), x399, x387) + var x410 uint64 + p384CmovznzU64(&x410, p384Uint1(x404), x401, x389) + out1[0] = x405 + out1[1] = x406 + out1[2] = x407 + out1[3] = x408 + out1[4] = x409 + out1[5] = x410 +} + +// p384Selectznz is a multi-limb conditional select. +// +// Postconditions: +// eval out1 = (if arg1 = 0 then eval arg2 else eval arg3) +// +// Input Bounds: +// arg1: [0x0 ~> 0x1] +// arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +// arg3: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +// Output Bounds: +// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +func p384Selectznz(out1 *[6]uint64, arg1 p384Uint1, arg2 *[6]uint64, arg3 *[6]uint64) { + var x1 uint64 + p384CmovznzU64(&x1, arg1, arg2[0], arg3[0]) + var x2 uint64 + p384CmovznzU64(&x2, arg1, arg2[1], arg3[1]) + var x3 uint64 + p384CmovznzU64(&x3, arg1, arg2[2], arg3[2]) + var x4 uint64 + p384CmovznzU64(&x4, arg1, arg2[3], arg3[3]) + var x5 uint64 + p384CmovznzU64(&x5, arg1, arg2[4], arg3[4]) + var x6 uint64 + p384CmovznzU64(&x6, arg1, arg2[5], arg3[5]) + out1[0] = x1 + out1[1] = x2 + out1[2] = x3 + out1[3] = x4 + out1[4] = x5 + out1[5] = x6 +} + +// p384ToBytes serializes a field element NOT in the Montgomery domain to bytes in little-endian order. +// +// Preconditions: +// 0 ≤ eval arg1 < m +// Postconditions: +// out1 = map (λ x, ⌊((eval arg1 mod m) mod 2^(8 * (x + 1))) / 2^(8 * x)⌋) [0..47] +// +// Input Bounds: +// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +// Output Bounds: +// out1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff]] +func p384ToBytes(out1 *[48]uint8, arg1 *[6]uint64) { + x1 := arg1[5] + x2 := arg1[4] + x3 := arg1[3] + x4 := arg1[2] + x5 := arg1[1] + x6 := arg1[0] + x7 := (uint8(x6) & 0xff) + x8 := (x6 >> 8) + x9 := (uint8(x8) & 0xff) + x10 := (x8 >> 8) + x11 := (uint8(x10) & 0xff) + x12 := (x10 >> 8) + x13 := (uint8(x12) & 0xff) + x14 := (x12 >> 8) + x15 := (uint8(x14) & 0xff) + x16 := (x14 >> 8) + x17 := (uint8(x16) & 0xff) + x18 := (x16 >> 8) + x19 := (uint8(x18) & 0xff) + x20 := uint8((x18 >> 8)) + x21 := (uint8(x5) & 0xff) + x22 := (x5 >> 8) + x23 := (uint8(x22) & 0xff) + x24 := (x22 >> 8) + x25 := (uint8(x24) & 0xff) + x26 := (x24 >> 8) + x27 := (uint8(x26) & 0xff) + x28 := (x26 >> 8) + x29 := (uint8(x28) & 0xff) + x30 := (x28 >> 8) + x31 := (uint8(x30) & 0xff) + x32 := (x30 >> 8) + x33 := (uint8(x32) & 0xff) + x34 := uint8((x32 >> 8)) + x35 := (uint8(x4) & 0xff) + x36 := (x4 >> 8) + x37 := (uint8(x36) & 0xff) + x38 := (x36 >> 8) + x39 := (uint8(x38) & 0xff) + x40 := (x38 >> 8) + x41 := (uint8(x40) & 0xff) + x42 := (x40 >> 8) + x43 := (uint8(x42) & 0xff) + x44 := (x42 >> 8) + x45 := (uint8(x44) & 0xff) + x46 := (x44 >> 8) + x47 := (uint8(x46) & 0xff) + x48 := uint8((x46 >> 8)) + x49 := (uint8(x3) & 0xff) + x50 := (x3 >> 8) + x51 := (uint8(x50) & 0xff) + x52 := (x50 >> 8) + x53 := (uint8(x52) & 0xff) + x54 := (x52 >> 8) + x55 := (uint8(x54) & 0xff) + x56 := (x54 >> 8) + x57 := (uint8(x56) & 0xff) + x58 := (x56 >> 8) + x59 := (uint8(x58) & 0xff) + x60 := (x58 >> 8) + x61 := (uint8(x60) & 0xff) + x62 := uint8((x60 >> 8)) + x63 := (uint8(x2) & 0xff) + x64 := (x2 >> 8) + x65 := (uint8(x64) & 0xff) + x66 := (x64 >> 8) + x67 := (uint8(x66) & 0xff) + x68 := (x66 >> 8) + x69 := (uint8(x68) & 0xff) + x70 := (x68 >> 8) + x71 := (uint8(x70) & 0xff) + x72 := (x70 >> 8) + x73 := (uint8(x72) & 0xff) + x74 := (x72 >> 8) + x75 := (uint8(x74) & 0xff) + x76 := uint8((x74 >> 8)) + x77 := (uint8(x1) & 0xff) + x78 := (x1 >> 8) + x79 := (uint8(x78) & 0xff) + x80 := (x78 >> 8) + x81 := (uint8(x80) & 0xff) + x82 := (x80 >> 8) + x83 := (uint8(x82) & 0xff) + x84 := (x82 >> 8) + x85 := (uint8(x84) & 0xff) + x86 := (x84 >> 8) + x87 := (uint8(x86) & 0xff) + x88 := (x86 >> 8) + x89 := (uint8(x88) & 0xff) + x90 := uint8((x88 >> 8)) + out1[0] = x7 + out1[1] = x9 + out1[2] = x11 + out1[3] = x13 + out1[4] = x15 + out1[5] = x17 + out1[6] = x19 + out1[7] = x20 + out1[8] = x21 + out1[9] = x23 + out1[10] = x25 + out1[11] = x27 + out1[12] = x29 + out1[13] = x31 + out1[14] = x33 + out1[15] = x34 + out1[16] = x35 + out1[17] = x37 + out1[18] = x39 + out1[19] = x41 + out1[20] = x43 + out1[21] = x45 + out1[22] = x47 + out1[23] = x48 + out1[24] = x49 + out1[25] = x51 + out1[26] = x53 + out1[27] = x55 + out1[28] = x57 + out1[29] = x59 + out1[30] = x61 + out1[31] = x62 + out1[32] = x63 + out1[33] = x65 + out1[34] = x67 + out1[35] = x69 + out1[36] = x71 + out1[37] = x73 + out1[38] = x75 + out1[39] = x76 + out1[40] = x77 + out1[41] = x79 + out1[42] = x81 + out1[43] = x83 + out1[44] = x85 + out1[45] = x87 + out1[46] = x89 + out1[47] = x90 +} + +// p384FromBytes deserializes a field element NOT in the Montgomery domain from bytes in little-endian order. +// +// Preconditions: +// 0 ≤ bytes_eval arg1 < m +// Postconditions: +// eval out1 mod m = bytes_eval arg1 mod m +// 0 ≤ eval out1 < m +// +// Input Bounds: +// arg1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff]] +// Output Bounds: +// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +func p384FromBytes(out1 *[6]uint64, arg1 *[48]uint8) { + x1 := (uint64(arg1[47]) << 56) + x2 := (uint64(arg1[46]) << 48) + x3 := (uint64(arg1[45]) << 40) + x4 := (uint64(arg1[44]) << 32) + x5 := (uint64(arg1[43]) << 24) + x6 := (uint64(arg1[42]) << 16) + x7 := (uint64(arg1[41]) << 8) + x8 := arg1[40] + x9 := (uint64(arg1[39]) << 56) + x10 := (uint64(arg1[38]) << 48) + x11 := (uint64(arg1[37]) << 40) + x12 := (uint64(arg1[36]) << 32) + x13 := (uint64(arg1[35]) << 24) + x14 := (uint64(arg1[34]) << 16) + x15 := (uint64(arg1[33]) << 8) + x16 := arg1[32] + x17 := (uint64(arg1[31]) << 56) + x18 := (uint64(arg1[30]) << 48) + x19 := (uint64(arg1[29]) << 40) + x20 := (uint64(arg1[28]) << 32) + x21 := (uint64(arg1[27]) << 24) + x22 := (uint64(arg1[26]) << 16) + x23 := (uint64(arg1[25]) << 8) + x24 := arg1[24] + x25 := (uint64(arg1[23]) << 56) + x26 := (uint64(arg1[22]) << 48) + x27 := (uint64(arg1[21]) << 40) + x28 := (uint64(arg1[20]) << 32) + x29 := (uint64(arg1[19]) << 24) + x30 := (uint64(arg1[18]) << 16) + x31 := (uint64(arg1[17]) << 8) + x32 := arg1[16] + x33 := (uint64(arg1[15]) << 56) + x34 := (uint64(arg1[14]) << 48) + x35 := (uint64(arg1[13]) << 40) + x36 := (uint64(arg1[12]) << 32) + x37 := (uint64(arg1[11]) << 24) + x38 := (uint64(arg1[10]) << 16) + x39 := (uint64(arg1[9]) << 8) + x40 := arg1[8] + x41 := (uint64(arg1[7]) << 56) + x42 := (uint64(arg1[6]) << 48) + x43 := (uint64(arg1[5]) << 40) + x44 := (uint64(arg1[4]) << 32) + x45 := (uint64(arg1[3]) << 24) + x46 := (uint64(arg1[2]) << 16) + x47 := (uint64(arg1[1]) << 8) + x48 := arg1[0] + x49 := (x47 + uint64(x48)) + x50 := (x46 + x49) + x51 := (x45 + x50) + x52 := (x44 + x51) + x53 := (x43 + x52) + x54 := (x42 + x53) + x55 := (x41 + x54) + x56 := (x39 + uint64(x40)) + x57 := (x38 + x56) + x58 := (x37 + x57) + x59 := (x36 + x58) + x60 := (x35 + x59) + x61 := (x34 + x60) + x62 := (x33 + x61) + x63 := (x31 + uint64(x32)) + x64 := (x30 + x63) + x65 := (x29 + x64) + x66 := (x28 + x65) + x67 := (x27 + x66) + x68 := (x26 + x67) + x69 := (x25 + x68) + x70 := (x23 + uint64(x24)) + x71 := (x22 + x70) + x72 := (x21 + x71) + x73 := (x20 + x72) + x74 := (x19 + x73) + x75 := (x18 + x74) + x76 := (x17 + x75) + x77 := (x15 + uint64(x16)) + x78 := (x14 + x77) + x79 := (x13 + x78) + x80 := (x12 + x79) + x81 := (x11 + x80) + x82 := (x10 + x81) + x83 := (x9 + x82) + x84 := (x7 + uint64(x8)) + x85 := (x6 + x84) + x86 := (x5 + x85) + x87 := (x4 + x86) + x88 := (x3 + x87) + x89 := (x2 + x88) + x90 := (x1 + x89) + out1[0] = x55 + out1[1] = x62 + out1[2] = x69 + out1[3] = x76 + out1[4] = x83 + out1[5] = x90 +} diff --git a/src/crypto/elliptic/internal/fiat/p384_invert.go b/src/crypto/elliptic/internal/fiat/p384_invert.go new file mode 100644 index 0000000000..24169e98d9 --- /dev/null +++ b/src/crypto/elliptic/internal/fiat/p384_invert.go @@ -0,0 +1,102 @@ +// Copyright 2021 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. + +// Code generated by addchain. DO NOT EDIT. + +package fiat + +// Invert sets e = 1/x, and returns e. +// +// If x == 0, Invert returns e = 0. +func (e *P384Element) Invert(x *P384Element) *P384Element { + // Inversion is implemented as exponentiation with exponent p − 2. + // The sequence of 15 multiplications and 383 squarings is derived from the + // following addition chain generated with github.com/mmcloughlin/addchain v0.3.0. + // + // _10 = 2*1 + // _11 = 1 + _10 + // _110 = 2*_11 + // _111 = 1 + _110 + // _111000 = _111 << 3 + // _111111 = _111 + _111000 + // x12 = _111111 << 6 + _111111 + // x24 = x12 << 12 + x12 + // x30 = x24 << 6 + _111111 + // x31 = 2*x30 + 1 + // x32 = 2*x31 + 1 + // x63 = x32 << 31 + x31 + // x126 = x63 << 63 + x63 + // x252 = x126 << 126 + x126 + // x255 = x252 << 3 + _111 + // i397 = ((x255 << 33 + x32) << 94 + x30) << 2 + // return 1 + i397 + // + + var z = new(P384Element).Set(e) + var t0 = new(P384Element) + var t1 = new(P384Element) + var t2 = new(P384Element) + var t3 = new(P384Element) + + z.Square(x) + z.Mul(x, z) + z.Square(z) + t1.Mul(x, z) + z.Square(t1) + for s := 1; s < 3; s++ { + z.Square(z) + } + z.Mul(t1, z) + t0.Square(z) + for s := 1; s < 6; s++ { + t0.Square(t0) + } + t0.Mul(z, t0) + t2.Square(t0) + for s := 1; s < 12; s++ { + t2.Square(t2) + } + t0.Mul(t0, t2) + for s := 0; s < 6; s++ { + t0.Square(t0) + } + z.Mul(z, t0) + t0.Square(z) + t2.Mul(x, t0) + t0.Square(t2) + t0.Mul(x, t0) + t3.Square(t0) + for s := 1; s < 31; s++ { + t3.Square(t3) + } + t2.Mul(t2, t3) + t3.Square(t2) + for s := 1; s < 63; s++ { + t3.Square(t3) + } + t2.Mul(t2, t3) + t3.Square(t2) + for s := 1; s < 126; s++ { + t3.Square(t3) + } + t2.Mul(t2, t3) + for s := 0; s < 3; s++ { + t2.Square(t2) + } + t1.Mul(t1, t2) + for s := 0; s < 33; s++ { + t1.Square(t1) + } + t0.Mul(t0, t1) + for s := 0; s < 94; s++ { + t0.Square(t0) + } + z.Mul(z, t0) + for s := 0; s < 2; s++ { + z.Square(z) + } + z.Mul(x, z) + + return e.Set(z) +} diff --git a/src/crypto/elliptic/internal/fiat/p521.go b/src/crypto/elliptic/internal/fiat/p521.go index 647c3f914f..3d12117e49 100644 --- a/src/crypto/elliptic/internal/fiat/p521.go +++ b/src/crypto/elliptic/internal/fiat/p521.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Package fiat implements prime order fields using formally verified algorithms -// from the Fiat Cryptography project. +// Code generated by generate.go. DO NOT EDIT. + package fiat import ( @@ -15,20 +15,18 @@ import ( // // The zero value is a valid zero element. type P521Element struct { - // This element has the following bounds, which are tighter than - // the output bounds of some operations. Those operations must be - // followed by a carry. - // - // [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], - // [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], - // [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000] - x [9]uint64 + // Values are represented internally always in the Montgomery domain, and + // converted in Bytes and SetBytes. + x p521MontgomeryDomainFieldElement } +const p521ElementLen = 66 + +type p521UntypedFieldElement = [9]uint64 + // One sets e = 1, and returns e. func (e *P521Element) One() *P521Element { - *e = P521Element{} - e.x[0] = 1 + p521SetOne(&e.x) return e } @@ -57,153 +55,81 @@ func (e *P521Element) Set(t *P521Element) *P521Element { func (e *P521Element) Bytes() []byte { // This function is outlined to make the allocations inline in the caller // rather than happen on the heap. - var out [66]byte + var out [p521ElementLen]byte return e.bytes(&out) } -func (e *P521Element) bytes(out *[66]byte) []byte { - p521ToBytes(out, &e.x) - invertEndianness(out[:]) +func (e *P521Element) bytes(out *[p521ElementLen]byte) []byte { + var tmp p521NonMontgomeryDomainFieldElement + p521FromMontgomery(&tmp, &e.x) + p521ToBytes(out, (*p521UntypedFieldElement)(&tmp)) + p521InvertEndianness(out[:]) return out[:] } -// SetBytes sets e = v, where v is a big-endian 66-byte encoding, and returns -// e. If v is not 66 bytes or it encodes a value higher than 2^521 - 1, SetBytes -// returns nil and an error, and e is unchanged. -func (e *P521Element) SetBytes(v []byte) (*P521Element, error) { - if len(v) != 66 || v[0] > 1 { - return nil, errors.New("invalid P-521 field encoding") - } - var in [66]byte - copy(in[:], v) - invertEndianness(in[:]) - p521FromBytes(&e.x, &in) - return e, nil -} +// p521MinusOneEncoding is the encoding of -1 mod p, so p - 1, the +// highest canonical encoding. It is used by SetBytes to check for non-canonical +// encodings such as p + k, 2p + k, etc. +var p521MinusOneEncoding = new(P521Element).Sub( + new(P521Element), new(P521Element).One()).Bytes() -func invertEndianness(v []byte) { - for i := 0; i < len(v)/2; i++ { - v[i], v[len(v)-1-i] = v[len(v)-1-i], v[i] +// SetBytes sets e = v, where v is a big-endian 66-byte encoding, and returns e. +// If v is not 66 bytes or it encodes a value higher than 2^521 - 1, +// SetBytes returns nil and an error, and e is unchanged. +func (e *P521Element) SetBytes(v []byte) (*P521Element, error) { + if len(v) != p521ElementLen { + return nil, errors.New("invalid P521Element encoding") } + for i := range v { + if v[i] < p521MinusOneEncoding[i] { + break + } + if v[i] > p521MinusOneEncoding[i] { + return nil, errors.New("invalid P521Element encoding") + } + } + var in [p521ElementLen]byte + copy(in[:], v) + p521InvertEndianness(in[:]) + var tmp p521NonMontgomeryDomainFieldElement + p521FromBytes((*p521UntypedFieldElement)(&tmp), &in) + p521ToMontgomery(&e.x, &tmp) + return e, nil } // Add sets e = t1 + t2, and returns e. func (e *P521Element) Add(t1, t2 *P521Element) *P521Element { p521Add(&e.x, &t1.x, &t2.x) - p521Carry(&e.x, &e.x) return e } // Sub sets e = t1 - t2, and returns e. func (e *P521Element) Sub(t1, t2 *P521Element) *P521Element { p521Sub(&e.x, &t1.x, &t2.x) - p521Carry(&e.x, &e.x) return e } // Mul sets e = t1 * t2, and returns e. func (e *P521Element) Mul(t1, t2 *P521Element) *P521Element { - p521CarryMul(&e.x, &t1.x, &t2.x) + p521Mul(&e.x, &t1.x, &t2.x) return e } // Square sets e = t * t, and returns e. func (e *P521Element) Square(t *P521Element) *P521Element { - p521CarrySquare(&e.x, &t.x) + p521Square(&e.x, &t.x) return e } -// Select sets e to a if cond == 1, and to b if cond == 0. +// Select sets v to a if cond == 1, and to b if cond == 0. func (v *P521Element) Select(a, b *P521Element, cond int) *P521Element { - p521Selectznz(&v.x, p521Uint1(cond), &b.x, &a.x) + p521Selectznz((*p521UntypedFieldElement)(&v.x), p521Uint1(cond), + (*p521UntypedFieldElement)(&b.x), (*p521UntypedFieldElement)(&a.x)) return v } -// Invert sets e = 1/t, and returns e. -// -// If t == 0, Invert returns e = 0. -func (e *P521Element) Invert(t *P521Element) *P521Element { - // Inversion is implemented as exponentiation with exponent p − 2. - // The sequence of multiplications and squarings was generated with - // github.com/mmcloughlin/addchain v0.2.0. - - var t1, t2 = new(P521Element), new(P521Element) - - // _10 = 2 * 1 - t1.Square(t) - - // _11 = 1 + _10 - t1.Mul(t, t1) - - // _1100 = _11 << 2 - t2.Square(t1) - t2.Square(t2) - - // _1111 = _11 + _1100 - t1.Mul(t1, t2) - - // _11110000 = _1111 << 4 - t2.Square(t1) - for i := 0; i < 3; i++ { - t2.Square(t2) +func p521InvertEndianness(v []byte) { + for i := 0; i < len(v)/2; i++ { + v[i], v[len(v)-1-i] = v[len(v)-1-i], v[i] } - - // _11111111 = _1111 + _11110000 - t1.Mul(t1, t2) - - // x16 = _11111111<<8 + _11111111 - t2.Square(t1) - for i := 0; i < 7; i++ { - t2.Square(t2) - } - t1.Mul(t1, t2) - - // x32 = x16<<16 + x16 - t2.Square(t1) - for i := 0; i < 15; i++ { - t2.Square(t2) - } - t1.Mul(t1, t2) - - // x64 = x32<<32 + x32 - t2.Square(t1) - for i := 0; i < 31; i++ { - t2.Square(t2) - } - t1.Mul(t1, t2) - - // x65 = 2*x64 + 1 - t2.Square(t1) - t2.Mul(t2, t) - - // x129 = x65<<64 + x64 - for i := 0; i < 64; i++ { - t2.Square(t2) - } - t1.Mul(t1, t2) - - // x130 = 2*x129 + 1 - t2.Square(t1) - t2.Mul(t2, t) - - // x259 = x130<<129 + x129 - for i := 0; i < 129; i++ { - t2.Square(t2) - } - t1.Mul(t1, t2) - - // x260 = 2*x259 + 1 - t2.Square(t1) - t2.Mul(t2, t) - - // x519 = x260<<259 + x259 - for i := 0; i < 259; i++ { - t2.Square(t2) - } - t1.Mul(t1, t2) - - // return x519<<2 + 1 - t1.Square(t1) - t1.Square(t1) - return e.Mul(t1, t) } diff --git a/src/crypto/elliptic/internal/fiat/p521_fiat64.go b/src/crypto/elliptic/internal/fiat/p521_fiat64.go index f86283b587..9f4f290f4c 100644 --- a/src/crypto/elliptic/internal/fiat/p521_fiat64.go +++ b/src/crypto/elliptic/internal/fiat/p521_fiat64.go @@ -1,133 +1,57 @@ // Code generated by Fiat Cryptography. DO NOT EDIT. // -// Autogenerated: 'fiat-crypto/src/ExtractionOCaml/unsaturated_solinas' --lang Go --no-wide-int --cmovznz-by-mul --internal-static --public-function-case camelCase --public-type-case camelCase --private-function-case camelCase --private-type-case camelCase --no-prefix-fiat --package-name fiat --doc-text-before-function-name '' --doc-prepend-header 'Code generated by Fiat Cryptography. DO NOT EDIT.' --doc-newline-before-package-declaration p521 64 9 '2^521 - 1' carry_mul carry_square carry add sub to_bytes from_bytes selectznz +// Autogenerated: word_by_word_montgomery --lang Go --no-wide-int --cmovznz-by-mul --relax-primitive-carry-to-bitwidth 32,64 --internal-static --public-function-case camelCase --public-type-case camelCase --private-function-case camelCase --private-type-case camelCase --doc-text-before-function-name '' --doc-newline-before-package-declaration --doc-prepend-header 'Code generated by Fiat Cryptography. DO NOT EDIT.' --package-name fiat --no-prefix-fiat p521 64 '2^521 - 1' mul square add sub one from_montgomery to_montgomery selectznz to_bytes from_bytes // // curve description: p521 // // machine_wordsize = 64 (from "64") // -// requested operations: carry_mul, carry_square, carry, add, sub, to_bytes, from_bytes, selectznz +// requested operations: mul, square, add, sub, one, from_montgomery, to_montgomery, selectznz, to_bytes, from_bytes // -// n = 9 (from "9") +// m = 0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff (from "2^521 - 1") // -// s-c = 2^521 - [(1, 1)] (from "2^521 - 1") // -// tight_bounds_multiplier = 1 (from "") +// +// NOTE: In addition to the bounds specified above each function, all +// +// functions synthesized for this Montgomery arithmetic require the +// +// input to be strictly less than the prime modulus (m), and also +// +// require the input to be in the unique saturated representation. +// +// All functions also ensure that these two properties are true of +// +// return values. // // // // Computed values: // -// carry_chain = [0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1] -// -// eval z = z[0] + (z[1] << 58) + (z[2] << 116) + (z[3] << 174) + (z[4] << 232) + (z[5] << 0x122) + (z[6] << 0x15c) + (z[7] << 0x196) + (z[8] << 0x1d0) +// eval z = z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) + (z[4] << 256) + (z[5] << 0x140) + (z[6] << 0x180) + (z[7] << 0x1c0) + (z[8] << 2^9) // // bytes_eval z = z[0] + (z[1] << 8) + (z[2] << 16) + (z[3] << 24) + (z[4] << 32) + (z[5] << 40) + (z[6] << 48) + (z[7] << 56) + (z[8] << 64) + (z[9] << 72) + (z[10] << 80) + (z[11] << 88) + (z[12] << 96) + (z[13] << 104) + (z[14] << 112) + (z[15] << 120) + (z[16] << 128) + (z[17] << 136) + (z[18] << 144) + (z[19] << 152) + (z[20] << 160) + (z[21] << 168) + (z[22] << 176) + (z[23] << 184) + (z[24] << 192) + (z[25] << 200) + (z[26] << 208) + (z[27] << 216) + (z[28] << 224) + (z[29] << 232) + (z[30] << 240) + (z[31] << 248) + (z[32] << 256) + (z[33] << 0x108) + (z[34] << 0x110) + (z[35] << 0x118) + (z[36] << 0x120) + (z[37] << 0x128) + (z[38] << 0x130) + (z[39] << 0x138) + (z[40] << 0x140) + (z[41] << 0x148) + (z[42] << 0x150) + (z[43] << 0x158) + (z[44] << 0x160) + (z[45] << 0x168) + (z[46] << 0x170) + (z[47] << 0x178) + (z[48] << 0x180) + (z[49] << 0x188) + (z[50] << 0x190) + (z[51] << 0x198) + (z[52] << 0x1a0) + (z[53] << 0x1a8) + (z[54] << 0x1b0) + (z[55] << 0x1b8) + (z[56] << 0x1c0) + (z[57] << 0x1c8) + (z[58] << 0x1d0) + (z[59] << 0x1d8) + (z[60] << 0x1e0) + (z[61] << 0x1e8) + (z[62] << 0x1f0) + (z[63] << 0x1f8) + (z[64] << 2^9) + (z[65] << 0x208) // -// balance = [0x7fffffffffffffe, 0x7fffffffffffffe, 0x7fffffffffffffe, 0x7fffffffffffffe, 0x7fffffffffffffe, 0x7fffffffffffffe, 0x7fffffffffffffe, 0x7fffffffffffffe, 0x3fffffffffffffe] +// twos_complement_eval z = let x1 := z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) + (z[4] << 256) + (z[5] << 0x140) + (z[6] << 0x180) + (z[7] << 0x1c0) + (z[8] << 2^9) in +// +// if x1 & (2^576-1) < 2^575 then x1 & (2^576-1) else (x1 & (2^576-1)) - 2^576 package fiat import "math/bits" -type p521Uint1 uint8 -type p521Int1 int8 +type p521Uint1 uint64 // We use uint64 instead of a more narrow type for performance reasons; see https://github.com/mit-plv/fiat-crypto/pull/1006#issuecomment-892625927 +type p521Int1 int64 // We use uint64 instead of a more narrow type for performance reasons; see https://github.com/mit-plv/fiat-crypto/pull/1006#issuecomment-892625927 -// p521AddcarryxU64 is a thin wrapper around bits.Add64 that uses p521Uint1 rather than uint64 -func p521AddcarryxU64(x uint64, y uint64, carry p521Uint1) (uint64, p521Uint1) { - sum, carryOut := bits.Add64(x, y, uint64(carry)) - return sum, p521Uint1(carryOut) -} +// The type p521MontgomeryDomainFieldElement is a field element in the Montgomery domain. +// +// Bounds: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +type p521MontgomeryDomainFieldElement [9]uint64 -// p521SubborrowxU64 is a thin wrapper around bits.Sub64 that uses p521Uint1 rather than uint64 -func p521SubborrowxU64(x uint64, y uint64, carry p521Uint1) (uint64, p521Uint1) { - sum, carryOut := bits.Sub64(x, y, uint64(carry)) - return sum, p521Uint1(carryOut) -} - -// p521AddcarryxU58 is an addition with carry. +// The type p521NonMontgomeryDomainFieldElement is a field element NOT in the Montgomery domain. // -// Postconditions: -// out1 = (arg1 + arg2 + arg3) mod 2^58 -// out2 = ⌊(arg1 + arg2 + arg3) / 2^58⌋ -// -// Input Bounds: -// arg1: [0x0 ~> 0x1] -// arg2: [0x0 ~> 0x3ffffffffffffff] -// arg3: [0x0 ~> 0x3ffffffffffffff] -// Output Bounds: -// out1: [0x0 ~> 0x3ffffffffffffff] -// out2: [0x0 ~> 0x1] -func p521AddcarryxU58(out1 *uint64, out2 *p521Uint1, arg1 p521Uint1, arg2 uint64, arg3 uint64) { - x1 := ((uint64(arg1) + arg2) + arg3) - x2 := (x1 & 0x3ffffffffffffff) - x3 := p521Uint1((x1 >> 58)) - *out1 = x2 - *out2 = x3 -} - -// p521SubborrowxU58 is a subtraction with borrow. -// -// Postconditions: -// out1 = (-arg1 + arg2 + -arg3) mod 2^58 -// out2 = -⌊(-arg1 + arg2 + -arg3) / 2^58⌋ -// -// Input Bounds: -// arg1: [0x0 ~> 0x1] -// arg2: [0x0 ~> 0x3ffffffffffffff] -// arg3: [0x0 ~> 0x3ffffffffffffff] -// Output Bounds: -// out1: [0x0 ~> 0x3ffffffffffffff] -// out2: [0x0 ~> 0x1] -func p521SubborrowxU58(out1 *uint64, out2 *p521Uint1, arg1 p521Uint1, arg2 uint64, arg3 uint64) { - x1 := ((int64(arg2) - int64(arg1)) - int64(arg3)) - x2 := p521Int1((x1 >> 58)) - x3 := (uint64(x1) & 0x3ffffffffffffff) - *out1 = x3 - *out2 = (0x0 - p521Uint1(x2)) -} - -// p521AddcarryxU57 is an addition with carry. -// -// Postconditions: -// out1 = (arg1 + arg2 + arg3) mod 2^57 -// out2 = ⌊(arg1 + arg2 + arg3) / 2^57⌋ -// -// Input Bounds: -// arg1: [0x0 ~> 0x1] -// arg2: [0x0 ~> 0x1ffffffffffffff] -// arg3: [0x0 ~> 0x1ffffffffffffff] -// Output Bounds: -// out1: [0x0 ~> 0x1ffffffffffffff] -// out2: [0x0 ~> 0x1] -func p521AddcarryxU57(out1 *uint64, out2 *p521Uint1, arg1 p521Uint1, arg2 uint64, arg3 uint64) { - x1 := ((uint64(arg1) + arg2) + arg3) - x2 := (x1 & 0x1ffffffffffffff) - x3 := p521Uint1((x1 >> 57)) - *out1 = x2 - *out2 = x3 -} - -// p521SubborrowxU57 is a subtraction with borrow. -// -// Postconditions: -// out1 = (-arg1 + arg2 + -arg3) mod 2^57 -// out2 = -⌊(-arg1 + arg2 + -arg3) / 2^57⌋ -// -// Input Bounds: -// arg1: [0x0 ~> 0x1] -// arg2: [0x0 ~> 0x1ffffffffffffff] -// arg3: [0x0 ~> 0x1ffffffffffffff] -// Output Bounds: -// out1: [0x0 ~> 0x1ffffffffffffff] -// out2: [0x0 ~> 0x1] -func p521SubborrowxU57(out1 *uint64, out2 *p521Uint1, arg1 p521Uint1, arg2 uint64, arg3 uint64) { - x1 := ((int64(arg2) - int64(arg1)) - int64(arg3)) - x2 := p521Int1((x1 >> 57)) - x3 := (uint64(x1) & 0x1ffffffffffffff) - *out1 = x3 - *out2 = (0x0 - p521Uint1(x2)) -} +// Bounds: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +type p521NonMontgomeryDomainFieldElement [9]uint64 // p521CmovznzU64 is a single-word conditional move. // @@ -146,1672 +70,5051 @@ func p521CmovznzU64(out1 *uint64, arg1 p521Uint1, arg2 uint64, arg3 uint64) { *out1 = x2 } -// p521CarryMul multiplies two field elements and reduces the result. +// p521Mul multiplies two field elements in the Montgomery domain. // +// Preconditions: +// 0 ≤ eval arg1 < m +// 0 ≤ eval arg2 < m // Postconditions: -// eval out1 mod m = (eval arg1 * eval arg2) mod m +// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg2)) mod m +// 0 ≤ eval out1 < m // -// Input Bounds: -// arg1: [[0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0x600000000000000]] -// arg2: [[0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0x600000000000000]] -// Output Bounds: -// out1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]] -func p521CarryMul(out1 *[9]uint64, arg1 *[9]uint64, arg2 *[9]uint64) { - var x1 uint64 - var x2 uint64 - x2, x1 = bits.Mul64(arg1[8], (arg2[8] * 0x2)) - var x3 uint64 - var x4 uint64 - x4, x3 = bits.Mul64(arg1[8], (arg2[7] * 0x2)) - var x5 uint64 - var x6 uint64 - x6, x5 = bits.Mul64(arg1[8], (arg2[6] * 0x2)) - var x7 uint64 - var x8 uint64 - x8, x7 = bits.Mul64(arg1[8], (arg2[5] * 0x2)) - var x9 uint64 +func p521Mul(out1 *p521MontgomeryDomainFieldElement, arg1 *p521MontgomeryDomainFieldElement, arg2 *p521MontgomeryDomainFieldElement) { + x1 := arg1[1] + x2 := arg1[2] + x3 := arg1[3] + x4 := arg1[4] + x5 := arg1[5] + x6 := arg1[6] + x7 := arg1[7] + x8 := arg1[8] + x9 := arg1[0] var x10 uint64 - x10, x9 = bits.Mul64(arg1[8], (arg2[4] * 0x2)) var x11 uint64 + x11, x10 = bits.Mul64(x9, arg2[8]) var x12 uint64 - x12, x11 = bits.Mul64(arg1[8], (arg2[3] * 0x2)) var x13 uint64 + x13, x12 = bits.Mul64(x9, arg2[7]) var x14 uint64 - x14, x13 = bits.Mul64(arg1[8], (arg2[2] * 0x2)) var x15 uint64 + x15, x14 = bits.Mul64(x9, arg2[6]) var x16 uint64 - x16, x15 = bits.Mul64(arg1[8], (arg2[1] * 0x2)) var x17 uint64 + x17, x16 = bits.Mul64(x9, arg2[5]) var x18 uint64 - x18, x17 = bits.Mul64(arg1[7], (arg2[8] * 0x2)) var x19 uint64 + x19, x18 = bits.Mul64(x9, arg2[4]) var x20 uint64 - x20, x19 = bits.Mul64(arg1[7], (arg2[7] * 0x2)) var x21 uint64 + x21, x20 = bits.Mul64(x9, arg2[3]) var x22 uint64 - x22, x21 = bits.Mul64(arg1[7], (arg2[6] * 0x2)) var x23 uint64 + x23, x22 = bits.Mul64(x9, arg2[2]) var x24 uint64 - x24, x23 = bits.Mul64(arg1[7], (arg2[5] * 0x2)) var x25 uint64 + x25, x24 = bits.Mul64(x9, arg2[1]) var x26 uint64 - x26, x25 = bits.Mul64(arg1[7], (arg2[4] * 0x2)) var x27 uint64 + x27, x26 = bits.Mul64(x9, arg2[0]) var x28 uint64 - x28, x27 = bits.Mul64(arg1[7], (arg2[3] * 0x2)) var x29 uint64 + x28, x29 = bits.Add64(x27, x24, uint64(0x0)) var x30 uint64 - x30, x29 = bits.Mul64(arg1[7], (arg2[2] * 0x2)) var x31 uint64 + x30, x31 = bits.Add64(x25, x22, uint64(p521Uint1(x29))) var x32 uint64 - x32, x31 = bits.Mul64(arg1[6], (arg2[8] * 0x2)) var x33 uint64 + x32, x33 = bits.Add64(x23, x20, uint64(p521Uint1(x31))) var x34 uint64 - x34, x33 = bits.Mul64(arg1[6], (arg2[7] * 0x2)) var x35 uint64 + x34, x35 = bits.Add64(x21, x18, uint64(p521Uint1(x33))) var x36 uint64 - x36, x35 = bits.Mul64(arg1[6], (arg2[6] * 0x2)) var x37 uint64 + x36, x37 = bits.Add64(x19, x16, uint64(p521Uint1(x35))) var x38 uint64 - x38, x37 = bits.Mul64(arg1[6], (arg2[5] * 0x2)) var x39 uint64 + x38, x39 = bits.Add64(x17, x14, uint64(p521Uint1(x37))) var x40 uint64 - x40, x39 = bits.Mul64(arg1[6], (arg2[4] * 0x2)) var x41 uint64 + x40, x41 = bits.Add64(x15, x12, uint64(p521Uint1(x39))) var x42 uint64 - x42, x41 = bits.Mul64(arg1[6], (arg2[3] * 0x2)) var x43 uint64 - var x44 uint64 - x44, x43 = bits.Mul64(arg1[5], (arg2[8] * 0x2)) + x42, x43 = bits.Add64(x13, x10, uint64(p521Uint1(x41))) + x44 := (uint64(p521Uint1(x43)) + x11) var x45 uint64 var x46 uint64 - x46, x45 = bits.Mul64(arg1[5], (arg2[7] * 0x2)) + x46, x45 = bits.Mul64(x26, 0x1ff) var x47 uint64 var x48 uint64 - x48, x47 = bits.Mul64(arg1[5], (arg2[6] * 0x2)) + x48, x47 = bits.Mul64(x26, 0xffffffffffffffff) var x49 uint64 var x50 uint64 - x50, x49 = bits.Mul64(arg1[5], (arg2[5] * 0x2)) + x50, x49 = bits.Mul64(x26, 0xffffffffffffffff) var x51 uint64 var x52 uint64 - x52, x51 = bits.Mul64(arg1[5], (arg2[4] * 0x2)) + x52, x51 = bits.Mul64(x26, 0xffffffffffffffff) var x53 uint64 var x54 uint64 - x54, x53 = bits.Mul64(arg1[4], (arg2[8] * 0x2)) + x54, x53 = bits.Mul64(x26, 0xffffffffffffffff) var x55 uint64 var x56 uint64 - x56, x55 = bits.Mul64(arg1[4], (arg2[7] * 0x2)) + x56, x55 = bits.Mul64(x26, 0xffffffffffffffff) var x57 uint64 var x58 uint64 - x58, x57 = bits.Mul64(arg1[4], (arg2[6] * 0x2)) + x58, x57 = bits.Mul64(x26, 0xffffffffffffffff) var x59 uint64 var x60 uint64 - x60, x59 = bits.Mul64(arg1[4], (arg2[5] * 0x2)) + x60, x59 = bits.Mul64(x26, 0xffffffffffffffff) var x61 uint64 var x62 uint64 - x62, x61 = bits.Mul64(arg1[3], (arg2[8] * 0x2)) + x62, x61 = bits.Mul64(x26, 0xffffffffffffffff) var x63 uint64 var x64 uint64 - x64, x63 = bits.Mul64(arg1[3], (arg2[7] * 0x2)) + x63, x64 = bits.Add64(x62, x59, uint64(0x0)) var x65 uint64 var x66 uint64 - x66, x65 = bits.Mul64(arg1[3], (arg2[6] * 0x2)) + x65, x66 = bits.Add64(x60, x57, uint64(p521Uint1(x64))) var x67 uint64 var x68 uint64 - x68, x67 = bits.Mul64(arg1[2], (arg2[8] * 0x2)) + x67, x68 = bits.Add64(x58, x55, uint64(p521Uint1(x66))) var x69 uint64 var x70 uint64 - x70, x69 = bits.Mul64(arg1[2], (arg2[7] * 0x2)) + x69, x70 = bits.Add64(x56, x53, uint64(p521Uint1(x68))) var x71 uint64 var x72 uint64 - x72, x71 = bits.Mul64(arg1[1], (arg2[8] * 0x2)) + x71, x72 = bits.Add64(x54, x51, uint64(p521Uint1(x70))) var x73 uint64 var x74 uint64 - x74, x73 = bits.Mul64(arg1[8], arg2[0]) + x73, x74 = bits.Add64(x52, x49, uint64(p521Uint1(x72))) var x75 uint64 var x76 uint64 - x76, x75 = bits.Mul64(arg1[7], arg2[1]) + x75, x76 = bits.Add64(x50, x47, uint64(p521Uint1(x74))) var x77 uint64 var x78 uint64 - x78, x77 = bits.Mul64(arg1[7], arg2[0]) - var x79 uint64 - var x80 uint64 - x80, x79 = bits.Mul64(arg1[6], arg2[2]) + x77, x78 = bits.Add64(x48, x45, uint64(p521Uint1(x76))) + x79 := (uint64(p521Uint1(x78)) + x46) var x81 uint64 + _, x81 = bits.Add64(x26, x61, uint64(0x0)) var x82 uint64 - x82, x81 = bits.Mul64(arg1[6], arg2[1]) var x83 uint64 + x82, x83 = bits.Add64(x28, x63, uint64(p521Uint1(x81))) var x84 uint64 - x84, x83 = bits.Mul64(arg1[6], arg2[0]) var x85 uint64 + x84, x85 = bits.Add64(x30, x65, uint64(p521Uint1(x83))) var x86 uint64 - x86, x85 = bits.Mul64(arg1[5], arg2[3]) var x87 uint64 + x86, x87 = bits.Add64(x32, x67, uint64(p521Uint1(x85))) var x88 uint64 - x88, x87 = bits.Mul64(arg1[5], arg2[2]) var x89 uint64 + x88, x89 = bits.Add64(x34, x69, uint64(p521Uint1(x87))) var x90 uint64 - x90, x89 = bits.Mul64(arg1[5], arg2[1]) var x91 uint64 + x90, x91 = bits.Add64(x36, x71, uint64(p521Uint1(x89))) var x92 uint64 - x92, x91 = bits.Mul64(arg1[5], arg2[0]) var x93 uint64 + x92, x93 = bits.Add64(x38, x73, uint64(p521Uint1(x91))) var x94 uint64 - x94, x93 = bits.Mul64(arg1[4], arg2[4]) var x95 uint64 + x94, x95 = bits.Add64(x40, x75, uint64(p521Uint1(x93))) var x96 uint64 - x96, x95 = bits.Mul64(arg1[4], arg2[3]) var x97 uint64 + x96, x97 = bits.Add64(x42, x77, uint64(p521Uint1(x95))) var x98 uint64 - x98, x97 = bits.Mul64(arg1[4], arg2[2]) var x99 uint64 + x98, x99 = bits.Add64(x44, x79, uint64(p521Uint1(x97))) var x100 uint64 - x100, x99 = bits.Mul64(arg1[4], arg2[1]) var x101 uint64 + x101, x100 = bits.Mul64(x1, arg2[8]) var x102 uint64 - x102, x101 = bits.Mul64(arg1[4], arg2[0]) var x103 uint64 + x103, x102 = bits.Mul64(x1, arg2[7]) var x104 uint64 - x104, x103 = bits.Mul64(arg1[3], arg2[5]) var x105 uint64 + x105, x104 = bits.Mul64(x1, arg2[6]) var x106 uint64 - x106, x105 = bits.Mul64(arg1[3], arg2[4]) var x107 uint64 + x107, x106 = bits.Mul64(x1, arg2[5]) var x108 uint64 - x108, x107 = bits.Mul64(arg1[3], arg2[3]) var x109 uint64 + x109, x108 = bits.Mul64(x1, arg2[4]) var x110 uint64 - x110, x109 = bits.Mul64(arg1[3], arg2[2]) var x111 uint64 + x111, x110 = bits.Mul64(x1, arg2[3]) var x112 uint64 - x112, x111 = bits.Mul64(arg1[3], arg2[1]) var x113 uint64 + x113, x112 = bits.Mul64(x1, arg2[2]) var x114 uint64 - x114, x113 = bits.Mul64(arg1[3], arg2[0]) var x115 uint64 + x115, x114 = bits.Mul64(x1, arg2[1]) var x116 uint64 - x116, x115 = bits.Mul64(arg1[2], arg2[6]) var x117 uint64 + x117, x116 = bits.Mul64(x1, arg2[0]) var x118 uint64 - x118, x117 = bits.Mul64(arg1[2], arg2[5]) var x119 uint64 + x118, x119 = bits.Add64(x117, x114, uint64(0x0)) var x120 uint64 - x120, x119 = bits.Mul64(arg1[2], arg2[4]) var x121 uint64 + x120, x121 = bits.Add64(x115, x112, uint64(p521Uint1(x119))) var x122 uint64 - x122, x121 = bits.Mul64(arg1[2], arg2[3]) var x123 uint64 + x122, x123 = bits.Add64(x113, x110, uint64(p521Uint1(x121))) var x124 uint64 - x124, x123 = bits.Mul64(arg1[2], arg2[2]) var x125 uint64 + x124, x125 = bits.Add64(x111, x108, uint64(p521Uint1(x123))) var x126 uint64 - x126, x125 = bits.Mul64(arg1[2], arg2[1]) var x127 uint64 + x126, x127 = bits.Add64(x109, x106, uint64(p521Uint1(x125))) var x128 uint64 - x128, x127 = bits.Mul64(arg1[2], arg2[0]) var x129 uint64 + x128, x129 = bits.Add64(x107, x104, uint64(p521Uint1(x127))) var x130 uint64 - x130, x129 = bits.Mul64(arg1[1], arg2[7]) var x131 uint64 + x130, x131 = bits.Add64(x105, x102, uint64(p521Uint1(x129))) var x132 uint64 - x132, x131 = bits.Mul64(arg1[1], arg2[6]) var x133 uint64 - var x134 uint64 - x134, x133 = bits.Mul64(arg1[1], arg2[5]) + x132, x133 = bits.Add64(x103, x100, uint64(p521Uint1(x131))) + x134 := (uint64(p521Uint1(x133)) + x101) var x135 uint64 var x136 uint64 - x136, x135 = bits.Mul64(arg1[1], arg2[4]) + x135, x136 = bits.Add64(x82, x116, uint64(0x0)) var x137 uint64 var x138 uint64 - x138, x137 = bits.Mul64(arg1[1], arg2[3]) + x137, x138 = bits.Add64(x84, x118, uint64(p521Uint1(x136))) var x139 uint64 var x140 uint64 - x140, x139 = bits.Mul64(arg1[1], arg2[2]) + x139, x140 = bits.Add64(x86, x120, uint64(p521Uint1(x138))) var x141 uint64 var x142 uint64 - x142, x141 = bits.Mul64(arg1[1], arg2[1]) + x141, x142 = bits.Add64(x88, x122, uint64(p521Uint1(x140))) var x143 uint64 var x144 uint64 - x144, x143 = bits.Mul64(arg1[1], arg2[0]) + x143, x144 = bits.Add64(x90, x124, uint64(p521Uint1(x142))) var x145 uint64 var x146 uint64 - x146, x145 = bits.Mul64(arg1[0], arg2[8]) + x145, x146 = bits.Add64(x92, x126, uint64(p521Uint1(x144))) var x147 uint64 var x148 uint64 - x148, x147 = bits.Mul64(arg1[0], arg2[7]) + x147, x148 = bits.Add64(x94, x128, uint64(p521Uint1(x146))) var x149 uint64 var x150 uint64 - x150, x149 = bits.Mul64(arg1[0], arg2[6]) + x149, x150 = bits.Add64(x96, x130, uint64(p521Uint1(x148))) var x151 uint64 var x152 uint64 - x152, x151 = bits.Mul64(arg1[0], arg2[5]) + x151, x152 = bits.Add64(x98, x132, uint64(p521Uint1(x150))) var x153 uint64 var x154 uint64 - x154, x153 = bits.Mul64(arg1[0], arg2[4]) + x153, x154 = bits.Add64(uint64(p521Uint1(x99)), x134, uint64(p521Uint1(x152))) var x155 uint64 var x156 uint64 - x156, x155 = bits.Mul64(arg1[0], arg2[3]) + x156, x155 = bits.Mul64(x135, 0x1ff) var x157 uint64 var x158 uint64 - x158, x157 = bits.Mul64(arg1[0], arg2[2]) + x158, x157 = bits.Mul64(x135, 0xffffffffffffffff) var x159 uint64 var x160 uint64 - x160, x159 = bits.Mul64(arg1[0], arg2[1]) + x160, x159 = bits.Mul64(x135, 0xffffffffffffffff) var x161 uint64 var x162 uint64 - x162, x161 = bits.Mul64(arg1[0], arg2[0]) + x162, x161 = bits.Mul64(x135, 0xffffffffffffffff) var x163 uint64 - var x164 p521Uint1 - x163, x164 = p521AddcarryxU64(x29, x15, 0x0) + var x164 uint64 + x164, x163 = bits.Mul64(x135, 0xffffffffffffffff) var x165 uint64 - x165, _ = p521AddcarryxU64(x30, x16, x164) + var x166 uint64 + x166, x165 = bits.Mul64(x135, 0xffffffffffffffff) var x167 uint64 - var x168 p521Uint1 - x167, x168 = p521AddcarryxU64(x41, x163, 0x0) + var x168 uint64 + x168, x167 = bits.Mul64(x135, 0xffffffffffffffff) var x169 uint64 - x169, _ = p521AddcarryxU64(x42, x165, x168) + var x170 uint64 + x170, x169 = bits.Mul64(x135, 0xffffffffffffffff) var x171 uint64 - var x172 p521Uint1 - x171, x172 = p521AddcarryxU64(x51, x167, 0x0) + var x172 uint64 + x172, x171 = bits.Mul64(x135, 0xffffffffffffffff) var x173 uint64 - x173, _ = p521AddcarryxU64(x52, x169, x172) + var x174 uint64 + x173, x174 = bits.Add64(x172, x169, uint64(0x0)) var x175 uint64 - var x176 p521Uint1 - x175, x176 = p521AddcarryxU64(x59, x171, 0x0) + var x176 uint64 + x175, x176 = bits.Add64(x170, x167, uint64(p521Uint1(x174))) var x177 uint64 - x177, _ = p521AddcarryxU64(x60, x173, x176) + var x178 uint64 + x177, x178 = bits.Add64(x168, x165, uint64(p521Uint1(x176))) var x179 uint64 - var x180 p521Uint1 - x179, x180 = p521AddcarryxU64(x65, x175, 0x0) + var x180 uint64 + x179, x180 = bits.Add64(x166, x163, uint64(p521Uint1(x178))) var x181 uint64 - x181, _ = p521AddcarryxU64(x66, x177, x180) + var x182 uint64 + x181, x182 = bits.Add64(x164, x161, uint64(p521Uint1(x180))) var x183 uint64 - var x184 p521Uint1 - x183, x184 = p521AddcarryxU64(x69, x179, 0x0) + var x184 uint64 + x183, x184 = bits.Add64(x162, x159, uint64(p521Uint1(x182))) var x185 uint64 - x185, _ = p521AddcarryxU64(x70, x181, x184) + var x186 uint64 + x185, x186 = bits.Add64(x160, x157, uint64(p521Uint1(x184))) var x187 uint64 - var x188 p521Uint1 - x187, x188 = p521AddcarryxU64(x71, x183, 0x0) - var x189 uint64 - x189, _ = p521AddcarryxU64(x72, x185, x188) + var x188 uint64 + x187, x188 = bits.Add64(x158, x155, uint64(p521Uint1(x186))) + x189 := (uint64(p521Uint1(x188)) + x156) var x191 uint64 - var x192 p521Uint1 - x191, x192 = p521AddcarryxU64(x161, x187, 0x0) + _, x191 = bits.Add64(x135, x171, uint64(0x0)) + var x192 uint64 var x193 uint64 - x193, _ = p521AddcarryxU64(x162, x189, x192) - x195 := ((x191 >> 58) | ((x193 << 6) & 0xffffffffffffffff)) - x196 := (x193 >> 58) - x197 := (x191 & 0x3ffffffffffffff) + x192, x193 = bits.Add64(x137, x173, uint64(p521Uint1(x191))) + var x194 uint64 + var x195 uint64 + x194, x195 = bits.Add64(x139, x175, uint64(p521Uint1(x193))) + var x196 uint64 + var x197 uint64 + x196, x197 = bits.Add64(x141, x177, uint64(p521Uint1(x195))) var x198 uint64 - var x199 p521Uint1 - x198, x199 = p521AddcarryxU64(x75, x73, 0x0) + var x199 uint64 + x198, x199 = bits.Add64(x143, x179, uint64(p521Uint1(x197))) var x200 uint64 - x200, _ = p521AddcarryxU64(x76, x74, x199) + var x201 uint64 + x200, x201 = bits.Add64(x145, x181, uint64(p521Uint1(x199))) var x202 uint64 - var x203 p521Uint1 - x202, x203 = p521AddcarryxU64(x79, x198, 0x0) + var x203 uint64 + x202, x203 = bits.Add64(x147, x183, uint64(p521Uint1(x201))) var x204 uint64 - x204, _ = p521AddcarryxU64(x80, x200, x203) + var x205 uint64 + x204, x205 = bits.Add64(x149, x185, uint64(p521Uint1(x203))) var x206 uint64 - var x207 p521Uint1 - x206, x207 = p521AddcarryxU64(x85, x202, 0x0) + var x207 uint64 + x206, x207 = bits.Add64(x151, x187, uint64(p521Uint1(x205))) var x208 uint64 - x208, _ = p521AddcarryxU64(x86, x204, x207) - var x210 uint64 - var x211 p521Uint1 - x210, x211 = p521AddcarryxU64(x93, x206, 0x0) + var x209 uint64 + x208, x209 = bits.Add64(x153, x189, uint64(p521Uint1(x207))) + x210 := (uint64(p521Uint1(x209)) + uint64(p521Uint1(x154))) + var x211 uint64 var x212 uint64 - x212, _ = p521AddcarryxU64(x94, x208, x211) + x212, x211 = bits.Mul64(x2, arg2[8]) + var x213 uint64 var x214 uint64 - var x215 p521Uint1 - x214, x215 = p521AddcarryxU64(x103, x210, 0x0) + x214, x213 = bits.Mul64(x2, arg2[7]) + var x215 uint64 var x216 uint64 - x216, _ = p521AddcarryxU64(x104, x212, x215) + x216, x215 = bits.Mul64(x2, arg2[6]) + var x217 uint64 var x218 uint64 - var x219 p521Uint1 - x218, x219 = p521AddcarryxU64(x115, x214, 0x0) + x218, x217 = bits.Mul64(x2, arg2[5]) + var x219 uint64 var x220 uint64 - x220, _ = p521AddcarryxU64(x116, x216, x219) + x220, x219 = bits.Mul64(x2, arg2[4]) + var x221 uint64 var x222 uint64 - var x223 p521Uint1 - x222, x223 = p521AddcarryxU64(x129, x218, 0x0) + x222, x221 = bits.Mul64(x2, arg2[3]) + var x223 uint64 var x224 uint64 - x224, _ = p521AddcarryxU64(x130, x220, x223) + x224, x223 = bits.Mul64(x2, arg2[2]) + var x225 uint64 var x226 uint64 - var x227 p521Uint1 - x226, x227 = p521AddcarryxU64(x145, x222, 0x0) + x226, x225 = bits.Mul64(x2, arg2[1]) + var x227 uint64 var x228 uint64 - x228, _ = p521AddcarryxU64(x146, x224, x227) + x228, x227 = bits.Mul64(x2, arg2[0]) + var x229 uint64 var x230 uint64 - var x231 p521Uint1 - x230, x231 = p521AddcarryxU64(x77, x1, 0x0) + x229, x230 = bits.Add64(x228, x225, uint64(0x0)) + var x231 uint64 var x232 uint64 - x232, _ = p521AddcarryxU64(x78, x2, x231) + x231, x232 = bits.Add64(x226, x223, uint64(p521Uint1(x230))) + var x233 uint64 var x234 uint64 - var x235 p521Uint1 - x234, x235 = p521AddcarryxU64(x81, x230, 0x0) + x233, x234 = bits.Add64(x224, x221, uint64(p521Uint1(x232))) + var x235 uint64 var x236 uint64 - x236, _ = p521AddcarryxU64(x82, x232, x235) + x235, x236 = bits.Add64(x222, x219, uint64(p521Uint1(x234))) + var x237 uint64 var x238 uint64 - var x239 p521Uint1 - x238, x239 = p521AddcarryxU64(x87, x234, 0x0) + x237, x238 = bits.Add64(x220, x217, uint64(p521Uint1(x236))) + var x239 uint64 var x240 uint64 - x240, _ = p521AddcarryxU64(x88, x236, x239) + x239, x240 = bits.Add64(x218, x215, uint64(p521Uint1(x238))) + var x241 uint64 var x242 uint64 - var x243 p521Uint1 - x242, x243 = p521AddcarryxU64(x95, x238, 0x0) + x241, x242 = bits.Add64(x216, x213, uint64(p521Uint1(x240))) + var x243 uint64 var x244 uint64 - x244, _ = p521AddcarryxU64(x96, x240, x243) + x243, x244 = bits.Add64(x214, x211, uint64(p521Uint1(x242))) + x245 := (uint64(p521Uint1(x244)) + x212) var x246 uint64 - var x247 p521Uint1 - x246, x247 = p521AddcarryxU64(x105, x242, 0x0) + var x247 uint64 + x246, x247 = bits.Add64(x192, x227, uint64(0x0)) var x248 uint64 - x248, _ = p521AddcarryxU64(x106, x244, x247) + var x249 uint64 + x248, x249 = bits.Add64(x194, x229, uint64(p521Uint1(x247))) var x250 uint64 - var x251 p521Uint1 - x250, x251 = p521AddcarryxU64(x117, x246, 0x0) + var x251 uint64 + x250, x251 = bits.Add64(x196, x231, uint64(p521Uint1(x249))) var x252 uint64 - x252, _ = p521AddcarryxU64(x118, x248, x251) + var x253 uint64 + x252, x253 = bits.Add64(x198, x233, uint64(p521Uint1(x251))) var x254 uint64 - var x255 p521Uint1 - x254, x255 = p521AddcarryxU64(x131, x250, 0x0) + var x255 uint64 + x254, x255 = bits.Add64(x200, x235, uint64(p521Uint1(x253))) var x256 uint64 - x256, _ = p521AddcarryxU64(x132, x252, x255) + var x257 uint64 + x256, x257 = bits.Add64(x202, x237, uint64(p521Uint1(x255))) var x258 uint64 - var x259 p521Uint1 - x258, x259 = p521AddcarryxU64(x147, x254, 0x0) + var x259 uint64 + x258, x259 = bits.Add64(x204, x239, uint64(p521Uint1(x257))) var x260 uint64 - x260, _ = p521AddcarryxU64(x148, x256, x259) + var x261 uint64 + x260, x261 = bits.Add64(x206, x241, uint64(p521Uint1(x259))) var x262 uint64 - var x263 p521Uint1 - x262, x263 = p521AddcarryxU64(x17, x3, 0x0) + var x263 uint64 + x262, x263 = bits.Add64(x208, x243, uint64(p521Uint1(x261))) var x264 uint64 - x264, _ = p521AddcarryxU64(x18, x4, x263) + var x265 uint64 + x264, x265 = bits.Add64(x210, x245, uint64(p521Uint1(x263))) var x266 uint64 - var x267 p521Uint1 - x266, x267 = p521AddcarryxU64(x83, x262, 0x0) + var x267 uint64 + x267, x266 = bits.Mul64(x246, 0x1ff) var x268 uint64 - x268, _ = p521AddcarryxU64(x84, x264, x267) + var x269 uint64 + x269, x268 = bits.Mul64(x246, 0xffffffffffffffff) var x270 uint64 - var x271 p521Uint1 - x270, x271 = p521AddcarryxU64(x89, x266, 0x0) + var x271 uint64 + x271, x270 = bits.Mul64(x246, 0xffffffffffffffff) var x272 uint64 - x272, _ = p521AddcarryxU64(x90, x268, x271) + var x273 uint64 + x273, x272 = bits.Mul64(x246, 0xffffffffffffffff) var x274 uint64 - var x275 p521Uint1 - x274, x275 = p521AddcarryxU64(x97, x270, 0x0) + var x275 uint64 + x275, x274 = bits.Mul64(x246, 0xffffffffffffffff) var x276 uint64 - x276, _ = p521AddcarryxU64(x98, x272, x275) + var x277 uint64 + x277, x276 = bits.Mul64(x246, 0xffffffffffffffff) var x278 uint64 - var x279 p521Uint1 - x278, x279 = p521AddcarryxU64(x107, x274, 0x0) + var x279 uint64 + x279, x278 = bits.Mul64(x246, 0xffffffffffffffff) var x280 uint64 - x280, _ = p521AddcarryxU64(x108, x276, x279) + var x281 uint64 + x281, x280 = bits.Mul64(x246, 0xffffffffffffffff) var x282 uint64 - var x283 p521Uint1 - x282, x283 = p521AddcarryxU64(x119, x278, 0x0) + var x283 uint64 + x283, x282 = bits.Mul64(x246, 0xffffffffffffffff) var x284 uint64 - x284, _ = p521AddcarryxU64(x120, x280, x283) + var x285 uint64 + x284, x285 = bits.Add64(x283, x280, uint64(0x0)) var x286 uint64 - var x287 p521Uint1 - x286, x287 = p521AddcarryxU64(x133, x282, 0x0) + var x287 uint64 + x286, x287 = bits.Add64(x281, x278, uint64(p521Uint1(x285))) var x288 uint64 - x288, _ = p521AddcarryxU64(x134, x284, x287) + var x289 uint64 + x288, x289 = bits.Add64(x279, x276, uint64(p521Uint1(x287))) var x290 uint64 - var x291 p521Uint1 - x290, x291 = p521AddcarryxU64(x149, x286, 0x0) + var x291 uint64 + x290, x291 = bits.Add64(x277, x274, uint64(p521Uint1(x289))) var x292 uint64 - x292, _ = p521AddcarryxU64(x150, x288, x291) + var x293 uint64 + x292, x293 = bits.Add64(x275, x272, uint64(p521Uint1(x291))) var x294 uint64 - var x295 p521Uint1 - x294, x295 = p521AddcarryxU64(x19, x5, 0x0) + var x295 uint64 + x294, x295 = bits.Add64(x273, x270, uint64(p521Uint1(x293))) var x296 uint64 - x296, _ = p521AddcarryxU64(x20, x6, x295) + var x297 uint64 + x296, x297 = bits.Add64(x271, x268, uint64(p521Uint1(x295))) var x298 uint64 - var x299 p521Uint1 - x298, x299 = p521AddcarryxU64(x31, x294, 0x0) - var x300 uint64 - x300, _ = p521AddcarryxU64(x32, x296, x299) + var x299 uint64 + x298, x299 = bits.Add64(x269, x266, uint64(p521Uint1(x297))) + x300 := (uint64(p521Uint1(x299)) + x267) var x302 uint64 - var x303 p521Uint1 - x302, x303 = p521AddcarryxU64(x91, x298, 0x0) + _, x302 = bits.Add64(x246, x282, uint64(0x0)) + var x303 uint64 var x304 uint64 - x304, _ = p521AddcarryxU64(x92, x300, x303) + x303, x304 = bits.Add64(x248, x284, uint64(p521Uint1(x302))) + var x305 uint64 var x306 uint64 - var x307 p521Uint1 - x306, x307 = p521AddcarryxU64(x99, x302, 0x0) + x305, x306 = bits.Add64(x250, x286, uint64(p521Uint1(x304))) + var x307 uint64 var x308 uint64 - x308, _ = p521AddcarryxU64(x100, x304, x307) + x307, x308 = bits.Add64(x252, x288, uint64(p521Uint1(x306))) + var x309 uint64 var x310 uint64 - var x311 p521Uint1 - x310, x311 = p521AddcarryxU64(x109, x306, 0x0) + x309, x310 = bits.Add64(x254, x290, uint64(p521Uint1(x308))) + var x311 uint64 var x312 uint64 - x312, _ = p521AddcarryxU64(x110, x308, x311) + x311, x312 = bits.Add64(x256, x292, uint64(p521Uint1(x310))) + var x313 uint64 var x314 uint64 - var x315 p521Uint1 - x314, x315 = p521AddcarryxU64(x121, x310, 0x0) + x313, x314 = bits.Add64(x258, x294, uint64(p521Uint1(x312))) + var x315 uint64 var x316 uint64 - x316, _ = p521AddcarryxU64(x122, x312, x315) + x315, x316 = bits.Add64(x260, x296, uint64(p521Uint1(x314))) + var x317 uint64 var x318 uint64 - var x319 p521Uint1 - x318, x319 = p521AddcarryxU64(x135, x314, 0x0) + x317, x318 = bits.Add64(x262, x298, uint64(p521Uint1(x316))) + var x319 uint64 var x320 uint64 - x320, _ = p521AddcarryxU64(x136, x316, x319) + x319, x320 = bits.Add64(x264, x300, uint64(p521Uint1(x318))) + x321 := (uint64(p521Uint1(x320)) + uint64(p521Uint1(x265))) var x322 uint64 - var x323 p521Uint1 - x322, x323 = p521AddcarryxU64(x151, x318, 0x0) + var x323 uint64 + x323, x322 = bits.Mul64(x3, arg2[8]) var x324 uint64 - x324, _ = p521AddcarryxU64(x152, x320, x323) + var x325 uint64 + x325, x324 = bits.Mul64(x3, arg2[7]) var x326 uint64 - var x327 p521Uint1 - x326, x327 = p521AddcarryxU64(x21, x7, 0x0) + var x327 uint64 + x327, x326 = bits.Mul64(x3, arg2[6]) var x328 uint64 - x328, _ = p521AddcarryxU64(x22, x8, x327) + var x329 uint64 + x329, x328 = bits.Mul64(x3, arg2[5]) var x330 uint64 - var x331 p521Uint1 - x330, x331 = p521AddcarryxU64(x33, x326, 0x0) + var x331 uint64 + x331, x330 = bits.Mul64(x3, arg2[4]) var x332 uint64 - x332, _ = p521AddcarryxU64(x34, x328, x331) + var x333 uint64 + x333, x332 = bits.Mul64(x3, arg2[3]) var x334 uint64 - var x335 p521Uint1 - x334, x335 = p521AddcarryxU64(x43, x330, 0x0) + var x335 uint64 + x335, x334 = bits.Mul64(x3, arg2[2]) var x336 uint64 - x336, _ = p521AddcarryxU64(x44, x332, x335) + var x337 uint64 + x337, x336 = bits.Mul64(x3, arg2[1]) var x338 uint64 - var x339 p521Uint1 - x338, x339 = p521AddcarryxU64(x101, x334, 0x0) + var x339 uint64 + x339, x338 = bits.Mul64(x3, arg2[0]) var x340 uint64 - x340, _ = p521AddcarryxU64(x102, x336, x339) + var x341 uint64 + x340, x341 = bits.Add64(x339, x336, uint64(0x0)) var x342 uint64 - var x343 p521Uint1 - x342, x343 = p521AddcarryxU64(x111, x338, 0x0) + var x343 uint64 + x342, x343 = bits.Add64(x337, x334, uint64(p521Uint1(x341))) var x344 uint64 - x344, _ = p521AddcarryxU64(x112, x340, x343) + var x345 uint64 + x344, x345 = bits.Add64(x335, x332, uint64(p521Uint1(x343))) var x346 uint64 - var x347 p521Uint1 - x346, x347 = p521AddcarryxU64(x123, x342, 0x0) + var x347 uint64 + x346, x347 = bits.Add64(x333, x330, uint64(p521Uint1(x345))) var x348 uint64 - x348, _ = p521AddcarryxU64(x124, x344, x347) + var x349 uint64 + x348, x349 = bits.Add64(x331, x328, uint64(p521Uint1(x347))) var x350 uint64 - var x351 p521Uint1 - x350, x351 = p521AddcarryxU64(x137, x346, 0x0) + var x351 uint64 + x350, x351 = bits.Add64(x329, x326, uint64(p521Uint1(x349))) var x352 uint64 - x352, _ = p521AddcarryxU64(x138, x348, x351) + var x353 uint64 + x352, x353 = bits.Add64(x327, x324, uint64(p521Uint1(x351))) var x354 uint64 - var x355 p521Uint1 - x354, x355 = p521AddcarryxU64(x153, x350, 0x0) - var x356 uint64 - x356, _ = p521AddcarryxU64(x154, x352, x355) + var x355 uint64 + x354, x355 = bits.Add64(x325, x322, uint64(p521Uint1(x353))) + x356 := (uint64(p521Uint1(x355)) + x323) + var x357 uint64 var x358 uint64 - var x359 p521Uint1 - x358, x359 = p521AddcarryxU64(x23, x9, 0x0) + x357, x358 = bits.Add64(x303, x338, uint64(0x0)) + var x359 uint64 var x360 uint64 - x360, _ = p521AddcarryxU64(x24, x10, x359) + x359, x360 = bits.Add64(x305, x340, uint64(p521Uint1(x358))) + var x361 uint64 var x362 uint64 - var x363 p521Uint1 - x362, x363 = p521AddcarryxU64(x35, x358, 0x0) + x361, x362 = bits.Add64(x307, x342, uint64(p521Uint1(x360))) + var x363 uint64 var x364 uint64 - x364, _ = p521AddcarryxU64(x36, x360, x363) + x363, x364 = bits.Add64(x309, x344, uint64(p521Uint1(x362))) + var x365 uint64 var x366 uint64 - var x367 p521Uint1 - x366, x367 = p521AddcarryxU64(x45, x362, 0x0) + x365, x366 = bits.Add64(x311, x346, uint64(p521Uint1(x364))) + var x367 uint64 var x368 uint64 - x368, _ = p521AddcarryxU64(x46, x364, x367) + x367, x368 = bits.Add64(x313, x348, uint64(p521Uint1(x366))) + var x369 uint64 var x370 uint64 - var x371 p521Uint1 - x370, x371 = p521AddcarryxU64(x53, x366, 0x0) + x369, x370 = bits.Add64(x315, x350, uint64(p521Uint1(x368))) + var x371 uint64 var x372 uint64 - x372, _ = p521AddcarryxU64(x54, x368, x371) + x371, x372 = bits.Add64(x317, x352, uint64(p521Uint1(x370))) + var x373 uint64 var x374 uint64 - var x375 p521Uint1 - x374, x375 = p521AddcarryxU64(x113, x370, 0x0) + x373, x374 = bits.Add64(x319, x354, uint64(p521Uint1(x372))) + var x375 uint64 var x376 uint64 - x376, _ = p521AddcarryxU64(x114, x372, x375) + x375, x376 = bits.Add64(x321, x356, uint64(p521Uint1(x374))) + var x377 uint64 var x378 uint64 - var x379 p521Uint1 - x378, x379 = p521AddcarryxU64(x125, x374, 0x0) + x378, x377 = bits.Mul64(x357, 0x1ff) + var x379 uint64 var x380 uint64 - x380, _ = p521AddcarryxU64(x126, x376, x379) + x380, x379 = bits.Mul64(x357, 0xffffffffffffffff) + var x381 uint64 var x382 uint64 - var x383 p521Uint1 - x382, x383 = p521AddcarryxU64(x139, x378, 0x0) + x382, x381 = bits.Mul64(x357, 0xffffffffffffffff) + var x383 uint64 var x384 uint64 - x384, _ = p521AddcarryxU64(x140, x380, x383) + x384, x383 = bits.Mul64(x357, 0xffffffffffffffff) + var x385 uint64 var x386 uint64 - var x387 p521Uint1 - x386, x387 = p521AddcarryxU64(x155, x382, 0x0) + x386, x385 = bits.Mul64(x357, 0xffffffffffffffff) + var x387 uint64 var x388 uint64 - x388, _ = p521AddcarryxU64(x156, x384, x387) + x388, x387 = bits.Mul64(x357, 0xffffffffffffffff) + var x389 uint64 var x390 uint64 - var x391 p521Uint1 - x390, x391 = p521AddcarryxU64(x25, x11, 0x0) + x390, x389 = bits.Mul64(x357, 0xffffffffffffffff) + var x391 uint64 var x392 uint64 - x392, _ = p521AddcarryxU64(x26, x12, x391) + x392, x391 = bits.Mul64(x357, 0xffffffffffffffff) + var x393 uint64 var x394 uint64 - var x395 p521Uint1 - x394, x395 = p521AddcarryxU64(x37, x390, 0x0) + x394, x393 = bits.Mul64(x357, 0xffffffffffffffff) + var x395 uint64 var x396 uint64 - x396, _ = p521AddcarryxU64(x38, x392, x395) + x395, x396 = bits.Add64(x394, x391, uint64(0x0)) + var x397 uint64 var x398 uint64 - var x399 p521Uint1 - x398, x399 = p521AddcarryxU64(x47, x394, 0x0) + x397, x398 = bits.Add64(x392, x389, uint64(p521Uint1(x396))) + var x399 uint64 var x400 uint64 - x400, _ = p521AddcarryxU64(x48, x396, x399) + x399, x400 = bits.Add64(x390, x387, uint64(p521Uint1(x398))) + var x401 uint64 var x402 uint64 - var x403 p521Uint1 - x402, x403 = p521AddcarryxU64(x55, x398, 0x0) + x401, x402 = bits.Add64(x388, x385, uint64(p521Uint1(x400))) + var x403 uint64 var x404 uint64 - x404, _ = p521AddcarryxU64(x56, x400, x403) + x403, x404 = bits.Add64(x386, x383, uint64(p521Uint1(x402))) + var x405 uint64 var x406 uint64 - var x407 p521Uint1 - x406, x407 = p521AddcarryxU64(x61, x402, 0x0) + x405, x406 = bits.Add64(x384, x381, uint64(p521Uint1(x404))) + var x407 uint64 var x408 uint64 - x408, _ = p521AddcarryxU64(x62, x404, x407) + x407, x408 = bits.Add64(x382, x379, uint64(p521Uint1(x406))) + var x409 uint64 var x410 uint64 - var x411 p521Uint1 - x410, x411 = p521AddcarryxU64(x127, x406, 0x0) - var x412 uint64 - x412, _ = p521AddcarryxU64(x128, x408, x411) + x409, x410 = bits.Add64(x380, x377, uint64(p521Uint1(x408))) + x411 := (uint64(p521Uint1(x410)) + x378) + var x413 uint64 + _, x413 = bits.Add64(x357, x393, uint64(0x0)) var x414 uint64 - var x415 p521Uint1 - x414, x415 = p521AddcarryxU64(x141, x410, 0x0) + var x415 uint64 + x414, x415 = bits.Add64(x359, x395, uint64(p521Uint1(x413))) var x416 uint64 - x416, _ = p521AddcarryxU64(x142, x412, x415) + var x417 uint64 + x416, x417 = bits.Add64(x361, x397, uint64(p521Uint1(x415))) var x418 uint64 - var x419 p521Uint1 - x418, x419 = p521AddcarryxU64(x157, x414, 0x0) + var x419 uint64 + x418, x419 = bits.Add64(x363, x399, uint64(p521Uint1(x417))) var x420 uint64 - x420, _ = p521AddcarryxU64(x158, x416, x419) + var x421 uint64 + x420, x421 = bits.Add64(x365, x401, uint64(p521Uint1(x419))) var x422 uint64 - var x423 p521Uint1 - x422, x423 = p521AddcarryxU64(x27, x13, 0x0) + var x423 uint64 + x422, x423 = bits.Add64(x367, x403, uint64(p521Uint1(x421))) var x424 uint64 - x424, _ = p521AddcarryxU64(x28, x14, x423) + var x425 uint64 + x424, x425 = bits.Add64(x369, x405, uint64(p521Uint1(x423))) var x426 uint64 - var x427 p521Uint1 - x426, x427 = p521AddcarryxU64(x39, x422, 0x0) + var x427 uint64 + x426, x427 = bits.Add64(x371, x407, uint64(p521Uint1(x425))) var x428 uint64 - x428, _ = p521AddcarryxU64(x40, x424, x427) + var x429 uint64 + x428, x429 = bits.Add64(x373, x409, uint64(p521Uint1(x427))) var x430 uint64 - var x431 p521Uint1 - x430, x431 = p521AddcarryxU64(x49, x426, 0x0) - var x432 uint64 - x432, _ = p521AddcarryxU64(x50, x428, x431) + var x431 uint64 + x430, x431 = bits.Add64(x375, x411, uint64(p521Uint1(x429))) + x432 := (uint64(p521Uint1(x431)) + uint64(p521Uint1(x376))) + var x433 uint64 var x434 uint64 - var x435 p521Uint1 - x434, x435 = p521AddcarryxU64(x57, x430, 0x0) + x434, x433 = bits.Mul64(x4, arg2[8]) + var x435 uint64 var x436 uint64 - x436, _ = p521AddcarryxU64(x58, x432, x435) + x436, x435 = bits.Mul64(x4, arg2[7]) + var x437 uint64 var x438 uint64 - var x439 p521Uint1 - x438, x439 = p521AddcarryxU64(x63, x434, 0x0) + x438, x437 = bits.Mul64(x4, arg2[6]) + var x439 uint64 var x440 uint64 - x440, _ = p521AddcarryxU64(x64, x436, x439) + x440, x439 = bits.Mul64(x4, arg2[5]) + var x441 uint64 var x442 uint64 - var x443 p521Uint1 - x442, x443 = p521AddcarryxU64(x67, x438, 0x0) + x442, x441 = bits.Mul64(x4, arg2[4]) + var x443 uint64 var x444 uint64 - x444, _ = p521AddcarryxU64(x68, x440, x443) + x444, x443 = bits.Mul64(x4, arg2[3]) + var x445 uint64 var x446 uint64 - var x447 p521Uint1 - x446, x447 = p521AddcarryxU64(x143, x442, 0x0) + x446, x445 = bits.Mul64(x4, arg2[2]) + var x447 uint64 var x448 uint64 - x448, _ = p521AddcarryxU64(x144, x444, x447) + x448, x447 = bits.Mul64(x4, arg2[1]) + var x449 uint64 var x450 uint64 - var x451 p521Uint1 - x450, x451 = p521AddcarryxU64(x159, x446, 0x0) + x450, x449 = bits.Mul64(x4, arg2[0]) + var x451 uint64 var x452 uint64 - x452, _ = p521AddcarryxU64(x160, x448, x451) + x451, x452 = bits.Add64(x450, x447, uint64(0x0)) + var x453 uint64 var x454 uint64 - var x455 p521Uint1 - x454, x455 = p521AddcarryxU64(x195, x450, 0x0) + x453, x454 = bits.Add64(x448, x445, uint64(p521Uint1(x452))) + var x455 uint64 var x456 uint64 - x456, _ = p521AddcarryxU64(x196, x452, x455) - x458 := ((x454 >> 58) | ((x456 << 6) & 0xffffffffffffffff)) - x459 := (x456 >> 58) - x460 := (x454 & 0x3ffffffffffffff) + x455, x456 = bits.Add64(x446, x443, uint64(p521Uint1(x454))) + var x457 uint64 + var x458 uint64 + x457, x458 = bits.Add64(x444, x441, uint64(p521Uint1(x456))) + var x459 uint64 + var x460 uint64 + x459, x460 = bits.Add64(x442, x439, uint64(p521Uint1(x458))) var x461 uint64 - var x462 p521Uint1 - x461, x462 = p521AddcarryxU64(x458, x418, 0x0) + var x462 uint64 + x461, x462 = bits.Add64(x440, x437, uint64(p521Uint1(x460))) var x463 uint64 - x463, _ = p521AddcarryxU64(x459, x420, x462) - x465 := ((x461 >> 58) | ((x463 << 6) & 0xffffffffffffffff)) - x466 := (x463 >> 58) - x467 := (x461 & 0x3ffffffffffffff) + var x464 uint64 + x463, x464 = bits.Add64(x438, x435, uint64(p521Uint1(x462))) + var x465 uint64 + var x466 uint64 + x465, x466 = bits.Add64(x436, x433, uint64(p521Uint1(x464))) + x467 := (uint64(p521Uint1(x466)) + x434) var x468 uint64 - var x469 p521Uint1 - x468, x469 = p521AddcarryxU64(x465, x386, 0x0) + var x469 uint64 + x468, x469 = bits.Add64(x414, x449, uint64(0x0)) var x470 uint64 - x470, _ = p521AddcarryxU64(x466, x388, x469) - x472 := ((x468 >> 58) | ((x470 << 6) & 0xffffffffffffffff)) - x473 := (x470 >> 58) - x474 := (x468 & 0x3ffffffffffffff) + var x471 uint64 + x470, x471 = bits.Add64(x416, x451, uint64(p521Uint1(x469))) + var x472 uint64 + var x473 uint64 + x472, x473 = bits.Add64(x418, x453, uint64(p521Uint1(x471))) + var x474 uint64 var x475 uint64 - var x476 p521Uint1 - x475, x476 = p521AddcarryxU64(x472, x354, 0x0) + x474, x475 = bits.Add64(x420, x455, uint64(p521Uint1(x473))) + var x476 uint64 var x477 uint64 - x477, _ = p521AddcarryxU64(x473, x356, x476) - x479 := ((x475 >> 58) | ((x477 << 6) & 0xffffffffffffffff)) - x480 := (x477 >> 58) - x481 := (x475 & 0x3ffffffffffffff) + x476, x477 = bits.Add64(x422, x457, uint64(p521Uint1(x475))) + var x478 uint64 + var x479 uint64 + x478, x479 = bits.Add64(x424, x459, uint64(p521Uint1(x477))) + var x480 uint64 + var x481 uint64 + x480, x481 = bits.Add64(x426, x461, uint64(p521Uint1(x479))) var x482 uint64 - var x483 p521Uint1 - x482, x483 = p521AddcarryxU64(x479, x322, 0x0) + var x483 uint64 + x482, x483 = bits.Add64(x428, x463, uint64(p521Uint1(x481))) var x484 uint64 - x484, _ = p521AddcarryxU64(x480, x324, x483) - x486 := ((x482 >> 58) | ((x484 << 6) & 0xffffffffffffffff)) - x487 := (x484 >> 58) - x488 := (x482 & 0x3ffffffffffffff) + var x485 uint64 + x484, x485 = bits.Add64(x430, x465, uint64(p521Uint1(x483))) + var x486 uint64 + var x487 uint64 + x486, x487 = bits.Add64(x432, x467, uint64(p521Uint1(x485))) + var x488 uint64 var x489 uint64 - var x490 p521Uint1 - x489, x490 = p521AddcarryxU64(x486, x290, 0x0) + x489, x488 = bits.Mul64(x468, 0x1ff) + var x490 uint64 var x491 uint64 - x491, _ = p521AddcarryxU64(x487, x292, x490) - x493 := ((x489 >> 58) | ((x491 << 6) & 0xffffffffffffffff)) - x494 := (x491 >> 58) - x495 := (x489 & 0x3ffffffffffffff) + x491, x490 = bits.Mul64(x468, 0xffffffffffffffff) + var x492 uint64 + var x493 uint64 + x493, x492 = bits.Mul64(x468, 0xffffffffffffffff) + var x494 uint64 + var x495 uint64 + x495, x494 = bits.Mul64(x468, 0xffffffffffffffff) var x496 uint64 - var x497 p521Uint1 - x496, x497 = p521AddcarryxU64(x493, x258, 0x0) + var x497 uint64 + x497, x496 = bits.Mul64(x468, 0xffffffffffffffff) var x498 uint64 - x498, _ = p521AddcarryxU64(x494, x260, x497) - x500 := ((x496 >> 58) | ((x498 << 6) & 0xffffffffffffffff)) - x501 := (x498 >> 58) - x502 := (x496 & 0x3ffffffffffffff) + var x499 uint64 + x499, x498 = bits.Mul64(x468, 0xffffffffffffffff) + var x500 uint64 + var x501 uint64 + x501, x500 = bits.Mul64(x468, 0xffffffffffffffff) + var x502 uint64 var x503 uint64 - var x504 p521Uint1 - x503, x504 = p521AddcarryxU64(x500, x226, 0x0) + x503, x502 = bits.Mul64(x468, 0xffffffffffffffff) + var x504 uint64 var x505 uint64 - x505, _ = p521AddcarryxU64(x501, x228, x504) - x507 := ((x503 >> 57) | ((x505 << 7) & 0xffffffffffffffff)) - x508 := (x505 >> 57) - x509 := (x503 & 0x1ffffffffffffff) + x505, x504 = bits.Mul64(x468, 0xffffffffffffffff) + var x506 uint64 + var x507 uint64 + x506, x507 = bits.Add64(x505, x502, uint64(0x0)) + var x508 uint64 + var x509 uint64 + x508, x509 = bits.Add64(x503, x500, uint64(p521Uint1(x507))) var x510 uint64 - var x511 p521Uint1 - x510, x511 = p521AddcarryxU64(x197, x507, 0x0) - x512 := (uint64(x511) + x508) - x513 := ((x510 >> 58) | ((x512 << 6) & 0xffffffffffffffff)) - x514 := (x510 & 0x3ffffffffffffff) - x515 := (x513 + x460) - x516 := p521Uint1((x515 >> 58)) - x517 := (x515 & 0x3ffffffffffffff) - x518 := (uint64(x516) + x467) - out1[0] = x514 - out1[1] = x517 - out1[2] = x518 - out1[3] = x474 - out1[4] = x481 - out1[5] = x488 - out1[6] = x495 - out1[7] = x502 - out1[8] = x509 + var x511 uint64 + x510, x511 = bits.Add64(x501, x498, uint64(p521Uint1(x509))) + var x512 uint64 + var x513 uint64 + x512, x513 = bits.Add64(x499, x496, uint64(p521Uint1(x511))) + var x514 uint64 + var x515 uint64 + x514, x515 = bits.Add64(x497, x494, uint64(p521Uint1(x513))) + var x516 uint64 + var x517 uint64 + x516, x517 = bits.Add64(x495, x492, uint64(p521Uint1(x515))) + var x518 uint64 + var x519 uint64 + x518, x519 = bits.Add64(x493, x490, uint64(p521Uint1(x517))) + var x520 uint64 + var x521 uint64 + x520, x521 = bits.Add64(x491, x488, uint64(p521Uint1(x519))) + x522 := (uint64(p521Uint1(x521)) + x489) + var x524 uint64 + _, x524 = bits.Add64(x468, x504, uint64(0x0)) + var x525 uint64 + var x526 uint64 + x525, x526 = bits.Add64(x470, x506, uint64(p521Uint1(x524))) + var x527 uint64 + var x528 uint64 + x527, x528 = bits.Add64(x472, x508, uint64(p521Uint1(x526))) + var x529 uint64 + var x530 uint64 + x529, x530 = bits.Add64(x474, x510, uint64(p521Uint1(x528))) + var x531 uint64 + var x532 uint64 + x531, x532 = bits.Add64(x476, x512, uint64(p521Uint1(x530))) + var x533 uint64 + var x534 uint64 + x533, x534 = bits.Add64(x478, x514, uint64(p521Uint1(x532))) + var x535 uint64 + var x536 uint64 + x535, x536 = bits.Add64(x480, x516, uint64(p521Uint1(x534))) + var x537 uint64 + var x538 uint64 + x537, x538 = bits.Add64(x482, x518, uint64(p521Uint1(x536))) + var x539 uint64 + var x540 uint64 + x539, x540 = bits.Add64(x484, x520, uint64(p521Uint1(x538))) + var x541 uint64 + var x542 uint64 + x541, x542 = bits.Add64(x486, x522, uint64(p521Uint1(x540))) + x543 := (uint64(p521Uint1(x542)) + uint64(p521Uint1(x487))) + var x544 uint64 + var x545 uint64 + x545, x544 = bits.Mul64(x5, arg2[8]) + var x546 uint64 + var x547 uint64 + x547, x546 = bits.Mul64(x5, arg2[7]) + var x548 uint64 + var x549 uint64 + x549, x548 = bits.Mul64(x5, arg2[6]) + var x550 uint64 + var x551 uint64 + x551, x550 = bits.Mul64(x5, arg2[5]) + var x552 uint64 + var x553 uint64 + x553, x552 = bits.Mul64(x5, arg2[4]) + var x554 uint64 + var x555 uint64 + x555, x554 = bits.Mul64(x5, arg2[3]) + var x556 uint64 + var x557 uint64 + x557, x556 = bits.Mul64(x5, arg2[2]) + var x558 uint64 + var x559 uint64 + x559, x558 = bits.Mul64(x5, arg2[1]) + var x560 uint64 + var x561 uint64 + x561, x560 = bits.Mul64(x5, arg2[0]) + var x562 uint64 + var x563 uint64 + x562, x563 = bits.Add64(x561, x558, uint64(0x0)) + var x564 uint64 + var x565 uint64 + x564, x565 = bits.Add64(x559, x556, uint64(p521Uint1(x563))) + var x566 uint64 + var x567 uint64 + x566, x567 = bits.Add64(x557, x554, uint64(p521Uint1(x565))) + var x568 uint64 + var x569 uint64 + x568, x569 = bits.Add64(x555, x552, uint64(p521Uint1(x567))) + var x570 uint64 + var x571 uint64 + x570, x571 = bits.Add64(x553, x550, uint64(p521Uint1(x569))) + var x572 uint64 + var x573 uint64 + x572, x573 = bits.Add64(x551, x548, uint64(p521Uint1(x571))) + var x574 uint64 + var x575 uint64 + x574, x575 = bits.Add64(x549, x546, uint64(p521Uint1(x573))) + var x576 uint64 + var x577 uint64 + x576, x577 = bits.Add64(x547, x544, uint64(p521Uint1(x575))) + x578 := (uint64(p521Uint1(x577)) + x545) + var x579 uint64 + var x580 uint64 + x579, x580 = bits.Add64(x525, x560, uint64(0x0)) + var x581 uint64 + var x582 uint64 + x581, x582 = bits.Add64(x527, x562, uint64(p521Uint1(x580))) + var x583 uint64 + var x584 uint64 + x583, x584 = bits.Add64(x529, x564, uint64(p521Uint1(x582))) + var x585 uint64 + var x586 uint64 + x585, x586 = bits.Add64(x531, x566, uint64(p521Uint1(x584))) + var x587 uint64 + var x588 uint64 + x587, x588 = bits.Add64(x533, x568, uint64(p521Uint1(x586))) + var x589 uint64 + var x590 uint64 + x589, x590 = bits.Add64(x535, x570, uint64(p521Uint1(x588))) + var x591 uint64 + var x592 uint64 + x591, x592 = bits.Add64(x537, x572, uint64(p521Uint1(x590))) + var x593 uint64 + var x594 uint64 + x593, x594 = bits.Add64(x539, x574, uint64(p521Uint1(x592))) + var x595 uint64 + var x596 uint64 + x595, x596 = bits.Add64(x541, x576, uint64(p521Uint1(x594))) + var x597 uint64 + var x598 uint64 + x597, x598 = bits.Add64(x543, x578, uint64(p521Uint1(x596))) + var x599 uint64 + var x600 uint64 + x600, x599 = bits.Mul64(x579, 0x1ff) + var x601 uint64 + var x602 uint64 + x602, x601 = bits.Mul64(x579, 0xffffffffffffffff) + var x603 uint64 + var x604 uint64 + x604, x603 = bits.Mul64(x579, 0xffffffffffffffff) + var x605 uint64 + var x606 uint64 + x606, x605 = bits.Mul64(x579, 0xffffffffffffffff) + var x607 uint64 + var x608 uint64 + x608, x607 = bits.Mul64(x579, 0xffffffffffffffff) + var x609 uint64 + var x610 uint64 + x610, x609 = bits.Mul64(x579, 0xffffffffffffffff) + var x611 uint64 + var x612 uint64 + x612, x611 = bits.Mul64(x579, 0xffffffffffffffff) + var x613 uint64 + var x614 uint64 + x614, x613 = bits.Mul64(x579, 0xffffffffffffffff) + var x615 uint64 + var x616 uint64 + x616, x615 = bits.Mul64(x579, 0xffffffffffffffff) + var x617 uint64 + var x618 uint64 + x617, x618 = bits.Add64(x616, x613, uint64(0x0)) + var x619 uint64 + var x620 uint64 + x619, x620 = bits.Add64(x614, x611, uint64(p521Uint1(x618))) + var x621 uint64 + var x622 uint64 + x621, x622 = bits.Add64(x612, x609, uint64(p521Uint1(x620))) + var x623 uint64 + var x624 uint64 + x623, x624 = bits.Add64(x610, x607, uint64(p521Uint1(x622))) + var x625 uint64 + var x626 uint64 + x625, x626 = bits.Add64(x608, x605, uint64(p521Uint1(x624))) + var x627 uint64 + var x628 uint64 + x627, x628 = bits.Add64(x606, x603, uint64(p521Uint1(x626))) + var x629 uint64 + var x630 uint64 + x629, x630 = bits.Add64(x604, x601, uint64(p521Uint1(x628))) + var x631 uint64 + var x632 uint64 + x631, x632 = bits.Add64(x602, x599, uint64(p521Uint1(x630))) + x633 := (uint64(p521Uint1(x632)) + x600) + var x635 uint64 + _, x635 = bits.Add64(x579, x615, uint64(0x0)) + var x636 uint64 + var x637 uint64 + x636, x637 = bits.Add64(x581, x617, uint64(p521Uint1(x635))) + var x638 uint64 + var x639 uint64 + x638, x639 = bits.Add64(x583, x619, uint64(p521Uint1(x637))) + var x640 uint64 + var x641 uint64 + x640, x641 = bits.Add64(x585, x621, uint64(p521Uint1(x639))) + var x642 uint64 + var x643 uint64 + x642, x643 = bits.Add64(x587, x623, uint64(p521Uint1(x641))) + var x644 uint64 + var x645 uint64 + x644, x645 = bits.Add64(x589, x625, uint64(p521Uint1(x643))) + var x646 uint64 + var x647 uint64 + x646, x647 = bits.Add64(x591, x627, uint64(p521Uint1(x645))) + var x648 uint64 + var x649 uint64 + x648, x649 = bits.Add64(x593, x629, uint64(p521Uint1(x647))) + var x650 uint64 + var x651 uint64 + x650, x651 = bits.Add64(x595, x631, uint64(p521Uint1(x649))) + var x652 uint64 + var x653 uint64 + x652, x653 = bits.Add64(x597, x633, uint64(p521Uint1(x651))) + x654 := (uint64(p521Uint1(x653)) + uint64(p521Uint1(x598))) + var x655 uint64 + var x656 uint64 + x656, x655 = bits.Mul64(x6, arg2[8]) + var x657 uint64 + var x658 uint64 + x658, x657 = bits.Mul64(x6, arg2[7]) + var x659 uint64 + var x660 uint64 + x660, x659 = bits.Mul64(x6, arg2[6]) + var x661 uint64 + var x662 uint64 + x662, x661 = bits.Mul64(x6, arg2[5]) + var x663 uint64 + var x664 uint64 + x664, x663 = bits.Mul64(x6, arg2[4]) + var x665 uint64 + var x666 uint64 + x666, x665 = bits.Mul64(x6, arg2[3]) + var x667 uint64 + var x668 uint64 + x668, x667 = bits.Mul64(x6, arg2[2]) + var x669 uint64 + var x670 uint64 + x670, x669 = bits.Mul64(x6, arg2[1]) + var x671 uint64 + var x672 uint64 + x672, x671 = bits.Mul64(x6, arg2[0]) + var x673 uint64 + var x674 uint64 + x673, x674 = bits.Add64(x672, x669, uint64(0x0)) + var x675 uint64 + var x676 uint64 + x675, x676 = bits.Add64(x670, x667, uint64(p521Uint1(x674))) + var x677 uint64 + var x678 uint64 + x677, x678 = bits.Add64(x668, x665, uint64(p521Uint1(x676))) + var x679 uint64 + var x680 uint64 + x679, x680 = bits.Add64(x666, x663, uint64(p521Uint1(x678))) + var x681 uint64 + var x682 uint64 + x681, x682 = bits.Add64(x664, x661, uint64(p521Uint1(x680))) + var x683 uint64 + var x684 uint64 + x683, x684 = bits.Add64(x662, x659, uint64(p521Uint1(x682))) + var x685 uint64 + var x686 uint64 + x685, x686 = bits.Add64(x660, x657, uint64(p521Uint1(x684))) + var x687 uint64 + var x688 uint64 + x687, x688 = bits.Add64(x658, x655, uint64(p521Uint1(x686))) + x689 := (uint64(p521Uint1(x688)) + x656) + var x690 uint64 + var x691 uint64 + x690, x691 = bits.Add64(x636, x671, uint64(0x0)) + var x692 uint64 + var x693 uint64 + x692, x693 = bits.Add64(x638, x673, uint64(p521Uint1(x691))) + var x694 uint64 + var x695 uint64 + x694, x695 = bits.Add64(x640, x675, uint64(p521Uint1(x693))) + var x696 uint64 + var x697 uint64 + x696, x697 = bits.Add64(x642, x677, uint64(p521Uint1(x695))) + var x698 uint64 + var x699 uint64 + x698, x699 = bits.Add64(x644, x679, uint64(p521Uint1(x697))) + var x700 uint64 + var x701 uint64 + x700, x701 = bits.Add64(x646, x681, uint64(p521Uint1(x699))) + var x702 uint64 + var x703 uint64 + x702, x703 = bits.Add64(x648, x683, uint64(p521Uint1(x701))) + var x704 uint64 + var x705 uint64 + x704, x705 = bits.Add64(x650, x685, uint64(p521Uint1(x703))) + var x706 uint64 + var x707 uint64 + x706, x707 = bits.Add64(x652, x687, uint64(p521Uint1(x705))) + var x708 uint64 + var x709 uint64 + x708, x709 = bits.Add64(x654, x689, uint64(p521Uint1(x707))) + var x710 uint64 + var x711 uint64 + x711, x710 = bits.Mul64(x690, 0x1ff) + var x712 uint64 + var x713 uint64 + x713, x712 = bits.Mul64(x690, 0xffffffffffffffff) + var x714 uint64 + var x715 uint64 + x715, x714 = bits.Mul64(x690, 0xffffffffffffffff) + var x716 uint64 + var x717 uint64 + x717, x716 = bits.Mul64(x690, 0xffffffffffffffff) + var x718 uint64 + var x719 uint64 + x719, x718 = bits.Mul64(x690, 0xffffffffffffffff) + var x720 uint64 + var x721 uint64 + x721, x720 = bits.Mul64(x690, 0xffffffffffffffff) + var x722 uint64 + var x723 uint64 + x723, x722 = bits.Mul64(x690, 0xffffffffffffffff) + var x724 uint64 + var x725 uint64 + x725, x724 = bits.Mul64(x690, 0xffffffffffffffff) + var x726 uint64 + var x727 uint64 + x727, x726 = bits.Mul64(x690, 0xffffffffffffffff) + var x728 uint64 + var x729 uint64 + x728, x729 = bits.Add64(x727, x724, uint64(0x0)) + var x730 uint64 + var x731 uint64 + x730, x731 = bits.Add64(x725, x722, uint64(p521Uint1(x729))) + var x732 uint64 + var x733 uint64 + x732, x733 = bits.Add64(x723, x720, uint64(p521Uint1(x731))) + var x734 uint64 + var x735 uint64 + x734, x735 = bits.Add64(x721, x718, uint64(p521Uint1(x733))) + var x736 uint64 + var x737 uint64 + x736, x737 = bits.Add64(x719, x716, uint64(p521Uint1(x735))) + var x738 uint64 + var x739 uint64 + x738, x739 = bits.Add64(x717, x714, uint64(p521Uint1(x737))) + var x740 uint64 + var x741 uint64 + x740, x741 = bits.Add64(x715, x712, uint64(p521Uint1(x739))) + var x742 uint64 + var x743 uint64 + x742, x743 = bits.Add64(x713, x710, uint64(p521Uint1(x741))) + x744 := (uint64(p521Uint1(x743)) + x711) + var x746 uint64 + _, x746 = bits.Add64(x690, x726, uint64(0x0)) + var x747 uint64 + var x748 uint64 + x747, x748 = bits.Add64(x692, x728, uint64(p521Uint1(x746))) + var x749 uint64 + var x750 uint64 + x749, x750 = bits.Add64(x694, x730, uint64(p521Uint1(x748))) + var x751 uint64 + var x752 uint64 + x751, x752 = bits.Add64(x696, x732, uint64(p521Uint1(x750))) + var x753 uint64 + var x754 uint64 + x753, x754 = bits.Add64(x698, x734, uint64(p521Uint1(x752))) + var x755 uint64 + var x756 uint64 + x755, x756 = bits.Add64(x700, x736, uint64(p521Uint1(x754))) + var x757 uint64 + var x758 uint64 + x757, x758 = bits.Add64(x702, x738, uint64(p521Uint1(x756))) + var x759 uint64 + var x760 uint64 + x759, x760 = bits.Add64(x704, x740, uint64(p521Uint1(x758))) + var x761 uint64 + var x762 uint64 + x761, x762 = bits.Add64(x706, x742, uint64(p521Uint1(x760))) + var x763 uint64 + var x764 uint64 + x763, x764 = bits.Add64(x708, x744, uint64(p521Uint1(x762))) + x765 := (uint64(p521Uint1(x764)) + uint64(p521Uint1(x709))) + var x766 uint64 + var x767 uint64 + x767, x766 = bits.Mul64(x7, arg2[8]) + var x768 uint64 + var x769 uint64 + x769, x768 = bits.Mul64(x7, arg2[7]) + var x770 uint64 + var x771 uint64 + x771, x770 = bits.Mul64(x7, arg2[6]) + var x772 uint64 + var x773 uint64 + x773, x772 = bits.Mul64(x7, arg2[5]) + var x774 uint64 + var x775 uint64 + x775, x774 = bits.Mul64(x7, arg2[4]) + var x776 uint64 + var x777 uint64 + x777, x776 = bits.Mul64(x7, arg2[3]) + var x778 uint64 + var x779 uint64 + x779, x778 = bits.Mul64(x7, arg2[2]) + var x780 uint64 + var x781 uint64 + x781, x780 = bits.Mul64(x7, arg2[1]) + var x782 uint64 + var x783 uint64 + x783, x782 = bits.Mul64(x7, arg2[0]) + var x784 uint64 + var x785 uint64 + x784, x785 = bits.Add64(x783, x780, uint64(0x0)) + var x786 uint64 + var x787 uint64 + x786, x787 = bits.Add64(x781, x778, uint64(p521Uint1(x785))) + var x788 uint64 + var x789 uint64 + x788, x789 = bits.Add64(x779, x776, uint64(p521Uint1(x787))) + var x790 uint64 + var x791 uint64 + x790, x791 = bits.Add64(x777, x774, uint64(p521Uint1(x789))) + var x792 uint64 + var x793 uint64 + x792, x793 = bits.Add64(x775, x772, uint64(p521Uint1(x791))) + var x794 uint64 + var x795 uint64 + x794, x795 = bits.Add64(x773, x770, uint64(p521Uint1(x793))) + var x796 uint64 + var x797 uint64 + x796, x797 = bits.Add64(x771, x768, uint64(p521Uint1(x795))) + var x798 uint64 + var x799 uint64 + x798, x799 = bits.Add64(x769, x766, uint64(p521Uint1(x797))) + x800 := (uint64(p521Uint1(x799)) + x767) + var x801 uint64 + var x802 uint64 + x801, x802 = bits.Add64(x747, x782, uint64(0x0)) + var x803 uint64 + var x804 uint64 + x803, x804 = bits.Add64(x749, x784, uint64(p521Uint1(x802))) + var x805 uint64 + var x806 uint64 + x805, x806 = bits.Add64(x751, x786, uint64(p521Uint1(x804))) + var x807 uint64 + var x808 uint64 + x807, x808 = bits.Add64(x753, x788, uint64(p521Uint1(x806))) + var x809 uint64 + var x810 uint64 + x809, x810 = bits.Add64(x755, x790, uint64(p521Uint1(x808))) + var x811 uint64 + var x812 uint64 + x811, x812 = bits.Add64(x757, x792, uint64(p521Uint1(x810))) + var x813 uint64 + var x814 uint64 + x813, x814 = bits.Add64(x759, x794, uint64(p521Uint1(x812))) + var x815 uint64 + var x816 uint64 + x815, x816 = bits.Add64(x761, x796, uint64(p521Uint1(x814))) + var x817 uint64 + var x818 uint64 + x817, x818 = bits.Add64(x763, x798, uint64(p521Uint1(x816))) + var x819 uint64 + var x820 uint64 + x819, x820 = bits.Add64(x765, x800, uint64(p521Uint1(x818))) + var x821 uint64 + var x822 uint64 + x822, x821 = bits.Mul64(x801, 0x1ff) + var x823 uint64 + var x824 uint64 + x824, x823 = bits.Mul64(x801, 0xffffffffffffffff) + var x825 uint64 + var x826 uint64 + x826, x825 = bits.Mul64(x801, 0xffffffffffffffff) + var x827 uint64 + var x828 uint64 + x828, x827 = bits.Mul64(x801, 0xffffffffffffffff) + var x829 uint64 + var x830 uint64 + x830, x829 = bits.Mul64(x801, 0xffffffffffffffff) + var x831 uint64 + var x832 uint64 + x832, x831 = bits.Mul64(x801, 0xffffffffffffffff) + var x833 uint64 + var x834 uint64 + x834, x833 = bits.Mul64(x801, 0xffffffffffffffff) + var x835 uint64 + var x836 uint64 + x836, x835 = bits.Mul64(x801, 0xffffffffffffffff) + var x837 uint64 + var x838 uint64 + x838, x837 = bits.Mul64(x801, 0xffffffffffffffff) + var x839 uint64 + var x840 uint64 + x839, x840 = bits.Add64(x838, x835, uint64(0x0)) + var x841 uint64 + var x842 uint64 + x841, x842 = bits.Add64(x836, x833, uint64(p521Uint1(x840))) + var x843 uint64 + var x844 uint64 + x843, x844 = bits.Add64(x834, x831, uint64(p521Uint1(x842))) + var x845 uint64 + var x846 uint64 + x845, x846 = bits.Add64(x832, x829, uint64(p521Uint1(x844))) + var x847 uint64 + var x848 uint64 + x847, x848 = bits.Add64(x830, x827, uint64(p521Uint1(x846))) + var x849 uint64 + var x850 uint64 + x849, x850 = bits.Add64(x828, x825, uint64(p521Uint1(x848))) + var x851 uint64 + var x852 uint64 + x851, x852 = bits.Add64(x826, x823, uint64(p521Uint1(x850))) + var x853 uint64 + var x854 uint64 + x853, x854 = bits.Add64(x824, x821, uint64(p521Uint1(x852))) + x855 := (uint64(p521Uint1(x854)) + x822) + var x857 uint64 + _, x857 = bits.Add64(x801, x837, uint64(0x0)) + var x858 uint64 + var x859 uint64 + x858, x859 = bits.Add64(x803, x839, uint64(p521Uint1(x857))) + var x860 uint64 + var x861 uint64 + x860, x861 = bits.Add64(x805, x841, uint64(p521Uint1(x859))) + var x862 uint64 + var x863 uint64 + x862, x863 = bits.Add64(x807, x843, uint64(p521Uint1(x861))) + var x864 uint64 + var x865 uint64 + x864, x865 = bits.Add64(x809, x845, uint64(p521Uint1(x863))) + var x866 uint64 + var x867 uint64 + x866, x867 = bits.Add64(x811, x847, uint64(p521Uint1(x865))) + var x868 uint64 + var x869 uint64 + x868, x869 = bits.Add64(x813, x849, uint64(p521Uint1(x867))) + var x870 uint64 + var x871 uint64 + x870, x871 = bits.Add64(x815, x851, uint64(p521Uint1(x869))) + var x872 uint64 + var x873 uint64 + x872, x873 = bits.Add64(x817, x853, uint64(p521Uint1(x871))) + var x874 uint64 + var x875 uint64 + x874, x875 = bits.Add64(x819, x855, uint64(p521Uint1(x873))) + x876 := (uint64(p521Uint1(x875)) + uint64(p521Uint1(x820))) + var x877 uint64 + var x878 uint64 + x878, x877 = bits.Mul64(x8, arg2[8]) + var x879 uint64 + var x880 uint64 + x880, x879 = bits.Mul64(x8, arg2[7]) + var x881 uint64 + var x882 uint64 + x882, x881 = bits.Mul64(x8, arg2[6]) + var x883 uint64 + var x884 uint64 + x884, x883 = bits.Mul64(x8, arg2[5]) + var x885 uint64 + var x886 uint64 + x886, x885 = bits.Mul64(x8, arg2[4]) + var x887 uint64 + var x888 uint64 + x888, x887 = bits.Mul64(x8, arg2[3]) + var x889 uint64 + var x890 uint64 + x890, x889 = bits.Mul64(x8, arg2[2]) + var x891 uint64 + var x892 uint64 + x892, x891 = bits.Mul64(x8, arg2[1]) + var x893 uint64 + var x894 uint64 + x894, x893 = bits.Mul64(x8, arg2[0]) + var x895 uint64 + var x896 uint64 + x895, x896 = bits.Add64(x894, x891, uint64(0x0)) + var x897 uint64 + var x898 uint64 + x897, x898 = bits.Add64(x892, x889, uint64(p521Uint1(x896))) + var x899 uint64 + var x900 uint64 + x899, x900 = bits.Add64(x890, x887, uint64(p521Uint1(x898))) + var x901 uint64 + var x902 uint64 + x901, x902 = bits.Add64(x888, x885, uint64(p521Uint1(x900))) + var x903 uint64 + var x904 uint64 + x903, x904 = bits.Add64(x886, x883, uint64(p521Uint1(x902))) + var x905 uint64 + var x906 uint64 + x905, x906 = bits.Add64(x884, x881, uint64(p521Uint1(x904))) + var x907 uint64 + var x908 uint64 + x907, x908 = bits.Add64(x882, x879, uint64(p521Uint1(x906))) + var x909 uint64 + var x910 uint64 + x909, x910 = bits.Add64(x880, x877, uint64(p521Uint1(x908))) + x911 := (uint64(p521Uint1(x910)) + x878) + var x912 uint64 + var x913 uint64 + x912, x913 = bits.Add64(x858, x893, uint64(0x0)) + var x914 uint64 + var x915 uint64 + x914, x915 = bits.Add64(x860, x895, uint64(p521Uint1(x913))) + var x916 uint64 + var x917 uint64 + x916, x917 = bits.Add64(x862, x897, uint64(p521Uint1(x915))) + var x918 uint64 + var x919 uint64 + x918, x919 = bits.Add64(x864, x899, uint64(p521Uint1(x917))) + var x920 uint64 + var x921 uint64 + x920, x921 = bits.Add64(x866, x901, uint64(p521Uint1(x919))) + var x922 uint64 + var x923 uint64 + x922, x923 = bits.Add64(x868, x903, uint64(p521Uint1(x921))) + var x924 uint64 + var x925 uint64 + x924, x925 = bits.Add64(x870, x905, uint64(p521Uint1(x923))) + var x926 uint64 + var x927 uint64 + x926, x927 = bits.Add64(x872, x907, uint64(p521Uint1(x925))) + var x928 uint64 + var x929 uint64 + x928, x929 = bits.Add64(x874, x909, uint64(p521Uint1(x927))) + var x930 uint64 + var x931 uint64 + x930, x931 = bits.Add64(x876, x911, uint64(p521Uint1(x929))) + var x932 uint64 + var x933 uint64 + x933, x932 = bits.Mul64(x912, 0x1ff) + var x934 uint64 + var x935 uint64 + x935, x934 = bits.Mul64(x912, 0xffffffffffffffff) + var x936 uint64 + var x937 uint64 + x937, x936 = bits.Mul64(x912, 0xffffffffffffffff) + var x938 uint64 + var x939 uint64 + x939, x938 = bits.Mul64(x912, 0xffffffffffffffff) + var x940 uint64 + var x941 uint64 + x941, x940 = bits.Mul64(x912, 0xffffffffffffffff) + var x942 uint64 + var x943 uint64 + x943, x942 = bits.Mul64(x912, 0xffffffffffffffff) + var x944 uint64 + var x945 uint64 + x945, x944 = bits.Mul64(x912, 0xffffffffffffffff) + var x946 uint64 + var x947 uint64 + x947, x946 = bits.Mul64(x912, 0xffffffffffffffff) + var x948 uint64 + var x949 uint64 + x949, x948 = bits.Mul64(x912, 0xffffffffffffffff) + var x950 uint64 + var x951 uint64 + x950, x951 = bits.Add64(x949, x946, uint64(0x0)) + var x952 uint64 + var x953 uint64 + x952, x953 = bits.Add64(x947, x944, uint64(p521Uint1(x951))) + var x954 uint64 + var x955 uint64 + x954, x955 = bits.Add64(x945, x942, uint64(p521Uint1(x953))) + var x956 uint64 + var x957 uint64 + x956, x957 = bits.Add64(x943, x940, uint64(p521Uint1(x955))) + var x958 uint64 + var x959 uint64 + x958, x959 = bits.Add64(x941, x938, uint64(p521Uint1(x957))) + var x960 uint64 + var x961 uint64 + x960, x961 = bits.Add64(x939, x936, uint64(p521Uint1(x959))) + var x962 uint64 + var x963 uint64 + x962, x963 = bits.Add64(x937, x934, uint64(p521Uint1(x961))) + var x964 uint64 + var x965 uint64 + x964, x965 = bits.Add64(x935, x932, uint64(p521Uint1(x963))) + x966 := (uint64(p521Uint1(x965)) + x933) + var x968 uint64 + _, x968 = bits.Add64(x912, x948, uint64(0x0)) + var x969 uint64 + var x970 uint64 + x969, x970 = bits.Add64(x914, x950, uint64(p521Uint1(x968))) + var x971 uint64 + var x972 uint64 + x971, x972 = bits.Add64(x916, x952, uint64(p521Uint1(x970))) + var x973 uint64 + var x974 uint64 + x973, x974 = bits.Add64(x918, x954, uint64(p521Uint1(x972))) + var x975 uint64 + var x976 uint64 + x975, x976 = bits.Add64(x920, x956, uint64(p521Uint1(x974))) + var x977 uint64 + var x978 uint64 + x977, x978 = bits.Add64(x922, x958, uint64(p521Uint1(x976))) + var x979 uint64 + var x980 uint64 + x979, x980 = bits.Add64(x924, x960, uint64(p521Uint1(x978))) + var x981 uint64 + var x982 uint64 + x981, x982 = bits.Add64(x926, x962, uint64(p521Uint1(x980))) + var x983 uint64 + var x984 uint64 + x983, x984 = bits.Add64(x928, x964, uint64(p521Uint1(x982))) + var x985 uint64 + var x986 uint64 + x985, x986 = bits.Add64(x930, x966, uint64(p521Uint1(x984))) + x987 := (uint64(p521Uint1(x986)) + uint64(p521Uint1(x931))) + var x988 uint64 + var x989 uint64 + x988, x989 = bits.Sub64(x969, 0xffffffffffffffff, uint64(0x0)) + var x990 uint64 + var x991 uint64 + x990, x991 = bits.Sub64(x971, 0xffffffffffffffff, uint64(p521Uint1(x989))) + var x992 uint64 + var x993 uint64 + x992, x993 = bits.Sub64(x973, 0xffffffffffffffff, uint64(p521Uint1(x991))) + var x994 uint64 + var x995 uint64 + x994, x995 = bits.Sub64(x975, 0xffffffffffffffff, uint64(p521Uint1(x993))) + var x996 uint64 + var x997 uint64 + x996, x997 = bits.Sub64(x977, 0xffffffffffffffff, uint64(p521Uint1(x995))) + var x998 uint64 + var x999 uint64 + x998, x999 = bits.Sub64(x979, 0xffffffffffffffff, uint64(p521Uint1(x997))) + var x1000 uint64 + var x1001 uint64 + x1000, x1001 = bits.Sub64(x981, 0xffffffffffffffff, uint64(p521Uint1(x999))) + var x1002 uint64 + var x1003 uint64 + x1002, x1003 = bits.Sub64(x983, 0xffffffffffffffff, uint64(p521Uint1(x1001))) + var x1004 uint64 + var x1005 uint64 + x1004, x1005 = bits.Sub64(x985, 0x1ff, uint64(p521Uint1(x1003))) + var x1007 uint64 + _, x1007 = bits.Sub64(x987, uint64(0x0), uint64(p521Uint1(x1005))) + var x1008 uint64 + p521CmovznzU64(&x1008, p521Uint1(x1007), x988, x969) + var x1009 uint64 + p521CmovznzU64(&x1009, p521Uint1(x1007), x990, x971) + var x1010 uint64 + p521CmovznzU64(&x1010, p521Uint1(x1007), x992, x973) + var x1011 uint64 + p521CmovznzU64(&x1011, p521Uint1(x1007), x994, x975) + var x1012 uint64 + p521CmovznzU64(&x1012, p521Uint1(x1007), x996, x977) + var x1013 uint64 + p521CmovznzU64(&x1013, p521Uint1(x1007), x998, x979) + var x1014 uint64 + p521CmovznzU64(&x1014, p521Uint1(x1007), x1000, x981) + var x1015 uint64 + p521CmovznzU64(&x1015, p521Uint1(x1007), x1002, x983) + var x1016 uint64 + p521CmovznzU64(&x1016, p521Uint1(x1007), x1004, x985) + out1[0] = x1008 + out1[1] = x1009 + out1[2] = x1010 + out1[3] = x1011 + out1[4] = x1012 + out1[5] = x1013 + out1[6] = x1014 + out1[7] = x1015 + out1[8] = x1016 } -// p521CarrySquare squares a field element and reduces the result. +// p521Square squares a field element in the Montgomery domain. // +// Preconditions: +// 0 ≤ eval arg1 < m // Postconditions: -// eval out1 mod m = (eval arg1 * eval arg1) mod m +// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg1)) mod m +// 0 ≤ eval out1 < m // -// Input Bounds: -// arg1: [[0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0x600000000000000]] -// Output Bounds: -// out1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]] -func p521CarrySquare(out1 *[9]uint64, arg1 *[9]uint64) { - x1 := arg1[8] - x2 := (x1 * 0x2) - x3 := (arg1[8] * 0x2) - x4 := arg1[7] - x5 := (x4 * 0x2) - x6 := (arg1[7] * 0x2) - x7 := arg1[6] - x8 := (x7 * 0x2) - x9 := (arg1[6] * 0x2) - x10 := arg1[5] - x11 := (x10 * 0x2) - x12 := (arg1[5] * 0x2) - x13 := (arg1[4] * 0x2) - x14 := (arg1[3] * 0x2) - x15 := (arg1[2] * 0x2) - x16 := (arg1[1] * 0x2) +func p521Square(out1 *p521MontgomeryDomainFieldElement, arg1 *p521MontgomeryDomainFieldElement) { + x1 := arg1[1] + x2 := arg1[2] + x3 := arg1[3] + x4 := arg1[4] + x5 := arg1[5] + x6 := arg1[6] + x7 := arg1[7] + x8 := arg1[8] + x9 := arg1[0] + var x10 uint64 + var x11 uint64 + x11, x10 = bits.Mul64(x9, arg1[8]) + var x12 uint64 + var x13 uint64 + x13, x12 = bits.Mul64(x9, arg1[7]) + var x14 uint64 + var x15 uint64 + x15, x14 = bits.Mul64(x9, arg1[6]) + var x16 uint64 var x17 uint64 + x17, x16 = bits.Mul64(x9, arg1[5]) var x18 uint64 - x18, x17 = bits.Mul64(arg1[8], (x1 * 0x2)) var x19 uint64 + x19, x18 = bits.Mul64(x9, arg1[4]) var x20 uint64 - x20, x19 = bits.Mul64(arg1[7], (x2 * 0x2)) var x21 uint64 + x21, x20 = bits.Mul64(x9, arg1[3]) var x22 uint64 - x22, x21 = bits.Mul64(arg1[7], (x4 * 0x2)) var x23 uint64 + x23, x22 = bits.Mul64(x9, arg1[2]) var x24 uint64 - x24, x23 = bits.Mul64(arg1[6], (x2 * 0x2)) var x25 uint64 + x25, x24 = bits.Mul64(x9, arg1[1]) var x26 uint64 - x26, x25 = bits.Mul64(arg1[6], (x5 * 0x2)) var x27 uint64 + x27, x26 = bits.Mul64(x9, arg1[0]) var x28 uint64 - x28, x27 = bits.Mul64(arg1[6], (x7 * 0x2)) var x29 uint64 + x28, x29 = bits.Add64(x27, x24, uint64(0x0)) var x30 uint64 - x30, x29 = bits.Mul64(arg1[5], (x2 * 0x2)) var x31 uint64 + x30, x31 = bits.Add64(x25, x22, uint64(p521Uint1(x29))) var x32 uint64 - x32, x31 = bits.Mul64(arg1[5], (x5 * 0x2)) var x33 uint64 + x32, x33 = bits.Add64(x23, x20, uint64(p521Uint1(x31))) var x34 uint64 - x34, x33 = bits.Mul64(arg1[5], (x8 * 0x2)) var x35 uint64 + x34, x35 = bits.Add64(x21, x18, uint64(p521Uint1(x33))) var x36 uint64 - x36, x35 = bits.Mul64(arg1[5], (x10 * 0x2)) var x37 uint64 + x36, x37 = bits.Add64(x19, x16, uint64(p521Uint1(x35))) var x38 uint64 - x38, x37 = bits.Mul64(arg1[4], (x2 * 0x2)) var x39 uint64 + x38, x39 = bits.Add64(x17, x14, uint64(p521Uint1(x37))) var x40 uint64 - x40, x39 = bits.Mul64(arg1[4], (x5 * 0x2)) var x41 uint64 + x40, x41 = bits.Add64(x15, x12, uint64(p521Uint1(x39))) var x42 uint64 - x42, x41 = bits.Mul64(arg1[4], (x8 * 0x2)) var x43 uint64 - var x44 uint64 - x44, x43 = bits.Mul64(arg1[4], (x11 * 0x2)) + x42, x43 = bits.Add64(x13, x10, uint64(p521Uint1(x41))) + x44 := (uint64(p521Uint1(x43)) + x11) var x45 uint64 var x46 uint64 - x46, x45 = bits.Mul64(arg1[4], arg1[4]) + x46, x45 = bits.Mul64(x26, 0x1ff) var x47 uint64 var x48 uint64 - x48, x47 = bits.Mul64(arg1[3], (x2 * 0x2)) + x48, x47 = bits.Mul64(x26, 0xffffffffffffffff) var x49 uint64 var x50 uint64 - x50, x49 = bits.Mul64(arg1[3], (x5 * 0x2)) + x50, x49 = bits.Mul64(x26, 0xffffffffffffffff) var x51 uint64 var x52 uint64 - x52, x51 = bits.Mul64(arg1[3], (x8 * 0x2)) + x52, x51 = bits.Mul64(x26, 0xffffffffffffffff) var x53 uint64 var x54 uint64 - x54, x53 = bits.Mul64(arg1[3], x12) + x54, x53 = bits.Mul64(x26, 0xffffffffffffffff) var x55 uint64 var x56 uint64 - x56, x55 = bits.Mul64(arg1[3], x13) + x56, x55 = bits.Mul64(x26, 0xffffffffffffffff) var x57 uint64 var x58 uint64 - x58, x57 = bits.Mul64(arg1[3], arg1[3]) + x58, x57 = bits.Mul64(x26, 0xffffffffffffffff) var x59 uint64 var x60 uint64 - x60, x59 = bits.Mul64(arg1[2], (x2 * 0x2)) + x60, x59 = bits.Mul64(x26, 0xffffffffffffffff) var x61 uint64 var x62 uint64 - x62, x61 = bits.Mul64(arg1[2], (x5 * 0x2)) + x62, x61 = bits.Mul64(x26, 0xffffffffffffffff) var x63 uint64 var x64 uint64 - x64, x63 = bits.Mul64(arg1[2], x9) + x63, x64 = bits.Add64(x62, x59, uint64(0x0)) var x65 uint64 var x66 uint64 - x66, x65 = bits.Mul64(arg1[2], x12) + x65, x66 = bits.Add64(x60, x57, uint64(p521Uint1(x64))) var x67 uint64 var x68 uint64 - x68, x67 = bits.Mul64(arg1[2], x13) + x67, x68 = bits.Add64(x58, x55, uint64(p521Uint1(x66))) var x69 uint64 var x70 uint64 - x70, x69 = bits.Mul64(arg1[2], x14) + x69, x70 = bits.Add64(x56, x53, uint64(p521Uint1(x68))) var x71 uint64 var x72 uint64 - x72, x71 = bits.Mul64(arg1[2], arg1[2]) + x71, x72 = bits.Add64(x54, x51, uint64(p521Uint1(x70))) var x73 uint64 var x74 uint64 - x74, x73 = bits.Mul64(arg1[1], (x2 * 0x2)) + x73, x74 = bits.Add64(x52, x49, uint64(p521Uint1(x72))) var x75 uint64 var x76 uint64 - x76, x75 = bits.Mul64(arg1[1], x6) + x75, x76 = bits.Add64(x50, x47, uint64(p521Uint1(x74))) var x77 uint64 var x78 uint64 - x78, x77 = bits.Mul64(arg1[1], x9) + x77, x78 = bits.Add64(x48, x45, uint64(p521Uint1(x76))) + x79 := (uint64(p521Uint1(x78)) + x46) + var x81 uint64 + _, x81 = bits.Add64(x26, x61, uint64(0x0)) + var x82 uint64 + var x83 uint64 + x82, x83 = bits.Add64(x28, x63, uint64(p521Uint1(x81))) + var x84 uint64 + var x85 uint64 + x84, x85 = bits.Add64(x30, x65, uint64(p521Uint1(x83))) + var x86 uint64 + var x87 uint64 + x86, x87 = bits.Add64(x32, x67, uint64(p521Uint1(x85))) + var x88 uint64 + var x89 uint64 + x88, x89 = bits.Add64(x34, x69, uint64(p521Uint1(x87))) + var x90 uint64 + var x91 uint64 + x90, x91 = bits.Add64(x36, x71, uint64(p521Uint1(x89))) + var x92 uint64 + var x93 uint64 + x92, x93 = bits.Add64(x38, x73, uint64(p521Uint1(x91))) + var x94 uint64 + var x95 uint64 + x94, x95 = bits.Add64(x40, x75, uint64(p521Uint1(x93))) + var x96 uint64 + var x97 uint64 + x96, x97 = bits.Add64(x42, x77, uint64(p521Uint1(x95))) + var x98 uint64 + var x99 uint64 + x98, x99 = bits.Add64(x44, x79, uint64(p521Uint1(x97))) + var x100 uint64 + var x101 uint64 + x101, x100 = bits.Mul64(x1, arg1[8]) + var x102 uint64 + var x103 uint64 + x103, x102 = bits.Mul64(x1, arg1[7]) + var x104 uint64 + var x105 uint64 + x105, x104 = bits.Mul64(x1, arg1[6]) + var x106 uint64 + var x107 uint64 + x107, x106 = bits.Mul64(x1, arg1[5]) + var x108 uint64 + var x109 uint64 + x109, x108 = bits.Mul64(x1, arg1[4]) + var x110 uint64 + var x111 uint64 + x111, x110 = bits.Mul64(x1, arg1[3]) + var x112 uint64 + var x113 uint64 + x113, x112 = bits.Mul64(x1, arg1[2]) + var x114 uint64 + var x115 uint64 + x115, x114 = bits.Mul64(x1, arg1[1]) + var x116 uint64 + var x117 uint64 + x117, x116 = bits.Mul64(x1, arg1[0]) + var x118 uint64 + var x119 uint64 + x118, x119 = bits.Add64(x117, x114, uint64(0x0)) + var x120 uint64 + var x121 uint64 + x120, x121 = bits.Add64(x115, x112, uint64(p521Uint1(x119))) + var x122 uint64 + var x123 uint64 + x122, x123 = bits.Add64(x113, x110, uint64(p521Uint1(x121))) + var x124 uint64 + var x125 uint64 + x124, x125 = bits.Add64(x111, x108, uint64(p521Uint1(x123))) + var x126 uint64 + var x127 uint64 + x126, x127 = bits.Add64(x109, x106, uint64(p521Uint1(x125))) + var x128 uint64 + var x129 uint64 + x128, x129 = bits.Add64(x107, x104, uint64(p521Uint1(x127))) + var x130 uint64 + var x131 uint64 + x130, x131 = bits.Add64(x105, x102, uint64(p521Uint1(x129))) + var x132 uint64 + var x133 uint64 + x132, x133 = bits.Add64(x103, x100, uint64(p521Uint1(x131))) + x134 := (uint64(p521Uint1(x133)) + x101) + var x135 uint64 + var x136 uint64 + x135, x136 = bits.Add64(x82, x116, uint64(0x0)) + var x137 uint64 + var x138 uint64 + x137, x138 = bits.Add64(x84, x118, uint64(p521Uint1(x136))) + var x139 uint64 + var x140 uint64 + x139, x140 = bits.Add64(x86, x120, uint64(p521Uint1(x138))) + var x141 uint64 + var x142 uint64 + x141, x142 = bits.Add64(x88, x122, uint64(p521Uint1(x140))) + var x143 uint64 + var x144 uint64 + x143, x144 = bits.Add64(x90, x124, uint64(p521Uint1(x142))) + var x145 uint64 + var x146 uint64 + x145, x146 = bits.Add64(x92, x126, uint64(p521Uint1(x144))) + var x147 uint64 + var x148 uint64 + x147, x148 = bits.Add64(x94, x128, uint64(p521Uint1(x146))) + var x149 uint64 + var x150 uint64 + x149, x150 = bits.Add64(x96, x130, uint64(p521Uint1(x148))) + var x151 uint64 + var x152 uint64 + x151, x152 = bits.Add64(x98, x132, uint64(p521Uint1(x150))) + var x153 uint64 + var x154 uint64 + x153, x154 = bits.Add64(uint64(p521Uint1(x99)), x134, uint64(p521Uint1(x152))) + var x155 uint64 + var x156 uint64 + x156, x155 = bits.Mul64(x135, 0x1ff) + var x157 uint64 + var x158 uint64 + x158, x157 = bits.Mul64(x135, 0xffffffffffffffff) + var x159 uint64 + var x160 uint64 + x160, x159 = bits.Mul64(x135, 0xffffffffffffffff) + var x161 uint64 + var x162 uint64 + x162, x161 = bits.Mul64(x135, 0xffffffffffffffff) + var x163 uint64 + var x164 uint64 + x164, x163 = bits.Mul64(x135, 0xffffffffffffffff) + var x165 uint64 + var x166 uint64 + x166, x165 = bits.Mul64(x135, 0xffffffffffffffff) + var x167 uint64 + var x168 uint64 + x168, x167 = bits.Mul64(x135, 0xffffffffffffffff) + var x169 uint64 + var x170 uint64 + x170, x169 = bits.Mul64(x135, 0xffffffffffffffff) + var x171 uint64 + var x172 uint64 + x172, x171 = bits.Mul64(x135, 0xffffffffffffffff) + var x173 uint64 + var x174 uint64 + x173, x174 = bits.Add64(x172, x169, uint64(0x0)) + var x175 uint64 + var x176 uint64 + x175, x176 = bits.Add64(x170, x167, uint64(p521Uint1(x174))) + var x177 uint64 + var x178 uint64 + x177, x178 = bits.Add64(x168, x165, uint64(p521Uint1(x176))) + var x179 uint64 + var x180 uint64 + x179, x180 = bits.Add64(x166, x163, uint64(p521Uint1(x178))) + var x181 uint64 + var x182 uint64 + x181, x182 = bits.Add64(x164, x161, uint64(p521Uint1(x180))) + var x183 uint64 + var x184 uint64 + x183, x184 = bits.Add64(x162, x159, uint64(p521Uint1(x182))) + var x185 uint64 + var x186 uint64 + x185, x186 = bits.Add64(x160, x157, uint64(p521Uint1(x184))) + var x187 uint64 + var x188 uint64 + x187, x188 = bits.Add64(x158, x155, uint64(p521Uint1(x186))) + x189 := (uint64(p521Uint1(x188)) + x156) + var x191 uint64 + _, x191 = bits.Add64(x135, x171, uint64(0x0)) + var x192 uint64 + var x193 uint64 + x192, x193 = bits.Add64(x137, x173, uint64(p521Uint1(x191))) + var x194 uint64 + var x195 uint64 + x194, x195 = bits.Add64(x139, x175, uint64(p521Uint1(x193))) + var x196 uint64 + var x197 uint64 + x196, x197 = bits.Add64(x141, x177, uint64(p521Uint1(x195))) + var x198 uint64 + var x199 uint64 + x198, x199 = bits.Add64(x143, x179, uint64(p521Uint1(x197))) + var x200 uint64 + var x201 uint64 + x200, x201 = bits.Add64(x145, x181, uint64(p521Uint1(x199))) + var x202 uint64 + var x203 uint64 + x202, x203 = bits.Add64(x147, x183, uint64(p521Uint1(x201))) + var x204 uint64 + var x205 uint64 + x204, x205 = bits.Add64(x149, x185, uint64(p521Uint1(x203))) + var x206 uint64 + var x207 uint64 + x206, x207 = bits.Add64(x151, x187, uint64(p521Uint1(x205))) + var x208 uint64 + var x209 uint64 + x208, x209 = bits.Add64(x153, x189, uint64(p521Uint1(x207))) + x210 := (uint64(p521Uint1(x209)) + uint64(p521Uint1(x154))) + var x211 uint64 + var x212 uint64 + x212, x211 = bits.Mul64(x2, arg1[8]) + var x213 uint64 + var x214 uint64 + x214, x213 = bits.Mul64(x2, arg1[7]) + var x215 uint64 + var x216 uint64 + x216, x215 = bits.Mul64(x2, arg1[6]) + var x217 uint64 + var x218 uint64 + x218, x217 = bits.Mul64(x2, arg1[5]) + var x219 uint64 + var x220 uint64 + x220, x219 = bits.Mul64(x2, arg1[4]) + var x221 uint64 + var x222 uint64 + x222, x221 = bits.Mul64(x2, arg1[3]) + var x223 uint64 + var x224 uint64 + x224, x223 = bits.Mul64(x2, arg1[2]) + var x225 uint64 + var x226 uint64 + x226, x225 = bits.Mul64(x2, arg1[1]) + var x227 uint64 + var x228 uint64 + x228, x227 = bits.Mul64(x2, arg1[0]) + var x229 uint64 + var x230 uint64 + x229, x230 = bits.Add64(x228, x225, uint64(0x0)) + var x231 uint64 + var x232 uint64 + x231, x232 = bits.Add64(x226, x223, uint64(p521Uint1(x230))) + var x233 uint64 + var x234 uint64 + x233, x234 = bits.Add64(x224, x221, uint64(p521Uint1(x232))) + var x235 uint64 + var x236 uint64 + x235, x236 = bits.Add64(x222, x219, uint64(p521Uint1(x234))) + var x237 uint64 + var x238 uint64 + x237, x238 = bits.Add64(x220, x217, uint64(p521Uint1(x236))) + var x239 uint64 + var x240 uint64 + x239, x240 = bits.Add64(x218, x215, uint64(p521Uint1(x238))) + var x241 uint64 + var x242 uint64 + x241, x242 = bits.Add64(x216, x213, uint64(p521Uint1(x240))) + var x243 uint64 + var x244 uint64 + x243, x244 = bits.Add64(x214, x211, uint64(p521Uint1(x242))) + x245 := (uint64(p521Uint1(x244)) + x212) + var x246 uint64 + var x247 uint64 + x246, x247 = bits.Add64(x192, x227, uint64(0x0)) + var x248 uint64 + var x249 uint64 + x248, x249 = bits.Add64(x194, x229, uint64(p521Uint1(x247))) + var x250 uint64 + var x251 uint64 + x250, x251 = bits.Add64(x196, x231, uint64(p521Uint1(x249))) + var x252 uint64 + var x253 uint64 + x252, x253 = bits.Add64(x198, x233, uint64(p521Uint1(x251))) + var x254 uint64 + var x255 uint64 + x254, x255 = bits.Add64(x200, x235, uint64(p521Uint1(x253))) + var x256 uint64 + var x257 uint64 + x256, x257 = bits.Add64(x202, x237, uint64(p521Uint1(x255))) + var x258 uint64 + var x259 uint64 + x258, x259 = bits.Add64(x204, x239, uint64(p521Uint1(x257))) + var x260 uint64 + var x261 uint64 + x260, x261 = bits.Add64(x206, x241, uint64(p521Uint1(x259))) + var x262 uint64 + var x263 uint64 + x262, x263 = bits.Add64(x208, x243, uint64(p521Uint1(x261))) + var x264 uint64 + var x265 uint64 + x264, x265 = bits.Add64(x210, x245, uint64(p521Uint1(x263))) + var x266 uint64 + var x267 uint64 + x267, x266 = bits.Mul64(x246, 0x1ff) + var x268 uint64 + var x269 uint64 + x269, x268 = bits.Mul64(x246, 0xffffffffffffffff) + var x270 uint64 + var x271 uint64 + x271, x270 = bits.Mul64(x246, 0xffffffffffffffff) + var x272 uint64 + var x273 uint64 + x273, x272 = bits.Mul64(x246, 0xffffffffffffffff) + var x274 uint64 + var x275 uint64 + x275, x274 = bits.Mul64(x246, 0xffffffffffffffff) + var x276 uint64 + var x277 uint64 + x277, x276 = bits.Mul64(x246, 0xffffffffffffffff) + var x278 uint64 + var x279 uint64 + x279, x278 = bits.Mul64(x246, 0xffffffffffffffff) + var x280 uint64 + var x281 uint64 + x281, x280 = bits.Mul64(x246, 0xffffffffffffffff) + var x282 uint64 + var x283 uint64 + x283, x282 = bits.Mul64(x246, 0xffffffffffffffff) + var x284 uint64 + var x285 uint64 + x284, x285 = bits.Add64(x283, x280, uint64(0x0)) + var x286 uint64 + var x287 uint64 + x286, x287 = bits.Add64(x281, x278, uint64(p521Uint1(x285))) + var x288 uint64 + var x289 uint64 + x288, x289 = bits.Add64(x279, x276, uint64(p521Uint1(x287))) + var x290 uint64 + var x291 uint64 + x290, x291 = bits.Add64(x277, x274, uint64(p521Uint1(x289))) + var x292 uint64 + var x293 uint64 + x292, x293 = bits.Add64(x275, x272, uint64(p521Uint1(x291))) + var x294 uint64 + var x295 uint64 + x294, x295 = bits.Add64(x273, x270, uint64(p521Uint1(x293))) + var x296 uint64 + var x297 uint64 + x296, x297 = bits.Add64(x271, x268, uint64(p521Uint1(x295))) + var x298 uint64 + var x299 uint64 + x298, x299 = bits.Add64(x269, x266, uint64(p521Uint1(x297))) + x300 := (uint64(p521Uint1(x299)) + x267) + var x302 uint64 + _, x302 = bits.Add64(x246, x282, uint64(0x0)) + var x303 uint64 + var x304 uint64 + x303, x304 = bits.Add64(x248, x284, uint64(p521Uint1(x302))) + var x305 uint64 + var x306 uint64 + x305, x306 = bits.Add64(x250, x286, uint64(p521Uint1(x304))) + var x307 uint64 + var x308 uint64 + x307, x308 = bits.Add64(x252, x288, uint64(p521Uint1(x306))) + var x309 uint64 + var x310 uint64 + x309, x310 = bits.Add64(x254, x290, uint64(p521Uint1(x308))) + var x311 uint64 + var x312 uint64 + x311, x312 = bits.Add64(x256, x292, uint64(p521Uint1(x310))) + var x313 uint64 + var x314 uint64 + x313, x314 = bits.Add64(x258, x294, uint64(p521Uint1(x312))) + var x315 uint64 + var x316 uint64 + x315, x316 = bits.Add64(x260, x296, uint64(p521Uint1(x314))) + var x317 uint64 + var x318 uint64 + x317, x318 = bits.Add64(x262, x298, uint64(p521Uint1(x316))) + var x319 uint64 + var x320 uint64 + x319, x320 = bits.Add64(x264, x300, uint64(p521Uint1(x318))) + x321 := (uint64(p521Uint1(x320)) + uint64(p521Uint1(x265))) + var x322 uint64 + var x323 uint64 + x323, x322 = bits.Mul64(x3, arg1[8]) + var x324 uint64 + var x325 uint64 + x325, x324 = bits.Mul64(x3, arg1[7]) + var x326 uint64 + var x327 uint64 + x327, x326 = bits.Mul64(x3, arg1[6]) + var x328 uint64 + var x329 uint64 + x329, x328 = bits.Mul64(x3, arg1[5]) + var x330 uint64 + var x331 uint64 + x331, x330 = bits.Mul64(x3, arg1[4]) + var x332 uint64 + var x333 uint64 + x333, x332 = bits.Mul64(x3, arg1[3]) + var x334 uint64 + var x335 uint64 + x335, x334 = bits.Mul64(x3, arg1[2]) + var x336 uint64 + var x337 uint64 + x337, x336 = bits.Mul64(x3, arg1[1]) + var x338 uint64 + var x339 uint64 + x339, x338 = bits.Mul64(x3, arg1[0]) + var x340 uint64 + var x341 uint64 + x340, x341 = bits.Add64(x339, x336, uint64(0x0)) + var x342 uint64 + var x343 uint64 + x342, x343 = bits.Add64(x337, x334, uint64(p521Uint1(x341))) + var x344 uint64 + var x345 uint64 + x344, x345 = bits.Add64(x335, x332, uint64(p521Uint1(x343))) + var x346 uint64 + var x347 uint64 + x346, x347 = bits.Add64(x333, x330, uint64(p521Uint1(x345))) + var x348 uint64 + var x349 uint64 + x348, x349 = bits.Add64(x331, x328, uint64(p521Uint1(x347))) + var x350 uint64 + var x351 uint64 + x350, x351 = bits.Add64(x329, x326, uint64(p521Uint1(x349))) + var x352 uint64 + var x353 uint64 + x352, x353 = bits.Add64(x327, x324, uint64(p521Uint1(x351))) + var x354 uint64 + var x355 uint64 + x354, x355 = bits.Add64(x325, x322, uint64(p521Uint1(x353))) + x356 := (uint64(p521Uint1(x355)) + x323) + var x357 uint64 + var x358 uint64 + x357, x358 = bits.Add64(x303, x338, uint64(0x0)) + var x359 uint64 + var x360 uint64 + x359, x360 = bits.Add64(x305, x340, uint64(p521Uint1(x358))) + var x361 uint64 + var x362 uint64 + x361, x362 = bits.Add64(x307, x342, uint64(p521Uint1(x360))) + var x363 uint64 + var x364 uint64 + x363, x364 = bits.Add64(x309, x344, uint64(p521Uint1(x362))) + var x365 uint64 + var x366 uint64 + x365, x366 = bits.Add64(x311, x346, uint64(p521Uint1(x364))) + var x367 uint64 + var x368 uint64 + x367, x368 = bits.Add64(x313, x348, uint64(p521Uint1(x366))) + var x369 uint64 + var x370 uint64 + x369, x370 = bits.Add64(x315, x350, uint64(p521Uint1(x368))) + var x371 uint64 + var x372 uint64 + x371, x372 = bits.Add64(x317, x352, uint64(p521Uint1(x370))) + var x373 uint64 + var x374 uint64 + x373, x374 = bits.Add64(x319, x354, uint64(p521Uint1(x372))) + var x375 uint64 + var x376 uint64 + x375, x376 = bits.Add64(x321, x356, uint64(p521Uint1(x374))) + var x377 uint64 + var x378 uint64 + x378, x377 = bits.Mul64(x357, 0x1ff) + var x379 uint64 + var x380 uint64 + x380, x379 = bits.Mul64(x357, 0xffffffffffffffff) + var x381 uint64 + var x382 uint64 + x382, x381 = bits.Mul64(x357, 0xffffffffffffffff) + var x383 uint64 + var x384 uint64 + x384, x383 = bits.Mul64(x357, 0xffffffffffffffff) + var x385 uint64 + var x386 uint64 + x386, x385 = bits.Mul64(x357, 0xffffffffffffffff) + var x387 uint64 + var x388 uint64 + x388, x387 = bits.Mul64(x357, 0xffffffffffffffff) + var x389 uint64 + var x390 uint64 + x390, x389 = bits.Mul64(x357, 0xffffffffffffffff) + var x391 uint64 + var x392 uint64 + x392, x391 = bits.Mul64(x357, 0xffffffffffffffff) + var x393 uint64 + var x394 uint64 + x394, x393 = bits.Mul64(x357, 0xffffffffffffffff) + var x395 uint64 + var x396 uint64 + x395, x396 = bits.Add64(x394, x391, uint64(0x0)) + var x397 uint64 + var x398 uint64 + x397, x398 = bits.Add64(x392, x389, uint64(p521Uint1(x396))) + var x399 uint64 + var x400 uint64 + x399, x400 = bits.Add64(x390, x387, uint64(p521Uint1(x398))) + var x401 uint64 + var x402 uint64 + x401, x402 = bits.Add64(x388, x385, uint64(p521Uint1(x400))) + var x403 uint64 + var x404 uint64 + x403, x404 = bits.Add64(x386, x383, uint64(p521Uint1(x402))) + var x405 uint64 + var x406 uint64 + x405, x406 = bits.Add64(x384, x381, uint64(p521Uint1(x404))) + var x407 uint64 + var x408 uint64 + x407, x408 = bits.Add64(x382, x379, uint64(p521Uint1(x406))) + var x409 uint64 + var x410 uint64 + x409, x410 = bits.Add64(x380, x377, uint64(p521Uint1(x408))) + x411 := (uint64(p521Uint1(x410)) + x378) + var x413 uint64 + _, x413 = bits.Add64(x357, x393, uint64(0x0)) + var x414 uint64 + var x415 uint64 + x414, x415 = bits.Add64(x359, x395, uint64(p521Uint1(x413))) + var x416 uint64 + var x417 uint64 + x416, x417 = bits.Add64(x361, x397, uint64(p521Uint1(x415))) + var x418 uint64 + var x419 uint64 + x418, x419 = bits.Add64(x363, x399, uint64(p521Uint1(x417))) + var x420 uint64 + var x421 uint64 + x420, x421 = bits.Add64(x365, x401, uint64(p521Uint1(x419))) + var x422 uint64 + var x423 uint64 + x422, x423 = bits.Add64(x367, x403, uint64(p521Uint1(x421))) + var x424 uint64 + var x425 uint64 + x424, x425 = bits.Add64(x369, x405, uint64(p521Uint1(x423))) + var x426 uint64 + var x427 uint64 + x426, x427 = bits.Add64(x371, x407, uint64(p521Uint1(x425))) + var x428 uint64 + var x429 uint64 + x428, x429 = bits.Add64(x373, x409, uint64(p521Uint1(x427))) + var x430 uint64 + var x431 uint64 + x430, x431 = bits.Add64(x375, x411, uint64(p521Uint1(x429))) + x432 := (uint64(p521Uint1(x431)) + uint64(p521Uint1(x376))) + var x433 uint64 + var x434 uint64 + x434, x433 = bits.Mul64(x4, arg1[8]) + var x435 uint64 + var x436 uint64 + x436, x435 = bits.Mul64(x4, arg1[7]) + var x437 uint64 + var x438 uint64 + x438, x437 = bits.Mul64(x4, arg1[6]) + var x439 uint64 + var x440 uint64 + x440, x439 = bits.Mul64(x4, arg1[5]) + var x441 uint64 + var x442 uint64 + x442, x441 = bits.Mul64(x4, arg1[4]) + var x443 uint64 + var x444 uint64 + x444, x443 = bits.Mul64(x4, arg1[3]) + var x445 uint64 + var x446 uint64 + x446, x445 = bits.Mul64(x4, arg1[2]) + var x447 uint64 + var x448 uint64 + x448, x447 = bits.Mul64(x4, arg1[1]) + var x449 uint64 + var x450 uint64 + x450, x449 = bits.Mul64(x4, arg1[0]) + var x451 uint64 + var x452 uint64 + x451, x452 = bits.Add64(x450, x447, uint64(0x0)) + var x453 uint64 + var x454 uint64 + x453, x454 = bits.Add64(x448, x445, uint64(p521Uint1(x452))) + var x455 uint64 + var x456 uint64 + x455, x456 = bits.Add64(x446, x443, uint64(p521Uint1(x454))) + var x457 uint64 + var x458 uint64 + x457, x458 = bits.Add64(x444, x441, uint64(p521Uint1(x456))) + var x459 uint64 + var x460 uint64 + x459, x460 = bits.Add64(x442, x439, uint64(p521Uint1(x458))) + var x461 uint64 + var x462 uint64 + x461, x462 = bits.Add64(x440, x437, uint64(p521Uint1(x460))) + var x463 uint64 + var x464 uint64 + x463, x464 = bits.Add64(x438, x435, uint64(p521Uint1(x462))) + var x465 uint64 + var x466 uint64 + x465, x466 = bits.Add64(x436, x433, uint64(p521Uint1(x464))) + x467 := (uint64(p521Uint1(x466)) + x434) + var x468 uint64 + var x469 uint64 + x468, x469 = bits.Add64(x414, x449, uint64(0x0)) + var x470 uint64 + var x471 uint64 + x470, x471 = bits.Add64(x416, x451, uint64(p521Uint1(x469))) + var x472 uint64 + var x473 uint64 + x472, x473 = bits.Add64(x418, x453, uint64(p521Uint1(x471))) + var x474 uint64 + var x475 uint64 + x474, x475 = bits.Add64(x420, x455, uint64(p521Uint1(x473))) + var x476 uint64 + var x477 uint64 + x476, x477 = bits.Add64(x422, x457, uint64(p521Uint1(x475))) + var x478 uint64 + var x479 uint64 + x478, x479 = bits.Add64(x424, x459, uint64(p521Uint1(x477))) + var x480 uint64 + var x481 uint64 + x480, x481 = bits.Add64(x426, x461, uint64(p521Uint1(x479))) + var x482 uint64 + var x483 uint64 + x482, x483 = bits.Add64(x428, x463, uint64(p521Uint1(x481))) + var x484 uint64 + var x485 uint64 + x484, x485 = bits.Add64(x430, x465, uint64(p521Uint1(x483))) + var x486 uint64 + var x487 uint64 + x486, x487 = bits.Add64(x432, x467, uint64(p521Uint1(x485))) + var x488 uint64 + var x489 uint64 + x489, x488 = bits.Mul64(x468, 0x1ff) + var x490 uint64 + var x491 uint64 + x491, x490 = bits.Mul64(x468, 0xffffffffffffffff) + var x492 uint64 + var x493 uint64 + x493, x492 = bits.Mul64(x468, 0xffffffffffffffff) + var x494 uint64 + var x495 uint64 + x495, x494 = bits.Mul64(x468, 0xffffffffffffffff) + var x496 uint64 + var x497 uint64 + x497, x496 = bits.Mul64(x468, 0xffffffffffffffff) + var x498 uint64 + var x499 uint64 + x499, x498 = bits.Mul64(x468, 0xffffffffffffffff) + var x500 uint64 + var x501 uint64 + x501, x500 = bits.Mul64(x468, 0xffffffffffffffff) + var x502 uint64 + var x503 uint64 + x503, x502 = bits.Mul64(x468, 0xffffffffffffffff) + var x504 uint64 + var x505 uint64 + x505, x504 = bits.Mul64(x468, 0xffffffffffffffff) + var x506 uint64 + var x507 uint64 + x506, x507 = bits.Add64(x505, x502, uint64(0x0)) + var x508 uint64 + var x509 uint64 + x508, x509 = bits.Add64(x503, x500, uint64(p521Uint1(x507))) + var x510 uint64 + var x511 uint64 + x510, x511 = bits.Add64(x501, x498, uint64(p521Uint1(x509))) + var x512 uint64 + var x513 uint64 + x512, x513 = bits.Add64(x499, x496, uint64(p521Uint1(x511))) + var x514 uint64 + var x515 uint64 + x514, x515 = bits.Add64(x497, x494, uint64(p521Uint1(x513))) + var x516 uint64 + var x517 uint64 + x516, x517 = bits.Add64(x495, x492, uint64(p521Uint1(x515))) + var x518 uint64 + var x519 uint64 + x518, x519 = bits.Add64(x493, x490, uint64(p521Uint1(x517))) + var x520 uint64 + var x521 uint64 + x520, x521 = bits.Add64(x491, x488, uint64(p521Uint1(x519))) + x522 := (uint64(p521Uint1(x521)) + x489) + var x524 uint64 + _, x524 = bits.Add64(x468, x504, uint64(0x0)) + var x525 uint64 + var x526 uint64 + x525, x526 = bits.Add64(x470, x506, uint64(p521Uint1(x524))) + var x527 uint64 + var x528 uint64 + x527, x528 = bits.Add64(x472, x508, uint64(p521Uint1(x526))) + var x529 uint64 + var x530 uint64 + x529, x530 = bits.Add64(x474, x510, uint64(p521Uint1(x528))) + var x531 uint64 + var x532 uint64 + x531, x532 = bits.Add64(x476, x512, uint64(p521Uint1(x530))) + var x533 uint64 + var x534 uint64 + x533, x534 = bits.Add64(x478, x514, uint64(p521Uint1(x532))) + var x535 uint64 + var x536 uint64 + x535, x536 = bits.Add64(x480, x516, uint64(p521Uint1(x534))) + var x537 uint64 + var x538 uint64 + x537, x538 = bits.Add64(x482, x518, uint64(p521Uint1(x536))) + var x539 uint64 + var x540 uint64 + x539, x540 = bits.Add64(x484, x520, uint64(p521Uint1(x538))) + var x541 uint64 + var x542 uint64 + x541, x542 = bits.Add64(x486, x522, uint64(p521Uint1(x540))) + x543 := (uint64(p521Uint1(x542)) + uint64(p521Uint1(x487))) + var x544 uint64 + var x545 uint64 + x545, x544 = bits.Mul64(x5, arg1[8]) + var x546 uint64 + var x547 uint64 + x547, x546 = bits.Mul64(x5, arg1[7]) + var x548 uint64 + var x549 uint64 + x549, x548 = bits.Mul64(x5, arg1[6]) + var x550 uint64 + var x551 uint64 + x551, x550 = bits.Mul64(x5, arg1[5]) + var x552 uint64 + var x553 uint64 + x553, x552 = bits.Mul64(x5, arg1[4]) + var x554 uint64 + var x555 uint64 + x555, x554 = bits.Mul64(x5, arg1[3]) + var x556 uint64 + var x557 uint64 + x557, x556 = bits.Mul64(x5, arg1[2]) + var x558 uint64 + var x559 uint64 + x559, x558 = bits.Mul64(x5, arg1[1]) + var x560 uint64 + var x561 uint64 + x561, x560 = bits.Mul64(x5, arg1[0]) + var x562 uint64 + var x563 uint64 + x562, x563 = bits.Add64(x561, x558, uint64(0x0)) + var x564 uint64 + var x565 uint64 + x564, x565 = bits.Add64(x559, x556, uint64(p521Uint1(x563))) + var x566 uint64 + var x567 uint64 + x566, x567 = bits.Add64(x557, x554, uint64(p521Uint1(x565))) + var x568 uint64 + var x569 uint64 + x568, x569 = bits.Add64(x555, x552, uint64(p521Uint1(x567))) + var x570 uint64 + var x571 uint64 + x570, x571 = bits.Add64(x553, x550, uint64(p521Uint1(x569))) + var x572 uint64 + var x573 uint64 + x572, x573 = bits.Add64(x551, x548, uint64(p521Uint1(x571))) + var x574 uint64 + var x575 uint64 + x574, x575 = bits.Add64(x549, x546, uint64(p521Uint1(x573))) + var x576 uint64 + var x577 uint64 + x576, x577 = bits.Add64(x547, x544, uint64(p521Uint1(x575))) + x578 := (uint64(p521Uint1(x577)) + x545) + var x579 uint64 + var x580 uint64 + x579, x580 = bits.Add64(x525, x560, uint64(0x0)) + var x581 uint64 + var x582 uint64 + x581, x582 = bits.Add64(x527, x562, uint64(p521Uint1(x580))) + var x583 uint64 + var x584 uint64 + x583, x584 = bits.Add64(x529, x564, uint64(p521Uint1(x582))) + var x585 uint64 + var x586 uint64 + x585, x586 = bits.Add64(x531, x566, uint64(p521Uint1(x584))) + var x587 uint64 + var x588 uint64 + x587, x588 = bits.Add64(x533, x568, uint64(p521Uint1(x586))) + var x589 uint64 + var x590 uint64 + x589, x590 = bits.Add64(x535, x570, uint64(p521Uint1(x588))) + var x591 uint64 + var x592 uint64 + x591, x592 = bits.Add64(x537, x572, uint64(p521Uint1(x590))) + var x593 uint64 + var x594 uint64 + x593, x594 = bits.Add64(x539, x574, uint64(p521Uint1(x592))) + var x595 uint64 + var x596 uint64 + x595, x596 = bits.Add64(x541, x576, uint64(p521Uint1(x594))) + var x597 uint64 + var x598 uint64 + x597, x598 = bits.Add64(x543, x578, uint64(p521Uint1(x596))) + var x599 uint64 + var x600 uint64 + x600, x599 = bits.Mul64(x579, 0x1ff) + var x601 uint64 + var x602 uint64 + x602, x601 = bits.Mul64(x579, 0xffffffffffffffff) + var x603 uint64 + var x604 uint64 + x604, x603 = bits.Mul64(x579, 0xffffffffffffffff) + var x605 uint64 + var x606 uint64 + x606, x605 = bits.Mul64(x579, 0xffffffffffffffff) + var x607 uint64 + var x608 uint64 + x608, x607 = bits.Mul64(x579, 0xffffffffffffffff) + var x609 uint64 + var x610 uint64 + x610, x609 = bits.Mul64(x579, 0xffffffffffffffff) + var x611 uint64 + var x612 uint64 + x612, x611 = bits.Mul64(x579, 0xffffffffffffffff) + var x613 uint64 + var x614 uint64 + x614, x613 = bits.Mul64(x579, 0xffffffffffffffff) + var x615 uint64 + var x616 uint64 + x616, x615 = bits.Mul64(x579, 0xffffffffffffffff) + var x617 uint64 + var x618 uint64 + x617, x618 = bits.Add64(x616, x613, uint64(0x0)) + var x619 uint64 + var x620 uint64 + x619, x620 = bits.Add64(x614, x611, uint64(p521Uint1(x618))) + var x621 uint64 + var x622 uint64 + x621, x622 = bits.Add64(x612, x609, uint64(p521Uint1(x620))) + var x623 uint64 + var x624 uint64 + x623, x624 = bits.Add64(x610, x607, uint64(p521Uint1(x622))) + var x625 uint64 + var x626 uint64 + x625, x626 = bits.Add64(x608, x605, uint64(p521Uint1(x624))) + var x627 uint64 + var x628 uint64 + x627, x628 = bits.Add64(x606, x603, uint64(p521Uint1(x626))) + var x629 uint64 + var x630 uint64 + x629, x630 = bits.Add64(x604, x601, uint64(p521Uint1(x628))) + var x631 uint64 + var x632 uint64 + x631, x632 = bits.Add64(x602, x599, uint64(p521Uint1(x630))) + x633 := (uint64(p521Uint1(x632)) + x600) + var x635 uint64 + _, x635 = bits.Add64(x579, x615, uint64(0x0)) + var x636 uint64 + var x637 uint64 + x636, x637 = bits.Add64(x581, x617, uint64(p521Uint1(x635))) + var x638 uint64 + var x639 uint64 + x638, x639 = bits.Add64(x583, x619, uint64(p521Uint1(x637))) + var x640 uint64 + var x641 uint64 + x640, x641 = bits.Add64(x585, x621, uint64(p521Uint1(x639))) + var x642 uint64 + var x643 uint64 + x642, x643 = bits.Add64(x587, x623, uint64(p521Uint1(x641))) + var x644 uint64 + var x645 uint64 + x644, x645 = bits.Add64(x589, x625, uint64(p521Uint1(x643))) + var x646 uint64 + var x647 uint64 + x646, x647 = bits.Add64(x591, x627, uint64(p521Uint1(x645))) + var x648 uint64 + var x649 uint64 + x648, x649 = bits.Add64(x593, x629, uint64(p521Uint1(x647))) + var x650 uint64 + var x651 uint64 + x650, x651 = bits.Add64(x595, x631, uint64(p521Uint1(x649))) + var x652 uint64 + var x653 uint64 + x652, x653 = bits.Add64(x597, x633, uint64(p521Uint1(x651))) + x654 := (uint64(p521Uint1(x653)) + uint64(p521Uint1(x598))) + var x655 uint64 + var x656 uint64 + x656, x655 = bits.Mul64(x6, arg1[8]) + var x657 uint64 + var x658 uint64 + x658, x657 = bits.Mul64(x6, arg1[7]) + var x659 uint64 + var x660 uint64 + x660, x659 = bits.Mul64(x6, arg1[6]) + var x661 uint64 + var x662 uint64 + x662, x661 = bits.Mul64(x6, arg1[5]) + var x663 uint64 + var x664 uint64 + x664, x663 = bits.Mul64(x6, arg1[4]) + var x665 uint64 + var x666 uint64 + x666, x665 = bits.Mul64(x6, arg1[3]) + var x667 uint64 + var x668 uint64 + x668, x667 = bits.Mul64(x6, arg1[2]) + var x669 uint64 + var x670 uint64 + x670, x669 = bits.Mul64(x6, arg1[1]) + var x671 uint64 + var x672 uint64 + x672, x671 = bits.Mul64(x6, arg1[0]) + var x673 uint64 + var x674 uint64 + x673, x674 = bits.Add64(x672, x669, uint64(0x0)) + var x675 uint64 + var x676 uint64 + x675, x676 = bits.Add64(x670, x667, uint64(p521Uint1(x674))) + var x677 uint64 + var x678 uint64 + x677, x678 = bits.Add64(x668, x665, uint64(p521Uint1(x676))) + var x679 uint64 + var x680 uint64 + x679, x680 = bits.Add64(x666, x663, uint64(p521Uint1(x678))) + var x681 uint64 + var x682 uint64 + x681, x682 = bits.Add64(x664, x661, uint64(p521Uint1(x680))) + var x683 uint64 + var x684 uint64 + x683, x684 = bits.Add64(x662, x659, uint64(p521Uint1(x682))) + var x685 uint64 + var x686 uint64 + x685, x686 = bits.Add64(x660, x657, uint64(p521Uint1(x684))) + var x687 uint64 + var x688 uint64 + x687, x688 = bits.Add64(x658, x655, uint64(p521Uint1(x686))) + x689 := (uint64(p521Uint1(x688)) + x656) + var x690 uint64 + var x691 uint64 + x690, x691 = bits.Add64(x636, x671, uint64(0x0)) + var x692 uint64 + var x693 uint64 + x692, x693 = bits.Add64(x638, x673, uint64(p521Uint1(x691))) + var x694 uint64 + var x695 uint64 + x694, x695 = bits.Add64(x640, x675, uint64(p521Uint1(x693))) + var x696 uint64 + var x697 uint64 + x696, x697 = bits.Add64(x642, x677, uint64(p521Uint1(x695))) + var x698 uint64 + var x699 uint64 + x698, x699 = bits.Add64(x644, x679, uint64(p521Uint1(x697))) + var x700 uint64 + var x701 uint64 + x700, x701 = bits.Add64(x646, x681, uint64(p521Uint1(x699))) + var x702 uint64 + var x703 uint64 + x702, x703 = bits.Add64(x648, x683, uint64(p521Uint1(x701))) + var x704 uint64 + var x705 uint64 + x704, x705 = bits.Add64(x650, x685, uint64(p521Uint1(x703))) + var x706 uint64 + var x707 uint64 + x706, x707 = bits.Add64(x652, x687, uint64(p521Uint1(x705))) + var x708 uint64 + var x709 uint64 + x708, x709 = bits.Add64(x654, x689, uint64(p521Uint1(x707))) + var x710 uint64 + var x711 uint64 + x711, x710 = bits.Mul64(x690, 0x1ff) + var x712 uint64 + var x713 uint64 + x713, x712 = bits.Mul64(x690, 0xffffffffffffffff) + var x714 uint64 + var x715 uint64 + x715, x714 = bits.Mul64(x690, 0xffffffffffffffff) + var x716 uint64 + var x717 uint64 + x717, x716 = bits.Mul64(x690, 0xffffffffffffffff) + var x718 uint64 + var x719 uint64 + x719, x718 = bits.Mul64(x690, 0xffffffffffffffff) + var x720 uint64 + var x721 uint64 + x721, x720 = bits.Mul64(x690, 0xffffffffffffffff) + var x722 uint64 + var x723 uint64 + x723, x722 = bits.Mul64(x690, 0xffffffffffffffff) + var x724 uint64 + var x725 uint64 + x725, x724 = bits.Mul64(x690, 0xffffffffffffffff) + var x726 uint64 + var x727 uint64 + x727, x726 = bits.Mul64(x690, 0xffffffffffffffff) + var x728 uint64 + var x729 uint64 + x728, x729 = bits.Add64(x727, x724, uint64(0x0)) + var x730 uint64 + var x731 uint64 + x730, x731 = bits.Add64(x725, x722, uint64(p521Uint1(x729))) + var x732 uint64 + var x733 uint64 + x732, x733 = bits.Add64(x723, x720, uint64(p521Uint1(x731))) + var x734 uint64 + var x735 uint64 + x734, x735 = bits.Add64(x721, x718, uint64(p521Uint1(x733))) + var x736 uint64 + var x737 uint64 + x736, x737 = bits.Add64(x719, x716, uint64(p521Uint1(x735))) + var x738 uint64 + var x739 uint64 + x738, x739 = bits.Add64(x717, x714, uint64(p521Uint1(x737))) + var x740 uint64 + var x741 uint64 + x740, x741 = bits.Add64(x715, x712, uint64(p521Uint1(x739))) + var x742 uint64 + var x743 uint64 + x742, x743 = bits.Add64(x713, x710, uint64(p521Uint1(x741))) + x744 := (uint64(p521Uint1(x743)) + x711) + var x746 uint64 + _, x746 = bits.Add64(x690, x726, uint64(0x0)) + var x747 uint64 + var x748 uint64 + x747, x748 = bits.Add64(x692, x728, uint64(p521Uint1(x746))) + var x749 uint64 + var x750 uint64 + x749, x750 = bits.Add64(x694, x730, uint64(p521Uint1(x748))) + var x751 uint64 + var x752 uint64 + x751, x752 = bits.Add64(x696, x732, uint64(p521Uint1(x750))) + var x753 uint64 + var x754 uint64 + x753, x754 = bits.Add64(x698, x734, uint64(p521Uint1(x752))) + var x755 uint64 + var x756 uint64 + x755, x756 = bits.Add64(x700, x736, uint64(p521Uint1(x754))) + var x757 uint64 + var x758 uint64 + x757, x758 = bits.Add64(x702, x738, uint64(p521Uint1(x756))) + var x759 uint64 + var x760 uint64 + x759, x760 = bits.Add64(x704, x740, uint64(p521Uint1(x758))) + var x761 uint64 + var x762 uint64 + x761, x762 = bits.Add64(x706, x742, uint64(p521Uint1(x760))) + var x763 uint64 + var x764 uint64 + x763, x764 = bits.Add64(x708, x744, uint64(p521Uint1(x762))) + x765 := (uint64(p521Uint1(x764)) + uint64(p521Uint1(x709))) + var x766 uint64 + var x767 uint64 + x767, x766 = bits.Mul64(x7, arg1[8]) + var x768 uint64 + var x769 uint64 + x769, x768 = bits.Mul64(x7, arg1[7]) + var x770 uint64 + var x771 uint64 + x771, x770 = bits.Mul64(x7, arg1[6]) + var x772 uint64 + var x773 uint64 + x773, x772 = bits.Mul64(x7, arg1[5]) + var x774 uint64 + var x775 uint64 + x775, x774 = bits.Mul64(x7, arg1[4]) + var x776 uint64 + var x777 uint64 + x777, x776 = bits.Mul64(x7, arg1[3]) + var x778 uint64 + var x779 uint64 + x779, x778 = bits.Mul64(x7, arg1[2]) + var x780 uint64 + var x781 uint64 + x781, x780 = bits.Mul64(x7, arg1[1]) + var x782 uint64 + var x783 uint64 + x783, x782 = bits.Mul64(x7, arg1[0]) + var x784 uint64 + var x785 uint64 + x784, x785 = bits.Add64(x783, x780, uint64(0x0)) + var x786 uint64 + var x787 uint64 + x786, x787 = bits.Add64(x781, x778, uint64(p521Uint1(x785))) + var x788 uint64 + var x789 uint64 + x788, x789 = bits.Add64(x779, x776, uint64(p521Uint1(x787))) + var x790 uint64 + var x791 uint64 + x790, x791 = bits.Add64(x777, x774, uint64(p521Uint1(x789))) + var x792 uint64 + var x793 uint64 + x792, x793 = bits.Add64(x775, x772, uint64(p521Uint1(x791))) + var x794 uint64 + var x795 uint64 + x794, x795 = bits.Add64(x773, x770, uint64(p521Uint1(x793))) + var x796 uint64 + var x797 uint64 + x796, x797 = bits.Add64(x771, x768, uint64(p521Uint1(x795))) + var x798 uint64 + var x799 uint64 + x798, x799 = bits.Add64(x769, x766, uint64(p521Uint1(x797))) + x800 := (uint64(p521Uint1(x799)) + x767) + var x801 uint64 + var x802 uint64 + x801, x802 = bits.Add64(x747, x782, uint64(0x0)) + var x803 uint64 + var x804 uint64 + x803, x804 = bits.Add64(x749, x784, uint64(p521Uint1(x802))) + var x805 uint64 + var x806 uint64 + x805, x806 = bits.Add64(x751, x786, uint64(p521Uint1(x804))) + var x807 uint64 + var x808 uint64 + x807, x808 = bits.Add64(x753, x788, uint64(p521Uint1(x806))) + var x809 uint64 + var x810 uint64 + x809, x810 = bits.Add64(x755, x790, uint64(p521Uint1(x808))) + var x811 uint64 + var x812 uint64 + x811, x812 = bits.Add64(x757, x792, uint64(p521Uint1(x810))) + var x813 uint64 + var x814 uint64 + x813, x814 = bits.Add64(x759, x794, uint64(p521Uint1(x812))) + var x815 uint64 + var x816 uint64 + x815, x816 = bits.Add64(x761, x796, uint64(p521Uint1(x814))) + var x817 uint64 + var x818 uint64 + x817, x818 = bits.Add64(x763, x798, uint64(p521Uint1(x816))) + var x819 uint64 + var x820 uint64 + x819, x820 = bits.Add64(x765, x800, uint64(p521Uint1(x818))) + var x821 uint64 + var x822 uint64 + x822, x821 = bits.Mul64(x801, 0x1ff) + var x823 uint64 + var x824 uint64 + x824, x823 = bits.Mul64(x801, 0xffffffffffffffff) + var x825 uint64 + var x826 uint64 + x826, x825 = bits.Mul64(x801, 0xffffffffffffffff) + var x827 uint64 + var x828 uint64 + x828, x827 = bits.Mul64(x801, 0xffffffffffffffff) + var x829 uint64 + var x830 uint64 + x830, x829 = bits.Mul64(x801, 0xffffffffffffffff) + var x831 uint64 + var x832 uint64 + x832, x831 = bits.Mul64(x801, 0xffffffffffffffff) + var x833 uint64 + var x834 uint64 + x834, x833 = bits.Mul64(x801, 0xffffffffffffffff) + var x835 uint64 + var x836 uint64 + x836, x835 = bits.Mul64(x801, 0xffffffffffffffff) + var x837 uint64 + var x838 uint64 + x838, x837 = bits.Mul64(x801, 0xffffffffffffffff) + var x839 uint64 + var x840 uint64 + x839, x840 = bits.Add64(x838, x835, uint64(0x0)) + var x841 uint64 + var x842 uint64 + x841, x842 = bits.Add64(x836, x833, uint64(p521Uint1(x840))) + var x843 uint64 + var x844 uint64 + x843, x844 = bits.Add64(x834, x831, uint64(p521Uint1(x842))) + var x845 uint64 + var x846 uint64 + x845, x846 = bits.Add64(x832, x829, uint64(p521Uint1(x844))) + var x847 uint64 + var x848 uint64 + x847, x848 = bits.Add64(x830, x827, uint64(p521Uint1(x846))) + var x849 uint64 + var x850 uint64 + x849, x850 = bits.Add64(x828, x825, uint64(p521Uint1(x848))) + var x851 uint64 + var x852 uint64 + x851, x852 = bits.Add64(x826, x823, uint64(p521Uint1(x850))) + var x853 uint64 + var x854 uint64 + x853, x854 = bits.Add64(x824, x821, uint64(p521Uint1(x852))) + x855 := (uint64(p521Uint1(x854)) + x822) + var x857 uint64 + _, x857 = bits.Add64(x801, x837, uint64(0x0)) + var x858 uint64 + var x859 uint64 + x858, x859 = bits.Add64(x803, x839, uint64(p521Uint1(x857))) + var x860 uint64 + var x861 uint64 + x860, x861 = bits.Add64(x805, x841, uint64(p521Uint1(x859))) + var x862 uint64 + var x863 uint64 + x862, x863 = bits.Add64(x807, x843, uint64(p521Uint1(x861))) + var x864 uint64 + var x865 uint64 + x864, x865 = bits.Add64(x809, x845, uint64(p521Uint1(x863))) + var x866 uint64 + var x867 uint64 + x866, x867 = bits.Add64(x811, x847, uint64(p521Uint1(x865))) + var x868 uint64 + var x869 uint64 + x868, x869 = bits.Add64(x813, x849, uint64(p521Uint1(x867))) + var x870 uint64 + var x871 uint64 + x870, x871 = bits.Add64(x815, x851, uint64(p521Uint1(x869))) + var x872 uint64 + var x873 uint64 + x872, x873 = bits.Add64(x817, x853, uint64(p521Uint1(x871))) + var x874 uint64 + var x875 uint64 + x874, x875 = bits.Add64(x819, x855, uint64(p521Uint1(x873))) + x876 := (uint64(p521Uint1(x875)) + uint64(p521Uint1(x820))) + var x877 uint64 + var x878 uint64 + x878, x877 = bits.Mul64(x8, arg1[8]) + var x879 uint64 + var x880 uint64 + x880, x879 = bits.Mul64(x8, arg1[7]) + var x881 uint64 + var x882 uint64 + x882, x881 = bits.Mul64(x8, arg1[6]) + var x883 uint64 + var x884 uint64 + x884, x883 = bits.Mul64(x8, arg1[5]) + var x885 uint64 + var x886 uint64 + x886, x885 = bits.Mul64(x8, arg1[4]) + var x887 uint64 + var x888 uint64 + x888, x887 = bits.Mul64(x8, arg1[3]) + var x889 uint64 + var x890 uint64 + x890, x889 = bits.Mul64(x8, arg1[2]) + var x891 uint64 + var x892 uint64 + x892, x891 = bits.Mul64(x8, arg1[1]) + var x893 uint64 + var x894 uint64 + x894, x893 = bits.Mul64(x8, arg1[0]) + var x895 uint64 + var x896 uint64 + x895, x896 = bits.Add64(x894, x891, uint64(0x0)) + var x897 uint64 + var x898 uint64 + x897, x898 = bits.Add64(x892, x889, uint64(p521Uint1(x896))) + var x899 uint64 + var x900 uint64 + x899, x900 = bits.Add64(x890, x887, uint64(p521Uint1(x898))) + var x901 uint64 + var x902 uint64 + x901, x902 = bits.Add64(x888, x885, uint64(p521Uint1(x900))) + var x903 uint64 + var x904 uint64 + x903, x904 = bits.Add64(x886, x883, uint64(p521Uint1(x902))) + var x905 uint64 + var x906 uint64 + x905, x906 = bits.Add64(x884, x881, uint64(p521Uint1(x904))) + var x907 uint64 + var x908 uint64 + x907, x908 = bits.Add64(x882, x879, uint64(p521Uint1(x906))) + var x909 uint64 + var x910 uint64 + x909, x910 = bits.Add64(x880, x877, uint64(p521Uint1(x908))) + x911 := (uint64(p521Uint1(x910)) + x878) + var x912 uint64 + var x913 uint64 + x912, x913 = bits.Add64(x858, x893, uint64(0x0)) + var x914 uint64 + var x915 uint64 + x914, x915 = bits.Add64(x860, x895, uint64(p521Uint1(x913))) + var x916 uint64 + var x917 uint64 + x916, x917 = bits.Add64(x862, x897, uint64(p521Uint1(x915))) + var x918 uint64 + var x919 uint64 + x918, x919 = bits.Add64(x864, x899, uint64(p521Uint1(x917))) + var x920 uint64 + var x921 uint64 + x920, x921 = bits.Add64(x866, x901, uint64(p521Uint1(x919))) + var x922 uint64 + var x923 uint64 + x922, x923 = bits.Add64(x868, x903, uint64(p521Uint1(x921))) + var x924 uint64 + var x925 uint64 + x924, x925 = bits.Add64(x870, x905, uint64(p521Uint1(x923))) + var x926 uint64 + var x927 uint64 + x926, x927 = bits.Add64(x872, x907, uint64(p521Uint1(x925))) + var x928 uint64 + var x929 uint64 + x928, x929 = bits.Add64(x874, x909, uint64(p521Uint1(x927))) + var x930 uint64 + var x931 uint64 + x930, x931 = bits.Add64(x876, x911, uint64(p521Uint1(x929))) + var x932 uint64 + var x933 uint64 + x933, x932 = bits.Mul64(x912, 0x1ff) + var x934 uint64 + var x935 uint64 + x935, x934 = bits.Mul64(x912, 0xffffffffffffffff) + var x936 uint64 + var x937 uint64 + x937, x936 = bits.Mul64(x912, 0xffffffffffffffff) + var x938 uint64 + var x939 uint64 + x939, x938 = bits.Mul64(x912, 0xffffffffffffffff) + var x940 uint64 + var x941 uint64 + x941, x940 = bits.Mul64(x912, 0xffffffffffffffff) + var x942 uint64 + var x943 uint64 + x943, x942 = bits.Mul64(x912, 0xffffffffffffffff) + var x944 uint64 + var x945 uint64 + x945, x944 = bits.Mul64(x912, 0xffffffffffffffff) + var x946 uint64 + var x947 uint64 + x947, x946 = bits.Mul64(x912, 0xffffffffffffffff) + var x948 uint64 + var x949 uint64 + x949, x948 = bits.Mul64(x912, 0xffffffffffffffff) + var x950 uint64 + var x951 uint64 + x950, x951 = bits.Add64(x949, x946, uint64(0x0)) + var x952 uint64 + var x953 uint64 + x952, x953 = bits.Add64(x947, x944, uint64(p521Uint1(x951))) + var x954 uint64 + var x955 uint64 + x954, x955 = bits.Add64(x945, x942, uint64(p521Uint1(x953))) + var x956 uint64 + var x957 uint64 + x956, x957 = bits.Add64(x943, x940, uint64(p521Uint1(x955))) + var x958 uint64 + var x959 uint64 + x958, x959 = bits.Add64(x941, x938, uint64(p521Uint1(x957))) + var x960 uint64 + var x961 uint64 + x960, x961 = bits.Add64(x939, x936, uint64(p521Uint1(x959))) + var x962 uint64 + var x963 uint64 + x962, x963 = bits.Add64(x937, x934, uint64(p521Uint1(x961))) + var x964 uint64 + var x965 uint64 + x964, x965 = bits.Add64(x935, x932, uint64(p521Uint1(x963))) + x966 := (uint64(p521Uint1(x965)) + x933) + var x968 uint64 + _, x968 = bits.Add64(x912, x948, uint64(0x0)) + var x969 uint64 + var x970 uint64 + x969, x970 = bits.Add64(x914, x950, uint64(p521Uint1(x968))) + var x971 uint64 + var x972 uint64 + x971, x972 = bits.Add64(x916, x952, uint64(p521Uint1(x970))) + var x973 uint64 + var x974 uint64 + x973, x974 = bits.Add64(x918, x954, uint64(p521Uint1(x972))) + var x975 uint64 + var x976 uint64 + x975, x976 = bits.Add64(x920, x956, uint64(p521Uint1(x974))) + var x977 uint64 + var x978 uint64 + x977, x978 = bits.Add64(x922, x958, uint64(p521Uint1(x976))) + var x979 uint64 + var x980 uint64 + x979, x980 = bits.Add64(x924, x960, uint64(p521Uint1(x978))) + var x981 uint64 + var x982 uint64 + x981, x982 = bits.Add64(x926, x962, uint64(p521Uint1(x980))) + var x983 uint64 + var x984 uint64 + x983, x984 = bits.Add64(x928, x964, uint64(p521Uint1(x982))) + var x985 uint64 + var x986 uint64 + x985, x986 = bits.Add64(x930, x966, uint64(p521Uint1(x984))) + x987 := (uint64(p521Uint1(x986)) + uint64(p521Uint1(x931))) + var x988 uint64 + var x989 uint64 + x988, x989 = bits.Sub64(x969, 0xffffffffffffffff, uint64(0x0)) + var x990 uint64 + var x991 uint64 + x990, x991 = bits.Sub64(x971, 0xffffffffffffffff, uint64(p521Uint1(x989))) + var x992 uint64 + var x993 uint64 + x992, x993 = bits.Sub64(x973, 0xffffffffffffffff, uint64(p521Uint1(x991))) + var x994 uint64 + var x995 uint64 + x994, x995 = bits.Sub64(x975, 0xffffffffffffffff, uint64(p521Uint1(x993))) + var x996 uint64 + var x997 uint64 + x996, x997 = bits.Sub64(x977, 0xffffffffffffffff, uint64(p521Uint1(x995))) + var x998 uint64 + var x999 uint64 + x998, x999 = bits.Sub64(x979, 0xffffffffffffffff, uint64(p521Uint1(x997))) + var x1000 uint64 + var x1001 uint64 + x1000, x1001 = bits.Sub64(x981, 0xffffffffffffffff, uint64(p521Uint1(x999))) + var x1002 uint64 + var x1003 uint64 + x1002, x1003 = bits.Sub64(x983, 0xffffffffffffffff, uint64(p521Uint1(x1001))) + var x1004 uint64 + var x1005 uint64 + x1004, x1005 = bits.Sub64(x985, 0x1ff, uint64(p521Uint1(x1003))) + var x1007 uint64 + _, x1007 = bits.Sub64(x987, uint64(0x0), uint64(p521Uint1(x1005))) + var x1008 uint64 + p521CmovznzU64(&x1008, p521Uint1(x1007), x988, x969) + var x1009 uint64 + p521CmovznzU64(&x1009, p521Uint1(x1007), x990, x971) + var x1010 uint64 + p521CmovznzU64(&x1010, p521Uint1(x1007), x992, x973) + var x1011 uint64 + p521CmovznzU64(&x1011, p521Uint1(x1007), x994, x975) + var x1012 uint64 + p521CmovznzU64(&x1012, p521Uint1(x1007), x996, x977) + var x1013 uint64 + p521CmovznzU64(&x1013, p521Uint1(x1007), x998, x979) + var x1014 uint64 + p521CmovznzU64(&x1014, p521Uint1(x1007), x1000, x981) + var x1015 uint64 + p521CmovznzU64(&x1015, p521Uint1(x1007), x1002, x983) + var x1016 uint64 + p521CmovznzU64(&x1016, p521Uint1(x1007), x1004, x985) + out1[0] = x1008 + out1[1] = x1009 + out1[2] = x1010 + out1[3] = x1011 + out1[4] = x1012 + out1[5] = x1013 + out1[6] = x1014 + out1[7] = x1015 + out1[8] = x1016 +} + +// p521Add adds two field elements in the Montgomery domain. +// +// Preconditions: +// 0 ≤ eval arg1 < m +// 0 ≤ eval arg2 < m +// Postconditions: +// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) + eval (from_montgomery arg2)) mod m +// 0 ≤ eval out1 < m +// +func p521Add(out1 *p521MontgomeryDomainFieldElement, arg1 *p521MontgomeryDomainFieldElement, arg2 *p521MontgomeryDomainFieldElement) { + var x1 uint64 + var x2 uint64 + x1, x2 = bits.Add64(arg1[0], arg2[0], uint64(0x0)) + var x3 uint64 + var x4 uint64 + x3, x4 = bits.Add64(arg1[1], arg2[1], uint64(p521Uint1(x2))) + var x5 uint64 + var x6 uint64 + x5, x6 = bits.Add64(arg1[2], arg2[2], uint64(p521Uint1(x4))) + var x7 uint64 + var x8 uint64 + x7, x8 = bits.Add64(arg1[3], arg2[3], uint64(p521Uint1(x6))) + var x9 uint64 + var x10 uint64 + x9, x10 = bits.Add64(arg1[4], arg2[4], uint64(p521Uint1(x8))) + var x11 uint64 + var x12 uint64 + x11, x12 = bits.Add64(arg1[5], arg2[5], uint64(p521Uint1(x10))) + var x13 uint64 + var x14 uint64 + x13, x14 = bits.Add64(arg1[6], arg2[6], uint64(p521Uint1(x12))) + var x15 uint64 + var x16 uint64 + x15, x16 = bits.Add64(arg1[7], arg2[7], uint64(p521Uint1(x14))) + var x17 uint64 + var x18 uint64 + x17, x18 = bits.Add64(arg1[8], arg2[8], uint64(p521Uint1(x16))) + var x19 uint64 + var x20 uint64 + x19, x20 = bits.Sub64(x1, 0xffffffffffffffff, uint64(0x0)) + var x21 uint64 + var x22 uint64 + x21, x22 = bits.Sub64(x3, 0xffffffffffffffff, uint64(p521Uint1(x20))) + var x23 uint64 + var x24 uint64 + x23, x24 = bits.Sub64(x5, 0xffffffffffffffff, uint64(p521Uint1(x22))) + var x25 uint64 + var x26 uint64 + x25, x26 = bits.Sub64(x7, 0xffffffffffffffff, uint64(p521Uint1(x24))) + var x27 uint64 + var x28 uint64 + x27, x28 = bits.Sub64(x9, 0xffffffffffffffff, uint64(p521Uint1(x26))) + var x29 uint64 + var x30 uint64 + x29, x30 = bits.Sub64(x11, 0xffffffffffffffff, uint64(p521Uint1(x28))) + var x31 uint64 + var x32 uint64 + x31, x32 = bits.Sub64(x13, 0xffffffffffffffff, uint64(p521Uint1(x30))) + var x33 uint64 + var x34 uint64 + x33, x34 = bits.Sub64(x15, 0xffffffffffffffff, uint64(p521Uint1(x32))) + var x35 uint64 + var x36 uint64 + x35, x36 = bits.Sub64(x17, 0x1ff, uint64(p521Uint1(x34))) + var x38 uint64 + _, x38 = bits.Sub64(uint64(p521Uint1(x18)), uint64(0x0), uint64(p521Uint1(x36))) + var x39 uint64 + p521CmovznzU64(&x39, p521Uint1(x38), x19, x1) + var x40 uint64 + p521CmovznzU64(&x40, p521Uint1(x38), x21, x3) + var x41 uint64 + p521CmovznzU64(&x41, p521Uint1(x38), x23, x5) + var x42 uint64 + p521CmovznzU64(&x42, p521Uint1(x38), x25, x7) + var x43 uint64 + p521CmovznzU64(&x43, p521Uint1(x38), x27, x9) + var x44 uint64 + p521CmovznzU64(&x44, p521Uint1(x38), x29, x11) + var x45 uint64 + p521CmovznzU64(&x45, p521Uint1(x38), x31, x13) + var x46 uint64 + p521CmovznzU64(&x46, p521Uint1(x38), x33, x15) + var x47 uint64 + p521CmovznzU64(&x47, p521Uint1(x38), x35, x17) + out1[0] = x39 + out1[1] = x40 + out1[2] = x41 + out1[3] = x42 + out1[4] = x43 + out1[5] = x44 + out1[6] = x45 + out1[7] = x46 + out1[8] = x47 +} + +// p521Sub subtracts two field elements in the Montgomery domain. +// +// Preconditions: +// 0 ≤ eval arg1 < m +// 0 ≤ eval arg2 < m +// Postconditions: +// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) - eval (from_montgomery arg2)) mod m +// 0 ≤ eval out1 < m +// +func p521Sub(out1 *p521MontgomeryDomainFieldElement, arg1 *p521MontgomeryDomainFieldElement, arg2 *p521MontgomeryDomainFieldElement) { + var x1 uint64 + var x2 uint64 + x1, x2 = bits.Sub64(arg1[0], arg2[0], uint64(0x0)) + var x3 uint64 + var x4 uint64 + x3, x4 = bits.Sub64(arg1[1], arg2[1], uint64(p521Uint1(x2))) + var x5 uint64 + var x6 uint64 + x5, x6 = bits.Sub64(arg1[2], arg2[2], uint64(p521Uint1(x4))) + var x7 uint64 + var x8 uint64 + x7, x8 = bits.Sub64(arg1[3], arg2[3], uint64(p521Uint1(x6))) + var x9 uint64 + var x10 uint64 + x9, x10 = bits.Sub64(arg1[4], arg2[4], uint64(p521Uint1(x8))) + var x11 uint64 + var x12 uint64 + x11, x12 = bits.Sub64(arg1[5], arg2[5], uint64(p521Uint1(x10))) + var x13 uint64 + var x14 uint64 + x13, x14 = bits.Sub64(arg1[6], arg2[6], uint64(p521Uint1(x12))) + var x15 uint64 + var x16 uint64 + x15, x16 = bits.Sub64(arg1[7], arg2[7], uint64(p521Uint1(x14))) + var x17 uint64 + var x18 uint64 + x17, x18 = bits.Sub64(arg1[8], arg2[8], uint64(p521Uint1(x16))) + var x19 uint64 + p521CmovznzU64(&x19, p521Uint1(x18), uint64(0x0), 0xffffffffffffffff) + var x20 uint64 + var x21 uint64 + x20, x21 = bits.Add64(x1, x19, uint64(0x0)) + var x22 uint64 + var x23 uint64 + x22, x23 = bits.Add64(x3, x19, uint64(p521Uint1(x21))) + var x24 uint64 + var x25 uint64 + x24, x25 = bits.Add64(x5, x19, uint64(p521Uint1(x23))) + var x26 uint64 + var x27 uint64 + x26, x27 = bits.Add64(x7, x19, uint64(p521Uint1(x25))) + var x28 uint64 + var x29 uint64 + x28, x29 = bits.Add64(x9, x19, uint64(p521Uint1(x27))) + var x30 uint64 + var x31 uint64 + x30, x31 = bits.Add64(x11, x19, uint64(p521Uint1(x29))) + var x32 uint64 + var x33 uint64 + x32, x33 = bits.Add64(x13, x19, uint64(p521Uint1(x31))) + var x34 uint64 + var x35 uint64 + x34, x35 = bits.Add64(x15, x19, uint64(p521Uint1(x33))) + var x36 uint64 + x36, _ = bits.Add64(x17, (x19 & 0x1ff), uint64(p521Uint1(x35))) + out1[0] = x20 + out1[1] = x22 + out1[2] = x24 + out1[3] = x26 + out1[4] = x28 + out1[5] = x30 + out1[6] = x32 + out1[7] = x34 + out1[8] = x36 +} + +// p521SetOne returns the field element one in the Montgomery domain. +// +// Postconditions: +// eval (from_montgomery out1) mod m = 1 mod m +// 0 ≤ eval out1 < m +// +func p521SetOne(out1 *p521MontgomeryDomainFieldElement) { + out1[0] = 0x80000000000000 + out1[1] = uint64(0x0) + out1[2] = uint64(0x0) + out1[3] = uint64(0x0) + out1[4] = uint64(0x0) + out1[5] = uint64(0x0) + out1[6] = uint64(0x0) + out1[7] = uint64(0x0) + out1[8] = uint64(0x0) +} + +// p521FromMontgomery translates a field element out of the Montgomery domain. +// +// Preconditions: +// 0 ≤ eval arg1 < m +// Postconditions: +// eval out1 mod m = (eval arg1 * ((2^64)⁻¹ mod m)^9) mod m +// 0 ≤ eval out1 < m +// +func p521FromMontgomery(out1 *p521NonMontgomeryDomainFieldElement, arg1 *p521MontgomeryDomainFieldElement) { + x1 := arg1[0] + var x2 uint64 + var x3 uint64 + x3, x2 = bits.Mul64(x1, 0x1ff) + var x4 uint64 + var x5 uint64 + x5, x4 = bits.Mul64(x1, 0xffffffffffffffff) + var x6 uint64 + var x7 uint64 + x7, x6 = bits.Mul64(x1, 0xffffffffffffffff) + var x8 uint64 + var x9 uint64 + x9, x8 = bits.Mul64(x1, 0xffffffffffffffff) + var x10 uint64 + var x11 uint64 + x11, x10 = bits.Mul64(x1, 0xffffffffffffffff) + var x12 uint64 + var x13 uint64 + x13, x12 = bits.Mul64(x1, 0xffffffffffffffff) + var x14 uint64 + var x15 uint64 + x15, x14 = bits.Mul64(x1, 0xffffffffffffffff) + var x16 uint64 + var x17 uint64 + x17, x16 = bits.Mul64(x1, 0xffffffffffffffff) + var x18 uint64 + var x19 uint64 + x19, x18 = bits.Mul64(x1, 0xffffffffffffffff) + var x20 uint64 + var x21 uint64 + x20, x21 = bits.Add64(x19, x16, uint64(0x0)) + var x22 uint64 + var x23 uint64 + x22, x23 = bits.Add64(x17, x14, uint64(p521Uint1(x21))) + var x24 uint64 + var x25 uint64 + x24, x25 = bits.Add64(x15, x12, uint64(p521Uint1(x23))) + var x26 uint64 + var x27 uint64 + x26, x27 = bits.Add64(x13, x10, uint64(p521Uint1(x25))) + var x28 uint64 + var x29 uint64 + x28, x29 = bits.Add64(x11, x8, uint64(p521Uint1(x27))) + var x30 uint64 + var x31 uint64 + x30, x31 = bits.Add64(x9, x6, uint64(p521Uint1(x29))) + var x32 uint64 + var x33 uint64 + x32, x33 = bits.Add64(x7, x4, uint64(p521Uint1(x31))) + var x34 uint64 + var x35 uint64 + x34, x35 = bits.Add64(x5, x2, uint64(p521Uint1(x33))) + var x37 uint64 + _, x37 = bits.Add64(x1, x18, uint64(0x0)) + var x38 uint64 + var x39 uint64 + x38, x39 = bits.Add64(uint64(0x0), x20, uint64(p521Uint1(x37))) + var x40 uint64 + var x41 uint64 + x40, x41 = bits.Add64(uint64(0x0), x22, uint64(p521Uint1(x39))) + var x42 uint64 + var x43 uint64 + x42, x43 = bits.Add64(uint64(0x0), x24, uint64(p521Uint1(x41))) + var x44 uint64 + var x45 uint64 + x44, x45 = bits.Add64(uint64(0x0), x26, uint64(p521Uint1(x43))) + var x46 uint64 + var x47 uint64 + x46, x47 = bits.Add64(uint64(0x0), x28, uint64(p521Uint1(x45))) + var x48 uint64 + var x49 uint64 + x48, x49 = bits.Add64(uint64(0x0), x30, uint64(p521Uint1(x47))) + var x50 uint64 + var x51 uint64 + x50, x51 = bits.Add64(uint64(0x0), x32, uint64(p521Uint1(x49))) + var x52 uint64 + var x53 uint64 + x52, x53 = bits.Add64(uint64(0x0), x34, uint64(p521Uint1(x51))) + var x54 uint64 + var x55 uint64 + x54, x55 = bits.Add64(x38, arg1[1], uint64(0x0)) + var x56 uint64 + var x57 uint64 + x56, x57 = bits.Add64(x40, uint64(0x0), uint64(p521Uint1(x55))) + var x58 uint64 + var x59 uint64 + x58, x59 = bits.Add64(x42, uint64(0x0), uint64(p521Uint1(x57))) + var x60 uint64 + var x61 uint64 + x60, x61 = bits.Add64(x44, uint64(0x0), uint64(p521Uint1(x59))) + var x62 uint64 + var x63 uint64 + x62, x63 = bits.Add64(x46, uint64(0x0), uint64(p521Uint1(x61))) + var x64 uint64 + var x65 uint64 + x64, x65 = bits.Add64(x48, uint64(0x0), uint64(p521Uint1(x63))) + var x66 uint64 + var x67 uint64 + x66, x67 = bits.Add64(x50, uint64(0x0), uint64(p521Uint1(x65))) + var x68 uint64 + var x69 uint64 + x68, x69 = bits.Add64(x52, uint64(0x0), uint64(p521Uint1(x67))) + var x70 uint64 + var x71 uint64 + x71, x70 = bits.Mul64(x54, 0x1ff) + var x72 uint64 + var x73 uint64 + x73, x72 = bits.Mul64(x54, 0xffffffffffffffff) + var x74 uint64 + var x75 uint64 + x75, x74 = bits.Mul64(x54, 0xffffffffffffffff) + var x76 uint64 + var x77 uint64 + x77, x76 = bits.Mul64(x54, 0xffffffffffffffff) + var x78 uint64 + var x79 uint64 + x79, x78 = bits.Mul64(x54, 0xffffffffffffffff) + var x80 uint64 + var x81 uint64 + x81, x80 = bits.Mul64(x54, 0xffffffffffffffff) + var x82 uint64 + var x83 uint64 + x83, x82 = bits.Mul64(x54, 0xffffffffffffffff) + var x84 uint64 + var x85 uint64 + x85, x84 = bits.Mul64(x54, 0xffffffffffffffff) + var x86 uint64 + var x87 uint64 + x87, x86 = bits.Mul64(x54, 0xffffffffffffffff) + var x88 uint64 + var x89 uint64 + x88, x89 = bits.Add64(x87, x84, uint64(0x0)) + var x90 uint64 + var x91 uint64 + x90, x91 = bits.Add64(x85, x82, uint64(p521Uint1(x89))) + var x92 uint64 + var x93 uint64 + x92, x93 = bits.Add64(x83, x80, uint64(p521Uint1(x91))) + var x94 uint64 + var x95 uint64 + x94, x95 = bits.Add64(x81, x78, uint64(p521Uint1(x93))) + var x96 uint64 + var x97 uint64 + x96, x97 = bits.Add64(x79, x76, uint64(p521Uint1(x95))) + var x98 uint64 + var x99 uint64 + x98, x99 = bits.Add64(x77, x74, uint64(p521Uint1(x97))) + var x100 uint64 + var x101 uint64 + x100, x101 = bits.Add64(x75, x72, uint64(p521Uint1(x99))) + var x102 uint64 + var x103 uint64 + x102, x103 = bits.Add64(x73, x70, uint64(p521Uint1(x101))) + var x105 uint64 + _, x105 = bits.Add64(x54, x86, uint64(0x0)) + var x106 uint64 + var x107 uint64 + x106, x107 = bits.Add64(x56, x88, uint64(p521Uint1(x105))) + var x108 uint64 + var x109 uint64 + x108, x109 = bits.Add64(x58, x90, uint64(p521Uint1(x107))) + var x110 uint64 + var x111 uint64 + x110, x111 = bits.Add64(x60, x92, uint64(p521Uint1(x109))) + var x112 uint64 + var x113 uint64 + x112, x113 = bits.Add64(x62, x94, uint64(p521Uint1(x111))) + var x114 uint64 + var x115 uint64 + x114, x115 = bits.Add64(x64, x96, uint64(p521Uint1(x113))) + var x116 uint64 + var x117 uint64 + x116, x117 = bits.Add64(x66, x98, uint64(p521Uint1(x115))) + var x118 uint64 + var x119 uint64 + x118, x119 = bits.Add64(x68, x100, uint64(p521Uint1(x117))) + var x120 uint64 + var x121 uint64 + x120, x121 = bits.Add64((uint64(p521Uint1(x69)) + (uint64(p521Uint1(x53)) + (uint64(p521Uint1(x35)) + x3))), x102, uint64(p521Uint1(x119))) + var x122 uint64 + var x123 uint64 + x122, x123 = bits.Add64(x106, arg1[2], uint64(0x0)) + var x124 uint64 + var x125 uint64 + x124, x125 = bits.Add64(x108, uint64(0x0), uint64(p521Uint1(x123))) + var x126 uint64 + var x127 uint64 + x126, x127 = bits.Add64(x110, uint64(0x0), uint64(p521Uint1(x125))) + var x128 uint64 + var x129 uint64 + x128, x129 = bits.Add64(x112, uint64(0x0), uint64(p521Uint1(x127))) + var x130 uint64 + var x131 uint64 + x130, x131 = bits.Add64(x114, uint64(0x0), uint64(p521Uint1(x129))) + var x132 uint64 + var x133 uint64 + x132, x133 = bits.Add64(x116, uint64(0x0), uint64(p521Uint1(x131))) + var x134 uint64 + var x135 uint64 + x134, x135 = bits.Add64(x118, uint64(0x0), uint64(p521Uint1(x133))) + var x136 uint64 + var x137 uint64 + x136, x137 = bits.Add64(x120, uint64(0x0), uint64(p521Uint1(x135))) + var x138 uint64 + var x139 uint64 + x139, x138 = bits.Mul64(x122, 0x1ff) + var x140 uint64 + var x141 uint64 + x141, x140 = bits.Mul64(x122, 0xffffffffffffffff) + var x142 uint64 + var x143 uint64 + x143, x142 = bits.Mul64(x122, 0xffffffffffffffff) + var x144 uint64 + var x145 uint64 + x145, x144 = bits.Mul64(x122, 0xffffffffffffffff) + var x146 uint64 + var x147 uint64 + x147, x146 = bits.Mul64(x122, 0xffffffffffffffff) + var x148 uint64 + var x149 uint64 + x149, x148 = bits.Mul64(x122, 0xffffffffffffffff) + var x150 uint64 + var x151 uint64 + x151, x150 = bits.Mul64(x122, 0xffffffffffffffff) + var x152 uint64 + var x153 uint64 + x153, x152 = bits.Mul64(x122, 0xffffffffffffffff) + var x154 uint64 + var x155 uint64 + x155, x154 = bits.Mul64(x122, 0xffffffffffffffff) + var x156 uint64 + var x157 uint64 + x156, x157 = bits.Add64(x155, x152, uint64(0x0)) + var x158 uint64 + var x159 uint64 + x158, x159 = bits.Add64(x153, x150, uint64(p521Uint1(x157))) + var x160 uint64 + var x161 uint64 + x160, x161 = bits.Add64(x151, x148, uint64(p521Uint1(x159))) + var x162 uint64 + var x163 uint64 + x162, x163 = bits.Add64(x149, x146, uint64(p521Uint1(x161))) + var x164 uint64 + var x165 uint64 + x164, x165 = bits.Add64(x147, x144, uint64(p521Uint1(x163))) + var x166 uint64 + var x167 uint64 + x166, x167 = bits.Add64(x145, x142, uint64(p521Uint1(x165))) + var x168 uint64 + var x169 uint64 + x168, x169 = bits.Add64(x143, x140, uint64(p521Uint1(x167))) + var x170 uint64 + var x171 uint64 + x170, x171 = bits.Add64(x141, x138, uint64(p521Uint1(x169))) + var x173 uint64 + _, x173 = bits.Add64(x122, x154, uint64(0x0)) + var x174 uint64 + var x175 uint64 + x174, x175 = bits.Add64(x124, x156, uint64(p521Uint1(x173))) + var x176 uint64 + var x177 uint64 + x176, x177 = bits.Add64(x126, x158, uint64(p521Uint1(x175))) + var x178 uint64 + var x179 uint64 + x178, x179 = bits.Add64(x128, x160, uint64(p521Uint1(x177))) + var x180 uint64 + var x181 uint64 + x180, x181 = bits.Add64(x130, x162, uint64(p521Uint1(x179))) + var x182 uint64 + var x183 uint64 + x182, x183 = bits.Add64(x132, x164, uint64(p521Uint1(x181))) + var x184 uint64 + var x185 uint64 + x184, x185 = bits.Add64(x134, x166, uint64(p521Uint1(x183))) + var x186 uint64 + var x187 uint64 + x186, x187 = bits.Add64(x136, x168, uint64(p521Uint1(x185))) + var x188 uint64 + var x189 uint64 + x188, x189 = bits.Add64((uint64(p521Uint1(x137)) + (uint64(p521Uint1(x121)) + (uint64(p521Uint1(x103)) + x71))), x170, uint64(p521Uint1(x187))) + var x190 uint64 + var x191 uint64 + x190, x191 = bits.Add64(x174, arg1[3], uint64(0x0)) + var x192 uint64 + var x193 uint64 + x192, x193 = bits.Add64(x176, uint64(0x0), uint64(p521Uint1(x191))) + var x194 uint64 + var x195 uint64 + x194, x195 = bits.Add64(x178, uint64(0x0), uint64(p521Uint1(x193))) + var x196 uint64 + var x197 uint64 + x196, x197 = bits.Add64(x180, uint64(0x0), uint64(p521Uint1(x195))) + var x198 uint64 + var x199 uint64 + x198, x199 = bits.Add64(x182, uint64(0x0), uint64(p521Uint1(x197))) + var x200 uint64 + var x201 uint64 + x200, x201 = bits.Add64(x184, uint64(0x0), uint64(p521Uint1(x199))) + var x202 uint64 + var x203 uint64 + x202, x203 = bits.Add64(x186, uint64(0x0), uint64(p521Uint1(x201))) + var x204 uint64 + var x205 uint64 + x204, x205 = bits.Add64(x188, uint64(0x0), uint64(p521Uint1(x203))) + var x206 uint64 + var x207 uint64 + x207, x206 = bits.Mul64(x190, 0x1ff) + var x208 uint64 + var x209 uint64 + x209, x208 = bits.Mul64(x190, 0xffffffffffffffff) + var x210 uint64 + var x211 uint64 + x211, x210 = bits.Mul64(x190, 0xffffffffffffffff) + var x212 uint64 + var x213 uint64 + x213, x212 = bits.Mul64(x190, 0xffffffffffffffff) + var x214 uint64 + var x215 uint64 + x215, x214 = bits.Mul64(x190, 0xffffffffffffffff) + var x216 uint64 + var x217 uint64 + x217, x216 = bits.Mul64(x190, 0xffffffffffffffff) + var x218 uint64 + var x219 uint64 + x219, x218 = bits.Mul64(x190, 0xffffffffffffffff) + var x220 uint64 + var x221 uint64 + x221, x220 = bits.Mul64(x190, 0xffffffffffffffff) + var x222 uint64 + var x223 uint64 + x223, x222 = bits.Mul64(x190, 0xffffffffffffffff) + var x224 uint64 + var x225 uint64 + x224, x225 = bits.Add64(x223, x220, uint64(0x0)) + var x226 uint64 + var x227 uint64 + x226, x227 = bits.Add64(x221, x218, uint64(p521Uint1(x225))) + var x228 uint64 + var x229 uint64 + x228, x229 = bits.Add64(x219, x216, uint64(p521Uint1(x227))) + var x230 uint64 + var x231 uint64 + x230, x231 = bits.Add64(x217, x214, uint64(p521Uint1(x229))) + var x232 uint64 + var x233 uint64 + x232, x233 = bits.Add64(x215, x212, uint64(p521Uint1(x231))) + var x234 uint64 + var x235 uint64 + x234, x235 = bits.Add64(x213, x210, uint64(p521Uint1(x233))) + var x236 uint64 + var x237 uint64 + x236, x237 = bits.Add64(x211, x208, uint64(p521Uint1(x235))) + var x238 uint64 + var x239 uint64 + x238, x239 = bits.Add64(x209, x206, uint64(p521Uint1(x237))) + var x241 uint64 + _, x241 = bits.Add64(x190, x222, uint64(0x0)) + var x242 uint64 + var x243 uint64 + x242, x243 = bits.Add64(x192, x224, uint64(p521Uint1(x241))) + var x244 uint64 + var x245 uint64 + x244, x245 = bits.Add64(x194, x226, uint64(p521Uint1(x243))) + var x246 uint64 + var x247 uint64 + x246, x247 = bits.Add64(x196, x228, uint64(p521Uint1(x245))) + var x248 uint64 + var x249 uint64 + x248, x249 = bits.Add64(x198, x230, uint64(p521Uint1(x247))) + var x250 uint64 + var x251 uint64 + x250, x251 = bits.Add64(x200, x232, uint64(p521Uint1(x249))) + var x252 uint64 + var x253 uint64 + x252, x253 = bits.Add64(x202, x234, uint64(p521Uint1(x251))) + var x254 uint64 + var x255 uint64 + x254, x255 = bits.Add64(x204, x236, uint64(p521Uint1(x253))) + var x256 uint64 + var x257 uint64 + x256, x257 = bits.Add64((uint64(p521Uint1(x205)) + (uint64(p521Uint1(x189)) + (uint64(p521Uint1(x171)) + x139))), x238, uint64(p521Uint1(x255))) + var x258 uint64 + var x259 uint64 + x258, x259 = bits.Add64(x242, arg1[4], uint64(0x0)) + var x260 uint64 + var x261 uint64 + x260, x261 = bits.Add64(x244, uint64(0x0), uint64(p521Uint1(x259))) + var x262 uint64 + var x263 uint64 + x262, x263 = bits.Add64(x246, uint64(0x0), uint64(p521Uint1(x261))) + var x264 uint64 + var x265 uint64 + x264, x265 = bits.Add64(x248, uint64(0x0), uint64(p521Uint1(x263))) + var x266 uint64 + var x267 uint64 + x266, x267 = bits.Add64(x250, uint64(0x0), uint64(p521Uint1(x265))) + var x268 uint64 + var x269 uint64 + x268, x269 = bits.Add64(x252, uint64(0x0), uint64(p521Uint1(x267))) + var x270 uint64 + var x271 uint64 + x270, x271 = bits.Add64(x254, uint64(0x0), uint64(p521Uint1(x269))) + var x272 uint64 + var x273 uint64 + x272, x273 = bits.Add64(x256, uint64(0x0), uint64(p521Uint1(x271))) + var x274 uint64 + var x275 uint64 + x275, x274 = bits.Mul64(x258, 0x1ff) + var x276 uint64 + var x277 uint64 + x277, x276 = bits.Mul64(x258, 0xffffffffffffffff) + var x278 uint64 + var x279 uint64 + x279, x278 = bits.Mul64(x258, 0xffffffffffffffff) + var x280 uint64 + var x281 uint64 + x281, x280 = bits.Mul64(x258, 0xffffffffffffffff) + var x282 uint64 + var x283 uint64 + x283, x282 = bits.Mul64(x258, 0xffffffffffffffff) + var x284 uint64 + var x285 uint64 + x285, x284 = bits.Mul64(x258, 0xffffffffffffffff) + var x286 uint64 + var x287 uint64 + x287, x286 = bits.Mul64(x258, 0xffffffffffffffff) + var x288 uint64 + var x289 uint64 + x289, x288 = bits.Mul64(x258, 0xffffffffffffffff) + var x290 uint64 + var x291 uint64 + x291, x290 = bits.Mul64(x258, 0xffffffffffffffff) + var x292 uint64 + var x293 uint64 + x292, x293 = bits.Add64(x291, x288, uint64(0x0)) + var x294 uint64 + var x295 uint64 + x294, x295 = bits.Add64(x289, x286, uint64(p521Uint1(x293))) + var x296 uint64 + var x297 uint64 + x296, x297 = bits.Add64(x287, x284, uint64(p521Uint1(x295))) + var x298 uint64 + var x299 uint64 + x298, x299 = bits.Add64(x285, x282, uint64(p521Uint1(x297))) + var x300 uint64 + var x301 uint64 + x300, x301 = bits.Add64(x283, x280, uint64(p521Uint1(x299))) + var x302 uint64 + var x303 uint64 + x302, x303 = bits.Add64(x281, x278, uint64(p521Uint1(x301))) + var x304 uint64 + var x305 uint64 + x304, x305 = bits.Add64(x279, x276, uint64(p521Uint1(x303))) + var x306 uint64 + var x307 uint64 + x306, x307 = bits.Add64(x277, x274, uint64(p521Uint1(x305))) + var x309 uint64 + _, x309 = bits.Add64(x258, x290, uint64(0x0)) + var x310 uint64 + var x311 uint64 + x310, x311 = bits.Add64(x260, x292, uint64(p521Uint1(x309))) + var x312 uint64 + var x313 uint64 + x312, x313 = bits.Add64(x262, x294, uint64(p521Uint1(x311))) + var x314 uint64 + var x315 uint64 + x314, x315 = bits.Add64(x264, x296, uint64(p521Uint1(x313))) + var x316 uint64 + var x317 uint64 + x316, x317 = bits.Add64(x266, x298, uint64(p521Uint1(x315))) + var x318 uint64 + var x319 uint64 + x318, x319 = bits.Add64(x268, x300, uint64(p521Uint1(x317))) + var x320 uint64 + var x321 uint64 + x320, x321 = bits.Add64(x270, x302, uint64(p521Uint1(x319))) + var x322 uint64 + var x323 uint64 + x322, x323 = bits.Add64(x272, x304, uint64(p521Uint1(x321))) + var x324 uint64 + var x325 uint64 + x324, x325 = bits.Add64((uint64(p521Uint1(x273)) + (uint64(p521Uint1(x257)) + (uint64(p521Uint1(x239)) + x207))), x306, uint64(p521Uint1(x323))) + var x326 uint64 + var x327 uint64 + x326, x327 = bits.Add64(x310, arg1[5], uint64(0x0)) + var x328 uint64 + var x329 uint64 + x328, x329 = bits.Add64(x312, uint64(0x0), uint64(p521Uint1(x327))) + var x330 uint64 + var x331 uint64 + x330, x331 = bits.Add64(x314, uint64(0x0), uint64(p521Uint1(x329))) + var x332 uint64 + var x333 uint64 + x332, x333 = bits.Add64(x316, uint64(0x0), uint64(p521Uint1(x331))) + var x334 uint64 + var x335 uint64 + x334, x335 = bits.Add64(x318, uint64(0x0), uint64(p521Uint1(x333))) + var x336 uint64 + var x337 uint64 + x336, x337 = bits.Add64(x320, uint64(0x0), uint64(p521Uint1(x335))) + var x338 uint64 + var x339 uint64 + x338, x339 = bits.Add64(x322, uint64(0x0), uint64(p521Uint1(x337))) + var x340 uint64 + var x341 uint64 + x340, x341 = bits.Add64(x324, uint64(0x0), uint64(p521Uint1(x339))) + var x342 uint64 + var x343 uint64 + x343, x342 = bits.Mul64(x326, 0x1ff) + var x344 uint64 + var x345 uint64 + x345, x344 = bits.Mul64(x326, 0xffffffffffffffff) + var x346 uint64 + var x347 uint64 + x347, x346 = bits.Mul64(x326, 0xffffffffffffffff) + var x348 uint64 + var x349 uint64 + x349, x348 = bits.Mul64(x326, 0xffffffffffffffff) + var x350 uint64 + var x351 uint64 + x351, x350 = bits.Mul64(x326, 0xffffffffffffffff) + var x352 uint64 + var x353 uint64 + x353, x352 = bits.Mul64(x326, 0xffffffffffffffff) + var x354 uint64 + var x355 uint64 + x355, x354 = bits.Mul64(x326, 0xffffffffffffffff) + var x356 uint64 + var x357 uint64 + x357, x356 = bits.Mul64(x326, 0xffffffffffffffff) + var x358 uint64 + var x359 uint64 + x359, x358 = bits.Mul64(x326, 0xffffffffffffffff) + var x360 uint64 + var x361 uint64 + x360, x361 = bits.Add64(x359, x356, uint64(0x0)) + var x362 uint64 + var x363 uint64 + x362, x363 = bits.Add64(x357, x354, uint64(p521Uint1(x361))) + var x364 uint64 + var x365 uint64 + x364, x365 = bits.Add64(x355, x352, uint64(p521Uint1(x363))) + var x366 uint64 + var x367 uint64 + x366, x367 = bits.Add64(x353, x350, uint64(p521Uint1(x365))) + var x368 uint64 + var x369 uint64 + x368, x369 = bits.Add64(x351, x348, uint64(p521Uint1(x367))) + var x370 uint64 + var x371 uint64 + x370, x371 = bits.Add64(x349, x346, uint64(p521Uint1(x369))) + var x372 uint64 + var x373 uint64 + x372, x373 = bits.Add64(x347, x344, uint64(p521Uint1(x371))) + var x374 uint64 + var x375 uint64 + x374, x375 = bits.Add64(x345, x342, uint64(p521Uint1(x373))) + var x377 uint64 + _, x377 = bits.Add64(x326, x358, uint64(0x0)) + var x378 uint64 + var x379 uint64 + x378, x379 = bits.Add64(x328, x360, uint64(p521Uint1(x377))) + var x380 uint64 + var x381 uint64 + x380, x381 = bits.Add64(x330, x362, uint64(p521Uint1(x379))) + var x382 uint64 + var x383 uint64 + x382, x383 = bits.Add64(x332, x364, uint64(p521Uint1(x381))) + var x384 uint64 + var x385 uint64 + x384, x385 = bits.Add64(x334, x366, uint64(p521Uint1(x383))) + var x386 uint64 + var x387 uint64 + x386, x387 = bits.Add64(x336, x368, uint64(p521Uint1(x385))) + var x388 uint64 + var x389 uint64 + x388, x389 = bits.Add64(x338, x370, uint64(p521Uint1(x387))) + var x390 uint64 + var x391 uint64 + x390, x391 = bits.Add64(x340, x372, uint64(p521Uint1(x389))) + var x392 uint64 + var x393 uint64 + x392, x393 = bits.Add64((uint64(p521Uint1(x341)) + (uint64(p521Uint1(x325)) + (uint64(p521Uint1(x307)) + x275))), x374, uint64(p521Uint1(x391))) + var x394 uint64 + var x395 uint64 + x394, x395 = bits.Add64(x378, arg1[6], uint64(0x0)) + var x396 uint64 + var x397 uint64 + x396, x397 = bits.Add64(x380, uint64(0x0), uint64(p521Uint1(x395))) + var x398 uint64 + var x399 uint64 + x398, x399 = bits.Add64(x382, uint64(0x0), uint64(p521Uint1(x397))) + var x400 uint64 + var x401 uint64 + x400, x401 = bits.Add64(x384, uint64(0x0), uint64(p521Uint1(x399))) + var x402 uint64 + var x403 uint64 + x402, x403 = bits.Add64(x386, uint64(0x0), uint64(p521Uint1(x401))) + var x404 uint64 + var x405 uint64 + x404, x405 = bits.Add64(x388, uint64(0x0), uint64(p521Uint1(x403))) + var x406 uint64 + var x407 uint64 + x406, x407 = bits.Add64(x390, uint64(0x0), uint64(p521Uint1(x405))) + var x408 uint64 + var x409 uint64 + x408, x409 = bits.Add64(x392, uint64(0x0), uint64(p521Uint1(x407))) + var x410 uint64 + var x411 uint64 + x411, x410 = bits.Mul64(x394, 0x1ff) + var x412 uint64 + var x413 uint64 + x413, x412 = bits.Mul64(x394, 0xffffffffffffffff) + var x414 uint64 + var x415 uint64 + x415, x414 = bits.Mul64(x394, 0xffffffffffffffff) + var x416 uint64 + var x417 uint64 + x417, x416 = bits.Mul64(x394, 0xffffffffffffffff) + var x418 uint64 + var x419 uint64 + x419, x418 = bits.Mul64(x394, 0xffffffffffffffff) + var x420 uint64 + var x421 uint64 + x421, x420 = bits.Mul64(x394, 0xffffffffffffffff) + var x422 uint64 + var x423 uint64 + x423, x422 = bits.Mul64(x394, 0xffffffffffffffff) + var x424 uint64 + var x425 uint64 + x425, x424 = bits.Mul64(x394, 0xffffffffffffffff) + var x426 uint64 + var x427 uint64 + x427, x426 = bits.Mul64(x394, 0xffffffffffffffff) + var x428 uint64 + var x429 uint64 + x428, x429 = bits.Add64(x427, x424, uint64(0x0)) + var x430 uint64 + var x431 uint64 + x430, x431 = bits.Add64(x425, x422, uint64(p521Uint1(x429))) + var x432 uint64 + var x433 uint64 + x432, x433 = bits.Add64(x423, x420, uint64(p521Uint1(x431))) + var x434 uint64 + var x435 uint64 + x434, x435 = bits.Add64(x421, x418, uint64(p521Uint1(x433))) + var x436 uint64 + var x437 uint64 + x436, x437 = bits.Add64(x419, x416, uint64(p521Uint1(x435))) + var x438 uint64 + var x439 uint64 + x438, x439 = bits.Add64(x417, x414, uint64(p521Uint1(x437))) + var x440 uint64 + var x441 uint64 + x440, x441 = bits.Add64(x415, x412, uint64(p521Uint1(x439))) + var x442 uint64 + var x443 uint64 + x442, x443 = bits.Add64(x413, x410, uint64(p521Uint1(x441))) + var x445 uint64 + _, x445 = bits.Add64(x394, x426, uint64(0x0)) + var x446 uint64 + var x447 uint64 + x446, x447 = bits.Add64(x396, x428, uint64(p521Uint1(x445))) + var x448 uint64 + var x449 uint64 + x448, x449 = bits.Add64(x398, x430, uint64(p521Uint1(x447))) + var x450 uint64 + var x451 uint64 + x450, x451 = bits.Add64(x400, x432, uint64(p521Uint1(x449))) + var x452 uint64 + var x453 uint64 + x452, x453 = bits.Add64(x402, x434, uint64(p521Uint1(x451))) + var x454 uint64 + var x455 uint64 + x454, x455 = bits.Add64(x404, x436, uint64(p521Uint1(x453))) + var x456 uint64 + var x457 uint64 + x456, x457 = bits.Add64(x406, x438, uint64(p521Uint1(x455))) + var x458 uint64 + var x459 uint64 + x458, x459 = bits.Add64(x408, x440, uint64(p521Uint1(x457))) + var x460 uint64 + var x461 uint64 + x460, x461 = bits.Add64((uint64(p521Uint1(x409)) + (uint64(p521Uint1(x393)) + (uint64(p521Uint1(x375)) + x343))), x442, uint64(p521Uint1(x459))) + var x462 uint64 + var x463 uint64 + x462, x463 = bits.Add64(x446, arg1[7], uint64(0x0)) + var x464 uint64 + var x465 uint64 + x464, x465 = bits.Add64(x448, uint64(0x0), uint64(p521Uint1(x463))) + var x466 uint64 + var x467 uint64 + x466, x467 = bits.Add64(x450, uint64(0x0), uint64(p521Uint1(x465))) + var x468 uint64 + var x469 uint64 + x468, x469 = bits.Add64(x452, uint64(0x0), uint64(p521Uint1(x467))) + var x470 uint64 + var x471 uint64 + x470, x471 = bits.Add64(x454, uint64(0x0), uint64(p521Uint1(x469))) + var x472 uint64 + var x473 uint64 + x472, x473 = bits.Add64(x456, uint64(0x0), uint64(p521Uint1(x471))) + var x474 uint64 + var x475 uint64 + x474, x475 = bits.Add64(x458, uint64(0x0), uint64(p521Uint1(x473))) + var x476 uint64 + var x477 uint64 + x476, x477 = bits.Add64(x460, uint64(0x0), uint64(p521Uint1(x475))) + var x478 uint64 + var x479 uint64 + x479, x478 = bits.Mul64(x462, 0x1ff) + var x480 uint64 + var x481 uint64 + x481, x480 = bits.Mul64(x462, 0xffffffffffffffff) + var x482 uint64 + var x483 uint64 + x483, x482 = bits.Mul64(x462, 0xffffffffffffffff) + var x484 uint64 + var x485 uint64 + x485, x484 = bits.Mul64(x462, 0xffffffffffffffff) + var x486 uint64 + var x487 uint64 + x487, x486 = bits.Mul64(x462, 0xffffffffffffffff) + var x488 uint64 + var x489 uint64 + x489, x488 = bits.Mul64(x462, 0xffffffffffffffff) + var x490 uint64 + var x491 uint64 + x491, x490 = bits.Mul64(x462, 0xffffffffffffffff) + var x492 uint64 + var x493 uint64 + x493, x492 = bits.Mul64(x462, 0xffffffffffffffff) + var x494 uint64 + var x495 uint64 + x495, x494 = bits.Mul64(x462, 0xffffffffffffffff) + var x496 uint64 + var x497 uint64 + x496, x497 = bits.Add64(x495, x492, uint64(0x0)) + var x498 uint64 + var x499 uint64 + x498, x499 = bits.Add64(x493, x490, uint64(p521Uint1(x497))) + var x500 uint64 + var x501 uint64 + x500, x501 = bits.Add64(x491, x488, uint64(p521Uint1(x499))) + var x502 uint64 + var x503 uint64 + x502, x503 = bits.Add64(x489, x486, uint64(p521Uint1(x501))) + var x504 uint64 + var x505 uint64 + x504, x505 = bits.Add64(x487, x484, uint64(p521Uint1(x503))) + var x506 uint64 + var x507 uint64 + x506, x507 = bits.Add64(x485, x482, uint64(p521Uint1(x505))) + var x508 uint64 + var x509 uint64 + x508, x509 = bits.Add64(x483, x480, uint64(p521Uint1(x507))) + var x510 uint64 + var x511 uint64 + x510, x511 = bits.Add64(x481, x478, uint64(p521Uint1(x509))) + var x513 uint64 + _, x513 = bits.Add64(x462, x494, uint64(0x0)) + var x514 uint64 + var x515 uint64 + x514, x515 = bits.Add64(x464, x496, uint64(p521Uint1(x513))) + var x516 uint64 + var x517 uint64 + x516, x517 = bits.Add64(x466, x498, uint64(p521Uint1(x515))) + var x518 uint64 + var x519 uint64 + x518, x519 = bits.Add64(x468, x500, uint64(p521Uint1(x517))) + var x520 uint64 + var x521 uint64 + x520, x521 = bits.Add64(x470, x502, uint64(p521Uint1(x519))) + var x522 uint64 + var x523 uint64 + x522, x523 = bits.Add64(x472, x504, uint64(p521Uint1(x521))) + var x524 uint64 + var x525 uint64 + x524, x525 = bits.Add64(x474, x506, uint64(p521Uint1(x523))) + var x526 uint64 + var x527 uint64 + x526, x527 = bits.Add64(x476, x508, uint64(p521Uint1(x525))) + var x528 uint64 + var x529 uint64 + x528, x529 = bits.Add64((uint64(p521Uint1(x477)) + (uint64(p521Uint1(x461)) + (uint64(p521Uint1(x443)) + x411))), x510, uint64(p521Uint1(x527))) + var x530 uint64 + var x531 uint64 + x530, x531 = bits.Add64(x514, arg1[8], uint64(0x0)) + var x532 uint64 + var x533 uint64 + x532, x533 = bits.Add64(x516, uint64(0x0), uint64(p521Uint1(x531))) + var x534 uint64 + var x535 uint64 + x534, x535 = bits.Add64(x518, uint64(0x0), uint64(p521Uint1(x533))) + var x536 uint64 + var x537 uint64 + x536, x537 = bits.Add64(x520, uint64(0x0), uint64(p521Uint1(x535))) + var x538 uint64 + var x539 uint64 + x538, x539 = bits.Add64(x522, uint64(0x0), uint64(p521Uint1(x537))) + var x540 uint64 + var x541 uint64 + x540, x541 = bits.Add64(x524, uint64(0x0), uint64(p521Uint1(x539))) + var x542 uint64 + var x543 uint64 + x542, x543 = bits.Add64(x526, uint64(0x0), uint64(p521Uint1(x541))) + var x544 uint64 + var x545 uint64 + x544, x545 = bits.Add64(x528, uint64(0x0), uint64(p521Uint1(x543))) + var x546 uint64 + var x547 uint64 + x547, x546 = bits.Mul64(x530, 0x1ff) + var x548 uint64 + var x549 uint64 + x549, x548 = bits.Mul64(x530, 0xffffffffffffffff) + var x550 uint64 + var x551 uint64 + x551, x550 = bits.Mul64(x530, 0xffffffffffffffff) + var x552 uint64 + var x553 uint64 + x553, x552 = bits.Mul64(x530, 0xffffffffffffffff) + var x554 uint64 + var x555 uint64 + x555, x554 = bits.Mul64(x530, 0xffffffffffffffff) + var x556 uint64 + var x557 uint64 + x557, x556 = bits.Mul64(x530, 0xffffffffffffffff) + var x558 uint64 + var x559 uint64 + x559, x558 = bits.Mul64(x530, 0xffffffffffffffff) + var x560 uint64 + var x561 uint64 + x561, x560 = bits.Mul64(x530, 0xffffffffffffffff) + var x562 uint64 + var x563 uint64 + x563, x562 = bits.Mul64(x530, 0xffffffffffffffff) + var x564 uint64 + var x565 uint64 + x564, x565 = bits.Add64(x563, x560, uint64(0x0)) + var x566 uint64 + var x567 uint64 + x566, x567 = bits.Add64(x561, x558, uint64(p521Uint1(x565))) + var x568 uint64 + var x569 uint64 + x568, x569 = bits.Add64(x559, x556, uint64(p521Uint1(x567))) + var x570 uint64 + var x571 uint64 + x570, x571 = bits.Add64(x557, x554, uint64(p521Uint1(x569))) + var x572 uint64 + var x573 uint64 + x572, x573 = bits.Add64(x555, x552, uint64(p521Uint1(x571))) + var x574 uint64 + var x575 uint64 + x574, x575 = bits.Add64(x553, x550, uint64(p521Uint1(x573))) + var x576 uint64 + var x577 uint64 + x576, x577 = bits.Add64(x551, x548, uint64(p521Uint1(x575))) + var x578 uint64 + var x579 uint64 + x578, x579 = bits.Add64(x549, x546, uint64(p521Uint1(x577))) + var x581 uint64 + _, x581 = bits.Add64(x530, x562, uint64(0x0)) + var x582 uint64 + var x583 uint64 + x582, x583 = bits.Add64(x532, x564, uint64(p521Uint1(x581))) + var x584 uint64 + var x585 uint64 + x584, x585 = bits.Add64(x534, x566, uint64(p521Uint1(x583))) + var x586 uint64 + var x587 uint64 + x586, x587 = bits.Add64(x536, x568, uint64(p521Uint1(x585))) + var x588 uint64 + var x589 uint64 + x588, x589 = bits.Add64(x538, x570, uint64(p521Uint1(x587))) + var x590 uint64 + var x591 uint64 + x590, x591 = bits.Add64(x540, x572, uint64(p521Uint1(x589))) + var x592 uint64 + var x593 uint64 + x592, x593 = bits.Add64(x542, x574, uint64(p521Uint1(x591))) + var x594 uint64 + var x595 uint64 + x594, x595 = bits.Add64(x544, x576, uint64(p521Uint1(x593))) + var x596 uint64 + var x597 uint64 + x596, x597 = bits.Add64((uint64(p521Uint1(x545)) + (uint64(p521Uint1(x529)) + (uint64(p521Uint1(x511)) + x479))), x578, uint64(p521Uint1(x595))) + x598 := (uint64(p521Uint1(x597)) + (uint64(p521Uint1(x579)) + x547)) + var x599 uint64 + var x600 uint64 + x599, x600 = bits.Sub64(x582, 0xffffffffffffffff, uint64(0x0)) + var x601 uint64 + var x602 uint64 + x601, x602 = bits.Sub64(x584, 0xffffffffffffffff, uint64(p521Uint1(x600))) + var x603 uint64 + var x604 uint64 + x603, x604 = bits.Sub64(x586, 0xffffffffffffffff, uint64(p521Uint1(x602))) + var x605 uint64 + var x606 uint64 + x605, x606 = bits.Sub64(x588, 0xffffffffffffffff, uint64(p521Uint1(x604))) + var x607 uint64 + var x608 uint64 + x607, x608 = bits.Sub64(x590, 0xffffffffffffffff, uint64(p521Uint1(x606))) + var x609 uint64 + var x610 uint64 + x609, x610 = bits.Sub64(x592, 0xffffffffffffffff, uint64(p521Uint1(x608))) + var x611 uint64 + var x612 uint64 + x611, x612 = bits.Sub64(x594, 0xffffffffffffffff, uint64(p521Uint1(x610))) + var x613 uint64 + var x614 uint64 + x613, x614 = bits.Sub64(x596, 0xffffffffffffffff, uint64(p521Uint1(x612))) + var x615 uint64 + var x616 uint64 + x615, x616 = bits.Sub64(x598, 0x1ff, uint64(p521Uint1(x614))) + var x618 uint64 + _, x618 = bits.Sub64(uint64(0x0), uint64(0x0), uint64(p521Uint1(x616))) + var x619 uint64 + p521CmovznzU64(&x619, p521Uint1(x618), x599, x582) + var x620 uint64 + p521CmovznzU64(&x620, p521Uint1(x618), x601, x584) + var x621 uint64 + p521CmovznzU64(&x621, p521Uint1(x618), x603, x586) + var x622 uint64 + p521CmovznzU64(&x622, p521Uint1(x618), x605, x588) + var x623 uint64 + p521CmovznzU64(&x623, p521Uint1(x618), x607, x590) + var x624 uint64 + p521CmovznzU64(&x624, p521Uint1(x618), x609, x592) + var x625 uint64 + p521CmovznzU64(&x625, p521Uint1(x618), x611, x594) + var x626 uint64 + p521CmovznzU64(&x626, p521Uint1(x618), x613, x596) + var x627 uint64 + p521CmovznzU64(&x627, p521Uint1(x618), x615, x598) + out1[0] = x619 + out1[1] = x620 + out1[2] = x621 + out1[3] = x622 + out1[4] = x623 + out1[5] = x624 + out1[6] = x625 + out1[7] = x626 + out1[8] = x627 +} + +// p521ToMontgomery translates a field element into the Montgomery domain. +// +// Preconditions: +// 0 ≤ eval arg1 < m +// Postconditions: +// eval (from_montgomery out1) mod m = eval arg1 mod m +// 0 ≤ eval out1 < m +// +func p521ToMontgomery(out1 *p521MontgomeryDomainFieldElement, arg1 *p521NonMontgomeryDomainFieldElement) { + var x1 uint64 + var x2 uint64 + x2, x1 = bits.Mul64(arg1[0], 0x400000000000) + var x3 uint64 + var x4 uint64 + x4, x3 = bits.Mul64(arg1[1], 0x400000000000) + var x5 uint64 + var x6 uint64 + x5, x6 = bits.Add64(x2, x3, uint64(0x0)) + var x7 uint64 + var x8 uint64 + x8, x7 = bits.Mul64(x1, 0x1ff) + var x9 uint64 + var x10 uint64 + x10, x9 = bits.Mul64(x1, 0xffffffffffffffff) + var x11 uint64 + var x12 uint64 + x12, x11 = bits.Mul64(x1, 0xffffffffffffffff) + var x13 uint64 + var x14 uint64 + x14, x13 = bits.Mul64(x1, 0xffffffffffffffff) + var x15 uint64 + var x16 uint64 + x16, x15 = bits.Mul64(x1, 0xffffffffffffffff) + var x17 uint64 + var x18 uint64 + x18, x17 = bits.Mul64(x1, 0xffffffffffffffff) + var x19 uint64 + var x20 uint64 + x20, x19 = bits.Mul64(x1, 0xffffffffffffffff) + var x21 uint64 + var x22 uint64 + x22, x21 = bits.Mul64(x1, 0xffffffffffffffff) + var x23 uint64 + var x24 uint64 + x24, x23 = bits.Mul64(x1, 0xffffffffffffffff) + var x25 uint64 + var x26 uint64 + x25, x26 = bits.Add64(x24, x21, uint64(0x0)) + var x27 uint64 + var x28 uint64 + x27, x28 = bits.Add64(x22, x19, uint64(p521Uint1(x26))) + var x29 uint64 + var x30 uint64 + x29, x30 = bits.Add64(x20, x17, uint64(p521Uint1(x28))) + var x31 uint64 + var x32 uint64 + x31, x32 = bits.Add64(x18, x15, uint64(p521Uint1(x30))) + var x33 uint64 + var x34 uint64 + x33, x34 = bits.Add64(x16, x13, uint64(p521Uint1(x32))) + var x35 uint64 + var x36 uint64 + x35, x36 = bits.Add64(x14, x11, uint64(p521Uint1(x34))) + var x37 uint64 + var x38 uint64 + x37, x38 = bits.Add64(x12, x9, uint64(p521Uint1(x36))) + var x39 uint64 + var x40 uint64 + x39, x40 = bits.Add64(x10, x7, uint64(p521Uint1(x38))) + var x42 uint64 + _, x42 = bits.Add64(x1, x23, uint64(0x0)) + var x43 uint64 + var x44 uint64 + x43, x44 = bits.Add64(x5, x25, uint64(p521Uint1(x42))) + var x45 uint64 + var x46 uint64 + x45, x46 = bits.Add64((uint64(p521Uint1(x6)) + x4), x27, uint64(p521Uint1(x44))) + var x47 uint64 + var x48 uint64 + x47, x48 = bits.Add64(uint64(0x0), x29, uint64(p521Uint1(x46))) + var x49 uint64 + var x50 uint64 + x49, x50 = bits.Add64(uint64(0x0), x31, uint64(p521Uint1(x48))) + var x51 uint64 + var x52 uint64 + x51, x52 = bits.Add64(uint64(0x0), x33, uint64(p521Uint1(x50))) + var x53 uint64 + var x54 uint64 + x53, x54 = bits.Add64(uint64(0x0), x35, uint64(p521Uint1(x52))) + var x55 uint64 + var x56 uint64 + x55, x56 = bits.Add64(uint64(0x0), x37, uint64(p521Uint1(x54))) + var x57 uint64 + var x58 uint64 + x57, x58 = bits.Add64(uint64(0x0), x39, uint64(p521Uint1(x56))) + var x59 uint64 + var x60 uint64 + x60, x59 = bits.Mul64(arg1[2], 0x400000000000) + var x61 uint64 + var x62 uint64 + x61, x62 = bits.Add64(x45, x59, uint64(0x0)) + var x63 uint64 + var x64 uint64 + x63, x64 = bits.Add64(x47, x60, uint64(p521Uint1(x62))) + var x65 uint64 + var x66 uint64 + x65, x66 = bits.Add64(x49, uint64(0x0), uint64(p521Uint1(x64))) + var x67 uint64 + var x68 uint64 + x67, x68 = bits.Add64(x51, uint64(0x0), uint64(p521Uint1(x66))) + var x69 uint64 + var x70 uint64 + x69, x70 = bits.Add64(x53, uint64(0x0), uint64(p521Uint1(x68))) + var x71 uint64 + var x72 uint64 + x71, x72 = bits.Add64(x55, uint64(0x0), uint64(p521Uint1(x70))) + var x73 uint64 + var x74 uint64 + x73, x74 = bits.Add64(x57, uint64(0x0), uint64(p521Uint1(x72))) + var x75 uint64 + var x76 uint64 + x76, x75 = bits.Mul64(x43, 0x1ff) + var x77 uint64 + var x78 uint64 + x78, x77 = bits.Mul64(x43, 0xffffffffffffffff) var x79 uint64 var x80 uint64 - x80, x79 = bits.Mul64(arg1[1], x12) + x80, x79 = bits.Mul64(x43, 0xffffffffffffffff) var x81 uint64 var x82 uint64 - x82, x81 = bits.Mul64(arg1[1], x13) + x82, x81 = bits.Mul64(x43, 0xffffffffffffffff) var x83 uint64 var x84 uint64 - x84, x83 = bits.Mul64(arg1[1], x14) + x84, x83 = bits.Mul64(x43, 0xffffffffffffffff) var x85 uint64 var x86 uint64 - x86, x85 = bits.Mul64(arg1[1], x15) + x86, x85 = bits.Mul64(x43, 0xffffffffffffffff) var x87 uint64 var x88 uint64 - x88, x87 = bits.Mul64(arg1[1], arg1[1]) + x88, x87 = bits.Mul64(x43, 0xffffffffffffffff) var x89 uint64 var x90 uint64 - x90, x89 = bits.Mul64(arg1[0], x3) + x90, x89 = bits.Mul64(x43, 0xffffffffffffffff) var x91 uint64 var x92 uint64 - x92, x91 = bits.Mul64(arg1[0], x6) + x92, x91 = bits.Mul64(x43, 0xffffffffffffffff) var x93 uint64 var x94 uint64 - x94, x93 = bits.Mul64(arg1[0], x9) + x93, x94 = bits.Add64(x92, x89, uint64(0x0)) var x95 uint64 var x96 uint64 - x96, x95 = bits.Mul64(arg1[0], x12) + x95, x96 = bits.Add64(x90, x87, uint64(p521Uint1(x94))) var x97 uint64 var x98 uint64 - x98, x97 = bits.Mul64(arg1[0], x13) + x97, x98 = bits.Add64(x88, x85, uint64(p521Uint1(x96))) var x99 uint64 var x100 uint64 - x100, x99 = bits.Mul64(arg1[0], x14) + x99, x100 = bits.Add64(x86, x83, uint64(p521Uint1(x98))) var x101 uint64 var x102 uint64 - x102, x101 = bits.Mul64(arg1[0], x15) + x101, x102 = bits.Add64(x84, x81, uint64(p521Uint1(x100))) var x103 uint64 var x104 uint64 - x104, x103 = bits.Mul64(arg1[0], x16) + x103, x104 = bits.Add64(x82, x79, uint64(p521Uint1(x102))) var x105 uint64 var x106 uint64 - x106, x105 = bits.Mul64(arg1[0], arg1[0]) + x105, x106 = bits.Add64(x80, x77, uint64(p521Uint1(x104))) var x107 uint64 - var x108 p521Uint1 - x107, x108 = p521AddcarryxU64(x51, x43, 0x0) - var x109 uint64 - x109, _ = p521AddcarryxU64(x52, x44, x108) + var x108 uint64 + x107, x108 = bits.Add64(x78, x75, uint64(p521Uint1(x106))) + var x110 uint64 + _, x110 = bits.Add64(x43, x91, uint64(0x0)) var x111 uint64 - var x112 p521Uint1 - x111, x112 = p521AddcarryxU64(x61, x107, 0x0) + var x112 uint64 + x111, x112 = bits.Add64(x61, x93, uint64(p521Uint1(x110))) var x113 uint64 - x113, _ = p521AddcarryxU64(x62, x109, x112) + var x114 uint64 + x113, x114 = bits.Add64(x63, x95, uint64(p521Uint1(x112))) var x115 uint64 - var x116 p521Uint1 - x115, x116 = p521AddcarryxU64(x73, x111, 0x0) + var x116 uint64 + x115, x116 = bits.Add64(x65, x97, uint64(p521Uint1(x114))) var x117 uint64 - x117, _ = p521AddcarryxU64(x74, x113, x116) + var x118 uint64 + x117, x118 = bits.Add64(x67, x99, uint64(p521Uint1(x116))) var x119 uint64 - var x120 p521Uint1 - x119, x120 = p521AddcarryxU64(x105, x115, 0x0) + var x120 uint64 + x119, x120 = bits.Add64(x69, x101, uint64(p521Uint1(x118))) var x121 uint64 - x121, _ = p521AddcarryxU64(x106, x117, x120) - x123 := ((x119 >> 58) | ((x121 << 6) & 0xffffffffffffffff)) - x124 := (x121 >> 58) - x125 := (x119 & 0x3ffffffffffffff) + var x122 uint64 + x121, x122 = bits.Add64(x71, x103, uint64(p521Uint1(x120))) + var x123 uint64 + var x124 uint64 + x123, x124 = bits.Add64(x73, x105, uint64(p521Uint1(x122))) + var x125 uint64 var x126 uint64 - var x127 p521Uint1 - x126, x127 = p521AddcarryxU64(x53, x45, 0x0) + x125, x126 = bits.Add64((uint64(p521Uint1(x74)) + (uint64(p521Uint1(x58)) + (uint64(p521Uint1(x40)) + x8))), x107, uint64(p521Uint1(x124))) + var x127 uint64 var x128 uint64 - x128, _ = p521AddcarryxU64(x54, x46, x127) + x128, x127 = bits.Mul64(arg1[3], 0x400000000000) + var x129 uint64 var x130 uint64 - var x131 p521Uint1 - x130, x131 = p521AddcarryxU64(x63, x126, 0x0) + x129, x130 = bits.Add64(x113, x127, uint64(0x0)) + var x131 uint64 var x132 uint64 - x132, _ = p521AddcarryxU64(x64, x128, x131) + x131, x132 = bits.Add64(x115, x128, uint64(p521Uint1(x130))) + var x133 uint64 var x134 uint64 - var x135 p521Uint1 - x134, x135 = p521AddcarryxU64(x75, x130, 0x0) + x133, x134 = bits.Add64(x117, uint64(0x0), uint64(p521Uint1(x132))) + var x135 uint64 var x136 uint64 - x136, _ = p521AddcarryxU64(x76, x132, x135) + x135, x136 = bits.Add64(x119, uint64(0x0), uint64(p521Uint1(x134))) + var x137 uint64 var x138 uint64 - var x139 p521Uint1 - x138, x139 = p521AddcarryxU64(x89, x134, 0x0) + x137, x138 = bits.Add64(x121, uint64(0x0), uint64(p521Uint1(x136))) + var x139 uint64 var x140 uint64 - x140, _ = p521AddcarryxU64(x90, x136, x139) + x139, x140 = bits.Add64(x123, uint64(0x0), uint64(p521Uint1(x138))) + var x141 uint64 var x142 uint64 - var x143 p521Uint1 - x142, x143 = p521AddcarryxU64(x55, x17, 0x0) + x141, x142 = bits.Add64(x125, uint64(0x0), uint64(p521Uint1(x140))) + var x143 uint64 var x144 uint64 - x144, _ = p521AddcarryxU64(x56, x18, x143) + x144, x143 = bits.Mul64(x111, 0x1ff) + var x145 uint64 var x146 uint64 - var x147 p521Uint1 - x146, x147 = p521AddcarryxU64(x65, x142, 0x0) + x146, x145 = bits.Mul64(x111, 0xffffffffffffffff) + var x147 uint64 var x148 uint64 - x148, _ = p521AddcarryxU64(x66, x144, x147) + x148, x147 = bits.Mul64(x111, 0xffffffffffffffff) + var x149 uint64 var x150 uint64 - var x151 p521Uint1 - x150, x151 = p521AddcarryxU64(x77, x146, 0x0) + x150, x149 = bits.Mul64(x111, 0xffffffffffffffff) + var x151 uint64 var x152 uint64 - x152, _ = p521AddcarryxU64(x78, x148, x151) + x152, x151 = bits.Mul64(x111, 0xffffffffffffffff) + var x153 uint64 var x154 uint64 - var x155 p521Uint1 - x154, x155 = p521AddcarryxU64(x91, x150, 0x0) + x154, x153 = bits.Mul64(x111, 0xffffffffffffffff) + var x155 uint64 var x156 uint64 - x156, _ = p521AddcarryxU64(x92, x152, x155) + x156, x155 = bits.Mul64(x111, 0xffffffffffffffff) + var x157 uint64 var x158 uint64 - var x159 p521Uint1 - x158, x159 = p521AddcarryxU64(x57, x19, 0x0) + x158, x157 = bits.Mul64(x111, 0xffffffffffffffff) + var x159 uint64 var x160 uint64 - x160, _ = p521AddcarryxU64(x58, x20, x159) + x160, x159 = bits.Mul64(x111, 0xffffffffffffffff) + var x161 uint64 var x162 uint64 - var x163 p521Uint1 - x162, x163 = p521AddcarryxU64(x67, x158, 0x0) + x161, x162 = bits.Add64(x160, x157, uint64(0x0)) + var x163 uint64 var x164 uint64 - x164, _ = p521AddcarryxU64(x68, x160, x163) + x163, x164 = bits.Add64(x158, x155, uint64(p521Uint1(x162))) + var x165 uint64 var x166 uint64 - var x167 p521Uint1 - x166, x167 = p521AddcarryxU64(x79, x162, 0x0) + x165, x166 = bits.Add64(x156, x153, uint64(p521Uint1(x164))) + var x167 uint64 var x168 uint64 - x168, _ = p521AddcarryxU64(x80, x164, x167) + x167, x168 = bits.Add64(x154, x151, uint64(p521Uint1(x166))) + var x169 uint64 var x170 uint64 - var x171 p521Uint1 - x170, x171 = p521AddcarryxU64(x93, x166, 0x0) + x169, x170 = bits.Add64(x152, x149, uint64(p521Uint1(x168))) + var x171 uint64 var x172 uint64 - x172, _ = p521AddcarryxU64(x94, x168, x171) + x171, x172 = bits.Add64(x150, x147, uint64(p521Uint1(x170))) + var x173 uint64 var x174 uint64 - var x175 p521Uint1 - x174, x175 = p521AddcarryxU64(x23, x21, 0x0) + x173, x174 = bits.Add64(x148, x145, uint64(p521Uint1(x172))) + var x175 uint64 var x176 uint64 - x176, _ = p521AddcarryxU64(x24, x22, x175) + x175, x176 = bits.Add64(x146, x143, uint64(p521Uint1(x174))) var x178 uint64 - var x179 p521Uint1 - x178, x179 = p521AddcarryxU64(x69, x174, 0x0) + _, x178 = bits.Add64(x111, x159, uint64(0x0)) + var x179 uint64 var x180 uint64 - x180, _ = p521AddcarryxU64(x70, x176, x179) + x179, x180 = bits.Add64(x129, x161, uint64(p521Uint1(x178))) + var x181 uint64 var x182 uint64 - var x183 p521Uint1 - x182, x183 = p521AddcarryxU64(x81, x178, 0x0) + x181, x182 = bits.Add64(x131, x163, uint64(p521Uint1(x180))) + var x183 uint64 var x184 uint64 - x184, _ = p521AddcarryxU64(x82, x180, x183) + x183, x184 = bits.Add64(x133, x165, uint64(p521Uint1(x182))) + var x185 uint64 var x186 uint64 - var x187 p521Uint1 - x186, x187 = p521AddcarryxU64(x95, x182, 0x0) + x185, x186 = bits.Add64(x135, x167, uint64(p521Uint1(x184))) + var x187 uint64 var x188 uint64 - x188, _ = p521AddcarryxU64(x96, x184, x187) + x187, x188 = bits.Add64(x137, x169, uint64(p521Uint1(x186))) + var x189 uint64 var x190 uint64 - var x191 p521Uint1 - x190, x191 = p521AddcarryxU64(x29, x25, 0x0) + x189, x190 = bits.Add64(x139, x171, uint64(p521Uint1(x188))) + var x191 uint64 var x192 uint64 - x192, _ = p521AddcarryxU64(x30, x26, x191) + x191, x192 = bits.Add64(x141, x173, uint64(p521Uint1(x190))) + var x193 uint64 var x194 uint64 - var x195 p521Uint1 - x194, x195 = p521AddcarryxU64(x71, x190, 0x0) + x193, x194 = bits.Add64((uint64(p521Uint1(x142)) + (uint64(p521Uint1(x126)) + (uint64(p521Uint1(x108)) + x76))), x175, uint64(p521Uint1(x192))) + var x195 uint64 var x196 uint64 - x196, _ = p521AddcarryxU64(x72, x192, x195) + x196, x195 = bits.Mul64(arg1[4], 0x400000000000) + var x197 uint64 var x198 uint64 - var x199 p521Uint1 - x198, x199 = p521AddcarryxU64(x83, x194, 0x0) + x197, x198 = bits.Add64(x181, x195, uint64(0x0)) + var x199 uint64 var x200 uint64 - x200, _ = p521AddcarryxU64(x84, x196, x199) + x199, x200 = bits.Add64(x183, x196, uint64(p521Uint1(x198))) + var x201 uint64 var x202 uint64 - var x203 p521Uint1 - x202, x203 = p521AddcarryxU64(x97, x198, 0x0) + x201, x202 = bits.Add64(x185, uint64(0x0), uint64(p521Uint1(x200))) + var x203 uint64 var x204 uint64 - x204, _ = p521AddcarryxU64(x98, x200, x203) + x203, x204 = bits.Add64(x187, uint64(0x0), uint64(p521Uint1(x202))) + var x205 uint64 var x206 uint64 - var x207 p521Uint1 - x206, x207 = p521AddcarryxU64(x31, x27, 0x0) + x205, x206 = bits.Add64(x189, uint64(0x0), uint64(p521Uint1(x204))) + var x207 uint64 var x208 uint64 - x208, _ = p521AddcarryxU64(x32, x28, x207) + x207, x208 = bits.Add64(x191, uint64(0x0), uint64(p521Uint1(x206))) + var x209 uint64 var x210 uint64 - var x211 p521Uint1 - x210, x211 = p521AddcarryxU64(x37, x206, 0x0) + x209, x210 = bits.Add64(x193, uint64(0x0), uint64(p521Uint1(x208))) + var x211 uint64 var x212 uint64 - x212, _ = p521AddcarryxU64(x38, x208, x211) + x212, x211 = bits.Mul64(x179, 0x1ff) + var x213 uint64 var x214 uint64 - var x215 p521Uint1 - x214, x215 = p521AddcarryxU64(x85, x210, 0x0) + x214, x213 = bits.Mul64(x179, 0xffffffffffffffff) + var x215 uint64 var x216 uint64 - x216, _ = p521AddcarryxU64(x86, x212, x215) + x216, x215 = bits.Mul64(x179, 0xffffffffffffffff) + var x217 uint64 var x218 uint64 - var x219 p521Uint1 - x218, x219 = p521AddcarryxU64(x99, x214, 0x0) + x218, x217 = bits.Mul64(x179, 0xffffffffffffffff) + var x219 uint64 var x220 uint64 - x220, _ = p521AddcarryxU64(x100, x216, x219) + x220, x219 = bits.Mul64(x179, 0xffffffffffffffff) + var x221 uint64 var x222 uint64 - var x223 p521Uint1 - x222, x223 = p521AddcarryxU64(x39, x33, 0x0) + x222, x221 = bits.Mul64(x179, 0xffffffffffffffff) + var x223 uint64 var x224 uint64 - x224, _ = p521AddcarryxU64(x40, x34, x223) + x224, x223 = bits.Mul64(x179, 0xffffffffffffffff) + var x225 uint64 var x226 uint64 - var x227 p521Uint1 - x226, x227 = p521AddcarryxU64(x47, x222, 0x0) + x226, x225 = bits.Mul64(x179, 0xffffffffffffffff) + var x227 uint64 var x228 uint64 - x228, _ = p521AddcarryxU64(x48, x224, x227) + x228, x227 = bits.Mul64(x179, 0xffffffffffffffff) + var x229 uint64 var x230 uint64 - var x231 p521Uint1 - x230, x231 = p521AddcarryxU64(x87, x226, 0x0) + x229, x230 = bits.Add64(x228, x225, uint64(0x0)) + var x231 uint64 var x232 uint64 - x232, _ = p521AddcarryxU64(x88, x228, x231) + x231, x232 = bits.Add64(x226, x223, uint64(p521Uint1(x230))) + var x233 uint64 var x234 uint64 - var x235 p521Uint1 - x234, x235 = p521AddcarryxU64(x101, x230, 0x0) + x233, x234 = bits.Add64(x224, x221, uint64(p521Uint1(x232))) + var x235 uint64 var x236 uint64 - x236, _ = p521AddcarryxU64(x102, x232, x235) + x235, x236 = bits.Add64(x222, x219, uint64(p521Uint1(x234))) + var x237 uint64 var x238 uint64 - var x239 p521Uint1 - x238, x239 = p521AddcarryxU64(x41, x35, 0x0) + x237, x238 = bits.Add64(x220, x217, uint64(p521Uint1(x236))) + var x239 uint64 var x240 uint64 - x240, _ = p521AddcarryxU64(x42, x36, x239) + x239, x240 = bits.Add64(x218, x215, uint64(p521Uint1(x238))) + var x241 uint64 var x242 uint64 - var x243 p521Uint1 - x242, x243 = p521AddcarryxU64(x49, x238, 0x0) + x241, x242 = bits.Add64(x216, x213, uint64(p521Uint1(x240))) + var x243 uint64 var x244 uint64 - x244, _ = p521AddcarryxU64(x50, x240, x243) + x243, x244 = bits.Add64(x214, x211, uint64(p521Uint1(x242))) var x246 uint64 - var x247 p521Uint1 - x246, x247 = p521AddcarryxU64(x59, x242, 0x0) + _, x246 = bits.Add64(x179, x227, uint64(0x0)) + var x247 uint64 var x248 uint64 - x248, _ = p521AddcarryxU64(x60, x244, x247) + x247, x248 = bits.Add64(x197, x229, uint64(p521Uint1(x246))) + var x249 uint64 var x250 uint64 - var x251 p521Uint1 - x250, x251 = p521AddcarryxU64(x103, x246, 0x0) + x249, x250 = bits.Add64(x199, x231, uint64(p521Uint1(x248))) + var x251 uint64 var x252 uint64 - x252, _ = p521AddcarryxU64(x104, x248, x251) + x251, x252 = bits.Add64(x201, x233, uint64(p521Uint1(x250))) + var x253 uint64 var x254 uint64 - var x255 p521Uint1 - x254, x255 = p521AddcarryxU64(x123, x250, 0x0) + x253, x254 = bits.Add64(x203, x235, uint64(p521Uint1(x252))) + var x255 uint64 var x256 uint64 - x256, _ = p521AddcarryxU64(x124, x252, x255) - x258 := ((x254 >> 58) | ((x256 << 6) & 0xffffffffffffffff)) - x259 := (x256 >> 58) - x260 := (x254 & 0x3ffffffffffffff) + x255, x256 = bits.Add64(x205, x237, uint64(p521Uint1(x254))) + var x257 uint64 + var x258 uint64 + x257, x258 = bits.Add64(x207, x239, uint64(p521Uint1(x256))) + var x259 uint64 + var x260 uint64 + x259, x260 = bits.Add64(x209, x241, uint64(p521Uint1(x258))) var x261 uint64 - var x262 p521Uint1 - x261, x262 = p521AddcarryxU64(x258, x234, 0x0) + var x262 uint64 + x261, x262 = bits.Add64((uint64(p521Uint1(x210)) + (uint64(p521Uint1(x194)) + (uint64(p521Uint1(x176)) + x144))), x243, uint64(p521Uint1(x260))) var x263 uint64 - x263, _ = p521AddcarryxU64(x259, x236, x262) - x265 := ((x261 >> 58) | ((x263 << 6) & 0xffffffffffffffff)) - x266 := (x263 >> 58) - x267 := (x261 & 0x3ffffffffffffff) + var x264 uint64 + x264, x263 = bits.Mul64(arg1[5], 0x400000000000) + var x265 uint64 + var x266 uint64 + x265, x266 = bits.Add64(x249, x263, uint64(0x0)) + var x267 uint64 var x268 uint64 - var x269 p521Uint1 - x268, x269 = p521AddcarryxU64(x265, x218, 0x0) + x267, x268 = bits.Add64(x251, x264, uint64(p521Uint1(x266))) + var x269 uint64 var x270 uint64 - x270, _ = p521AddcarryxU64(x266, x220, x269) - x272 := ((x268 >> 58) | ((x270 << 6) & 0xffffffffffffffff)) - x273 := (x270 >> 58) - x274 := (x268 & 0x3ffffffffffffff) + x269, x270 = bits.Add64(x253, uint64(0x0), uint64(p521Uint1(x268))) + var x271 uint64 + var x272 uint64 + x271, x272 = bits.Add64(x255, uint64(0x0), uint64(p521Uint1(x270))) + var x273 uint64 + var x274 uint64 + x273, x274 = bits.Add64(x257, uint64(0x0), uint64(p521Uint1(x272))) var x275 uint64 - var x276 p521Uint1 - x275, x276 = p521AddcarryxU64(x272, x202, 0x0) + var x276 uint64 + x275, x276 = bits.Add64(x259, uint64(0x0), uint64(p521Uint1(x274))) var x277 uint64 - x277, _ = p521AddcarryxU64(x273, x204, x276) - x279 := ((x275 >> 58) | ((x277 << 6) & 0xffffffffffffffff)) - x280 := (x277 >> 58) - x281 := (x275 & 0x3ffffffffffffff) + var x278 uint64 + x277, x278 = bits.Add64(x261, uint64(0x0), uint64(p521Uint1(x276))) + var x279 uint64 + var x280 uint64 + x280, x279 = bits.Mul64(x247, 0x1ff) + var x281 uint64 var x282 uint64 - var x283 p521Uint1 - x282, x283 = p521AddcarryxU64(x279, x186, 0x0) + x282, x281 = bits.Mul64(x247, 0xffffffffffffffff) + var x283 uint64 var x284 uint64 - x284, _ = p521AddcarryxU64(x280, x188, x283) - x286 := ((x282 >> 58) | ((x284 << 6) & 0xffffffffffffffff)) - x287 := (x284 >> 58) - x288 := (x282 & 0x3ffffffffffffff) + x284, x283 = bits.Mul64(x247, 0xffffffffffffffff) + var x285 uint64 + var x286 uint64 + x286, x285 = bits.Mul64(x247, 0xffffffffffffffff) + var x287 uint64 + var x288 uint64 + x288, x287 = bits.Mul64(x247, 0xffffffffffffffff) var x289 uint64 - var x290 p521Uint1 - x289, x290 = p521AddcarryxU64(x286, x170, 0x0) + var x290 uint64 + x290, x289 = bits.Mul64(x247, 0xffffffffffffffff) var x291 uint64 - x291, _ = p521AddcarryxU64(x287, x172, x290) - x293 := ((x289 >> 58) | ((x291 << 6) & 0xffffffffffffffff)) - x294 := (x291 >> 58) - x295 := (x289 & 0x3ffffffffffffff) + var x292 uint64 + x292, x291 = bits.Mul64(x247, 0xffffffffffffffff) + var x293 uint64 + var x294 uint64 + x294, x293 = bits.Mul64(x247, 0xffffffffffffffff) + var x295 uint64 var x296 uint64 - var x297 p521Uint1 - x296, x297 = p521AddcarryxU64(x293, x154, 0x0) + x296, x295 = bits.Mul64(x247, 0xffffffffffffffff) + var x297 uint64 var x298 uint64 - x298, _ = p521AddcarryxU64(x294, x156, x297) - x300 := ((x296 >> 58) | ((x298 << 6) & 0xffffffffffffffff)) - x301 := (x298 >> 58) - x302 := (x296 & 0x3ffffffffffffff) + x297, x298 = bits.Add64(x296, x293, uint64(0x0)) + var x299 uint64 + var x300 uint64 + x299, x300 = bits.Add64(x294, x291, uint64(p521Uint1(x298))) + var x301 uint64 + var x302 uint64 + x301, x302 = bits.Add64(x292, x289, uint64(p521Uint1(x300))) var x303 uint64 - var x304 p521Uint1 - x303, x304 = p521AddcarryxU64(x300, x138, 0x0) + var x304 uint64 + x303, x304 = bits.Add64(x290, x287, uint64(p521Uint1(x302))) var x305 uint64 - x305, _ = p521AddcarryxU64(x301, x140, x304) - x307 := ((x303 >> 57) | ((x305 << 7) & 0xffffffffffffffff)) - x308 := (x305 >> 57) - x309 := (x303 & 0x1ffffffffffffff) + var x306 uint64 + x305, x306 = bits.Add64(x288, x285, uint64(p521Uint1(x304))) + var x307 uint64 + var x308 uint64 + x307, x308 = bits.Add64(x286, x283, uint64(p521Uint1(x306))) + var x309 uint64 var x310 uint64 - var x311 p521Uint1 - x310, x311 = p521AddcarryxU64(x125, x307, 0x0) - x312 := (uint64(x311) + x308) - x313 := ((x310 >> 58) | ((x312 << 6) & 0xffffffffffffffff)) - x314 := (x310 & 0x3ffffffffffffff) - x315 := (x313 + x260) - x316 := p521Uint1((x315 >> 58)) - x317 := (x315 & 0x3ffffffffffffff) - x318 := (uint64(x316) + x267) - out1[0] = x314 - out1[1] = x317 - out1[2] = x318 - out1[3] = x274 - out1[4] = x281 - out1[5] = x288 - out1[6] = x295 - out1[7] = x302 - out1[8] = x309 -} - -// p521Carry reduces a field element. -// -// Postconditions: -// eval out1 mod m = eval arg1 mod m -// -// Input Bounds: -// arg1: [[0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0x600000000000000]] -// Output Bounds: -// out1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]] -func p521Carry(out1 *[9]uint64, arg1 *[9]uint64) { - x1 := arg1[0] - x2 := ((x1 >> 58) + arg1[1]) - x3 := ((x2 >> 58) + arg1[2]) - x4 := ((x3 >> 58) + arg1[3]) - x5 := ((x4 >> 58) + arg1[4]) - x6 := ((x5 >> 58) + arg1[5]) - x7 := ((x6 >> 58) + arg1[6]) - x8 := ((x7 >> 58) + arg1[7]) - x9 := ((x8 >> 58) + arg1[8]) - x10 := ((x1 & 0x3ffffffffffffff) + (x9 >> 57)) - x11 := (uint64(p521Uint1((x10 >> 58))) + (x2 & 0x3ffffffffffffff)) - x12 := (x10 & 0x3ffffffffffffff) - x13 := (x11 & 0x3ffffffffffffff) - x14 := (uint64(p521Uint1((x11 >> 58))) + (x3 & 0x3ffffffffffffff)) - x15 := (x4 & 0x3ffffffffffffff) - x16 := (x5 & 0x3ffffffffffffff) - x17 := (x6 & 0x3ffffffffffffff) - x18 := (x7 & 0x3ffffffffffffff) - x19 := (x8 & 0x3ffffffffffffff) - x20 := (x9 & 0x1ffffffffffffff) - out1[0] = x12 - out1[1] = x13 - out1[2] = x14 - out1[3] = x15 - out1[4] = x16 - out1[5] = x17 - out1[6] = x18 - out1[7] = x19 - out1[8] = x20 -} - -// p521Add adds two field elements. -// -// Postconditions: -// eval out1 mod m = (eval arg1 + eval arg2) mod m -// -// Input Bounds: -// arg1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]] -// arg2: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]] -// Output Bounds: -// out1: [[0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0x600000000000000]] -func p521Add(out1 *[9]uint64, arg1 *[9]uint64, arg2 *[9]uint64) { - x1 := (arg1[0] + arg2[0]) - x2 := (arg1[1] + arg2[1]) - x3 := (arg1[2] + arg2[2]) - x4 := (arg1[3] + arg2[3]) - x5 := (arg1[4] + arg2[4]) - x6 := (arg1[5] + arg2[5]) - x7 := (arg1[6] + arg2[6]) - x8 := (arg1[7] + arg2[7]) - x9 := (arg1[8] + arg2[8]) - out1[0] = x1 - out1[1] = x2 - out1[2] = x3 - out1[3] = x4 - out1[4] = x5 - out1[5] = x6 - out1[6] = x7 - out1[7] = x8 - out1[8] = x9 -} - -// p521Sub subtracts two field elements. -// -// Postconditions: -// eval out1 mod m = (eval arg1 - eval arg2) mod m -// -// Input Bounds: -// arg1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]] -// arg2: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]] -// Output Bounds: -// out1: [[0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0x600000000000000]] -func p521Sub(out1 *[9]uint64, arg1 *[9]uint64, arg2 *[9]uint64) { - x1 := ((0x7fffffffffffffe + arg1[0]) - arg2[0]) - x2 := ((0x7fffffffffffffe + arg1[1]) - arg2[1]) - x3 := ((0x7fffffffffffffe + arg1[2]) - arg2[2]) - x4 := ((0x7fffffffffffffe + arg1[3]) - arg2[3]) - x5 := ((0x7fffffffffffffe + arg1[4]) - arg2[4]) - x6 := ((0x7fffffffffffffe + arg1[5]) - arg2[5]) - x7 := ((0x7fffffffffffffe + arg1[6]) - arg2[6]) - x8 := ((0x7fffffffffffffe + arg1[7]) - arg2[7]) - x9 := ((0x3fffffffffffffe + arg1[8]) - arg2[8]) - out1[0] = x1 - out1[1] = x2 - out1[2] = x3 - out1[3] = x4 - out1[4] = x5 - out1[5] = x6 - out1[6] = x7 - out1[7] = x8 - out1[8] = x9 -} - -// p521ToBytes serializes a field element to bytes in little-endian order. -// -// Postconditions: -// out1 = map (λ x, ⌊((eval arg1 mod m) mod 2^(8 * (x + 1))) / 2^(8 * x)⌋) [0..65] -// -// Input Bounds: -// arg1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]] -// Output Bounds: -// out1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0x1]] -func p521ToBytes(out1 *[66]uint8, arg1 *[9]uint64) { - var x1 uint64 - var x2 p521Uint1 - p521SubborrowxU58(&x1, &x2, 0x0, arg1[0], 0x3ffffffffffffff) - var x3 uint64 - var x4 p521Uint1 - p521SubborrowxU58(&x3, &x4, x2, arg1[1], 0x3ffffffffffffff) - var x5 uint64 - var x6 p521Uint1 - p521SubborrowxU58(&x5, &x6, x4, arg1[2], 0x3ffffffffffffff) - var x7 uint64 - var x8 p521Uint1 - p521SubborrowxU58(&x7, &x8, x6, arg1[3], 0x3ffffffffffffff) - var x9 uint64 - var x10 p521Uint1 - p521SubborrowxU58(&x9, &x10, x8, arg1[4], 0x3ffffffffffffff) - var x11 uint64 - var x12 p521Uint1 - p521SubborrowxU58(&x11, &x12, x10, arg1[5], 0x3ffffffffffffff) - var x13 uint64 - var x14 p521Uint1 - p521SubborrowxU58(&x13, &x14, x12, arg1[6], 0x3ffffffffffffff) - var x15 uint64 - var x16 p521Uint1 - p521SubborrowxU58(&x15, &x16, x14, arg1[7], 0x3ffffffffffffff) - var x17 uint64 - var x18 p521Uint1 - p521SubborrowxU57(&x17, &x18, x16, arg1[8], 0x1ffffffffffffff) - var x19 uint64 - p521CmovznzU64(&x19, x18, uint64(0x0), 0xffffffffffffffff) - var x20 uint64 - var x21 p521Uint1 - p521AddcarryxU58(&x20, &x21, 0x0, x1, (x19 & 0x3ffffffffffffff)) - var x22 uint64 - var x23 p521Uint1 - p521AddcarryxU58(&x22, &x23, x21, x3, (x19 & 0x3ffffffffffffff)) - var x24 uint64 - var x25 p521Uint1 - p521AddcarryxU58(&x24, &x25, x23, x5, (x19 & 0x3ffffffffffffff)) - var x26 uint64 - var x27 p521Uint1 - p521AddcarryxU58(&x26, &x27, x25, x7, (x19 & 0x3ffffffffffffff)) - var x28 uint64 - var x29 p521Uint1 - p521AddcarryxU58(&x28, &x29, x27, x9, (x19 & 0x3ffffffffffffff)) - var x30 uint64 - var x31 p521Uint1 - p521AddcarryxU58(&x30, &x31, x29, x11, (x19 & 0x3ffffffffffffff)) - var x32 uint64 - var x33 p521Uint1 - p521AddcarryxU58(&x32, &x33, x31, x13, (x19 & 0x3ffffffffffffff)) - var x34 uint64 - var x35 p521Uint1 - p521AddcarryxU58(&x34, &x35, x33, x15, (x19 & 0x3ffffffffffffff)) - var x36 uint64 - var x37 p521Uint1 - p521AddcarryxU57(&x36, &x37, x35, x17, (x19 & 0x1ffffffffffffff)) - x38 := (x34 << 6) - x39 := (x32 << 4) - x40 := (x30 << 2) - x41 := (x26 << 6) - x42 := (x24 << 4) - x43 := (x22 << 2) - x44 := (uint8(x20) & 0xff) - x45 := (x20 >> 8) - x46 := (uint8(x45) & 0xff) - x47 := (x45 >> 8) - x48 := (uint8(x47) & 0xff) - x49 := (x47 >> 8) - x50 := (uint8(x49) & 0xff) - x51 := (x49 >> 8) - x52 := (uint8(x51) & 0xff) - x53 := (x51 >> 8) - x54 := (uint8(x53) & 0xff) - x55 := (x53 >> 8) - x56 := (uint8(x55) & 0xff) - x57 := uint8((x55 >> 8)) - x58 := (x43 + uint64(x57)) - x59 := (uint8(x58) & 0xff) - x60 := (x58 >> 8) - x61 := (uint8(x60) & 0xff) - x62 := (x60 >> 8) - x63 := (uint8(x62) & 0xff) - x64 := (x62 >> 8) - x65 := (uint8(x64) & 0xff) - x66 := (x64 >> 8) - x67 := (uint8(x66) & 0xff) - x68 := (x66 >> 8) - x69 := (uint8(x68) & 0xff) - x70 := (x68 >> 8) - x71 := (uint8(x70) & 0xff) - x72 := uint8((x70 >> 8)) - x73 := (x42 + uint64(x72)) - x74 := (uint8(x73) & 0xff) - x75 := (x73 >> 8) - x76 := (uint8(x75) & 0xff) - x77 := (x75 >> 8) - x78 := (uint8(x77) & 0xff) - x79 := (x77 >> 8) - x80 := (uint8(x79) & 0xff) - x81 := (x79 >> 8) - x82 := (uint8(x81) & 0xff) - x83 := (x81 >> 8) - x84 := (uint8(x83) & 0xff) - x85 := (x83 >> 8) - x86 := (uint8(x85) & 0xff) - x87 := uint8((x85 >> 8)) - x88 := (x41 + uint64(x87)) - x89 := (uint8(x88) & 0xff) - x90 := (x88 >> 8) - x91 := (uint8(x90) & 0xff) - x92 := (x90 >> 8) - x93 := (uint8(x92) & 0xff) - x94 := (x92 >> 8) - x95 := (uint8(x94) & 0xff) - x96 := (x94 >> 8) - x97 := (uint8(x96) & 0xff) - x98 := (x96 >> 8) - x99 := (uint8(x98) & 0xff) - x100 := (x98 >> 8) - x101 := (uint8(x100) & 0xff) - x102 := uint8((x100 >> 8)) - x103 := (uint8(x28) & 0xff) - x104 := (x28 >> 8) - x105 := (uint8(x104) & 0xff) - x106 := (x104 >> 8) - x107 := (uint8(x106) & 0xff) - x108 := (x106 >> 8) - x109 := (uint8(x108) & 0xff) - x110 := (x108 >> 8) - x111 := (uint8(x110) & 0xff) - x112 := (x110 >> 8) - x113 := (uint8(x112) & 0xff) - x114 := (x112 >> 8) - x115 := (uint8(x114) & 0xff) - x116 := uint8((x114 >> 8)) - x117 := (x40 + uint64(x116)) - x118 := (uint8(x117) & 0xff) - x119 := (x117 >> 8) - x120 := (uint8(x119) & 0xff) - x121 := (x119 >> 8) - x122 := (uint8(x121) & 0xff) - x123 := (x121 >> 8) - x124 := (uint8(x123) & 0xff) - x125 := (x123 >> 8) - x126 := (uint8(x125) & 0xff) - x127 := (x125 >> 8) - x128 := (uint8(x127) & 0xff) - x129 := (x127 >> 8) - x130 := (uint8(x129) & 0xff) - x131 := uint8((x129 >> 8)) - x132 := (x39 + uint64(x131)) - x133 := (uint8(x132) & 0xff) - x134 := (x132 >> 8) - x135 := (uint8(x134) & 0xff) - x136 := (x134 >> 8) - x137 := (uint8(x136) & 0xff) - x138 := (x136 >> 8) - x139 := (uint8(x138) & 0xff) - x140 := (x138 >> 8) - x141 := (uint8(x140) & 0xff) - x142 := (x140 >> 8) - x143 := (uint8(x142) & 0xff) - x144 := (x142 >> 8) - x145 := (uint8(x144) & 0xff) - x146 := uint8((x144 >> 8)) - x147 := (x38 + uint64(x146)) - x148 := (uint8(x147) & 0xff) - x149 := (x147 >> 8) - x150 := (uint8(x149) & 0xff) - x151 := (x149 >> 8) - x152 := (uint8(x151) & 0xff) - x153 := (x151 >> 8) - x154 := (uint8(x153) & 0xff) - x155 := (x153 >> 8) - x156 := (uint8(x155) & 0xff) - x157 := (x155 >> 8) - x158 := (uint8(x157) & 0xff) - x159 := (x157 >> 8) - x160 := (uint8(x159) & 0xff) - x161 := uint8((x159 >> 8)) - x162 := (uint8(x36) & 0xff) - x163 := (x36 >> 8) - x164 := (uint8(x163) & 0xff) - x165 := (x163 >> 8) - x166 := (uint8(x165) & 0xff) - x167 := (x165 >> 8) - x168 := (uint8(x167) & 0xff) - x169 := (x167 >> 8) - x170 := (uint8(x169) & 0xff) - x171 := (x169 >> 8) - x172 := (uint8(x171) & 0xff) - x173 := (x171 >> 8) - x174 := (uint8(x173) & 0xff) - x175 := p521Uint1((x173 >> 8)) - out1[0] = x44 - out1[1] = x46 - out1[2] = x48 - out1[3] = x50 - out1[4] = x52 - out1[5] = x54 - out1[6] = x56 - out1[7] = x59 - out1[8] = x61 - out1[9] = x63 - out1[10] = x65 - out1[11] = x67 - out1[12] = x69 - out1[13] = x71 - out1[14] = x74 - out1[15] = x76 - out1[16] = x78 - out1[17] = x80 - out1[18] = x82 - out1[19] = x84 - out1[20] = x86 - out1[21] = x89 - out1[22] = x91 - out1[23] = x93 - out1[24] = x95 - out1[25] = x97 - out1[26] = x99 - out1[27] = x101 - out1[28] = x102 - out1[29] = x103 - out1[30] = x105 - out1[31] = x107 - out1[32] = x109 - out1[33] = x111 - out1[34] = x113 - out1[35] = x115 - out1[36] = x118 - out1[37] = x120 - out1[38] = x122 - out1[39] = x124 - out1[40] = x126 - out1[41] = x128 - out1[42] = x130 - out1[43] = x133 - out1[44] = x135 - out1[45] = x137 - out1[46] = x139 - out1[47] = x141 - out1[48] = x143 - out1[49] = x145 - out1[50] = x148 - out1[51] = x150 - out1[52] = x152 - out1[53] = x154 - out1[54] = x156 - out1[55] = x158 - out1[56] = x160 - out1[57] = x161 - out1[58] = x162 - out1[59] = x164 - out1[60] = x166 - out1[61] = x168 - out1[62] = x170 - out1[63] = x172 - out1[64] = x174 - out1[65] = uint8(x175) -} - -// p521FromBytes deserializes a field element from bytes in little-endian order. -// -// Postconditions: -// eval out1 mod m = bytes_eval arg1 mod m -// -// Input Bounds: -// arg1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0x1]] -// Output Bounds: -// out1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]] -func p521FromBytes(out1 *[9]uint64, arg1 *[66]uint8) { - x1 := (uint64(p521Uint1(arg1[65])) << 56) - x2 := (uint64(arg1[64]) << 48) - x3 := (uint64(arg1[63]) << 40) - x4 := (uint64(arg1[62]) << 32) - x5 := (uint64(arg1[61]) << 24) - x6 := (uint64(arg1[60]) << 16) - x7 := (uint64(arg1[59]) << 8) - x8 := arg1[58] - x9 := (uint64(arg1[57]) << 50) - x10 := (uint64(arg1[56]) << 42) - x11 := (uint64(arg1[55]) << 34) - x12 := (uint64(arg1[54]) << 26) - x13 := (uint64(arg1[53]) << 18) - x14 := (uint64(arg1[52]) << 10) - x15 := (uint64(arg1[51]) << 2) - x16 := (uint64(arg1[50]) << 52) - x17 := (uint64(arg1[49]) << 44) - x18 := (uint64(arg1[48]) << 36) - x19 := (uint64(arg1[47]) << 28) - x20 := (uint64(arg1[46]) << 20) - x21 := (uint64(arg1[45]) << 12) - x22 := (uint64(arg1[44]) << 4) - x23 := (uint64(arg1[43]) << 54) - x24 := (uint64(arg1[42]) << 46) - x25 := (uint64(arg1[41]) << 38) - x26 := (uint64(arg1[40]) << 30) - x27 := (uint64(arg1[39]) << 22) - x28 := (uint64(arg1[38]) << 14) - x29 := (uint64(arg1[37]) << 6) - x30 := (uint64(arg1[36]) << 56) - x31 := (uint64(arg1[35]) << 48) - x32 := (uint64(arg1[34]) << 40) - x33 := (uint64(arg1[33]) << 32) - x34 := (uint64(arg1[32]) << 24) - x35 := (uint64(arg1[31]) << 16) - x36 := (uint64(arg1[30]) << 8) - x37 := arg1[29] - x38 := (uint64(arg1[28]) << 50) - x39 := (uint64(arg1[27]) << 42) - x40 := (uint64(arg1[26]) << 34) - x41 := (uint64(arg1[25]) << 26) - x42 := (uint64(arg1[24]) << 18) - x43 := (uint64(arg1[23]) << 10) - x44 := (uint64(arg1[22]) << 2) - x45 := (uint64(arg1[21]) << 52) - x46 := (uint64(arg1[20]) << 44) - x47 := (uint64(arg1[19]) << 36) - x48 := (uint64(arg1[18]) << 28) - x49 := (uint64(arg1[17]) << 20) - x50 := (uint64(arg1[16]) << 12) - x51 := (uint64(arg1[15]) << 4) - x52 := (uint64(arg1[14]) << 54) - x53 := (uint64(arg1[13]) << 46) - x54 := (uint64(arg1[12]) << 38) - x55 := (uint64(arg1[11]) << 30) - x56 := (uint64(arg1[10]) << 22) - x57 := (uint64(arg1[9]) << 14) - x58 := (uint64(arg1[8]) << 6) - x59 := (uint64(arg1[7]) << 56) - x60 := (uint64(arg1[6]) << 48) - x61 := (uint64(arg1[5]) << 40) - x62 := (uint64(arg1[4]) << 32) - x63 := (uint64(arg1[3]) << 24) - x64 := (uint64(arg1[2]) << 16) - x65 := (uint64(arg1[1]) << 8) - x66 := arg1[0] - x67 := (x65 + uint64(x66)) - x68 := (x64 + x67) - x69 := (x63 + x68) - x70 := (x62 + x69) - x71 := (x61 + x70) - x72 := (x60 + x71) - x73 := (x59 + x72) - x74 := (x73 & 0x3ffffffffffffff) - x75 := uint8((x73 >> 58)) - x76 := (x58 + uint64(x75)) - x77 := (x57 + x76) - x78 := (x56 + x77) - x79 := (x55 + x78) - x80 := (x54 + x79) - x81 := (x53 + x80) - x82 := (x52 + x81) - x83 := (x82 & 0x3ffffffffffffff) - x84 := uint8((x82 >> 58)) - x85 := (x51 + uint64(x84)) - x86 := (x50 + x85) - x87 := (x49 + x86) - x88 := (x48 + x87) - x89 := (x47 + x88) - x90 := (x46 + x89) - x91 := (x45 + x90) - x92 := (x91 & 0x3ffffffffffffff) - x93 := uint8((x91 >> 58)) - x94 := (x44 + uint64(x93)) - x95 := (x43 + x94) - x96 := (x42 + x95) - x97 := (x41 + x96) - x98 := (x40 + x97) - x99 := (x39 + x98) - x100 := (x38 + x99) - x101 := (x36 + uint64(x37)) - x102 := (x35 + x101) - x103 := (x34 + x102) - x104 := (x33 + x103) - x105 := (x32 + x104) - x106 := (x31 + x105) - x107 := (x30 + x106) - x108 := (x107 & 0x3ffffffffffffff) - x109 := uint8((x107 >> 58)) - x110 := (x29 + uint64(x109)) - x111 := (x28 + x110) - x112 := (x27 + x111) - x113 := (x26 + x112) - x114 := (x25 + x113) - x115 := (x24 + x114) - x116 := (x23 + x115) - x117 := (x116 & 0x3ffffffffffffff) - x118 := uint8((x116 >> 58)) - x119 := (x22 + uint64(x118)) - x120 := (x21 + x119) - x121 := (x20 + x120) - x122 := (x19 + x121) - x123 := (x18 + x122) - x124 := (x17 + x123) - x125 := (x16 + x124) - x126 := (x125 & 0x3ffffffffffffff) - x127 := uint8((x125 >> 58)) - x128 := (x15 + uint64(x127)) - x129 := (x14 + x128) - x130 := (x13 + x129) - x131 := (x12 + x130) - x132 := (x11 + x131) - x133 := (x10 + x132) - x134 := (x9 + x133) - x135 := (x7 + uint64(x8)) - x136 := (x6 + x135) - x137 := (x5 + x136) - x138 := (x4 + x137) - x139 := (x3 + x138) - x140 := (x2 + x139) - x141 := (x1 + x140) - out1[0] = x74 - out1[1] = x83 - out1[2] = x92 - out1[3] = x100 - out1[4] = x108 - out1[5] = x117 - out1[6] = x126 - out1[7] = x134 - out1[8] = x141 + x309, x310 = bits.Add64(x284, x281, uint64(p521Uint1(x308))) + var x311 uint64 + var x312 uint64 + x311, x312 = bits.Add64(x282, x279, uint64(p521Uint1(x310))) + var x314 uint64 + _, x314 = bits.Add64(x247, x295, uint64(0x0)) + var x315 uint64 + var x316 uint64 + x315, x316 = bits.Add64(x265, x297, uint64(p521Uint1(x314))) + var x317 uint64 + var x318 uint64 + x317, x318 = bits.Add64(x267, x299, uint64(p521Uint1(x316))) + var x319 uint64 + var x320 uint64 + x319, x320 = bits.Add64(x269, x301, uint64(p521Uint1(x318))) + var x321 uint64 + var x322 uint64 + x321, x322 = bits.Add64(x271, x303, uint64(p521Uint1(x320))) + var x323 uint64 + var x324 uint64 + x323, x324 = bits.Add64(x273, x305, uint64(p521Uint1(x322))) + var x325 uint64 + var x326 uint64 + x325, x326 = bits.Add64(x275, x307, uint64(p521Uint1(x324))) + var x327 uint64 + var x328 uint64 + x327, x328 = bits.Add64(x277, x309, uint64(p521Uint1(x326))) + var x329 uint64 + var x330 uint64 + x329, x330 = bits.Add64((uint64(p521Uint1(x278)) + (uint64(p521Uint1(x262)) + (uint64(p521Uint1(x244)) + x212))), x311, uint64(p521Uint1(x328))) + var x331 uint64 + var x332 uint64 + x332, x331 = bits.Mul64(arg1[6], 0x400000000000) + var x333 uint64 + var x334 uint64 + x333, x334 = bits.Add64(x317, x331, uint64(0x0)) + var x335 uint64 + var x336 uint64 + x335, x336 = bits.Add64(x319, x332, uint64(p521Uint1(x334))) + var x337 uint64 + var x338 uint64 + x337, x338 = bits.Add64(x321, uint64(0x0), uint64(p521Uint1(x336))) + var x339 uint64 + var x340 uint64 + x339, x340 = bits.Add64(x323, uint64(0x0), uint64(p521Uint1(x338))) + var x341 uint64 + var x342 uint64 + x341, x342 = bits.Add64(x325, uint64(0x0), uint64(p521Uint1(x340))) + var x343 uint64 + var x344 uint64 + x343, x344 = bits.Add64(x327, uint64(0x0), uint64(p521Uint1(x342))) + var x345 uint64 + var x346 uint64 + x345, x346 = bits.Add64(x329, uint64(0x0), uint64(p521Uint1(x344))) + var x347 uint64 + var x348 uint64 + x348, x347 = bits.Mul64(x315, 0x1ff) + var x349 uint64 + var x350 uint64 + x350, x349 = bits.Mul64(x315, 0xffffffffffffffff) + var x351 uint64 + var x352 uint64 + x352, x351 = bits.Mul64(x315, 0xffffffffffffffff) + var x353 uint64 + var x354 uint64 + x354, x353 = bits.Mul64(x315, 0xffffffffffffffff) + var x355 uint64 + var x356 uint64 + x356, x355 = bits.Mul64(x315, 0xffffffffffffffff) + var x357 uint64 + var x358 uint64 + x358, x357 = bits.Mul64(x315, 0xffffffffffffffff) + var x359 uint64 + var x360 uint64 + x360, x359 = bits.Mul64(x315, 0xffffffffffffffff) + var x361 uint64 + var x362 uint64 + x362, x361 = bits.Mul64(x315, 0xffffffffffffffff) + var x363 uint64 + var x364 uint64 + x364, x363 = bits.Mul64(x315, 0xffffffffffffffff) + var x365 uint64 + var x366 uint64 + x365, x366 = bits.Add64(x364, x361, uint64(0x0)) + var x367 uint64 + var x368 uint64 + x367, x368 = bits.Add64(x362, x359, uint64(p521Uint1(x366))) + var x369 uint64 + var x370 uint64 + x369, x370 = bits.Add64(x360, x357, uint64(p521Uint1(x368))) + var x371 uint64 + var x372 uint64 + x371, x372 = bits.Add64(x358, x355, uint64(p521Uint1(x370))) + var x373 uint64 + var x374 uint64 + x373, x374 = bits.Add64(x356, x353, uint64(p521Uint1(x372))) + var x375 uint64 + var x376 uint64 + x375, x376 = bits.Add64(x354, x351, uint64(p521Uint1(x374))) + var x377 uint64 + var x378 uint64 + x377, x378 = bits.Add64(x352, x349, uint64(p521Uint1(x376))) + var x379 uint64 + var x380 uint64 + x379, x380 = bits.Add64(x350, x347, uint64(p521Uint1(x378))) + var x382 uint64 + _, x382 = bits.Add64(x315, x363, uint64(0x0)) + var x383 uint64 + var x384 uint64 + x383, x384 = bits.Add64(x333, x365, uint64(p521Uint1(x382))) + var x385 uint64 + var x386 uint64 + x385, x386 = bits.Add64(x335, x367, uint64(p521Uint1(x384))) + var x387 uint64 + var x388 uint64 + x387, x388 = bits.Add64(x337, x369, uint64(p521Uint1(x386))) + var x389 uint64 + var x390 uint64 + x389, x390 = bits.Add64(x339, x371, uint64(p521Uint1(x388))) + var x391 uint64 + var x392 uint64 + x391, x392 = bits.Add64(x341, x373, uint64(p521Uint1(x390))) + var x393 uint64 + var x394 uint64 + x393, x394 = bits.Add64(x343, x375, uint64(p521Uint1(x392))) + var x395 uint64 + var x396 uint64 + x395, x396 = bits.Add64(x345, x377, uint64(p521Uint1(x394))) + var x397 uint64 + var x398 uint64 + x397, x398 = bits.Add64((uint64(p521Uint1(x346)) + (uint64(p521Uint1(x330)) + (uint64(p521Uint1(x312)) + x280))), x379, uint64(p521Uint1(x396))) + var x399 uint64 + var x400 uint64 + x400, x399 = bits.Mul64(arg1[7], 0x400000000000) + var x401 uint64 + var x402 uint64 + x401, x402 = bits.Add64(x385, x399, uint64(0x0)) + var x403 uint64 + var x404 uint64 + x403, x404 = bits.Add64(x387, x400, uint64(p521Uint1(x402))) + var x405 uint64 + var x406 uint64 + x405, x406 = bits.Add64(x389, uint64(0x0), uint64(p521Uint1(x404))) + var x407 uint64 + var x408 uint64 + x407, x408 = bits.Add64(x391, uint64(0x0), uint64(p521Uint1(x406))) + var x409 uint64 + var x410 uint64 + x409, x410 = bits.Add64(x393, uint64(0x0), uint64(p521Uint1(x408))) + var x411 uint64 + var x412 uint64 + x411, x412 = bits.Add64(x395, uint64(0x0), uint64(p521Uint1(x410))) + var x413 uint64 + var x414 uint64 + x413, x414 = bits.Add64(x397, uint64(0x0), uint64(p521Uint1(x412))) + var x415 uint64 + var x416 uint64 + x416, x415 = bits.Mul64(x383, 0x1ff) + var x417 uint64 + var x418 uint64 + x418, x417 = bits.Mul64(x383, 0xffffffffffffffff) + var x419 uint64 + var x420 uint64 + x420, x419 = bits.Mul64(x383, 0xffffffffffffffff) + var x421 uint64 + var x422 uint64 + x422, x421 = bits.Mul64(x383, 0xffffffffffffffff) + var x423 uint64 + var x424 uint64 + x424, x423 = bits.Mul64(x383, 0xffffffffffffffff) + var x425 uint64 + var x426 uint64 + x426, x425 = bits.Mul64(x383, 0xffffffffffffffff) + var x427 uint64 + var x428 uint64 + x428, x427 = bits.Mul64(x383, 0xffffffffffffffff) + var x429 uint64 + var x430 uint64 + x430, x429 = bits.Mul64(x383, 0xffffffffffffffff) + var x431 uint64 + var x432 uint64 + x432, x431 = bits.Mul64(x383, 0xffffffffffffffff) + var x433 uint64 + var x434 uint64 + x433, x434 = bits.Add64(x432, x429, uint64(0x0)) + var x435 uint64 + var x436 uint64 + x435, x436 = bits.Add64(x430, x427, uint64(p521Uint1(x434))) + var x437 uint64 + var x438 uint64 + x437, x438 = bits.Add64(x428, x425, uint64(p521Uint1(x436))) + var x439 uint64 + var x440 uint64 + x439, x440 = bits.Add64(x426, x423, uint64(p521Uint1(x438))) + var x441 uint64 + var x442 uint64 + x441, x442 = bits.Add64(x424, x421, uint64(p521Uint1(x440))) + var x443 uint64 + var x444 uint64 + x443, x444 = bits.Add64(x422, x419, uint64(p521Uint1(x442))) + var x445 uint64 + var x446 uint64 + x445, x446 = bits.Add64(x420, x417, uint64(p521Uint1(x444))) + var x447 uint64 + var x448 uint64 + x447, x448 = bits.Add64(x418, x415, uint64(p521Uint1(x446))) + var x450 uint64 + _, x450 = bits.Add64(x383, x431, uint64(0x0)) + var x451 uint64 + var x452 uint64 + x451, x452 = bits.Add64(x401, x433, uint64(p521Uint1(x450))) + var x453 uint64 + var x454 uint64 + x453, x454 = bits.Add64(x403, x435, uint64(p521Uint1(x452))) + var x455 uint64 + var x456 uint64 + x455, x456 = bits.Add64(x405, x437, uint64(p521Uint1(x454))) + var x457 uint64 + var x458 uint64 + x457, x458 = bits.Add64(x407, x439, uint64(p521Uint1(x456))) + var x459 uint64 + var x460 uint64 + x459, x460 = bits.Add64(x409, x441, uint64(p521Uint1(x458))) + var x461 uint64 + var x462 uint64 + x461, x462 = bits.Add64(x411, x443, uint64(p521Uint1(x460))) + var x463 uint64 + var x464 uint64 + x463, x464 = bits.Add64(x413, x445, uint64(p521Uint1(x462))) + var x465 uint64 + var x466 uint64 + x465, x466 = bits.Add64((uint64(p521Uint1(x414)) + (uint64(p521Uint1(x398)) + (uint64(p521Uint1(x380)) + x348))), x447, uint64(p521Uint1(x464))) + var x467 uint64 + var x468 uint64 + x468, x467 = bits.Mul64(arg1[8], 0x400000000000) + var x469 uint64 + var x470 uint64 + x469, x470 = bits.Add64(x453, x467, uint64(0x0)) + var x471 uint64 + var x472 uint64 + x471, x472 = bits.Add64(x455, x468, uint64(p521Uint1(x470))) + var x473 uint64 + var x474 uint64 + x473, x474 = bits.Add64(x457, uint64(0x0), uint64(p521Uint1(x472))) + var x475 uint64 + var x476 uint64 + x475, x476 = bits.Add64(x459, uint64(0x0), uint64(p521Uint1(x474))) + var x477 uint64 + var x478 uint64 + x477, x478 = bits.Add64(x461, uint64(0x0), uint64(p521Uint1(x476))) + var x479 uint64 + var x480 uint64 + x479, x480 = bits.Add64(x463, uint64(0x0), uint64(p521Uint1(x478))) + var x481 uint64 + var x482 uint64 + x481, x482 = bits.Add64(x465, uint64(0x0), uint64(p521Uint1(x480))) + var x483 uint64 + var x484 uint64 + x484, x483 = bits.Mul64(x451, 0x1ff) + var x485 uint64 + var x486 uint64 + x486, x485 = bits.Mul64(x451, 0xffffffffffffffff) + var x487 uint64 + var x488 uint64 + x488, x487 = bits.Mul64(x451, 0xffffffffffffffff) + var x489 uint64 + var x490 uint64 + x490, x489 = bits.Mul64(x451, 0xffffffffffffffff) + var x491 uint64 + var x492 uint64 + x492, x491 = bits.Mul64(x451, 0xffffffffffffffff) + var x493 uint64 + var x494 uint64 + x494, x493 = bits.Mul64(x451, 0xffffffffffffffff) + var x495 uint64 + var x496 uint64 + x496, x495 = bits.Mul64(x451, 0xffffffffffffffff) + var x497 uint64 + var x498 uint64 + x498, x497 = bits.Mul64(x451, 0xffffffffffffffff) + var x499 uint64 + var x500 uint64 + x500, x499 = bits.Mul64(x451, 0xffffffffffffffff) + var x501 uint64 + var x502 uint64 + x501, x502 = bits.Add64(x500, x497, uint64(0x0)) + var x503 uint64 + var x504 uint64 + x503, x504 = bits.Add64(x498, x495, uint64(p521Uint1(x502))) + var x505 uint64 + var x506 uint64 + x505, x506 = bits.Add64(x496, x493, uint64(p521Uint1(x504))) + var x507 uint64 + var x508 uint64 + x507, x508 = bits.Add64(x494, x491, uint64(p521Uint1(x506))) + var x509 uint64 + var x510 uint64 + x509, x510 = bits.Add64(x492, x489, uint64(p521Uint1(x508))) + var x511 uint64 + var x512 uint64 + x511, x512 = bits.Add64(x490, x487, uint64(p521Uint1(x510))) + var x513 uint64 + var x514 uint64 + x513, x514 = bits.Add64(x488, x485, uint64(p521Uint1(x512))) + var x515 uint64 + var x516 uint64 + x515, x516 = bits.Add64(x486, x483, uint64(p521Uint1(x514))) + var x518 uint64 + _, x518 = bits.Add64(x451, x499, uint64(0x0)) + var x519 uint64 + var x520 uint64 + x519, x520 = bits.Add64(x469, x501, uint64(p521Uint1(x518))) + var x521 uint64 + var x522 uint64 + x521, x522 = bits.Add64(x471, x503, uint64(p521Uint1(x520))) + var x523 uint64 + var x524 uint64 + x523, x524 = bits.Add64(x473, x505, uint64(p521Uint1(x522))) + var x525 uint64 + var x526 uint64 + x525, x526 = bits.Add64(x475, x507, uint64(p521Uint1(x524))) + var x527 uint64 + var x528 uint64 + x527, x528 = bits.Add64(x477, x509, uint64(p521Uint1(x526))) + var x529 uint64 + var x530 uint64 + x529, x530 = bits.Add64(x479, x511, uint64(p521Uint1(x528))) + var x531 uint64 + var x532 uint64 + x531, x532 = bits.Add64(x481, x513, uint64(p521Uint1(x530))) + var x533 uint64 + var x534 uint64 + x533, x534 = bits.Add64((uint64(p521Uint1(x482)) + (uint64(p521Uint1(x466)) + (uint64(p521Uint1(x448)) + x416))), x515, uint64(p521Uint1(x532))) + x535 := (uint64(p521Uint1(x534)) + (uint64(p521Uint1(x516)) + x484)) + var x536 uint64 + var x537 uint64 + x536, x537 = bits.Sub64(x519, 0xffffffffffffffff, uint64(0x0)) + var x538 uint64 + var x539 uint64 + x538, x539 = bits.Sub64(x521, 0xffffffffffffffff, uint64(p521Uint1(x537))) + var x540 uint64 + var x541 uint64 + x540, x541 = bits.Sub64(x523, 0xffffffffffffffff, uint64(p521Uint1(x539))) + var x542 uint64 + var x543 uint64 + x542, x543 = bits.Sub64(x525, 0xffffffffffffffff, uint64(p521Uint1(x541))) + var x544 uint64 + var x545 uint64 + x544, x545 = bits.Sub64(x527, 0xffffffffffffffff, uint64(p521Uint1(x543))) + var x546 uint64 + var x547 uint64 + x546, x547 = bits.Sub64(x529, 0xffffffffffffffff, uint64(p521Uint1(x545))) + var x548 uint64 + var x549 uint64 + x548, x549 = bits.Sub64(x531, 0xffffffffffffffff, uint64(p521Uint1(x547))) + var x550 uint64 + var x551 uint64 + x550, x551 = bits.Sub64(x533, 0xffffffffffffffff, uint64(p521Uint1(x549))) + var x552 uint64 + var x553 uint64 + x552, x553 = bits.Sub64(x535, 0x1ff, uint64(p521Uint1(x551))) + var x555 uint64 + _, x555 = bits.Sub64(uint64(0x0), uint64(0x0), uint64(p521Uint1(x553))) + var x556 uint64 + p521CmovznzU64(&x556, p521Uint1(x555), x536, x519) + var x557 uint64 + p521CmovznzU64(&x557, p521Uint1(x555), x538, x521) + var x558 uint64 + p521CmovznzU64(&x558, p521Uint1(x555), x540, x523) + var x559 uint64 + p521CmovznzU64(&x559, p521Uint1(x555), x542, x525) + var x560 uint64 + p521CmovznzU64(&x560, p521Uint1(x555), x544, x527) + var x561 uint64 + p521CmovznzU64(&x561, p521Uint1(x555), x546, x529) + var x562 uint64 + p521CmovznzU64(&x562, p521Uint1(x555), x548, x531) + var x563 uint64 + p521CmovznzU64(&x563, p521Uint1(x555), x550, x533) + var x564 uint64 + p521CmovznzU64(&x564, p521Uint1(x555), x552, x535) + out1[0] = x556 + out1[1] = x557 + out1[2] = x558 + out1[3] = x559 + out1[4] = x560 + out1[5] = x561 + out1[6] = x562 + out1[7] = x563 + out1[8] = x564 } // p521Selectznz is a multi-limb conditional select. @@ -1854,3 +5157,353 @@ func p521Selectznz(out1 *[9]uint64, arg1 p521Uint1, arg2 *[9]uint64, arg3 *[9]ui out1[7] = x8 out1[8] = x9 } + +// p521ToBytes serializes a field element NOT in the Montgomery domain to bytes in little-endian order. +// +// Preconditions: +// 0 ≤ eval arg1 < m +// Postconditions: +// out1 = map (λ x, ⌊((eval arg1 mod m) mod 2^(8 * (x + 1))) / 2^(8 * x)⌋) [0..65] +// +// Input Bounds: +// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0x1ff]] +// Output Bounds: +// out1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0x1]] +func p521ToBytes(out1 *[66]uint8, arg1 *[9]uint64) { + x1 := arg1[8] + x2 := arg1[7] + x3 := arg1[6] + x4 := arg1[5] + x5 := arg1[4] + x6 := arg1[3] + x7 := arg1[2] + x8 := arg1[1] + x9 := arg1[0] + x10 := (uint8(x9) & 0xff) + x11 := (x9 >> 8) + x12 := (uint8(x11) & 0xff) + x13 := (x11 >> 8) + x14 := (uint8(x13) & 0xff) + x15 := (x13 >> 8) + x16 := (uint8(x15) & 0xff) + x17 := (x15 >> 8) + x18 := (uint8(x17) & 0xff) + x19 := (x17 >> 8) + x20 := (uint8(x19) & 0xff) + x21 := (x19 >> 8) + x22 := (uint8(x21) & 0xff) + x23 := uint8((x21 >> 8)) + x24 := (uint8(x8) & 0xff) + x25 := (x8 >> 8) + x26 := (uint8(x25) & 0xff) + x27 := (x25 >> 8) + x28 := (uint8(x27) & 0xff) + x29 := (x27 >> 8) + x30 := (uint8(x29) & 0xff) + x31 := (x29 >> 8) + x32 := (uint8(x31) & 0xff) + x33 := (x31 >> 8) + x34 := (uint8(x33) & 0xff) + x35 := (x33 >> 8) + x36 := (uint8(x35) & 0xff) + x37 := uint8((x35 >> 8)) + x38 := (uint8(x7) & 0xff) + x39 := (x7 >> 8) + x40 := (uint8(x39) & 0xff) + x41 := (x39 >> 8) + x42 := (uint8(x41) & 0xff) + x43 := (x41 >> 8) + x44 := (uint8(x43) & 0xff) + x45 := (x43 >> 8) + x46 := (uint8(x45) & 0xff) + x47 := (x45 >> 8) + x48 := (uint8(x47) & 0xff) + x49 := (x47 >> 8) + x50 := (uint8(x49) & 0xff) + x51 := uint8((x49 >> 8)) + x52 := (uint8(x6) & 0xff) + x53 := (x6 >> 8) + x54 := (uint8(x53) & 0xff) + x55 := (x53 >> 8) + x56 := (uint8(x55) & 0xff) + x57 := (x55 >> 8) + x58 := (uint8(x57) & 0xff) + x59 := (x57 >> 8) + x60 := (uint8(x59) & 0xff) + x61 := (x59 >> 8) + x62 := (uint8(x61) & 0xff) + x63 := (x61 >> 8) + x64 := (uint8(x63) & 0xff) + x65 := uint8((x63 >> 8)) + x66 := (uint8(x5) & 0xff) + x67 := (x5 >> 8) + x68 := (uint8(x67) & 0xff) + x69 := (x67 >> 8) + x70 := (uint8(x69) & 0xff) + x71 := (x69 >> 8) + x72 := (uint8(x71) & 0xff) + x73 := (x71 >> 8) + x74 := (uint8(x73) & 0xff) + x75 := (x73 >> 8) + x76 := (uint8(x75) & 0xff) + x77 := (x75 >> 8) + x78 := (uint8(x77) & 0xff) + x79 := uint8((x77 >> 8)) + x80 := (uint8(x4) & 0xff) + x81 := (x4 >> 8) + x82 := (uint8(x81) & 0xff) + x83 := (x81 >> 8) + x84 := (uint8(x83) & 0xff) + x85 := (x83 >> 8) + x86 := (uint8(x85) & 0xff) + x87 := (x85 >> 8) + x88 := (uint8(x87) & 0xff) + x89 := (x87 >> 8) + x90 := (uint8(x89) & 0xff) + x91 := (x89 >> 8) + x92 := (uint8(x91) & 0xff) + x93 := uint8((x91 >> 8)) + x94 := (uint8(x3) & 0xff) + x95 := (x3 >> 8) + x96 := (uint8(x95) & 0xff) + x97 := (x95 >> 8) + x98 := (uint8(x97) & 0xff) + x99 := (x97 >> 8) + x100 := (uint8(x99) & 0xff) + x101 := (x99 >> 8) + x102 := (uint8(x101) & 0xff) + x103 := (x101 >> 8) + x104 := (uint8(x103) & 0xff) + x105 := (x103 >> 8) + x106 := (uint8(x105) & 0xff) + x107 := uint8((x105 >> 8)) + x108 := (uint8(x2) & 0xff) + x109 := (x2 >> 8) + x110 := (uint8(x109) & 0xff) + x111 := (x109 >> 8) + x112 := (uint8(x111) & 0xff) + x113 := (x111 >> 8) + x114 := (uint8(x113) & 0xff) + x115 := (x113 >> 8) + x116 := (uint8(x115) & 0xff) + x117 := (x115 >> 8) + x118 := (uint8(x117) & 0xff) + x119 := (x117 >> 8) + x120 := (uint8(x119) & 0xff) + x121 := uint8((x119 >> 8)) + x122 := (uint8(x1) & 0xff) + x123 := p521Uint1((x1 >> 8)) + out1[0] = x10 + out1[1] = x12 + out1[2] = x14 + out1[3] = x16 + out1[4] = x18 + out1[5] = x20 + out1[6] = x22 + out1[7] = x23 + out1[8] = x24 + out1[9] = x26 + out1[10] = x28 + out1[11] = x30 + out1[12] = x32 + out1[13] = x34 + out1[14] = x36 + out1[15] = x37 + out1[16] = x38 + out1[17] = x40 + out1[18] = x42 + out1[19] = x44 + out1[20] = x46 + out1[21] = x48 + out1[22] = x50 + out1[23] = x51 + out1[24] = x52 + out1[25] = x54 + out1[26] = x56 + out1[27] = x58 + out1[28] = x60 + out1[29] = x62 + out1[30] = x64 + out1[31] = x65 + out1[32] = x66 + out1[33] = x68 + out1[34] = x70 + out1[35] = x72 + out1[36] = x74 + out1[37] = x76 + out1[38] = x78 + out1[39] = x79 + out1[40] = x80 + out1[41] = x82 + out1[42] = x84 + out1[43] = x86 + out1[44] = x88 + out1[45] = x90 + out1[46] = x92 + out1[47] = x93 + out1[48] = x94 + out1[49] = x96 + out1[50] = x98 + out1[51] = x100 + out1[52] = x102 + out1[53] = x104 + out1[54] = x106 + out1[55] = x107 + out1[56] = x108 + out1[57] = x110 + out1[58] = x112 + out1[59] = x114 + out1[60] = x116 + out1[61] = x118 + out1[62] = x120 + out1[63] = x121 + out1[64] = x122 + out1[65] = uint8(x123) +} + +// p521FromBytes deserializes a field element NOT in the Montgomery domain from bytes in little-endian order. +// +// Preconditions: +// 0 ≤ bytes_eval arg1 < m +// Postconditions: +// eval out1 mod m = bytes_eval arg1 mod m +// 0 ≤ eval out1 < m +// +// Input Bounds: +// arg1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0x1]] +// Output Bounds: +// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0x1ff]] +func p521FromBytes(out1 *[9]uint64, arg1 *[66]uint8) { + x1 := (uint64(p521Uint1(arg1[65])) << 8) + x2 := arg1[64] + x3 := (uint64(arg1[63]) << 56) + x4 := (uint64(arg1[62]) << 48) + x5 := (uint64(arg1[61]) << 40) + x6 := (uint64(arg1[60]) << 32) + x7 := (uint64(arg1[59]) << 24) + x8 := (uint64(arg1[58]) << 16) + x9 := (uint64(arg1[57]) << 8) + x10 := arg1[56] + x11 := (uint64(arg1[55]) << 56) + x12 := (uint64(arg1[54]) << 48) + x13 := (uint64(arg1[53]) << 40) + x14 := (uint64(arg1[52]) << 32) + x15 := (uint64(arg1[51]) << 24) + x16 := (uint64(arg1[50]) << 16) + x17 := (uint64(arg1[49]) << 8) + x18 := arg1[48] + x19 := (uint64(arg1[47]) << 56) + x20 := (uint64(arg1[46]) << 48) + x21 := (uint64(arg1[45]) << 40) + x22 := (uint64(arg1[44]) << 32) + x23 := (uint64(arg1[43]) << 24) + x24 := (uint64(arg1[42]) << 16) + x25 := (uint64(arg1[41]) << 8) + x26 := arg1[40] + x27 := (uint64(arg1[39]) << 56) + x28 := (uint64(arg1[38]) << 48) + x29 := (uint64(arg1[37]) << 40) + x30 := (uint64(arg1[36]) << 32) + x31 := (uint64(arg1[35]) << 24) + x32 := (uint64(arg1[34]) << 16) + x33 := (uint64(arg1[33]) << 8) + x34 := arg1[32] + x35 := (uint64(arg1[31]) << 56) + x36 := (uint64(arg1[30]) << 48) + x37 := (uint64(arg1[29]) << 40) + x38 := (uint64(arg1[28]) << 32) + x39 := (uint64(arg1[27]) << 24) + x40 := (uint64(arg1[26]) << 16) + x41 := (uint64(arg1[25]) << 8) + x42 := arg1[24] + x43 := (uint64(arg1[23]) << 56) + x44 := (uint64(arg1[22]) << 48) + x45 := (uint64(arg1[21]) << 40) + x46 := (uint64(arg1[20]) << 32) + x47 := (uint64(arg1[19]) << 24) + x48 := (uint64(arg1[18]) << 16) + x49 := (uint64(arg1[17]) << 8) + x50 := arg1[16] + x51 := (uint64(arg1[15]) << 56) + x52 := (uint64(arg1[14]) << 48) + x53 := (uint64(arg1[13]) << 40) + x54 := (uint64(arg1[12]) << 32) + x55 := (uint64(arg1[11]) << 24) + x56 := (uint64(arg1[10]) << 16) + x57 := (uint64(arg1[9]) << 8) + x58 := arg1[8] + x59 := (uint64(arg1[7]) << 56) + x60 := (uint64(arg1[6]) << 48) + x61 := (uint64(arg1[5]) << 40) + x62 := (uint64(arg1[4]) << 32) + x63 := (uint64(arg1[3]) << 24) + x64 := (uint64(arg1[2]) << 16) + x65 := (uint64(arg1[1]) << 8) + x66 := arg1[0] + x67 := (x65 + uint64(x66)) + x68 := (x64 + x67) + x69 := (x63 + x68) + x70 := (x62 + x69) + x71 := (x61 + x70) + x72 := (x60 + x71) + x73 := (x59 + x72) + x74 := (x57 + uint64(x58)) + x75 := (x56 + x74) + x76 := (x55 + x75) + x77 := (x54 + x76) + x78 := (x53 + x77) + x79 := (x52 + x78) + x80 := (x51 + x79) + x81 := (x49 + uint64(x50)) + x82 := (x48 + x81) + x83 := (x47 + x82) + x84 := (x46 + x83) + x85 := (x45 + x84) + x86 := (x44 + x85) + x87 := (x43 + x86) + x88 := (x41 + uint64(x42)) + x89 := (x40 + x88) + x90 := (x39 + x89) + x91 := (x38 + x90) + x92 := (x37 + x91) + x93 := (x36 + x92) + x94 := (x35 + x93) + x95 := (x33 + uint64(x34)) + x96 := (x32 + x95) + x97 := (x31 + x96) + x98 := (x30 + x97) + x99 := (x29 + x98) + x100 := (x28 + x99) + x101 := (x27 + x100) + x102 := (x25 + uint64(x26)) + x103 := (x24 + x102) + x104 := (x23 + x103) + x105 := (x22 + x104) + x106 := (x21 + x105) + x107 := (x20 + x106) + x108 := (x19 + x107) + x109 := (x17 + uint64(x18)) + x110 := (x16 + x109) + x111 := (x15 + x110) + x112 := (x14 + x111) + x113 := (x13 + x112) + x114 := (x12 + x113) + x115 := (x11 + x114) + x116 := (x9 + uint64(x10)) + x117 := (x8 + x116) + x118 := (x7 + x117) + x119 := (x6 + x118) + x120 := (x5 + x119) + x121 := (x4 + x120) + x122 := (x3 + x121) + x123 := (x1 + uint64(x2)) + out1[0] = x73 + out1[1] = x80 + out1[2] = x87 + out1[3] = x94 + out1[4] = x101 + out1[5] = x108 + out1[6] = x115 + out1[7] = x122 + out1[8] = x123 +} diff --git a/src/crypto/elliptic/internal/fiat/p521_invert.go b/src/crypto/elliptic/internal/fiat/p521_invert.go new file mode 100644 index 0000000000..407711af36 --- /dev/null +++ b/src/crypto/elliptic/internal/fiat/p521_invert.go @@ -0,0 +1,89 @@ +// Copyright 2021 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. + +// Code generated by addchain. DO NOT EDIT. + +package fiat + +// Invert sets e = 1/x, and returns e. +// +// If x == 0, Invert returns e = 0. +func (e *P521Element) Invert(x *P521Element) *P521Element { + // Inversion is implemented as exponentiation with exponent p − 2. + // The sequence of 13 multiplications and 520 squarings is derived from the + // following addition chain generated with github.com/mmcloughlin/addchain v0.3.0. + // + // _10 = 2*1 + // _11 = 1 + _10 + // _1100 = _11 << 2 + // _1111 = _11 + _1100 + // _11110000 = _1111 << 4 + // _11111111 = _1111 + _11110000 + // x16 = _11111111 << 8 + _11111111 + // x32 = x16 << 16 + x16 + // x64 = x32 << 32 + x32 + // x65 = 2*x64 + 1 + // x129 = x65 << 64 + x64 + // x130 = 2*x129 + 1 + // x259 = x130 << 129 + x129 + // x260 = 2*x259 + 1 + // x519 = x260 << 259 + x259 + // return x519 << 2 + 1 + // + + var z = new(P521Element).Set(e) + var t0 = new(P521Element) + + z.Square(x) + z.Mul(x, z) + t0.Square(z) + for s := 1; s < 2; s++ { + t0.Square(t0) + } + z.Mul(z, t0) + t0.Square(z) + for s := 1; s < 4; s++ { + t0.Square(t0) + } + z.Mul(z, t0) + t0.Square(z) + for s := 1; s < 8; s++ { + t0.Square(t0) + } + z.Mul(z, t0) + t0.Square(z) + for s := 1; s < 16; s++ { + t0.Square(t0) + } + z.Mul(z, t0) + t0.Square(z) + for s := 1; s < 32; s++ { + t0.Square(t0) + } + z.Mul(z, t0) + t0.Square(z) + t0.Mul(x, t0) + for s := 0; s < 64; s++ { + t0.Square(t0) + } + z.Mul(z, t0) + t0.Square(z) + t0.Mul(x, t0) + for s := 0; s < 129; s++ { + t0.Square(t0) + } + z.Mul(z, t0) + t0.Square(z) + t0.Mul(x, t0) + for s := 0; s < 259; s++ { + t0.Square(t0) + } + z.Mul(z, t0) + for s := 0; s < 2; s++ { + z.Square(z) + } + z.Mul(x, z) + + return e.Set(z) +} diff --git a/src/crypto/elliptic/internal/fiat/p521_test.go b/src/crypto/elliptic/internal/fiat/p521_test.go deleted file mode 100644 index 2b374faa27..0000000000 --- a/src/crypto/elliptic/internal/fiat/p521_test.go +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2021 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 fiat_test - -import ( - "crypto/elliptic/internal/fiat" - "crypto/rand" - "testing" -) - -func p521Random(t *testing.T) *fiat.P521Element { - buf := make([]byte, 66) - if _, err := rand.Read(buf); err != nil { - t.Fatal(err) - } - buf[0] &= 1 - e, err := new(fiat.P521Element).SetBytes(buf) - if err != nil { - t.Fatal(err) - } - return e -} - -func TestP521Invert(t *testing.T) { - a := p521Random(t) - inv := new(fiat.P521Element).Invert(a) - one := new(fiat.P521Element).Mul(a, inv) - if new(fiat.P521Element).One().Equal(one) != 1 { - t.Errorf("a * 1/a != 1; got %x for %x", one.Bytes(), a.Bytes()) - } - inv.Invert(new(fiat.P521Element)) - if new(fiat.P521Element).Equal(inv) != 1 { - t.Errorf("1/0 != 0; got %x", inv.Bytes()) - } -} diff --git a/src/crypto/elliptic/internal/nistec/nistec_test.go b/src/crypto/elliptic/internal/nistec/nistec_test.go new file mode 100644 index 0000000000..4eae998c5d --- /dev/null +++ b/src/crypto/elliptic/internal/nistec/nistec_test.go @@ -0,0 +1,94 @@ +// Copyright 2021 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 nistec_test + +import ( + "crypto/elliptic/internal/nistec" + "math/rand" + "os" + "strings" + "testing" +) + +func TestAllocations(t *testing.T) { + if strings.HasSuffix(os.Getenv("GO_BUILDER_NAME"), "-noopt") { + t.Skip("skipping allocations test without relevant optimizations") + } + t.Run("P224", func(t *testing.T) { + if allocs := testing.AllocsPerRun(100, func() { + p := nistec.NewP224Generator() + scalar := make([]byte, 66) + rand.Read(scalar) + p.ScalarMult(p, scalar) + out := p.Bytes() + if _, err := p.SetBytes(out); err != nil { + t.Fatal(err) + } + }); allocs > 0 { + t.Errorf("expected zero allocations, got %0.1f", allocs) + } + }) + t.Run("P384", func(t *testing.T) { + if allocs := testing.AllocsPerRun(100, func() { + p := nistec.NewP384Generator() + scalar := make([]byte, 66) + rand.Read(scalar) + p.ScalarMult(p, scalar) + out := p.Bytes() + if _, err := p.SetBytes(out); err != nil { + t.Fatal(err) + } + }); allocs > 0 { + t.Errorf("expected zero allocations, got %0.1f", allocs) + } + }) + t.Run("P521", func(t *testing.T) { + if allocs := testing.AllocsPerRun(100, func() { + p := nistec.NewP521Generator() + scalar := make([]byte, 66) + rand.Read(scalar) + p.ScalarMult(p, scalar) + out := p.Bytes() + if _, err := p.SetBytes(out); err != nil { + t.Fatal(err) + } + }); allocs > 0 { + t.Errorf("expected zero allocations, got %0.1f", allocs) + } + }) +} + +func BenchmarkScalarMult(b *testing.B) { + b.Run("P224", func(b *testing.B) { + scalar := make([]byte, 66) + rand.Read(scalar) + p := nistec.NewP224Generator() + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + p.ScalarMult(p, scalar) + } + }) + b.Run("P384", func(b *testing.B) { + scalar := make([]byte, 66) + rand.Read(scalar) + p := nistec.NewP384Generator() + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + p.ScalarMult(p, scalar) + } + }) + b.Run("P521", func(b *testing.B) { + scalar := make([]byte, 66) + rand.Read(scalar) + p := nistec.NewP521Generator() + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + p.ScalarMult(p, scalar) + } + }) +} diff --git a/src/crypto/elliptic/internal/nistec/p224.go b/src/crypto/elliptic/internal/nistec/p224.go new file mode 100644 index 0000000000..74dbc184dd --- /dev/null +++ b/src/crypto/elliptic/internal/nistec/p224.go @@ -0,0 +1,293 @@ +// Copyright 2021 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 nistec + +import ( + "crypto/elliptic/internal/fiat" + "crypto/subtle" + "errors" +) + +var p224B, _ = new(fiat.P224Element).SetBytes([]byte{0xb4, 0x05, 0x0a, 0x85, + 0x0c, 0x04, 0xb3, 0xab, 0xf5, 0x41, 0x32, 0x56, 0x50, 0x44, 0xb0, 0xb7, + 0xd7, 0xbf, 0xd8, 0xba, 0x27, 0x0b, 0x39, 0x43, 0x23, 0x55, 0xff, 0xb4}) + +var p224G, _ = NewP224Point().SetBytes([]byte{0x04, + 0xb7, 0x0e, 0x0c, 0xbd, 0x6b, 0xb4, 0xbf, 0x7f, 0x32, 0x13, 0x90, 0xb9, + 0x4a, 0x03, 0xc1, 0xd3, 0x56, 0xc2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xd6, + 0x11, 0x5c, 0x1d, 0x21, 0xbd, 0x37, 0x63, 0x88, 0xb5, 0xf7, 0x23, 0xfb, + 0x4c, 0x22, 0xdf, 0xe6, 0xcd, 0x43, 0x75, 0xa0, 0x5a, 0x07, 0x47, 0x64, + 0x44, 0xd5, 0x81, 0x99, 0x85, 0x0, 0x7e, 0x34}) + +const p224ElementLength = 28 + +// P224Point is a P-224 point. The zero value is NOT valid. +type P224Point struct { + // The point is represented in projective coordinates (X:Y:Z), + // where x = X/Z and y = Y/Z. + x, y, z *fiat.P224Element +} + +// NewP224Point returns a new P224Point representing the point at infinity point. +func NewP224Point() *P224Point { + return &P224Point{ + x: new(fiat.P224Element), + y: new(fiat.P224Element).One(), + z: new(fiat.P224Element), + } +} + +// NewP224Generator returns a new P224Point set to the canonical generator. +func NewP224Generator() *P224Point { + return (&P224Point{ + x: new(fiat.P224Element), + y: new(fiat.P224Element), + z: new(fiat.P224Element), + }).Set(p224G) +} + +// Set sets p = q and returns p. +func (p *P224Point) Set(q *P224Point) *P224Point { + p.x.Set(q.x) + p.y.Set(q.y) + p.z.Set(q.z) + return p +} + +// SetBytes sets p to the compressed, uncompressed, or infinity value encoded in +// b, as specified in SEC 1, Version 2.0, Section 2.3.4. If the point is not on +// the curve, it returns nil and an error, and the receiver is unchanged. +// Otherwise, it returns p. +func (p *P224Point) SetBytes(b []byte) (*P224Point, error) { + switch { + // Point at infinity. + case len(b) == 1 && b[0] == 0: + return p.Set(NewP224Point()), nil + + // Uncompressed form. + case len(b) == 1+2*p224ElementLength && b[0] == 4: + x, err := new(fiat.P224Element).SetBytes(b[1 : 1+p224ElementLength]) + if err != nil { + return nil, err + } + y, err := new(fiat.P224Element).SetBytes(b[1+p224ElementLength:]) + if err != nil { + return nil, err + } + if err := p224CheckOnCurve(x, y); err != nil { + return nil, err + } + p.x.Set(x) + p.y.Set(y) + p.z.One() + return p, nil + + // Compressed form + case len(b) == 1+p224ElementLength && b[0] == 0: + return nil, errors.New("unimplemented") // TODO(filippo) + + default: + return nil, errors.New("invalid P224 point encoding") + } +} + +func p224CheckOnCurve(x, y *fiat.P224Element) error { + // x³ - 3x + b. + x3 := new(fiat.P224Element).Square(x) + x3.Mul(x3, x) + + threeX := new(fiat.P224Element).Add(x, x) + threeX.Add(threeX, x) + + x3.Sub(x3, threeX) + x3.Add(x3, p224B) + + // y² = x³ - 3x + b + y2 := new(fiat.P224Element).Square(y) + + if x3.Equal(y2) != 1 { + return errors.New("P224 point not on curve") + } + return nil +} + +// Bytes returns the uncompressed or infinity encoding of p, as specified in +// SEC 1, Version 2.0, Section 2.3.3. Note that the encoding of the point at +// infinity is shorter than all other encodings. +func (p *P224Point) Bytes() []byte { + // This function is outlined to make the allocations inline in the caller + // rather than happen on the heap. + var out [133]byte + return p.bytes(&out) +} + +func (p *P224Point) bytes(out *[133]byte) []byte { + if p.z.IsZero() == 1 { + return append(out[:0], 0) + } + + zinv := new(fiat.P224Element).Invert(p.z) + xx := new(fiat.P224Element).Mul(p.x, zinv) + yy := new(fiat.P224Element).Mul(p.y, zinv) + + buf := append(out[:0], 4) + buf = append(buf, xx.Bytes()...) + buf = append(buf, yy.Bytes()...) + return buf +} + +// Add sets q = p1 + p2, and returns q. The points may overlap. +func (q *P224Point) Add(p1, p2 *P224Point) *P224Point { + // Complete addition formula for a = -3 from "Complete addition formulas for + // prime order elliptic curves" (https://eprint.iacr.org/2015/1060), §A.2. + + t0 := new(fiat.P224Element).Mul(p1.x, p2.x) // t0 := X1 * X2 + t1 := new(fiat.P224Element).Mul(p1.y, p2.y) // t1 := Y1 * Y2 + t2 := new(fiat.P224Element).Mul(p1.z, p2.z) // t2 := Z1 * Z2 + t3 := new(fiat.P224Element).Add(p1.x, p1.y) // t3 := X1 + Y1 + t4 := new(fiat.P224Element).Add(p2.x, p2.y) // t4 := X2 + Y2 + t3.Mul(t3, t4) // t3 := t3 * t4 + t4.Add(t0, t1) // t4 := t0 + t1 + t3.Sub(t3, t4) // t3 := t3 - t4 + t4.Add(p1.y, p1.z) // t4 := Y1 + Z1 + x3 := new(fiat.P224Element).Add(p2.y, p2.z) // X3 := Y2 + Z2 + t4.Mul(t4, x3) // t4 := t4 * X3 + x3.Add(t1, t2) // X3 := t1 + t2 + t4.Sub(t4, x3) // t4 := t4 - X3 + x3.Add(p1.x, p1.z) // X3 := X1 + Z1 + y3 := new(fiat.P224Element).Add(p2.x, p2.z) // Y3 := X2 + Z2 + x3.Mul(x3, y3) // X3 := X3 * Y3 + y3.Add(t0, t2) // Y3 := t0 + t2 + y3.Sub(x3, y3) // Y3 := X3 - Y3 + z3 := new(fiat.P224Element).Mul(p224B, t2) // Z3 := b * t2 + x3.Sub(y3, z3) // X3 := Y3 - Z3 + z3.Add(x3, x3) // Z3 := X3 + X3 + x3.Add(x3, z3) // X3 := X3 + Z3 + z3.Sub(t1, x3) // Z3 := t1 - X3 + x3.Add(t1, x3) // X3 := t1 + X3 + y3.Mul(p224B, y3) // Y3 := b * Y3 + t1.Add(t2, t2) // t1 := t2 + t2 + t2.Add(t1, t2) // t2 := t1 + t2 + y3.Sub(y3, t2) // Y3 := Y3 - t2 + y3.Sub(y3, t0) // Y3 := Y3 - t0 + t1.Add(y3, y3) // t1 := Y3 + Y3 + y3.Add(t1, y3) // Y3 := t1 + Y3 + t1.Add(t0, t0) // t1 := t0 + t0 + t0.Add(t1, t0) // t0 := t1 + t0 + t0.Sub(t0, t2) // t0 := t0 - t2 + t1.Mul(t4, y3) // t1 := t4 * Y3 + t2.Mul(t0, y3) // t2 := t0 * Y3 + y3.Mul(x3, z3) // Y3 := X3 * Z3 + y3.Add(y3, t2) // Y3 := Y3 + t2 + x3.Mul(t3, x3) // X3 := t3 * X3 + x3.Sub(x3, t1) // X3 := X3 - t1 + z3.Mul(t4, z3) // Z3 := t4 * Z3 + t1.Mul(t3, t0) // t1 := t3 * t0 + z3.Add(z3, t1) // Z3 := Z3 + t1 + + q.x.Set(x3) + q.y.Set(y3) + q.z.Set(z3) + return q +} + +// Double sets q = p + p, and returns q. The points may overlap. +func (q *P224Point) Double(p *P224Point) *P224Point { + // Complete addition formula for a = -3 from "Complete addition formulas for + // prime order elliptic curves" (https://eprint.iacr.org/2015/1060), §A.2. + + t0 := new(fiat.P224Element).Square(p.x) // t0 := X ^ 2 + t1 := new(fiat.P224Element).Square(p.y) // t1 := Y ^ 2 + t2 := new(fiat.P224Element).Square(p.z) // t2 := Z ^ 2 + t3 := new(fiat.P224Element).Mul(p.x, p.y) // t3 := X * Y + t3.Add(t3, t3) // t3 := t3 + t3 + z3 := new(fiat.P224Element).Mul(p.x, p.z) // Z3 := X * Z + z3.Add(z3, z3) // Z3 := Z3 + Z3 + y3 := new(fiat.P224Element).Mul(p224B, t2) // Y3 := b * t2 + y3.Sub(y3, z3) // Y3 := Y3 - Z3 + x3 := new(fiat.P224Element).Add(y3, y3) // X3 := Y3 + Y3 + y3.Add(x3, y3) // Y3 := X3 + Y3 + x3.Sub(t1, y3) // X3 := t1 - Y3 + y3.Add(t1, y3) // Y3 := t1 + Y3 + y3.Mul(x3, y3) // Y3 := X3 * Y3 + x3.Mul(x3, t3) // X3 := X3 * t3 + t3.Add(t2, t2) // t3 := t2 + t2 + t2.Add(t2, t3) // t2 := t2 + t3 + z3.Mul(p224B, z3) // Z3 := b * Z3 + z3.Sub(z3, t2) // Z3 := Z3 - t2 + z3.Sub(z3, t0) // Z3 := Z3 - t0 + t3.Add(z3, z3) // t3 := Z3 + Z3 + z3.Add(z3, t3) // Z3 := Z3 + t3 + t3.Add(t0, t0) // t3 := t0 + t0 + t0.Add(t3, t0) // t0 := t3 + t0 + t0.Sub(t0, t2) // t0 := t0 - t2 + t0.Mul(t0, z3) // t0 := t0 * Z3 + y3.Add(y3, t0) // Y3 := Y3 + t0 + t0.Mul(p.y, p.z) // t0 := Y * Z + t0.Add(t0, t0) // t0 := t0 + t0 + z3.Mul(t0, z3) // Z3 := t0 * Z3 + x3.Sub(x3, z3) // X3 := X3 - Z3 + z3.Mul(t0, t1) // Z3 := t0 * t1 + z3.Add(z3, z3) // Z3 := Z3 + Z3 + z3.Add(z3, z3) // Z3 := Z3 + Z3 + + q.x.Set(x3) + q.y.Set(y3) + q.z.Set(z3) + return q +} + +// Select sets q to p1 if cond == 1, and to p2 if cond == 0. +func (q *P224Point) Select(p1, p2 *P224Point, cond int) *P224Point { + q.x.Select(p1.x, p2.x, cond) + q.y.Select(p1.y, p2.y, cond) + q.z.Select(p1.z, p2.z, cond) + return q +} + +// ScalarMult sets p = scalar * q, and returns p. +func (p *P224Point) ScalarMult(q *P224Point, scalar []byte) *P224Point { + // table holds the first 16 multiples of q. The explicit newP224Point calls + // get inlined, letting the allocations live on the stack. + var table = [16]*P224Point{ + NewP224Point(), NewP224Point(), NewP224Point(), NewP224Point(), + NewP224Point(), NewP224Point(), NewP224Point(), NewP224Point(), + NewP224Point(), NewP224Point(), NewP224Point(), NewP224Point(), + NewP224Point(), NewP224Point(), NewP224Point(), NewP224Point(), + } + for i := 1; i < 16; i++ { + table[i].Add(table[i-1], q) + } + + // Instead of doing the classic double-and-add chain, we do it with a + // four-bit window: we double four times, and then add [0-15]P. + t := NewP224Point() + p.Set(NewP224Point()) + for _, byte := range scalar { + p.Double(p) + p.Double(p) + p.Double(p) + p.Double(p) + + for i := uint8(0); i < 16; i++ { + cond := subtle.ConstantTimeByteEq(byte>>4, i) + t.Select(table[i], t, cond) + } + p.Add(p, t) + + p.Double(p) + p.Double(p) + p.Double(p) + p.Double(p) + + for i := uint8(0); i < 16; i++ { + cond := subtle.ConstantTimeByteEq(byte&0b1111, i) + t.Select(table[i], t, cond) + } + p.Add(p, t) + } + + return p +} diff --git a/src/crypto/elliptic/internal/nistec/p384.go b/src/crypto/elliptic/internal/nistec/p384.go new file mode 100644 index 0000000000..24a166de0a --- /dev/null +++ b/src/crypto/elliptic/internal/nistec/p384.go @@ -0,0 +1,298 @@ +// Copyright 2021 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 nistec + +import ( + "crypto/elliptic/internal/fiat" + "crypto/subtle" + "errors" +) + +var p384B, _ = new(fiat.P384Element).SetBytes([]byte{ + 0xb3, 0x31, 0x2f, 0xa7, 0xe2, 0x3e, 0xe7, 0xe4, 0x98, 0x8e, 0x05, 0x6b, + 0xe3, 0xf8, 0x2d, 0x19, 0x18, 0x1d, 0x9c, 0x6e, 0xfe, 0x81, 0x41, 0x12, + 0x03, 0x14, 0x08, 0x8f, 0x50, 0x13, 0x87, 0x5a, 0xc6, 0x56, 0x39, 0x8d, + 0x8a, 0x2e, 0xd1, 0x9d, 0x2a, 0x85, 0xc8, 0xed, 0xd3, 0xec, 0x2a, 0xef}) + +var p384G, _ = NewP384Point().SetBytes([]byte{0x4, + 0xaa, 0x87, 0xca, 0x22, 0xbe, 0x8b, 0x05, 0x37, 0x8e, 0xb1, 0xc7, 0x1e, + 0xf3, 0x20, 0xad, 0x74, 0x6e, 0x1d, 0x3b, 0x62, 0x8b, 0xa7, 0x9b, 0x98, + 0x59, 0xf7, 0x41, 0xe0, 0x82, 0x54, 0x2a, 0x38, 0x55, 0x02, 0xf2, 0x5d, + 0xbf, 0x55, 0x29, 0x6c, 0x3a, 0x54, 0x5e, 0x38, 0x72, 0x76, 0x0a, 0xb7, + 0x36, 0x17, 0xde, 0x4a, 0x96, 0x26, 0x2c, 0x6f, 0x5d, 0x9e, 0x98, 0xbf, + 0x92, 0x92, 0xdc, 0x29, 0xf8, 0xf4, 0x1d, 0xbd, 0x28, 0x9a, 0x14, 0x7c, + 0xe9, 0xda, 0x31, 0x13, 0xb5, 0xf0, 0xb8, 0xc0, 0x0a, 0x60, 0xb1, 0xce, + 0x1d, 0x7e, 0x81, 0x9d, 0x7a, 0x43, 0x1d, 0x7c, 0x90, 0xea, 0x0e, 0x5f}) + +const p384ElementLength = 48 + +// P384Point is a P-384 point. The zero value is NOT valid. +type P384Point struct { + // The point is represented in projective coordinates (X:Y:Z), + // where x = X/Z and y = Y/Z. + x, y, z *fiat.P384Element +} + +// NewP384Point returns a new P384Point representing the point at infinity point. +func NewP384Point() *P384Point { + return &P384Point{ + x: new(fiat.P384Element), + y: new(fiat.P384Element).One(), + z: new(fiat.P384Element), + } +} + +// NewP384Generator returns a new P384Point set to the canonical generator. +func NewP384Generator() *P384Point { + return (&P384Point{ + x: new(fiat.P384Element), + y: new(fiat.P384Element), + z: new(fiat.P384Element), + }).Set(p384G) +} + +// Set sets p = q and returns p. +func (p *P384Point) Set(q *P384Point) *P384Point { + p.x.Set(q.x) + p.y.Set(q.y) + p.z.Set(q.z) + return p +} + +// SetBytes sets p to the compressed, uncompressed, or infinity value encoded in +// b, as specified in SEC 1, Version 2.0, Section 2.3.4. If the point is not on +// the curve, it returns nil and an error, and the receiver is unchanged. +// Otherwise, it returns p. +func (p *P384Point) SetBytes(b []byte) (*P384Point, error) { + switch { + // Point at infinity. + case len(b) == 1 && b[0] == 0: + return p.Set(NewP384Point()), nil + + // Uncompressed form. + case len(b) == 1+2*p384ElementLength && b[0] == 4: + x, err := new(fiat.P384Element).SetBytes(b[1 : 1+p384ElementLength]) + if err != nil { + return nil, err + } + y, err := new(fiat.P384Element).SetBytes(b[1+p384ElementLength:]) + if err != nil { + return nil, err + } + if err := p384CheckOnCurve(x, y); err != nil { + return nil, err + } + p.x.Set(x) + p.y.Set(y) + p.z.One() + return p, nil + + // Compressed form + case len(b) == 1+p384ElementLength && b[0] == 0: + return nil, errors.New("unimplemented") // TODO(filippo) + + default: + return nil, errors.New("invalid P384 point encoding") + } +} + +func p384CheckOnCurve(x, y *fiat.P384Element) error { + // x³ - 3x + b. + x3 := new(fiat.P384Element).Square(x) + x3.Mul(x3, x) + + threeX := new(fiat.P384Element).Add(x, x) + threeX.Add(threeX, x) + + x3.Sub(x3, threeX) + x3.Add(x3, p384B) + + // y² = x³ - 3x + b + y2 := new(fiat.P384Element).Square(y) + + if x3.Equal(y2) != 1 { + return errors.New("P384 point not on curve") + } + return nil +} + +// Bytes returns the uncompressed or infinity encoding of p, as specified in +// SEC 1, Version 2.0, Section 2.3.3. Note that the encoding of the point at +// infinity is shorter than all other encodings. +func (p *P384Point) Bytes() []byte { + // This function is outlined to make the allocations inline in the caller + // rather than happen on the heap. + var out [133]byte + return p.bytes(&out) +} + +func (p *P384Point) bytes(out *[133]byte) []byte { + if p.z.IsZero() == 1 { + return append(out[:0], 0) + } + + zinv := new(fiat.P384Element).Invert(p.z) + xx := new(fiat.P384Element).Mul(p.x, zinv) + yy := new(fiat.P384Element).Mul(p.y, zinv) + + buf := append(out[:0], 4) + buf = append(buf, xx.Bytes()...) + buf = append(buf, yy.Bytes()...) + return buf +} + +// Add sets q = p1 + p2, and returns q. The points may overlap. +func (q *P384Point) Add(p1, p2 *P384Point) *P384Point { + // Complete addition formula for a = -3 from "Complete addition formulas for + // prime order elliptic curves" (https://eprint.iacr.org/2015/1060), §A.2. + + t0 := new(fiat.P384Element).Mul(p1.x, p2.x) // t0 := X1 * X2 + t1 := new(fiat.P384Element).Mul(p1.y, p2.y) // t1 := Y1 * Y2 + t2 := new(fiat.P384Element).Mul(p1.z, p2.z) // t2 := Z1 * Z2 + t3 := new(fiat.P384Element).Add(p1.x, p1.y) // t3 := X1 + Y1 + t4 := new(fiat.P384Element).Add(p2.x, p2.y) // t4 := X2 + Y2 + t3.Mul(t3, t4) // t3 := t3 * t4 + t4.Add(t0, t1) // t4 := t0 + t1 + t3.Sub(t3, t4) // t3 := t3 - t4 + t4.Add(p1.y, p1.z) // t4 := Y1 + Z1 + x3 := new(fiat.P384Element).Add(p2.y, p2.z) // X3 := Y2 + Z2 + t4.Mul(t4, x3) // t4 := t4 * X3 + x3.Add(t1, t2) // X3 := t1 + t2 + t4.Sub(t4, x3) // t4 := t4 - X3 + x3.Add(p1.x, p1.z) // X3 := X1 + Z1 + y3 := new(fiat.P384Element).Add(p2.x, p2.z) // Y3 := X2 + Z2 + x3.Mul(x3, y3) // X3 := X3 * Y3 + y3.Add(t0, t2) // Y3 := t0 + t2 + y3.Sub(x3, y3) // Y3 := X3 - Y3 + z3 := new(fiat.P384Element).Mul(p384B, t2) // Z3 := b * t2 + x3.Sub(y3, z3) // X3 := Y3 - Z3 + z3.Add(x3, x3) // Z3 := X3 + X3 + x3.Add(x3, z3) // X3 := X3 + Z3 + z3.Sub(t1, x3) // Z3 := t1 - X3 + x3.Add(t1, x3) // X3 := t1 + X3 + y3.Mul(p384B, y3) // Y3 := b * Y3 + t1.Add(t2, t2) // t1 := t2 + t2 + t2.Add(t1, t2) // t2 := t1 + t2 + y3.Sub(y3, t2) // Y3 := Y3 - t2 + y3.Sub(y3, t0) // Y3 := Y3 - t0 + t1.Add(y3, y3) // t1 := Y3 + Y3 + y3.Add(t1, y3) // Y3 := t1 + Y3 + t1.Add(t0, t0) // t1 := t0 + t0 + t0.Add(t1, t0) // t0 := t1 + t0 + t0.Sub(t0, t2) // t0 := t0 - t2 + t1.Mul(t4, y3) // t1 := t4 * Y3 + t2.Mul(t0, y3) // t2 := t0 * Y3 + y3.Mul(x3, z3) // Y3 := X3 * Z3 + y3.Add(y3, t2) // Y3 := Y3 + t2 + x3.Mul(t3, x3) // X3 := t3 * X3 + x3.Sub(x3, t1) // X3 := X3 - t1 + z3.Mul(t4, z3) // Z3 := t4 * Z3 + t1.Mul(t3, t0) // t1 := t3 * t0 + z3.Add(z3, t1) // Z3 := Z3 + t1 + + q.x.Set(x3) + q.y.Set(y3) + q.z.Set(z3) + return q +} + +// Double sets q = p + p, and returns q. The points may overlap. +func (q *P384Point) Double(p *P384Point) *P384Point { + // Complete addition formula for a = -3 from "Complete addition formulas for + // prime order elliptic curves" (https://eprint.iacr.org/2015/1060), §A.2. + + t0 := new(fiat.P384Element).Square(p.x) // t0 := X ^ 2 + t1 := new(fiat.P384Element).Square(p.y) // t1 := Y ^ 2 + t2 := new(fiat.P384Element).Square(p.z) // t2 := Z ^ 2 + t3 := new(fiat.P384Element).Mul(p.x, p.y) // t3 := X * Y + t3.Add(t3, t3) // t3 := t3 + t3 + z3 := new(fiat.P384Element).Mul(p.x, p.z) // Z3 := X * Z + z3.Add(z3, z3) // Z3 := Z3 + Z3 + y3 := new(fiat.P384Element).Mul(p384B, t2) // Y3 := b * t2 + y3.Sub(y3, z3) // Y3 := Y3 - Z3 + x3 := new(fiat.P384Element).Add(y3, y3) // X3 := Y3 + Y3 + y3.Add(x3, y3) // Y3 := X3 + Y3 + x3.Sub(t1, y3) // X3 := t1 - Y3 + y3.Add(t1, y3) // Y3 := t1 + Y3 + y3.Mul(x3, y3) // Y3 := X3 * Y3 + x3.Mul(x3, t3) // X3 := X3 * t3 + t3.Add(t2, t2) // t3 := t2 + t2 + t2.Add(t2, t3) // t2 := t2 + t3 + z3.Mul(p384B, z3) // Z3 := b * Z3 + z3.Sub(z3, t2) // Z3 := Z3 - t2 + z3.Sub(z3, t0) // Z3 := Z3 - t0 + t3.Add(z3, z3) // t3 := Z3 + Z3 + z3.Add(z3, t3) // Z3 := Z3 + t3 + t3.Add(t0, t0) // t3 := t0 + t0 + t0.Add(t3, t0) // t0 := t3 + t0 + t0.Sub(t0, t2) // t0 := t0 - t2 + t0.Mul(t0, z3) // t0 := t0 * Z3 + y3.Add(y3, t0) // Y3 := Y3 + t0 + t0.Mul(p.y, p.z) // t0 := Y * Z + t0.Add(t0, t0) // t0 := t0 + t0 + z3.Mul(t0, z3) // Z3 := t0 * Z3 + x3.Sub(x3, z3) // X3 := X3 - Z3 + z3.Mul(t0, t1) // Z3 := t0 * t1 + z3.Add(z3, z3) // Z3 := Z3 + Z3 + z3.Add(z3, z3) // Z3 := Z3 + Z3 + + q.x.Set(x3) + q.y.Set(y3) + q.z.Set(z3) + return q +} + +// Select sets q to p1 if cond == 1, and to p2 if cond == 0. +func (q *P384Point) Select(p1, p2 *P384Point, cond int) *P384Point { + q.x.Select(p1.x, p2.x, cond) + q.y.Select(p1.y, p2.y, cond) + q.z.Select(p1.z, p2.z, cond) + return q +} + +// ScalarMult sets p = scalar * q, and returns p. +func (p *P384Point) ScalarMult(q *P384Point, scalar []byte) *P384Point { + // table holds the first 16 multiples of q. The explicit newP384Point calls + // get inlined, letting the allocations live on the stack. + var table = [16]*P384Point{ + NewP384Point(), NewP384Point(), NewP384Point(), NewP384Point(), + NewP384Point(), NewP384Point(), NewP384Point(), NewP384Point(), + NewP384Point(), NewP384Point(), NewP384Point(), NewP384Point(), + NewP384Point(), NewP384Point(), NewP384Point(), NewP384Point(), + } + for i := 1; i < 16; i++ { + table[i].Add(table[i-1], q) + } + + // Instead of doing the classic double-and-add chain, we do it with a + // four-bit window: we double four times, and then add [0-15]P. + t := NewP384Point() + p.Set(NewP384Point()) + for _, byte := range scalar { + p.Double(p) + p.Double(p) + p.Double(p) + p.Double(p) + + for i := uint8(0); i < 16; i++ { + cond := subtle.ConstantTimeByteEq(byte>>4, i) + t.Select(table[i], t, cond) + } + p.Add(p, t) + + p.Double(p) + p.Double(p) + p.Double(p) + p.Double(p) + + for i := uint8(0); i < 16; i++ { + cond := subtle.ConstantTimeByteEq(byte&0b1111, i) + t.Select(table[i], t, cond) + } + p.Add(p, t) + } + + return p +} diff --git a/src/crypto/elliptic/internal/nistec/p521.go b/src/crypto/elliptic/internal/nistec/p521.go index e5b4e46d4b..cdbd195cf4 100644 --- a/src/crypto/elliptic/internal/nistec/p521.go +++ b/src/crypto/elliptic/internal/nistec/p521.go @@ -58,7 +58,11 @@ func NewP521Point() *P521Point { // NewP521Generator returns a new P521Point set to the canonical generator. func NewP521Generator() *P521Point { - return NewP521Point().Set(p521G) + return (&P521Point{ + x: new(fiat.P521Element), + y: new(fiat.P521Element), + z: new(fiat.P521Element), + }).Set(p521G) } // Set sets p = q and returns p. diff --git a/src/crypto/elliptic/internal/nistec/p521_test.go b/src/crypto/elliptic/internal/nistec/p521_test.go deleted file mode 100644 index e62c1cbf29..0000000000 --- a/src/crypto/elliptic/internal/nistec/p521_test.go +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2021 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 nistec_test - -import ( - "crypto/elliptic/internal/nistec" - "math/rand" - "os" - "strings" - "testing" -) - -func TestP521Allocations(t *testing.T) { - if strings.HasSuffix(os.Getenv("GO_BUILDER_NAME"), "-noopt") { - t.Skip("skipping allocations test without relevant optimizations") - } - if allocs := testing.AllocsPerRun(100, func() { - p := nistec.NewP521Generator() - scalar := make([]byte, 66) - rand.Read(scalar) - p.ScalarMult(p, scalar) - out := p.Bytes() - if _, err := p.SetBytes(out); err != nil { - t.Fatal(err) - } - }); allocs > 0 { - t.Errorf("expected zero allocations, got %0.1f", allocs) - } -} - -func BenchmarkScalarMult(b *testing.B) { - b.Run("P521", func(b *testing.B) { - scalar := make([]byte, 66) - rand.Read(scalar) - p := nistec.NewP521Generator() - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - p.ScalarMult(p, scalar) - } - }) -} diff --git a/src/crypto/elliptic/p224.go b/src/crypto/elliptic/p224.go index 8f3622c89c..a8533b85ff 100644 --- a/src/crypto/elliptic/p224.go +++ b/src/crypto/elliptic/p224.go @@ -1,735 +1,136 @@ -// Copyright 2012 The Go Authors. All rights reserved. +// Copyright 2013 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package elliptic -// This is a constant-time, 32-bit implementation of P224. See FIPS 186-3, -// section D.2.2. -// -// See https://www.imperialviolet.org/2010/12/04/ecc.html ([1]) for background. - import ( - "encoding/binary" + "crypto/elliptic/internal/nistec" + "crypto/rand" "math/big" - "math/bits" ) -var p224 p224Curve - +// p224Curve is a Curve implementation based on nistec.P224Point. +// +// It's a wrapper that exposes the big.Int-based Curve interface and encodes the +// legacy idiosyncrasies it requires, such as invalid and infinity point +// handling. +// +// To interact with the nistec package, points are encoded into and decoded from +// properly formatted byte slices. All big.Int use is limited to this package. +// Encoding and decoding is 1/1000th of the runtime of a scalar multiplication, +// so the overhead is acceptable. type p224Curve struct { - *CurveParams - gx, gy, b p224FieldElement + params *CurveParams } +var p224 p224Curve +var _ Curve = p224 + func initP224() { - // See FIPS 186-3, section D.2.2 - p224.CurveParams = &CurveParams{Name: "P-224"} - p224.P, _ = new(big.Int).SetString("26959946667150639794667015087019630673557916260026308143510066298881", 10) - p224.N, _ = new(big.Int).SetString("26959946667150639794667015087019625940457807714424391721682722368061", 10) - p224.B, _ = new(big.Int).SetString("b4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4", 16) - p224.Gx, _ = new(big.Int).SetString("b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 16) - p224.Gy, _ = new(big.Int).SetString("bd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34", 16) - p224.BitSize = 224 - - p224FromBig(&p224.gx, p224.Gx) - p224FromBig(&p224.gy, p224.Gy) - p224FromBig(&p224.b, p224.B) -} - -// P224 returns a Curve which implements P-224 (see FIPS 186-3, section D.2.2). -// -// The cryptographic operations are implemented using constant-time algorithms. -func P224() Curve { - initonce.Do(initAll) - return p224 + p224.params = &CurveParams{ + Name: "P-224", + BitSize: 224, + // FIPS 186-4, section D.1.2.2 + P: bigFromDecimal("26959946667150639794667015087019630673557916260026308143510066298881"), + N: bigFromDecimal("26959946667150639794667015087019625940457807714424391721682722368061"), + B: bigFromHex("b4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4"), + Gx: bigFromHex("b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21"), + Gy: bigFromHex("bd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34"), + } } func (curve p224Curve) Params() *CurveParams { - return curve.CurveParams + return curve.params } -func (curve p224Curve) IsOnCurve(bigX, bigY *big.Int) bool { - var x, y p224FieldElement - p224FromBig(&x, bigX) - p224FromBig(&y, bigY) - - // y² = x³ - 3x + b - var tmp p224LargeFieldElement - var x3 p224FieldElement - p224Square(&x3, &x, &tmp) - p224Mul(&x3, &x3, &x, &tmp) - - for i := 0; i < 8; i++ { - x[i] *= 3 +func (curve p224Curve) IsOnCurve(x, y *big.Int) bool { + // IsOnCurve is documented to reject (0, 0), the conventional point at + // infinity, which however is accepted by p224PointFromAffine. + if x.Sign() == 0 && y.Sign() == 0 { + return false } - p224Sub(&x3, &x3, &x) - p224Reduce(&x3) - p224Add(&x3, &x3, &curve.b) - p224Contract(&x3, &x3) - - p224Square(&y, &y, &tmp) - p224Contract(&y, &y) - - for i := 0; i < 8; i++ { - if y[i] != x3[i] { - return false - } - } - return true + _, ok := p224PointFromAffine(x, y) + return ok } -func (p224Curve) Add(bigX1, bigY1, bigX2, bigY2 *big.Int) (x, y *big.Int) { - var x1, y1, z1, x2, y2, z2, x3, y3, z3 p224FieldElement - - p224FromBig(&x1, bigX1) - p224FromBig(&y1, bigY1) - if bigX1.Sign() != 0 || bigY1.Sign() != 0 { - z1[0] = 1 +func p224PointFromAffine(x, y *big.Int) (p *nistec.P224Point, ok bool) { + // (0, 0) is by convention the point at infinity, which can't be represented + // in affine coordinates. Marshal incorrectly encodes it as an uncompressed + // point, which SetBytes would correctly reject. See Issue 37294. + if x.Sign() == 0 && y.Sign() == 0 { + return nistec.NewP224Point(), true } - p224FromBig(&x2, bigX2) - p224FromBig(&y2, bigY2) - if bigX2.Sign() != 0 || bigY2.Sign() != 0 { - z2[0] = 1 + if x.BitLen() > 224 || y.BitLen() > 224 { + return nil, false } - - p224AddJacobian(&x3, &y3, &z3, &x1, &y1, &z1, &x2, &y2, &z2) - return p224ToAffine(&x3, &y3, &z3) + p, err := nistec.NewP224Point().SetBytes(Marshal(P224(), x, y)) + if err != nil { + return nil, false + } + return p, true } -func (p224Curve) Double(bigX1, bigY1 *big.Int) (x, y *big.Int) { - var x1, y1, z1, x2, y2, z2 p224FieldElement - - p224FromBig(&x1, bigX1) - p224FromBig(&y1, bigY1) - z1[0] = 1 - - p224DoubleJacobian(&x2, &y2, &z2, &x1, &y1, &z1) - return p224ToAffine(&x2, &y2, &z2) -} - -func (p224Curve) ScalarMult(bigX1, bigY1 *big.Int, scalar []byte) (x, y *big.Int) { - var x1, y1, z1, x2, y2, z2 p224FieldElement - - p224FromBig(&x1, bigX1) - p224FromBig(&y1, bigY1) - z1[0] = 1 - - p224ScalarMult(&x2, &y2, &z2, &x1, &y1, &z1, scalar) - return p224ToAffine(&x2, &y2, &z2) -} - -func (curve p224Curve) ScalarBaseMult(scalar []byte) (x, y *big.Int) { - var z1, x2, y2, z2 p224FieldElement - - z1[0] = 1 - p224ScalarMult(&x2, &y2, &z2, &curve.gx, &curve.gy, &z1, scalar) - return p224ToAffine(&x2, &y2, &z2) -} - -// Field element functions. -// -// The field that we're dealing with is ℤ/pℤ where p = 2**224 - 2**96 + 1. -// -// Field elements are represented by a FieldElement, which is a typedef to an -// array of 8 uint32's. The value of a FieldElement, a, is: -// a[0] + 2**28·a[1] + 2**56·a[1] + ... + 2**196·a[7] -// -// Using 28-bit limbs means that there's only 4 bits of headroom, which is less -// than we would really like. But it has the useful feature that we hit 2**224 -// exactly, making the reflections during a reduce much nicer. -type p224FieldElement [8]uint32 - -// p224P is the order of the field, represented as a p224FieldElement. -var p224P = p224FieldElement{1, 0, 0, 0xffff000, 0xfffffff, 0xfffffff, 0xfffffff, 0xfffffff} - -// p224IsZero returns 1 if a == 0 mod p and 0 otherwise. -// -// a[i] < 2**29 -func p224IsZero(a *p224FieldElement) uint32 { - var minimal p224FieldElement - p224Contract(&minimal, a) - - var acc uint32 - for _, v := range minimal { - acc |= v - } - mask := ^maskIsNotZero(acc) - - return 1 & mask -} - -// p224Add computes *out = a+b -// -// a[i] + b[i] < 2**32 -func p224Add(out, a, b *p224FieldElement) { - for i := 0; i < 8; i++ { - out[i] = a[i] + b[i] - } -} - -const two31p3 = 1<<31 + 1<<3 -const two31m3 = 1<<31 - 1<<3 -const two31m15m3 = 1<<31 - 1<<15 - 1<<3 - -// p224ZeroModP31 is 0 mod p where bit 31 is set in all limbs so that we can -// subtract smaller amounts without underflow. See the section "Subtraction" in -// [1] for reasoning. -// -// To calculate this value, start by adding 2³¹ to the lowest limb and -// subtracting 2³ from the next one to compensate. Repeat for each next limb, -// ending up with 2³¹ - 2³ in each of them, and a carry of -2³. Apply the -// reduction identity, and we need to subtract 2³ * 2⁹⁶ - 2³ = 2¹⁵ * 2⁸⁴ - 2³ so -// we subtract 2¹⁵ from the 4th limb and add 2³ to the first limb. -var p224ZeroModP31 = []uint32{two31p3, two31m3, two31m3, two31m15m3, two31m3, two31m3, two31m3, two31m3} - -// p224Sub computes *out = a-b -// -// a[i], b[i] < 2**30 -// out[i] < 2**32 -func p224Sub(out, a, b *p224FieldElement) { - for i := 0; i < 8; i++ { - out[i] = a[i] + p224ZeroModP31[i] - b[i] - } -} - -// LargeFieldElement also represents an element of the field. The limbs are -// still spaced 28-bits apart and in little-endian order. So the limbs are at -// 0, 28, 56, ..., 392 bits, each 64-bits wide. -type p224LargeFieldElement [15]uint64 - -const two63p35 = 1<<63 + 1<<35 -const two63m35 = 1<<63 - 1<<35 -const two63m35m19 = 1<<63 - 1<<35 - 1<<19 - -// p224ZeroModP63 is 0 mod p where bit 63 is set in all limbs. See the section -// "Subtraction" in [1] for why. -var p224ZeroModP63 = [8]uint64{two63p35, two63m35, two63m35, two63m35, two63m35m19, two63m35, two63m35, two63m35} - -const bottom12Bits = 0xfff -const bottom28Bits = 0xfffffff - -// p224Mul computes *out = a*b -// -// a[i] < 2**29, b[i] < 2**30 (or vice versa) -// out[i] < 2**29 -func p224Mul(out, a, b *p224FieldElement, tmp *p224LargeFieldElement) { - for i := range tmp { - tmp[i] = 0 - } - - for i := 0; i < 8; i++ { - for j := 0; j < 8; j++ { - tmp[i+j] += uint64(a[i]) * uint64(b[j]) - } - } - - p224ReduceLarge(out, tmp) -} - -// Square computes *out = a*a -// -// a[i] < 2**29 -// out[i] < 2**29 -func p224Square(out, a *p224FieldElement, tmp *p224LargeFieldElement) { - for i := range tmp { - tmp[i] = 0 - } - - for i := 0; i < 8; i++ { - for j := 0; j <= i; j++ { - r := uint64(a[i]) * uint64(a[j]) - if i == j { - tmp[i+j] += r - } else { - tmp[i+j] += r * 2 - } - } - } - - p224ReduceLarge(out, tmp) -} - -// ReduceLarge converts a p224LargeFieldElement to a p224FieldElement. -// -// in[i] < 2**62 -// out[i] < 2**29 -func p224ReduceLarge(out *p224FieldElement, in *p224LargeFieldElement) { - for i := 0; i < 8; i++ { - in[i] += p224ZeroModP63[i] - } - - // Eliminate the coefficients at 2**224 and greater by applying the - // reduction identity. - // - // a + top * 2²²⁴ = a + top * 2⁹⁶ - top - // - // Since top here is in[8..14], both the subtraction at offset 0 and the - // addition at offset 96 (3 * 28 + 16) span multiple limbs. The subtraction - // can't underflow because of the p224ZeroModP63 addition above, while the - // addition can't overflow because of the 62 bit input bounds. - for i := 14; i >= 8; i-- { - in[i-8] -= in[i] - in[i-5] += (in[i] & 0xffff) << 12 - in[i-4] += in[i] >> 16 - } - in[8] = 0 - // in[0..7] < 2**64 - // in[9..14] discarded - - // Run a carry chain and light reduction. Keep [0] large so we can do the - // subtraction safely. As the values become small enough, we start to store - // them in out and use 32-bit operations. - for i := 1; i < 8; i++ { - in[i+1] += in[i] >> 28 - out[i] = uint32(in[i] & bottom28Bits) - } - in[0] -= in[8] - out[3] += uint32(in[8]&0xffff) << 12 - out[4] += uint32(in[8] >> 16) - // in[0] < 2**64 - // out[3] < 2**29 - // out[4] < 2**29 - // out[1,2,5..7] < 2**28 - - // Carry the overflow of [0] into the short 28 bit limbs. - out[0] = uint32(in[0] & bottom28Bits) - out[1] += uint32((in[0] >> 28) & bottom28Bits) - out[2] += uint32(in[0] >> 56) - // out[0] < 2**28 - // out[1..4] < 2**29 - // out[5..7] < 2**28 -} - -// Reduce reduces the coefficients of a to smaller bounds. -// -// On entry: a[i] < 2**31 + 2**30 -// On exit: a[i] < 2**29 -func p224Reduce(a *p224FieldElement) { - for i := 0; i < 7; i++ { - a[i+1] += a[i] >> 28 - a[i] &= bottom28Bits - } - top := a[7] >> 28 - a[7] &= bottom28Bits - - a[0] -= top - a[3] += top << 12 - - // We may have just made a[0] negative but if we did top must have been not - // zero, so a[3] is not zero, so we can carry down to a[0]. (Note that we - // don't actually check if a[0] went negative, like in p224Contract, nor we - // try to stop the carry at a[1] or a[2], because here we can afford to go - // above 28 bits, so instead we carry all the way down from a[3].) - mask := maskIsNotZero(top) - a[3] -= 1 & mask - a[2] += mask & (1<<28 - 1) - a[1] += mask & (1<<28 - 1) - a[0] += mask & (1 << 28) -} - -// p224Invert calculates *out = in**-1 by using Fermat's little theorem and -// computing in**(p-2) = in**(2**224 - 2**96 - 1). -func p224Invert(out, in *p224FieldElement) { - var f1, f2, f3, f4 p224FieldElement - var c p224LargeFieldElement - - p224Square(&f1, in, &c) // 2 - p224Mul(&f1, &f1, in, &c) // 2**2 - 1 - p224Square(&f1, &f1, &c) // 2**3 - 2 - p224Mul(&f1, &f1, in, &c) // 2**3 - 1 - p224Square(&f2, &f1, &c) // 2**4 - 2 - p224Square(&f2, &f2, &c) // 2**5 - 4 - p224Square(&f2, &f2, &c) // 2**6 - 8 - p224Mul(&f1, &f1, &f2, &c) // 2**6 - 1 - p224Square(&f2, &f1, &c) // 2**7 - 2 - for i := 0; i < 5; i++ { // 2**12 - 2**6 - p224Square(&f2, &f2, &c) - } - p224Mul(&f2, &f2, &f1, &c) // 2**12 - 1 - p224Square(&f3, &f2, &c) // 2**13 - 2 - for i := 0; i < 11; i++ { // 2**24 - 2**12 - p224Square(&f3, &f3, &c) - } - p224Mul(&f2, &f3, &f2, &c) // 2**24 - 1 - p224Square(&f3, &f2, &c) // 2**25 - 2 - for i := 0; i < 23; i++ { // 2**48 - 2**24 - p224Square(&f3, &f3, &c) - } - p224Mul(&f3, &f3, &f2, &c) // 2**48 - 1 - p224Square(&f4, &f3, &c) // 2**49 - 2 - for i := 0; i < 47; i++ { // 2**96 - 2**48 - p224Square(&f4, &f4, &c) - } - p224Mul(&f3, &f3, &f4, &c) // 2**96 - 1 - p224Square(&f4, &f3, &c) // 2**97 - 2 - for i := 0; i < 23; i++ { // 2**120 - 2**24 - p224Square(&f4, &f4, &c) - } - p224Mul(&f2, &f4, &f2, &c) // 2**120 - 1 - for i := 0; i < 6; i++ { // 2**126 - 2**6 - p224Square(&f2, &f2, &c) - } - p224Mul(&f1, &f1, &f2, &c) // 2**126 - 1 - p224Square(&f1, &f1, &c) // 2**127 - 2 - p224Mul(&f1, &f1, in, &c) // 2**127 - 1 - for i := 0; i < 97; i++ { // 2**224 - 2**97 - p224Square(&f1, &f1, &c) - } - p224Mul(out, &f1, &f3, &c) // 2**224 - 2**96 - 1 -} - -// p224Contract converts a FieldElement to its unique, minimal form. -// -// On entry, in[i] < 2**29 -// On exit, out[i] < 2**28 and out < p -func p224Contract(out, in *p224FieldElement) { - copy(out[:], in[:]) - - // First, carry the bits above 28 to the higher limb. - for i := 0; i < 7; i++ { - out[i+1] += out[i] >> 28 - out[i] &= bottom28Bits - } - top := out[7] >> 28 - out[7] &= bottom28Bits - - // Use the reduction identity to carry the overflow. - // - // a + top * 2²²⁴ = a + top * 2⁹⁶ - top - out[0] -= top - out[3] += top << 12 - - // We may just have made out[0] negative. So we carry down. If we made - // out[0] negative then we know that out[3] is sufficiently positive - // because we just added to it. - for i := 0; i < 3; i++ { - mask := maskIsNegative(out[i]) - out[i] += (1 << 28) & mask - out[i+1] -= 1 & mask - } - - // We might have pushed out[3] over 2**28 so we perform another, partial, - // carry chain; carry the overflow according to the reduction identity; and - // carry down in case we made out[0] negative. - for i := 3; i < 7; i++ { - out[i+1] += out[i] >> 28 - out[i] &= bottom28Bits - } - top = out[7] >> 28 - out[7] &= bottom28Bits - - out[0] -= top - out[3] += top << 12 - - for i := 0; i < 3; i++ { - mask := maskIsNegative(out[i]) - out[i] += (1 << 28) & mask - out[i+1] -= 1 & mask - } - - // There are two cases to consider for out[3]: - // 1) The first time that we eliminated top, we didn't push out[3] over - // 2**28. In this case, the partial carry chain didn't change any values - // and top is now zero. - // 2) We did push out[3] over 2**28 the first time that we eliminated top. - // The first value of top was in [0..2], therefore, after overflowing - // and being reduced by the second carry chain, out[3] <= 2<<12 - 1. - // In both cases, out[3] cannot have overflowed when we eliminated top for - // the second time. - - // Now we need to subtract p if the value is >= p. To check, we subtract p - // with a borrow chain and look at the final borrow bit. - var b uint32 - for i := 0; i < len(out); i++ { - _, b = bits.Sub32(out[i], p224P[i], b) - } - mask := ^maskIsNotZero(b) - - out[0] -= 1 & mask - out[3] -= 0xffff000 & mask - out[4] -= 0xfffffff & mask - out[5] -= 0xfffffff & mask - out[6] -= 0xfffffff & mask - out[7] -= 0xfffffff & mask - - // Do one final carry down, in case we made out[0] negative. One of - // out[0..3] needs to be positive and able to absorb the -1 or the value - // would have been < p, and the subtraction wouldn't have happened. - for i := 0; i < 3; i++ { - mask := maskIsNegative(out[i]) - out[i] += (1 << 28) & mask - out[i+1] -= 1 & mask - } -} - -// maskIsNegative returns 0xffffffff if the most significant bit of v is set, -// and 0 otherwise. -func maskIsNegative(v uint32) uint32 { return uint32(int32(v) >> 31) } - -// maskIfNegative returns 0xffffffff if v is not zero, and 0 otherwise. -func maskIsNotZero(v uint32) uint32 { - v |= v >> 16 - v |= v >> 8 - v |= v >> 4 - v |= v >> 2 - v |= v >> 1 - return uint32(int32(v<<31) >> 31) -} - -// Group element functions. -// -// These functions deal with group elements. The group is an elliptic curve -// group with a = -3 defined in FIPS 186-3, section D.2.2. - -// p224AddJacobian computes *out = a+b where a != b. -func p224AddJacobian(x3, y3, z3, x1, y1, z1, x2, y2, z2 *p224FieldElement) { - // See https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-p224Add-2007-bl - var z1z1, z2z2, u1, u2, s1, s2, h, i, j, r, v p224FieldElement - var c p224LargeFieldElement - - z1IsZero := p224IsZero(z1) - z2IsZero := p224IsZero(z2) - - // Z1Z1 = Z1² - p224Square(&z1z1, z1, &c) - // Z2Z2 = Z2² - p224Square(&z2z2, z2, &c) - // U1 = X1*Z2Z2 - p224Mul(&u1, x1, &z2z2, &c) - // U2 = X2*Z1Z1 - p224Mul(&u2, x2, &z1z1, &c) - // S1 = Y1*Z2*Z2Z2 - p224Mul(&s1, z2, &z2z2, &c) - p224Mul(&s1, y1, &s1, &c) - // S2 = Y2*Z1*Z1Z1 - p224Mul(&s2, z1, &z1z1, &c) - p224Mul(&s2, y2, &s2, &c) - // H = U2-U1 - p224Sub(&h, &u2, &u1) - p224Reduce(&h) - xEqual := p224IsZero(&h) - // I = (2*H)² - for j := 0; j < 8; j++ { - i[j] = h[j] << 1 - } - p224Reduce(&i) - p224Square(&i, &i, &c) - // J = H*I - p224Mul(&j, &h, &i, &c) - // r = 2*(S2-S1) - p224Sub(&r, &s2, &s1) - p224Reduce(&r) - yEqual := p224IsZero(&r) - if xEqual == 1 && yEqual == 1 && z1IsZero == 0 && z2IsZero == 0 { - p224DoubleJacobian(x3, y3, z3, x1, y1, z1) - return - } - for i := 0; i < 8; i++ { - r[i] <<= 1 - } - p224Reduce(&r) - // V = U1*I - p224Mul(&v, &u1, &i, &c) - // Z3 = ((Z1+Z2)²-Z1Z1-Z2Z2)*H - p224Add(&z1z1, &z1z1, &z2z2) - p224Add(&z2z2, z1, z2) - p224Reduce(&z2z2) - p224Square(&z2z2, &z2z2, &c) - p224Sub(z3, &z2z2, &z1z1) - p224Reduce(z3) - p224Mul(z3, z3, &h, &c) - // X3 = r²-J-2*V - for i := 0; i < 8; i++ { - z1z1[i] = v[i] << 1 - } - p224Add(&z1z1, &j, &z1z1) - p224Reduce(&z1z1) - p224Square(x3, &r, &c) - p224Sub(x3, x3, &z1z1) - p224Reduce(x3) - // Y3 = r*(V-X3)-2*S1*J - for i := 0; i < 8; i++ { - s1[i] <<= 1 - } - p224Mul(&s1, &s1, &j, &c) - p224Sub(&z1z1, &v, x3) - p224Reduce(&z1z1) - p224Mul(&z1z1, &z1z1, &r, &c) - p224Sub(y3, &z1z1, &s1) - p224Reduce(y3) - - p224CopyConditional(x3, x2, z1IsZero) - p224CopyConditional(x3, x1, z2IsZero) - p224CopyConditional(y3, y2, z1IsZero) - p224CopyConditional(y3, y1, z2IsZero) - p224CopyConditional(z3, z2, z1IsZero) - p224CopyConditional(z3, z1, z2IsZero) -} - -// p224DoubleJacobian computes *out = a+a. -func p224DoubleJacobian(x3, y3, z3, x1, y1, z1 *p224FieldElement) { - var delta, gamma, beta, alpha, t p224FieldElement - var c p224LargeFieldElement - - p224Square(&delta, z1, &c) - p224Square(&gamma, y1, &c) - p224Mul(&beta, x1, &gamma, &c) - - // alpha = 3*(X1-delta)*(X1+delta) - p224Add(&t, x1, &delta) - for i := 0; i < 8; i++ { - t[i] += t[i] << 1 - } - p224Reduce(&t) - p224Sub(&alpha, x1, &delta) - p224Reduce(&alpha) - p224Mul(&alpha, &alpha, &t, &c) - - // Z3 = (Y1+Z1)²-gamma-delta - p224Add(z3, y1, z1) - p224Reduce(z3) - p224Square(z3, z3, &c) - p224Sub(z3, z3, &gamma) - p224Reduce(z3) - p224Sub(z3, z3, &delta) - p224Reduce(z3) - - // X3 = alpha²-8*beta - for i := 0; i < 8; i++ { - delta[i] = beta[i] << 3 - } - p224Reduce(&delta) - p224Square(x3, &alpha, &c) - p224Sub(x3, x3, &delta) - p224Reduce(x3) - - // Y3 = alpha*(4*beta-X3)-8*gamma² - for i := 0; i < 8; i++ { - beta[i] <<= 2 - } - p224Sub(&beta, &beta, x3) - p224Reduce(&beta) - p224Square(&gamma, &gamma, &c) - for i := 0; i < 8; i++ { - gamma[i] <<= 3 - } - p224Reduce(&gamma) - p224Mul(y3, &alpha, &beta, &c) - p224Sub(y3, y3, &gamma) - p224Reduce(y3) -} - -// p224CopyConditional sets *out = *in in constant time if control is not zero. -func p224CopyConditional(out, in *p224FieldElement, control uint32) { - mask := maskIsNotZero(control) - for i := 0; i < 8; i++ { - out[i] ^= (out[i] ^ in[i]) & mask - } -} - -func p224ScalarMult(outX, outY, outZ, inX, inY, inZ *p224FieldElement, scalar []byte) { - var xx, yy, zz p224FieldElement - for i := 0; i < 8; i++ { - outX[i] = 0 - outY[i] = 0 - outZ[i] = 0 - } - - for _, byte := range scalar { - for bitNum := uint(0); bitNum < 8; bitNum++ { - p224DoubleJacobian(outX, outY, outZ, outX, outY, outZ) - bit := uint32((byte >> (7 - bitNum)) & 1) - p224AddJacobian(&xx, &yy, &zz, inX, inY, inZ, outX, outY, outZ) - p224CopyConditional(outX, &xx, bit) - p224CopyConditional(outY, &yy, bit) - p224CopyConditional(outZ, &zz, bit) - } - } -} - -// p224ToAffine converts from Jacobian to affine form. -func p224ToAffine(x, y, z *p224FieldElement) (*big.Int, *big.Int) { - var zinv, zinvsq, outx, outy p224FieldElement - var tmp p224LargeFieldElement - - if isPointAtInfinity := p224IsZero(z); isPointAtInfinity == 1 { +func p224PointToAffine(p *nistec.P224Point) (x, y *big.Int) { + out := p.Bytes() + if len(out) == 1 && out[0] == 0 { + // This is the correct encoding of the point at infinity, which + // Unmarshal does not support. See Issue 37294. return new(big.Int), new(big.Int) } - - p224Invert(&zinv, z) - p224Square(&zinvsq, &zinv, &tmp) - p224Mul(x, x, &zinvsq, &tmp) - p224Mul(&zinvsq, &zinvsq, &zinv, &tmp) - p224Mul(y, y, &zinvsq, &tmp) - - p224Contract(&outx, x) - p224Contract(&outy, y) - return p224ToBig(&outx), p224ToBig(&outy) -} - -// get28BitsFromEnd returns the least-significant 28 bits from buf>>shift, -// where buf is interpreted as a big-endian number. shift must be at most -// 4 bits higher than a multiple of 8. -func get28BitsFromEnd(buf []byte, shift int) uint32 { - buf = buf[:len(buf)-shift/8] - shift = shift % 8 - if shift > 4 { - panic("misuse of get28BitsFromEnd") + x, y = Unmarshal(P224(), out) + if x == nil { + panic("crypto/elliptic: internal error: Unmarshal rejected a valid point encoding") } - - ret := binary.BigEndian.Uint32(buf[len(buf)-4:]) - ret >>= shift - ret &= bottom28Bits - return ret + return x, y } -// p224FromBig sets *out = *in. -func p224FromBig(out *p224FieldElement, in *big.Int) { - bytes := in.FillBytes(make([]byte, 224/8)) - for i := range out { - out[i] = get28BitsFromEnd(bytes, 28*i) +// p224RandomPoint returns a random point on the curve. It's used when Add, +// Double, or ScalarMult are fed a point not on the curve, which is undefined +// behavior. Originally, we used to do the math on it anyway (which allows +// invalid curve attacks) and relied on the caller and Unmarshal to avoid this +// happening in the first place. Now, we just can't construct a nistec.P224Point +// for an invalid pair of coordinates, because that API is safer. If we panic, +// we risk introducing a DoS. If we return nil, we risk a panic. If we return +// the input, ecdsa.Verify might fail open. The safest course seems to be to +// return a valid, random point, which hopefully won't help the attacker. +func p224RandomPoint() (x, y *big.Int) { + _, x, y, err := GenerateKey(P224(), rand.Reader) + if err != nil { + panic("crypto/elliptic: failed to generate random point") } + return x, y } -// p224ToBig returns in as a big.Int. -func p224ToBig(in *p224FieldElement) *big.Int { - var buf [28]byte - buf[27] = byte(in[0]) - buf[26] = byte(in[0] >> 8) - buf[25] = byte(in[0] >> 16) - buf[24] = byte(((in[0] >> 24) & 0x0f) | (in[1]<<4)&0xf0) - - buf[23] = byte(in[1] >> 4) - buf[22] = byte(in[1] >> 12) - buf[21] = byte(in[1] >> 20) - - buf[20] = byte(in[2]) - buf[19] = byte(in[2] >> 8) - buf[18] = byte(in[2] >> 16) - buf[17] = byte(((in[2] >> 24) & 0x0f) | (in[3]<<4)&0xf0) - - buf[16] = byte(in[3] >> 4) - buf[15] = byte(in[3] >> 12) - buf[14] = byte(in[3] >> 20) - - buf[13] = byte(in[4]) - buf[12] = byte(in[4] >> 8) - buf[11] = byte(in[4] >> 16) - buf[10] = byte(((in[4] >> 24) & 0x0f) | (in[5]<<4)&0xf0) - - buf[9] = byte(in[5] >> 4) - buf[8] = byte(in[5] >> 12) - buf[7] = byte(in[5] >> 20) - - buf[6] = byte(in[6]) - buf[5] = byte(in[6] >> 8) - buf[4] = byte(in[6] >> 16) - buf[3] = byte(((in[6] >> 24) & 0x0f) | (in[7]<<4)&0xf0) - - buf[2] = byte(in[7] >> 4) - buf[1] = byte(in[7] >> 12) - buf[0] = byte(in[7] >> 20) - - return new(big.Int).SetBytes(buf[:]) +func (p224Curve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) { + p1, ok := p224PointFromAffine(x1, y1) + if !ok { + return p224RandomPoint() + } + p2, ok := p224PointFromAffine(x2, y2) + if !ok { + return p224RandomPoint() + } + return p224PointToAffine(p1.Add(p1, p2)) +} + +func (p224Curve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) { + p, ok := p224PointFromAffine(x1, y1) + if !ok { + return p224RandomPoint() + } + return p224PointToAffine(p.Double(p)) +} + +func (p224Curve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *big.Int) { + p, ok := p224PointFromAffine(Bx, By) + if !ok { + return p224RandomPoint() + } + return p224PointToAffine(p.ScalarMult(p, scalar)) +} + +func (p224Curve) ScalarBaseMult(scalar []byte) (*big.Int, *big.Int) { + p := nistec.NewP224Generator() + return p224PointToAffine(p.ScalarMult(p, scalar)) } diff --git a/src/crypto/elliptic/p224_test.go b/src/crypto/elliptic/p224_test.go index 3e0c78b0f9..7971f631bf 100644 --- a/src/crypto/elliptic/p224_test.go +++ b/src/crypto/elliptic/p224_test.go @@ -8,313 +8,9 @@ import ( "encoding/hex" "fmt" "math/big" - "math/bits" - "math/rand" - "reflect" "testing" - "testing/quick" ) -var toFromBigTests = []string{ - "0", - "1", - "23", - "b70e0cb46bb4bf7f321390b94a03c1d356c01122343280d6105c1d21", - "706a46d476dcb76798e6046d89474788d164c18032d268fd10704fa6", -} - -func p224AlternativeToBig(in *p224FieldElement) *big.Int { - ret := new(big.Int) - tmp := new(big.Int) - - for i := len(in) - 1; i >= 0; i-- { - ret.Lsh(ret, 28) - tmp.SetInt64(int64(in[i])) - ret.Add(ret, tmp) - } - ret.Mod(ret, P224().Params().P) - return ret -} - -func TestP224ToFromBig(t *testing.T) { - for i, test := range toFromBigTests { - n, _ := new(big.Int).SetString(test, 16) - var x p224FieldElement - p224FromBig(&x, n) - m := p224ToBig(&x) - if n.Cmp(m) != 0 { - t.Errorf("#%d: %x != %x", i, n, m) - } - q := p224AlternativeToBig(&x) - if n.Cmp(q) != 0 { - t.Errorf("#%d: %x != %x (alternative)", i, n, q) - } - } -} - -// quickCheckConfig32 will make each quickcheck test run (32 * -quickchecks) -// times. The default value of -quickchecks is 100. -var quickCheckConfig32 = &quick.Config{MaxCountScale: 32} - -// weirdLimbs can be combined to generate a range of edge-case field elements. -var weirdLimbs = [...]uint32{ - 0, 1, (1 << 29) - 1, - (1 << 12), (1 << 12) - 1, - (1 << 28), (1 << 28) - 1, -} - -func generateLimb(rand *rand.Rand) uint32 { - const bottom29Bits = 0x1fffffff - n := rand.Intn(len(weirdLimbs) + 3) - switch n { - case len(weirdLimbs): - // Random value. - return uint32(rand.Int31n(1 << 29)) - case len(weirdLimbs) + 1: - // Sum of two values. - k := generateLimb(rand) + generateLimb(rand) - return k & bottom29Bits - case len(weirdLimbs) + 2: - // Difference of two values. - k := generateLimb(rand) - generateLimb(rand) - return k & bottom29Bits - default: - return weirdLimbs[n] - } -} - -func (p224FieldElement) Generate(rand *rand.Rand, size int) reflect.Value { - return reflect.ValueOf(p224FieldElement{ - generateLimb(rand), - generateLimb(rand), - generateLimb(rand), - generateLimb(rand), - generateLimb(rand), - generateLimb(rand), - generateLimb(rand), - generateLimb(rand), - }) -} - -func isInBounds(x *p224FieldElement) bool { - return bits.Len32(x[0]) <= 29 && - bits.Len32(x[1]) <= 29 && - bits.Len32(x[2]) <= 29 && - bits.Len32(x[3]) <= 29 && - bits.Len32(x[4]) <= 29 && - bits.Len32(x[5]) <= 29 && - bits.Len32(x[6]) <= 29 && - bits.Len32(x[7]) <= 29 -} - -func TestP224Mul(t *testing.T) { - mulMatchesBigInt := func(a, b, out p224FieldElement) bool { - var tmp p224LargeFieldElement - p224Mul(&out, &a, &b, &tmp) - - exp := new(big.Int).Mul(p224AlternativeToBig(&a), p224AlternativeToBig(&b)) - exp.Mod(exp, P224().Params().P) - got := p224AlternativeToBig(&out) - if exp.Cmp(got) != 0 || !isInBounds(&out) { - t.Logf("a = %x", a) - t.Logf("b = %x", b) - t.Logf("p224Mul(a, b) = %x = %v", out, got) - t.Logf("a * b = %v", exp) - return false - } - - return true - } - - a := p224FieldElement{0xfffffff, 0xfffffff, 0xf00ffff, 0x20f, 0x0, 0x0, 0x0, 0x0} - b := p224FieldElement{1, 0, 0, 0, 0, 0, 0, 0} - if !mulMatchesBigInt(a, b, p224FieldElement{}) { - t.Fail() - } - - if err := quick.Check(mulMatchesBigInt, quickCheckConfig32); err != nil { - t.Error(err) - } -} - -func TestP224Square(t *testing.T) { - squareMatchesBigInt := func(a, out p224FieldElement) bool { - var tmp p224LargeFieldElement - p224Square(&out, &a, &tmp) - - exp := p224AlternativeToBig(&a) - exp.Mul(exp, exp) - exp.Mod(exp, P224().Params().P) - got := p224AlternativeToBig(&out) - if exp.Cmp(got) != 0 || !isInBounds(&out) { - t.Logf("a = %x", a) - t.Logf("p224Square(a, b) = %x = %v", out, got) - t.Logf("a * a = %v", exp) - return false - } - - return true - } - - if err := quick.Check(squareMatchesBigInt, quickCheckConfig32); err != nil { - t.Error(err) - } -} - -func TestP224Add(t *testing.T) { - addMatchesBigInt := func(a, b, out p224FieldElement) bool { - p224Add(&out, &a, &b) - - exp := new(big.Int).Add(p224AlternativeToBig(&a), p224AlternativeToBig(&b)) - exp.Mod(exp, P224().Params().P) - got := p224AlternativeToBig(&out) - if exp.Cmp(got) != 0 { - t.Logf("a = %x", a) - t.Logf("b = %x", b) - t.Logf("p224Add(a, b) = %x = %v", out, got) - t.Logf("a + b = %v", exp) - return false - } - - return true - } - - if err := quick.Check(addMatchesBigInt, quickCheckConfig32); err != nil { - t.Error(err) - } -} - -func TestP224Reduce(t *testing.T) { - reduceMatchesBigInt := func(a p224FieldElement) bool { - out := a - // TODO: generate higher values for functions like p224Reduce that are - // expected to work with higher input bounds. - p224Reduce(&out) - - exp := p224AlternativeToBig(&a) - got := p224AlternativeToBig(&out) - if exp.Cmp(got) != 0 || !isInBounds(&out) { - t.Logf("a = %x = %v", a, exp) - t.Logf("p224Reduce(a) = %x = %v", out, got) - return false - } - - return true - } - - if err := quick.Check(reduceMatchesBigInt, quickCheckConfig32); err != nil { - t.Error(err) - } -} - -func TestP224Contract(t *testing.T) { - contractMatchesBigInt := func(a, out p224FieldElement) bool { - p224Contract(&out, &a) - - exp := p224AlternativeToBig(&a) - got := p224AlternativeToBig(&out) - if exp.Cmp(got) != 0 { - t.Logf("a = %x = %v", a, exp) - t.Logf("p224Contract(a) = %x = %v", out, got) - return false - } - - // Check that out < P. - for i := range p224P { - k := 8 - i - 1 - if out[k] > p224P[k] { - t.Logf("p224Contract(a) = %x", out) - return false - } - if out[k] < p224P[k] { - return true - } - } - t.Logf("p224Contract(a) = %x", out) - return false - } - - if !contractMatchesBigInt(p224P, p224FieldElement{}) { - t.Error("p224Contract(p) is broken") - } - pMinus1 := p224FieldElement{0, 0, 0, 0xffff000, 0xfffffff, 0xfffffff, 0xfffffff, 0xfffffff} - if !contractMatchesBigInt(pMinus1, p224FieldElement{}) { - t.Error("p224Contract(p - 1) is broken") - } - // Check that we can handle input above p, but lowest limb zero. - a := p224FieldElement{0, 1, 0, 0xffff000, 0xfffffff, 0xfffffff, 0xfffffff, 0xfffffff} - if !contractMatchesBigInt(a, p224FieldElement{}) { - t.Error("p224Contract(p + 2²⁸) is broken") - } - // Check that we can handle input above p, but lowest three limbs zero. - b := p224FieldElement{0, 0, 0, 0xffff001, 0xfffffff, 0xfffffff, 0xfffffff, 0xfffffff} - if !contractMatchesBigInt(b, p224FieldElement{}) { - t.Error("p224Contract(p + 2⁸⁴) is broken") - } - - if err := quick.Check(contractMatchesBigInt, quickCheckConfig32); err != nil { - t.Error(err) - } -} - -func TestP224IsZero(t *testing.T) { - if got := p224IsZero(&p224FieldElement{}); got != 1 { - t.Errorf("p224IsZero(0) = %d, expected 1", got) - } - if got := p224IsZero(&p224P); got != 1 { - t.Errorf("p224IsZero(p) = %d, expected 1", got) - } - if got := p224IsZero(&p224FieldElement{1}); got != 0 { - t.Errorf("p224IsZero(1) = %d, expected 0", got) - } - - isZeroMatchesBigInt := func(a p224FieldElement) bool { - isZero := p224IsZero(&a) - - big := p224AlternativeToBig(&a) - if big.Sign() == 0 && isZero != 1 { - return false - } - if big.Sign() != 0 && isZero != 0 { - return false - } - return true - } - - if err := quick.Check(isZeroMatchesBigInt, quickCheckConfig32); err != nil { - t.Error(err) - } -} - -func TestP224Invert(t *testing.T) { - var out p224FieldElement - - p224Invert(&out, &p224FieldElement{}) - if got := p224IsZero(&out); got != 1 { - t.Errorf("p224Invert(0) = %x, expected 0", out) - } - - p224Invert(&out, &p224P) - if got := p224IsZero(&out); got != 1 { - t.Errorf("p224Invert(p) = %x, expected 0", out) - } - - p224Invert(&out, &p224FieldElement{1}) - p224Contract(&out, &out) - if out != (p224FieldElement{1}) { - t.Errorf("p224Invert(1) = %x, expected 1", out) - } - - var tmp p224LargeFieldElement - a := p224FieldElement{1, 2, 3, 4, 5, 6, 7, 8} - p224Invert(&out, &a) - p224Mul(&out, &out, &a, &tmp) - p224Contract(&out, &out) - if out != (p224FieldElement{1}) { - t.Errorf("p224Invert(a) * a = %x, expected 1", out) - } -} - type baseMultTest struct { k string x, y string @@ -602,7 +298,7 @@ func TestP224BaseMult(t *testing.T) { func TestP224GenericBaseMult(t *testing.T) { // We use the P224 CurveParams directly in order to test the generic implementation. - p224 := P224().Params() + p224 := genericParamsForCurve(P224()) for i, e := range p224BaseMultTests { k, ok := new(big.Int).SetString(e.k, 10) if !ok { diff --git a/src/crypto/elliptic/p256.go b/src/crypto/elliptic/p256.go index 7747de7a50..7ff7e33548 100644 --- a/src/crypto/elliptic/p256.go +++ b/src/crypto/elliptic/p256.go @@ -209,6 +209,8 @@ var p256Precomputed = [p256Limbs * 2 * 15 * 2]uint32{ // Field element operations: +const bottom28Bits = 0xfffffff + // nonZeroToAllOnes returns: // 0xffffffff for 0 < x <= 2**31 // 0 for x == 0 or x > 2**31. @@ -269,6 +271,7 @@ const ( two30m2 = 1<<30 - 1<<2 two30p13m2 = 1<<30 + 1<<13 - 1<<2 two31m2 = 1<<31 - 1<<2 + two31m3 = 1<<31 - 1<<3 two31p24m2 = 1<<31 + 1<<24 - 1<<2 two30m27m2 = 1<<30 - 1<<27 - 1<<2 ) diff --git a/src/crypto/elliptic/p256_test.go b/src/crypto/elliptic/p256_test.go index 1435f5e1a5..c6862d9547 100644 --- a/src/crypto/elliptic/p256_test.go +++ b/src/crypto/elliptic/p256_test.go @@ -34,7 +34,7 @@ var p256MultTests = []scalarMultTest{ func TestP256BaseMult(t *testing.T) { p256 := P256() - p256Generic := p256.Params() + p256Generic := genericParamsForCurve(p256) scalars := make([]*big.Int, 0, len(p224BaseMultTests)+1) for _, e := range p224BaseMultTests { @@ -60,23 +60,6 @@ func TestP256BaseMult(t *testing.T) { func TestP256Mult(t *testing.T) { p256 := P256() - p256Generic := p256.Params() - - for i, e := range p224BaseMultTests { - x, _ := new(big.Int).SetString(e.x, 16) - y, _ := new(big.Int).SetString(e.y, 16) - k, _ := new(big.Int).SetString(e.k, 10) - - xx, yy := p256.ScalarMult(x, y, k.Bytes()) - xx2, yy2 := p256Generic.ScalarMult(x, y, k.Bytes()) - if xx.Cmp(xx2) != 0 || yy.Cmp(yy2) != 0 { - t.Errorf("#%d: got (%x, %x), want (%x, %x)", i, xx, yy, xx2, yy2) - } - if testing.Short() && i > 5 { - break - } - } - for i, e := range p256MultTests { x, _ := new(big.Int).SetString(e.xIn, 16) y, _ := new(big.Int).SetString(e.yIn, 16) diff --git a/src/crypto/elliptic/p384.go b/src/crypto/elliptic/p384.go new file mode 100644 index 0000000000..0fb7471850 --- /dev/null +++ b/src/crypto/elliptic/p384.go @@ -0,0 +1,141 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package elliptic + +import ( + "crypto/elliptic/internal/nistec" + "crypto/rand" + "math/big" +) + +// p384Curve is a Curve implementation based on nistec.P384Point. +// +// It's a wrapper that exposes the big.Int-based Curve interface and encodes the +// legacy idiosyncrasies it requires, such as invalid and infinity point +// handling. +// +// To interact with the nistec package, points are encoded into and decoded from +// properly formatted byte slices. All big.Int use is limited to this package. +// Encoding and decoding is 1/1000th of the runtime of a scalar multiplication, +// so the overhead is acceptable. +type p384Curve struct { + params *CurveParams +} + +var p384 p384Curve +var _ Curve = p384 + +func initP384() { + p384.params = &CurveParams{ + Name: "P-384", + BitSize: 384, + // FIPS 186-4, section D.1.2.4 + P: bigFromDecimal("394020061963944792122790401001436138050797392704654" + + "46667948293404245721771496870329047266088258938001861606973112319"), + N: bigFromDecimal("394020061963944792122790401001436138050797392704654" + + "46667946905279627659399113263569398956308152294913554433653942643"), + B: bigFromHex("b3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088" + + "f5013875ac656398d8a2ed19d2a85c8edd3ec2aef"), + Gx: bigFromHex("aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741" + + "e082542a385502f25dbf55296c3a545e3872760ab7"), + Gy: bigFromHex("3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da31" + + "13b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f"), + } +} + +func (curve p384Curve) Params() *CurveParams { + return curve.params +} + +func (curve p384Curve) IsOnCurve(x, y *big.Int) bool { + // IsOnCurve is documented to reject (0, 0), the conventional point at + // infinity, which however is accepted by p384PointFromAffine. + if x.Sign() == 0 && y.Sign() == 0 { + return false + } + _, ok := p384PointFromAffine(x, y) + return ok +} + +func p384PointFromAffine(x, y *big.Int) (p *nistec.P384Point, ok bool) { + // (0, 0) is by convention the point at infinity, which can't be represented + // in affine coordinates. Marshal incorrectly encodes it as an uncompressed + // point, which SetBytes would correctly reject. See Issue 37294. + if x.Sign() == 0 && y.Sign() == 0 { + return nistec.NewP384Point(), true + } + if x.BitLen() > 384 || y.BitLen() > 384 { + return nil, false + } + p, err := nistec.NewP384Point().SetBytes(Marshal(P384(), x, y)) + if err != nil { + return nil, false + } + return p, true +} + +func p384PointToAffine(p *nistec.P384Point) (x, y *big.Int) { + out := p.Bytes() + if len(out) == 1 && out[0] == 0 { + // This is the correct encoding of the point at infinity, which + // Unmarshal does not support. See Issue 37294. + return new(big.Int), new(big.Int) + } + x, y = Unmarshal(P384(), out) + if x == nil { + panic("crypto/elliptic: internal error: Unmarshal rejected a valid point encoding") + } + return x, y +} + +// p384RandomPoint returns a random point on the curve. It's used when Add, +// Double, or ScalarMult are fed a point not on the curve, which is undefined +// behavior. Originally, we used to do the math on it anyway (which allows +// invalid curve attacks) and relied on the caller and Unmarshal to avoid this +// happening in the first place. Now, we just can't construct a nistec.P384Point +// for an invalid pair of coordinates, because that API is safer. If we panic, +// we risk introducing a DoS. If we return nil, we risk a panic. If we return +// the input, ecdsa.Verify might fail open. The safest course seems to be to +// return a valid, random point, which hopefully won't help the attacker. +func p384RandomPoint() (x, y *big.Int) { + _, x, y, err := GenerateKey(P384(), rand.Reader) + if err != nil { + panic("crypto/elliptic: failed to generate random point") + } + return x, y +} + +func (p384Curve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) { + p1, ok := p384PointFromAffine(x1, y1) + if !ok { + return p384RandomPoint() + } + p2, ok := p384PointFromAffine(x2, y2) + if !ok { + return p384RandomPoint() + } + return p384PointToAffine(p1.Add(p1, p2)) +} + +func (p384Curve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) { + p, ok := p384PointFromAffine(x1, y1) + if !ok { + return p384RandomPoint() + } + return p384PointToAffine(p.Double(p)) +} + +func (p384Curve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *big.Int) { + p, ok := p384PointFromAffine(Bx, By) + if !ok { + return p384RandomPoint() + } + return p384PointToAffine(p.ScalarMult(p, scalar)) +} + +func (p384Curve) ScalarBaseMult(scalar []byte) (*big.Int, *big.Int) { + p := nistec.NewP384Generator() + return p384PointToAffine(p.ScalarMult(p, scalar)) +} diff --git a/src/crypto/elliptic/p521.go b/src/crypto/elliptic/p521.go index 4cc5f86d6d..6c9eed30e5 100644 --- a/src/crypto/elliptic/p521.go +++ b/src/crypto/elliptic/p521.go @@ -55,19 +55,25 @@ func (curve p521Curve) Params() *CurveParams { } func (curve p521Curve) IsOnCurve(x, y *big.Int) bool { - // IsOnCurve is documented to reject (0, 0), so we don't use - // p521PointFromAffine, but let SetBytes reject the invalid Marshal output. - _, err := nistec.NewP521Point().SetBytes(Marshal(curve, x, y)) - return err == nil + // IsOnCurve is documented to reject (0, 0), the conventional point at + // infinity, which however is accepted by p521PointFromAffine. + if x.Sign() == 0 && y.Sign() == 0 { + return false + } + _, ok := p521PointFromAffine(x, y) + return ok } func p521PointFromAffine(x, y *big.Int) (p *nistec.P521Point, ok bool) { // (0, 0) is by convention the point at infinity, which can't be represented // in affine coordinates. Marshal incorrectly encodes it as an uncompressed - // point, which SetBytes correctly rejects. See Issue 37294. + // point, which SetBytes would correctly reject. See Issue 37294. if x.Sign() == 0 && y.Sign() == 0 { return nistec.NewP521Point(), true } + if x.BitLen() > 521 || y.BitLen() > 521 { + return nil, false + } p, err := nistec.NewP521Point().SetBytes(Marshal(P521(), x, y)) if err != nil { return nil, false @@ -106,7 +112,7 @@ func p521RandomPoint() (x, y *big.Int) { return x, y } -func (curve p521Curve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) { +func (p521Curve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) { p1, ok := p521PointFromAffine(x1, y1) if !ok { return p521RandomPoint() @@ -118,7 +124,7 @@ func (curve p521Curve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) { return p521PointToAffine(p1.Add(p1, p2)) } -func (curve p521Curve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) { +func (p521Curve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) { p, ok := p521PointFromAffine(x1, y1) if !ok { return p521RandomPoint() @@ -126,7 +132,7 @@ func (curve p521Curve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) { return p521PointToAffine(p.Double(p)) } -func (curve p521Curve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *big.Int) { +func (p521Curve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *big.Int) { p, ok := p521PointFromAffine(Bx, By) if !ok { return p521RandomPoint() @@ -134,7 +140,7 @@ func (curve p521Curve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *bi return p521PointToAffine(p.ScalarMult(p, scalar)) } -func (curve p521Curve) ScalarBaseMult(scalar []byte) (*big.Int, *big.Int) { +func (p521Curve) ScalarBaseMult(scalar []byte) (*big.Int, *big.Int) { p := nistec.NewP521Generator() return p521PointToAffine(p.ScalarMult(p, scalar)) } diff --git a/src/crypto/tls/common.go b/src/crypto/tls/common.go index 610a5162dd..bb5bec3c4d 100644 --- a/src/crypto/tls/common.go +++ b/src/crypto/tls/common.go @@ -18,6 +18,7 @@ import ( "crypto/x509" "errors" "fmt" + "internal/godebug" "io" "net" "strings" @@ -682,11 +683,20 @@ type Config struct { ClientSessionCache ClientSessionCache // MinVersion contains the minimum TLS version that is acceptable. - // If zero, TLS 1.0 is currently taken as the minimum. + // + // By default, TLS 1.2 is currently used as the minimum when acting as a + // client, and TLS 1.0 when acting as a server. TLS 1.0 is the minimum + // supported by this package, both as a client and as a server. + // + // The client-side default can temporarily be reverted to TLS 1.0 by + // including the value "x509sha1=1" in the GODEBUG environment variable. + // Note that this option will be removed in Go 1.19 (but it will still be + // possible to set this field to VersionTLS10 explicitly). MinVersion uint16 // MaxVersion contains the maximum TLS version that is acceptable. - // If zero, the maximum version supported by this package is used, + // + // By default, the maximum version supported by this package is used, // which is currently TLS 1.3. MaxVersion uint16 @@ -964,9 +974,21 @@ var supportedVersions = []uint16{ VersionTLS10, } -func (c *Config) supportedVersions() []uint16 { +// debugEnableTLS10 enables TLS 1.0. See issue 45428. +var debugEnableTLS10 = godebug.Get("tls10default") == "1" + +// roleClient and roleServer are meant to call supportedVersions and parents +// with more readability at the callsite. +const roleClient = true +const roleServer = false + +func (c *Config) supportedVersions(isClient bool) []uint16 { versions := make([]uint16, 0, len(supportedVersions)) for _, v := range supportedVersions { + if (c == nil || c.MinVersion == 0) && !debugEnableTLS10 && + isClient && v < VersionTLS12 { + continue + } if c != nil && c.MinVersion != 0 && v < c.MinVersion { continue } @@ -978,8 +1000,8 @@ func (c *Config) supportedVersions() []uint16 { return versions } -func (c *Config) maxSupportedVersion() uint16 { - supportedVersions := c.supportedVersions() +func (c *Config) maxSupportedVersion(isClient bool) uint16 { + supportedVersions := c.supportedVersions(isClient) if len(supportedVersions) == 0 { return 0 } @@ -1020,8 +1042,8 @@ func (c *Config) supportsCurve(curve CurveID) bool { // mutualVersion returns the protocol version to use given the advertised // versions of the peer. Priority is given to the peer preference order. -func (c *Config) mutualVersion(peerVersions []uint16) (uint16, bool) { - supportedVersions := c.supportedVersions() +func (c *Config) mutualVersion(isClient bool, peerVersions []uint16) (uint16, bool) { + supportedVersions := c.supportedVersions(isClient) for _, peerVersion := range peerVersions { for _, v := range supportedVersions { if v == peerVersion { @@ -1100,7 +1122,7 @@ func (chi *ClientHelloInfo) SupportsCertificate(c *Certificate) error { if config == nil { config = &Config{} } - vers, ok := config.mutualVersion(chi.SupportedVersions) + vers, ok := config.mutualVersion(roleServer, chi.SupportedVersions) if !ok { return errors.New("no mutually supported protocol versions") } diff --git a/src/crypto/tls/handshake_client.go b/src/crypto/tls/handshake_client.go index 4af3d998a3..2ae6f3f534 100644 --- a/src/crypto/tls/handshake_client.go +++ b/src/crypto/tls/handshake_client.go @@ -52,12 +52,12 @@ func (c *Conn) makeClientHello() (*clientHelloMsg, ecdheParameters, error) { return nil, nil, errors.New("tls: NextProtos values too large") } - supportedVersions := config.supportedVersions() + supportedVersions := config.supportedVersions(roleClient) if len(supportedVersions) == 0 { return nil, nil, errors.New("tls: no supported versions satisfy MinVersion and MaxVersion") } - clientHelloVersion := config.maxSupportedVersion() + clientHelloVersion := config.maxSupportedVersion(roleClient) // The version at the beginning of the ClientHello was capped at TLS 1.2 // for compatibility reasons. The supported_versions extension is used // to negotiate versions now. See RFC 8446, Section 4.2.1. @@ -194,7 +194,7 @@ func (c *Conn) clientHandshake(ctx context.Context) (err error) { // If we are negotiating a protocol version that's lower than what we // support, check for the server downgrade canaries. // See RFC 8446, Section 4.1.3. - maxVers := c.config.maxSupportedVersion() + maxVers := c.config.maxSupportedVersion(roleClient) tls12Downgrade := string(serverHello.random[24:]) == downgradeCanaryTLS12 tls11Downgrade := string(serverHello.random[24:]) == downgradeCanaryTLS11 if maxVers == VersionTLS13 && c.vers <= VersionTLS12 && (tls12Downgrade || tls11Downgrade) || @@ -362,7 +362,7 @@ func (c *Conn) pickTLSVersion(serverHello *serverHelloMsg) error { peerVersion = serverHello.supportedVersion } - vers, ok := c.config.mutualVersion([]uint16{peerVersion}) + vers, ok := c.config.mutualVersion(roleClient, []uint16{peerVersion}) if !ok { c.sendAlert(alertProtocolVersion) return fmt.Errorf("tls: server selected unsupported protocol version %x", peerVersion) diff --git a/src/crypto/tls/handshake_server.go b/src/crypto/tls/handshake_server.go index 43f30e2fef..5cb152755b 100644 --- a/src/crypto/tls/handshake_server.go +++ b/src/crypto/tls/handshake_server.go @@ -156,7 +156,7 @@ func (c *Conn) readClientHello(ctx context.Context) (*clientHelloMsg, error) { if len(clientHello.supportedVersions) == 0 { clientVersions = supportedVersionsFromMax(clientHello.vers) } - c.vers, ok = c.config.mutualVersion(clientVersions) + c.vers, ok = c.config.mutualVersion(roleServer, clientVersions) if !ok { c.sendAlert(alertProtocolVersion) return nil, fmt.Errorf("tls: client offered only unsupported versions: %x", clientVersions) @@ -191,7 +191,7 @@ func (hs *serverHandshakeState) processClientHello() error { hs.hello.random = make([]byte, 32) serverRandom := hs.hello.random // Downgrade protection canaries. See RFC 8446, Section 4.1.3. - maxVers := c.config.maxSupportedVersion() + maxVers := c.config.maxSupportedVersion(roleServer) if maxVers >= VersionTLS12 && c.vers < maxVers || testingOnlyForceDowngradeCanary { if c.vers == VersionTLS12 { copy(serverRandom[24:], downgradeCanaryTLS12) @@ -354,7 +354,7 @@ func (hs *serverHandshakeState) pickCipherSuite() error { for _, id := range hs.clientHello.cipherSuites { if id == TLS_FALLBACK_SCSV { // The client is doing a fallback connection. See RFC 7507. - if hs.clientHello.vers < c.config.maxSupportedVersion() { + if hs.clientHello.vers < c.config.maxSupportedVersion(roleServer) { c.sendAlert(alertInappropriateFallback) return errors.New("tls: client using inappropriate protocol fallback") } diff --git a/src/crypto/tls/handshake_server_test.go b/src/crypto/tls/handshake_server_test.go index f61b4c88ef..5fb2ebbbb3 100644 --- a/src/crypto/tls/handshake_server_test.go +++ b/src/crypto/tls/handshake_server_test.go @@ -385,13 +385,30 @@ func TestVersion(t *testing.T) { } clientConfig := &Config{ InsecureSkipVerify: true, + MinVersion: VersionTLS10, } state, _, err := testHandshake(t, clientConfig, serverConfig) if err != nil { t.Fatalf("handshake failed: %s", err) } if state.Version != VersionTLS11 { - t.Fatalf("Incorrect version %x, should be %x", state.Version, VersionTLS11) + t.Fatalf("incorrect version %x, should be %x", state.Version, VersionTLS11) + } + + clientConfig.MinVersion = 0 + _, _, err = testHandshake(t, clientConfig, serverConfig) + if err == nil { + t.Fatalf("expected failure to connect with TLS 1.0/1.1") + } + + defer func(old bool) { debugEnableTLS10 = old }(debugEnableTLS10) + debugEnableTLS10 = true + _, _, err = testHandshake(t, clientConfig, serverConfig) + if err != nil { + t.Fatalf("handshake failed: %s", err) + } + if state.Version != VersionTLS11 { + t.Fatalf("incorrect version %x, should be %x", state.Version, VersionTLS11) } } @@ -472,6 +489,7 @@ func testCrossVersionResume(t *testing.T, version uint16) { InsecureSkipVerify: true, ClientSessionCache: NewLRUClientSessionCache(1), ServerName: "servername", + MinVersion: VersionTLS10, } // Establish a session at TLS 1.1. diff --git a/src/crypto/tls/handshake_server_tls13.go b/src/crypto/tls/handshake_server_tls13.go index 08251b84de..0b19502762 100644 --- a/src/crypto/tls/handshake_server_tls13.go +++ b/src/crypto/tls/handshake_server_tls13.go @@ -110,7 +110,7 @@ func (hs *serverHandshakeStateTLS13) processClientHello() error { if id == TLS_FALLBACK_SCSV { // Use c.vers instead of max(supported_versions) because an attacker // could defeat this by adding an arbitrary high version otherwise. - if c.vers < c.config.maxSupportedVersion() { + if c.vers < c.config.maxSupportedVersion(roleServer) { c.sendAlert(alertInappropriateFallback) return errors.New("tls: client using inappropriate protocol fallback") } diff --git a/src/crypto/tls/handshake_test.go b/src/crypto/tls/handshake_test.go index 90ac9bd11e..bacc8b7d4f 100644 --- a/src/crypto/tls/handshake_test.go +++ b/src/crypto/tls/handshake_test.go @@ -363,6 +363,8 @@ func runMain(m *testing.M) int { Certificates: make([]Certificate, 2), InsecureSkipVerify: true, CipherSuites: allCipherSuites(), + MinVersion: VersionTLS10, + MaxVersion: VersionTLS13, } testConfig.Certificates[0].Certificate = [][]byte{testRSACertificate} testConfig.Certificates[0].PrivateKey = testRSAPrivateKey diff --git a/src/crypto/x509/root_darwin.go b/src/crypto/x509/root_darwin.go index 164ad9dc77..ef051efd31 100644 --- a/src/crypto/x509/root_darwin.go +++ b/src/crypto/x509/root_darwin.go @@ -10,11 +10,11 @@ import ( "bytes" macOS "crypto/x509/internal/macos" "fmt" + "internal/godebug" "os" - "strings" ) -var debugDarwinRoots = strings.Contains(os.Getenv("GODEBUG"), "x509roots=1") +var debugDarwinRoots = godebug.Get("x509roots") == "1" func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) { return nil, nil diff --git a/src/crypto/x509/verify_test.go b/src/crypto/x509/verify_test.go index df78abd77e..b9b71f4c1e 100644 --- a/src/crypto/x509/verify_test.go +++ b/src/crypto/x509/verify_test.go @@ -534,6 +534,10 @@ func testVerify(t *testing.T, test verifyTest, useSystemRoots bool) { } func TestGoVerify(t *testing.T) { + // Temporarily enable SHA-1 verification since a number of test chains + // require it. TODO(filippo): regenerate test chains. + defer func(old bool) { debugAllowSHA1 = old }(debugAllowSHA1) + debugAllowSHA1 = true for _, test := range verifyTests { t.Run(test.name, func(t *testing.T) { testVerify(t, test, false) diff --git a/src/crypto/x509/x509.go b/src/crypto/x509/x509.go index 4304ab54e1..b5c2b22cd7 100644 --- a/src/crypto/x509/x509.go +++ b/src/crypto/x509/x509.go @@ -18,6 +18,7 @@ import ( "encoding/pem" "errors" "fmt" + "internal/godebug" "io" "math/big" "net" @@ -181,15 +182,15 @@ type SignatureAlgorithm int const ( UnknownSignatureAlgorithm SignatureAlgorithm = iota - MD2WithRSA // Unsupported. - MD5WithRSA // Only supported for signing, not verification. - SHA1WithRSA + MD2WithRSA // Unsupported. + MD5WithRSA // Only supported for signing, not verification. + SHA1WithRSA // Only supported for signing, not verification. SHA256WithRSA SHA384WithRSA SHA512WithRSA DSAWithSHA1 // Unsupported. DSAWithSHA256 // Unsupported. - ECDSAWithSHA1 + ECDSAWithSHA1 // Only supported for signing, not verification. ECDSAWithSHA256 ECDSAWithSHA384 ECDSAWithSHA512 @@ -729,11 +730,23 @@ type Certificate struct { // involves algorithms that are not currently implemented. var ErrUnsupportedAlgorithm = errors.New("x509: cannot verify signature: algorithm unimplemented") -// An InsecureAlgorithmError +// debugAllowSHA1 allows SHA-1 signatures. See issue 41682. +var debugAllowSHA1 = godebug.Get("x509sha1") == "1" + +// An InsecureAlgorithmError indicates that the SignatureAlgorithm used to +// generate the signature is not secure, and the signature has been rejected. +// +// To temporarily restore support for SHA-1 signatures, include the value +// "x509sha1=1" in the GODEBUG environment variable. Note that this option will +// be removed in Go 1.19. type InsecureAlgorithmError SignatureAlgorithm func (e InsecureAlgorithmError) Error() string { - return fmt.Sprintf("x509: cannot verify signature: insecure algorithm %v", SignatureAlgorithm(e)) + var override string + if SignatureAlgorithm(e) == SHA1WithRSA || SignatureAlgorithm(e) == ECDSAWithSHA1 { + override = " (temporarily override with GODEBUG=x509sha1=1)" + } + return fmt.Sprintf("x509: cannot verify signature: insecure algorithm %v", SignatureAlgorithm(e)) + override } // ConstraintViolationError results when a requested usage is not permitted by @@ -825,6 +838,11 @@ func checkSignature(algo SignatureAlgorithm, signed, signature []byte, publicKey } case crypto.MD5: return InsecureAlgorithmError(algo) + case crypto.SHA1: + if !debugAllowSHA1 { + return InsecureAlgorithmError(algo) + } + fallthrough default: if !hashType.Available() { return ErrUnsupportedAlgorithm @@ -1579,9 +1597,12 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv } // Check the signature to ensure the crypto.Signer behaved correctly. - // We skip this check if the signature algorithm is MD5WithRSA as we - // only support this algorithm for signing, and not verification. - if sigAlg := getSignatureAlgorithmFromAI(signatureAlgorithm); sigAlg != MD5WithRSA { + sigAlg := getSignatureAlgorithmFromAI(signatureAlgorithm) + switch sigAlg { + case MD5WithRSA, SHA1WithRSA, ECDSAWithSHA1: + // We skip the check if the signature algorithm is only supported for + // signing, not verification. + default: if err := checkSignature(sigAlg, c.Raw, signature, key.Public()); err != nil { return nil, fmt.Errorf("x509: signature over certificate returned by signer is invalid: %w", err) } diff --git a/src/crypto/x509/x509_test.go b/src/crypto/x509/x509_test.go index a4053abf41..affab3789d 100644 --- a/src/crypto/x509/x509_test.go +++ b/src/crypto/x509/x509_test.go @@ -585,10 +585,10 @@ func TestCreateSelfSignedCertificate(t *testing.T) { checkSig bool sigAlgo SignatureAlgorithm }{ - {"RSA/RSA", &testPrivateKey.PublicKey, testPrivateKey, true, SHA1WithRSA}, + {"RSA/RSA", &testPrivateKey.PublicKey, testPrivateKey, true, SHA384WithRSA}, {"RSA/ECDSA", &testPrivateKey.PublicKey, ecdsaPriv, false, ECDSAWithSHA384}, {"ECDSA/RSA", &ecdsaPriv.PublicKey, testPrivateKey, false, SHA256WithRSA}, - {"ECDSA/ECDSA", &ecdsaPriv.PublicKey, ecdsaPriv, true, ECDSAWithSHA1}, + {"ECDSA/ECDSA", &ecdsaPriv.PublicKey, ecdsaPriv, true, ECDSAWithSHA256}, {"RSAPSS/RSAPSS", &testPrivateKey.PublicKey, testPrivateKey, true, SHA256WithRSAPSS}, {"ECDSA/RSAPSS", &ecdsaPriv.PublicKey, testPrivateKey, false, SHA256WithRSAPSS}, {"RSAPSS/ECDSA", &testPrivateKey.PublicKey, ecdsaPriv, false, ECDSAWithSHA384}, @@ -886,7 +886,6 @@ var ecdsaTests = []struct { sigAlgo SignatureAlgorithm pemCert string }{ - {ECDSAWithSHA1, ecdsaSHA1CertPem}, {ECDSAWithSHA256, ecdsaSHA256p256CertPem}, {ECDSAWithSHA256, ecdsaSHA256p384CertPem}, {ECDSAWithSHA384, ecdsaSHA384p521CertPem}, @@ -1389,10 +1388,10 @@ func TestCreateCertificateRequest(t *testing.T) { priv interface{} sigAlgo SignatureAlgorithm }{ - {"RSA", testPrivateKey, SHA1WithRSA}, - {"ECDSA-256", ecdsa256Priv, ECDSAWithSHA1}, - {"ECDSA-384", ecdsa384Priv, ECDSAWithSHA1}, - {"ECDSA-521", ecdsa521Priv, ECDSAWithSHA1}, + {"RSA", testPrivateKey, SHA256WithRSA}, + {"ECDSA-256", ecdsa256Priv, ECDSAWithSHA256}, + {"ECDSA-384", ecdsa384Priv, ECDSAWithSHA256}, + {"ECDSA-521", ecdsa521Priv, ECDSAWithSHA256}, {"Ed25519", ed25519Priv, PureEd25519}, } @@ -1783,6 +1782,9 @@ func TestInsecureAlgorithmErrorString(t *testing.T) { sa SignatureAlgorithm want string }{ + {MD5WithRSA, "x509: cannot verify signature: insecure algorithm MD5-RSA"}, + {SHA1WithRSA, "x509: cannot verify signature: insecure algorithm SHA1-RSA (temporarily override with GODEBUG=x509sha1=1)"}, + {ECDSAWithSHA1, "x509: cannot verify signature: insecure algorithm ECDSA-SHA1 (temporarily override with GODEBUG=x509sha1=1)"}, {MD2WithRSA, "x509: cannot verify signature: insecure algorithm MD2-RSA"}, {-1, "x509: cannot verify signature: insecure algorithm -1"}, {0, "x509: cannot verify signature: insecure algorithm 0"}, @@ -1846,6 +1848,30 @@ func TestMD5(t *testing.T) { } } +func TestSHA1(t *testing.T) { + pemBlock, _ := pem.Decode([]byte(ecdsaSHA1CertPem)) + cert, err := ParseCertificate(pemBlock.Bytes) + if err != nil { + t.Fatalf("failed to parse certificate: %s", err) + } + if sa := cert.SignatureAlgorithm; sa != ECDSAWithSHA1 { + t.Errorf("signature algorithm is %v, want %v", sa, ECDSAWithSHA1) + } + if err = cert.CheckSignatureFrom(cert); err == nil { + t.Fatalf("certificate verification succeeded incorrectly") + } + if _, ok := err.(InsecureAlgorithmError); !ok { + t.Fatalf("certificate verification returned %v (%T), wanted InsecureAlgorithmError", err, err) + } + + defer func(old bool) { debugAllowSHA1 = old }(debugAllowSHA1) + debugAllowSHA1 = true + + if err = cert.CheckSignatureFrom(cert); err != nil { + t.Fatalf("SHA-1 certificate did not verify with GODEBUG=x509sha1=1: %v", err) + } +} + // certMissingRSANULL contains an RSA public key where the AlgorithmIdentifier // parameters are omitted rather than being an ASN.1 NULL. const certMissingRSANULL = ` @@ -2897,19 +2923,31 @@ func TestCreateCertificateBrokenSigner(t *testing.T) { } } -func TestCreateCertificateMD5(t *testing.T) { - template := &Certificate{ - SerialNumber: big.NewInt(10), - DNSNames: []string{"example.com"}, - SignatureAlgorithm: MD5WithRSA, - } - k, err := rsa.GenerateKey(rand.Reader, 1024) +func TestCreateCertificateLegacy(t *testing.T) { + ecdsaPriv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { - t.Fatalf("failed to generate test key: %s", err) + t.Fatalf("Failed to generate ECDSA key: %s", err) } - _, err = CreateCertificate(rand.Reader, template, template, k.Public(), &brokenSigner{k.Public()}) - if err != nil { - t.Fatalf("CreateCertificate failed when SignatureAlgorithm = MD5WithRSA: %s", err) + + for _, sigAlg := range []SignatureAlgorithm{ + MD5WithRSA, SHA1WithRSA, ECDSAWithSHA1, + } { + template := &Certificate{ + SerialNumber: big.NewInt(10), + DNSNames: []string{"example.com"}, + SignatureAlgorithm: sigAlg, + } + var k crypto.Signer + switch sigAlg { + case MD5WithRSA, SHA1WithRSA: + k = testPrivateKey + case ECDSAWithSHA1: + k = ecdsaPriv + } + _, err := CreateCertificate(rand.Reader, template, template, k.Public(), &brokenSigner{k.Public()}) + if err != nil { + t.Fatalf("CreateCertificate failed when SignatureAlgorithm = %v: %s", sigAlg, err) + } } } @@ -3131,7 +3169,6 @@ func TestParseCertificateRawEquals(t *testing.T) { if !bytes.Equal(p.Bytes, cert.Raw) { t.Fatalf("unexpected Certificate.Raw\ngot: %x\nwant: %x\n", cert.Raw, p.Bytes) } - fmt.Printf("in: %x\nout: %x\n", p.Bytes, cert.Raw) } // mismatchingSigAlgIDPEM contains a certificate where the Certificate diff --git a/src/database/sql/driver/driver.go b/src/database/sql/driver/driver.go index f09396175a..ea1de5a8fb 100644 --- a/src/database/sql/driver/driver.go +++ b/src/database/sql/driver/driver.go @@ -156,6 +156,9 @@ var ErrSkip = errors.New("driver: skip fast-path; continue as if unimplemented") // if there's a possibility that the database server might have // performed the operation. Even if the server sends back an error, // you shouldn't return ErrBadConn. +// +// Errors will be checked using errors.Is. An error may +// wrap ErrBadConn or implement the Is(error) bool method. var ErrBadConn = errors.New("driver: bad connection") // Pinger is an optional interface that may be implemented by a Conn. diff --git a/src/database/sql/fakedb_test.go b/src/database/sql/fakedb_test.go index 4b68f1cba9..34e97e012b 100644 --- a/src/database/sql/fakedb_test.go +++ b/src/database/sql/fakedb_test.go @@ -96,6 +96,19 @@ type fakeDB struct { allowAny bool } +type fakeError struct { + Message string + Wrapped error +} + +func (err fakeError) Error() string { + return err.Message +} + +func (err fakeError) Unwrap() error { + return err.Wrapped +} + type table struct { mu sync.Mutex colname []string @@ -368,7 +381,7 @@ func (c *fakeConn) isDirtyAndMark() bool { func (c *fakeConn) Begin() (driver.Tx, error) { if c.isBad() { - return nil, driver.ErrBadConn + return nil, fakeError{Wrapped: driver.ErrBadConn} } if c.currTx != nil { return nil, errors.New("fakedb: already in a transaction") @@ -401,7 +414,7 @@ func (c *fakeConn) ResetSession(ctx context.Context) error { c.dirtySession = false c.currTx = nil if c.isBad() { - return driver.ErrBadConn + return fakeError{Message: "Reset Session: bad conn", Wrapped: driver.ErrBadConn} } return nil } @@ -629,7 +642,7 @@ func (c *fakeConn) PrepareContext(ctx context.Context, query string) (driver.Stm } if c.stickyBad || (hookPrepareBadConn != nil && hookPrepareBadConn()) { - return nil, driver.ErrBadConn + return nil, fakeError{Message: "Preapre: Sticky Bad", Wrapped: driver.ErrBadConn} } c.touchMem() @@ -756,7 +769,7 @@ func (s *fakeStmt) ExecContext(ctx context.Context, args []driver.NamedValue) (d } if s.c.stickyBad || (hookExecBadConn != nil && hookExecBadConn()) { - return nil, driver.ErrBadConn + return nil, fakeError{Message: "Exec: Sticky Bad", Wrapped: driver.ErrBadConn} } if s.c.isDirtyAndMark() { return nil, errFakeConnSessionDirty @@ -870,7 +883,7 @@ func (s *fakeStmt) QueryContext(ctx context.Context, args []driver.NamedValue) ( } if s.c.stickyBad || (hookQueryBadConn != nil && hookQueryBadConn()) { - return nil, driver.ErrBadConn + return nil, fakeError{Message: "Query: Sticky Bad", Wrapped: driver.ErrBadConn} } if s.c.isDirtyAndMark() { return nil, errFakeConnSessionDirty @@ -1031,7 +1044,7 @@ var hookCommitBadConn func() bool func (tx *fakeTx) Commit() error { tx.c.currTx = nil if hookCommitBadConn != nil && hookCommitBadConn() { - return driver.ErrBadConn + return fakeError{Message: "Commit: Hook Bad Conn", Wrapped: driver.ErrBadConn} } tx.c.touchMem() return nil @@ -1043,7 +1056,7 @@ var hookRollbackBadConn func() bool func (tx *fakeTx) Rollback() error { tx.c.currTx = nil if hookRollbackBadConn != nil && hookRollbackBadConn() { - return driver.ErrBadConn + return fakeError{Message: "Rollback: Hook Bad Conn", Wrapped: driver.ErrBadConn} } tx.c.touchMem() return nil diff --git a/src/database/sql/sql.go b/src/database/sql/sql.go index b40b5c8fe4..5131c08b51 100644 --- a/src/database/sql/sql.go +++ b/src/database/sql/sql.go @@ -464,8 +464,8 @@ type DB struct { // connections in Stmt.css. numClosed uint64 - mu sync.Mutex // protects following fields - freeConn []*driverConn + mu sync.Mutex // protects following fields + freeConn []*driverConn // free connections ordered by returnedAt oldest to newest connRequests map[uint64]chan connRequest nextRequest uint64 // Next key to use in connRequests. numOpen int // number of opened and pending open connections @@ -848,14 +848,15 @@ func (db *DB) pingDC(ctx context.Context, dc *driverConn, release func(error)) e func (db *DB) PingContext(ctx context.Context) error { var dc *driverConn var err error - + var isBadConn bool for i := 0; i < maxBadConnRetries; i++ { dc, err = db.conn(ctx, cachedOrNewConn) - if err != driver.ErrBadConn { + isBadConn = errors.Is(err, driver.ErrBadConn) + if !isBadConn { break } } - if err == driver.ErrBadConn { + if isBadConn { dc, err = db.conn(ctx, alwaysNewConn) } if err != nil { @@ -1079,7 +1080,7 @@ func (db *DB) connectionCleaner(d time.Duration) { return } - closing := db.connectionCleanerRunLocked() + d, closing := db.connectionCleanerRunLocked(d) db.mu.Unlock() for _, c := range closing { c.Close() @@ -1088,45 +1089,74 @@ func (db *DB) connectionCleaner(d time.Duration) { if d < minInterval { d = minInterval } + + if !t.Stop() { + select { + case <-t.C: + default: + } + } t.Reset(d) } } -func (db *DB) connectionCleanerRunLocked() (closing []*driverConn) { +// connectionCleanerRunLocked removes connections that should be closed from +// freeConn and returns them along side an updated duration to the next check +// if a quicker check is required to ensure connections are checked appropriately. +func (db *DB) connectionCleanerRunLocked(d time.Duration) (time.Duration, []*driverConn) { + var idleClosing int64 + var closing []*driverConn + if db.maxIdleTime > 0 { + // As freeConn is ordered by returnedAt process + // in reverse order to minimise the work needed. + idleSince := nowFunc().Add(-db.maxIdleTime) + last := len(db.freeConn) - 1 + for i := last; i >= 0; i-- { + c := db.freeConn[i] + if c.returnedAt.Before(idleSince) { + i++ + closing = db.freeConn[:i] + db.freeConn = db.freeConn[i:] + idleClosing = int64(len(closing)) + db.maxIdleTimeClosed += idleClosing + break + } + } + + if len(db.freeConn) > 0 { + c := db.freeConn[0] + if d2 := c.returnedAt.Sub(idleSince); d2 < d { + // Ensure idle connections are cleaned up as soon as + // possible. + d = d2 + } + } + } + if db.maxLifetime > 0 { expiredSince := nowFunc().Add(-db.maxLifetime) for i := 0; i < len(db.freeConn); i++ { c := db.freeConn[i] if c.createdAt.Before(expiredSince) { closing = append(closing, c) + last := len(db.freeConn) - 1 - db.freeConn[i] = db.freeConn[last] + // Use slow delete as order is required to ensure + // connections are reused least idle time first. + copy(db.freeConn[i:], db.freeConn[i+1:]) db.freeConn[last] = nil db.freeConn = db.freeConn[:last] i-- + } else if d2 := c.createdAt.Sub(expiredSince); d2 < d { + // Prevent connections sitting the freeConn when they + // have expired by updating our next deadline d. + d = d2 } } - db.maxLifetimeClosed += int64(len(closing)) + db.maxLifetimeClosed += int64(len(closing)) - idleClosing } - if db.maxIdleTime > 0 { - expiredSince := nowFunc().Add(-db.maxIdleTime) - var expiredCount int64 - for i := 0; i < len(db.freeConn); i++ { - c := db.freeConn[i] - if db.maxIdleTime > 0 && c.returnedAt.Before(expiredSince) { - closing = append(closing, c) - expiredCount++ - last := len(db.freeConn) - 1 - db.freeConn[i] = db.freeConn[last] - db.freeConn[last] = nil - db.freeConn = db.freeConn[:last] - i-- - } - } - db.maxIdleTimeClosed += expiredCount - } - return + return d, closing } // DBStats contains database statistics. @@ -1272,11 +1302,12 @@ func (db *DB) conn(ctx context.Context, strategy connReuseStrategy) (*driverConn lifetime := db.maxLifetime // Prefer a free connection, if possible. - numFree := len(db.freeConn) - if strategy == cachedOrNewConn && numFree > 0 { - conn := db.freeConn[0] - copy(db.freeConn, db.freeConn[1:]) - db.freeConn = db.freeConn[:numFree-1] + last := len(db.freeConn) - 1 + if strategy == cachedOrNewConn && last >= 0 { + // Reuse the lowest idle time connection so we can close + // connections which remain idle as soon as possible. + conn := db.freeConn[last] + db.freeConn = db.freeConn[:last] conn.inUse = true if conn.expired(lifetime) { db.maxLifetimeClosed++ @@ -1287,9 +1318,9 @@ func (db *DB) conn(ctx context.Context, strategy connReuseStrategy) (*driverConn db.mu.Unlock() // Reset the session if required. - if err := conn.resetSession(ctx); err == driver.ErrBadConn { + if err := conn.resetSession(ctx); errors.Is(err, driver.ErrBadConn) { conn.Close() - return nil, driver.ErrBadConn + return nil, err } return conn, nil @@ -1351,9 +1382,9 @@ func (db *DB) conn(ctx context.Context, strategy connReuseStrategy) (*driverConn } // Reset the session if required. - if err := ret.conn.resetSession(ctx); err == driver.ErrBadConn { + if err := ret.conn.resetSession(ctx); errors.Is(err, driver.ErrBadConn) { ret.conn.Close() - return nil, driver.ErrBadConn + return nil, err } return ret.conn, ret.err } @@ -1412,7 +1443,7 @@ const debugGetPut = false // putConn adds a connection to the db's free pool. // err is optionally the last error that occurred on this connection. func (db *DB) putConn(dc *driverConn, err error, resetSession bool) { - if err != driver.ErrBadConn { + if !errors.Is(err, driver.ErrBadConn) { if !dc.validateConnection(resetSession) { err = driver.ErrBadConn } @@ -1426,7 +1457,7 @@ func (db *DB) putConn(dc *driverConn, err error, resetSession bool) { panic("sql: connection returned that was never out") } - if err != driver.ErrBadConn && dc.expired(db.maxLifetime) { + if !errors.Is(err, driver.ErrBadConn) && dc.expired(db.maxLifetime) { db.maxLifetimeClosed++ err = driver.ErrBadConn } @@ -1441,7 +1472,7 @@ func (db *DB) putConn(dc *driverConn, err error, resetSession bool) { } dc.onPut = nil - if err == driver.ErrBadConn { + if errors.Is(err, driver.ErrBadConn) { // Don't reuse bad connections. // Since the conn is considered bad and is being discarded, treat it // as closed. Don't decrement the open count here, finalClose will @@ -1521,13 +1552,15 @@ const maxBadConnRetries = 2 func (db *DB) PrepareContext(ctx context.Context, query string) (*Stmt, error) { var stmt *Stmt var err error + var isBadConn bool for i := 0; i < maxBadConnRetries; i++ { stmt, err = db.prepare(ctx, query, cachedOrNewConn) - if err != driver.ErrBadConn { + isBadConn = errors.Is(err, driver.ErrBadConn) + if !isBadConn { break } } - if err == driver.ErrBadConn { + if isBadConn { return db.prepare(ctx, query, alwaysNewConn) } return stmt, err @@ -1597,13 +1630,15 @@ func (db *DB) prepareDC(ctx context.Context, dc *driverConn, release func(error) func (db *DB) ExecContext(ctx context.Context, query string, args ...interface{}) (Result, error) { var res Result var err error + var isBadConn bool for i := 0; i < maxBadConnRetries; i++ { res, err = db.exec(ctx, query, args, cachedOrNewConn) - if err != driver.ErrBadConn { + isBadConn = errors.Is(err, driver.ErrBadConn) + if !isBadConn { break } } - if err == driver.ErrBadConn { + if isBadConn { return db.exec(ctx, query, args, alwaysNewConn) } return res, err @@ -1670,13 +1705,15 @@ func (db *DB) execDC(ctx context.Context, dc *driverConn, release func(error), q func (db *DB) QueryContext(ctx context.Context, query string, args ...interface{}) (*Rows, error) { var rows *Rows var err error + var isBadConn bool for i := 0; i < maxBadConnRetries; i++ { rows, err = db.query(ctx, query, args, cachedOrNewConn) - if err != driver.ErrBadConn { + isBadConn = errors.Is(err, driver.ErrBadConn) + if !isBadConn { break } } - if err == driver.ErrBadConn { + if isBadConn { return db.query(ctx, query, args, alwaysNewConn) } return rows, err @@ -1805,13 +1842,15 @@ func (db *DB) QueryRow(query string, args ...interface{}) *Row { func (db *DB) BeginTx(ctx context.Context, opts *TxOptions) (*Tx, error) { var tx *Tx var err error + var isBadConn bool for i := 0; i < maxBadConnRetries; i++ { tx, err = db.begin(ctx, opts, cachedOrNewConn) - if err != driver.ErrBadConn { + isBadConn = errors.Is(err, driver.ErrBadConn) + if !isBadConn { break } } - if err == driver.ErrBadConn { + if isBadConn { return db.begin(ctx, opts, alwaysNewConn) } return tx, err @@ -1884,13 +1923,15 @@ var ErrConnDone = errors.New("sql: connection is already closed") func (db *DB) Conn(ctx context.Context) (*Conn, error) { var dc *driverConn var err error + var isBadConn bool for i := 0; i < maxBadConnRetries; i++ { dc, err = db.conn(ctx, cachedOrNewConn) - if err != driver.ErrBadConn { + isBadConn = errors.Is(err, driver.ErrBadConn) + if !isBadConn { break } } - if err == driver.ErrBadConn { + if isBadConn { dc, err = db.conn(ctx, alwaysNewConn) } if err != nil { @@ -2002,8 +2043,8 @@ func (c *Conn) PrepareContext(ctx context.Context, query string) (*Stmt, error) // Raw executes f exposing the underlying driver connection for the // duration of f. The driverConn must not be used outside of f. // -// Once f returns and err is not equal to driver.ErrBadConn, the Conn will -// continue to be usable until Conn.Close is called. +// Once f returns and err is not driver.ErrBadConn, the Conn will continue to be usable +// until Conn.Close is called. func (c *Conn) Raw(f func(driverConn interface{}) error) (err error) { var dc *driverConn var release releaseConn @@ -2054,7 +2095,7 @@ func (c *Conn) BeginTx(ctx context.Context, opts *TxOptions) (*Tx, error) { // as the sql operation is done with the dc. func (c *Conn) closemuRUnlockCondReleaseConn(err error) { c.closemu.RUnlock() - if err == driver.ErrBadConn { + if errors.Is(err, driver.ErrBadConn) { c.close(err) } } @@ -2248,7 +2289,7 @@ func (tx *Tx) Commit() error { withLock(tx.dc, func() { err = tx.txi.Commit() }) - if err != driver.ErrBadConn { + if !errors.Is(err, driver.ErrBadConn) { tx.closePrepared() } tx.close(err) @@ -2280,7 +2321,7 @@ func (tx *Tx) rollback(discardConn bool) error { withLock(tx.dc, func() { err = tx.txi.Rollback() }) - if err != driver.ErrBadConn { + if !errors.Is(err, driver.ErrBadConn) { tx.closePrepared() } if discardConn { @@ -2323,8 +2364,8 @@ func (tx *Tx) PrepareContext(ctx context.Context, query string) (*Stmt, error) { // Prepare creates a prepared statement for use within a transaction. // -// The returned statement operates within the transaction and can no longer -// be used once the transaction has been committed or rolled back. +// The returned statement operates within the transaction and will be closed +// when the transaction has been committed or rolled back. // // To use an existing prepared statement on this transaction, see Tx.Stmt. // @@ -2586,7 +2627,7 @@ func (s *Stmt) ExecContext(ctx context.Context, args ...interface{}) (Result, er } dc, releaseConn, ds, err := s.connStmt(ctx, strategy) if err != nil { - if err == driver.ErrBadConn { + if errors.Is(err, driver.ErrBadConn) { continue } return nil, err @@ -2594,7 +2635,7 @@ func (s *Stmt) ExecContext(ctx context.Context, args ...interface{}) (Result, er res, err = resultFromStatement(ctx, dc.ci, ds, args...) releaseConn(err) - if err != driver.ErrBadConn { + if !errors.Is(err, driver.ErrBadConn) { return res, err } } @@ -2734,7 +2775,7 @@ func (s *Stmt) QueryContext(ctx context.Context, args ...interface{}) (*Rows, er } dc, releaseConn, ds, err := s.connStmt(ctx, strategy) if err != nil { - if err == driver.ErrBadConn { + if errors.Is(err, driver.ErrBadConn) { continue } return nil, err @@ -2768,7 +2809,7 @@ func (s *Stmt) QueryContext(ctx context.Context, args ...interface{}) (*Rows, er } releaseConn(err) - if err != driver.ErrBadConn { + if !errors.Is(err, driver.ErrBadConn) { return nil, err } } diff --git a/src/database/sql/sql_test.go b/src/database/sql/sql_test.go index f771dee4a9..889adc3164 100644 --- a/src/database/sql/sql_test.go +++ b/src/database/sql/sql_test.go @@ -2399,10 +2399,14 @@ func TestConnMaxLifetime(t *testing.T) { tx.Commit() tx2.Commit() - driver.mu.Lock() - opens = driver.openCount - opens0 - closes = driver.closeCount - closes0 - driver.mu.Unlock() + // Give connectionCleaner chance to run. + for i := 0; i < 100 && closes != 1; i++ { + time.Sleep(time.Millisecond) + driver.mu.Lock() + opens = driver.openCount - opens0 + closes = driver.closeCount - closes0 + driver.mu.Unlock() + } if opens != 3 { t.Errorf("opens = %d; want 3", opens) @@ -2410,6 +2414,10 @@ func TestConnMaxLifetime(t *testing.T) { if closes != 1 { t.Errorf("closes = %d; want 1", closes) } + + if s := db.Stats(); s.MaxLifetimeClosed != 1 { + t.Errorf("MaxLifetimeClosed = %d; want 1 %#v", s.MaxLifetimeClosed, s) + } } // golang.org/issue/5323 @@ -3151,7 +3159,7 @@ func TestTxEndBadConn(t *testing.T) { return broken } - if err := op(); err != driver.ErrBadConn { + if err := op(); !errors.Is(err, driver.ErrBadConn) { t.Errorf(name+": %v", err) return } @@ -3896,14 +3904,48 @@ func TestStatsMaxIdleClosedTen(t *testing.T) { } } +// testUseConns uses count concurrent connections with 1 nanosecond apart. +// Returns the returnedAt time of the final connection. +func testUseConns(t *testing.T, count int, tm time.Time, db *DB) time.Time { + conns := make([]*Conn, count) + ctx := context.Background() + for i := range conns { + c, err := db.Conn(ctx) + if err != nil { + t.Error(err) + } + conns[i] = c + } + + for _, c := range conns { + tm = tm.Add(time.Nanosecond) + nowFunc = func() time.Time { + return tm + } + if err := c.Close(); err != nil { + t.Error(err) + } + } + + return tm +} + func TestMaxIdleTime(t *testing.T) { + usedConns := 5 + reusedConns := 2 list := []struct { wantMaxIdleTime time.Duration + wantNextCheck time.Duration wantIdleClosed int64 timeOffset time.Duration }{ - {time.Nanosecond, 1, 10 * time.Millisecond}, - {time.Hour, 0, 10 * time.Millisecond}, + { + time.Millisecond, + time.Millisecond - time.Nanosecond, + int64(usedConns - reusedConns), + 10 * time.Millisecond, + }, + {time.Hour, time.Second, 0, 10 * time.Millisecond}, } baseTime := time.Unix(0, 0) defer func() { @@ -3917,23 +3959,38 @@ func TestMaxIdleTime(t *testing.T) { db := newTestDB(t, "people") defer closeDB(t, db) - db.SetMaxOpenConns(1) - db.SetMaxIdleConns(1) + db.SetMaxOpenConns(usedConns) + db.SetMaxIdleConns(usedConns) db.SetConnMaxIdleTime(item.wantMaxIdleTime) db.SetConnMaxLifetime(0) preMaxIdleClosed := db.Stats().MaxIdleTimeClosed - if err := db.Ping(); err != nil { - t.Fatal(err) - } + // Busy usedConns. + tm := testUseConns(t, usedConns, baseTime, db) - nowFunc = func() time.Time { - return baseTime.Add(item.timeOffset) - } + tm = baseTime.Add(item.timeOffset) + + // Reuse connections which should never be considered idle + // and exercises the sorting for issue 39471. + testUseConns(t, reusedConns, tm, db) db.mu.Lock() - closing := db.connectionCleanerRunLocked() + nc, closing := db.connectionCleanerRunLocked(time.Second) + if nc != item.wantNextCheck { + t.Errorf("got %v; want %v next check duration", nc, item.wantNextCheck) + } + + // Validate freeConn order. + var last time.Time + for _, c := range db.freeConn { + if last.After(c.returnedAt) { + t.Error("freeConn is not ordered by returnedAt") + break + } + last = c.returnedAt + } + db.mu.Unlock() for _, c := range closing { c.Close() @@ -3945,7 +4002,7 @@ func TestMaxIdleTime(t *testing.T) { st := db.Stats() maxIdleClosed := st.MaxIdleTimeClosed - preMaxIdleClosed if g, w := maxIdleClosed, item.wantIdleClosed; g != w { - t.Errorf(" got: %d; want %d max idle closed conns", g, w) + t.Errorf("got: %d; want %d max idle closed conns", g, w) } }) } diff --git a/src/debug/elf/elf.go b/src/debug/elf/elf.go index 9f8399d4d3..4c51bc4de2 100644 --- a/src/debug/elf/elf.go +++ b/src/debug/elf/elf.go @@ -2349,6 +2349,7 @@ const ( R_PPC64_GOT16_HI R_PPC64 = 16 // R_POWERPC_GOT16_HI R_PPC64_GOT16_HA R_PPC64 = 17 // R_POWERPC_GOT16_HA R_PPC64_JMP_SLOT R_PPC64 = 21 // R_POWERPC_JMP_SLOT + R_PPC64_RELATIVE R_PPC64 = 22 // R_POWERPC_RELATIVE R_PPC64_REL32 R_PPC64 = 26 // R_POWERPC_REL32 R_PPC64_ADDR64 R_PPC64 = 38 R_PPC64_ADDR16_HIGHER R_PPC64 = 39 @@ -2457,6 +2458,7 @@ var rppc64Strings = []intName{ {16, "R_PPC64_GOT16_HI"}, {17, "R_PPC64_GOT16_HA"}, {21, "R_PPC64_JMP_SLOT"}, + {22, "R_PPC64_RELATIVE"}, {26, "R_PPC64_REL32"}, {38, "R_PPC64_ADDR64"}, {39, "R_PPC64_ADDR16_HIGHER"}, diff --git a/src/debug/gosym/pclntab.go b/src/debug/gosym/pclntab.go index 134cb3d194..a687c406b2 100644 --- a/src/debug/gosym/pclntab.go +++ b/src/debug/gosym/pclntab.go @@ -297,6 +297,7 @@ func (t *LineTable) go12Funcs() []Func { ft := t.funcTab() funcs := make([]Func, ft.Count()) + syms := make([]Sym, len(funcs)) for i := range funcs { f := &funcs[i] f.Entry = ft.pc(i) @@ -304,13 +305,14 @@ func (t *LineTable) go12Funcs() []Func { info := t.funcData(uint32(i)) f.LineTable = t f.FrameSize = int(info.deferreturn()) - f.Sym = &Sym{ + syms[i] = Sym{ Value: f.Entry, Type: 'T', Name: t.funcName(info.nameoff()), GoType: 0, Func: f, } + f.Sym = &syms[i] } return funcs } diff --git a/src/debug/plan9obj/file.go b/src/debug/plan9obj/file.go index 314608da61..c054635148 100644 --- a/src/debug/plan9obj/file.go +++ b/src/debug/plan9obj/file.go @@ -301,11 +301,15 @@ func newTable(symtab []byte, ptrsz int) ([]Sym, error) { return syms, nil } +// ErrNoSymbols is returned by File.Symbols if there is no such section +// in the File. +var ErrNoSymbols = errors.New("no symbol section") + // Symbols returns the symbol table for f. func (f *File) Symbols() ([]Sym, error) { symtabSection := f.Section("syms") if symtabSection == nil { - return nil, errors.New("no symbol section") + return nil, ErrNoSymbols } symtab, err := symtabSection.Data() diff --git a/src/encoding/ascii85/ascii85.go b/src/encoding/ascii85/ascii85.go index d42eb0ab00..f1f7af863c 100644 --- a/src/encoding/ascii85/ascii85.go +++ b/src/encoding/ascii85/ascii85.go @@ -142,9 +142,7 @@ func (e *encoder) Write(p []byte) (n int, err error) { } // Trailing fringe. - for i := 0; i < len(p); i++ { - e.buf[i] = p[i] - } + copy(e.buf[:], p) e.nbuf = len(p) n += len(p) return diff --git a/src/encoding/base32/base32.go b/src/encoding/base32/base32.go index 2f7d3637e5..3feea9ba47 100644 --- a/src/encoding/base32/base32.go +++ b/src/encoding/base32/base32.go @@ -221,9 +221,7 @@ func (e *encoder) Write(p []byte) (n int, err error) { } // Trailing fringe. - for i := 0; i < len(p); i++ { - e.buf[i] = p[i] - } + copy(e.buf[:], p) e.nbuf = len(p) n += len(p) return diff --git a/src/encoding/base64/base64.go b/src/encoding/base64/base64.go index 0c33f8e5f8..4a3e590649 100644 --- a/src/encoding/base64/base64.go +++ b/src/encoding/base64/base64.go @@ -229,9 +229,7 @@ func (e *encoder) Write(p []byte) (n int, err error) { } // Trailing fringe. - for i := 0; i < len(p); i++ { - e.buf[i] = p[i] - } + copy(e.buf[:], p) e.nbuf = len(p) n += len(p) return diff --git a/src/errors/wrap.go b/src/errors/wrap.go index b73d5a8ce2..ab3cdb86d3 100644 --- a/src/errors/wrap.go +++ b/src/errors/wrap.go @@ -59,7 +59,7 @@ func Is(err, target error) bool { } } -// As finds the first error in err's chain that matches target, and if so, sets +// As finds the first error in err's chain that matches target, and if one is found, sets // target to that error value and returns true. Otherwise, it returns false. // // The chain consists of err itself followed by the sequence of errors obtained by diff --git a/src/errors/wrap_test.go b/src/errors/wrap_test.go index 6f66e99c4a..a22fee2f04 100644 --- a/src/errors/wrap_test.go +++ b/src/errors/wrap_test.go @@ -265,3 +265,13 @@ func ExampleAs() { // Output: // Failed at path: non-existing } + +func ExampleUnwrap() { + err1 := errors.New("error1") + err2 := fmt.Errorf("error2: [%w]", err1) + fmt.Println(err2) + fmt.Println(errors.Unwrap(err2)) + // Output + // error2: [error1] + // error1 +} diff --git a/src/go.mod b/src/go.mod index 35231cf911..7d982c75aa 100644 --- a/src/go.mod +++ b/src/go.mod @@ -8,6 +8,6 @@ require ( ) require ( - golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e // indirect + golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac // indirect golang.org/x/text v0.3.7 // indirect ) diff --git a/src/go.sum b/src/go.sum index 621d61384a..ff1279697d 100644 --- a/src/go.sum +++ b/src/go.sum @@ -2,7 +2,7 @@ golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s3 golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/net v0.0.0-20211005215030-d2e5035098b3 h1:G64nFNerDErBd2KdvHvIn3Ee6ccUQBTfhDZEO0DccfU= golang.org/x/net v0.0.0-20211005215030-d2e5035098b3/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e h1:XMgFehsDnnLGtjvjOfqWSUzt0alpTR1RSEuznObga2c= -golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac h1:oN6lz7iLW/YC7un8pq+9bOLyXrprv2+DKfkJY+2LJJw= +golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index f4a92f8be4..1dd65d60d9 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -173,7 +173,7 @@ var depsRules = ` io/fs < embed; - unicode, fmt !< os, os/signal; + unicode, fmt !< net, os, os/signal; os/signal, STR < path/filepath @@ -187,6 +187,8 @@ var depsRules = ` OS < golang.org/x/sys/cpu; + os < internal/godebug; + # FMT is OS (which includes string routines) plus reflect and fmt. # It does not include package log, which should be avoided in core packages. strconv, unicode @@ -352,6 +354,13 @@ var depsRules = ` golang.org/x/net/lif, golang.org/x/net/route; + os, runtime, strconv, sync, unsafe, + internal/godebug + < internal/intern; + + internal/bytealg, internal/intern, internal/itoa, math/bits, sort, strconv + < net/netip; + # net is unavoidable when doing any networking, # so large dependencies must be kept out. # This is a long-looking list but most of these @@ -360,10 +369,12 @@ var depsRules = ` golang.org/x/net/dns/dnsmessage, golang.org/x/net/lif, golang.org/x/net/route, + internal/godebug, internal/nettrace, internal/poll, internal/singleflight, internal/race, + net/netip, os < net; @@ -515,7 +526,8 @@ var depsRules = ` FMT, DEBUG, flag, runtime/trace, internal/sysinfo, math/rand < testing; - FMT, crypto/sha256, encoding/json, go/ast, go/parser, go/token, math/rand, encoding/hex, crypto/sha256 + FMT, crypto/sha256, encoding/json, go/ast, go/parser, go/token, + internal/godebug, math/rand, encoding/hex, crypto/sha256 < internal/fuzz; internal/fuzz, internal/testlog, runtime/pprof, regexp diff --git a/src/go/doc/exports.go b/src/go/doc/exports.go index 819c030c9b..671c622205 100644 --- a/src/go/doc/exports.go +++ b/src/go/doc/exports.go @@ -79,18 +79,15 @@ func hasExportedName(list []*ast.Ident) bool { return false } -// removeErrorField removes anonymous fields named "error" from an interface. -// This is called when "error" has been determined to be a local name, -// not the predeclared type. -// -func removeErrorField(ityp *ast.InterfaceType) { +// removeAnonymousField removes anonymous fields named name from an interface. +func removeAnonymousField(name string, ityp *ast.InterfaceType) { list := ityp.Methods.List // we know that ityp.Methods != nil j := 0 for _, field := range list { keepField := true if n := len(field.Names); n == 0 { // anonymous field - if fname, _ := baseTypeName(field.Type); fname == "error" { + if fname, _ := baseTypeName(field.Type); fname == name { keepField = false } } @@ -119,16 +116,25 @@ func (r *reader) filterFieldList(parent *namedType, fields *ast.FieldList, ityp for _, field := range list { keepField := false if n := len(field.Names); n == 0 { - // anonymous field + // anonymous field or embedded type or union element fname := r.recordAnonymousField(parent, field.Type) - if token.IsExported(fname) { - keepField = true - } else if ityp != nil && fname == "error" { - // possibly the predeclared error interface; keep - // it for now but remember this interface so that - // it can be fixed if error is also defined locally - keepField = true - r.remember(ityp) + if fname != "" { + if token.IsExported(fname) { + keepField = true + } else if ityp != nil && predeclaredTypes[fname] { + // possibly an embedded predeclared type; keep it for now but + // remember this interface so that it can be fixed if name is also + // defined locally + keepField = true + r.remember(fname, ityp) + } + } else { + // If we're operating on an interface, assume that this is an embedded + // type or union element. + // + // TODO(rfindley): consider traversing into approximation/unions + // elements to see if they are entirely unexported. + keepField = ityp != nil } } else { field.Names = filterIdentList(field.Names) @@ -172,6 +178,17 @@ func (r *reader) filterType(parent *namedType, typ ast.Expr) { // nothing to do case *ast.ParenExpr: r.filterType(nil, t.X) + case *ast.StarExpr: // possibly an embedded type literal + r.filterType(nil, t.X) + case *ast.UnaryExpr: + if t.Op == token.TILDE { // approximation element + r.filterType(nil, t.X) + } + case *ast.BinaryExpr: + if t.Op == token.OR { // union + r.filterType(nil, t.X) + r.filterType(nil, t.Y) + } case *ast.ArrayType: r.filterType(nil, t.Elt) case *ast.StructType: @@ -179,6 +196,7 @@ func (r *reader) filterType(parent *namedType, typ ast.Expr) { t.Incomplete = true } case *ast.FuncType: + r.filterParamList(t.TypeParams) r.filterParamList(t.Params) r.filterParamList(t.Results) case *ast.InterfaceType: @@ -219,12 +237,16 @@ func (r *reader) filterSpec(spec ast.Spec) bool { } } case *ast.TypeSpec: + // Don't filter type parameters here, by analogy with function parameters + // which are not filtered for top-level function declarations. if name := s.Name.Name; token.IsExported(name) { r.filterType(r.lookupType(s.Name.Name), s.Type) return true - } else if name == "error" { - // special case: remember that error is declared locally - r.errorDecl = true + } else if IsPredeclared(name) { + if r.shadowedPredecl == nil { + r.shadowedPredecl = make(map[string]bool) + } + r.shadowedPredecl[name] = true } } return false diff --git a/src/go/doc/filter.go b/src/go/doc/filter.go index a6f243f33e..9904da150e 100644 --- a/src/go/doc/filter.go +++ b/src/go/doc/filter.go @@ -34,6 +34,8 @@ func matchDecl(d *ast.GenDecl, f Filter) bool { if f(v.Name.Name) { return true } + // We don't match ordinary parameters in filterFuncs, so by analogy don't + // match type parameters here. switch t := v.Type.(type) { case *ast.StructType: if matchFields(t.Fields, f) { diff --git a/src/go/doc/reader.go b/src/go/doc/reader.go index c277b35e89..348b9b59a0 100644 --- a/src/go/doc/reader.go +++ b/src/go/doc/reader.go @@ -101,6 +101,10 @@ func baseTypeName(x ast.Expr) (name string, imported bool) { switch t := x.(type) { case *ast.Ident: return t.Name, false + case *ast.IndexExpr: + return baseTypeName(t.X) + case *ast.IndexListExpr: + return baseTypeName(t.X) case *ast.SelectorExpr: if _, ok := t.X.(*ast.Ident); ok { // only possible for qualified type names; @@ -112,7 +116,7 @@ func baseTypeName(x ast.Expr) (name string, imported bool) { case *ast.StarExpr: return baseTypeName(t.X) } - return + return "", false } // An embeddedSet describes a set of embedded types. @@ -163,9 +167,9 @@ type reader struct { types map[string]*namedType funcs methodSet - // support for package-local error type declarations - errorDecl bool // if set, type "error" was declared locally - fixlist []*ast.InterfaceType // list of interfaces containing anonymous field "error" + // support for package-local shadowing of predeclared types + shadowedPredecl map[string]bool + fixmap map[string][]*ast.InterfaceType } func (r *reader) isVisible(name string) bool { @@ -224,8 +228,11 @@ func (r *reader) readDoc(comment *ast.CommentGroup) { r.doc += "\n" + text } -func (r *reader) remember(typ *ast.InterfaceType) { - r.fixlist = append(r.fixlist, typ) +func (r *reader) remember(predecl string, typ *ast.InterfaceType) { + if r.fixmap == nil { + r.fixmap = make(map[string][]*ast.InterfaceType) + } + r.fixmap[predecl] = append(r.fixmap[predecl], typ) } func specNames(specs []ast.Spec) []string { @@ -679,10 +686,11 @@ func (r *reader) computeMethodSets() { } } - // if error was declared locally, don't treat it as exported field anymore - if r.errorDecl { - for _, ityp := range r.fixlist { - removeErrorField(ityp) + // For any predeclared names that are declared locally, don't treat them as + // exported fields anymore. + for predecl := range r.shadowedPredecl { + for _, ityp := range r.fixmap[predecl] { + removeAnonymousField(predecl, ityp) } } } @@ -869,6 +877,7 @@ func IsPredeclared(s string) bool { } var predeclaredTypes = map[string]bool{ + "any": true, "bool": true, "byte": true, "complex64": true, diff --git a/src/go/doc/testdata/generics.0.golden b/src/go/doc/testdata/generics.0.golden new file mode 100644 index 0000000000..a6dbcf673c --- /dev/null +++ b/src/go/doc/testdata/generics.0.golden @@ -0,0 +1,70 @@ +// Package generics contains the new syntax supporting generic ... +PACKAGE generics + +IMPORTPATH + testdata/generics + +FILENAMES + testdata/generics.go + +FUNCTIONS + // AnotherFunc has an implicit constraint interface. Neither type ... + func AnotherFunc[T ~struct{ f int }](_ struct{ f int }) + + // Func has an instantiated constraint. + func Func[T Constraint[string, Type[int]]]() + + +TYPES + // AFuncType demonstrates filtering of parameters and type ... + type AFuncType[T ~struct{ f int }] func(_ struct { + // contains filtered or unexported fields + }) + + // Constraint is a constraint interface with two type parameters. + type Constraint[P, Q interface{ string | ~int | Type[int] }] interface { + ~int | ~byte | Type[string] + M() P + } + + // NewEmbeddings demonstrates how we filter the new embedded ... + type NewEmbeddings interface { + string // should not be filtered + + struct { + // contains filtered or unexported fields + } + ~struct { + // contains filtered or unexported fields + } + *struct { + // contains filtered or unexported fields + } + struct { + // contains filtered or unexported fields + } | ~struct { + // contains filtered or unexported fields + } + // contains filtered or unexported methods + } + + // Parameterized types should be shown. + type Type[P any] struct { + Field P + } + + // Variables with an instantiated type should be shown. + var X Type[int] + + // Constructors for parameterized types should be shown. + func Constructor[lowerCase any]() Type[lowerCase] + + // MethodA uses a different name for its receiver type parameter. + func (t Type[A]) MethodA(p A) + + // MethodB has a blank receiver type parameter. + func (t Type[_]) MethodB() + + // MethodC has a lower-case receiver type parameter. + func (t Type[c]) MethodC() + diff --git a/src/go/doc/testdata/generics.1.golden b/src/go/doc/testdata/generics.1.golden new file mode 100644 index 0000000000..c0548b5e96 --- /dev/null +++ b/src/go/doc/testdata/generics.1.golden @@ -0,0 +1,60 @@ +// Package generics contains the new syntax supporting generic ... +PACKAGE generics + +IMPORTPATH + testdata/generics + +FILENAMES + testdata/generics.go + +FUNCTIONS + // AnotherFunc has an implicit constraint interface. Neither type ... + func AnotherFunc[T ~struct{ f int }](_ struct{ f int }) + + // Func has an instantiated constraint. + func Func[T Constraint[string, Type[int]]]() + + +TYPES + // AFuncType demonstrates filtering of parameters and type ... + type AFuncType[T ~struct{ f int }] func(_ struct{ f int }) + + // Constraint is a constraint interface with two type parameters. + type Constraint[P, Q interface{ string | ~int | Type[int] }] interface { + ~int | ~byte | Type[string] + M() P + } + + // NewEmbeddings demonstrates how we filter the new embedded ... + type NewEmbeddings interface { + string // should not be filtered + int16 + struct{ f int } + ~struct{ f int } + *struct{ f int } + struct{ f int } | ~struct{ f int } + } + + // Parameterized types should be shown. + type Type[P any] struct { + Field P + } + + // Variables with an instantiated type should be shown. + var X Type[int] + + // Constructors for parameterized types should be shown. + func Constructor[lowerCase any]() Type[lowerCase] + + // MethodA uses a different name for its receiver type parameter. + func (t Type[A]) MethodA(p A) + + // MethodB has a blank receiver type parameter. + func (t Type[_]) MethodB() + + // MethodC has a lower-case receiver type parameter. + func (t Type[c]) MethodC() + + // int16 shadows the predeclared type int16. + type int16 int + diff --git a/src/go/doc/testdata/generics.2.golden b/src/go/doc/testdata/generics.2.golden new file mode 100644 index 0000000000..a6dbcf673c --- /dev/null +++ b/src/go/doc/testdata/generics.2.golden @@ -0,0 +1,70 @@ +// Package generics contains the new syntax supporting generic ... +PACKAGE generics + +IMPORTPATH + testdata/generics + +FILENAMES + testdata/generics.go + +FUNCTIONS + // AnotherFunc has an implicit constraint interface. Neither type ... + func AnotherFunc[T ~struct{ f int }](_ struct{ f int }) + + // Func has an instantiated constraint. + func Func[T Constraint[string, Type[int]]]() + + +TYPES + // AFuncType demonstrates filtering of parameters and type ... + type AFuncType[T ~struct{ f int }] func(_ struct { + // contains filtered or unexported fields + }) + + // Constraint is a constraint interface with two type parameters. + type Constraint[P, Q interface{ string | ~int | Type[int] }] interface { + ~int | ~byte | Type[string] + M() P + } + + // NewEmbeddings demonstrates how we filter the new embedded ... + type NewEmbeddings interface { + string // should not be filtered + + struct { + // contains filtered or unexported fields + } + ~struct { + // contains filtered or unexported fields + } + *struct { + // contains filtered or unexported fields + } + struct { + // contains filtered or unexported fields + } | ~struct { + // contains filtered or unexported fields + } + // contains filtered or unexported methods + } + + // Parameterized types should be shown. + type Type[P any] struct { + Field P + } + + // Variables with an instantiated type should be shown. + var X Type[int] + + // Constructors for parameterized types should be shown. + func Constructor[lowerCase any]() Type[lowerCase] + + // MethodA uses a different name for its receiver type parameter. + func (t Type[A]) MethodA(p A) + + // MethodB has a blank receiver type parameter. + func (t Type[_]) MethodB() + + // MethodC has a lower-case receiver type parameter. + func (t Type[c]) MethodC() + diff --git a/src/go/doc/testdata/generics.go b/src/go/doc/testdata/generics.go new file mode 100644 index 0000000000..b5debba437 --- /dev/null +++ b/src/go/doc/testdata/generics.go @@ -0,0 +1,61 @@ +// Copyright 2021 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 generics contains the new syntax supporting generic programming in +// Go. +package generics + +// Variables with an instantiated type should be shown. +var X Type[int] + +// Parameterized types should be shown. +type Type[P any] struct { + Field P +} + +// Constructors for parameterized types should be shown. +func Constructor[lowerCase any]() Type[lowerCase] { + return Type[lowerCase]{} +} + +// MethodA uses a different name for its receiver type parameter. +func (t Type[A]) MethodA(p A) {} + +// MethodB has a blank receiver type parameter. +func (t Type[_]) MethodB() {} + +// MethodC has a lower-case receiver type parameter. +func (t Type[c]) MethodC() {} + +// Constraint is a constraint interface with two type parameters. +type Constraint[P, Q interface{ string | ~int | Type[int] }] interface { + ~int | ~byte | Type[string] + M() P +} + +// int16 shadows the predeclared type int16. +type int16 int + +// NewEmbeddings demonstrates how we filter the new embedded elements. +type NewEmbeddings interface { + string // should not be filtered + int16 + struct{ f int } + ~struct{ f int } + *struct{ f int } + struct{ f int } | ~struct{ f int } +} + +// Func has an instantiated constraint. +func Func[T Constraint[string, Type[int]]]() {} + +// AnotherFunc has an implicit constraint interface. +// +// Neither type parameters nor regular parameters should be filtered. +func AnotherFunc[T ~struct{ f int }](_ struct{ f int }) {} + +// AFuncType demonstrates filtering of parameters and type parameters. Here we +// don't filter type parameters (to be consistent with function declarations), +// but DO filter the RHS. +type AFuncType[T ~struct{ f int }] func(_ struct{ f int }) diff --git a/src/go/types/api_test.go b/src/go/types/api_test.go index 7407426979..807bffbff6 100644 --- a/src/go/types/api_test.go +++ b/src/go/types/api_test.go @@ -345,18 +345,18 @@ func TestTypesInfo(t *testing.T) { {broken + `x5; func _() { var x map[string][...]int; x = map[string][...]int{"": {1,2,3}} }`, `x`, `map[string][-1]int`}, // parameterized functions - {genericPkg + `p0; func f[T any](T) {}; var _ = f[int]`, `f`, `func[generic_p0.T interface{}](generic_p0.T)`}, + {genericPkg + `p0; func f[T any](T) {}; var _ = f[int]`, `f`, `func[T interface{}](T)`}, {genericPkg + `p1; func f[T any](T) {}; var _ = f[int]`, `f[int]`, `func(int)`}, {genericPkg + `p2; func f[T any](T) {}; func _() { f(42) }`, `f`, `func(int)`}, {genericPkg + `p3; func f[T any](T) {}; func _() { f[int](42) }`, `f[int]`, `func(int)`}, - {genericPkg + `p4; func f[T any](T) {}; func _() { f[int](42) }`, `f`, `func[generic_p4.T interface{}](generic_p4.T)`}, + {genericPkg + `p4; func f[T any](T) {}; func _() { f[int](42) }`, `f`, `func[T interface{}](T)`}, {genericPkg + `p5; func f[T any](T) {}; func _() { f(42) }`, `f(42)`, `()`}, // type parameters {genericPkg + `t0; type t[] int; var _ t`, `t`, `generic_t0.t`}, // t[] is a syntax error that is ignored in this test in favor of t - {genericPkg + `t1; type t[P any] int; var _ t[int]`, `t`, `generic_t1.t[generic_t1.P interface{}]`}, - {genericPkg + `t2; type t[P interface{}] int; var _ t[int]`, `t`, `generic_t2.t[generic_t2.P interface{}]`}, - {genericPkg + `t3; type t[P, Q interface{}] int; var _ t[int, int]`, `t`, `generic_t3.t[generic_t3.P, generic_t3.Q interface{}]`}, + {genericPkg + `t1; type t[P any] int; var _ t[int]`, `t`, `generic_t1.t[P interface{}]`}, + {genericPkg + `t2; type t[P interface{}] int; var _ t[int]`, `t`, `generic_t2.t[P interface{}]`}, + {genericPkg + `t3; type t[P, Q interface{}] int; var _ t[int, int]`, `t`, `generic_t3.t[P, Q interface{}]`}, // TODO (rFindley): compare with types2, which resolves the type broken_t4.t[P₁, Q₂ interface{m()}] here {broken + `t4; type t[P, Q interface{ m() }] int; var _ t[int, int]`, `t`, `broken_t4.t`}, @@ -365,7 +365,7 @@ func TestTypesInfo(t *testing.T) { {genericPkg + `g0; type t[P any] int; var x struct{ f t[int] }; var _ = x.f`, `x.f`, `generic_g0.t[int]`}, // issue 45096 - {genericPkg + `issue45096; func _[T interface{ ~int8 | ~int16 | ~int32 }](x T) { _ = x < 0 }`, `0`, `generic_issue45096.T`}, + {genericPkg + `issue45096; func _[T interface{ ~int8 | ~int16 | ~int32 }](x T) { _ = x < 0 }`, `0`, `T`}, // issue 47895 {`package p; import "unsafe"; type S struct { f int }; var s S; var _ = unsafe.Offsetof(s.f)`, `s.f`, `int`}, @@ -604,13 +604,6 @@ func TestDefsInfo(t *testing.T) { {`package p3; type x int`, `x`, `type p3.x int`}, {`package p4; func f()`, `f`, `func p4.f()`}, {`package p5; func f() int { x, _ := 1, 2; return x }`, `_`, `var _ int`}, - - // generic types must be sanitized - // (need to use sufficiently nested types to provoke unexpanded types) - {genericPkg + `g0; type t[P any] P; const x = t[int](42)`, `x`, `const generic_g0.x generic_g0.t[int]`}, - {genericPkg + `g1; type t[P any] P; var x = t[int](42)`, `x`, `var generic_g1.x generic_g1.t[int]`}, - {genericPkg + `g2; type t[P any] P; type x struct{ f t[int] }`, `x`, `type generic_g2.x struct{f generic_g2.t[int]}`}, - {genericPkg + `g3; type t[P any] P; func f(x struct{ f t[string] }); var g = f`, `g`, `var generic_g3.g func(x struct{f generic_g3.t[string]})`}, } for _, test := range tests { @@ -649,13 +642,6 @@ func TestUsesInfo(t *testing.T) { {`package p2; func _() { _ = x }; var x int`, `x`, `var p2.x int`}, {`package p3; func _() { type _ x }; type x int`, `x`, `type p3.x int`}, {`package p4; func _() { _ = f }; func f()`, `f`, `func p4.f()`}, - - // generic types must be sanitized - // (need to use sufficiently nested types to provoke unexpanded types) - {genericPkg + `g0; func _() { _ = x }; type t[P any] P; const x = t[int](42)`, `x`, `const generic_g0.x generic_g0.t[int]`}, - {genericPkg + `g1; func _() { _ = x }; type t[P any] P; var x = t[int](42)`, `x`, `var generic_g1.x generic_g1.t[int]`}, - {genericPkg + `g2; func _() { type _ x }; type t[P any] P; type x struct{ f t[int] }`, `x`, `type generic_g2.x struct{f generic_g2.t[int]}`}, - {genericPkg + `g3; func _() { _ = f }; type t[P any] P; func f(x struct{ f t[string] })`, `f`, `func generic_g3.f(x struct{f generic_g3.t[string]})`}, } for _, test := range tests { diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index de7d7e6b5f..aefac786ca 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -83,7 +83,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b // of S and the respective parameter passing rules apply." S := x.typ var T Type - if s := asSlice(S); s != nil { + if s, _ := structure(S).(*Slice); s != nil { T = s.elem } else { check.invalidArg(x, _InvalidAppend, "%s is not a slice", x) @@ -296,8 +296,10 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b } // the argument types must be of floating-point type - f := func(x Type) Type { - if t := asBasic(x); t != nil { + // (applyTypeFunc never calls f with a type parameter) + f := func(typ Type) Type { + assert(asTypeParam(typ) == nil) + if t := asBasic(typ); t != nil { switch t.kind { case Float32: return Typ[Complex64] @@ -330,14 +332,14 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b case _Copy: // copy(x, y []T) int - dst, _ := singleUnder(x.typ).(*Slice) + dst, _ := structure(x.typ).(*Slice) var y operand arg(&y, 1) if y.mode == invalid { return } - src, _ := singleUnderString(y.typ).(*Slice) + src, _ := structureString(y.typ).(*Slice) if dst == nil || src == nil { check.invalidArg(x, _InvalidCopy, "copy expects slice arguments; found %s and %s", x, &y) @@ -418,8 +420,10 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b } // the argument must be of complex type - f := func(x Type) Type { - if t := asBasic(x); t != nil { + // (applyTypeFunc never calls f with a type parameter) + f := func(typ Type) Type { + assert(asTypeParam(typ) == nil) + if t := asBasic(typ); t != nil { switch t.kind { case Complex64: return Typ[Float32] @@ -469,7 +473,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b } var min int // minimum number of arguments - switch singleUnder(T).(type) { + switch structure(T).(type) { case *Slice: min = 2 case *Map, *Chan: @@ -772,11 +776,11 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b return true } -// If typ is a type parameter, single under returns the single underlying -// type of all types in the corresponding type constraint if it exists, or -// nil if it doesn't exist. If typ is not a type parameter, singleUnder -// just returns the underlying type. -func singleUnder(typ Type) Type { +// If typ is a type parameter, structure returns the single underlying +// type of all types in the corresponding type constraint if it exists, +// or nil otherwise. If typ is not a type parameter, structure returns +// the underlying type. +func structure(typ Type) Type { var su Type if underIs(typ, func(u Type) bool { if su != nil && !Identical(su, u) { @@ -791,10 +795,10 @@ func singleUnder(typ Type) Type { return nil } -// singleUnderString is like singleUnder but also considers []byte and -// string as "identical". In this case, if successful, the result is always -// []byte. -func singleUnderString(typ Type) Type { +// structureString is like structure but also considers []byte and +// string as "identical". In this case, if successful, the result +// is always []byte. +func structureString(typ Type) Type { var su Type if underIs(typ, func(u Type) bool { if isString(u) { @@ -825,7 +829,7 @@ func hasVarSize(t Type) bool { } case *TypeParam: return true - case *Named, *Union, *top: + case *Named, *Union: unreachable() } return false @@ -843,7 +847,10 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type { // Test if t satisfies the requirements for the argument // type and collect possible result types at the same time. var terms []*Term - if !tp.iface().typeSet().is(func(t *term) bool { + if !tp.is(func(t *term) bool { + if t == nil { + return false + } if r := f(t.typ); r != nil { terms = append(terms, NewTerm(t.tilde, r)) return true @@ -853,8 +860,8 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type { return nil } - // Construct a suitable new type parameter for the sum type. The - // type param is placed in the current package so export/import + // Construct a suitable new type parameter for the result type. + // The type parameter is placed in the current package so export/import // works as expected. tpar := NewTypeName(token.NoPos, check.pkg, "", nil) ptyp := check.newTypeParam(tpar, NewInterfaceType(nil, []Type{NewUnion(terms)})) // assigns type to tpar as a side-effect diff --git a/src/go/types/builtins_test.go b/src/go/types/builtins_test.go index db56aea3fe..edcd7e7724 100644 --- a/src/go/types/builtins_test.go +++ b/src/go/types/builtins_test.go @@ -113,15 +113,15 @@ var builtinCalls = []struct { {"Alignof", `_ = unsafe.Alignof(0)`, `invalid type`}, // constant {"Alignof", `var x struct{}; _ = unsafe.Alignof(x)`, `invalid type`}, // constant - {"Alignof", `var x P; _ = unsafe.Alignof(x)`, `func(p.P) uintptr`}, + {"Alignof", `var x P; _ = unsafe.Alignof(x)`, `func(P) uintptr`}, {"Offsetof", `var x struct{f bool}; _ = unsafe.Offsetof(x.f)`, `invalid type`}, // constant {"Offsetof", `var x struct{_ int; f bool}; _ = unsafe.Offsetof((&x).f)`, `invalid type`}, // constant - {"Offsetof", `var x struct{_ int; f P}; _ = unsafe.Offsetof((&x).f)`, `func(p.P) uintptr`}, + {"Offsetof", `var x struct{_ int; f P}; _ = unsafe.Offsetof((&x).f)`, `func(P) uintptr`}, {"Sizeof", `_ = unsafe.Sizeof(0)`, `invalid type`}, // constant {"Sizeof", `var x struct{}; _ = unsafe.Sizeof(x)`, `invalid type`}, // constant - {"Sizeof", `var x P; _ = unsafe.Sizeof(x)`, `func(p.P) uintptr`}, + {"Sizeof", `var x P; _ = unsafe.Sizeof(x)`, `func(P) uintptr`}, {"Slice", `var p *int; _ = unsafe.Slice(p, 1)`, `func(*int, int) []int`}, {"Slice", `var p *byte; var n uintptr; _ = unsafe.Slice(p, n)`, `func(*byte, uintptr) []byte`}, diff --git a/src/go/types/call.go b/src/go/types/call.go index 6894f1c182..a7024f5f9c 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -91,6 +91,8 @@ func (check *Checker) instantiateSignature(pos token.Pos, typ *Signature, targs pos = posList[i] } check.softErrorf(atPos(pos), _Todo, err.Error()) + } else { + check.mono.recordInstance(check.pkg, pos, tparams, targs, posList) } return inst @@ -141,8 +143,7 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind { } if t := asInterface(T); t != nil { if !t.IsMethodSet() { - // TODO(rfindley): remove the phrase "type list" from this error. - check.errorf(call, _Todo, "cannot use interface %s in conversion (contains type list or is comparable)", T) + check.errorf(call, _Todo, "cannot use interface %s in conversion (contains specific type constraints or is comparable)", T) break } } @@ -173,7 +174,8 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind { // signature may be generic cgocall := x.mode == cgofunc - sig := asSignature(x.typ) + // a type parameter may be "called" if all types have the same signature + sig, _ := structure(x.typ).(*Signature) if sig == nil { check.invalidOp(x, _InvalidCall, "cannot call non-function %s", x) x.mode = invalid diff --git a/src/go/types/check.go b/src/go/types/check.go index 2b8ef9f061..3a0e4a6a23 100644 --- a/src/go/types/check.go +++ b/src/go/types/check.go @@ -129,6 +129,7 @@ type Checker struct { imports []*PkgName // list of imported packages dotImportMap map[dotImportKey]*PkgName // maps dot-imported objects to the package they were dot-imported through recvTParamMap map[*ast.Ident]*TypeParam // maps blank receiver type parameters to their type + mono monoGraph // graph for detecting non-monomorphizable instantiation loops firstErr error // first error encountered methods map[*TypeName][]*Func // maps package scope type names to associated non-blank (non-interface) methods @@ -306,6 +307,11 @@ func (check *Checker) checkFiles(files []*ast.File) (err error) { check.recordUntyped() + if check.firstErr == nil { + // TODO(mdempsky): Ensure monomorph is safe when errors exist. + check.monomorph() + } + check.pkg.complete = true // no longer needed - release memory diff --git a/src/go/types/check_test.go b/src/go/types/check_test.go index e6176738d1..75b26e34bd 100644 --- a/src/go/types/check_test.go +++ b/src/go/types/check_test.go @@ -359,6 +359,7 @@ func TestIssue47243_TypedRHS(t *testing.T) { } func TestCheck(t *testing.T) { DefPredeclaredTestFuncs(); testDirFiles(t, "testdata/check", false) } +func TestSpec(t *testing.T) { DefPredeclaredTestFuncs(); testDirFiles(t, "testdata/spec", false) } func TestExamples(t *testing.T) { testDirFiles(t, "testdata/examples", false) } func TestFixedbugs(t *testing.T) { testDirFiles(t, "testdata/fixedbugs", false) } diff --git a/src/go/types/conversions.go b/src/go/types/conversions.go index fe62adbf10..a6f0714ba0 100644 --- a/src/go/types/conversions.go +++ b/src/go/types/conversions.go @@ -16,26 +16,54 @@ import ( func (check *Checker) conversion(x *operand, T Type) { constArg := x.mode == constant_ - var ok bool - var cause string - switch { - case constArg && isConstType(T): - // constant conversion + constConvertibleTo := func(T Type, val *constant.Value) bool { switch t := asBasic(T); { - case representableConst(x.val, check, t, &x.val): - ok = true + case t == nil: + // nothing to do + case representableConst(x.val, check, t, val): + return true case isInteger(x.typ) && isString(t): codepoint := unicode.ReplacementChar if i, ok := constant.Uint64Val(x.val); ok && i <= unicode.MaxRune { codepoint = rune(i) } - x.val = constant.MakeString(string(codepoint)) - ok = true + if val != nil { + *val = constant.MakeString(string(codepoint)) + } + return true } + return false + } + + var ok bool + var cause string + switch { + case constArg && isConstType(T): + // constant conversion + ok = constConvertibleTo(T, &x.val) + case constArg && isTypeParam(T): + // x is convertible to T if it is convertible + // to each specific type in the type set of T. + // If T's type set is empty, or if it doesn't + // have specific types, constant x cannot be + // converted. + ok = under(T).(*TypeParam).underIs(func(u Type) bool { + // t is nil if there are no specific type terms + if u == nil { + cause = check.sprintf("%s does not contain specific types", T) + return false + } + if !constConvertibleTo(u, nil) { + cause = check.sprintf("cannot convert %s to %s (in %s)", x, u, T) + return false + } + return true + }) + x.mode = value // type parameters are not constants case x.convertibleTo(check, T, &cause): // non-constant conversion - x.mode = value ok = true + x.mode = value } if !ok { @@ -92,6 +120,16 @@ func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool { return true } + // determine type parameter operands with specific type terms + Vp, _ := under(x.typ).(*TypeParam) + Tp, _ := under(T).(*TypeParam) + if Vp != nil && !Vp.hasTerms() { + Vp = nil + } + if Tp != nil && !Tp.hasTerms() { + Tp = nil + } + errorf := func(format string, args ...interface{}) { if check != nil && cause != nil { msg := check.sprintf(format, args...) @@ -102,11 +140,7 @@ func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool { } } - // TODO(gri) consider passing under(x.typ), under(T) into convertibleToImpl (optimization) - Vp, _ := under(x.typ).(*TypeParam) - Tp, _ := under(T).(*TypeParam) - - // generic cases + // generic cases with specific type terms // (generic operands cannot be constants, so we can ignore x.val) switch { case Vp != nil && Tp != nil: @@ -210,6 +244,10 @@ func convertibleToImpl(check *Checker, V, T Type, cause *string) bool { return false } +// Helper predicates for convertibleToImpl. The types provided to convertibleToImpl +// may be type parameters but they won't have specific type terms. Thus it is ok to +// use the toT convenience converters in the predicates below. + func isUintptr(typ Type) bool { t := asBasic(typ) return t != nil && t.kind == Uintptr diff --git a/src/go/types/decl.go b/src/go/types/decl.go index 6982fed0b8..8d255dcf3d 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -653,9 +653,12 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) { named.underlying = Typ[Invalid] } - // If the RHS is a type parameter, it must be from this type declaration. - if tpar, _ := named.underlying.(*TypeParam); tpar != nil && tparamIndex(named.TypeParams().list(), tpar) < 0 { - check.errorf(tdecl.Type, _Todo, "cannot use function type parameter %s as RHS in type declaration", tpar) + // Disallow a lone type parameter as the RHS of a type declaration (issue #45639). + // We can look directly at named.underlying because even if it is still a *Named + // type (underlying not fully resolved yet) it cannot become a type parameter due + // to this very restriction. + if tpar, _ := named.underlying.(*TypeParam); tpar != nil { + check.error(tdecl.Type, _Todo, "cannot use a type parameter as RHS in type declaration") named.underlying = Typ[Invalid] } } diff --git a/src/go/types/errorcodes.go b/src/go/types/errorcodes.go index 49c6a74c20..88dd0fda2f 100644 --- a/src/go/types/errorcodes.go +++ b/src/go/types/errorcodes.go @@ -1301,6 +1301,13 @@ const ( // var _ = unsafe.Slice(&x, uint64(1) << 63) _InvalidUnsafeSlice + // _InvalidInstanceCycle occurs when an invalid cycle is detected + // within the instantiation graph. + // + // Example: + // func f[T any]() { f[*T]() } + _InvalidInstanceCycle + // _Todo is a placeholder for error codes that have not been decided. // TODO(rFindley) remove this error code after deciding on errors for generics code. _Todo diff --git a/src/go/types/expr.go b/src/go/types/expr.go index 8b26e64971..d4de212e06 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -100,6 +100,8 @@ func (check *Checker) overflow(x *operand, op token.Token, opPos token.Pos) { // Typed constants must be representable in // their type after each constant operation. + // x.typ cannot be a type parameter (type + // parameters cannot be constant types). if isTyped(x.typ) { check.representable(x, asBasic(x.typ)) return @@ -142,6 +144,8 @@ var op2str2 = [...]string{ token.SHL: "shift", } +// If typ is a type parameter, underIs returns the result of typ.underIs(f). +// Otherwise, underIs returns the result of f(under(typ)). func underIs(typ Type, f func(Type) bool) bool { u := under(typ) if tpar, _ := u.(*TypeParam); tpar != nil { @@ -677,6 +681,7 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const return nil, nil, _InvalidUntypedConversion } case *TypeParam: + // TODO(gri) review this code - doesn't look quite right ok := t.underIs(func(t Type) bool { target, _, _ := check.implicitTypeAndValue(x, t) return target != nil @@ -1223,7 +1228,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { goto Error } - switch utyp := singleUnder(base).(type) { + switch utyp := structure(base).(type) { case *Struct: if len(e.Elts) == 0 { break diff --git a/src/go/types/index.go b/src/go/types/index.go index 24c1812039..a85d314efa 100644 --- a/src/go/types/index.go +++ b/src/go/types/index.go @@ -101,77 +101,80 @@ func (check *Checker) indexExpr(x *operand, e *typeparams.IndexExpr) (isFuncInst case *TypeParam: // TODO(gri) report detailed failure cause for better error messages - var tkey, telem Type // tkey != nil if we have maps + var key, elem Type // key != nil: we must have all maps + mode := variable // non-maps result mode + // TODO(gri) factor out closure and use it for non-typeparam cases as well if typ.underIs(func(u Type) bool { - var key, elem Type - alen := int64(-1) // valid if >= 0 + l := int64(-1) // valid if >= 0 + var k, e Type // k is only set for maps switch t := u.(type) { case *Basic: - if !isString(t) { - return false + if isString(t) { + e = universeByte + mode = value } - elem = universeByte case *Array: - elem = t.elem - alen = t.len - case *Pointer: - a, _ := under(t.base).(*Array) - if a == nil { - return false + l = t.len + e = t.elem + if x.mode != variable { + mode = value + } + case *Pointer: + if t := asArray(t.base); t != nil { + l = t.len + e = t.elem } - elem = a.elem - alen = a.len case *Slice: - elem = t.elem + e = t.elem case *Map: - key = t.key - elem = t.elem - default: + k = t.key + e = t.elem + } + if e == nil { return false } - assert(elem != nil) - if telem == nil { + if elem == nil { // first type - tkey, telem = key, elem - length = alen - } else { - // all map keys must be identical (incl. all nil) - if !Identical(key, tkey) { - return false - } - // all element types must be identical - if !Identical(elem, telem) { - return false - } - tkey, telem = key, elem - // track the minimal length for arrays - if alen >= 0 && alen < length { - length = alen - } + length = l + key, elem = k, e + return true + } + // all map keys must be identical (incl. all nil) + // (that is, we cannot mix maps with other types) + if !Identical(key, k) { + return false + } + // all element types must be identical + if !Identical(elem, e) { + return false + } + // track the minimal length for arrays, if any + if l >= 0 && l < length { + length = l } return true }) { // For maps, the index expression must be assignable to the map key type. - if tkey != nil { + if key != nil { index := check.singleIndex(e) if index == nil { x.mode = invalid return false } - var key operand - check.expr(&key, index) - check.assignment(&key, tkey, "map index") + var k operand + check.expr(&k, index) + check.assignment(&k, key, "map index") // ok to continue even if indexing failed - map element type is known x.mode = mapindex - x.typ = telem + x.typ = elem x.expr = e return false } // no maps valid = true - x.mode = variable - x.typ = telem + x.mode = mode + x.typ = elem } } @@ -207,7 +210,7 @@ func (check *Checker) sliceExpr(x *operand, e *ast.SliceExpr) { valid := false length := int64(-1) // valid if >= 0 - switch u := singleUnder(x.typ).(type) { + switch u := structure(x.typ).(type) { case nil: check.errorf(x, _NonSliceableOperand, "cannot slice %s: type set has no single underlying type", x) x.mode = invalid diff --git a/src/go/types/infer.go b/src/go/types/infer.go index 3348c29476..41326a1be8 100644 --- a/src/go/types/infer.go +++ b/src/go/types/infer.go @@ -214,7 +214,7 @@ func (check *Checker) infer(posn positioner, tparams []*TypeParam, targs []Type, // At least one type argument couldn't be inferred. assert(index >= 0 && targs[index] == nil) tpar := tparams[index] - check.errorf(posn, _Todo, "cannot infer %s (%v) (%v)", tpar.obj.name, tpar.obj.pos, targs) + check.errorf(posn, _Todo, "cannot infer %s (%v)", tpar.obj.name, tpar.obj.pos) return nil } @@ -270,7 +270,7 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) { }() switch t := typ.(type) { - case nil, *top, *Basic: // TODO(gri) should nil be handled here? + case nil, *Basic: // TODO(gri) should nil be handled here? break case *Array: @@ -315,7 +315,7 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) { } } return tset.is(func(t *term) bool { - return w.isParameterized(t.typ) + return t != nil && w.isParameterized(t.typ) }) case *Map: @@ -358,7 +358,7 @@ func (w *tpWalker) isParameterizedTypeList(list []Type) bool { func (check *Checker) inferB(tparams []*TypeParam, targs []Type) (types []Type, index int) { assert(len(tparams) >= len(targs) && len(targs) > 0) - // Setup bidirectional unification between those structural bounds + // Setup bidirectional unification between constraints // and the corresponding type arguments (which may be nil!). u := newUnifier(false) u.x.init(tparams) @@ -371,20 +371,26 @@ func (check *Checker) inferB(tparams []*TypeParam, targs []Type) (types []Type, } } - // Unify type parameters with their structural constraints, if any. + // If a constraint has a structural type, unify the corresponding type parameter with it. for _, tpar := range tparams { - typ := tpar - sbound := typ.structuralType() + sbound := structure(tpar) if sbound != nil { - if !u.unify(typ, sbound) { - check.errorf(tpar.obj, _Todo, "%s does not match %s", tpar.obj, sbound) + // If the structural type is the underlying type of a single + // defined type in the constraint, use that defined type instead. + if named, _ := tpar.singleType().(*Named); named != nil { + sbound = named + } + if !u.unify(tpar, sbound) { + // TODO(gri) improve error message by providing the type arguments + // which we know already + check.errorf(tpar.obj, _Todo, "%s does not match %s", tpar, sbound) return nil, 0 } } } // u.x.types() now contains the incoming type arguments plus any additional type - // arguments for which there were structural constraints. The newly inferred non- + // arguments which were inferred from structural types. The newly inferred non- // nil entries may still contain references to other type parameters. // For instance, for [A any, B interface{ []C }, C interface{ *A }], if A == int // was given, unification produced the type list [int, []C, *A]. We eliminate the @@ -499,7 +505,7 @@ func (w *cycleFinder) typ(typ Type) { defer delete(w.seen, typ) switch t := typ.(type) { - case *Basic, *top: + case *Basic: // nothing to do case *Array: diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index 3720cb725a..8d8d281842 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -134,8 +134,16 @@ func (check *Checker) verify(pos token.Pos, tparams []*TypeParam, targs []Type) // TODO(gri) This should be a method of interfaces or type sets. func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *TypeParam, smap substMap) error { iface := tpar.iface() + + // Every type argument satisfies interface{}. if iface.Empty() { - return nil // no type bound + return nil + } + + // A type argument that is a type parameter with an empty type set satisfies any constraint. + // (The empty set is a subset of any set.) + if targ := asTypeParam(targ); targ != nil && targ.iface().typeSet().IsEmpty() { + return nil } // TODO(rfindley): it would be great if users could pass in a qualifier here, @@ -149,6 +157,11 @@ func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *TypeParam, smap return errors.New(sprintf(nil, qf, false, format, args...)) } + // No type argument with non-empty type set satisfies the empty type set. + if iface.typeSet().IsEmpty() { + return errorf("%s does not satisfy %s (constraint type set is empty)", targ, tpar.bound) + } + // The type parameter bound is parameterized with the same type parameters // as the instantiated type; before we can use it for bounds checking we // need to instantiate it with the type arguments with which we instantiate @@ -190,28 +203,27 @@ func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *TypeParam, smap } } - // targ's underlying type must also be one of the interface types listed, if any + // targ must also be in the set of types of iface, if any. + // Constraints with empty type sets were already excluded above. if !iface.typeSet().hasTerms() { return nil // nothing to do } - // If targ is itself a type parameter, each of its possible types, but at least one, must be in the - // list of iface types (i.e., the targ type list must be a non-empty subset of the iface types). + // If targ is itself a type parameter, each of its possible types must be in the set + // of iface types (i.e., the targ type set must be a subset of the iface type set). + // Type arguments with empty type sets were already excluded above. if targ := asTypeParam(targ); targ != nil { targBound := targ.iface() - if !targBound.typeSet().hasTerms() { - return errorf("%s does not satisfy %s (%s has no type constraints)", targ, tpar.bound, targ) - } if !targBound.typeSet().subsetOf(iface.typeSet()) { - // TODO(gri) need better error message + // TODO(gri) report which type is missing return errorf("%s does not satisfy %s", targ, tpar.bound) } return nil } - // Otherwise, targ's type or underlying type must also be one of the interface types listed, if any. + // Otherwise, targ's type must be included in the iface type set. if !iface.typeSet().includes(targ) { - // TODO(gri) better error message + // TODO(gri) report which type is missing return errorf("%s does not satisfy %s", targ, tpar.bound) } diff --git a/src/go/types/mono.go b/src/go/types/mono.go new file mode 100644 index 0000000000..d4d884393b --- /dev/null +++ b/src/go/types/mono.go @@ -0,0 +1,335 @@ +// Copyright 2021 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 ( + "go/token" +) + +// This file implements a check to validate that a Go package doesn't +// have unbounded recursive instantiation, which is not compatible +// with compilers using static instantiation (such as +// monomorphization). +// +// It implements a sort of "type flow" analysis by detecting which +// type parameters are instantiated with other type parameters (or +// types derived thereof). A package cannot be statically instantiated +// if the graph has any cycles involving at least one derived type. +// +// Concretely, we construct a directed, weighted graph. Vertices are +// used to represent type parameters as well as some defined +// types. Edges are used to represent how types depend on each other: +// +// * Everywhere a type-parameterized function or type is instantiated, +// we add edges to each type parameter from the vertices (if any) +// representing each type parameter or defined type referenced by +// the type argument. If the type argument is just the referenced +// type itself, then the edge has weight 0, otherwise 1. +// +// * For every defined type declared within a type-parameterized +// function or method, we add an edge of weight 1 to the defined +// type from each ambient type parameter. +// +// For example, given: +// +// func f[A, B any]() { +// type T int +// f[T, map[A]B]() +// } +// +// we construct vertices representing types A, B, and T. Because of +// declaration "type T int", we construct edges T<-A and T<-B with +// weight 1; and because of instantiation "f[T, map[A]B]" we construct +// edges A<-T with weight 0, and B<-A and B<-B with weight 1. +// +// Finally, we look for any positive-weight cycles. Zero-weight cycles +// are allowed because static instantiation will reach a fixed point. + +type monoGraph struct { + vertices []monoVertex + edges []monoEdge + + // canon maps method receiver type parameters to their respective + // receiver type's type parameters. + canon map[*TypeParam]*TypeParam + + // nameIdx maps a defined type or (canonical) type parameter to its + // vertex index. + nameIdx map[*TypeName]int +} + +type monoVertex struct { + weight int // weight of heaviest known path to this vertex + pre int // previous edge (if any) in the above path + len int // length of the above path + + // obj is the defined type or type parameter represented by this + // vertex. + obj *TypeName +} + +type monoEdge struct { + dst, src int + weight int + + pos token.Pos + typ Type +} + +func (check *Checker) monomorph() { + // We detect unbounded instantiation cycles using a variant of + // Bellman-Ford's algorithm. Namely, instead of always running |V| + // iterations, we run until we either reach a fixed point or we've + // found a path of length |V|. This allows us to terminate earlier + // when there are no cycles, which should be the common case. + + again := true + for again { + again = false + + for i, edge := range check.mono.edges { + src := &check.mono.vertices[edge.src] + dst := &check.mono.vertices[edge.dst] + + // N.B., we're looking for the greatest weight paths, unlike + // typical Bellman-Ford. + w := src.weight + edge.weight + if w <= dst.weight { + continue + } + + dst.pre = i + dst.len = src.len + 1 + if dst.len == len(check.mono.vertices) { + check.reportInstanceLoop(edge.dst) + return + } + + dst.weight = w + again = true + } + } +} + +func (check *Checker) reportInstanceLoop(v int) { + var stack []int + seen := make([]bool, len(check.mono.vertices)) + + // We have a path that contains a cycle and ends at v, but v may + // only be reachable from the cycle, not on the cycle itself. We + // start by walking backwards along the path until we find a vertex + // that appears twice. + for !seen[v] { + stack = append(stack, v) + seen[v] = true + v = check.mono.edges[check.mono.vertices[v].pre].src + } + + // Trim any vertices we visited before visiting v the first + // time. Since v is the first vertex we found within the cycle, any + // vertices we visited earlier cannot be part of the cycle. + for stack[0] != v { + stack = stack[1:] + } + + // TODO(mdempsky): Pivot stack so we report the cycle from the top? + + obj0 := check.mono.vertices[v].obj + check.errorf(obj0, _InvalidInstanceCycle, "instantiation cycle:") + + qf := RelativeTo(check.pkg) + for _, v := range stack { + edge := check.mono.edges[check.mono.vertices[v].pre] + obj := check.mono.vertices[edge.dst].obj + + switch obj.Type().(type) { + default: + panic("unexpected type") + case *Named: + check.errorf(atPos(edge.pos), _InvalidInstanceCycle, "\t%s implicitly parameterized by %s", obj.Name(), TypeString(edge.typ, qf)) // secondary error, \t indented + case *TypeParam: + check.errorf(atPos(edge.pos), _InvalidInstanceCycle, "\t%s instantiated as %s", obj.Name(), TypeString(edge.typ, qf)) // secondary error, \t indented + } + } +} + +// recordCanon records that tpar is the canonical type parameter +// corresponding to method type parameter mpar. +func (w *monoGraph) recordCanon(mpar, tpar *TypeParam) { + if w.canon == nil { + w.canon = make(map[*TypeParam]*TypeParam) + } + w.canon[mpar] = tpar +} + +// recordInstance records that the given type parameters were +// instantiated with the corresponding type arguments. +func (w *monoGraph) recordInstance(pkg *Package, pos token.Pos, tparams []*TypeParam, targs []Type, posList []token.Pos) { + for i, tpar := range tparams { + pos := pos + if i < len(posList) { + pos = posList[i] + } + w.assign(pkg, pos, tpar, targs[i]) + } +} + +// assign records that tpar was instantiated as targ at pos. +func (w *monoGraph) assign(pkg *Package, pos token.Pos, tpar *TypeParam, targ Type) { + // Go generics do not have an analog to C++`s template-templates, + // where a template parameter can itself be an instantiable + // template. So any instantiation cycles must occur within a single + // package. Accordingly, we can ignore instantiations of imported + // type parameters. + // + // TODO(mdempsky): Push this check up into recordInstance? All type + // parameters in a list will appear in the same package. + if tpar.Obj().Pkg() != pkg { + return + } + + // flow adds an edge from vertex src representing that typ flows to tpar. + flow := func(src int, typ Type) { + weight := 1 + if typ == targ { + weight = 0 + } + + w.addEdge(w.typeParamVertex(tpar), src, weight, pos, targ) + } + + // Recursively walk the type argument to find any defined types or + // type parameters. + var do func(typ Type) + do = func(typ Type) { + switch typ := typ.(type) { + default: + panic("unexpected type") + + case *TypeParam: + assert(typ.Obj().Pkg() == pkg) + flow(w.typeParamVertex(typ), typ) + + case *Named: + if src := w.localNamedVertex(pkg, typ.Origin()); src >= 0 { + flow(src, typ) + } + + targs := typ.TypeArgs() + for i := 0; i < targs.Len(); i++ { + do(targs.At(i)) + } + + case *Array: + do(typ.Elem()) + case *Basic: + // ok + case *Chan: + do(typ.Elem()) + case *Map: + do(typ.Key()) + do(typ.Elem()) + case *Pointer: + do(typ.Elem()) + case *Slice: + do(typ.Elem()) + + case *Interface: + for i := 0; i < typ.NumMethods(); i++ { + do(typ.Method(i).Type()) + } + case *Signature: + tuple := func(tup *Tuple) { + for i := 0; i < tup.Len(); i++ { + do(tup.At(i).Type()) + } + } + tuple(typ.Params()) + tuple(typ.Results()) + case *Struct: + for i := 0; i < typ.NumFields(); i++ { + do(typ.Field(i).Type()) + } + } + } + do(targ) +} + +// localNamedVertex returns the index of the vertex representing +// named, or -1 if named doesn't need representation. +func (w *monoGraph) localNamedVertex(pkg *Package, named *Named) int { + obj := named.Obj() + if obj.Pkg() != pkg { + return -1 // imported type + } + + root := pkg.Scope() + if obj.Parent() == root { + return -1 // package scope, no ambient type parameters + } + + if idx, ok := w.nameIdx[obj]; ok { + return idx + } + + idx := -1 + + // Walk the type definition's scope to find any ambient type + // parameters that it's implicitly parameterized by. + for scope := obj.Parent(); scope != root; scope = scope.Parent() { + for _, elem := range scope.elems { + if elem, ok := elem.(*TypeName); ok && !elem.IsAlias() && elem.Pos() < obj.Pos() { + if tpar, ok := elem.Type().(*TypeParam); ok { + if idx < 0 { + idx = len(w.vertices) + w.vertices = append(w.vertices, monoVertex{obj: obj}) + } + + w.addEdge(idx, w.typeParamVertex(tpar), 1, obj.Pos(), tpar) + } + } + } + } + + if w.nameIdx == nil { + w.nameIdx = make(map[*TypeName]int) + } + w.nameIdx[obj] = idx + return idx +} + +// typeParamVertex returns the index of the vertex representing tpar. +func (w *monoGraph) typeParamVertex(tpar *TypeParam) int { + if x, ok := w.canon[tpar]; ok { + tpar = x + } + + obj := tpar.Obj() + + if idx, ok := w.nameIdx[obj]; ok { + return idx + } + + if w.nameIdx == nil { + w.nameIdx = make(map[*TypeName]int) + } + + idx := len(w.vertices) + w.vertices = append(w.vertices, monoVertex{obj: obj}) + w.nameIdx[obj] = idx + return idx +} + +func (w *monoGraph) addEdge(dst, src, weight int, pos token.Pos, typ Type) { + // TODO(mdempsky): Deduplicate redundant edges? + w.edges = append(w.edges, monoEdge{ + dst: dst, + src: src, + weight: weight, + + pos: pos, + typ: typ, + }) +} diff --git a/src/go/types/mono_test.go b/src/go/types/mono_test.go new file mode 100644 index 0000000000..5df3d493f8 --- /dev/null +++ b/src/go/types/mono_test.go @@ -0,0 +1,92 @@ +// Copyright 2021 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_test + +import ( + "bytes" + "errors" + "fmt" + "go/ast" + "go/importer" + "go/parser" + "go/token" + "go/types" + "strings" + "testing" +) + +func checkMono(t *testing.T, body string) error { + fset := token.NewFileSet() + file, err := parser.ParseFile(fset, "x.go", "package x; import `unsafe`; var _ unsafe.Pointer;\n"+body, 0) + if err != nil { + t.Fatal(err) + } + files := []*ast.File{file} + + var buf bytes.Buffer + conf := types.Config{ + Error: func(err error) { fmt.Fprintln(&buf, err) }, + Importer: importer.Default(), + } + conf.Check("x", fset, files, nil) + if buf.Len() == 0 { + return nil + } + return errors.New(strings.TrimRight(buf.String(), "\n")) +} + +func TestMonoGood(t *testing.T) { + for i, good := range goods { + if err := checkMono(t, good); err != nil { + t.Errorf("%d: unexpected failure: %v", i, err) + } + } +} + +func TestMonoBad(t *testing.T) { + for i, bad := range bads { + if err := checkMono(t, bad); err == nil { + t.Errorf("%d: unexpected success", i) + } else { + t.Log(err) + } + } +} + +var goods = []string{ + "func F[T any](x T) { F(x) }", + "func F[T, U, V any]() { F[U, V, T](); F[V, T, U]() }", + "type Ring[A, B, C any] struct { L *Ring[B, C, A]; R *Ring[C, A, B] }", + "func F[T any]() { type U[T any] [unsafe.Sizeof(F[*T])]byte }", + "func F[T any]() { type U[T any] [unsafe.Sizeof(F[*T])]byte; var _ U[int] }", + "type U[T any] [unsafe.Sizeof(F[*T])]byte; func F[T any]() { var _ U[U[int]] }", + "func F[T any]() { type A = int; F[A]() }", +} + +// TODO(mdempsky): Validate specific error messages and positioning. + +var bads = []string{ + "func F[T any](x T) { F(&x) }", + "func F[T any]() { F[*T]() }", + "func F[T any]() { F[[]T]() }", + "func F[T any]() { F[[1]T]() }", + "func F[T any]() { F[chan T]() }", + "func F[T any]() { F[map[*T]int]() }", + "func F[T any]() { F[map[error]T]() }", + "func F[T any]() { F[func(T)]() }", + "func F[T any]() { F[func() T]() }", + "func F[T any]() { F[struct{ t T }]() }", + "func F[T any]() { F[interface{ t() T }]() }", + "type U[_ any] int; func F[T any]() { F[U[T]]() }", + "func F[T any]() { type U int; F[U]() }", + "func F[T any]() { type U int; F[*U]() }", + "type U[T any] int; func (U[T]) m() { var _ U[*T] }", + "type U[T any] int; func (*U[T]) m() { var _ U[*T] }", + "type U[T1 any] [unsafe.Sizeof(F[*T1])]byte; func F[T2 any]() { var _ U[T2] }", + "func F[A, B, C, D, E any]() { F[B, C, D, E, *A]() }", + "type U[_ any] int; const X = unsafe.Sizeof(func() { type A[T any] U[A[*T]] })", + "func F[T any]() { type A = *T; F[A]() }", + "type A[T any] struct { _ A[*T] }", +} diff --git a/src/go/types/object.go b/src/go/types/object.go index 18015fc967..a8bd62a04e 100644 --- a/src/go/types/object.go +++ b/src/go/types/object.go @@ -269,6 +269,8 @@ func (obj *TypeName) IsAlias() bool { return obj.pkg != nil || t.name != obj.name || t == universeByte || t == universeRune case *Named: return obj != t.obj + case *TypeParam: + return obj != t.obj default: return true } diff --git a/src/go/types/object_test.go b/src/go/types/object_test.go index 0ff8fdd6fa..c12af64df7 100644 --- a/src/go/types/object_test.go +++ b/src/go/types/object_test.go @@ -30,6 +30,8 @@ func TestIsAlias(t *testing.T) { pkg := NewPackage("p", "p") t1 := NewTypeName(0, pkg, "t1", nil) n1 := NewNamed(t1, new(Struct), nil) + t5 := NewTypeName(0, pkg, "t5", nil) + NewTypeParam(t5, nil) for _, test := range []struct { name *TypeName alias bool @@ -43,6 +45,7 @@ func TestIsAlias(t *testing.T) { {NewTypeName(0, nil, "int32", Typ[Int32]), false}, // type name refers to basic type with same name {NewTypeName(0, pkg, "int32", Typ[Int32]), true}, // type name is declared in user-defined package (outside Universe) {NewTypeName(0, nil, "rune", Typ[Rune]), true}, // type name refers to basic type rune which is an alias already + {t5, false}, // type name refers to type parameter and vice versa } { check(test.name, test.alias) } diff --git a/src/go/types/operand.go b/src/go/types/operand.go index 855dac66aa..8b76e939b6 100644 --- a/src/go/types/operand.go +++ b/src/go/types/operand.go @@ -234,50 +234,45 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er V := x.typ - const debugAssignableTo = false - if debugAssignableTo && check != nil { - check.dump("V = %s", V) - check.dump("T = %s", T) - } - // x's type is identical to T if Identical(V, T) { return true, 0 } - Vu := optype(V) - Tu := optype(T) - - if debugAssignableTo && check != nil { - check.dump("Vu = %s", Vu) - check.dump("Tu = %s", Tu) - } + Vu := under(V) + Tu := under(T) + Vp, _ := Vu.(*TypeParam) + Tp, _ := Tu.(*TypeParam) // x is an untyped value representable by a value of type T. if isUntyped(Vu) { - if t, _ := under(T).(*TypeParam); t != nil { - return t.is(func(t *term) bool { - // TODO(gri) this could probably be more efficient - if t.tilde { - // TODO(gri) We need to check assignability - // for the underlying type of x. + assert(Vp == nil) + if Tp != nil { + // T is a type parameter: x is assignable to T if it is + // representable by each specific type in the type set of T. + return Tp.is(func(t *term) bool { + if t == nil { + return false } - ok, _ := x.assignableTo(check, t.typ, reason) - return ok + // A term may be a tilde term but the underlying + // type of an untyped value doesn't change so we + // don't need to do anything special. + newType, _, _ := check.implicitTypeAndValue(x, t.typ) + return newType != nil }), _IncompatibleAssign } - newType, _, _ := check.implicitTypeAndValue(x, Tu) + newType, _, _ := check.implicitTypeAndValue(x, T) return newType != nil, _IncompatibleAssign } // Vu is typed // x's type V and T have identical underlying types - // and at least one of V or T is not a named type - if Identical(Vu, Tu) && (!isNamed(V) || !isNamed(T)) { + // and at least one of V or T is not a named type. + if Identical(Vu, Tu) && (!hasName(V) || !hasName(T)) { return true, 0 } - // T is an interface type and x implements T + // T is an interface type and x implements T and T is not a type parameter if Ti, ok := Tu.(*Interface); ok { if m, wrongType := check.missingMethod(V, Ti, true); m != nil /* Implements(V, Ti) */ { if reason != nil { @@ -300,12 +295,68 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er // x is a bidirectional channel value, T is a channel // type, x's type V and T have identical element types, - // and at least one of V or T is not a named type + // and at least one of V or T is not a named type. if Vc, ok := Vu.(*Chan); ok && Vc.dir == SendRecv { if Tc, ok := Tu.(*Chan); ok && Identical(Vc.elem, Tc.elem) { - return !isNamed(V) || !isNamed(T), _InvalidChanAssign + return !hasName(V) || !hasName(T), _InvalidChanAssign } } + // optimization: if we don't have type parameters, we're done + if Vp == nil && Tp == nil { + return false, _IncompatibleAssign + } + + errorf := func(format string, args ...interface{}) { + if check != nil && reason != nil { + msg := check.sprintf(format, args...) + if *reason != "" { + msg += "\n\t" + *reason + } + *reason = msg + } + } + + // x's type V is not a named type and T is a type parameter, and + // x is assignable to each specific type in T's type set. + if !hasName(V) && Tp != nil { + ok := false + code := _IncompatibleAssign + Tp.is(func(T *term) bool { + if T == nil { + return false // no specific types + } + ok, code = x.assignableTo(check, T.typ, reason) + if !ok { + errorf("cannot assign %s to %s (in %s)", x.typ, T.typ, Tp) + return false + } + return true + }) + return ok, code + } + + // x's type V is a type parameter and T is not a named type, + // and values x' of each specific type in V's type set are + // assignable to T. + if Vp != nil && !hasName(T) { + x := *x // don't clobber outer x + ok := false + code := _IncompatibleAssign + Vp.is(func(V *term) bool { + if V == nil { + return false // no specific types + } + x.typ = V.typ + ok, code = x.assignableTo(check, T, reason) + if !ok { + errorf("cannot assign %s (in %s) to %s", V.typ, Vp, T) + return false + } + return true + }) + return ok, code + } + return false, _IncompatibleAssign } diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index b687c151c7..3c76d15c79 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -8,9 +8,10 @@ package types import "go/token" -// isNamed reports whether typ has a name. -// isNamed may be called with types that are not fully set up. -func isNamed(typ Type) bool { +// hasName reports whether typ has a name. This includes +// predeclared types, defined types, and type parameters. +// hasName may be called with types that are not fully set up. +func hasName(typ Type) bool { switch typ.(type) { case *Basic, *Named, *TypeParam: return true @@ -72,7 +73,7 @@ func isOrdered(typ Type) bool { return is(typ, IsOrdered) } func isConstType(typ Type) bool { // Type parameters are never const types. - t, _ := under(typ).(*Basic) + t := asBasic(typ) return t != nil && t.info&IsConstType != 0 } @@ -81,6 +82,12 @@ func IsInterface(typ Type) bool { return asInterface(typ) != nil } +// isTypeParam reports whether typ is a type parameter. +func isTypeParam(typ Type) bool { + _, ok := under(typ).(*TypeParam) + return ok +} + // Comparable reports whether values of type T are comparable. func Comparable(T Type) bool { return comparable(T, nil) @@ -341,10 +348,6 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool { case *TypeParam: // nothing to do (x and y being equal is caught in the very beginning of this function) - case *top: - // Either both types are theTop in which case the initial x == y check - // will have caught them. Otherwise they are not identical. - case nil: // avoid a crash in case of nil type diff --git a/src/go/types/signature.go b/src/go/types/signature.go index c83bf09032..ad69c95d12 100644 --- a/src/go/types/signature.go +++ b/src/go/types/signature.go @@ -148,6 +148,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast list := make([]Type, sig.RecvTypeParams().Len()) for i, t := range sig.RecvTypeParams().list() { list[i] = t + check.mono.recordCanon(t, recvTParams[i]) } smap := makeSubstMap(recvTParams, list) for i, tpar := range sig.RecvTypeParams().list() { diff --git a/src/go/types/sizeof_test.go b/src/go/types/sizeof_test.go index 0e3c0064a0..5b7ee8bb78 100644 --- a/src/go/types/sizeof_test.go +++ b/src/go/types/sizeof_test.go @@ -33,7 +33,6 @@ func TestSizeof(t *testing.T) { {Named{}, 68, 128}, {TypeParam{}, 28, 48}, {term{}, 12, 24}, - {top{}, 0, 0}, // Objects {PkgName{}, 48, 88}, diff --git a/src/go/types/stmt.go b/src/go/types/stmt.go index 7197310bd9..cc4eceae5d 100644 --- a/src/go/types/stmt.go +++ b/src/go/types/stmt.go @@ -834,7 +834,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { if x.mode != invalid { // Ranging over a type parameter is permitted if it has a single underlying type. var cause string - u := singleUnder(x.typ) + u := structure(x.typ) switch t := u.(type) { case nil: cause = "type set has no single underlying type" diff --git a/src/go/types/subst.go b/src/go/types/subst.go index e539ab54e6..f0b79f60c6 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -74,7 +74,7 @@ func (subst *subster) typ(typ Type) Type { // Call typOrNil if it's possible that typ is nil. panic("nil typ") - case *Basic, *top: + case *Basic: // nothing to do case *Array: diff --git a/src/go/types/termlist.go b/src/go/types/termlist.go index 99114cbf4c..c4ab0e037e 100644 --- a/src/go/types/termlist.go +++ b/src/go/types/termlist.go @@ -93,8 +93,8 @@ func (xl termlist) norm() termlist { } // If the type set represented by xl is specified by a single (non-𝓤) term, -// structuralType returns that type. Otherwise it returns nil. -func (xl termlist) structuralType() Type { +// singleType returns that type. Otherwise it returns nil. +func (xl termlist) singleType() Type { if nl := xl.norm(); len(nl) == 1 { return nl[0].typ // if nl.isAll() then typ is nil, which is ok } diff --git a/src/go/types/termlist_test.go b/src/go/types/termlist_test.go index d1fe28f728..dddca7a682 100644 --- a/src/go/types/termlist_test.go +++ b/src/go/types/termlist_test.go @@ -106,7 +106,7 @@ func TestTermlistNorm(t *testing.T) { } } -func TestTermlistStructuralType(t *testing.T) { +func TestTermlistSingleType(t *testing.T) { // helper to deal with nil types tstring := func(typ Type) string { if typ == nil { @@ -128,9 +128,9 @@ func TestTermlistStructuralType(t *testing.T) { "∅ ∪ ~int ∪ string": "nil", } { xl := maketl(test) - got := tstring(xl.structuralType()) + got := tstring(xl.singleType()) if got != want { - t.Errorf("(%v).structuralType() == %v; want %v", test, got, want) + t.Errorf("(%v).singleType() == %v; want %v", test, got, want) } } } diff --git a/src/go/types/testdata/check/issues.go2 b/src/go/types/testdata/check/issues.go2 index 6a93bcc9ac..b7bba5d3b1 100644 --- a/src/go/types/testdata/check/issues.go2 +++ b/src/go/types/testdata/check/issues.go2 @@ -224,6 +224,13 @@ func _[T interface{ ~func() }](f T) { go f() } +type F1 func() +type F2 func() +func _[T interface{ func()|F1|F2 }](f T) { + f() + go f() +} + // We must compare against the underlying type of term list entries // when checking if a constraint is satisfied by a type. The under- // lying type of each term list entry must be computed after the diff --git a/src/go/types/testdata/check/linalg.go2 b/src/go/types/testdata/check/linalg.go2 index efc090a1d1..f02e773dbe 100644 --- a/src/go/types/testdata/check/linalg.go2 +++ b/src/go/types/testdata/check/linalg.go2 @@ -4,8 +4,6 @@ package linalg -import "math" - // Numeric is type bound that matches any numeric type. // It would likely be in a constraints package in the standard library. type Numeric interface { @@ -52,32 +50,33 @@ type Complex interface { ~complex64 | ~complex128 } -// OrderedAbs is a helper type that defines an Abs method for -// ordered numeric types. -type OrderedAbs[T OrderedNumeric] T - -func (a OrderedAbs[T]) Abs() OrderedAbs[T] { - if a < 0 { - return -a - } - return a -} - -// ComplexAbs is a helper type that defines an Abs method for -// complex types. -type ComplexAbs[T Complex] T - -func (a ComplexAbs[T]) Abs() ComplexAbs[T] { - r := float64(real(a)) - i := float64(imag(a)) - d := math.Sqrt(r * r + i * i) - return ComplexAbs[T](complex(d, 0)) -} - -func OrderedAbsDifference[T OrderedNumeric](a, b T) T { - return T(AbsDifference(OrderedAbs[T](a), OrderedAbs[T](b))) -} - -func ComplexAbsDifference[T Complex](a, b T) T { - return T(AbsDifference(ComplexAbs[T](a), ComplexAbs[T](b))) -} +// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). +// // OrderedAbs is a helper type that defines an Abs method for +// // ordered numeric types. +// type OrderedAbs[T OrderedNumeric] T +// +// func (a OrderedAbs[T]) Abs() OrderedAbs[T] { +// if a < 0 { +// return -a +// } +// return a +// } +// +// // ComplexAbs is a helper type that defines an Abs method for +// // complex types. +// type ComplexAbs[T Complex] T +// +// func (a ComplexAbs[T]) Abs() ComplexAbs[T] { +// r := float64(real(a)) +// i := float64(imag(a)) +// d := math.Sqrt(r * r + i * i) +// return ComplexAbs[T](complex(d, 0)) +// } +// +// func OrderedAbsDifference[T OrderedNumeric](a, b T) T { +// return T(AbsDifference(OrderedAbs[T](a), OrderedAbs[T](b))) +// } +// +// func ComplexAbsDifference[T Complex](a, b T) T { +// return T(AbsDifference(ComplexAbs[T](a), ComplexAbs[T](b))) +// } diff --git a/src/go/types/testdata/check/typeinst.go2 b/src/go/types/testdata/check/typeinst.go2 index f4f6c0264b..65481202e4 100644 --- a/src/go/types/testdata/check/typeinst.go2 +++ b/src/go/types/testdata/check/typeinst.go2 @@ -8,7 +8,8 @@ type myInt int // Parameterized type declarations -type T1[P any] P +// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). +type T1[P any] P // ERROR cannot use a type parameter as RHS in type declaration type T2[P any] struct { f P @@ -19,7 +20,7 @@ type List[P any] []P // Alias type declarations cannot have type parameters. // Issue #46477 proposses to change that. -type A1[P any] = /* ERROR cannot be alias */ P +type A1[P any] = /* ERROR cannot be alias */ struct{} // Pending clarification of #46477 we disallow aliases // of generic types. diff --git a/src/go/types/testdata/check/typeinst2.go2 b/src/go/types/testdata/check/typeinst2.go2 index 37d32263d4..f07c42a1da 100644 --- a/src/go/types/testdata/check/typeinst2.go2 +++ b/src/go/types/testdata/check/typeinst2.go2 @@ -87,25 +87,27 @@ type NumericAbs[T any] interface { func AbsDifference[T NumericAbs[T]](x T) { panic(0) } -type OrderedAbs[T any] T - -func (a OrderedAbs[T]) Abs() OrderedAbs[T] - -func OrderedAbsDifference[T any](x T) { - AbsDifference(OrderedAbs[T](x)) -} +// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). +// type OrderedAbs[T any] T +// +// func (a OrderedAbs[T]) Abs() OrderedAbs[T] +// +// func OrderedAbsDifference[T any](x T) { +// AbsDifference(OrderedAbs[T](x)) +// } // same code, reduced to essence func g[P interface{ m() P }](x P) { panic(0) } -type T4[P any] P - -func (_ T4[P]) m() T4[P] - -func _[Q any](x Q) { - g(T4[Q](x)) -} +// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). +// type T4[P any] P +// +// func (_ T4[P]) m() T4[P] +// +// func _[Q any](x Q) { +// g(T4[Q](x)) +// } // Another test case that caused problems in the past @@ -226,10 +228,10 @@ type I012 interface { } func f012[T I012]() {} -var _ = f012[int /* ERROR does not satisfy I012 */ ] -var _ = f012[bool /* ERROR does not satisfy I012 */ ] -var _ = f012[string /* ERROR does not satisfy I012 */ ] -var _ = f012[float64 /* ERROR does not satisfy I012 */ ] +var _ = f012[int /* ERROR does not satisfy I012.*type set is empty */ ] +var _ = f012[bool /* ERROR does not satisfy I012.*type set is empty */ ] +var _ = f012[string /* ERROR does not satisfy I012.*type set is empty */ ] +var _ = f012[float64 /* ERROR does not satisfy I012.*type set is empty */ ] type I12 interface { E1 @@ -256,3 +258,23 @@ var _ = f0_[float64 /* ERROR does not satisfy I0_ */ ] // Using a function instance as a type is an error. var _ f0 // ERROR not a type var _ f0 /* ERROR not a type */ [int] + +// Empty type sets can only be satisfied by empty type sets. +type none interface { + // force an empty type set + int + string +} + +func ff[T none]() {} +func gg[T any]() {} +func hh[T ~int]() {} + +func _[T none]() { + _ = ff[int /* ERROR int does not satisfy none \(constraint type set is empty\) */ ] + _ = ff[T] // pathological but ok because T's type set is empty, too + _ = gg[int] + _ = gg[T] + _ = hh[int] + _ = hh[T] +} diff --git a/src/go/types/testdata/check/typeparams.go2 b/src/go/types/testdata/check/typeparams.go2 index 3694b0ed00..09d478c4d7 100644 --- a/src/go/types/testdata/check/typeparams.go2 +++ b/src/go/types/testdata/check/typeparams.go2 @@ -114,6 +114,14 @@ func _[T interface{ [10]int }](x T, i int) { _ = x[i]; _ = x[9]; _ = x[10 /* ERR func _[T interface{ [10]byte | string }](x T, i int) { _ = x[i]; _ = x[9]; _ = x[10 /* ERROR out of bounds */ ] } func _[T interface{ [10]int | *[20]int | []int }](x T, i int) { _ = x[i]; _ = x[9]; _ = x[10 /* ERROR out of bounds */ ] } +// indexing with strings and non-variable arrays (assignment not permitted) +func _[T string](x T) { _ = x[0]; x /* ERROR cannot assign */ [0] = 0 } +func _[T []byte | string](x T) { x /* ERROR cannot assign */ [0] = 0 } +func _[T [10]byte]() { f := func() (x T) { return }; f /* ERROR cannot assign */ ()[0] = 0 } +func _[T [10]byte]() { f := func() (x *T) { return }; f /* ERROR cannot index */ ()[0] = 0 } +func _[T [10]byte]() { f := func() (x *T) { return }; (*f())[0] = 0 } +func _[T *[10]byte]() { f := func() (x T) { return }; f()[0] = 0 } + // slicing func _[T interface{ ~[10]E }, E any] (x T, i, j, k int) { var _ []E = x[i:j] } @@ -352,15 +360,16 @@ func _() { // the previous example was extracted from -func f12[T interface{m() T}]() {} - -type A[T any] T - -func (a A[T]) m() A[T] - -func _[T any]() { - f12[A[T]]() -} +// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). +// func f12[T interface{m() T}]() {} +// +// type A[T any] T +// +// func (a A[T]) m() A[T] +// +// func _[T any]() { +// f12[A[T]]() +// } // method expressions diff --git a/src/go/types/testdata/examples/inference.go2 b/src/go/types/testdata/examples/inference.go2 index 9a2dcc47f2..73246b0137 100644 --- a/src/go/types/testdata/examples/inference.go2 +++ b/src/go/types/testdata/examples/inference.go2 @@ -99,3 +99,26 @@ func _() { related2(1.0, []int{}) related2 /* ERROR does not satisfy */ (float64(1.0), []int{}) } + +type List[P any] []P + +func related3[Elem any, Slice []Elem | List[Elem]]() Slice { return nil } + +func _() { + // related3 can be instantiated explicitly + related3[int, []int]() + related3[byte, List[byte]]() + + // Alternatively, the 2nd type argument can be inferred + // from the first one through constraint type inference. + related3[int]() + + // The inferred type is the structural type of the Slice + // type parameter. + var _ []int = related3[int]() + + // It is not the defined parameterized type List. + type anotherList []float32 + var _ anotherList = related3[float32]() // valid + var _ anotherList = related3 /* ERROR cannot use .* \(value of type List\[float32\]\) as anotherList */ [float32, List[float32]]() +} diff --git a/src/go/types/testdata/examples/methods.go2 b/src/go/types/testdata/examples/methods.go2 index 4e87041e54..1d76d553dc 100644 --- a/src/go/types/testdata/examples/methods.go2 +++ b/src/go/types/testdata/examples/methods.go2 @@ -6,8 +6,6 @@ package p -import "unsafe" - // Parameterized types may have methods. type T1[A any] struct{ a A } @@ -97,17 +95,18 @@ type T0 struct{} func (T0) _() {} func (T1[A]) _() {} -// A generic receiver type may constrain its type parameter such -// that it must be a pointer type. Such receiver types are not -// permitted. -type T3a[P interface{ ~int | ~string | ~float64 }] P - -func (T3a[_]) m() {} // this is ok - -type T3b[P interface{ ~unsafe.Pointer }] P - -func (T3b /* ERROR invalid receiver */ [_]) m() {} - -type T3c[P interface{ *int | *string }] P - -func (T3c /* ERROR invalid receiver */ [_]) m() {} +// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). +// // A generic receiver type may constrain its type parameter such +// // that it must be a pointer type. Such receiver types are not +// // permitted. +// type T3a[P interface{ ~int | ~string | ~float64 }] P +// +// func (T3a[_]) m() {} // this is ok +// +// type T3b[P interface{ ~unsafe.Pointer }] P +// +// func (T3b /* ERROR invalid receiver */ [_]) m() {} +// +// type T3c[P interface{ *int | *string }] P +// +// func (T3c /* ERROR invalid receiver */ [_]) m() {} diff --git a/src/go/types/testdata/examples/types.go2 b/src/go/types/testdata/examples/types.go2 index 367b73120c..33642fa42f 100644 --- a/src/go/types/testdata/examples/types.go2 +++ b/src/go/types/testdata/examples/types.go2 @@ -191,12 +191,13 @@ type _ struct { // _ = y < 0 //} -// It is not permitted to declare a local type whose underlying -// type is a type parameter not declared by that type declaration. -func _[T any]() { - type _ T // ERROR cannot use function type parameter T as RHS in type declaration - type _ [_ any] T // ERROR cannot use function type parameter T as RHS in type declaration -} +// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). +// // It is not permitted to declare a local type whose underlying +// // type is a type parameter not declared by that type declaration. +// func _[T any]() { +// type _ T // ERROR cannot use function type parameter T as RHS in type declaration +// type _ [_ any] T // ERROR cannot use function type parameter T as RHS in type declaration +// } // As a special case, an explicit type argument may be omitted // from a type parameter bound if the type bound expects exactly diff --git a/src/go/types/testdata/fixedbugs/issue39634.go2 b/src/go/types/testdata/fixedbugs/issue39634.go2 index 5cff6e7555..2de2f4378a 100644 --- a/src/go/types/testdata/fixedbugs/issue39634.go2 +++ b/src/go/types/testdata/fixedbugs/issue39634.go2 @@ -74,9 +74,10 @@ func F20[t Z20]() { F20(t /* ERROR invalid composite literal type */ {}) } type Z21 /* ERROR illegal cycle */ interface{ Z21 } func F21[T Z21]() { ( /* ERROR not used */ F21[Z21]) } -// crash 24 -type T24[P any] P -func (r T24[P]) m() { T24 /* ERROR without instantiation */ .m() } +// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). +// // crash 24 +// type T24[P any] P +// func (r T24[P]) m() { T24 /* ERROR without instantiation */ .m() } // crash 25 type T25[A any] int diff --git a/src/go/types/testdata/fixedbugs/issue39768.go2 b/src/go/types/testdata/fixedbugs/issue39768.go2 index fb522733e0..696d9d9bee 100644 --- a/src/go/types/testdata/fixedbugs/issue39768.go2 +++ b/src/go/types/testdata/fixedbugs/issue39768.go2 @@ -4,14 +4,15 @@ package p -type T[P any] P -type A = T // ERROR cannot use generic type -var x A[int] -var _ A - -type B = T[int] -var y B = x -var _ B /* ERROR not a generic type */ [int] +// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). +// type T[P any] P +// type A = T // ERROR cannot use generic type +// var x A[int] +// var _ A +// +// type B = T[int] +// var y B = x +// var _ B /* ERROR not a generic type */ [int] // test case from issue diff --git a/src/go/types/testdata/fixedbugs/issue39938.go2 b/src/go/types/testdata/fixedbugs/issue39938.go2 index 31bec5fb01..114646786d 100644 --- a/src/go/types/testdata/fixedbugs/issue39938.go2 +++ b/src/go/types/testdata/fixedbugs/issue39938.go2 @@ -8,7 +8,7 @@ package p -type E0[P any] P +type E0[P any] []P type E1[P any] *P type E2[P any] struct{ _ P } type E3[P any] struct{ _ *P } diff --git a/src/go/types/testdata/fixedbugs/issue45639.go2 b/src/go/types/testdata/fixedbugs/issue45639.go2 index 441fb4cb34..80148fe481 100644 --- a/src/go/types/testdata/fixedbugs/issue45639.go2 +++ b/src/go/types/testdata/fixedbugs/issue45639.go2 @@ -4,9 +4,10 @@ package P -// It is not permitted to declare a local type whose underlying -// type is a type parameters not declared by that type declaration. -func _[T any]() { - type _ T // ERROR cannot use function type parameter T as RHS in type declaration - type _ [_ any] T // ERROR cannot use function type parameter T as RHS in type declaration -} +// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). +// // It is not permitted to declare a local type whose underlying +// // type is a type parameters not declared by that type declaration. +// func _[T any]() { +// type _ T // ERROR cannot use function type parameter T as RHS in type declaration +// type _ [_ any] T // ERROR cannot use function type parameter T as RHS in type declaration +// } diff --git a/src/go/types/testdata/fixedbugs/issue45985.go2 b/src/go/types/testdata/fixedbugs/issue45985.go2 index 6e42dbb633..637e2cad5e 100644 --- a/src/go/types/testdata/fixedbugs/issue45985.go2 +++ b/src/go/types/testdata/fixedbugs/issue45985.go2 @@ -5,7 +5,7 @@ package issue45985 // TODO(rFindley): this error should be on app[int] below. -func app[S /* ERROR "type S = S does not match" */ interface{ ~[]T }, T any](s S, e T) S { +func app[S /* ERROR "S does not match" */ interface{ ~[]T }, T any](s S, e T) S { return append(s, e) } diff --git a/src/go/types/testdata/fixedbugs/issue47411.go2 b/src/go/types/testdata/fixedbugs/issue47411.go2 index 2fc26d9e85..fde704bb41 100644 --- a/src/go/types/testdata/fixedbugs/issue47411.go2 +++ b/src/go/types/testdata/fixedbugs/issue47411.go2 @@ -19,7 +19,7 @@ func _[P comparable, _ = f[R /* ERROR R has no constraints */ ] _ = g[int] - _ = g[P /* ERROR P has no type constraints */ ] + _ = g[P /* ERROR P does not satisfy interface{interface{comparable; ~int\|~string} */ ] _ = g[Q] _ = g[func /* ERROR does not satisfy comparable */()] _ = g[R /* ERROR R has no constraints */ ] diff --git a/src/go/types/testdata/fixedbugs/issue47747.go2 b/src/go/types/testdata/fixedbugs/issue47747.go2 index af52056bef..6a2e787bf9 100644 --- a/src/go/types/testdata/fixedbugs/issue47747.go2 +++ b/src/go/types/testdata/fixedbugs/issue47747.go2 @@ -4,15 +4,16 @@ package p -type T1[P any] P - -func (T1[_]) m() {} - -func _[P any](x *T1[P]) { - // x.m exists because x is of type *T1 where T1 is a defined type - // (even though under(T1) is a type parameter) - x.m() -} +// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). +// type T1[P any] P +// +// func (T1[_]) m() {} +// +// func _[P any](x *T1[P]) { +// // x.m exists because x is of type *T1 where T1 is a defined type +// // (even though under(T1) is a type parameter) +// x.m() +// } func _[P interface{ m() }](x P) { @@ -40,29 +41,31 @@ type Barer[t any] interface { Bar(t) } -type Foo1[t any] t -type Bar[t any] t - -func (l Foo1[t]) Foo(v Barer[t]) { v.Bar(t(l)) } -func (b *Bar[t]) Bar(l t) { *b = Bar[t](l) } - -func _[t any](f Fooer1[t]) t { - var b Bar[t] - f.Foo(&b) - return t(b) -} +// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). +// type Foo1[t any] t +// type Bar[t any] t +// +// func (l Foo1[t]) Foo(v Barer[t]) { v.Bar(t(l)) } +// func (b *Bar[t]) Bar(l t) { *b = Bar[t](l) } +// +// func _[t any](f Fooer1[t]) t { +// var b Bar[t] +// f.Foo(&b) +// return t(b) +// } // Test case 2 from issue -type Fooer2[t any] interface { - Foo() -} - -type Foo2[t any] t - -func (f *Foo2[t]) Foo() {} - -func _[t any](v t) { - var f = Foo2[t](v) - _ = Fooer2[t](&f) -} +// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). +// type Fooer2[t any] interface { +// Foo() +// } +// +// type Foo2[t any] t +// +// func (f *Foo2[t]) Foo() {} +// +// func _[t any](v t) { +// var f = Foo2[t](v) +// _ = Fooer2[t](&f) +// } diff --git a/src/go/types/testdata/fixedbugs/issue48018.go2 b/src/go/types/testdata/fixedbugs/issue48018.go2 new file mode 100644 index 0000000000..e6ccc6b9be --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue48018.go2 @@ -0,0 +1,20 @@ +// Copyright 2021 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 + +type Box[A any] struct { + value A +} + +func Nest[A /* ERROR instantiation cycle */ any](b Box[A], n int) interface{} { + if n == 0 { + return b + } + return Nest(Box[Box[A]]{b}, n-1) +} + +func main() { + Nest(Box[int]{0}, 10) +} diff --git a/src/go/types/testdata/fixedbugs/issue48974.go2 b/src/go/types/testdata/fixedbugs/issue48974.go2 index ca4b6d9321..d8ff7c8cf4 100644 --- a/src/go/types/testdata/fixedbugs/issue48974.go2 +++ b/src/go/types/testdata/fixedbugs/issue48974.go2 @@ -8,7 +8,7 @@ type Fooer interface { Foo() } -type Fooable[F Fooer] struct { +type Fooable[F /* ERROR instantiation cycle */ Fooer] struct { ptr F } diff --git a/src/go/types/testdata/fixedbugs/issue49242.go2 b/src/go/types/testdata/fixedbugs/issue49242.go2 new file mode 100644 index 0000000000..524a0cbae3 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue49242.go2 @@ -0,0 +1,27 @@ +// Copyright 2021 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 + +func _[P int](x P) int { + return x // ERROR cannot use x .* as int value in return statement +} + +func _[P int]() int { + return P /* ERROR cannot use P\(1\) .* as int value in return statement */ (1) +} + +func _[P int](x int) P { + return x // ERROR cannot use x .* as P value in return statement +} + +func _[P, Q any](x P) Q { + return x // ERROR cannot use x .* as Q value in return statement +} + +// test case from issue +func F[G interface{ uint }]() int { + f := func(uint) int { return 0 } + return f(G /* ERROR cannot use G\(1\) .* as uint value in argument to f */ (1)) +} diff --git a/src/go/types/testdata/fixedbugs/issue49247.go2 b/src/go/types/testdata/fixedbugs/issue49247.go2 new file mode 100644 index 0000000000..3f25e0ee35 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue49247.go2 @@ -0,0 +1,20 @@ +// Copyright 2021 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 + +type integer interface { + ~int | ~int8 | ~int16 | ~int32 | ~int64 | + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr +} + +func Add1024[T integer](s []T) { + for i, v := range s { + s[i] = v + 1024 // ERROR cannot convert 1024 \(untyped int constant\) to T + } +} + +func f[T interface{ int8 }]() { + println(T(1024 /* ERROR cannot convert 1024 \(untyped int value\) to T */)) +} diff --git a/src/go/types/testdata/fixedbugs/issue49296.go2 b/src/go/types/testdata/fixedbugs/issue49296.go2 new file mode 100644 index 0000000000..8c6d0b678d --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue49296.go2 @@ -0,0 +1,21 @@ +// Copyright 2021 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 + +func _[ + T0 any, + T1 []int, + T2 ~float64 | ~complex128 | chan int, +]() { + // TODO(rfindley): the types2 error here is clearer. + _ = T0(nil /* ERROR cannot convert nil \(untyped nil value\) to T0 */ ) + _ = T1(1 /* ERROR cannot convert 1 .* to T1 */ ) + _ = T2(2 /* ERROR cannot convert 2 .* to T2 */ ) +} + +// test case from issue +func f[T interface{[]int}]() { + _ = T(1 /* ERROR cannot convert */ ) +} diff --git a/src/go/types/testdata/spec/assignability.go2 b/src/go/types/testdata/spec/assignability.go2 new file mode 100644 index 0000000000..a6e71aac81 --- /dev/null +++ b/src/go/types/testdata/spec/assignability.go2 @@ -0,0 +1,266 @@ +// Copyright 2021 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 assignability + +// See the end of this package for the declarations +// of the types and variables used in these tests. + +// "x's type is identical to T" +func _[TP any](X TP) { + b = b + a = a + l = l + s = s + p = p + f = f + i = i + m = m + c = c + d = d + + B = B + A = A + L = L + S = S + P = P + F = F + I = I + M = M + C = C + D = D + X = X +} + +// "x's type V and T have identical underlying types +// and at least one of V or T is not a named type." +// (here a named type is a type with a name) +func _[TP1, TP2 Interface](X1 TP1, X2 TP2) { + b = B // ERROR cannot use B .* as int value + a = A + l = L + s = S + p = P + f = F + i = I + m = M + c = C + d = D + + B = b // ERROR cannot use b .* as Basic value + A = a + L = l + S = s + P = p + F = f + I = i + M = m + C = c + D = d + X1 = i // ERROR cannot use i .* as TP1 value + X1 = X2 // ERROR cannot use X2 .* as TP1 value +} + +// "T is an interface type and x implements T and T is not a type parameter" +func _[TP Interface](X TP) { + i = d // ERROR missing method m + i = D + i = X + X = i // ERROR cannot use i .* as TP value +} + +// "x is a bidirectional channel value, T is a channel type, x's type V and T have identical element types, and at least one of V or T is not a named type" +// (here a named type is a type with a name) +type ( + _SendChan = chan<- int + _RecvChan = <-chan int + + SendChan _SendChan + RecvChan _RecvChan +) + +func _[ + _CC ~_Chan, + _SC ~_SendChan, + _RC ~_RecvChan, + + CC Chan, + SC SendChan, + RC RecvChan, +]() { + var ( + _ _SendChan = c + _ _RecvChan = c + _ _Chan = c + + _ _SendChan = C + _ _RecvChan = C + _ _Chan = C + + _ SendChan = c + _ RecvChan = c + _ Chan = c + + _ SendChan = C // ERROR cannot use C .* as SendChan value + _ RecvChan = C // ERROR cannot use C .* as RecvChan value + _ Chan = C + _ Chan = make /* ERROR cannot use make\(chan Basic\) .* as Chan value */ (chan Basic) + ) + + var ( + _ _CC = C // ERROR cannot use C .* as _CC value + _ _SC = C // ERROR cannot use C .* as _SC value + _ _RC = C // ERROR cannot use C .* as _RC value + + _ CC = _CC /* ERROR cannot use _CC\(nil\) .* as CC value */ (nil) + _ SC = _CC /* ERROR cannot use _CC\(nil\) .* as SC value */ (nil) + _ RC = _CC /* ERROR cannot use _CC\(nil\) .* as RC value */ (nil) + + _ CC = C // ERROR cannot use C .* as CC value + _ SC = C // ERROR cannot use C .* as SC value + _ RC = C // ERROR cannot use C .* as RC value + ) +} + +// "x's type V is not a named type and T is a type parameter, and x is assignable to each specific type in T's type set." +func _[ + TP0 any, + TP1 ~_Chan, + TP2 ~chan int | ~chan byte, +]() { + var ( + _ TP0 = c // ERROR cannot use c .* as TP0 value + _ TP0 = C // ERROR cannot use C .* as TP0 value + _ TP1 = c + _ TP1 = C // ERROR cannot use C .* as TP1 value + _ TP2 = c // ERROR .* cannot assign chan int to chan byte + ) +} + +// "x's type V is a type parameter and T is not a named type, and values x' of each specific type in V's type set are assignable to T." +func _[ + TP0 Interface, + TP1 ~_Chan, + TP2 ~chan int | ~chan byte, +](X0 TP0, X1 TP1, X2 TP2) { + i = X0 + I = X0 + c = X1 + C = X1 // ERROR cannot use X1 .* as Chan value + c = X2 // ERROR .* cannot assign chan byte \(in TP2\) to chan int +} + +// "x is the predeclared identifier nil and T is a pointer, function, slice, map, channel, or interface type" +// TODO(rfindley) error messages about untyped nil diverge from types2 here. +// Consider aligning them. +func _[TP Interface](X TP) { + b = nil // ERROR cannot use.*untyped nil + a = nil // ERROR cannot use.*untyped nil + l = nil + s = nil // ERROR cannot use.*untyped nil + p = nil + f = nil + i = nil + m = nil + c = nil + d = nil // ERROR cannot use.*untyped nil + + B = nil // ERROR cannot use.*untyped nil + A = nil // ERROR cannot use.*untyped nil + L = nil + S = nil // ERROR cannot use.*untyped nil + P = nil + F = nil + I = nil + M = nil + C = nil + D = nil // ERROR cannot use.*untyped nil + X = nil // ERROR cannot use.*untyped nil +} + +// "x is an untyped constant representable by a value of type T" +func _[ + Int8 ~int8, + Int16 ~int16, + Int32 ~int32, + Int64 ~int64, + Int8_16 ~int8 | ~int16, +]( + i8 Int8, + i16 Int16, + i32 Int32, + i64 Int64, + i8_16 Int8_16, +) { + b = 42 + b = 42.0 + // etc. + + i8 = -1 << 7 + i8 = 1<<7 - 1 + i16 = -1 << 15 + i16 = 1<<15 - 1 + i32 = -1 << 31 + i32 = 1<<31 - 1 + i64 = -1 << 63 + i64 = 1<<63 - 1 + + i8_16 = -1 << 7 + i8_16 = 1<<7 - 1 + i8_16 = - /* ERROR cannot use .* as Int8_16 */ 1 << 15 + i8_16 = 1 /* ERROR cannot use .* as Int8_16 */ <<15 - 1 +} + +// proto-types for tests + +type ( + _Basic = int + _Array = [10]int + _Slice = []int + _Struct = struct{ f int } + _Pointer = *int + _Func = func(x int) string + _Interface = interface{ m() int } + _Map = map[string]int + _Chan = chan int + + Basic _Basic + Array _Array + Slice _Slice + Struct _Struct + Pointer _Pointer + Func _Func + Interface _Interface + Map _Map + Chan _Chan + Defined _Struct +) + +func (Defined) m() int + +// proto-variables for tests + +var ( + b _Basic + a _Array + l _Slice + s _Struct + p _Pointer + f _Func + i _Interface + m _Map + c _Chan + d _Struct + + B Basic + A Array + L Slice + S Struct + P Pointer + F Func + I Interface + M Map + C Chan + D Defined +) diff --git a/src/go/types/testdata/examples/conversions.go2 b/src/go/types/testdata/spec/conversions.go2 similarity index 83% rename from src/go/types/testdata/examples/conversions.go2 rename to src/go/types/testdata/spec/conversions.go2 index eb988ffed1..e54403cea9 100644 --- a/src/go/types/testdata/examples/conversions.go2 +++ b/src/go/types/testdata/spec/conversions.go2 @@ -6,6 +6,41 @@ package conversions import "unsafe" +// constant conversions + +func _[T ~byte]() T { return 255 } +func _[T ~byte]() T { return 256 /* ERROR cannot use 256 .* as T value */ } + +func _[T ~byte]() { + const _ = T /* ERROR T\(0\) .* is not constant */ (0) + var _ T = 255 + var _ T = 256 // ERROR cannot use 256 .* as T value +} + +func _[T ~string]() T { return T('a') } +func _[T ~int | ~string]() T { return T('a') } +func _[T ~byte | ~int | ~string]() T { return T(256 /* ERROR cannot convert 256 .* to T */ ) } + +// implicit conversions never convert to string +func _[T ~string]() { + var _ string = 0 // ERROR cannot use .* as string value + var _ T = 0 // ERROR cannot use .* as T value +} + +// failing const conversions of constants to type parameters report a cause +func _[ + T1 any, + T2 interface{ m() }, + T3 ~int | ~float64 | ~bool, + T4 ~int | ~string, +]() { + // TODO(rfindley): align the error formatting here with types2. + _ = T1(0 /* ERROR cannot convert 0 .* to T1.*T1 does not contain specific types */ ) + _ = T2(1 /* ERROR cannot convert 1 .* to T2.*T2 does not contain specific types */ ) + _ = T3(2 /* ERROR cannot convert 2 .* to T3.*cannot convert 2 .* to bool \(in T3\) */ ) + _ = T4(3.14 /* ERROR cannot convert 3.14 .* to T4.*cannot convert 3.14 .* to int \(in T4\) */ ) +} + // "x is assignable to T" // - tested via assignability tests diff --git a/src/go/types/type.go b/src/go/types/type.go index 502c9b2d52..4247f52c31 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -9,26 +9,13 @@ package types type Type interface { // Underlying returns the underlying type of a type // w/o following forwarding chains. Only used by - // client packages (here for backward-compatibility). + // client packages. Underlying() Type // String returns a string representation of a type. String() string } -// top represents the top of the type lattice. -// It is the underlying type of a type parameter that -// can be satisfied by any type (ignoring methods), -// because its type constraint contains no restrictions -// besides methods. -type top struct{} - -// theTop is the singleton top type. -var theTop = &top{} - -func (t *top) Underlying() Type { return t } -func (t *top) String() string { return TypeString(t, nil) } - // under returns the true expanded underlying type. // If it doesn't exist, the result is Typ[Invalid]. // under must only be called when a type is known @@ -40,77 +27,47 @@ func under(t Type) Type { return t } -// optype returns a type's operational type. Except for -// type parameters, the operational type is the same -// as the underlying type (as returned by under). For -// Type parameters, the operational type is the structural -// type, if any; otherwise it's the top type. -// The result is never the incoming type parameter. -func optype(typ Type) Type { - if t := asTypeParam(typ); t != nil { - // TODO(gri) review accuracy of this comment - // If the optype is typ, return the top type as we have - // no information. It also prevents infinite recursion - // via the asTypeParam converter function. This can happen - // for a type parameter list of the form: - // (type T interface { type T }). - // See also issue #39680. - if u := t.structuralType(); u != nil { - assert(u != typ) // "naked" type parameters cannot be embedded - return under(u) // optype should always return an underlying type - } - return theTop - } - return under(typ) -} - -// Converters -// -// A converter must only be called when a type is -// known to be fully set up. A converter returns -// a type's operational type (see comment for optype) -// or nil if the type argument is not of the -// respective type. +// Convenience converters func asBasic(t Type) *Basic { - op, _ := optype(t).(*Basic) + op, _ := under(t).(*Basic) return op } func asArray(t Type) *Array { - op, _ := optype(t).(*Array) + op, _ := under(t).(*Array) return op } func asSlice(t Type) *Slice { - op, _ := optype(t).(*Slice) + op, _ := under(t).(*Slice) return op } func asStruct(t Type) *Struct { - op, _ := optype(t).(*Struct) + op, _ := under(t).(*Struct) return op } func asPointer(t Type) *Pointer { - op, _ := optype(t).(*Pointer) + op, _ := under(t).(*Pointer) return op } func asSignature(t Type) *Signature { - op, _ := optype(t).(*Signature) + op, _ := under(t).(*Signature) return op } -// If the argument to asInterface, asNamed, or asTypeParam is of the respective type -// (possibly after expanding an instance type), these methods return that type. -// Otherwise the result is nil. - func asInterface(t Type) *Interface { - op, _ := optype(t).(*Interface) + op, _ := under(t).(*Interface) return op } +// If the argument to asNamed, or asTypeParam is of the respective type +// (possibly after expanding resolving a *Named type), these methods return that type. +// Otherwise the result is nil. + func asNamed(t Type) *Named { e, _ := t.(*Named) if e != nil { diff --git a/src/go/types/typeparam.go b/src/go/types/typeparam.go index af36266f11..731b746d05 100644 --- a/src/go/types/typeparam.go +++ b/src/go/types/typeparam.go @@ -118,15 +118,26 @@ func (t *TypeParam) iface() *Interface { return ityp } -// structuralType returns the structural type of the type parameter's constraint; or nil. -func (t *TypeParam) structuralType() Type { - return t.iface().typeSet().structuralType() +// singleType returns the single type of the type parameter constraint; or nil. +func (t *TypeParam) singleType() Type { + return t.iface().typeSet().singleType() } +// hasTerms reports whether the type parameter constraint has specific type terms. +func (t *TypeParam) hasTerms() bool { + return t.iface().typeSet().hasTerms() +} + +// is calls f with the specific type terms of t's constraint and reports whether +// all calls to f returned true. If there are no specific terms, is +// returns the result of f(nil). func (t *TypeParam) is(f func(*term) bool) bool { return t.iface().typeSet().is(f) } +// underIs calls f with the underlying types of the specific type terms +// of t's constraint and reports whether all calls to f returned true. +// If there are no specific terms, underIs returns the result of f(nil). func (t *TypeParam) underIs(f func(Type) bool) bool { return t.iface().typeSet().underIs(f) } diff --git a/src/go/types/typeset.go b/src/go/types/typeset.go index a1893d0588..f8e76ed400 100644 --- a/src/go/types/typeset.go +++ b/src/go/types/typeset.go @@ -37,7 +37,7 @@ func (s *_TypeSet) IsComparable() bool { return s.comparable } return s.is(func(t *term) bool { - return Comparable(t.typ) + return t != nil && Comparable(t.typ) }) } @@ -99,27 +99,29 @@ func (s *_TypeSet) String() string { // ---------------------------------------------------------------------------- // Implementation -func (s *_TypeSet) hasTerms() bool { return !s.terms.isAll() } -func (s *_TypeSet) structuralType() Type { return s.terms.structuralType() } -func (s *_TypeSet) includes(t Type) bool { return s.terms.includes(t) } +// hasTerms reports whether the type set has specific type terms. +func (s *_TypeSet) hasTerms() bool { return !s.terms.isEmpty() && !s.terms.isAll() } + +// singleType returns the single type in s if there is exactly one; otherwise the result is nil. +func (s *_TypeSet) singleType() Type { return s.terms.singleType() } + +// includes reports whether t ∈ s. +func (s *_TypeSet) includes(t Type) bool { return s.terms.includes(t) } + +// subsetOf reports whether s1 ⊆ s2. func (s1 *_TypeSet) subsetOf(s2 *_TypeSet) bool { return s1.terms.subsetOf(s2.terms) } // TODO(gri) TypeSet.is and TypeSet.underIs should probably also go into termlist.go -var topTerm = term{false, theTop} - +// is calls f with the specific type terms of s and reports whether +// all calls to f returned true. If there are no specific terms, is +// returns the result of f(nil). func (s *_TypeSet) is(f func(*term) bool) bool { - if len(s.terms) == 0 { - return false + if !s.hasTerms() { + return f(nil) } for _, t := range s.terms { - // Terms represent the top term with a nil type. - // The rest of the type checker uses the top type - // instead. Convert. - // TODO(gri) investigate if we can do without this - if t.typ == nil { - t = &topTerm - } + assert(t.typ != nil) if !f(t) { return false } @@ -127,17 +129,17 @@ func (s *_TypeSet) is(f func(*term) bool) bool { return true } +// underIs calls f with the underlying types of the specific type terms +// of s and reports whether all calls to f returned true. If there are +// no specific terms, is returns the result of f(nil). func (s *_TypeSet) underIs(f func(Type) bool) bool { - if len(s.terms) == 0 { - return false + if !s.hasTerms() { + return f(nil) } for _, t := range s.terms { - // see corresponding comment in TypeSet.is + assert(t.typ != nil) + // x == under(x) for ~x terms u := t.typ - if u == nil { - u = theTop - } - // t == under(t) for ~t terms if !t.tilde { u = under(u) } diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index 9154ebc406..e138af6488 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -274,18 +274,11 @@ func (w *typeWriter) typ(typ Type) { w.error("unnamed type parameter") break } - // Optionally write out package for typeparams (like Named). - if t.obj.pkg != nil { - writePackage(w.buf, t.obj.pkg, w.qf) - } w.string(t.obj.name) if w.debug || w.ctxt != nil { w.string(subscript(t.id)) } - case *top: - w.error("⊤") - default: // For externally defined implementations of Type. // Note: In this case cycles won't be caught. diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index 092e355b38..e1d942a5c6 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -141,7 +141,7 @@ func (check *Checker) typ(e ast.Expr) Type { // constraint interface. func (check *Checker) varType(e ast.Expr) Type { typ := check.definedType(e, nil) - // We don't want to call under() (via asInterface) or complete interfaces while we + // We don't want to call under() (via toInterface) or complete interfaces while we // are in the middle of type-checking parameter declarations that might belong to // interface methods. Delay this check to the end of type-checking. check.later(func() { @@ -457,6 +457,8 @@ func (check *Checker) instantiatedType(x ast.Expr, targsx []ast.Expr, def *Named pos = posList[i] } check.softErrorf(atPos(pos), _Todo, err.Error()) + } else { + check.mono.recordInstance(check.pkg, x.Pos(), inst.tparams.list(), inst.targs.list(), posList) } } diff --git a/src/go/types/unify.go b/src/go/types/unify.go index 99c9c9e614..d3b86008ef 100644 --- a/src/go/types/unify.go +++ b/src/go/types/unify.go @@ -235,13 +235,13 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { // If exact unification is known to fail because we attempt to // match a type name against an unnamed type literal, consider // the underlying type of the named type. - // (Subtle: We use isNamed to include any type with a name (incl. - // basic types and type parameters. We use asNamed() because we only + // (Subtle: We use hasName to include any type with a name (incl. + // basic types and type parameters. We use asNamed because we only // want *Named types.) switch { - case !isNamed(x) && y != nil && asNamed(y) != nil: + case !hasName(x) && y != nil && asNamed(y) != nil: return u.nify(x, under(y), p) - case x != nil && asNamed(x) != nil && !isNamed(y): + case x != nil && asNamed(x) != nil && !hasName(y): return u.nify(under(x), y, p) } } diff --git a/src/internal/buildcfg/exp.go b/src/internal/buildcfg/exp.go index 043d079cf6..a9b29d6718 100644 --- a/src/internal/buildcfg/exp.go +++ b/src/internal/buildcfg/exp.go @@ -56,6 +56,7 @@ func ParseGOEXPERIMENT(goos, goarch, goexp string) (flags, baseline goexperiment RegabiWrappers: regabiSupported, RegabiReflect: regabiSupported, RegabiArgs: regabiSupported, + PacerRedesign: true, } // Start with the statically enabled set of experiments. diff --git a/src/internal/cpu/cpu_test.go b/src/internal/cpu/cpu_test.go index 06ad20800f..8c21256b34 100644 --- a/src/internal/cpu/cpu_test.go +++ b/src/internal/cpu/cpu_test.go @@ -6,6 +6,7 @@ package cpu_test import ( . "internal/cpu" + "internal/godebug" "internal/testenv" "os" "os/exec" @@ -52,7 +53,7 @@ func TestDisableAllCapabilities(t *testing.T) { func TestAllCapabilitiesDisabled(t *testing.T) { MustHaveDebugOptionsSupport(t) - if os.Getenv("GODEBUG") != "cpu.all=off" { + if godebug.Get("cpu.all") != "off" { t.Skipf("skipping test: GODEBUG=cpu.all=off not set") } diff --git a/src/internal/cpu/cpu_x86_test.go b/src/internal/cpu/cpu_x86_test.go index 0fef065f20..c8be210055 100644 --- a/src/internal/cpu/cpu_x86_test.go +++ b/src/internal/cpu/cpu_x86_test.go @@ -8,7 +8,7 @@ package cpu_test import ( . "internal/cpu" - "os" + "internal/godebug" "testing" ) @@ -25,7 +25,7 @@ func TestDisableSSE3(t *testing.T) { func TestSSE3DebugOption(t *testing.T) { MustHaveDebugOptionsSupport(t) - if os.Getenv("GODEBUG") != "cpu.sse3=off" { + if godebug.Get("cpu.sse3") != "off" { t.Skipf("skipping test: GODEBUG=cpu.sse3=off not set") } diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index 5008927f0e..8bd40fe8bf 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -12,6 +12,7 @@ import ( "crypto/sha256" "errors" "fmt" + "internal/godebug" "io" "io/ioutil" "math/bits" @@ -245,7 +246,7 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err // Send it back to a worker for minimization. Disable inputC so // other workers don't continue fuzzing. c.crashMinimizing = &result - fmt.Fprintf(c.opts.Log, "fuzz: minimizing %d-byte crash input...\n", len(result.entry.Data)) + fmt.Fprintf(c.opts.Log, "fuzz: minimizing %d-byte crash file\n", len(result.entry.Data)) c.queueForMinimization(result, nil) } else if !crashWritten { // Found a crasher that's either minimized or not minimizable. @@ -316,6 +317,23 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err // Update the coordinator's coverage mask and save the value. inputSize := len(result.entry.Data) if opts.CacheDir != "" { + // It is possible that the input that was discovered is already + // present in the corpus, but the worker produced a coverage map + // that still expanded our total coverage (this may happen due to + // flakiness in the coverage counters). In order to prevent adding + // duplicate entries to the corpus (and re-writing the file on + // disk), skip it if the on disk file already exists. + // TOOD(roland): this check is limited in that it will only be + // applied if we are using the CacheDir. Another option would be + // to iterate through the corpus and check if it is already present, + // which would catch cases where we are not caching entries. + // A slightly faster approach would be to keep some kind of map of + // entry hashes, which would allow us to avoid iterating through + // all entries. + _, err = os.Stat(result.entry.Path) + if err == nil { + continue + } err := writeToCorpus(&result.entry, opts.CacheDir) if err != nil { stop(err) @@ -979,11 +997,15 @@ func readCorpusData(data []byte, types []reflect.Type) ([]interface{}, error) { // provided. func CheckCorpus(vals []interface{}, types []reflect.Type) error { if len(vals) != len(types) { - return fmt.Errorf("wrong number of values in corpus entry %v: want %v", vals, types) + return fmt.Errorf("wrong number of values in corpus entry: %d, want %d", len(vals), len(types)) + } + valsT := make([]reflect.Type, len(vals)) + for valsI, v := range vals { + valsT[valsI] = reflect.TypeOf(v) } for i := range types { - if reflect.TypeOf(vals[i]) != types[i] { - return fmt.Errorf("mismatched types in corpus entry: %v, want %v", vals, types) + if valsT[i] != types[i] { + return fmt.Errorf("mismatched types in corpus entry: %v, want %v", valsT, types) } } return nil @@ -1046,13 +1068,7 @@ var ( func shouldPrintDebugInfo() bool { debugInfoOnce.Do(func() { - debug := strings.Split(os.Getenv("GODEBUG"), ",") - for _, f := range debug { - if f == "fuzzdebug=1" { - debugInfo = true - break - } - } + debugInfo = godebug.Get("fuzzdebug") == "1" }) return debugInfo } diff --git a/src/internal/fuzz/minimize.go b/src/internal/fuzz/minimize.go index 974df369ee..c6e4559665 100644 --- a/src/internal/fuzz/minimize.go +++ b/src/internal/fuzz/minimize.go @@ -79,6 +79,25 @@ func minimizeBytes(v []byte, try func(interface{}) bool, shouldStop func() bool) j = len(v) } } + + // Then, try to make it more simplified and human-readable by trying to replace each + // byte with a printable character. + printableChars := []byte("012789ABCXYZabcxyz !\"#$%&'()*+,.") + for i, b := range v { + if shouldStop() { + return + } + + for _, pc := range printableChars { + v[i] = pc + if try(v) { + // Successful. Move on to the next byte in v. + break + } + // Unsuccessful. Revert v[i] back to original value. + v[i] = b + } + } } func minimizeInteger(v uint, try func(interface{}) bool, shouldStop func() bool) { diff --git a/src/internal/fuzz/minimize_test.go b/src/internal/fuzz/minimize_test.go index 13385e14d6..dc153d0de4 100644 --- a/src/internal/fuzz/minimize_test.go +++ b/src/internal/fuzz/minimize_test.go @@ -13,6 +13,8 @@ import ( "fmt" "reflect" "testing" + "unicode" + "unicode/utf8" ) func TestMinimizeInput(t *testing.T) { @@ -54,7 +56,7 @@ func TestMinimizeInput(t *testing.T) { return fmt.Errorf("bad %v", e.Values[0]) }, input: []interface{}{[]byte{1, 2, 3, 4, 5}}, - expected: []interface{}{[]byte{2, 3}}, + expected: []interface{}{[]byte("00")}, }, { name: "set_of_bytes", @@ -71,6 +73,18 @@ func TestMinimizeInput(t *testing.T) { input: []interface{}{[]byte{0, 1, 2, 3, 4, 5}}, expected: []interface{}{[]byte{0, 4, 5}}, }, + { + name: "non_ascii_bytes", + fn: func(e CorpusEntry) error { + b := e.Values[0].([]byte) + if len(b) == 3 { + return fmt.Errorf("bad %v", e.Values[0]) + } + return nil + }, + input: []interface{}{[]byte("ท")}, // ท is 3 bytes + expected: []interface{}{[]byte("000")}, + }, { name: "ones_string", fn: func(e CorpusEntry) error { @@ -89,6 +103,31 @@ func TestMinimizeInput(t *testing.T) { input: []interface{}{"001010001000000000000000000"}, expected: []interface{}{"111"}, }, + { + name: "string_length", + fn: func(e CorpusEntry) error { + b := e.Values[0].(string) + if len(b) == 5 { + return fmt.Errorf("bad %v", e.Values[0]) + } + return nil + }, + input: []interface{}{"zzzzz"}, + expected: []interface{}{"00000"}, + }, + { + name: "string_with_letter", + fn: func(e CorpusEntry) error { + b := e.Values[0].(string) + r, _ := utf8.DecodeRune([]byte(b)) + if unicode.IsLetter(r) { + return fmt.Errorf("bad %v", e.Values[0]) + } + return nil + }, + input: []interface{}{"ZZZZZ"}, + expected: []interface{}{"A"}, + }, { name: "int", fn: func(e CorpusEntry) error { diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index 388675f713..02efa7f84a 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -153,7 +153,7 @@ func (w *worker) coordinate(ctx context.Context) error { Warmup: input.warmup, CoverageData: input.coverageData, } - entry, resp, err := w.client.fuzz(ctx, input.entry, args) + entry, resp, isInternalError, err := w.client.fuzz(ctx, input.entry, args) canMinimize := true if err != nil { // Error communicating with worker. @@ -167,14 +167,6 @@ func (w *worker) coordinate(ctx context.Context) error { // Report an error, but don't record a crasher. return fmt.Errorf("communicating with fuzzing process: %v", err) } - if w.waitErr == nil || isInterruptError(w.waitErr) { - // Worker stopped, either by exiting with status 0 or after being - // interrupted with a signal (not sent by coordinator). See comment in - // termC case above. - // - // Since we expect I/O errors around interrupts, ignore this error. - return nil - } if sig, ok := terminationSignal(w.waitErr); ok && !isCrashSignal(sig) { // Worker terminated by a signal that probably wasn't caused by a // specific input to the fuzz function. For example, on Linux, @@ -183,6 +175,11 @@ func (w *worker) coordinate(ctx context.Context) error { // is closed. Don't record a crasher. return fmt.Errorf("fuzzing process terminated by unexpected signal; no crash will be recorded: %v", w.waitErr) } + if isInternalError { + // An internal error occurred which shouldn't be considered + // a crash. + return err + } // Unexpected termination. Set error message and fall through. // We'll restart the worker on the next iteration. // Don't attempt to minimize this since it crashed the worker. @@ -567,6 +564,10 @@ type fuzzResponse struct { // Err is the error string caused by the value in shared memory, which is // non-empty if the value in shared memory caused a crash. Err string + + // InternalErr is the error string caused by an internal error in the + // worker. This shouldn't be considered a crasher. + InternalErr string } // pingArgs contains arguments to workerServer.ping. @@ -663,7 +664,8 @@ func (ws *workerServer) serve(ctx context.Context) error { func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) (resp fuzzResponse) { if args.CoverageData != nil { if ws.coverageMask != nil && len(args.CoverageData) != len(ws.coverageMask) { - panic(fmt.Sprintf("unexpected size for CoverageData: got %d, expected %d", len(args.CoverageData), len(ws.coverageMask))) + resp.InternalErr = fmt.Sprintf("unexpected size for CoverageData: got %d, expected %d", len(args.CoverageData), len(ws.coverageMask)) + return resp } ws.coverageMask = args.CoverageData } @@ -682,12 +684,14 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) (resp fuzzRespo ws.memMu <- mem }() if args.Limit > 0 && mem.header().count >= args.Limit { - panic(fmt.Sprintf("mem.header().count %d already exceeds args.Limit %d", mem.header().count, args.Limit)) + resp.InternalErr = fmt.Sprintf("mem.header().count %d already exceeds args.Limit %d", mem.header().count, args.Limit) + return resp } vals, err := unmarshalCorpusFile(mem.valueCopy()) if err != nil { - panic(err) + resp.InternalErr = err.Error() + return resp } shouldStop := func() bool { @@ -1027,7 +1031,7 @@ func (wc *workerClient) minimize(ctx context.Context, entryIn CorpusEntry, args entryOut.Parent = entryIn.Parent entryOut.Generation = entryIn.Generation if err != nil { - panic(fmt.Sprintf("workerClient.minimize unmarshaling minimized value: %v", err)) + return CorpusEntry{}, minimizeResponse{}, fmt.Errorf("workerClient.minimize unmarshaling minimized value: %v", err) } } else { // Did not minimize, but the original input may still be interesting, @@ -1039,40 +1043,43 @@ func (wc *workerClient) minimize(ctx context.Context, entryIn CorpusEntry, args } // fuzz tells the worker to call the fuzz method. See workerServer.fuzz. -func (wc *workerClient) fuzz(ctx context.Context, entryIn CorpusEntry, args fuzzArgs) (entryOut CorpusEntry, resp fuzzResponse, err error) { +func (wc *workerClient) fuzz(ctx context.Context, entryIn CorpusEntry, args fuzzArgs) (entryOut CorpusEntry, resp fuzzResponse, isInternalError bool, err error) { wc.mu.Lock() defer wc.mu.Unlock() mem, ok := <-wc.memMu if !ok { - return CorpusEntry{}, fuzzResponse{}, errSharedMemClosed + return CorpusEntry{}, fuzzResponse{}, true, errSharedMemClosed } mem.header().count = 0 inp, err := CorpusEntryData(entryIn) if err != nil { - return CorpusEntry{}, fuzzResponse{}, err + return CorpusEntry{}, fuzzResponse{}, true, err } mem.setValue(inp) wc.memMu <- mem c := call{Fuzz: &args} callErr := wc.callLocked(ctx, c, &resp) + if resp.InternalErr != "" { + return CorpusEntry{}, fuzzResponse{}, true, errors.New(resp.InternalErr) + } mem, ok = <-wc.memMu if !ok { - return CorpusEntry{}, fuzzResponse{}, errSharedMemClosed + return CorpusEntry{}, fuzzResponse{}, true, errSharedMemClosed } defer func() { wc.memMu <- mem }() resp.Count = mem.header().count if !bytes.Equal(inp, mem.valueRef()) { - panic("workerServer.fuzz modified input") + return CorpusEntry{}, fuzzResponse{}, true, errors.New("workerServer.fuzz modified input") } needEntryOut := callErr != nil || resp.Err != "" || (!args.Warmup && resp.CoverageData != nil) if needEntryOut { valuesOut, err := unmarshalCorpusFile(inp) if err != nil { - panic(fmt.Sprintf("unmarshaling fuzz input value after call: %v", err)) + return CorpusEntry{}, fuzzResponse{}, true, fmt.Errorf("unmarshaling fuzz input value after call: %v", err) } wc.m.r.restore(mem.header().randState, mem.header().randInc) if !args.Warmup { @@ -1098,7 +1105,7 @@ func (wc *workerClient) fuzz(ctx context.Context, entryIn CorpusEntry, args fuzz } } - return entryOut, resp, callErr + return entryOut, resp, false, callErr } // ping tells the worker to call the ping method. See workerServer.ping. diff --git a/src/internal/fuzz/worker_test.go b/src/internal/fuzz/worker_test.go index e32770b02b..c6f83fd08d 100644 --- a/src/internal/fuzz/worker_test.go +++ b/src/internal/fuzz/worker_test.go @@ -96,7 +96,7 @@ func BenchmarkWorkerFuzz(b *testing.B) { Limit: int64(b.N) - i, Timeout: workerFuzzDuration, } - _, resp, err := w.client.fuzz(context.Background(), entry, args) + _, resp, _, err := w.client.fuzz(context.Background(), entry, args) if err != nil { b.Fatal(err) } diff --git a/src/internal/godebug/godebug.go b/src/internal/godebug/godebug.go new file mode 100644 index 0000000000..ac434e5fd8 --- /dev/null +++ b/src/internal/godebug/godebug.go @@ -0,0 +1,34 @@ +// Copyright 2021 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 godebug parses the GODEBUG environment variable. +package godebug + +import "os" + +// Get returns the value for the provided GODEBUG key. +func Get(key string) string { + return get(os.Getenv("GODEBUG"), key) +} + +// get returns the value part of key=value in s (a GODEBUG value). +func get(s, key string) string { + for i := 0; i < len(s)-len(key)-1; i++ { + if i > 0 && s[i-1] != ',' { + continue + } + afterKey := s[i+len(key):] + if afterKey[0] != '=' || s[i:i+len(key)] != key { + continue + } + val := afterKey[1:] + for i, b := range val { + if b == ',' { + return val[:i] + } + } + return val + } + return "" +} diff --git a/src/internal/godebug/godebug_test.go b/src/internal/godebug/godebug_test.go new file mode 100644 index 0000000000..41b9117b73 --- /dev/null +++ b/src/internal/godebug/godebug_test.go @@ -0,0 +1,34 @@ +// Copyright 2021 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 godebug + +import "testing" + +func TestGet(t *testing.T) { + tests := []struct { + godebug string + key string + want string + }{ + {"", "", ""}, + {"", "foo", ""}, + {"foo=bar", "foo", "bar"}, + {"foo=bar,after=x", "foo", "bar"}, + {"before=x,foo=bar,after=x", "foo", "bar"}, + {"before=x,foo=bar", "foo", "bar"}, + {",,,foo=bar,,,", "foo", "bar"}, + {"foodecoy=wrong,foo=bar", "foo", "bar"}, + {"foo=", "foo", ""}, + {"foo", "foo", ""}, + {",foo", "foo", ""}, + {"foo=bar,baz", "loooooooong", ""}, + } + for _, tt := range tests { + got := get(tt.godebug, tt.key) + if got != tt.want { + t.Errorf("get(%q, %q) = %q; want %q", tt.godebug, tt.key, got, tt.want) + } + } +} diff --git a/src/internal/goexperiment/exp_pacerredesign_off.go b/src/internal/goexperiment/exp_pacerredesign_off.go new file mode 100644 index 0000000000..62e1831437 --- /dev/null +++ b/src/internal/goexperiment/exp_pacerredesign_off.go @@ -0,0 +1,9 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build !goexperiment.pacerredesign +// +build !goexperiment.pacerredesign + +package goexperiment + +const PacerRedesign = false +const PacerRedesignInt = 0 diff --git a/src/internal/goexperiment/exp_pacerredesign_on.go b/src/internal/goexperiment/exp_pacerredesign_on.go new file mode 100644 index 0000000000..b22b031009 --- /dev/null +++ b/src/internal/goexperiment/exp_pacerredesign_on.go @@ -0,0 +1,9 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build goexperiment.pacerredesign +// +build goexperiment.pacerredesign + +package goexperiment + +const PacerRedesign = true +const PacerRedesignInt = 1 diff --git a/src/internal/goexperiment/flags.go b/src/internal/goexperiment/flags.go index 0a61a0e5fc..3bf19222e1 100644 --- a/src/internal/goexperiment/flags.go +++ b/src/internal/goexperiment/flags.go @@ -83,4 +83,10 @@ type Flags struct { // Requires wrappers (to do ABI translation), and reflect (so // reflection calls use registers). RegabiArgs bool + + // PacerRedesign enables the new GC pacer in the runtime. + // + // Details regarding the new pacer may be found at + // https://golang.org/design/44167-gc-pacer-redesign + PacerRedesign bool } diff --git a/src/internal/intern/intern.go b/src/internal/intern/intern.go new file mode 100644 index 0000000000..666caa6d2f --- /dev/null +++ b/src/internal/intern/intern.go @@ -0,0 +1,178 @@ +// 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 intern lets you make smaller comparable values by boxing +// a larger comparable value (such as a 16 byte string header) down +// into a globally unique 8 byte pointer. +// +// The globally unique pointers are garbage collected with weak +// references and finalizers. This package hides that. +package intern + +import ( + "internal/godebug" + "runtime" + "sync" + "unsafe" +) + +// A Value pointer is the handle to an underlying comparable value. +// See func Get for how Value pointers may be used. +type Value struct { + _ [0]func() // prevent people from accidentally using value type as comparable + cmpVal interface{} + // resurrected is guarded by mu (for all instances of Value). + // It is set true whenever v is synthesized from a uintptr. + resurrected bool +} + +// Get returns the comparable value passed to the Get func +// that returned v. +func (v *Value) Get() interface{} { return v.cmpVal } + +// key is a key in our global value map. +// It contains type-specialized fields to avoid allocations +// when converting common types to empty interfaces. +type key struct { + s string + cmpVal interface{} + // isString reports whether key contains a string. + // Without it, the zero value of key is ambiguous. + isString bool +} + +// keyFor returns a key to use with cmpVal. +func keyFor(cmpVal interface{}) key { + if s, ok := cmpVal.(string); ok { + return key{s: s, isString: true} + } + return key{cmpVal: cmpVal} +} + +// Value returns a *Value built from k. +func (k key) Value() *Value { + if k.isString { + return &Value{cmpVal: k.s} + } + return &Value{cmpVal: k.cmpVal} +} + +var ( + // mu guards valMap, a weakref map of *Value by underlying value. + // It also guards the resurrected field of all *Values. + mu sync.Mutex + valMap = map[key]uintptr{} // to uintptr(*Value) + valSafe = safeMap() // non-nil in safe+leaky mode +) + +// safeMap returns a non-nil map if we're in safe-but-leaky mode, +// as controlled by GODEBUG=intern=leaky +func safeMap() map[key]*Value { + if godebug.Get("intern") == "leaky" { + return map[key]*Value{} + } + return nil +} + +// Get returns a pointer representing the comparable value cmpVal. +// +// The returned pointer will be the same for Get(v) and Get(v2) +// if and only if v == v2, and can be used as a map key. +func Get(cmpVal interface{}) *Value { + return get(keyFor(cmpVal)) +} + +// GetByString is identical to Get, except that it is specialized for strings. +// This avoids an allocation from putting a string into an interface{} +// to pass as an argument to Get. +func GetByString(s string) *Value { + return get(key{s: s, isString: true}) +} + +// We play unsafe games that violate Go's rules (and assume a non-moving +// collector). So we quiet Go here. +// See the comment below Get for more implementation details. +//go:nocheckptr +func get(k key) *Value { + mu.Lock() + defer mu.Unlock() + + var v *Value + if valSafe != nil { + v = valSafe[k] + } else if addr, ok := valMap[k]; ok { + v = (*Value)(unsafe.Pointer(addr)) + v.resurrected = true + } + if v != nil { + return v + } + v = k.Value() + if valSafe != nil { + valSafe[k] = v + } else { + // SetFinalizer before uintptr conversion (theoretical concern; + // see https://github.com/go4org/intern/issues/13) + runtime.SetFinalizer(v, finalize) + valMap[k] = uintptr(unsafe.Pointer(v)) + } + return v +} + +func finalize(v *Value) { + mu.Lock() + defer mu.Unlock() + if v.resurrected { + // We lost the race. Somebody resurrected it while we + // were about to finalize it. Try again next round. + v.resurrected = false + runtime.SetFinalizer(v, finalize) + return + } + delete(valMap, keyFor(v.cmpVal)) +} + +// Interning is simple if you don't require that unused values be +// garbage collectable. But we do require that; we don't want to be +// DOS vector. We do this by using a uintptr to hide the pointer from +// the garbage collector, and using a finalizer to eliminate the +// pointer when no other code is using it. +// +// The obvious implementation of this is to use a +// map[interface{}]uintptr-of-*interface{}, and set up a finalizer to +// delete from the map. Unfortunately, this is racy. Because pointers +// are being created in violation of Go's unsafety rules, it's +// possible to create a pointer to a value concurrently with the GC +// concluding that the value can be collected. There are other races +// that break the equality invariant as well, but the use-after-free +// will cause a runtime crash. +// +// To make this work, the finalizer needs to know that no references +// have been unsafely created since the finalizer was set up. To do +// this, values carry a "resurrected" sentinel, which gets set +// whenever a pointer is unsafely created. If the finalizer encounters +// the sentinel, it clears the sentinel and delays collection for one +// additional GC cycle, by re-installing itself as finalizer. This +// ensures that the unsafely created pointer is visible to the GC, and +// will correctly prevent collection. +// +// This technique does mean that interned values that get reused take +// at least 3 GC cycles to fully collect (1 to clear the sentinel, 1 +// to clean up the unsafe map, 1 to be actually deleted). +// +// @ianlancetaylor commented in +// https://github.com/golang/go/issues/41303#issuecomment-717401656 +// that it is possible to implement weak references in terms of +// finalizers without unsafe. Unfortunately, the approach he outlined +// does not work here, for two reasons. First, there is no way to +// construct a strong pointer out of a weak pointer; our map stores +// weak pointers, but we must return strong pointers to callers. +// Second, and more fundamentally, we must return not just _a_ strong +// pointer to callers, but _the same_ strong pointer to callers. In +// order to return _the same_ strong pointer to callers, we must track +// it, which is exactly what we cannot do with strong pointers. +// +// See https://github.com/inetaf/netaddr/issues/53 for more +// discussion, and https://github.com/go4org/intern/issues/2 for an +// illustration of the subtleties at play. diff --git a/src/internal/intern/intern_test.go b/src/internal/intern/intern_test.go new file mode 100644 index 0000000000..d1e409ef95 --- /dev/null +++ b/src/internal/intern/intern_test.go @@ -0,0 +1,199 @@ +// 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 intern + +import ( + "fmt" + "runtime" + "testing" +) + +func TestBasics(t *testing.T) { + clearMap() + foo := Get("foo") + bar := Get("bar") + empty := Get("") + nilEface := Get(nil) + i := Get(0x7777777) + foo2 := Get("foo") + bar2 := Get("bar") + empty2 := Get("") + nilEface2 := Get(nil) + i2 := Get(0x7777777) + foo3 := GetByString("foo") + empty3 := GetByString("") + + if foo.Get() != foo2.Get() { + t.Error("foo/foo2 values differ") + } + if foo.Get() != foo3.Get() { + t.Error("foo/foo3 values differ") + } + if foo.Get() != "foo" { + t.Error("foo.Get not foo") + } + if foo != foo2 { + t.Error("foo/foo2 pointers differ") + } + if foo != foo3 { + t.Error("foo/foo3 pointers differ") + } + + if bar.Get() != bar2.Get() { + t.Error("bar values differ") + } + if bar.Get() != "bar" { + t.Error("bar.Get not bar") + } + if bar != bar2 { + t.Error("bar pointers differ") + } + + if i.Get() != i.Get() { + t.Error("i values differ") + } + if i.Get() != 0x7777777 { + t.Error("i.Get not 0x7777777") + } + if i != i2 { + t.Error("i pointers differ") + } + + if empty.Get() != empty2.Get() { + t.Error("empty/empty2 values differ") + } + if empty.Get() != empty.Get() { + t.Error("empty/empty3 values differ") + } + if empty.Get() != "" { + t.Error("empty.Get not empty string") + } + if empty != empty2 { + t.Error("empty/empty2 pointers differ") + } + if empty != empty3 { + t.Error("empty/empty3 pointers differ") + } + + if nilEface.Get() != nilEface2.Get() { + t.Error("nilEface values differ") + } + if nilEface.Get() != nil { + t.Error("nilEface.Get not nil") + } + if nilEface != nilEface2 { + t.Error("nilEface pointers differ") + } + + if n := mapLen(); n != 5 { + t.Errorf("map len = %d; want 4", n) + } + + wantEmpty(t) +} + +func wantEmpty(t testing.TB) { + t.Helper() + const gcTries = 5000 + for try := 0; try < gcTries; try++ { + runtime.GC() + n := mapLen() + if n == 0 { + break + } + if try == gcTries-1 { + t.Errorf("map len = %d after (%d GC tries); want 0, contents: %v", n, gcTries, mapKeys()) + } + } +} + +func TestStress(t *testing.T) { + iters := 10000 + if testing.Short() { + iters = 1000 + } + var sink []byte + for i := 0; i < iters; i++ { + _ = Get("foo") + sink = make([]byte, 1<<20) + } + _ = sink +} + +func BenchmarkStress(b *testing.B) { + done := make(chan struct{}) + defer close(done) + go func() { + for { + select { + case <-done: + return + default: + } + runtime.GC() + } + }() + + clearMap() + v1 := Get("foo") + b.ReportAllocs() + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + v2 := Get("foo") + if v1 != v2 { + b.Fatal("wrong value") + } + // And also a key we don't retain: + _ = Get("bar") + } + }) + runtime.GC() + wantEmpty(b) +} + +func mapLen() int { + mu.Lock() + defer mu.Unlock() + return len(valMap) +} + +func mapKeys() (keys []string) { + mu.Lock() + defer mu.Unlock() + for k := range valMap { + keys = append(keys, fmt.Sprint(k)) + } + return keys +} + +func clearMap() { + mu.Lock() + defer mu.Unlock() + for k := range valMap { + delete(valMap, k) + } +} + +var ( + globalString = "not a constant" + sink string +) + +func TestGetByStringAllocs(t *testing.T) { + allocs := int(testing.AllocsPerRun(100, func() { + GetByString(globalString) + })) + if allocs != 0 { + t.Errorf("GetString allocated %d objects, want 0", allocs) + } +} + +func BenchmarkGetByString(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + v := GetByString(globalString) + sink = v.Get().(string) + } +} diff --git a/src/internal/poll/fd_unix.go b/src/internal/poll/fd_unix.go index d4c32e4d41..85971a16cd 100644 --- a/src/internal/poll/fd_unix.go +++ b/src/internal/poll/fd_unix.go @@ -7,6 +7,7 @@ package poll import ( + "internal/syscall/unix" "io" "sync/atomic" "syscall" @@ -239,7 +240,7 @@ func (fd *FD) ReadFromInet4(p []byte, from *syscall.SockaddrInet4) (int, error) return 0, err } for { - n, err := syscall.RecvfromInet4(fd.Sysfd, p, 0, from) + n, err := unix.RecvfromInet4(fd.Sysfd, p, 0, from) if err != nil { if err == syscall.EINTR { continue @@ -266,7 +267,7 @@ func (fd *FD) ReadFromInet6(p []byte, from *syscall.SockaddrInet6) (int, error) return 0, err } for { - n, err := syscall.RecvfromInet6(fd.Sysfd, p, 0, from) + n, err := unix.RecvfromInet6(fd.Sysfd, p, 0, from) if err != nil { if err == syscall.EINTR { continue @@ -310,6 +311,60 @@ func (fd *FD) ReadMsg(p []byte, oob []byte, flags int) (int, int, int, syscall.S } } +// ReadMsgInet4 is ReadMsg, but specialized for syscall.SockaddrInet4. +func (fd *FD) ReadMsgInet4(p []byte, oob []byte, flags int, sa4 *syscall.SockaddrInet4) (int, int, int, error) { + if err := fd.readLock(); err != nil { + return 0, 0, 0, err + } + defer fd.readUnlock() + if err := fd.pd.prepareRead(fd.isFile); err != nil { + return 0, 0, 0, err + } + for { + n, oobn, sysflags, err := unix.RecvmsgInet4(fd.Sysfd, p, oob, flags, sa4) + if err != nil { + if err == syscall.EINTR { + continue + } + // TODO(dfc) should n and oobn be set to 0 + if err == syscall.EAGAIN && fd.pd.pollable() { + if err = fd.pd.waitRead(fd.isFile); err == nil { + continue + } + } + } + err = fd.eofError(n, err) + return n, oobn, sysflags, err + } +} + +// ReadMsgInet6 is ReadMsg, but specialized for syscall.SockaddrInet6. +func (fd *FD) ReadMsgInet6(p []byte, oob []byte, flags int, sa6 *syscall.SockaddrInet6) (int, int, int, error) { + if err := fd.readLock(); err != nil { + return 0, 0, 0, err + } + defer fd.readUnlock() + if err := fd.pd.prepareRead(fd.isFile); err != nil { + return 0, 0, 0, err + } + for { + n, oobn, sysflags, err := unix.RecvmsgInet6(fd.Sysfd, p, oob, flags, sa6) + if err != nil { + if err == syscall.EINTR { + continue + } + // TODO(dfc) should n and oobn be set to 0 + if err == syscall.EAGAIN && fd.pd.pollable() { + if err = fd.pd.waitRead(fd.isFile); err == nil { + continue + } + } + } + err = fd.eofError(n, err) + return n, oobn, sysflags, err + } +} + // Write implements io.Writer. func (fd *FD) Write(p []byte) (int, error) { if err := fd.writeLock(); err != nil { @@ -381,7 +436,7 @@ func (fd *FD) Pwrite(p []byte, off int64) (int, error) { } // WriteToInet4 wraps the sendto network call for IPv4 addresses. -func (fd *FD) WriteToInet4(p []byte, sa syscall.SockaddrInet4) (int, error) { +func (fd *FD) WriteToInet4(p []byte, sa *syscall.SockaddrInet4) (int, error) { if err := fd.writeLock(); err != nil { return 0, err } @@ -390,7 +445,7 @@ func (fd *FD) WriteToInet4(p []byte, sa syscall.SockaddrInet4) (int, error) { return 0, err } for { - err := syscall.SendtoInet4(fd.Sysfd, p, 0, sa) + err := unix.SendtoInet4(fd.Sysfd, p, 0, sa) if err == syscall.EINTR { continue } @@ -407,7 +462,7 @@ func (fd *FD) WriteToInet4(p []byte, sa syscall.SockaddrInet4) (int, error) { } // WriteToInet6 wraps the sendto network call for IPv6 addresses. -func (fd *FD) WriteToInet6(p []byte, sa syscall.SockaddrInet6) (int, error) { +func (fd *FD) WriteToInet6(p []byte, sa *syscall.SockaddrInet6) (int, error) { if err := fd.writeLock(); err != nil { return 0, err } @@ -416,7 +471,7 @@ func (fd *FD) WriteToInet6(p []byte, sa syscall.SockaddrInet6) (int, error) { return 0, err } for { - err := syscall.SendtoInet6(fd.Sysfd, p, 0, sa) + err := unix.SendtoInet6(fd.Sysfd, p, 0, sa) if err == syscall.EINTR { continue } @@ -484,6 +539,58 @@ func (fd *FD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (int, int, err } } +// WriteMsgInet4 is WriteMsg specialized for syscall.SockaddrInet4. +func (fd *FD) WriteMsgInet4(p []byte, oob []byte, sa *syscall.SockaddrInet4) (int, int, error) { + if err := fd.writeLock(); err != nil { + return 0, 0, err + } + defer fd.writeUnlock() + if err := fd.pd.prepareWrite(fd.isFile); err != nil { + return 0, 0, err + } + for { + n, err := unix.SendmsgNInet4(fd.Sysfd, p, oob, sa, 0) + if err == syscall.EINTR { + continue + } + if err == syscall.EAGAIN && fd.pd.pollable() { + if err = fd.pd.waitWrite(fd.isFile); err == nil { + continue + } + } + if err != nil { + return n, 0, err + } + return n, len(oob), err + } +} + +// WriteMsgInet6 is WriteMsg specialized for syscall.SockaddrInet6. +func (fd *FD) WriteMsgInet6(p []byte, oob []byte, sa *syscall.SockaddrInet6) (int, int, error) { + if err := fd.writeLock(); err != nil { + return 0, 0, err + } + defer fd.writeUnlock() + if err := fd.pd.prepareWrite(fd.isFile); err != nil { + return 0, 0, err + } + for { + n, err := unix.SendmsgNInet6(fd.Sysfd, p, oob, sa, 0) + if err == syscall.EINTR { + continue + } + if err == syscall.EAGAIN && fd.pd.pollable() { + if err = fd.pd.waitWrite(fd.isFile); err == nil { + continue + } + } + if err != nil { + return n, 0, err + } + return n, len(oob), err + } +} + // Accept wraps the accept network call. func (fd *FD) Accept() (int, syscall.Sockaddr, string, error) { if err := fd.readLock(); err != nil { diff --git a/src/internal/poll/fd_windows.go b/src/internal/poll/fd_windows.go index 48fcdf306c..1ca281b2a4 100644 --- a/src/internal/poll/fd_windows.go +++ b/src/internal/poll/fd_windows.go @@ -79,8 +79,6 @@ type operation struct { buf syscall.WSABuf msg windows.WSAMsg sa syscall.Sockaddr - sa4 syscall.SockaddrInet4 - sa6 syscall.SockaddrInet6 rsa *syscall.RawSockaddrAny rsan int32 handle syscall.Handle @@ -595,7 +593,7 @@ func (fd *FD) ReadFrom(buf []byte) (int, syscall.Sockaddr, error) { return n, sa, nil } -// ReadFrom wraps the recvfrom network call for IPv4. +// ReadFromInet4 wraps the recvfrom network call for IPv4. func (fd *FD) ReadFromInet4(buf []byte, sa4 *syscall.SockaddrInet4) (int, error) { if len(buf) == 0 { return 0, nil @@ -620,14 +618,11 @@ func (fd *FD) ReadFromInet4(buf []byte, sa4 *syscall.SockaddrInet4) (int, error) if err != nil { return n, err } - sa, _ := o.rsa.Sockaddr() - if sa != nil { - *sa4 = *(sa.(*syscall.SockaddrInet4)) - } + rawToSockaddrInet4(o.rsa, sa4) return n, err } -// ReadFrom wraps the recvfrom network call for IPv6. +// ReadFromInet6 wraps the recvfrom network call for IPv6. func (fd *FD) ReadFromInet6(buf []byte, sa6 *syscall.SockaddrInet6) (int, error) { if len(buf) == 0 { return 0, nil @@ -652,10 +647,7 @@ func (fd *FD) ReadFromInet6(buf []byte, sa6 *syscall.SockaddrInet6) (int, error) if err != nil { return n, err } - sa, _ := o.rsa.Sockaddr() - if sa != nil { - *sa6 = *(sa.(*syscall.SockaddrInet6)) - } + rawToSockaddrInet6(o.rsa, sa6) return n, err } @@ -857,8 +849,8 @@ func (fd *FD) WriteTo(buf []byte, sa syscall.Sockaddr) (int, error) { return ntotal, nil } -// WriteTo wraps the sendto network call for IPv4. -func (fd *FD) WriteToInet4(buf []byte, sa4 syscall.SockaddrInet4) (int, error) { +// WriteToInet4 is WriteTo, specialized for syscall.SockaddrInet4. +func (fd *FD) WriteToInet4(buf []byte, sa4 *syscall.SockaddrInet4) (int, error) { if err := fd.writeLock(); err != nil { return 0, err } @@ -868,9 +860,8 @@ func (fd *FD) WriteToInet4(buf []byte, sa4 syscall.SockaddrInet4) (int, error) { // handle zero-byte payload o := &fd.wop o.InitBuf(buf) - o.sa4 = sa4 n, err := execIO(o, func(o *operation) error { - return syscall.WSASendtoInet4(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, o.sa4, &o.o, nil) + return windows.WSASendtoInet4(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, sa4, &o.o, nil) }) return n, err } @@ -883,9 +874,8 @@ func (fd *FD) WriteToInet4(buf []byte, sa4 syscall.SockaddrInet4) (int, error) { } o := &fd.wop o.InitBuf(b) - o.sa4 = sa4 n, err := execIO(o, func(o *operation) error { - return syscall.WSASendtoInet4(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, o.sa4, &o.o, nil) + return windows.WSASendtoInet4(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, sa4, &o.o, nil) }) ntotal += int(n) if err != nil { @@ -896,9 +886,41 @@ func (fd *FD) WriteToInet4(buf []byte, sa4 syscall.SockaddrInet4) (int, error) { return ntotal, nil } -// WriteTo wraps the sendto network call for IPv6. -func (fd *FD) WriteToInet6(buf []byte, sa syscall.SockaddrInet6) (int, error) { - return fd.WriteTo(buf, &sa) +// WriteToInet6 is WriteTo, specialized for syscall.SockaddrInet6. +func (fd *FD) WriteToInet6(buf []byte, sa6 *syscall.SockaddrInet6) (int, error) { + if err := fd.writeLock(); err != nil { + return 0, err + } + defer fd.writeUnlock() + + if len(buf) == 0 { + // handle zero-byte payload + o := &fd.wop + o.InitBuf(buf) + n, err := execIO(o, func(o *operation) error { + return windows.WSASendtoInet6(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, sa6, &o.o, nil) + }) + return n, err + } + + ntotal := 0 + for len(buf) > 0 { + b := buf + if len(b) > maxRW { + b = b[:maxRW] + } + o := &fd.wop + o.InitBuf(b) + n, err := execIO(o, func(o *operation) error { + return windows.WSASendtoInet6(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, sa6, &o.o, nil) + }) + ntotal += int(n) + if err != nil { + return ntotal, err + } + buf = buf[n:] + } + return ntotal, nil } // Call ConnectEx. This doesn't need any locking, since it is only @@ -1094,31 +1116,54 @@ func (fd *FD) RawWrite(f func(uintptr) bool) error { return syscall.EWINDOWS } -func sockaddrToRaw(sa syscall.Sockaddr) (unsafe.Pointer, int32, error) { +func sockaddrInet4ToRaw(rsa *syscall.RawSockaddrAny, sa *syscall.SockaddrInet4) int32 { + *rsa = syscall.RawSockaddrAny{} + raw := (*syscall.RawSockaddrInet4)(unsafe.Pointer(rsa)) + raw.Family = syscall.AF_INET + p := (*[2]byte)(unsafe.Pointer(&raw.Port)) + p[0] = byte(sa.Port >> 8) + p[1] = byte(sa.Port) + raw.Addr = sa.Addr + return int32(unsafe.Sizeof(*raw)) +} + +func sockaddrInet6ToRaw(rsa *syscall.RawSockaddrAny, sa *syscall.SockaddrInet6) int32 { + *rsa = syscall.RawSockaddrAny{} + raw := (*syscall.RawSockaddrInet6)(unsafe.Pointer(rsa)) + raw.Family = syscall.AF_INET6 + p := (*[2]byte)(unsafe.Pointer(&raw.Port)) + p[0] = byte(sa.Port >> 8) + p[1] = byte(sa.Port) + raw.Scope_id = sa.ZoneId + raw.Addr = sa.Addr + return int32(unsafe.Sizeof(*raw)) +} + +func rawToSockaddrInet4(rsa *syscall.RawSockaddrAny, sa *syscall.SockaddrInet4) { + pp := (*syscall.RawSockaddrInet4)(unsafe.Pointer(rsa)) + p := (*[2]byte)(unsafe.Pointer(&pp.Port)) + sa.Port = int(p[0])<<8 + int(p[1]) + sa.Addr = pp.Addr +} + +func rawToSockaddrInet6(rsa *syscall.RawSockaddrAny, sa *syscall.SockaddrInet6) { + pp := (*syscall.RawSockaddrInet6)(unsafe.Pointer(rsa)) + p := (*[2]byte)(unsafe.Pointer(&pp.Port)) + sa.Port = int(p[0])<<8 + int(p[1]) + sa.ZoneId = pp.Scope_id + sa.Addr = pp.Addr +} + +func sockaddrToRaw(rsa *syscall.RawSockaddrAny, sa syscall.Sockaddr) (int32, error) { switch sa := sa.(type) { case *syscall.SockaddrInet4: - var raw syscall.RawSockaddrInet4 - raw.Family = syscall.AF_INET - p := (*[2]byte)(unsafe.Pointer(&raw.Port)) - p[0] = byte(sa.Port >> 8) - p[1] = byte(sa.Port) - for i := 0; i < len(sa.Addr); i++ { - raw.Addr[i] = sa.Addr[i] - } - return unsafe.Pointer(&raw), int32(unsafe.Sizeof(raw)), nil + sz := sockaddrInet4ToRaw(rsa, sa) + return sz, nil case *syscall.SockaddrInet6: - var raw syscall.RawSockaddrInet6 - raw.Family = syscall.AF_INET6 - p := (*[2]byte)(unsafe.Pointer(&raw.Port)) - p[0] = byte(sa.Port >> 8) - p[1] = byte(sa.Port) - raw.Scope_id = sa.ZoneId - for i := 0; i < len(sa.Addr); i++ { - raw.Addr[i] = sa.Addr[i] - } - return unsafe.Pointer(&raw), int32(unsafe.Sizeof(raw)), nil + sz := sockaddrInet6ToRaw(rsa, sa) + return sz, nil default: - return nil, 0, syscall.EWINDOWS + return 0, syscall.EWINDOWS } } @@ -1135,7 +1180,9 @@ func (fd *FD) ReadMsg(p []byte, oob []byte, flags int) (int, int, int, syscall.S o := &fd.rop o.InitMsg(p, oob) - o.rsa = new(syscall.RawSockaddrAny) + if o.rsa == nil { + o.rsa = new(syscall.RawSockaddrAny) + } o.msg.Name = (syscall.Pointer)(unsafe.Pointer(o.rsa)) o.msg.Namelen = int32(unsafe.Sizeof(*o.rsa)) o.msg.Flags = uint32(flags) @@ -1150,6 +1197,64 @@ func (fd *FD) ReadMsg(p []byte, oob []byte, flags int) (int, int, int, syscall.S return n, int(o.msg.Control.Len), int(o.msg.Flags), sa, err } +// ReadMsgInet4 is ReadMsg, but specialized to return a syscall.SockaddrInet4. +func (fd *FD) ReadMsgInet4(p []byte, oob []byte, flags int, sa4 *syscall.SockaddrInet4) (int, int, int, error) { + if err := fd.readLock(); err != nil { + return 0, 0, 0, err + } + defer fd.readUnlock() + + if len(p) > maxRW { + p = p[:maxRW] + } + + o := &fd.rop + o.InitMsg(p, oob) + if o.rsa == nil { + o.rsa = new(syscall.RawSockaddrAny) + } + o.msg.Name = (syscall.Pointer)(unsafe.Pointer(o.rsa)) + o.msg.Namelen = int32(unsafe.Sizeof(*o.rsa)) + o.msg.Flags = uint32(flags) + n, err := execIO(o, func(o *operation) error { + return windows.WSARecvMsg(o.fd.Sysfd, &o.msg, &o.qty, &o.o, nil) + }) + err = fd.eofError(n, err) + if err == nil { + rawToSockaddrInet4(o.rsa, sa4) + } + return n, int(o.msg.Control.Len), int(o.msg.Flags), err +} + +// ReadMsgInet6 is ReadMsg, but specialized to return a syscall.SockaddrInet6. +func (fd *FD) ReadMsgInet6(p []byte, oob []byte, flags int, sa6 *syscall.SockaddrInet6) (int, int, int, error) { + if err := fd.readLock(); err != nil { + return 0, 0, 0, err + } + defer fd.readUnlock() + + if len(p) > maxRW { + p = p[:maxRW] + } + + o := &fd.rop + o.InitMsg(p, oob) + if o.rsa == nil { + o.rsa = new(syscall.RawSockaddrAny) + } + o.msg.Name = (syscall.Pointer)(unsafe.Pointer(o.rsa)) + o.msg.Namelen = int32(unsafe.Sizeof(*o.rsa)) + o.msg.Flags = uint32(flags) + n, err := execIO(o, func(o *operation) error { + return windows.WSARecvMsg(o.fd.Sysfd, &o.msg, &o.qty, &o.o, nil) + }) + err = fd.eofError(n, err) + if err == nil { + rawToSockaddrInet6(o.rsa, sa6) + } + return n, int(o.msg.Control.Len), int(o.msg.Flags), err +} + // WriteMsg wraps the WSASendMsg network call. func (fd *FD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (int, int, error) { if len(p) > maxRW { @@ -1164,11 +1269,14 @@ func (fd *FD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (int, int, err o := &fd.wop o.InitMsg(p, oob) if sa != nil { - rsa, len, err := sockaddrToRaw(sa) + if o.rsa == nil { + o.rsa = new(syscall.RawSockaddrAny) + } + len, err := sockaddrToRaw(o.rsa, sa) if err != nil { return 0, 0, err } - o.msg.Name = (syscall.Pointer)(rsa) + o.msg.Name = (syscall.Pointer)(unsafe.Pointer(o.rsa)) o.msg.Namelen = len } n, err := execIO(o, func(o *operation) error { @@ -1176,3 +1284,53 @@ func (fd *FD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (int, int, err }) return n, int(o.msg.Control.Len), err } + +// WriteMsgInet4 is WriteMsg specialized for syscall.SockaddrInet4. +func (fd *FD) WriteMsgInet4(p []byte, oob []byte, sa *syscall.SockaddrInet4) (int, int, error) { + if len(p) > maxRW { + return 0, 0, errors.New("packet is too large (only 1GB is allowed)") + } + + if err := fd.writeLock(); err != nil { + return 0, 0, err + } + defer fd.writeUnlock() + + o := &fd.wop + o.InitMsg(p, oob) + if o.rsa == nil { + o.rsa = new(syscall.RawSockaddrAny) + } + len := sockaddrInet4ToRaw(o.rsa, sa) + o.msg.Name = (syscall.Pointer)(unsafe.Pointer(o.rsa)) + o.msg.Namelen = len + n, err := execIO(o, func(o *operation) error { + return windows.WSASendMsg(o.fd.Sysfd, &o.msg, 0, &o.qty, &o.o, nil) + }) + return n, int(o.msg.Control.Len), err +} + +// WriteMsgInet6 is WriteMsg specialized for syscall.SockaddrInet6. +func (fd *FD) WriteMsgInet6(p []byte, oob []byte, sa *syscall.SockaddrInet6) (int, int, error) { + if len(p) > maxRW { + return 0, 0, errors.New("packet is too large (only 1GB is allowed)") + } + + if err := fd.writeLock(); err != nil { + return 0, 0, err + } + defer fd.writeUnlock() + + o := &fd.wop + o.InitMsg(p, oob) + if o.rsa == nil { + o.rsa = new(syscall.RawSockaddrAny) + } + len := sockaddrInet6ToRaw(o.rsa, sa) + o.msg.Name = (syscall.Pointer)(unsafe.Pointer(o.rsa)) + o.msg.Namelen = len + n, err := execIO(o, func(o *operation) error { + return windows.WSASendMsg(o.fd.Sysfd, &o.msg, 0, &o.qty, &o.o, nil) + }) + return n, int(o.msg.Control.Len), err +} diff --git a/src/internal/syscall/unix/net.go b/src/internal/syscall/unix/net.go new file mode 100644 index 0000000000..85632e1c03 --- /dev/null +++ b/src/internal/syscall/unix/net.go @@ -0,0 +1,44 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris + +package unix + +import ( + "syscall" + _ "unsafe" +) + +//go:linkname RecvfromInet4 syscall.recvfromInet4 +//go:noescape +func RecvfromInet4(fd int, p []byte, flags int, from *syscall.SockaddrInet4) (int, error) + +//go:linkname RecvfromInet6 syscall.recvfromInet6 +//go:noescape +func RecvfromInet6(fd int, p []byte, flags int, from *syscall.SockaddrInet6) (n int, err error) + +//go:linkname SendtoInet4 syscall.sendtoInet4 +//go:noescape +func SendtoInet4(fd int, p []byte, flags int, to *syscall.SockaddrInet4) (err error) + +//go:linkname SendtoInet6 syscall.sendtoInet6 +//go:noescape +func SendtoInet6(fd int, p []byte, flags int, to *syscall.SockaddrInet6) (err error) + +//go:linkname SendmsgNInet4 syscall.sendmsgNInet4 +//go:noescape +func SendmsgNInet4(fd int, p, oob []byte, to *syscall.SockaddrInet4, flags int) (n int, err error) + +//go:linkname SendmsgNInet6 syscall.sendmsgNInet6 +//go:noescape +func SendmsgNInet6(fd int, p, oob []byte, to *syscall.SockaddrInet6, flags int) (n int, err error) + +//go:linkname RecvmsgInet4 syscall.recvmsgInet4 +//go:noescape +func RecvmsgInet4(fd int, p, oob []byte, flags int, from *syscall.SockaddrInet4) (n, oobn int, recvflags int, err error) + +//go:linkname RecvmsgInet6 syscall.recvmsgInet6 +//go:noescape +func RecvmsgInet6(fd int, p, oob []byte, flags int, from *syscall.SockaddrInet6) (n, oobn int, recvflags int, err error) diff --git a/src/internal/syscall/unix/net_js.go b/src/internal/syscall/unix/net_js.go new file mode 100644 index 0000000000..622fc8eb14 --- /dev/null +++ b/src/internal/syscall/unix/net_js.go @@ -0,0 +1,44 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build js + +package unix + +import ( + "syscall" + _ "unsafe" +) + +func RecvfromInet4(fd int, p []byte, flags int, from *syscall.SockaddrInet4) (int, error) { + return 0, syscall.ENOSYS +} + +func RecvfromInet6(fd int, p []byte, flags int, from *syscall.SockaddrInet6) (n int, err error) { + return 0, syscall.ENOSYS +} + +func SendtoInet4(fd int, p []byte, flags int, to *syscall.SockaddrInet4) (err error) { + return syscall.ENOSYS +} + +func SendtoInet6(fd int, p []byte, flags int, to *syscall.SockaddrInet6) (err error) { + return syscall.ENOSYS +} + +func SendmsgNInet4(fd int, p, oob []byte, to *syscall.SockaddrInet4, flags int) (n int, err error) { + return 0, syscall.ENOSYS +} + +func SendmsgNInet6(fd int, p, oob []byte, to *syscall.SockaddrInet6, flags int) (n int, err error) { + return 0, syscall.ENOSYS +} + +func RecvmsgInet4(fd int, p, oob []byte, flags int, from *syscall.SockaddrInet4) (n, oobn int, recvflags int, err error) { + return 0, 0, 0, syscall.ENOSYS +} + +func RecvmsgInet6(fd int, p, oob []byte, flags int, from *syscall.SockaddrInet6) (n, oobn int, recvflags int, err error) { + return 0, 0, 0, syscall.ENOSYS +} diff --git a/src/internal/syscall/windows/net_windows.go b/src/internal/syscall/windows/net_windows.go new file mode 100644 index 0000000000..3d3df7161c --- /dev/null +++ b/src/internal/syscall/windows/net_windows.go @@ -0,0 +1,18 @@ +// Copyright 2021 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" + _ "unsafe" +) + +//go:linkname WSASendtoInet4 syscall.wsaSendtoInet4 +//go:noescape +func WSASendtoInet4(s syscall.Handle, bufs *syscall.WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *syscall.SockaddrInet4, overlapped *syscall.Overlapped, croutine *byte) (err error) + +//go:linkname WSASendtoInet6 syscall.wsaSendtoInet6 +//go:noescape +func WSASendtoInet6(s syscall.Handle, bufs *syscall.WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *syscall.SockaddrInet6, overlapped *syscall.Overlapped, croutine *byte) (err error) diff --git a/src/internal/syscall/windows/registry/key.go b/src/internal/syscall/windows/registry/key.go index ba5c292c5e..ec38cf9288 100644 --- a/src/internal/syscall/windows/registry/key.go +++ b/src/internal/syscall/windows/registry/key.go @@ -25,7 +25,10 @@ // package registry -import "syscall" +import ( + "runtime" + "syscall" +) const ( // Registry key security and access rights. @@ -88,6 +91,12 @@ func OpenKey(k Key, path string, access uint32) (Key, error) { // ReadSubKeyNames returns the names of subkeys of key k. func (k Key) ReadSubKeyNames() ([]string, error) { + // RegEnumKeyEx must be called repeatedly and to completion. + // During this time, this goroutine cannot migrate away from + // its current thread. See #49320. + runtime.LockOSThread() + defer runtime.UnlockOSThread() + names := make([]string, 0) // Registry key size limit is 255 bytes and described there: // https://msdn.microsoft.com/library/windows/desktop/ms724872.aspx diff --git a/src/net/conf.go b/src/net/conf.go index 1115699ab0..415caedacc 100644 --- a/src/net/conf.go +++ b/src/net/conf.go @@ -8,6 +8,7 @@ package net import ( "internal/bytealg" + "internal/godebug" "os" "runtime" "sync" @@ -286,7 +287,7 @@ func (c *conf) hostLookupOrder(r *Resolver, hostname string) (ret hostLookupOrde // cgo+2 // same, but debug level 2 // etc. func goDebugNetDNS() (dnsMode string, debugLevel int) { - goDebug := goDebugString("netdns") + goDebug := godebug.Get("netdns") parsePart := func(s string) { if s == "" { return diff --git a/src/net/dnsclient.go b/src/net/dnsclient.go index 3c1a12995a..a779c37e53 100644 --- a/src/net/dnsclient.go +++ b/src/net/dnsclient.go @@ -76,6 +76,11 @@ func equalASCIIName(x, y dnsmessage.Name) bool { // (currently restricted to hostname-compatible "preferred name" LDH labels and // SRV-like "underscore labels"; see golang.org/issue/12421). func isDomainName(s string) bool { + // The root domain name is valid. See golang.org/issue/45715. + if s == "." { + return true + } + // See RFC 1035, RFC 3696. // Presentation format has dots before every label except the first, and the // terminal empty label is optional here because we assume fully-qualified diff --git a/src/net/dnsclient_unix_test.go b/src/net/dnsclient_unix_test.go index 1d704d021e..14366eca8c 100644 --- a/src/net/dnsclient_unix_test.go +++ b/src/net/dnsclient_unix_test.go @@ -2120,3 +2120,44 @@ func TestNullMX(t *testing.T) { t.Errorf("records = [%v]; want [%v]", strings.Join(records, " "), want[0]) } } + +func TestRootNS(t *testing.T) { + // See https://golang.org/issue/45715. + fake := fakeDNSServer{ + rh: func(n, _ string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) { + r := dnsmessage.Message{ + Header: dnsmessage.Header{ + ID: q.Header.ID, + Response: true, + RCode: dnsmessage.RCodeSuccess, + }, + Questions: q.Questions, + Answers: []dnsmessage.Resource{ + { + Header: dnsmessage.ResourceHeader{ + Name: q.Questions[0].Name, + Type: dnsmessage.TypeNS, + Class: dnsmessage.ClassINET, + }, + Body: &dnsmessage.NSResource{ + NS: dnsmessage.MustNewName("i.root-servers.net."), + }, + }, + }, + } + return r, nil + }, + } + r := Resolver{PreferGo: true, Dial: fake.DialContext} + rrset, err := r.LookupNS(context.Background(), ".") + if err != nil { + t.Fatalf("LookupNS: %v", err) + } + if want := []*NS{&NS{Host: "i.root-servers.net."}}; !reflect.DeepEqual(rrset, want) { + records := []string{} + for _, rr := range rrset { + records = append(records, fmt.Sprintf("%v", rr)) + } + t.Errorf("records = [%v]; want [%v]", strings.Join(records, " "), want[0]) + } +} diff --git a/src/net/fd_posix.go b/src/net/fd_posix.go index 1887a45186..1845c173bb 100644 --- a/src/net/fd_posix.go +++ b/src/net/fd_posix.go @@ -80,6 +80,18 @@ func (fd *netFD) readMsg(p []byte, oob []byte, flags int) (n, oobn, retflags int return n, oobn, retflags, sa, wrapSyscallError(readMsgSyscallName, err) } +func (fd *netFD) readMsgInet4(p []byte, oob []byte, flags int, sa *syscall.SockaddrInet4) (n, oobn, retflags int, err error) { + n, oobn, retflags, err = fd.pfd.ReadMsgInet4(p, oob, flags, sa) + runtime.KeepAlive(fd) + return n, oobn, retflags, wrapSyscallError(readMsgSyscallName, err) +} + +func (fd *netFD) readMsgInet6(p []byte, oob []byte, flags int, sa *syscall.SockaddrInet6) (n, oobn, retflags int, err error) { + n, oobn, retflags, err = fd.pfd.ReadMsgInet6(p, oob, flags, sa) + runtime.KeepAlive(fd) + return n, oobn, retflags, wrapSyscallError(readMsgSyscallName, err) +} + func (fd *netFD) Write(p []byte) (nn int, err error) { nn, err = fd.pfd.Write(p) runtime.KeepAlive(fd) @@ -92,13 +104,13 @@ func (fd *netFD) writeTo(p []byte, sa syscall.Sockaddr) (n int, err error) { return n, wrapSyscallError(writeToSyscallName, err) } -func (fd *netFD) writeToInet4(p []byte, sa syscall.SockaddrInet4) (n int, err error) { +func (fd *netFD) writeToInet4(p []byte, sa *syscall.SockaddrInet4) (n int, err error) { n, err = fd.pfd.WriteToInet4(p, sa) runtime.KeepAlive(fd) return n, wrapSyscallError(writeToSyscallName, err) } -func (fd *netFD) writeToInet6(p []byte, sa syscall.SockaddrInet6) (n int, err error) { +func (fd *netFD) writeToInet6(p []byte, sa *syscall.SockaddrInet6) (n int, err error) { n, err = fd.pfd.WriteToInet6(p, sa) runtime.KeepAlive(fd) return n, wrapSyscallError(writeToSyscallName, err) @@ -110,6 +122,18 @@ func (fd *netFD) writeMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oob return n, oobn, wrapSyscallError(writeMsgSyscallName, err) } +func (fd *netFD) writeMsgInet4(p []byte, oob []byte, sa *syscall.SockaddrInet4) (n int, oobn int, err error) { + n, oobn, err = fd.pfd.WriteMsgInet4(p, oob, sa) + runtime.KeepAlive(fd) + return n, oobn, wrapSyscallError(writeMsgSyscallName, err) +} + +func (fd *netFD) writeMsgInet6(p []byte, oob []byte, sa *syscall.SockaddrInet6) (n int, oobn int, err error) { + n, oobn, err = fd.pfd.WriteMsgInet6(p, oob, sa) + runtime.KeepAlive(fd) + return n, oobn, wrapSyscallError(writeMsgSyscallName, err) +} + func (fd *netFD) SetDeadline(t time.Time) error { return fd.pfd.SetDeadline(t) } diff --git a/src/net/http/client_test.go b/src/net/http/client_test.go index e741c3746f..fb6fbe7197 100644 --- a/src/net/http/client_test.go +++ b/src/net/http/client_test.go @@ -1205,64 +1205,80 @@ func TestClientTimeout_h2(t *testing.T) { testClientTimeout(t, h2Mode) } func testClientTimeout(t *testing.T, h2 bool) { setParallel(t) defer afterTest(t) - testDone := make(chan struct{}) // closed in defer below - sawRoot := make(chan bool, 1) - sawSlow := make(chan bool, 1) + var ( + mu sync.Mutex + nonce string // a unique per-request string + sawSlowNonce bool // true if the handler saw /slow?nonce= + ) cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { + _ = r.ParseForm() if r.URL.Path == "/" { - sawRoot <- true - Redirect(w, r, "/slow", StatusFound) + Redirect(w, r, "/slow?nonce="+r.Form.Get("nonce"), StatusFound) return } if r.URL.Path == "/slow" { - sawSlow <- true + mu.Lock() + if r.Form.Get("nonce") == nonce { + sawSlowNonce = true + } else { + t.Logf("mismatched nonce: received %s, want %s", r.Form.Get("nonce"), nonce) + } + mu.Unlock() + w.Write([]byte("Hello")) w.(Flusher).Flush() - <-testDone + <-r.Context().Done() return } })) defer cst.close() - defer close(testDone) // before cst.close, to unblock /slow handler - // 200ms should be long enough to get a normal request (the / - // handler), but not so long that it makes the test slow. - const timeout = 200 * time.Millisecond - cst.c.Timeout = timeout - - res, err := cst.c.Get(cst.ts.URL) - if err != nil { - if strings.Contains(err.Error(), "Client.Timeout") { - t.Skipf("host too slow to get fast resource in %v", timeout) + // Try to trigger a timeout after reading part of the response body. + // The initial timeout is emprically usually long enough on a decently fast + // machine, but if we undershoot we'll retry with exponentially longer + // timeouts until the test either passes or times out completely. + // This keeps the test reasonably fast in the typical case but allows it to + // also eventually succeed on arbitrarily slow machines. + timeout := 10 * time.Millisecond + nextNonce := 0 + for ; ; timeout *= 2 { + if timeout <= 0 { + // The only way we can feasibly hit this while the test is running is if + // the request fails without actually waiting for the timeout to occur. + t.Fatalf("timeout overflow") } - t.Fatal(err) - } + if deadline, ok := t.Deadline(); ok && !time.Now().Add(timeout).Before(deadline) { + t.Fatalf("failed to produce expected timeout before test deadline") + } + t.Logf("attempting test with timeout %v", timeout) + cst.c.Timeout = timeout - select { - case <-sawRoot: - // good. - default: - t.Fatal("handler never got / request") - } + mu.Lock() + nonce = fmt.Sprint(nextNonce) + nextNonce++ + sawSlowNonce = false + mu.Unlock() + res, err := cst.c.Get(cst.ts.URL + "/?nonce=" + nonce) + if err != nil { + if strings.Contains(err.Error(), "Client.Timeout") { + // Timed out before handler could respond. + t.Logf("timeout before response received") + continue + } + t.Fatal(err) + } - select { - case <-sawSlow: - // good. - default: - t.Fatal("handler never got /slow request") - } + mu.Lock() + ok := sawSlowNonce + mu.Unlock() + if !ok { + t.Fatal("handler never got /slow request, but client returned response") + } - errc := make(chan error, 1) - go func() { - _, err := io.ReadAll(res.Body) - errc <- err + _, err = io.ReadAll(res.Body) res.Body.Close() - }() - const failTime = 5 * time.Second - select { - case err := <-errc: if err == nil { t.Fatal("expected error from ReadAll") } @@ -1275,8 +1291,8 @@ func testClientTimeout(t *testing.T, h2 bool) { if got := ne.Error(); !strings.Contains(got, "(Client.Timeout") { t.Errorf("error string = %q; missing timeout substring", got) } - case <-time.After(failTime): - t.Errorf("timeout after %v waiting for timeout of %v", failTime, timeout) + + break } } diff --git a/src/net/http/export_test.go b/src/net/http/export_test.go index 096a6d382a..a849327f45 100644 --- a/src/net/http/export_test.go +++ b/src/net/http/export_test.go @@ -88,12 +88,7 @@ func SetPendingDialHooks(before, after func()) { func SetTestHookServerServe(fn func(*Server, net.Listener)) { testHookServerServe = fn } -func NewTestTimeoutHandler(handler Handler, ch <-chan time.Time) Handler { - ctx, cancel := context.WithCancel(context.Background()) - go func() { - <-ch - cancel() - }() +func NewTestTimeoutHandler(handler Handler, ctx context.Context) Handler { return &timeoutHandler{ handler: handler, testContext: ctx, diff --git a/src/net/http/main_test.go b/src/net/http/main_test.go index 632a308a5c..27872b4e7a 100644 --- a/src/net/http/main_test.go +++ b/src/net/http/main_test.go @@ -43,7 +43,7 @@ func interestingGoroutines() (gs []string) { // These only show up with GOTRACEBACK=2; Issue 5005 (comment 28) strings.Contains(stack, "runtime.goexit") || strings.Contains(stack, "created by runtime.gc") || - strings.Contains(stack, "net/http_test.interestingGoroutines") || + strings.Contains(stack, "interestingGoroutines") || strings.Contains(stack, "runtime.MHeap_Scavenger") { continue } diff --git a/src/net/http/serve_test.go b/src/net/http/serve_test.go index 6394da3bb7..e8fb77446c 100644 --- a/src/net/http/serve_test.go +++ b/src/net/http/serve_test.go @@ -23,6 +23,7 @@ import ( "net" . "net/http" "net/http/httptest" + "net/http/httptrace" "net/http/httputil" "net/http/internal" "net/http/internal/testcert" @@ -2273,6 +2274,18 @@ func TestRequestBodyTimeoutClosesConnection(t *testing.T) { } } +// cancelableTimeoutContext overwrites the error message to DeadlineExceeded +type cancelableTimeoutContext struct { + context.Context +} + +func (c cancelableTimeoutContext) Err() error { + if c.Context.Err() != nil { + return context.DeadlineExceeded + } + return nil +} + func TestTimeoutHandler_h1(t *testing.T) { testTimeoutHandler(t, h1Mode) } func TestTimeoutHandler_h2(t *testing.T) { testTimeoutHandler(t, h2Mode) } func testTimeoutHandler(t *testing.T, h2 bool) { @@ -2285,8 +2298,9 @@ func testTimeoutHandler(t *testing.T, h2 bool) { _, werr := w.Write([]byte("hi")) writeErrors <- werr }) - timeout := make(chan time.Time, 1) // write to this to force timeouts - cst := newClientServerTest(t, h2, NewTestTimeoutHandler(sayHi, timeout)) + ctx, cancel := context.WithCancel(context.Background()) + h := NewTestTimeoutHandler(sayHi, cancelableTimeoutContext{ctx}) + cst := newClientServerTest(t, h2, h) defer cst.close() // Succeed without timing out: @@ -2307,7 +2321,8 @@ func testTimeoutHandler(t *testing.T, h2 bool) { } // Times out: - timeout <- time.Time{} + cancel() + res, err = cst.c.Get(cst.ts.URL) if err != nil { t.Error(err) @@ -2428,8 +2443,9 @@ func TestTimeoutHandlerRaceHeaderTimeout(t *testing.T) { _, werr := w.Write([]byte("hi")) writeErrors <- werr }) - timeout := make(chan time.Time, 1) // write to this to force timeouts - cst := newClientServerTest(t, h1Mode, NewTestTimeoutHandler(sayHi, timeout)) + ctx, cancel := context.WithCancel(context.Background()) + h := NewTestTimeoutHandler(sayHi, cancelableTimeoutContext{ctx}) + cst := newClientServerTest(t, h1Mode, h) defer cst.close() // Succeed without timing out: @@ -2450,7 +2466,8 @@ func TestTimeoutHandlerRaceHeaderTimeout(t *testing.T) { } // Times out: - timeout <- time.Time{} + cancel() + res, err = cst.c.Get(cst.ts.URL) if err != nil { t.Error(err) @@ -2500,6 +2517,41 @@ func TestTimeoutHandlerStartTimerWhenServing(t *testing.T) { } } +func TestTimeoutHandlerContextCanceled(t *testing.T) { + setParallel(t) + defer afterTest(t) + sendHi := make(chan bool, 1) + writeErrors := make(chan error, 1) + sayHi := HandlerFunc(func(w ResponseWriter, r *Request) { + w.Header().Set("Content-Type", "text/plain") + <-sendHi + _, werr := w.Write([]byte("hi")) + writeErrors <- werr + }) + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Hour) + h := NewTestTimeoutHandler(sayHi, ctx) + cancel() + cst := newClientServerTest(t, h1Mode, h) + defer cst.close() + + // Succeed without timing out: + sendHi <- true + res, err := cst.c.Get(cst.ts.URL) + if err != nil { + t.Error(err) + } + if g, e := res.StatusCode, StatusServiceUnavailable; g != e { + t.Errorf("got res.StatusCode %d; expected %d", g, e) + } + body, _ := io.ReadAll(res.Body) + if g, e := string(body), ""; g != e { + t.Errorf("got body %q; expected %q", g, e) + } + if g, e := <-writeErrors, context.Canceled; g != e { + t.Errorf("got unexpected Write error on first request: %v", g) + } +} + // https://golang.org/issue/15948 func TestTimeoutHandlerEmptyResponse(t *testing.T) { setParallel(t) @@ -5689,22 +5741,37 @@ func testServerKeepAlivesEnabled(t *testing.T, h2 bool) { } // Not parallel: messes with global variable. (http2goAwayTimeout) defer afterTest(t) - cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { - fmt.Fprintf(w, "%v", r.RemoteAddr) - })) + cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {})) defer cst.close() srv := cst.ts.Config srv.SetKeepAlivesEnabled(false) - a := cst.getURL(cst.ts.URL) - if !waitCondition(2*time.Second, 10*time.Millisecond, srv.ExportAllConnsIdle) { - t.Fatalf("test server has active conns") - } - b := cst.getURL(cst.ts.URL) - if a == b { - t.Errorf("got same connection between first and second requests") - } - if !waitCondition(2*time.Second, 10*time.Millisecond, srv.ExportAllConnsIdle) { - t.Fatalf("test server has active conns") + for try := 0; try < 2; try++ { + if !waitCondition(2*time.Second, 10*time.Millisecond, srv.ExportAllConnsIdle) { + t.Fatalf("request %v: test server has active conns", try) + } + conns := 0 + var info httptrace.GotConnInfo + ctx := httptrace.WithClientTrace(context.Background(), &httptrace.ClientTrace{ + GotConn: func(v httptrace.GotConnInfo) { + conns++ + info = v + }, + }) + req, err := NewRequestWithContext(ctx, "GET", cst.ts.URL, nil) + if err != nil { + t.Fatal(err) + } + res, err := cst.c.Do(req) + if err != nil { + t.Fatal(err) + } + res.Body.Close() + if conns != 1 { + t.Fatalf("request %v: got %v conns, want 1", try, conns) + } + if info.Reused || info.WasIdle { + t.Fatalf("request %v: Reused=%v (want false), WasIdle=%v (want false)", try, info.Reused, info.WasIdle) + } } } diff --git a/src/net/http/server.go b/src/net/http/server.go index e9b0b4d9bd..08fd478ed9 100644 --- a/src/net/http/server.go +++ b/src/net/http/server.go @@ -13,6 +13,7 @@ import ( "crypto/tls" "errors" "fmt" + "internal/godebug" "io" "log" "math/rand" @@ -20,7 +21,6 @@ import ( "net/textproto" "net/url" urlpkg "net/url" - "os" "path" "runtime" "sort" @@ -3296,7 +3296,7 @@ func (srv *Server) onceSetNextProtoDefaults_Serve() { // configured otherwise. (by setting srv.TLSNextProto non-nil) // It must only be called via srv.nextProtoOnce (use srv.setupHTTP2_*). func (srv *Server) onceSetNextProtoDefaults() { - if omitBundledHTTP2 || strings.Contains(os.Getenv("GODEBUG"), "http2server=0") { + if omitBundledHTTP2 || godebug.Get("http2server") == "0" { return } // Enable HTTP/2 by default if the user hasn't otherwise @@ -3391,9 +3391,15 @@ func (h *timeoutHandler) ServeHTTP(w ResponseWriter, r *Request) { case <-ctx.Done(): tw.mu.Lock() defer tw.mu.Unlock() - w.WriteHeader(StatusServiceUnavailable) - io.WriteString(w, h.errorBody()) - tw.timedOut = true + switch err := ctx.Err(); err { + case context.DeadlineExceeded: + w.WriteHeader(StatusServiceUnavailable) + io.WriteString(w, h.errorBody()) + tw.err = ErrHandlerTimeout + default: + w.WriteHeader(StatusServiceUnavailable) + tw.err = err + } } } @@ -3404,7 +3410,7 @@ type timeoutWriter struct { req *Request mu sync.Mutex - timedOut bool + err error wroteHeader bool code int } @@ -3424,8 +3430,8 @@ func (tw *timeoutWriter) Header() Header { return tw.h } func (tw *timeoutWriter) Write(p []byte) (int, error) { tw.mu.Lock() defer tw.mu.Unlock() - if tw.timedOut { - return 0, ErrHandlerTimeout + if tw.err != nil { + return 0, tw.err } if !tw.wroteHeader { tw.writeHeaderLocked(StatusOK) @@ -3437,7 +3443,7 @@ func (tw *timeoutWriter) writeHeaderLocked(code int) { checkWriteHeaderCode(code) switch { - case tw.timedOut: + case tw.err != nil: return case tw.wroteHeader: if tw.req != nil { diff --git a/src/net/http/transport.go b/src/net/http/transport.go index 0e60992e6c..f2d2f79280 100644 --- a/src/net/http/transport.go +++ b/src/net/http/transport.go @@ -17,6 +17,7 @@ import ( "crypto/tls" "errors" "fmt" + "internal/godebug" "io" "log" "net" @@ -24,7 +25,6 @@ import ( "net/http/internal/ascii" "net/textproto" "net/url" - "os" "reflect" "strings" "sync" @@ -360,7 +360,7 @@ func (t *Transport) hasCustomTLSDialer() bool { // It must be called via t.nextProtoOnce.Do. func (t *Transport) onceSetNextProtoDefaults() { t.tlsNextProtoWasNil = (t.TLSNextProto == nil) - if strings.Contains(os.Getenv("GODEBUG"), "http2client=0") { + if godebug.Get("http2client") == "0" { return } @@ -2481,7 +2481,7 @@ type requestAndChan struct { callerGone <-chan struct{} // closed when roundTrip caller has returned } -// A writeRequest is sent by the readLoop's goroutine to the +// A writeRequest is sent by the caller's goroutine to the // writeLoop's goroutine to write a request while the read loop // concurrently waits on both the write response and the server's // reply. diff --git a/src/net/ipsock_posix.go b/src/net/ipsock_posix.go index 0910f63d48..e433e8a91c 100644 --- a/src/net/ipsock_posix.go +++ b/src/net/ipsock_posix.go @@ -9,6 +9,7 @@ package net import ( "context" "internal/poll" + "net/netip" "runtime" "syscall" ) @@ -196,3 +197,32 @@ func ipToSockaddr(family int, ip IP, port int, zone string) (syscall.Sockaddr, e } return nil, &AddrError{Err: "invalid address family", Addr: ip.String()} } + +func addrPortToSockaddrInet4(ap netip.AddrPort) (syscall.SockaddrInet4, error) { + // ipToSockaddrInet4 has special handling here for zero length slices. + // We do not, because netip has no concept of a generic zero IP address. + addr := ap.Addr() + if !addr.Is4() { + return syscall.SockaddrInet4{}, &AddrError{Err: "non-IPv4 address", Addr: addr.String()} + } + sa := syscall.SockaddrInet4{ + Addr: addr.As4(), + Port: int(ap.Port()), + } + return sa, nil +} + +func addrPortToSockaddrInet6(ap netip.AddrPort) (syscall.SockaddrInet6, error) { + // ipToSockaddrInet6 has special handling here for zero length slices. + // We do not, because netip has no concept of a generic zero IP address. + addr := ap.Addr() + if !addr.Is6() { + return syscall.SockaddrInet6{}, &AddrError{Err: "non-IPv6 address", Addr: addr.String()} + } + sa := syscall.SockaddrInet6{ + Addr: addr.As16(), + Port: int(ap.Port()), + ZoneId: uint32(zoneCache.index(addr.Zone())), + } + return sa, nil +} diff --git a/src/net/lookup.go b/src/net/lookup.go index fe573b8a27..ff4ddbeb82 100644 --- a/src/net/lookup.go +++ b/src/net/lookup.go @@ -8,6 +8,7 @@ import ( "context" "internal/nettrace" "internal/singleflight" + "net/netip" "sync" ) @@ -232,6 +233,28 @@ func (r *Resolver) LookupIP(ctx context.Context, network, host string) ([]IP, er return ips, nil } +// LookupNetIP looks up host using the local resolver. +// It returns a slice of that host's IP addresses of the type specified by +// network. +// The network must be one of "ip", "ip4" or "ip6". +func (r *Resolver) LookupNetIP(ctx context.Context, network, host string) ([]netip.Addr, error) { + // TODO(bradfitz): make this efficient, making the internal net package + // type throughout be netip.Addr and only converting to the net.IP slice + // version at the edge. But for now (2021-10-20), this is a wrapper around + // the old way. + ips, err := r.LookupIP(ctx, network, host) + if err != nil { + return nil, err + } + ret := make([]netip.Addr, 0, len(ips)) + for _, ip := range ips { + if a, ok := netip.AddrFromSlice(ip); ok { + ret = append(ret, a) + } + } + return ret, nil +} + // onlyValuesCtx is a context that uses an underlying context // for value lookup if the underlying context hasn't yet expired. type onlyValuesCtx struct { @@ -535,9 +558,7 @@ func (r *Resolver) LookupMX(ctx context.Context, name string) ([]*MX, error) { if mx == nil { continue } - // Bypass the hostname validity check for targets which contain only a dot, - // as this is used to represent a 'Null' MX record. - if mx.Host != "." && !isDomainName(mx.Host) { + if !isDomainName(mx.Host) { continue } filteredMX = append(filteredMX, mx) diff --git a/src/net/net_fake.go b/src/net/net_fake.go index d58bd82029..ee5644c67f 100644 --- a/src/net/net_fake.go +++ b/src/net/net_fake.go @@ -279,15 +279,31 @@ func (fd *netFD) readMsg(p []byte, oob []byte, flags int) (n, oobn, retflags int return 0, 0, 0, nil, syscall.ENOSYS } +func (fd *netFD) readMsgInet4(p []byte, oob []byte, flags int, sa *syscall.SockaddrInet4) (n, oobn, retflags int, err error) { + return 0, 0, 0, syscall.ENOSYS +} + +func (fd *netFD) readMsgInet6(p []byte, oob []byte, flags int, sa *syscall.SockaddrInet6) (n, oobn, retflags int, err error) { + return 0, 0, 0, syscall.ENOSYS +} + +func (fd *netFD) writeMsgInet4(p []byte, oob []byte, sa *syscall.SockaddrInet4) (n int, oobn int, err error) { + return 0, 0, syscall.ENOSYS +} + +func (fd *netFD) writeMsgInet6(p []byte, oob []byte, sa *syscall.SockaddrInet6) (n int, oobn int, err error) { + return 0, 0, syscall.ENOSYS +} + func (fd *netFD) writeTo(p []byte, sa syscall.Sockaddr) (n int, err error) { return 0, syscall.ENOSYS } -func (fd *netFD) writeToInet4(p []byte, sa syscall.SockaddrInet4) (n int, err error) { +func (fd *netFD) writeToInet4(p []byte, sa *syscall.SockaddrInet4) (n int, err error) { return 0, syscall.ENOSYS } -func (fd *netFD) writeToInet6(p []byte, sa syscall.SockaddrInet6) (n int, err error) { +func (fd *netFD) writeToInet6(p []byte, sa *syscall.SockaddrInet6) (n int, err error) { return 0, syscall.ENOSYS } diff --git a/src/net/netip/export_test.go b/src/net/netip/export_test.go new file mode 100644 index 0000000000..59971fa2e4 --- /dev/null +++ b/src/net/netip/export_test.go @@ -0,0 +1,30 @@ +// Copyright 2021 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 netip + +import "internal/intern" + +var ( + Z0 = z0 + Z4 = z4 + Z6noz = z6noz +) + +type Uint128 = uint128 + +func Mk128(hi, lo uint64) Uint128 { + return uint128{hi, lo} +} + +func MkAddr(u Uint128, z *intern.Value) Addr { + return Addr{u, z} +} + +func IPv4(a, b, c, d uint8) Addr { return AddrFrom4([4]byte{a, b, c, d}) } + +var TestAppendToMarshal = testAppendToMarshal + +func (a Addr) IsZero() bool { return a.isZero() } +func (p Prefix) IsZero() bool { return p.isZero() } diff --git a/src/net/netip/inlining_test.go b/src/net/netip/inlining_test.go new file mode 100644 index 0000000000..107fe1f083 --- /dev/null +++ b/src/net/netip/inlining_test.go @@ -0,0 +1,110 @@ +// 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 netip + +import ( + "internal/testenv" + "os/exec" + "path/filepath" + "regexp" + "runtime" + "strings" + "testing" +) + +func TestInlining(t *testing.T) { + testenv.MustHaveGoBuild(t) + t.Parallel() + var exe string + if runtime.GOOS == "windows" { + exe = ".exe" + } + out, err := exec.Command( + filepath.Join(runtime.GOROOT(), "bin", "go"+exe), + "build", + "--gcflags=-m", + "net/netip").CombinedOutput() + if err != nil { + t.Fatalf("go build: %v, %s", err, out) + } + got := map[string]bool{} + regexp.MustCompile(` can inline (\S+)`).ReplaceAllFunc(out, func(match []byte) []byte { + got[strings.TrimPrefix(string(match), " can inline ")] = true + return nil + }) + wantInlinable := []string{ + "(*uint128).halves", + "Addr.BitLen", + "Addr.hasZone", + "Addr.Is4", + "Addr.Is4In6", + "Addr.Is6", + "Addr.IsLoopback", + "Addr.IsMulticast", + "Addr.IsInterfaceLocalMulticast", + "Addr.IsValid", + "Addr.IsUnspecified", + "Addr.Less", + "Addr.lessOrEq", + "Addr.Unmap", + "Addr.Zone", + "Addr.v4", + "Addr.v6", + "Addr.v6u16", + "Addr.withoutZone", + "AddrPortFrom", + "AddrPort.Addr", + "AddrPort.Port", + "AddrPort.IsValid", + "Prefix.IsSingleIP", + "Prefix.Masked", + "Prefix.IsValid", + "PrefixFrom", + "Prefix.Addr", + "Prefix.Bits", + "AddrFrom4", + "IPv6LinkLocalAllNodes", + "IPv6Unspecified", + "MustParseAddr", + "MustParseAddrPort", + "MustParsePrefix", + "appendDecimal", + "appendHex", + "uint128.addOne", + "uint128.and", + "uint128.bitsClearedFrom", + "uint128.bitsSetFrom", + "uint128.isZero", + "uint128.not", + "uint128.or", + "uint128.subOne", + "uint128.xor", + } + switch runtime.GOARCH { + case "amd64", "arm64": + // These don't inline on 32-bit. + wantInlinable = append(wantInlinable, + "u64CommonPrefixLen", + "uint128.commonPrefixLen", + "Addr.Next", + "Addr.Prev", + ) + } + + for _, want := range wantInlinable { + if !got[want] { + t.Errorf("%q is no longer inlinable", want) + continue + } + delete(got, want) + } + for sym := range got { + if strings.Contains(sym, ".func") { + continue + } + t.Logf("not in expected set, but also inlinable: %q", sym) + + } +} diff --git a/src/net/netip/leaf_alts.go b/src/net/netip/leaf_alts.go new file mode 100644 index 0000000000..c51f7dfa54 --- /dev/null +++ b/src/net/netip/leaf_alts.go @@ -0,0 +1,43 @@ +// Copyright 2021 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. + +// Stuff that exists in std, but we can't use due to being a dependency +// of net, for go/build deps_test policy reasons. + +package netip + +func stringsLastIndexByte(s string, b byte) int { + for i := len(s) - 1; i >= 0; i-- { + if s[i] == b { + return i + } + } + return -1 +} + +func beUint64(b []byte) uint64 { + _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808 + return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 | + uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56 +} + +func bePutUint64(b []byte, v uint64) { + _ = b[7] // early bounds check to guarantee safety of writes below + b[0] = byte(v >> 56) + b[1] = byte(v >> 48) + b[2] = byte(v >> 40) + b[3] = byte(v >> 32) + b[4] = byte(v >> 24) + b[5] = byte(v >> 16) + b[6] = byte(v >> 8) + b[7] = byte(v) +} + +func bePutUint32(b []byte, v uint32) { + _ = b[3] // early bounds check to guarantee safety of writes below + b[0] = byte(v >> 24) + b[1] = byte(v >> 16) + b[2] = byte(v >> 8) + b[3] = byte(v) +} diff --git a/src/net/netip/netip.go b/src/net/netip/netip.go new file mode 100644 index 0000000000..8cde6ef3d2 --- /dev/null +++ b/src/net/netip/netip.go @@ -0,0 +1,1418 @@ +// 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 netip defines an IP address type that's a small value type. +// Building on that Addr type, the package also defines AddrPort (an +// IP address and a port), and Prefix (an IP address and a bit length +// prefix). +// +// Compared to the net.IP type, this package's Addr type takes less +// memory, is immutable, and is comparable (supports == and being a +// map key). +package netip + +import ( + "errors" + "math" + "strconv" + + "internal/bytealg" + "internal/intern" + "internal/itoa" +) + +// Sizes: (64-bit) +// net.IP: 24 byte slice header + {4, 16} = 28 to 40 bytes +// net.IPAddr: 40 byte slice header + {4, 16} = 44 to 56 bytes + zone length +// netip.Addr: 24 bytes (zone is per-name singleton, shared across all users) + +// Addr represents an IPv4 or IPv6 address (with or without a scoped +// addressing zone), similar to net.IP or net.IPAddr. +// +// Unlike net.IP or net.IPAddr, Addr is a comparable value +// type (it supports == and can be a map key) and is immutable. +type Addr struct { + // addr is the hi and lo bits of an IPv6 address. If z==z4, + // hi and lo contain the IPv4-mapped IPv6 address. + // + // hi and lo are constructed by interpreting a 16-byte IPv6 + // address as a big-endian 128-bit number. The most significant + // bits of that number go into hi, the rest into lo. + // + // For example, 0011:2233:4455:6677:8899:aabb:ccdd:eeff is stored as: + // addr.hi = 0x0011223344556677 + // addr.lo = 0x8899aabbccddeeff + // + // We store IPs like this, rather than as [16]byte, because it + // turns most operations on IPs into arithmetic and bit-twiddling + // operations on 64-bit registers, which is much faster than + // bytewise processing. + addr uint128 + + // z is a combination of the address family and the IPv6 zone. + // + // nil means invalid IP address (for a zero Addr). + // z4 means an IPv4 address. + // z6noz means an IPv6 address without a zone. + // + // Otherwise it's the interned zone name string. + z *intern.Value +} + +// z0, z4, and z6noz are sentinel IP.z values. +// See the IP type's field docs. +var ( + z0 = (*intern.Value)(nil) + z4 = new(intern.Value) + z6noz = new(intern.Value) +) + +// IPv6LinkLocalAllNodes returns the IPv6 link-local all nodes multicast +// address ff02::1. +func IPv6LinkLocalAllNodes() Addr { return AddrFrom16([16]byte{0: 0xff, 1: 0x02, 15: 0x01}) } + +// IPv6Unspecified returns the IPv6 unspecified address "::". +func IPv6Unspecified() Addr { return Addr{z: z6noz} } + +// AddrFrom4 returns the address of the IPv4 address given by the bytes in addr. +func AddrFrom4(addr [4]byte) Addr { + return Addr{ + addr: uint128{0, 0xffff00000000 | uint64(addr[0])<<24 | uint64(addr[1])<<16 | uint64(addr[2])<<8 | uint64(addr[3])}, + z: z4, + } +} + +// AddrFrom16 returns the IPv6 address given by the bytes in addr. +// An IPv6-mapped IPv4 address is left as an IPv6 address. +// (Use Unmap to convert them if needed.) +func AddrFrom16(addr [16]byte) Addr { + return Addr{ + addr: uint128{ + beUint64(addr[:8]), + beUint64(addr[8:]), + }, + z: z6noz, + } +} + +// ipv6Slice is like IPv6Raw, but operates on a 16-byte slice. Assumes +// slice is 16 bytes, caller must enforce this. +func ipv6Slice(addr []byte) Addr { + return Addr{ + addr: uint128{ + beUint64(addr[:8]), + beUint64(addr[8:]), + }, + z: z6noz, + } +} + +// ParseAddr parses s as an IP address, returning the result. The string +// s can be in dotted decimal ("192.0.2.1"), IPv6 ("2001:db8::68"), +// or IPv6 with a scoped addressing zone ("fe80::1cc0:3e8c:119f:c2e1%ens18"). +func ParseAddr(s string) (Addr, error) { + for i := 0; i < len(s); i++ { + switch s[i] { + case '.': + return parseIPv4(s) + case ':': + return parseIPv6(s) + case '%': + // Assume that this was trying to be an IPv6 address with + // a zone specifier, but the address is missing. + return Addr{}, parseAddrError{in: s, msg: "missing IPv6 address"} + } + } + return Addr{}, parseAddrError{in: s, msg: "unable to parse IP"} +} + +// MustParseAddr calls ParseAddr(s) and panics on error. +// It is intended for use in tests with hard-coded strings. +func MustParseAddr(s string) Addr { + ip, err := ParseAddr(s) + if err != nil { + panic(err) + } + return ip +} + +type parseAddrError struct { + in string // the string given to ParseAddr + msg string // an explanation of the parse failure + at string // optionally, the unparsed portion of in at which the error occurred. +} + +func (err parseAddrError) Error() string { + q := strconv.Quote + if err.at != "" { + return "ParseAddr(" + q(err.in) + "): " + err.msg + " (at " + q(err.at) + ")" + } + return "ParseAddr(" + q(err.in) + "): " + err.msg +} + +// parseIPv4 parses s as an IPv4 address (in form "192.168.0.1"). +func parseIPv4(s string) (ip Addr, err error) { + var fields [4]uint8 + var val, pos int + var digLen int // number of digits in current octet + for i := 0; i < len(s); i++ { + if s[i] >= '0' && s[i] <= '9' { + if digLen == 1 && val == 0 { + return Addr{}, parseAddrError{in: s, msg: "IPv4 field has octet with leading zero"} + } + val = val*10 + int(s[i]) - '0' + digLen++ + if val > 255 { + return Addr{}, parseAddrError{in: s, msg: "IPv4 field has value >255"} + } + } else if s[i] == '.' { + // .1.2.3 + // 1.2.3. + // 1..2.3 + if i == 0 || i == len(s)-1 || s[i-1] == '.' { + return Addr{}, parseAddrError{in: s, msg: "IPv4 field must have at least one digit", at: s[i:]} + } + // 1.2.3.4.5 + if pos == 3 { + return Addr{}, parseAddrError{in: s, msg: "IPv4 address too long"} + } + fields[pos] = uint8(val) + pos++ + val = 0 + digLen = 0 + } else { + return Addr{}, parseAddrError{in: s, msg: "unexpected character", at: s[i:]} + } + } + if pos < 3 { + return Addr{}, parseAddrError{in: s, msg: "IPv4 address too short"} + } + fields[3] = uint8(val) + return AddrFrom4(fields), nil +} + +// parseIPv6 parses s as an IPv6 address (in form "2001:db8::68"). +func parseIPv6(in string) (Addr, error) { + s := in + + // Split off the zone right from the start. Yes it's a second scan + // of the string, but trying to handle it inline makes a bunch of + // other inner loop conditionals more expensive, and it ends up + // being slower. + zone := "" + i := bytealg.IndexByteString(s, '%') + if i != -1 { + s, zone = s[:i], s[i+1:] + if zone == "" { + // Not allowed to have an empty zone if explicitly specified. + return Addr{}, parseAddrError{in: in, msg: "zone must be a non-empty string"} + } + } + + var ip [16]byte + ellipsis := -1 // position of ellipsis in ip + + // Might have leading ellipsis + if len(s) >= 2 && s[0] == ':' && s[1] == ':' { + ellipsis = 0 + s = s[2:] + // Might be only ellipsis + if len(s) == 0 { + return IPv6Unspecified().WithZone(zone), nil + } + } + + // Loop, parsing hex numbers followed by colon. + i = 0 + for i < 16 { + // Hex number. Similar to parseIPv4, inlining the hex number + // parsing yields a significant performance increase. + off := 0 + acc := uint32(0) + for ; off < len(s); off++ { + c := s[off] + if c >= '0' && c <= '9' { + acc = (acc << 4) + uint32(c-'0') + } else if c >= 'a' && c <= 'f' { + acc = (acc << 4) + uint32(c-'a'+10) + } else if c >= 'A' && c <= 'F' { + acc = (acc << 4) + uint32(c-'A'+10) + } else { + break + } + if acc > math.MaxUint16 { + // Overflow, fail. + return Addr{}, parseAddrError{in: in, msg: "IPv6 field has value >=2^16", at: s} + } + } + if off == 0 { + // No digits found, fail. + return Addr{}, parseAddrError{in: in, msg: "each colon-separated field must have at least one digit", at: s} + } + + // If followed by dot, might be in trailing IPv4. + if off < len(s) && s[off] == '.' { + if ellipsis < 0 && i != 12 { + // Not the right place. + return Addr{}, parseAddrError{in: in, msg: "embedded IPv4 address must replace the final 2 fields of the address", at: s} + } + if i+4 > 16 { + // Not enough room. + return Addr{}, parseAddrError{in: in, msg: "too many hex fields to fit an embedded IPv4 at the end of the address", at: s} + } + // TODO: could make this a bit faster by having a helper + // that parses to a [4]byte, and have both parseIPv4 and + // parseIPv6 use it. + ip4, err := parseIPv4(s) + if err != nil { + return Addr{}, parseAddrError{in: in, msg: err.Error(), at: s} + } + ip[i] = ip4.v4(0) + ip[i+1] = ip4.v4(1) + ip[i+2] = ip4.v4(2) + ip[i+3] = ip4.v4(3) + s = "" + i += 4 + break + } + + // Save this 16-bit chunk. + ip[i] = byte(acc >> 8) + ip[i+1] = byte(acc) + i += 2 + + // Stop at end of string. + s = s[off:] + if len(s) == 0 { + break + } + + // Otherwise must be followed by colon and more. + if s[0] != ':' { + return Addr{}, parseAddrError{in: in, msg: "unexpected character, want colon", at: s} + } else if len(s) == 1 { + return Addr{}, parseAddrError{in: in, msg: "colon must be followed by more characters", at: s} + } + s = s[1:] + + // Look for ellipsis. + if s[0] == ':' { + if ellipsis >= 0 { // already have one + return Addr{}, parseAddrError{in: in, msg: "multiple :: in address", at: s} + } + ellipsis = i + s = s[1:] + if len(s) == 0 { // can be at end + break + } + } + } + + // Must have used entire string. + if len(s) != 0 { + return Addr{}, parseAddrError{in: in, msg: "trailing garbage after address", at: s} + } + + // If didn't parse enough, expand ellipsis. + if i < 16 { + if ellipsis < 0 { + return Addr{}, parseAddrError{in: in, msg: "address string too short"} + } + n := 16 - i + for j := i - 1; j >= ellipsis; j-- { + ip[j+n] = ip[j] + } + for j := ellipsis + n - 1; j >= ellipsis; j-- { + ip[j] = 0 + } + } else if ellipsis >= 0 { + // Ellipsis must represent at least one 0 group. + return Addr{}, parseAddrError{in: in, msg: "the :: must expand to at least one field of zeros"} + } + return AddrFrom16(ip).WithZone(zone), nil +} + +// AddrFromSlice parses the 4- or 16-byte byte slice as an IPv4 or IPv6 address. +// Note that a net.IP can be passed directly as the []byte argument. +// If slice's length is not 4 or 16, AddrFromSlice returns Addr{}, false. +func AddrFromSlice(slice []byte) (ip Addr, ok bool) { + switch len(slice) { + case 4: + return AddrFrom4(*(*[4]byte)(slice)), true + case 16: + return ipv6Slice(slice), true + } + return Addr{}, false +} + +// v4 returns the i'th byte of ip. If ip is not an IPv4, v4 returns +// unspecified garbage. +func (ip Addr) v4(i uint8) uint8 { + return uint8(ip.addr.lo >> ((3 - i) * 8)) +} + +// v6 returns the i'th byte of ip. If ip is an IPv4 address, this +// accesses the IPv4-mapped IPv6 address form of the IP. +func (ip Addr) v6(i uint8) uint8 { + return uint8(*(ip.addr.halves()[(i/8)%2]) >> ((7 - i%8) * 8)) +} + +// v6u16 returns the i'th 16-bit word of ip. If ip is an IPv4 address, +// this accesses the IPv4-mapped IPv6 address form of the IP. +func (ip Addr) v6u16(i uint8) uint16 { + return uint16(*(ip.addr.halves()[(i/4)%2]) >> ((3 - i%4) * 16)) +} + +// isZero reports whether ip is the zero value of the IP type. +// The zero value is not a valid IP address of any type. +// +// Note that "0.0.0.0" and "::" are not the zero value. Use IsUnspecified to +// check for these values instead. +func (ip Addr) isZero() bool { + // Faster than comparing ip == Addr{}, but effectively equivalent, + // as there's no way to make an IP with a nil z from this package. + return ip.z == z0 +} + +// IsValid reports whether the Addr is an initialized address (not the zero Addr). +// +// Note that "0.0.0.0" and "::" are both valid values. +func (ip Addr) IsValid() bool { return ip.z != z0 } + +// BitLen returns the number of bits in the IP address: +// 128 for IPv6, 32 for IPv4, and 0 for the zero Addr. +// +// Note that IPv4-mapped IPv6 addresses are considered IPv6 addresses +// and therefore have bit length 128. +func (ip Addr) BitLen() int { + switch ip.z { + case z0: + return 0 + case z4: + return 32 + } + return 128 +} + +// Zone returns ip's IPv6 scoped addressing zone, if any. +func (ip Addr) Zone() string { + if ip.z == nil { + return "" + } + zone, _ := ip.z.Get().(string) + return zone +} + +// Compare returns an integer comparing two IPs. +// The result will be 0 if ip == ip2, -1 if ip < ip2, and +1 if ip > ip2. +// The definition of "less than" is the same as the Less method. +func (ip Addr) Compare(ip2 Addr) int { + f1, f2 := ip.BitLen(), ip2.BitLen() + if f1 < f2 { + return -1 + } + if f1 > f2 { + return 1 + } + hi1, hi2 := ip.addr.hi, ip2.addr.hi + if hi1 < hi2 { + return -1 + } + if hi1 > hi2 { + return 1 + } + lo1, lo2 := ip.addr.lo, ip2.addr.lo + if lo1 < lo2 { + return -1 + } + if lo1 > lo2 { + return 1 + } + if ip.Is6() { + za, zb := ip.Zone(), ip2.Zone() + if za < zb { + return -1 + } + if za > zb { + return 1 + } + } + return 0 +} + +// Less reports whether ip sorts before ip2. +// IP addresses sort first by length, then their address. +// IPv6 addresses with zones sort just after the same address without a zone. +func (ip Addr) Less(ip2 Addr) bool { return ip.Compare(ip2) == -1 } + +func (ip Addr) lessOrEq(ip2 Addr) bool { return ip.Compare(ip2) <= 0 } + +// ipZone returns the standard library net.IP from ip, as well +// as the zone. +// The optional reuse IP provides memory to reuse. +func (ip Addr) ipZone(reuse []byte) (stdIP []byte, zone string) { + base := reuse[:0] + switch { + case ip.z == z0: + return nil, "" + case ip.Is4(): + a4 := ip.As4() + return append(base, a4[:]...), "" + default: + a16 := ip.As16() + return append(base, a16[:]...), ip.Zone() + } +} + +// IPAddrParts returns the net.IPAddr representation of an Addr. +// +// The slice will be nil if ip is the zero Addr. +// The zone is the empty string if there is no zone. +func (ip Addr) IPAddrParts() (slice []byte, zone string) { + return ip.ipZone(nil) +} + +// Is4 reports whether ip is an IPv4 address. +// +// It returns false for IP4-mapped IPv6 addresses. See IP.Unmap. +func (ip Addr) Is4() bool { + return ip.z == z4 +} + +// Is4In6 reports whether ip is an IPv4-mapped IPv6 address. +func (ip Addr) Is4In6() bool { + return ip.Is6() && ip.addr.hi == 0 && ip.addr.lo>>32 == 0xffff +} + +// Is6 reports whether ip is an IPv6 address, including IPv4-mapped +// IPv6 addresses. +func (ip Addr) Is6() bool { + return ip.z != z0 && ip.z != z4 +} + +// Unmap returns ip with any IPv4-mapped IPv6 address prefix removed. +// +// That is, if ip is an IPv6 address wrapping an IPv4 adddress, it +// returns the wrapped IPv4 address. Otherwise it returns ip unmodified. +func (ip Addr) Unmap() Addr { + if ip.Is4In6() { + ip.z = z4 + } + return ip +} + +// WithZone returns an IP that's the same as ip but with the provided +// zone. If zone is empty, the zone is removed. If ip is an IPv4 +// address, WithZone is a no-op and returns ip unchanged. +func (ip Addr) WithZone(zone string) Addr { + if !ip.Is6() { + return ip + } + if zone == "" { + ip.z = z6noz + return ip + } + ip.z = intern.GetByString(zone) + return ip +} + +// withoutZone unconditionally strips the zone from IP. +// It's similar to WithZone, but small enough to be inlinable. +func (ip Addr) withoutZone() Addr { + if !ip.Is6() { + return ip + } + ip.z = z6noz + return ip +} + +// hasZone reports whether IP has an IPv6 zone. +func (ip Addr) hasZone() bool { + return ip.z != z0 && ip.z != z4 && ip.z != z6noz +} + +// IsLinkLocalUnicast reports whether ip is a link-local unicast address. +func (ip Addr) IsLinkLocalUnicast() bool { + // Dynamic Configuration of IPv4 Link-Local Addresses + // https://datatracker.ietf.org/doc/html/rfc3927#section-2.1 + if ip.Is4() { + return ip.v4(0) == 169 && ip.v4(1) == 254 + } + // IP Version 6 Addressing Architecture (2.4 Address Type Identification) + // https://datatracker.ietf.org/doc/html/rfc4291#section-2.4 + if ip.Is6() { + return ip.v6u16(0)&0xffc0 == 0xfe80 + } + return false // zero value +} + +// IsLoopback reports whether ip is a loopback address. +func (ip Addr) IsLoopback() bool { + // Requirements for Internet Hosts -- Communication Layers (3.2.1.3 Addressing) + // https://datatracker.ietf.org/doc/html/rfc1122#section-3.2.1.3 + if ip.Is4() { + return ip.v4(0) == 127 + } + // IP Version 6 Addressing Architecture (2.4 Address Type Identification) + // https://datatracker.ietf.org/doc/html/rfc4291#section-2.4 + if ip.Is6() { + return ip.addr.hi == 0 && ip.addr.lo == 1 + } + return false // zero value +} + +// IsMulticast reports whether ip is a multicast address. +func (ip Addr) IsMulticast() bool { + // Host Extensions for IP Multicasting (4. HOST GROUP ADDRESSES) + // https://datatracker.ietf.org/doc/html/rfc1112#section-4 + if ip.Is4() { + return ip.v4(0)&0xf0 == 0xe0 + } + // IP Version 6 Addressing Architecture (2.4 Address Type Identification) + // https://datatracker.ietf.org/doc/html/rfc4291#section-2.4 + if ip.Is6() { + return ip.addr.hi>>(64-8) == 0xff // ip.v6(0) == 0xff + } + return false // zero value +} + +// IsInterfaceLocalMulticast reports whether ip is an IPv6 interface-local +// multicast address. +func (ip Addr) IsInterfaceLocalMulticast() bool { + // IPv6 Addressing Architecture (2.7.1. Pre-Defined Multicast Addresses) + // https://datatracker.ietf.org/doc/html/rfc4291#section-2.7.1 + if ip.Is6() { + return ip.v6u16(0)&0xff0f == 0xff01 + } + return false // zero value +} + +// IsLinkLocalMulticast reports whether ip is a link-local multicast address. +func (ip Addr) IsLinkLocalMulticast() bool { + // IPv4 Multicast Guidelines (4. Local Network Control Block (224.0.0/24)) + // https://datatracker.ietf.org/doc/html/rfc5771#section-4 + if ip.Is4() { + return ip.v4(0) == 224 && ip.v4(1) == 0 && ip.v4(2) == 0 + } + // IPv6 Addressing Architecture (2.7.1. Pre-Defined Multicast Addresses) + // https://datatracker.ietf.org/doc/html/rfc4291#section-2.7.1 + if ip.Is6() { + return ip.v6u16(0)&0xff0f == 0xff02 + } + return false // zero value +} + +// IsGlobalUnicast reports whether ip is a global unicast address. +// +// It returns true for IPv6 addresses which fall outside of the current +// IANA-allocated 2000::/3 global unicast space, with the exception of the +// link-local address space. It also returns true even if ip is in the IPv4 +// private address space or IPv6 unique local address space. +// It returns false for the zero Addr. +// +// For reference, see RFC 1122, RFC 4291, and RFC 4632. +func (ip Addr) IsGlobalUnicast() bool { + if ip.z == z0 { + // Invalid or zero-value. + return false + } + + // Match package net's IsGlobalUnicast logic. Notably private IPv4 addresses + // and ULA IPv6 addresses are still considered "global unicast". + if ip.Is4() && (ip == AddrFrom4([4]byte{}) || ip == AddrFrom4([4]byte{255, 255, 255, 255})) { + return false + } + + return ip != IPv6Unspecified() && + !ip.IsLoopback() && + !ip.IsMulticast() && + !ip.IsLinkLocalUnicast() +} + +// IsPrivate reports whether ip is a private address, according to RFC 1918 +// (IPv4 addresses) and RFC 4193 (IPv6 addresses). That is, it reports whether +// ip is in 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, or fc00::/7. This is the +// same as net.IP.IsPrivate. +func (ip Addr) IsPrivate() bool { + // Match the stdlib's IsPrivate logic. + if ip.Is4() { + // RFC 1918 allocates 10.0.0.0/8, 172.16.0.0/12, and 192.168.0.0/16 as + // private IPv4 address subnets. + return ip.v4(0) == 10 || + (ip.v4(0) == 172 && ip.v4(1)&0xf0 == 16) || + (ip.v4(0) == 192 && ip.v4(1) == 168) + } + + if ip.Is6() { + // RFC 4193 allocates fc00::/7 as the unique local unicast IPv6 address + // subnet. + return ip.v6(0)&0xfe == 0xfc + } + + return false // zero value +} + +// IsUnspecified reports whether ip is an unspecified address, either the IPv4 +// address "0.0.0.0" or the IPv6 address "::". +// +// Note that the zero Addr is not an unspecified address. +func (ip Addr) IsUnspecified() bool { + return ip == AddrFrom4([4]byte{}) || ip == IPv6Unspecified() +} + +// Prefix keeps only the top b bits of IP, producing a Prefix +// of the specified length. +// If ip is a zero Addr, Prefix always returns a zero Prefix and a nil error. +// Otherwise, if bits is less than zero or greater than ip.BitLen(), +// Prefix returns an error. +func (ip Addr) Prefix(b int) (Prefix, error) { + if b < 0 { + return Prefix{}, errors.New("negative Prefix bits") + } + effectiveBits := b + switch ip.z { + case z0: + return Prefix{}, nil + case z4: + if b > 32 { + return Prefix{}, errors.New("prefix length " + itoa.Itoa(b) + " too large for IPv4") + } + effectiveBits += 96 + default: + if b > 128 { + return Prefix{}, errors.New("prefix length " + itoa.Itoa(b) + " too large for IPv6") + } + } + ip.addr = ip.addr.and(mask6(effectiveBits)) + return PrefixFrom(ip, b), nil +} + +const ( + netIPv4len = 4 + netIPv6len = 16 +) + +// As16 returns the IP address in its 16-byte representation. +// IPv4 addresses are returned in their v6-mapped form. +// IPv6 addresses with zones are returned without their zone (use the +// Zone method to get it). +// The ip zero value returns all zeroes. +func (ip Addr) As16() (a16 [16]byte) { + bePutUint64(a16[:8], ip.addr.hi) + bePutUint64(a16[8:], ip.addr.lo) + return a16 +} + +// As4 returns an IPv4 or IPv4-in-IPv6 address in its 4-byte representation. +// If ip is the zero Addr or an IPv6 address, As4 panics. +// Note that 0.0.0.0 is not the zero Addr. +func (ip Addr) As4() (a4 [4]byte) { + if ip.z == z4 || ip.Is4In6() { + bePutUint32(a4[:], uint32(ip.addr.lo)) + return a4 + } + if ip.z == z0 { + panic("As4 called on IP zero value") + } + panic("As4 called on IPv6 address") +} + +// Next returns the address following ip. +// If there is none, it returns the zero Addr. +func (ip Addr) Next() Addr { + ip.addr = ip.addr.addOne() + if ip.Is4() { + if uint32(ip.addr.lo) == 0 { + // Overflowed. + return Addr{} + } + } else { + if ip.addr.isZero() { + // Overflowed + return Addr{} + } + } + return ip +} + +// Prev returns the IP before ip. +// If there is none, it returns the IP zero value. +func (ip Addr) Prev() Addr { + if ip.Is4() { + if uint32(ip.addr.lo) == 0 { + return Addr{} + } + } else if ip.addr.isZero() { + return Addr{} + } + ip.addr = ip.addr.subOne() + return ip +} + +// String returns the string form of the IP address ip. +// It returns one of 5 forms: +// +// - "invalid IP", if ip is the zero Addr +// - IPv4 dotted decimal ("192.0.2.1") +// - IPv6 ("2001:db8::1") +// - "::ffff:1.2.3.4" (if Is4In6) +// - IPv6 with zone ("fe80:db8::1%eth0") +// +// Note that unlike package net's IP.String method, +// IP4-mapped IPv6 addresses format with a "::ffff:" +// prefix before the dotted quad. +func (ip Addr) String() string { + switch ip.z { + case z0: + return "invalid IP" + case z4: + return ip.string4() + default: + if ip.Is4In6() { + // TODO(bradfitz): this could alloc less. + return "::ffff:" + ip.Unmap().String() + } + return ip.string6() + } +} + +// AppendTo appends a text encoding of ip, +// as generated by MarshalText, +// to b and returns the extended buffer. +func (ip Addr) AppendTo(b []byte) []byte { + switch ip.z { + case z0: + return b + case z4: + return ip.appendTo4(b) + default: + if ip.Is4In6() { + b = append(b, "::ffff:"...) + return ip.Unmap().appendTo4(b) + } + return ip.appendTo6(b) + } +} + +// digits is a string of the hex digits from 0 to f. It's used in +// appendDecimal and appendHex to format IP addresses. +const digits = "0123456789abcdef" + +// appendDecimal appends the decimal string representation of x to b. +func appendDecimal(b []byte, x uint8) []byte { + // Using this function rather than strconv.AppendUint makes IPv4 + // string building 2x faster. + + if x >= 100 { + b = append(b, digits[x/100]) + } + if x >= 10 { + b = append(b, digits[x/10%10]) + } + return append(b, digits[x%10]) +} + +// appendHex appends the hex string representation of x to b. +func appendHex(b []byte, x uint16) []byte { + // Using this function rather than strconv.AppendUint makes IPv6 + // string building 2x faster. + + if x >= 0x1000 { + b = append(b, digits[x>>12]) + } + if x >= 0x100 { + b = append(b, digits[x>>8&0xf]) + } + if x >= 0x10 { + b = append(b, digits[x>>4&0xf]) + } + return append(b, digits[x&0xf]) +} + +// appendHexPad appends the fully padded hex string representation of x to b. +func appendHexPad(b []byte, x uint16) []byte { + return append(b, digits[x>>12], digits[x>>8&0xf], digits[x>>4&0xf], digits[x&0xf]) +} + +func (ip Addr) string4() string { + const max = len("255.255.255.255") + ret := make([]byte, 0, max) + ret = ip.appendTo4(ret) + return string(ret) +} + +func (ip Addr) appendTo4(ret []byte) []byte { + ret = appendDecimal(ret, ip.v4(0)) + ret = append(ret, '.') + ret = appendDecimal(ret, ip.v4(1)) + ret = append(ret, '.') + ret = appendDecimal(ret, ip.v4(2)) + ret = append(ret, '.') + ret = appendDecimal(ret, ip.v4(3)) + return ret +} + +// string6 formats ip in IPv6 textual representation. It follows the +// guidelines in section 4 of RFC 5952 +// (https://tools.ietf.org/html/rfc5952#section-4): no unnecessary +// zeros, use :: to elide the longest run of zeros, and don't use :: +// to compact a single zero field. +func (ip Addr) string6() string { + // Use a zone with a "plausibly long" name, so that most zone-ful + // IP addresses won't require additional allocation. + // + // The compiler does a cool optimization here, where ret ends up + // stack-allocated and so the only allocation this function does + // is to construct the returned string. As such, it's okay to be a + // bit greedy here, size-wise. + const max = len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0") + ret := make([]byte, 0, max) + ret = ip.appendTo6(ret) + return string(ret) +} + +func (ip Addr) appendTo6(ret []byte) []byte { + zeroStart, zeroEnd := uint8(255), uint8(255) + for i := uint8(0); i < 8; i++ { + j := i + for j < 8 && ip.v6u16(j) == 0 { + j++ + } + if l := j - i; l >= 2 && l > zeroEnd-zeroStart { + zeroStart, zeroEnd = i, j + } + } + + for i := uint8(0); i < 8; i++ { + if i == zeroStart { + ret = append(ret, ':', ':') + i = zeroEnd + if i >= 8 { + break + } + } else if i > 0 { + ret = append(ret, ':') + } + + ret = appendHex(ret, ip.v6u16(i)) + } + + if ip.z != z6noz { + ret = append(ret, '%') + ret = append(ret, ip.Zone()...) + } + return ret +} + +// StringExpanded is like String but IPv6 addresses are expanded with leading +// zeroes and no "::" compression. For example, "2001:db8::1" becomes +// "2001:0db8:0000:0000:0000:0000:0000:0001". +func (ip Addr) StringExpanded() string { + switch ip.z { + case z0, z4: + return ip.String() + } + + const size = len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff") + ret := make([]byte, 0, size) + for i := uint8(0); i < 8; i++ { + if i > 0 { + ret = append(ret, ':') + } + + ret = appendHexPad(ret, ip.v6u16(i)) + } + + if ip.z != z6noz { + // The addition of a zone will cause a second allocation, but when there + // is no zone the ret slice will be stack allocated. + ret = append(ret, '%') + ret = append(ret, ip.Zone()...) + } + return string(ret) +} + +// MarshalText implements the encoding.TextMarshaler interface, +// The encoding is the same as returned by String, with one exception: +// If ip is the zero Addr, the encoding is the empty string. +func (ip Addr) MarshalText() ([]byte, error) { + switch ip.z { + case z0: + return []byte(""), nil + case z4: + max := len("255.255.255.255") + b := make([]byte, 0, max) + return ip.appendTo4(b), nil + default: + max := len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0") + b := make([]byte, 0, max) + if ip.Is4In6() { + b = append(b, "::ffff:"...) + return ip.Unmap().appendTo4(b), nil + } + return ip.appendTo6(b), nil + } +} + +// UnmarshalText implements the encoding.TextUnmarshaler interface. +// The IP address is expected in a form accepted by ParseAddr. +// +// If text is empty, UnmarshalText sets *ip to the zero Addr and +// returns no error. +func (ip *Addr) UnmarshalText(text []byte) error { + if len(text) == 0 { + *ip = Addr{} + return nil + } + var err error + *ip, err = ParseAddr(string(text)) + return err +} + +// MarshalBinary implements the encoding.BinaryMarshaler interface. +// It returns a zero-length slice for the zero Addr, +// the 4-byte form for an IPv4 address, +// and the 16-byte form with zone appended for an IPv6 address. +func (ip Addr) MarshalBinary() ([]byte, error) { + switch ip.z { + case z0: + return nil, nil + case z4: + b := ip.As4() + return b[:], nil + default: + b16 := ip.As16() + b := b16[:] + if z := ip.Zone(); z != "" { + b = append(b, []byte(z)...) + } + return b, nil + } +} + +// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface. +// It expects data in the form generated by MarshalBinary. +func (ip *Addr) UnmarshalBinary(b []byte) error { + n := len(b) + switch { + case n == 0: + *ip = Addr{} + return nil + case n == 4: + *ip = AddrFrom4(*(*[4]byte)(b)) + return nil + case n == 16: + *ip = ipv6Slice(b) + return nil + case n > 16: + *ip = ipv6Slice(b[:16]).WithZone(string(b[16:])) + return nil + } + return errors.New("unexpected slice size") +} + +// AddrPort is an IP and a port number. +type AddrPort struct { + ip Addr + port uint16 +} + +// AddrPortFrom returns an AddrPort with the provided IP and port. +// It does not allocate. +func AddrPortFrom(ip Addr, port uint16) AddrPort { return AddrPort{ip: ip, port: port} } + +// Addr returns p's IP address. +func (p AddrPort) Addr() Addr { return p.ip } + +// Port returns p's port. +func (p AddrPort) Port() uint16 { return p.port } + +// splitAddrPort splits s into an IP address string and a port +// string. It splits strings shaped like "foo:bar" or "[foo]:bar", +// without further validating the substrings. v6 indicates whether the +// ip string should parse as an IPv6 address or an IPv4 address, in +// order for s to be a valid ip:port string. +func splitAddrPort(s string) (ip, port string, v6 bool, err error) { + i := stringsLastIndexByte(s, ':') + if i == -1 { + return "", "", false, errors.New("not an ip:port") + } + + ip, port = s[:i], s[i+1:] + if len(ip) == 0 { + return "", "", false, errors.New("no IP") + } + if len(port) == 0 { + return "", "", false, errors.New("no port") + } + if ip[0] == '[' { + if len(ip) < 2 || ip[len(ip)-1] != ']' { + return "", "", false, errors.New("missing ]") + } + ip = ip[1 : len(ip)-1] + v6 = true + } + + return ip, port, v6, nil +} + +// ParseAddrPort parses s as an AddrPort. +// +// It doesn't do any name resolution: both the address and the port +// must be numeric. +func ParseAddrPort(s string) (AddrPort, error) { + var ipp AddrPort + ip, port, v6, err := splitAddrPort(s) + if err != nil { + return ipp, err + } + port16, err := strconv.ParseUint(port, 10, 16) + if err != nil { + return ipp, errors.New("invalid port " + strconv.Quote(port) + " parsing " + strconv.Quote(s)) + } + ipp.port = uint16(port16) + ipp.ip, err = ParseAddr(ip) + if err != nil { + return AddrPort{}, err + } + if v6 && ipp.ip.Is4() { + return AddrPort{}, errors.New("invalid ip:port " + strconv.Quote(s) + ", square brackets can only be used with IPv6 addresses") + } else if !v6 && ipp.ip.Is6() { + return AddrPort{}, errors.New("invalid ip:port " + strconv.Quote(s) + ", IPv6 addresses must be surrounded by square brackets") + } + return ipp, nil +} + +// MustParseAddrPort calls ParseAddrPort(s) and panics on error. +// It is intended for use in tests with hard-coded strings. +func MustParseAddrPort(s string) AddrPort { + ip, err := ParseAddrPort(s) + if err != nil { + panic(err) + } + return ip +} + +// isZero reports whether p is the zero AddrPort. +func (p AddrPort) isZero() bool { return p == AddrPort{} } + +// IsValid reports whether p.IP() is valid. +// All ports are valid, including zero. +func (p AddrPort) IsValid() bool { return p.ip.IsValid() } + +func (p AddrPort) String() string { + switch p.ip.z { + case z0: + return "invalid AddrPort" + case z4: + a := p.ip.As4() + buf := make([]byte, 0, 21) + for i := range a { + buf = strconv.AppendUint(buf, uint64(a[i]), 10) + buf = append(buf, "...:"[i]) + } + buf = strconv.AppendUint(buf, uint64(p.port), 10) + return string(buf) + default: + // TODO: this could be more efficient allocation-wise: + return joinHostPort(p.ip.String(), itoa.Itoa(int(p.port))) + } +} + +func joinHostPort(host, port string) string { + // We assume that host is a literal IPv6 address if host has + // colons. + if bytealg.IndexByteString(host, ':') >= 0 { + return "[" + host + "]:" + port + } + return host + ":" + port +} + +// AppendTo appends a text encoding of p, +// as generated by MarshalText, +// to b and returns the extended buffer. +func (p AddrPort) AppendTo(b []byte) []byte { + switch p.ip.z { + case z0: + return b + case z4: + b = p.ip.appendTo4(b) + default: + b = append(b, '[') + b = p.ip.appendTo6(b) + b = append(b, ']') + } + b = append(b, ':') + b = strconv.AppendInt(b, int64(p.port), 10) + return b +} + +// MarshalText implements the encoding.TextMarshaler interface. The +// encoding is the same as returned by String, with one exception: if +// p.Addr() is the zero Addr, the encoding is the empty string. +func (p AddrPort) MarshalText() ([]byte, error) { + var max int + switch p.ip.z { + case z0: + case z4: + max = len("255.255.255.255:65535") + default: + max = len("[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0]:65535") + } + b := make([]byte, 0, max) + b = p.AppendTo(b) + return b, nil +} + +// UnmarshalText implements the encoding.TextUnmarshaler +// interface. The AddrPort is expected in a form +// generated by MarshalText or accepted by ParseAddrPort. +func (p *AddrPort) UnmarshalText(text []byte) error { + if len(text) == 0 { + *p = AddrPort{} + return nil + } + var err error + *p, err = ParseAddrPort(string(text)) + return err +} + +// Prefix is an IP address prefix (CIDR) representing an IP network. +// +// The first Bits() of Addr() are specified. The remaining bits match any address. +// The range of Bits() is [0,32] for IPv4 or [0,128] for IPv6. +type Prefix struct { + ip Addr + + // bits is logically a uint8 (storing [0,128]) but also + // encodes an "invalid" bit, currently represented by the + // invalidPrefixBits sentinel value. It could be packed into + // the uint8 more with more complicated expressions in the + // accessors, but the extra byte (in padding anyway) doesn't + // hurt and simplifies code below. + bits int16 +} + +// invalidPrefixBits is the Prefix.bits value used when PrefixFrom is +// outside the range of a uint8. It's returned as the int -1 in the +// public API. +const invalidPrefixBits = -1 + +// PrefixFrom returns a Prefix with the provided IP address and bit +// prefix length. +// +// It does not allocate. Unlike Addr.Prefix, PrefixFrom does not mask +// off the host bits of ip. +// +// If bits is less than zero or greater than ip.BitLen, Prefix.Bits +// will return an invalid value -1. +func PrefixFrom(ip Addr, bits int) Prefix { + if bits < 0 || bits > ip.BitLen() { + bits = invalidPrefixBits + } + b16 := int16(bits) + return Prefix{ + ip: ip.withoutZone(), + bits: b16, + } +} + +// Addr returns p's IP address. +func (p Prefix) Addr() Addr { return p.ip } + +// Bits returns p's prefix length. +// +// It reports -1 if invalid. +func (p Prefix) Bits() int { return int(p.bits) } + +// IsValid reports whether p.Bits() has a valid range for p.IP(). +// If p.Addr() is the zero Addr, IsValid returns false. +// Note that if p is the zero Prefix, then p.IsValid() == false. +func (p Prefix) IsValid() bool { return !p.ip.isZero() && p.bits >= 0 && int(p.bits) <= p.ip.BitLen() } + +func (p Prefix) isZero() bool { return p == Prefix{} } + +// IsSingleIP reports whether p contains exactly one IP. +func (p Prefix) IsSingleIP() bool { return p.bits != 0 && int(p.bits) == p.ip.BitLen() } + +// ParsePrefix parses s as an IP address prefix. +// The string can be in the form "192.168.1.0/24" or "2001::db8::/32", +// the CIDR notation defined in RFC 4632 and RFC 4291. +// +// Note that masked address bits are not zeroed. Use Masked for that. +func ParsePrefix(s string) (Prefix, error) { + i := stringsLastIndexByte(s, '/') + if i < 0 { + return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + "): no '/'") + } + ip, err := ParseAddr(s[:i]) + if err != nil { + return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + "): " + err.Error()) + } + bitsStr := s[i+1:] + bits, err := strconv.Atoi(bitsStr) + if err != nil { + return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + ": bad bits after slash: " + strconv.Quote(bitsStr)) + } + maxBits := 32 + if ip.Is6() { + maxBits = 128 + } + if bits < 0 || bits > maxBits { + return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + ": prefix length out of range") + } + return PrefixFrom(ip, bits), nil +} + +// MustParsePrefix calls ParsePrefix(s) and panics on error. +// It is intended for use in tests with hard-coded strings. +func MustParsePrefix(s string) Prefix { + ip, err := ParsePrefix(s) + if err != nil { + panic(err) + } + return ip +} + +// Masked returns p in its canonical form, with all but the high +// p.Bits() bits of p.Addr() masked off. +// +// If p is zero or otherwise invalid, Masked returns the zero Prefix. +func (p Prefix) Masked() Prefix { + if m, err := p.ip.Prefix(int(p.bits)); err == nil { + return m + } + return Prefix{} +} + +// Contains reports whether the network p includes ip. +// +// An IPv4 address will not match an IPv6 prefix. +// A v6-mapped IPv6 address will not match an IPv4 prefix. +// A zero-value IP will not match any prefix. +// If ip has an IPv6 zone, Contains returns false, +// because Prefixes strip zones. +func (p Prefix) Contains(ip Addr) bool { + if !p.IsValid() || ip.hasZone() { + return false + } + if f1, f2 := p.ip.BitLen(), ip.BitLen(); f1 == 0 || f2 == 0 || f1 != f2 { + return false + } + if ip.Is4() { + // xor the IP addresses together; mismatched bits are now ones. + // Shift away the number of bits we don't care about. + // Shifts in Go are more efficient if the compiler can prove + // that the shift amount is smaller than the width of the shifted type (64 here). + // We know that p.bits is in the range 0..32 because p is Valid; + // the compiler doesn't know that, so mask with 63 to help it. + // Now truncate to 32 bits, because this is IPv4. + // If all the bits we care about are equal, the result will be zero. + return uint32((ip.addr.lo^p.ip.addr.lo)>>((32-p.bits)&63)) == 0 + } else { + // xor the IP addresses together. + // Mask away the bits we don't care about. + // If all the bits we care about are equal, the result will be zero. + return ip.addr.xor(p.ip.addr).and(mask6(int(p.bits))).isZero() + } +} + +// Overlaps reports whether p and o contain any IP addresses in common. +// +// If p and o are of different address families or either have a zero +// IP, it reports false. Like the Contains method, a prefix with a +// v6-mapped IPv4 IP is still treated as an IPv6 mask. +func (p Prefix) Overlaps(o Prefix) bool { + if !p.IsValid() || !o.IsValid() { + return false + } + if p == o { + return true + } + if p.ip.Is4() != o.ip.Is4() { + return false + } + var minBits int16 + if p.bits < o.bits { + minBits = p.bits + } else { + minBits = o.bits + } + if minBits == 0 { + return true + } + // One of these Prefix calls might look redundant, but we don't require + // that p and o values are normalized (via Prefix.Masked) first, + // so the Prefix call on the one that's already minBits serves to zero + // out any remaining bits in IP. + var err error + if p, err = p.ip.Prefix(int(minBits)); err != nil { + return false + } + if o, err = o.ip.Prefix(int(minBits)); err != nil { + return false + } + return p.ip == o.ip +} + +// AppendTo appends a text encoding of p, +// as generated by MarshalText, +// to b and returns the extended buffer. +func (p Prefix) AppendTo(b []byte) []byte { + if p.isZero() { + return b + } + if !p.IsValid() { + return append(b, "invalid Prefix"...) + } + + // p.ip is non-nil, because p is valid. + if p.ip.z == z4 { + b = p.ip.appendTo4(b) + } else { + b = p.ip.appendTo6(b) + } + + b = append(b, '/') + b = appendDecimal(b, uint8(p.bits)) + return b +} + +// MarshalText implements the encoding.TextMarshaler interface, +// The encoding is the same as returned by String, with one exception: +// If p is the zero value, the encoding is the empty string. +func (p Prefix) MarshalText() ([]byte, error) { + var max int + switch p.ip.z { + case z0: + case z4: + max = len("255.255.255.255/32") + default: + max = len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0/128") + } + b := make([]byte, 0, max) + b = p.AppendTo(b) + return b, nil +} + +// UnmarshalText implements the encoding.TextUnmarshaler interface. +// The IP address is expected in a form accepted by ParsePrefix +// or generated by MarshalText. +func (p *Prefix) UnmarshalText(text []byte) error { + if len(text) == 0 { + *p = Prefix{} + return nil + } + var err error + *p, err = ParsePrefix(string(text)) + return err +} + +// String returns the CIDR notation of p: "/". +func (p Prefix) String() string { + if !p.IsValid() { + return "invalid Prefix" + } + return p.ip.String() + "/" + itoa.Itoa(int(p.bits)) +} diff --git a/src/net/netip/netip_pkg_test.go b/src/net/netip/netip_pkg_test.go new file mode 100644 index 0000000000..f5cd9ee86d --- /dev/null +++ b/src/net/netip/netip_pkg_test.go @@ -0,0 +1,359 @@ +// 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 netip + +import ( + "bytes" + "encoding" + "encoding/json" + "strings" + "testing" +) + +var ( + mustPrefix = MustParsePrefix + mustIP = MustParseAddr +) + +func TestPrefixValid(t *testing.T) { + v4 := MustParseAddr("1.2.3.4") + v6 := MustParseAddr("::1") + tests := []struct { + ipp Prefix + want bool + }{ + {Prefix{v4, -2}, false}, + {Prefix{v4, -1}, false}, + {Prefix{v4, 0}, true}, + {Prefix{v4, 32}, true}, + {Prefix{v4, 33}, false}, + + {Prefix{v6, -2}, false}, + {Prefix{v6, -1}, false}, + {Prefix{v6, 0}, true}, + {Prefix{v6, 32}, true}, + {Prefix{v6, 128}, true}, + {Prefix{v6, 129}, false}, + + {Prefix{Addr{}, -2}, false}, + {Prefix{Addr{}, -1}, false}, + {Prefix{Addr{}, 0}, false}, + {Prefix{Addr{}, 32}, false}, + {Prefix{Addr{}, 128}, false}, + } + for _, tt := range tests { + got := tt.ipp.IsValid() + if got != tt.want { + t.Errorf("(%v).IsValid() = %v want %v", tt.ipp, got, tt.want) + } + } +} + +var nextPrevTests = []struct { + ip Addr + next Addr + prev Addr +}{ + {mustIP("10.0.0.1"), mustIP("10.0.0.2"), mustIP("10.0.0.0")}, + {mustIP("10.0.0.255"), mustIP("10.0.1.0"), mustIP("10.0.0.254")}, + {mustIP("127.0.0.1"), mustIP("127.0.0.2"), mustIP("127.0.0.0")}, + {mustIP("254.255.255.255"), mustIP("255.0.0.0"), mustIP("254.255.255.254")}, + {mustIP("255.255.255.255"), Addr{}, mustIP("255.255.255.254")}, + {mustIP("0.0.0.0"), mustIP("0.0.0.1"), Addr{}}, + {mustIP("::"), mustIP("::1"), Addr{}}, + {mustIP("::%x"), mustIP("::1%x"), Addr{}}, + {mustIP("::1"), mustIP("::2"), mustIP("::")}, + {mustIP("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"), Addr{}, mustIP("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe")}, +} + +func TestIPNextPrev(t *testing.T) { + doNextPrev(t) + + for _, ip := range []Addr{ + mustIP("0.0.0.0"), + mustIP("::"), + } { + got := ip.Prev() + if !got.isZero() { + t.Errorf("IP(%v).Prev = %v; want zero", ip, got) + } + } + + var allFF [16]byte + for i := range allFF { + allFF[i] = 0xff + } + + for _, ip := range []Addr{ + mustIP("255.255.255.255"), + AddrFrom16(allFF), + } { + got := ip.Next() + if !got.isZero() { + t.Errorf("IP(%v).Next = %v; want zero", ip, got) + } + } +} + +func BenchmarkIPNextPrev(b *testing.B) { + for i := 0; i < b.N; i++ { + doNextPrev(b) + } +} + +func doNextPrev(t testing.TB) { + for _, tt := range nextPrevTests { + gnext, gprev := tt.ip.Next(), tt.ip.Prev() + if gnext != tt.next { + t.Errorf("IP(%v).Next = %v; want %v", tt.ip, gnext, tt.next) + } + if gprev != tt.prev { + t.Errorf("IP(%v).Prev = %v; want %v", tt.ip, gprev, tt.prev) + } + if !tt.ip.Next().isZero() && tt.ip.Next().Prev() != tt.ip { + t.Errorf("IP(%v).Next.Prev = %v; want %v", tt.ip, tt.ip.Next().Prev(), tt.ip) + } + if !tt.ip.Prev().isZero() && tt.ip.Prev().Next() != tt.ip { + t.Errorf("IP(%v).Prev.Next = %v; want %v", tt.ip, tt.ip.Prev().Next(), tt.ip) + } + } +} + +func TestIPBitLen(t *testing.T) { + tests := []struct { + ip Addr + want int + }{ + {Addr{}, 0}, + {mustIP("0.0.0.0"), 32}, + {mustIP("10.0.0.1"), 32}, + {mustIP("::"), 128}, + {mustIP("fed0::1"), 128}, + {mustIP("::ffff:10.0.0.1"), 128}, + } + for _, tt := range tests { + got := tt.ip.BitLen() + if got != tt.want { + t.Errorf("BitLen(%v) = %d; want %d", tt.ip, got, tt.want) + } + } +} + +func TestPrefixContains(t *testing.T) { + tests := []struct { + ipp Prefix + ip Addr + want bool + }{ + {mustPrefix("9.8.7.6/0"), mustIP("9.8.7.6"), true}, + {mustPrefix("9.8.7.6/16"), mustIP("9.8.7.6"), true}, + {mustPrefix("9.8.7.6/16"), mustIP("9.8.6.4"), true}, + {mustPrefix("9.8.7.6/16"), mustIP("9.9.7.6"), false}, + {mustPrefix("9.8.7.6/32"), mustIP("9.8.7.6"), true}, + {mustPrefix("9.8.7.6/32"), mustIP("9.8.7.7"), false}, + {mustPrefix("9.8.7.6/32"), mustIP("9.8.7.7"), false}, + {mustPrefix("::1/0"), mustIP("::1"), true}, + {mustPrefix("::1/0"), mustIP("::2"), true}, + {mustPrefix("::1/127"), mustIP("::1"), true}, + {mustPrefix("::1/127"), mustIP("::2"), false}, + {mustPrefix("::1/128"), mustIP("::1"), true}, + {mustPrefix("::1/127"), mustIP("::2"), false}, + // zones support + {mustPrefix("::1%a/128"), mustIP("::1"), true}, // prefix zones are stripped... + {mustPrefix("::1%a/128"), mustIP("::1%a"), false}, // but ip zones are not + // invalid IP + {mustPrefix("::1/0"), Addr{}, false}, + {mustPrefix("1.2.3.4/0"), Addr{}, false}, + // invalid Prefix + {Prefix{mustIP("::1"), 129}, mustIP("::1"), false}, + {Prefix{mustIP("1.2.3.4"), 33}, mustIP("1.2.3.4"), false}, + {Prefix{Addr{}, 0}, mustIP("1.2.3.4"), false}, + {Prefix{Addr{}, 32}, mustIP("1.2.3.4"), false}, + {Prefix{Addr{}, 128}, mustIP("::1"), false}, + // wrong IP family + {mustPrefix("::1/0"), mustIP("1.2.3.4"), false}, + {mustPrefix("1.2.3.4/0"), mustIP("::1"), false}, + } + for _, tt := range tests { + got := tt.ipp.Contains(tt.ip) + if got != tt.want { + t.Errorf("(%v).Contains(%v) = %v want %v", tt.ipp, tt.ip, got, tt.want) + } + } +} + +func TestParseIPError(t *testing.T) { + tests := []struct { + ip string + errstr string + }{ + { + ip: "localhost", + }, + { + ip: "500.0.0.1", + errstr: "field has value >255", + }, + { + ip: "::gggg%eth0", + errstr: "must have at least one digit", + }, + { + ip: "fe80::1cc0:3e8c:119f:c2e1%", + errstr: "zone must be a non-empty string", + }, + { + ip: "%eth0", + errstr: "missing IPv6 address", + }, + } + for _, test := range tests { + t.Run(test.ip, func(t *testing.T) { + _, err := ParseAddr(test.ip) + if err == nil { + t.Fatal("no error") + } + if _, ok := err.(parseAddrError); !ok { + t.Errorf("error type is %T, want parseIPError", err) + } + if test.errstr == "" { + test.errstr = "unable to parse IP" + } + if got := err.Error(); !strings.Contains(got, test.errstr) { + t.Errorf("error is missing substring %q: %s", test.errstr, got) + } + }) + } +} + +func TestParseAddrPort(t *testing.T) { + tests := []struct { + in string + want AddrPort + wantErr bool + }{ + {in: "1.2.3.4:1234", want: AddrPort{mustIP("1.2.3.4"), 1234}}, + {in: "1.1.1.1:123456", wantErr: true}, + {in: "1.1.1.1:-123", wantErr: true}, + {in: "[::1]:1234", want: AddrPort{mustIP("::1"), 1234}}, + {in: "[1.2.3.4]:1234", wantErr: true}, + {in: "fe80::1:1234", wantErr: true}, + {in: ":0", wantErr: true}, // if we need to parse this form, there should be a separate function that explicitly allows it + } + for _, test := range tests { + t.Run(test.in, func(t *testing.T) { + got, err := ParseAddrPort(test.in) + if err != nil { + if test.wantErr { + return + } + t.Fatal(err) + } + if got != test.want { + t.Errorf("got %v; want %v", got, test.want) + } + if got.String() != test.in { + t.Errorf("String = %q; want %q", got.String(), test.in) + } + }) + + t.Run(test.in+"/AppendTo", func(t *testing.T) { + got, err := ParseAddrPort(test.in) + if err == nil { + testAppendToMarshal(t, got) + } + }) + + // TextMarshal and TextUnmarshal mostly behave like + // ParseAddrPort and String. Divergent behavior are handled in + // TestAddrPortMarshalUnmarshal. + t.Run(test.in+"/Marshal", func(t *testing.T) { + var got AddrPort + jsin := `"` + test.in + `"` + err := json.Unmarshal([]byte(jsin), &got) + if err != nil { + if test.wantErr { + return + } + t.Fatal(err) + } + if got != test.want { + t.Errorf("got %v; want %v", got, test.want) + } + gotb, err := json.Marshal(got) + if err != nil { + t.Fatal(err) + } + if string(gotb) != jsin { + t.Errorf("Marshal = %q; want %q", string(gotb), jsin) + } + }) + } +} + +func TestAddrPortMarshalUnmarshal(t *testing.T) { + tests := []struct { + in string + want AddrPort + }{ + {"", AddrPort{}}, + } + + for _, test := range tests { + t.Run(test.in, func(t *testing.T) { + orig := `"` + test.in + `"` + + var ipp AddrPort + if err := json.Unmarshal([]byte(orig), &ipp); err != nil { + t.Fatalf("failed to unmarshal: %v", err) + } + + ippb, err := json.Marshal(ipp) + if err != nil { + t.Fatalf("failed to marshal: %v", err) + } + + back := string(ippb) + if orig != back { + t.Errorf("Marshal = %q; want %q", back, orig) + } + + testAppendToMarshal(t, ipp) + }) + } +} + +type appendMarshaler interface { + encoding.TextMarshaler + AppendTo([]byte) []byte +} + +// testAppendToMarshal tests that x's AppendTo and MarshalText methods yield the same results. +// x's MarshalText method must not return an error. +func testAppendToMarshal(t *testing.T, x appendMarshaler) { + t.Helper() + m, err := x.MarshalText() + if err != nil { + t.Fatalf("(%v).MarshalText: %v", x, err) + } + a := make([]byte, 0, len(m)) + a = x.AppendTo(a) + if !bytes.Equal(m, a) { + t.Errorf("(%v).MarshalText = %q, (%v).AppendTo = %q", x, m, x, a) + } +} + +func TestIPv6Accessor(t *testing.T) { + var a [16]byte + for i := range a { + a[i] = uint8(i) + 1 + } + ip := AddrFrom16(a) + for i := range a { + if got, want := ip.v6(uint8(i)), uint8(i)+1; got != want { + t.Errorf("v6(%v) = %v; want %v", i, got, want) + } + } +} diff --git a/src/net/netip/netip_test.go b/src/net/netip/netip_test.go new file mode 100644 index 0000000000..c39b1ec201 --- /dev/null +++ b/src/net/netip/netip_test.go @@ -0,0 +1,1817 @@ +// 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 netip_test + +import ( + "bytes" + "encoding/json" + "flag" + "fmt" + "internal/intern" + "net" + . "net/netip" + "reflect" + "sort" + "strings" + "testing" +) + +var long = flag.Bool("long", false, "run long tests") + +type uint128 = Uint128 + +var ( + mustPrefix = MustParsePrefix + mustIP = MustParseAddr +) + +func TestParseAddr(t *testing.T) { + var validIPs = []struct { + in string + ip Addr // output of ParseAddr() + str string // output of String(). If "", use in. + wantErr string + }{ + // Basic zero IPv4 address. + { + in: "0.0.0.0", + ip: MkAddr(Mk128(0, 0xffff00000000), Z4), + }, + // Basic non-zero IPv4 address. + { + in: "192.168.140.255", + ip: MkAddr(Mk128(0, 0xffffc0a88cff), Z4), + }, + // IPv4 address in windows-style "print all the digits" form. + { + in: "010.000.015.001", + wantErr: `ParseAddr("010.000.015.001"): IPv4 field has octet with leading zero`, + }, + // IPv4 address with a silly amount of leading zeros. + { + in: "000001.00000002.00000003.000000004", + wantErr: `ParseAddr("000001.00000002.00000003.000000004"): IPv4 field has octet with leading zero`, + }, + // 4-in-6 with octet with leading zero + { + in: "::ffff:1.2.03.4", + wantErr: `ParseAddr("::ffff:1.2.03.4"): ParseAddr("1.2.03.4"): IPv4 field has octet with leading zero (at "1.2.03.4")`, + }, + // Basic zero IPv6 address. + { + in: "::", + ip: MkAddr(Mk128(0, 0), Z6noz), + }, + // Localhost IPv6. + { + in: "::1", + ip: MkAddr(Mk128(0, 1), Z6noz), + }, + // Fully expanded IPv6 address. + { + in: "fd7a:115c:a1e0:ab12:4843:cd96:626b:430b", + ip: MkAddr(Mk128(0xfd7a115ca1e0ab12, 0x4843cd96626b430b), Z6noz), + }, + // IPv6 with elided fields in the middle. + { + in: "fd7a:115c::626b:430b", + ip: MkAddr(Mk128(0xfd7a115c00000000, 0x00000000626b430b), Z6noz), + }, + // IPv6 with elided fields at the end. + { + in: "fd7a:115c:a1e0:ab12:4843:cd96::", + ip: MkAddr(Mk128(0xfd7a115ca1e0ab12, 0x4843cd9600000000), Z6noz), + }, + // IPv6 with single elided field at the end. + { + in: "fd7a:115c:a1e0:ab12:4843:cd96:626b::", + ip: MkAddr(Mk128(0xfd7a115ca1e0ab12, 0x4843cd96626b0000), Z6noz), + str: "fd7a:115c:a1e0:ab12:4843:cd96:626b:0", + }, + // IPv6 with single elided field in the middle. + { + in: "fd7a:115c:a1e0::4843:cd96:626b:430b", + ip: MkAddr(Mk128(0xfd7a115ca1e00000, 0x4843cd96626b430b), Z6noz), + str: "fd7a:115c:a1e0:0:4843:cd96:626b:430b", + }, + // IPv6 with the trailing 32 bits written as IPv4 dotted decimal. (4in6) + { + in: "::ffff:192.168.140.255", + ip: MkAddr(Mk128(0, 0x0000ffffc0a88cff), Z6noz), + str: "::ffff:192.168.140.255", + }, + // IPv6 with a zone specifier. + { + in: "fd7a:115c:a1e0:ab12:4843:cd96:626b:430b%eth0", + ip: MkAddr(Mk128(0xfd7a115ca1e0ab12, 0x4843cd96626b430b), intern.Get("eth0")), + }, + // IPv6 with dotted decimal and zone specifier. + { + in: "1:2::ffff:192.168.140.255%eth1", + ip: MkAddr(Mk128(0x0001000200000000, 0x0000ffffc0a88cff), intern.Get("eth1")), + str: "1:2::ffff:c0a8:8cff%eth1", + }, + // IPv6 with capital letters. + { + in: "FD9E:1A04:F01D::1", + ip: MkAddr(Mk128(0xfd9e1a04f01d0000, 0x1), Z6noz), + str: "fd9e:1a04:f01d::1", + }, + } + + for _, test := range validIPs { + t.Run(test.in, func(t *testing.T) { + got, err := ParseAddr(test.in) + if err != nil { + if err.Error() == test.wantErr { + return + } + t.Fatal(err) + } + if test.wantErr != "" { + t.Fatalf("wanted error %q; got none", test.wantErr) + } + if got != test.ip { + t.Errorf("got %#v, want %#v", got, test.ip) + } + + // Check that ParseAddr is a pure function. + got2, err := ParseAddr(test.in) + if err != nil { + t.Fatal(err) + } + if got != got2 { + t.Errorf("ParseAddr(%q) got 2 different results: %#v, %#v", test.in, got, got2) + } + + // Check that ParseAddr(ip.String()) is the identity function. + s := got.String() + got3, err := ParseAddr(s) + if err != nil { + t.Fatal(err) + } + if got != got3 { + t.Errorf("ParseAddr(%q) != ParseAddr(ParseIP(%q).String()). Got %#v, want %#v", test.in, test.in, got3, got) + } + + // Check that the slow-but-readable parser produces the same result. + slow, err := parseIPSlow(test.in) + if err != nil { + t.Fatal(err) + } + if got != slow { + t.Errorf("ParseAddr(%q) = %#v, parseIPSlow(%q) = %#v", test.in, got, test.in, slow) + } + + // Check that the parsed IP formats as expected. + s = got.String() + wants := test.str + if wants == "" { + wants = test.in + } + if s != wants { + t.Errorf("ParseAddr(%q).String() got %q, want %q", test.in, s, wants) + } + + // Check that AppendTo matches MarshalText. + TestAppendToMarshal(t, got) + + // Check that MarshalText/UnmarshalText work similarly to + // ParseAddr/String (see TestIPMarshalUnmarshal for + // marshal-specific behavior that's not common with + // ParseAddr/String). + js := `"` + test.in + `"` + var jsgot Addr + if err := json.Unmarshal([]byte(js), &jsgot); err != nil { + t.Fatal(err) + } + if jsgot != got { + t.Errorf("json.Unmarshal(%q) = %#v, want %#v", test.in, jsgot, got) + } + jsb, err := json.Marshal(jsgot) + if err != nil { + t.Fatal(err) + } + jswant := `"` + wants + `"` + jsback := string(jsb) + if jsback != jswant { + t.Errorf("Marshal(Unmarshal(%q)) = %s, want %s", test.in, jsback, jswant) + } + }) + } + + var invalidIPs = []string{ + // Empty string + "", + // Garbage non-IP + "bad", + // Single number. Some parsers accept this as an IPv4 address in + // big-endian uint32 form, but we don't. + "1234", + // IPv4 with a zone specifier + "1.2.3.4%eth0", + // IPv4 field must have at least one digit + ".1.2.3", + "1.2.3.", + "1..2.3", + // IPv4 address too long + "1.2.3.4.5", + // IPv4 in dotted octal form + "0300.0250.0214.0377", + // IPv4 in dotted hex form + "0xc0.0xa8.0x8c.0xff", + // IPv4 in class B form + "192.168.12345", + // IPv4 in class B form, with a small enough number to be + // parseable as a regular dotted decimal field. + "127.0.1", + // IPv4 in class A form + "192.1234567", + // IPv4 in class A form, with a small enough number to be + // parseable as a regular dotted decimal field. + "127.1", + // IPv4 field has value >255 + "192.168.300.1", + // IPv4 with too many fields + "192.168.0.1.5.6", + // IPv6 with not enough fields + "1:2:3:4:5:6:7", + // IPv6 with too many fields + "1:2:3:4:5:6:7:8:9", + // IPv6 with 8 fields and a :: expander + "1:2:3:4::5:6:7:8", + // IPv6 with a field bigger than 2b + "fe801::1", + // IPv6 with non-hex values in field + "fe80:tail:scal:e::", + // IPv6 with a zone delimiter but no zone. + "fe80::1%", + // IPv6 (without ellipsis) with too many fields for trailing embedded IPv4. + "ffff:ffff:ffff:ffff:ffff:ffff:ffff:192.168.140.255", + // IPv6 (with ellipsis) with too many fields for trailing embedded IPv4. + "ffff::ffff:ffff:ffff:ffff:ffff:ffff:192.168.140.255", + // IPv6 with invalid embedded IPv4. + "::ffff:192.168.140.bad", + // IPv6 with multiple ellipsis ::. + "fe80::1::1", + // IPv6 with invalid non hex/colon character. + "fe80:1?:1", + // IPv6 with truncated bytes after single colon. + "fe80:", + } + + for _, s := range invalidIPs { + t.Run(s, func(t *testing.T) { + got, err := ParseAddr(s) + if err == nil { + t.Errorf("ParseAddr(%q) = %#v, want error", s, got) + } + + slow, err := parseIPSlow(s) + if err == nil { + t.Errorf("parseIPSlow(%q) = %#v, want error", s, slow) + } + + std := net.ParseIP(s) + if std != nil { + t.Errorf("net.ParseIP(%q) = %#v, want error", s, std) + } + + if s == "" { + // Don't test unmarshaling of "" here, do it in + // IPMarshalUnmarshal. + return + } + var jsgot Addr + js := []byte(`"` + s + `"`) + if err := json.Unmarshal(js, &jsgot); err == nil { + t.Errorf("json.Unmarshal(%q) = %#v, want error", s, jsgot) + } + }) + } +} + +func TestIPv4Constructors(t *testing.T) { + if AddrFrom4([4]byte{1, 2, 3, 4}) != MustParseAddr("1.2.3.4") { + t.Errorf("don't match") + } +} + +func TestAddrMarshalUnmarshalBinary(t *testing.T) { + tests := []struct { + ip string + wantSize int + }{ + {"", 0}, // zero IP + {"1.2.3.4", 4}, + {"fd7a:115c:a1e0:ab12:4843:cd96:626b:430b", 16}, + {"::ffff:c000:0280", 16}, + {"::ffff:c000:0280%eth0", 20}, + } + for _, tc := range tests { + var ip Addr + if len(tc.ip) > 0 { + ip = mustIP(tc.ip) + } + b, err := ip.MarshalBinary() + if err != nil { + t.Fatal(err) + } + if len(b) != tc.wantSize { + t.Fatalf("%q encoded to size %d; want %d", tc.ip, len(b), tc.wantSize) + } + var ip2 Addr + if err := ip2.UnmarshalBinary(b); err != nil { + t.Fatal(err) + } + if ip != ip2 { + t.Fatalf("got %v; want %v", ip2, ip) + } + } + + // Cannot unmarshal from unexpected IP length. + for _, l := range []int{3, 5} { + var ip2 Addr + if err := ip2.UnmarshalBinary(bytes.Repeat([]byte{1}, l)); err == nil { + t.Fatalf("unmarshaled from unexpected IP length %d", l) + } + } +} + +func TestAddrMarshalUnmarshal(t *testing.T) { + // This only tests the cases where Marshal/Unmarshal diverges from + // the behavior of ParseAddr/String. For the rest of the test cases, + // see TestParseAddr above. + orig := `""` + var ip Addr + if err := json.Unmarshal([]byte(orig), &ip); err != nil { + t.Fatalf("Unmarshal(%q) got error %v", orig, err) + } + if ip != (Addr{}) { + t.Errorf("Unmarshal(%q) is not the zero Addr", orig) + } + + jsb, err := json.Marshal(ip) + if err != nil { + t.Fatalf("Marshal(%v) got error %v", ip, err) + } + back := string(jsb) + if back != orig { + t.Errorf("Marshal(Unmarshal(%q)) got %q, want %q", orig, back, orig) + } +} + +func TestAddrFrom16(t *testing.T) { + tests := []struct { + name string + in [16]byte + want Addr + }{ + { + name: "v6-raw", + in: [...]byte{15: 1}, + want: MkAddr(Mk128(0, 1), Z6noz), + }, + { + name: "v4-raw", + in: [...]byte{10: 0xff, 11: 0xff, 12: 1, 13: 2, 14: 3, 15: 4}, + want: MkAddr(Mk128(0, 0xffff01020304), Z6noz), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := AddrFrom16(tt.in) + if got != tt.want { + t.Errorf("got %#v; want %#v", got, tt.want) + } + }) + } +} + +func TestIPProperties(t *testing.T) { + var ( + nilIP Addr + + unicast4 = mustIP("192.0.2.1") + unicast6 = mustIP("2001:db8::1") + unicastZone6 = mustIP("2001:db8::1%eth0") + unicast6Unassigned = mustIP("4000::1") // not in 2000::/3. + + multicast4 = mustIP("224.0.0.1") + multicast6 = mustIP("ff02::1") + multicastZone6 = mustIP("ff02::1%eth0") + + llu4 = mustIP("169.254.0.1") + llu6 = mustIP("fe80::1") + llu6Last = mustIP("febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff") + lluZone6 = mustIP("fe80::1%eth0") + + loopback4 = mustIP("127.0.0.1") + loopback6 = mustIP("::1") + + ilm6 = mustIP("ff01::1") + ilmZone6 = mustIP("ff01::1%eth0") + + private4a = mustIP("10.0.0.1") + private4b = mustIP("172.16.0.1") + private4c = mustIP("192.168.1.1") + private6 = mustIP("fd00::1") + + unspecified4 = AddrFrom4([4]byte{}) + unspecified6 = IPv6Unspecified() + ) + + tests := []struct { + name string + ip Addr + globalUnicast bool + interfaceLocalMulticast bool + linkLocalMulticast bool + linkLocalUnicast bool + loopback bool + multicast bool + private bool + unspecified bool + }{ + { + name: "nil", + ip: nilIP, + }, + { + name: "unicast v4Addr", + ip: unicast4, + globalUnicast: true, + }, + { + name: "unicast v6Addr", + ip: unicast6, + globalUnicast: true, + }, + { + name: "unicast v6AddrZone", + ip: unicastZone6, + globalUnicast: true, + }, + { + name: "unicast v6Addr unassigned", + ip: unicast6Unassigned, + globalUnicast: true, + }, + { + name: "multicast v4Addr", + ip: multicast4, + linkLocalMulticast: true, + multicast: true, + }, + { + name: "multicast v6Addr", + ip: multicast6, + linkLocalMulticast: true, + multicast: true, + }, + { + name: "multicast v6AddrZone", + ip: multicastZone6, + linkLocalMulticast: true, + multicast: true, + }, + { + name: "link-local unicast v4Addr", + ip: llu4, + linkLocalUnicast: true, + }, + { + name: "link-local unicast v6Addr", + ip: llu6, + linkLocalUnicast: true, + }, + { + name: "link-local unicast v6Addr upper bound", + ip: llu6Last, + linkLocalUnicast: true, + }, + { + name: "link-local unicast v6AddrZone", + ip: lluZone6, + linkLocalUnicast: true, + }, + { + name: "loopback v4Addr", + ip: loopback4, + loopback: true, + }, + { + name: "loopback v6Addr", + ip: loopback6, + loopback: true, + }, + { + name: "interface-local multicast v6Addr", + ip: ilm6, + interfaceLocalMulticast: true, + multicast: true, + }, + { + name: "interface-local multicast v6AddrZone", + ip: ilmZone6, + interfaceLocalMulticast: true, + multicast: true, + }, + { + name: "private v4Addr 10/8", + ip: private4a, + globalUnicast: true, + private: true, + }, + { + name: "private v4Addr 172.16/12", + ip: private4b, + globalUnicast: true, + private: true, + }, + { + name: "private v4Addr 192.168/16", + ip: private4c, + globalUnicast: true, + private: true, + }, + { + name: "private v6Addr", + ip: private6, + globalUnicast: true, + private: true, + }, + { + name: "unspecified v4Addr", + ip: unspecified4, + unspecified: true, + }, + { + name: "unspecified v6Addr", + ip: unspecified6, + unspecified: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + gu := tt.ip.IsGlobalUnicast() + if gu != tt.globalUnicast { + t.Errorf("IsGlobalUnicast(%v) = %v; want %v", tt.ip, gu, tt.globalUnicast) + } + + ilm := tt.ip.IsInterfaceLocalMulticast() + if ilm != tt.interfaceLocalMulticast { + t.Errorf("IsInterfaceLocalMulticast(%v) = %v; want %v", tt.ip, ilm, tt.interfaceLocalMulticast) + } + + llu := tt.ip.IsLinkLocalUnicast() + if llu != tt.linkLocalUnicast { + t.Errorf("IsLinkLocalUnicast(%v) = %v; want %v", tt.ip, llu, tt.linkLocalUnicast) + } + + llm := tt.ip.IsLinkLocalMulticast() + if llm != tt.linkLocalMulticast { + t.Errorf("IsLinkLocalMulticast(%v) = %v; want %v", tt.ip, llm, tt.linkLocalMulticast) + } + + lo := tt.ip.IsLoopback() + if lo != tt.loopback { + t.Errorf("IsLoopback(%v) = %v; want %v", tt.ip, lo, tt.loopback) + } + + multicast := tt.ip.IsMulticast() + if multicast != tt.multicast { + t.Errorf("IsMulticast(%v) = %v; want %v", tt.ip, multicast, tt.multicast) + } + + private := tt.ip.IsPrivate() + if private != tt.private { + t.Errorf("IsPrivate(%v) = %v; want %v", tt.ip, private, tt.private) + } + + unspecified := tt.ip.IsUnspecified() + if unspecified != tt.unspecified { + t.Errorf("IsUnspecified(%v) = %v; want %v", tt.ip, unspecified, tt.unspecified) + } + }) + } +} + +func TestAddrWellKnown(t *testing.T) { + tests := []struct { + name string + ip Addr + std net.IP + }{ + { + name: "IPv6 link-local all nodes", + ip: IPv6LinkLocalAllNodes(), + std: net.IPv6linklocalallnodes, + }, + { + name: "IPv6 unspecified", + ip: IPv6Unspecified(), + std: net.IPv6unspecified, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + want := tt.std.String() + got := tt.ip.String() + + if got != want { + t.Fatalf("got %s, want %s", got, want) + } + }) + } +} + +func TestLessCompare(t *testing.T) { + tests := []struct { + a, b Addr + want bool + }{ + {Addr{}, Addr{}, false}, + {Addr{}, mustIP("1.2.3.4"), true}, + {mustIP("1.2.3.4"), Addr{}, false}, + + {mustIP("1.2.3.4"), mustIP("0102:0304::0"), true}, + {mustIP("0102:0304::0"), mustIP("1.2.3.4"), false}, + {mustIP("1.2.3.4"), mustIP("1.2.3.4"), false}, + + {mustIP("::1"), mustIP("::2"), true}, + {mustIP("::1"), mustIP("::1%foo"), true}, + {mustIP("::1%foo"), mustIP("::2"), true}, + {mustIP("::2"), mustIP("::3"), true}, + + {mustIP("::"), mustIP("0.0.0.0"), false}, + {mustIP("0.0.0.0"), mustIP("::"), true}, + + {mustIP("::1%a"), mustIP("::1%b"), true}, + {mustIP("::1%a"), mustIP("::1%a"), false}, + {mustIP("::1%b"), mustIP("::1%a"), false}, + } + for _, tt := range tests { + got := tt.a.Less(tt.b) + if got != tt.want { + t.Errorf("Less(%q, %q) = %v; want %v", tt.a, tt.b, got, tt.want) + } + cmp := tt.a.Compare(tt.b) + if got && cmp != -1 { + t.Errorf("Less(%q, %q) = true, but Compare = %v (not -1)", tt.a, tt.b, cmp) + } + if cmp < -1 || cmp > 1 { + t.Errorf("bogus Compare return value %v", cmp) + } + if cmp == 0 && tt.a != tt.b { + t.Errorf("Compare(%q, %q) = 0; but not equal", tt.a, tt.b) + } + if cmp == 1 && !tt.b.Less(tt.a) { + t.Errorf("Compare(%q, %q) = 1; but b.Less(a) isn't true", tt.a, tt.b) + } + + // Also check inverse. + if got == tt.want && got { + got2 := tt.b.Less(tt.a) + if got2 { + t.Errorf("Less(%q, %q) was correctly %v, but so was Less(%q, %q)", tt.a, tt.b, got, tt.b, tt.a) + } + } + } + + // And just sort. + values := []Addr{ + mustIP("::1"), + mustIP("::2"), + Addr{}, + mustIP("1.2.3.4"), + mustIP("8.8.8.8"), + mustIP("::1%foo"), + } + sort.Slice(values, func(i, j int) bool { return values[i].Less(values[j]) }) + got := fmt.Sprintf("%s", values) + want := `[invalid IP 1.2.3.4 8.8.8.8 ::1 ::1%foo ::2]` + if got != want { + t.Errorf("unexpected sort\n got: %s\nwant: %s\n", got, want) + } +} + +func TestIPStringExpanded(t *testing.T) { + tests := []struct { + ip Addr + s string + }{ + { + ip: Addr{}, + s: "invalid IP", + }, + { + ip: mustIP("192.0.2.1"), + s: "192.0.2.1", + }, + { + ip: mustIP("::ffff:192.0.2.1"), + s: "0000:0000:0000:0000:0000:ffff:c000:0201", + }, + { + ip: mustIP("2001:db8::1"), + s: "2001:0db8:0000:0000:0000:0000:0000:0001", + }, + { + ip: mustIP("2001:db8::1%eth0"), + s: "2001:0db8:0000:0000:0000:0000:0000:0001%eth0", + }, + } + + for _, tt := range tests { + t.Run(tt.ip.String(), func(t *testing.T) { + want := tt.s + got := tt.ip.StringExpanded() + + if got != want { + t.Fatalf("got %s, want %s", got, want) + } + }) + } +} + +func TestPrefixMasking(t *testing.T) { + type subtest struct { + ip Addr + bits uint8 + p Prefix + ok bool + } + + // makeIPv6 produces a set of IPv6 subtests with an optional zone identifier. + makeIPv6 := func(zone string) []subtest { + if zone != "" { + zone = "%" + zone + } + + return []subtest{ + { + ip: mustIP(fmt.Sprintf("2001:db8::1%s", zone)), + bits: 255, + }, + { + ip: mustIP(fmt.Sprintf("2001:db8::1%s", zone)), + bits: 32, + p: mustPrefix(fmt.Sprintf("2001:db8::%s/32", zone)), + ok: true, + }, + { + ip: mustIP(fmt.Sprintf("fe80::dead:beef:dead:beef%s", zone)), + bits: 96, + p: mustPrefix(fmt.Sprintf("fe80::dead:beef:0:0%s/96", zone)), + ok: true, + }, + { + ip: mustIP(fmt.Sprintf("aaaa::%s", zone)), + bits: 4, + p: mustPrefix(fmt.Sprintf("a000::%s/4", zone)), + ok: true, + }, + { + ip: mustIP(fmt.Sprintf("::%s", zone)), + bits: 63, + p: mustPrefix(fmt.Sprintf("::%s/63", zone)), + ok: true, + }, + } + } + + tests := []struct { + family string + subtests []subtest + }{ + { + family: "nil", + subtests: []subtest{ + { + bits: 255, + ok: true, + }, + { + bits: 16, + ok: true, + }, + }, + }, + { + family: "IPv4", + subtests: []subtest{ + { + ip: mustIP("192.0.2.0"), + bits: 255, + }, + { + ip: mustIP("192.0.2.0"), + bits: 16, + p: mustPrefix("192.0.0.0/16"), + ok: true, + }, + { + ip: mustIP("255.255.255.255"), + bits: 20, + p: mustPrefix("255.255.240.0/20"), + ok: true, + }, + { + // Partially masking one byte that contains both + // 1s and 0s on either side of the mask limit. + ip: mustIP("100.98.156.66"), + bits: 10, + p: mustPrefix("100.64.0.0/10"), + ok: true, + }, + }, + }, + { + family: "IPv6", + subtests: makeIPv6(""), + }, + { + family: "IPv6 zone", + subtests: makeIPv6("eth0"), + }, + } + + for _, tt := range tests { + t.Run(tt.family, func(t *testing.T) { + for _, st := range tt.subtests { + t.Run(st.p.String(), func(t *testing.T) { + // Ensure st.ip is not mutated. + orig := st.ip.String() + + p, err := st.ip.Prefix(int(st.bits)) + if st.ok && err != nil { + t.Fatalf("failed to produce prefix: %v", err) + } + if !st.ok && err == nil { + t.Fatal("expected an error, but none occurred") + } + if err != nil { + t.Logf("err: %v", err) + return + } + + if !reflect.DeepEqual(p, st.p) { + t.Errorf("prefix = %q, want %q", p, st.p) + } + + if got := st.ip.String(); got != orig { + t.Errorf("IP was mutated: %q, want %q", got, orig) + } + }) + } + }) + } +} + +func TestPrefixMarshalUnmarshal(t *testing.T) { + tests := []string{ + "", + "1.2.3.4/32", + "0.0.0.0/0", + "::/0", + "::1/128", + "::ffff:c000:1234/128", + "2001:db8::/32", + } + + for _, s := range tests { + t.Run(s, func(t *testing.T) { + // Ensure that JSON (and by extension, text) marshaling is + // sane by entering quoted input. + orig := `"` + s + `"` + + var p Prefix + if err := json.Unmarshal([]byte(orig), &p); err != nil { + t.Fatalf("failed to unmarshal: %v", err) + } + + pb, err := json.Marshal(p) + if err != nil { + t.Fatalf("failed to marshal: %v", err) + } + + back := string(pb) + if orig != back { + t.Errorf("Marshal = %q; want %q", back, orig) + } + }) + } +} + +func TestPrefixMarshalUnmarshalZone(t *testing.T) { + orig := `"fe80::1cc0:3e8c:119f:c2e1%ens18/128"` + unzoned := `"fe80::1cc0:3e8c:119f:c2e1/128"` + + var p Prefix + if err := json.Unmarshal([]byte(orig), &p); err != nil { + t.Fatalf("failed to unmarshal: %v", err) + } + + pb, err := json.Marshal(p) + if err != nil { + t.Fatalf("failed to marshal: %v", err) + } + + back := string(pb) + if back != unzoned { + t.Errorf("Marshal = %q; want %q", back, unzoned) + } +} + +func TestPrefixUnmarshalTextNonZero(t *testing.T) { + ip := mustPrefix("fe80::/64") + if err := ip.UnmarshalText([]byte("xxx")); err == nil { + t.Fatal("unmarshaled into non-empty Prefix") + } +} + +func TestIs4AndIs6(t *testing.T) { + tests := []struct { + ip Addr + is4 bool + is6 bool + }{ + {Addr{}, false, false}, + {mustIP("1.2.3.4"), true, false}, + {mustIP("127.0.0.2"), true, false}, + {mustIP("::1"), false, true}, + {mustIP("::ffff:192.0.2.128"), false, true}, + {mustIP("::fffe:c000:0280"), false, true}, + {mustIP("::1%eth0"), false, true}, + } + for _, tt := range tests { + got4 := tt.ip.Is4() + if got4 != tt.is4 { + t.Errorf("Is4(%q) = %v; want %v", tt.ip, got4, tt.is4) + } + + got6 := tt.ip.Is6() + if got6 != tt.is6 { + t.Errorf("Is6(%q) = %v; want %v", tt.ip, got6, tt.is6) + } + } +} + +func TestIs4In6(t *testing.T) { + tests := []struct { + ip Addr + want bool + wantUnmap Addr + }{ + {Addr{}, false, Addr{}}, + {mustIP("::ffff:c000:0280"), true, mustIP("192.0.2.128")}, + {mustIP("::ffff:192.0.2.128"), true, mustIP("192.0.2.128")}, + {mustIP("::ffff:192.0.2.128%eth0"), true, mustIP("192.0.2.128")}, + {mustIP("::fffe:c000:0280"), false, mustIP("::fffe:c000:0280")}, + {mustIP("::ffff:127.1.2.3"), true, mustIP("127.1.2.3")}, + {mustIP("::ffff:7f01:0203"), true, mustIP("127.1.2.3")}, + {mustIP("0:0:0:0:0000:ffff:127.1.2.3"), true, mustIP("127.1.2.3")}, + {mustIP("0:0:0:0:000000:ffff:127.1.2.3"), true, mustIP("127.1.2.3")}, + {mustIP("0:0:0:0::ffff:127.1.2.3"), true, mustIP("127.1.2.3")}, + {mustIP("::1"), false, mustIP("::1")}, + {mustIP("1.2.3.4"), false, mustIP("1.2.3.4")}, + } + for _, tt := range tests { + got := tt.ip.Is4In6() + if got != tt.want { + t.Errorf("Is4In6(%q) = %v; want %v", tt.ip, got, tt.want) + } + u := tt.ip.Unmap() + if u != tt.wantUnmap { + t.Errorf("Unmap(%q) = %v; want %v", tt.ip, u, tt.wantUnmap) + } + } +} + +func TestPrefixMasked(t *testing.T) { + tests := []struct { + prefix Prefix + masked Prefix + }{ + { + prefix: mustPrefix("192.168.0.255/24"), + masked: mustPrefix("192.168.0.0/24"), + }, + { + prefix: mustPrefix("2100::/3"), + masked: mustPrefix("2000::/3"), + }, + { + prefix: PrefixFrom(mustIP("2000::"), 129), + masked: Prefix{}, + }, + { + prefix: PrefixFrom(mustIP("1.2.3.4"), 33), + masked: Prefix{}, + }, + } + for _, test := range tests { + t.Run(test.prefix.String(), func(t *testing.T) { + got := test.prefix.Masked() + if got != test.masked { + t.Errorf("Masked=%s, want %s", got, test.masked) + } + }) + } +} + +func TestPrefix(t *testing.T) { + tests := []struct { + prefix string + ip Addr + bits int + str string + contains []Addr + notContains []Addr + }{ + { + prefix: "192.168.0.0/24", + ip: mustIP("192.168.0.0"), + bits: 24, + contains: mustIPs("192.168.0.1", "192.168.0.55"), + notContains: mustIPs("192.168.1.1", "1.1.1.1"), + }, + { + prefix: "192.168.1.1/32", + ip: mustIP("192.168.1.1"), + bits: 32, + contains: mustIPs("192.168.1.1"), + notContains: mustIPs("192.168.1.2"), + }, + { + prefix: "100.64.0.0/10", // CGNAT range; prefix not multiple of 8 + ip: mustIP("100.64.0.0"), + bits: 10, + contains: mustIPs("100.64.0.0", "100.64.0.1", "100.81.251.94", "100.100.100.100", "100.127.255.254", "100.127.255.255"), + notContains: mustIPs("100.63.255.255", "100.128.0.0"), + }, + { + prefix: "2001:db8::/96", + ip: mustIP("2001:db8::"), + bits: 96, + contains: mustIPs("2001:db8::aaaa:bbbb", "2001:db8::1"), + notContains: mustIPs("2001:db8::1:aaaa:bbbb", "2001:db9::"), + }, + { + prefix: "0.0.0.0/0", + ip: mustIP("0.0.0.0"), + bits: 0, + contains: mustIPs("192.168.0.1", "1.1.1.1"), + notContains: append(mustIPs("2001:db8::1"), Addr{}), + }, + { + prefix: "::/0", + ip: mustIP("::"), + bits: 0, + contains: mustIPs("::1", "2001:db8::1"), + notContains: mustIPs("192.0.2.1"), + }, + { + prefix: "2000::/3", + ip: mustIP("2000::"), + bits: 3, + contains: mustIPs("2001:db8::1"), + notContains: mustIPs("fe80::1"), + }, + { + prefix: "::%0/00/80", + ip: mustIP("::"), + bits: 80, + str: "::/80", + contains: mustIPs("::"), + notContains: mustIPs("ff::%0/00", "ff::%1/23", "::%0/00", "::%1/23"), + }, + } + for _, test := range tests { + t.Run(test.prefix, func(t *testing.T) { + prefix, err := ParsePrefix(test.prefix) + if err != nil { + t.Fatal(err) + } + if prefix.Addr() != test.ip { + t.Errorf("IP=%s, want %s", prefix.Addr(), test.ip) + } + if prefix.Bits() != test.bits { + t.Errorf("bits=%d, want %d", prefix.Bits(), test.bits) + } + for _, ip := range test.contains { + if !prefix.Contains(ip) { + t.Errorf("does not contain %s", ip) + } + } + for _, ip := range test.notContains { + if prefix.Contains(ip) { + t.Errorf("contains %s", ip) + } + } + want := test.str + if want == "" { + want = test.prefix + } + if got := prefix.String(); got != want { + t.Errorf("prefix.String()=%q, want %q", got, want) + } + + TestAppendToMarshal(t, prefix) + }) + } +} + +func TestPrefixFromInvalidBits(t *testing.T) { + v4 := MustParseAddr("1.2.3.4") + v6 := MustParseAddr("66::66") + tests := []struct { + ip Addr + in, want int + }{ + {v4, 0, 0}, + {v6, 0, 0}, + {v4, 1, 1}, + {v4, 33, -1}, + {v6, 33, 33}, + {v6, 127, 127}, + {v6, 128, 128}, + {v4, 254, -1}, + {v4, 255, -1}, + {v4, -1, -1}, + {v6, -1, -1}, + {v4, -5, -1}, + {v6, -5, -1}, + } + for _, tt := range tests { + p := PrefixFrom(tt.ip, tt.in) + if got := p.Bits(); got != tt.want { + t.Errorf("for (%v, %v), Bits out = %v; want %v", tt.ip, tt.in, got, tt.want) + } + } +} + +func TestParsePrefixAllocs(t *testing.T) { + tests := []struct { + ip string + slash string + }{ + {"192.168.1.0", "/24"}, + {"aaaa:bbbb:cccc::", "/24"}, + } + for _, test := range tests { + prefix := test.ip + test.slash + t.Run(prefix, func(t *testing.T) { + ipAllocs := int(testing.AllocsPerRun(5, func() { + ParseAddr(test.ip) + })) + prefixAllocs := int(testing.AllocsPerRun(5, func() { + ParsePrefix(prefix) + })) + if got := prefixAllocs - ipAllocs; got != 0 { + t.Errorf("allocs=%d, want 0", got) + } + }) + } +} + +func TestParsePrefixError(t *testing.T) { + tests := []struct { + prefix string + errstr string + }{ + { + prefix: "192.168.0.0", + errstr: "no '/'", + }, + { + prefix: "1.257.1.1/24", + errstr: "value >255", + }, + { + prefix: "1.1.1.0/q", + errstr: "bad bits", + }, + { + prefix: "1.1.1.0/-1", + errstr: "out of range", + }, + { + prefix: "1.1.1.0/33", + errstr: "out of range", + }, + { + prefix: "2001::/129", + errstr: "out of range", + }, + } + for _, test := range tests { + t.Run(test.prefix, func(t *testing.T) { + _, err := ParsePrefix(test.prefix) + if err == nil { + t.Fatal("no error") + } + if got := err.Error(); !strings.Contains(got, test.errstr) { + t.Errorf("error is missing substring %q: %s", test.errstr, got) + } + }) + } +} + +func TestPrefixIsSingleIP(t *testing.T) { + tests := []struct { + ipp Prefix + want bool + }{ + {ipp: mustPrefix("127.0.0.1/32"), want: true}, + {ipp: mustPrefix("127.0.0.1/31"), want: false}, + {ipp: mustPrefix("127.0.0.1/0"), want: false}, + {ipp: mustPrefix("::1/128"), want: true}, + {ipp: mustPrefix("::1/127"), want: false}, + {ipp: mustPrefix("::1/0"), want: false}, + {ipp: Prefix{}, want: false}, + } + for _, tt := range tests { + got := tt.ipp.IsSingleIP() + if got != tt.want { + t.Errorf("IsSingleIP(%v) = %v want %v", tt.ipp, got, tt.want) + } + } +} + +func mustIPs(strs ...string) []Addr { + var res []Addr + for _, s := range strs { + res = append(res, mustIP(s)) + } + return res +} + +func BenchmarkBinaryMarshalRoundTrip(b *testing.B) { + b.ReportAllocs() + tests := []struct { + name string + ip string + }{ + {"ipv4", "1.2.3.4"}, + {"ipv6", "2001:db8::1"}, + {"ipv6+zone", "2001:db8::1%eth0"}, + } + for _, tc := range tests { + b.Run(tc.name, func(b *testing.B) { + ip := mustIP(tc.ip) + for i := 0; i < b.N; i++ { + bt, err := ip.MarshalBinary() + if err != nil { + b.Fatal(err) + } + var ip2 Addr + if err := ip2.UnmarshalBinary(bt); err != nil { + b.Fatal(err) + } + } + }) + } +} + +func BenchmarkStdIPv4(b *testing.B) { + b.ReportAllocs() + ips := []net.IP{} + for i := 0; i < b.N; i++ { + ip := net.IPv4(8, 8, 8, 8) + ips = ips[:0] + for i := 0; i < 100; i++ { + ips = append(ips, ip) + } + } +} + +func BenchmarkIPv4(b *testing.B) { + b.ReportAllocs() + ips := []Addr{} + for i := 0; i < b.N; i++ { + ip := IPv4(8, 8, 8, 8) + ips = ips[:0] + for i := 0; i < 100; i++ { + ips = append(ips, ip) + } + } +} + +// ip4i was one of the possible representations of IP that came up in +// discussions, inlining IPv4 addresses, but having an "overflow" +// interface for IPv6 or IPv6 + zone. This is here for benchmarking. +type ip4i struct { + ip4 [4]byte + flags1 byte + flags2 byte + flags3 byte + flags4 byte + ipv6 interface{} +} + +func newip4i_v4(a, b, c, d byte) ip4i { + return ip4i{ip4: [4]byte{a, b, c, d}} +} + +// BenchmarkIPv4_inline benchmarks the candidate representation, ip4i. +func BenchmarkIPv4_inline(b *testing.B) { + b.ReportAllocs() + ips := []ip4i{} + for i := 0; i < b.N; i++ { + ip := newip4i_v4(8, 8, 8, 8) + ips = ips[:0] + for i := 0; i < 100; i++ { + ips = append(ips, ip) + } + } +} + +func BenchmarkStdIPv6(b *testing.B) { + b.ReportAllocs() + ips := []net.IP{} + for i := 0; i < b.N; i++ { + ip := net.ParseIP("2001:db8::1") + ips = ips[:0] + for i := 0; i < 100; i++ { + ips = append(ips, ip) + } + } +} + +func BenchmarkIPv6(b *testing.B) { + b.ReportAllocs() + ips := []Addr{} + for i := 0; i < b.N; i++ { + ip := mustIP("2001:db8::1") + ips = ips[:0] + for i := 0; i < 100; i++ { + ips = append(ips, ip) + } + } +} + +func BenchmarkIPv4Contains(b *testing.B) { + b.ReportAllocs() + prefix := PrefixFrom(IPv4(192, 168, 1, 0), 24) + ip := IPv4(192, 168, 1, 1) + for i := 0; i < b.N; i++ { + prefix.Contains(ip) + } +} + +func BenchmarkIPv6Contains(b *testing.B) { + b.ReportAllocs() + prefix := MustParsePrefix("::1/128") + ip := MustParseAddr("::1") + for i := 0; i < b.N; i++ { + prefix.Contains(ip) + } +} + +var parseBenchInputs = []struct { + name string + ip string +}{ + {"v4", "192.168.1.1"}, + {"v6", "fd7a:115c:a1e0:ab12:4843:cd96:626b:430b"}, + {"v6_ellipsis", "fd7a:115c::626b:430b"}, + {"v6_v4", "::ffff:192.168.140.255"}, + {"v6_zone", "1:2::ffff:192.168.140.255%eth1"}, +} + +func BenchmarkParseAddr(b *testing.B) { + sinkInternValue = intern.Get("eth1") // Pin to not benchmark the intern package + for _, test := range parseBenchInputs { + b.Run(test.name, func(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + sinkIP, _ = ParseAddr(test.ip) + } + }) + } +} + +func BenchmarkStdParseIP(b *testing.B) { + for _, test := range parseBenchInputs { + b.Run(test.name, func(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + sinkStdIP = net.ParseIP(test.ip) + } + }) + } +} + +func BenchmarkIPString(b *testing.B) { + for _, test := range parseBenchInputs { + ip := MustParseAddr(test.ip) + b.Run(test.name, func(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + sinkString = ip.String() + } + }) + } +} + +func BenchmarkIPStringExpanded(b *testing.B) { + for _, test := range parseBenchInputs { + ip := MustParseAddr(test.ip) + b.Run(test.name, func(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + sinkString = ip.StringExpanded() + } + }) + } +} + +func BenchmarkIPMarshalText(b *testing.B) { + b.ReportAllocs() + ip := MustParseAddr("66.55.44.33") + for i := 0; i < b.N; i++ { + sinkBytes, _ = ip.MarshalText() + } +} + +func BenchmarkAddrPortString(b *testing.B) { + for _, test := range parseBenchInputs { + ip := MustParseAddr(test.ip) + ipp := AddrPortFrom(ip, 60000) + b.Run(test.name, func(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + sinkString = ipp.String() + } + }) + } +} + +func BenchmarkAddrPortMarshalText(b *testing.B) { + for _, test := range parseBenchInputs { + ip := MustParseAddr(test.ip) + ipp := AddrPortFrom(ip, 60000) + b.Run(test.name, func(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + sinkBytes, _ = ipp.MarshalText() + } + }) + } +} + +func BenchmarkPrefixMasking(b *testing.B) { + tests := []struct { + name string + ip Addr + bits int + }{ + { + name: "IPv4 /32", + ip: IPv4(192, 0, 2, 0), + bits: 32, + }, + { + name: "IPv4 /17", + ip: IPv4(192, 0, 2, 0), + bits: 17, + }, + { + name: "IPv4 /0", + ip: IPv4(192, 0, 2, 0), + bits: 0, + }, + { + name: "IPv6 /128", + ip: mustIP("2001:db8::1"), + bits: 128, + }, + { + name: "IPv6 /65", + ip: mustIP("2001:db8::1"), + bits: 65, + }, + { + name: "IPv6 /0", + ip: mustIP("2001:db8::1"), + bits: 0, + }, + { + name: "IPv6 zone /128", + ip: mustIP("2001:db8::1%eth0"), + bits: 128, + }, + { + name: "IPv6 zone /65", + ip: mustIP("2001:db8::1%eth0"), + bits: 65, + }, + { + name: "IPv6 zone /0", + ip: mustIP("2001:db8::1%eth0"), + bits: 0, + }, + } + + for _, tt := range tests { + b.Run(tt.name, func(b *testing.B) { + b.ReportAllocs() + + for i := 0; i < b.N; i++ { + sinkPrefix, _ = tt.ip.Prefix(tt.bits) + } + }) + } +} + +func BenchmarkPrefixMarshalText(b *testing.B) { + b.ReportAllocs() + ipp := MustParsePrefix("66.55.44.33/22") + for i := 0; i < b.N; i++ { + sinkBytes, _ = ipp.MarshalText() + } +} + +func BenchmarkParseAddrPort(b *testing.B) { + for _, test := range parseBenchInputs { + var ipp string + if strings.HasPrefix(test.name, "v6") { + ipp = fmt.Sprintf("[%s]:1234", test.ip) + } else { + ipp = fmt.Sprintf("%s:1234", test.ip) + } + b.Run(test.name, func(b *testing.B) { + b.ReportAllocs() + + for i := 0; i < b.N; i++ { + sinkAddrPort, _ = ParseAddrPort(ipp) + } + }) + } +} + +func TestAs4(t *testing.T) { + tests := []struct { + ip Addr + want [4]byte + wantPanic bool + }{ + { + ip: mustIP("1.2.3.4"), + want: [4]byte{1, 2, 3, 4}, + }, + { + ip: AddrFrom16(mustIP("1.2.3.4").As16()), // IPv4-in-IPv6 + want: [4]byte{1, 2, 3, 4}, + }, + { + ip: mustIP("0.0.0.0"), + want: [4]byte{0, 0, 0, 0}, + }, + { + ip: Addr{}, + wantPanic: true, + }, + { + ip: mustIP("::1"), + wantPanic: true, + }, + } + as4 := func(ip Addr) (v [4]byte, gotPanic bool) { + defer func() { + if recover() != nil { + gotPanic = true + return + } + }() + v = ip.As4() + return + } + for i, tt := range tests { + got, gotPanic := as4(tt.ip) + if gotPanic != tt.wantPanic { + t.Errorf("%d. panic on %v = %v; want %v", i, tt.ip, gotPanic, tt.wantPanic) + continue + } + if got != tt.want { + t.Errorf("%d. %v = %v; want %v", i, tt.ip, got, tt.want) + } + } +} + +func TestPrefixOverlaps(t *testing.T) { + pfx := mustPrefix + tests := []struct { + a, b Prefix + want bool + }{ + {Prefix{}, pfx("1.2.0.0/16"), false}, // first zero + {pfx("1.2.0.0/16"), Prefix{}, false}, // second zero + {pfx("::0/3"), pfx("0.0.0.0/3"), false}, // different families + + {pfx("1.2.0.0/16"), pfx("1.2.0.0/16"), true}, // equal + + {pfx("1.2.0.0/16"), pfx("1.2.3.0/24"), true}, + {pfx("1.2.3.0/24"), pfx("1.2.0.0/16"), true}, + + {pfx("1.2.0.0/16"), pfx("1.2.3.0/32"), true}, + {pfx("1.2.3.0/32"), pfx("1.2.0.0/16"), true}, + + // Match /0 either order + {pfx("1.2.3.0/32"), pfx("0.0.0.0/0"), true}, + {pfx("0.0.0.0/0"), pfx("1.2.3.0/32"), true}, + + {pfx("1.2.3.0/32"), pfx("5.5.5.5/0"), true}, // normalization not required; /0 means true + + // IPv6 overlapping + {pfx("5::1/128"), pfx("5::0/8"), true}, + {pfx("5::0/8"), pfx("5::1/128"), true}, + + // IPv6 not overlapping + {pfx("1::1/128"), pfx("2::2/128"), false}, + {pfx("0100::0/8"), pfx("::1/128"), false}, + + // v6-mapped v4 should not overlap with IPv4. + {PrefixFrom(AddrFrom16(mustIP("1.2.0.0").As16()), 16), pfx("1.2.3.0/24"), false}, + + // Invalid prefixes + {PrefixFrom(mustIP("1.2.3.4"), 33), pfx("1.2.3.0/24"), false}, + {PrefixFrom(mustIP("2000::"), 129), pfx("2000::/64"), false}, + } + for i, tt := range tests { + if got := tt.a.Overlaps(tt.b); got != tt.want { + t.Errorf("%d. (%v).Overlaps(%v) = %v; want %v", i, tt.a, tt.b, got, tt.want) + } + // Overlaps is commutative + if got := tt.b.Overlaps(tt.a); got != tt.want { + t.Errorf("%d. (%v).Overlaps(%v) = %v; want %v", i, tt.b, tt.a, got, tt.want) + } + } +} + +// Sink variables are here to force the compiler to not elide +// seemingly useless work in benchmarks and allocation tests. If you +// were to just `_ = foo()` within a test function, the compiler could +// correctly deduce that foo() does nothing and doesn't need to be +// called. By writing results to a global variable, we hide that fact +// from the compiler and force it to keep the code under test. +var ( + sinkIP Addr + sinkStdIP net.IP + sinkAddrPort AddrPort + sinkPrefix Prefix + sinkPrefixSlice []Prefix + sinkInternValue *intern.Value + sinkIP16 [16]byte + sinkIP4 [4]byte + sinkBool bool + sinkString string + sinkBytes []byte + sinkUDPAddr = &net.UDPAddr{IP: make(net.IP, 0, 16)} +) + +func TestNoAllocs(t *testing.T) { + // Wrappers that panic on error, to prove that our alloc-free + // methods are returning successfully. + panicIP := func(ip Addr, err error) Addr { + if err != nil { + panic(err) + } + return ip + } + panicPfx := func(pfx Prefix, err error) Prefix { + if err != nil { + panic(err) + } + return pfx + } + panicIPP := func(ipp AddrPort, err error) AddrPort { + if err != nil { + panic(err) + } + return ipp + } + test := func(name string, f func()) { + t.Run(name, func(t *testing.T) { + n := testing.AllocsPerRun(1000, f) + if n != 0 { + t.Fatalf("allocs = %d; want 0", int(n)) + } + }) + } + + // IP constructors + test("IPv4", func() { sinkIP = IPv4(1, 2, 3, 4) }) + test("AddrFrom4", func() { sinkIP = AddrFrom4([4]byte{1, 2, 3, 4}) }) + test("AddrFrom16", func() { sinkIP = AddrFrom16([16]byte{}) }) + test("ParseAddr/4", func() { sinkIP = panicIP(ParseAddr("1.2.3.4")) }) + test("ParseAddr/6", func() { sinkIP = panicIP(ParseAddr("::1")) }) + test("MustParseAddr", func() { sinkIP = MustParseAddr("1.2.3.4") }) + test("IPv6LinkLocalAllNodes", func() { sinkIP = IPv6LinkLocalAllNodes() }) + test("IPv6Unspecified", func() { sinkIP = IPv6Unspecified() }) + + // IP methods + test("IP.IsZero", func() { sinkBool = MustParseAddr("1.2.3.4").IsZero() }) + test("IP.BitLen", func() { sinkBool = MustParseAddr("1.2.3.4").BitLen() == 8 }) + test("IP.Zone/4", func() { sinkBool = MustParseAddr("1.2.3.4").Zone() == "" }) + test("IP.Zone/6", func() { sinkBool = MustParseAddr("fe80::1").Zone() == "" }) + test("IP.Zone/6zone", func() { sinkBool = MustParseAddr("fe80::1%zone").Zone() == "" }) + test("IP.Compare", func() { + a := MustParseAddr("1.2.3.4") + b := MustParseAddr("2.3.4.5") + sinkBool = a.Compare(b) == 0 + }) + test("IP.Less", func() { + a := MustParseAddr("1.2.3.4") + b := MustParseAddr("2.3.4.5") + sinkBool = a.Less(b) + }) + test("IP.Is4", func() { sinkBool = MustParseAddr("1.2.3.4").Is4() }) + test("IP.Is6", func() { sinkBool = MustParseAddr("fe80::1").Is6() }) + test("IP.Is4In6", func() { sinkBool = MustParseAddr("fe80::1").Is4In6() }) + test("IP.Unmap", func() { sinkIP = MustParseAddr("ffff::2.3.4.5").Unmap() }) + test("IP.WithZone", func() { sinkIP = MustParseAddr("fe80::1").WithZone("") }) + test("IP.IsGlobalUnicast", func() { sinkBool = MustParseAddr("2001:db8::1").IsGlobalUnicast() }) + test("IP.IsInterfaceLocalMulticast", func() { sinkBool = MustParseAddr("fe80::1").IsInterfaceLocalMulticast() }) + test("IP.IsLinkLocalMulticast", func() { sinkBool = MustParseAddr("fe80::1").IsLinkLocalMulticast() }) + test("IP.IsLinkLocalUnicast", func() { sinkBool = MustParseAddr("fe80::1").IsLinkLocalUnicast() }) + test("IP.IsLoopback", func() { sinkBool = MustParseAddr("fe80::1").IsLoopback() }) + test("IP.IsMulticast", func() { sinkBool = MustParseAddr("fe80::1").IsMulticast() }) + test("IP.IsPrivate", func() { sinkBool = MustParseAddr("fd00::1").IsPrivate() }) + test("IP.IsUnspecified", func() { sinkBool = IPv6Unspecified().IsUnspecified() }) + test("IP.Prefix/4", func() { sinkPrefix = panicPfx(MustParseAddr("1.2.3.4").Prefix(20)) }) + test("IP.Prefix/6", func() { sinkPrefix = panicPfx(MustParseAddr("fe80::1").Prefix(64)) }) + test("IP.As16", func() { sinkIP16 = MustParseAddr("1.2.3.4").As16() }) + test("IP.As4", func() { sinkIP4 = MustParseAddr("1.2.3.4").As4() }) + test("IP.Next", func() { sinkIP = MustParseAddr("1.2.3.4").Next() }) + test("IP.Prev", func() { sinkIP = MustParseAddr("1.2.3.4").Prev() }) + + // AddrPort constructors + test("AddrPortFrom", func() { sinkAddrPort = AddrPortFrom(IPv4(1, 2, 3, 4), 22) }) + test("ParseAddrPort", func() { sinkAddrPort = panicIPP(ParseAddrPort("[::1]:1234")) }) + test("MustParseAddrPort", func() { sinkAddrPort = MustParseAddrPort("[::1]:1234") }) + + // Prefix constructors + test("PrefixFrom", func() { sinkPrefix = PrefixFrom(IPv4(1, 2, 3, 4), 32) }) + test("ParsePrefix/4", func() { sinkPrefix = panicPfx(ParsePrefix("1.2.3.4/20")) }) + test("ParsePrefix/6", func() { sinkPrefix = panicPfx(ParsePrefix("fe80::1/64")) }) + test("MustParsePrefix", func() { sinkPrefix = MustParsePrefix("1.2.3.4/20") }) + + // Prefix methods + test("Prefix.Contains", func() { sinkBool = MustParsePrefix("1.2.3.0/24").Contains(MustParseAddr("1.2.3.4")) }) + test("Prefix.Overlaps", func() { + a, b := MustParsePrefix("1.2.3.0/24"), MustParsePrefix("1.2.0.0/16") + sinkBool = a.Overlaps(b) + }) + test("Prefix.IsZero", func() { sinkBool = MustParsePrefix("1.2.0.0/16").IsZero() }) + test("Prefix.IsSingleIP", func() { sinkBool = MustParsePrefix("1.2.3.4/32").IsSingleIP() }) + test("IPPRefix.Masked", func() { sinkPrefix = MustParsePrefix("1.2.3.4/16").Masked() }) +} + +func TestPrefixString(t *testing.T) { + tests := []struct { + ipp Prefix + want string + }{ + {Prefix{}, "invalid Prefix"}, + {PrefixFrom(Addr{}, 8), "invalid Prefix"}, + {PrefixFrom(MustParseAddr("1.2.3.4"), 88), "invalid Prefix"}, + } + + for _, tt := range tests { + if got := tt.ipp.String(); got != tt.want { + t.Errorf("(%#v).String() = %q want %q", tt.ipp, got, tt.want) + } + } +} + +func TestInvalidAddrPortString(t *testing.T) { + tests := []struct { + ipp AddrPort + want string + }{ + {AddrPort{}, "invalid AddrPort"}, + {AddrPortFrom(Addr{}, 80), "invalid AddrPort"}, + } + + for _, tt := range tests { + if got := tt.ipp.String(); got != tt.want { + t.Errorf("(%#v).String() = %q want %q", tt.ipp, got, tt.want) + } + } +} + +var sink16 [16]byte + +func BenchmarkAs16(b *testing.B) { + addr := MustParseAddr("1::10") + for i := 0; i < b.N; i++ { + sink16 = addr.As16() + } +} diff --git a/src/net/netip/slow_test.go b/src/net/netip/slow_test.go new file mode 100644 index 0000000000..5b46a39a83 --- /dev/null +++ b/src/net/netip/slow_test.go @@ -0,0 +1,190 @@ +// 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 netip_test + +import ( + "fmt" + . "net/netip" + "strconv" + "strings" +) + +// zeros is a slice of eight stringified zeros. It's used in +// parseIPSlow to construct slices of specific amounts of zero fields, +// from 1 to 8. +var zeros = []string{"0", "0", "0", "0", "0", "0", "0", "0"} + +// parseIPSlow is like ParseIP, but aims for readability above +// speed. It's the reference implementation for correctness checking +// and against which we measure optimized parsers. +// +// parseIPSlow understands the following forms of IP addresses: +// - Regular IPv4: 1.2.3.4 +// - IPv4 with many leading zeros: 0000001.0000002.0000003.0000004 +// - Regular IPv6: 1111:2222:3333:4444:5555:6666:7777:8888 +// - IPv6 with many leading zeros: 00000001:0000002:0000003:0000004:0000005:0000006:0000007:0000008 +// - IPv6 with zero blocks elided: 1111:2222::7777:8888 +// - IPv6 with trailing 32 bits expressed as IPv4: 1111:2222:3333:4444:5555:6666:77.77.88.88 +// +// It does not process the following IP address forms, which have been +// varyingly accepted by some programs due to an under-specification +// of the shapes of IPv4 addresses: +// +// - IPv4 as a single 32-bit uint: 4660 (same as "1.2.3.4") +// - IPv4 with octal numbers: 0300.0250.0.01 (same as "192.168.0.1") +// - IPv4 with hex numbers: 0xc0.0xa8.0x0.0x1 (same as "192.168.0.1") +// - IPv4 in "class-B style": 1.2.52 (same as "1.2.3.4") +// - IPv4 in "class-A style": 1.564 (same as "1.2.3.4") +func parseIPSlow(s string) (Addr, error) { + // Identify and strip out the zone, if any. There should be 0 or 1 + // '%' in the string. + var zone string + fs := strings.Split(s, "%") + switch len(fs) { + case 1: + // No zone, that's fine. + case 2: + s, zone = fs[0], fs[1] + if zone == "" { + return Addr{}, fmt.Errorf("netaddr.ParseIP(%q): no zone after zone specifier", s) + } + default: + return Addr{}, fmt.Errorf("netaddr.ParseIP(%q): too many zone specifiers", s) // TODO: less specific? + } + + // IPv4 by itself is easy to do in a helper. + if strings.Count(s, ":") == 0 { + if zone != "" { + return Addr{}, fmt.Errorf("netaddr.ParseIP(%q): IPv4 addresses cannot have a zone", s) + } + return parseIPv4Slow(s) + } + + normal, err := normalizeIPv6Slow(s) + if err != nil { + return Addr{}, err + } + + // At this point, we've normalized the address back into 8 hex + // fields of 16 bits each. Parse that. + fs = strings.Split(normal, ":") + if len(fs) != 8 { + return Addr{}, fmt.Errorf("netaddr.ParseIP(%q): wrong size address", s) + } + var ret [16]byte + for i, f := range fs { + a, b, err := parseWord(f) + if err != nil { + return Addr{}, err + } + ret[i*2] = a + ret[i*2+1] = b + } + + return AddrFrom16(ret).WithZone(zone), nil +} + +// normalizeIPv6Slow expands s, which is assumed to be an IPv6 +// address, to its canonical text form. +// +// The canonical form of an IPv6 address is 8 colon-separated fields, +// where each field should be a hex value from 0 to ffff. This +// function does not verify the contents of each field. +// +// This function performs two transformations: +// - The last 32 bits of an IPv6 address may be represented in +// IPv4-style dotted quad form, as in 1:2:3:4:5:6:7.8.9.10. That +// address is transformed to its hex equivalent, +// e.g. 1:2:3:4:5:6:708:90a. +// - An address may contain one "::", which expands into as many +// 16-bit blocks of zeros as needed to make the address its correct +// full size. For example, fe80::1:2 expands to fe80:0:0:0:0:0:1:2. +// +// Both short forms may be present in a single address, +// e.g. fe80::1.2.3.4. +func normalizeIPv6Slow(orig string) (string, error) { + s := orig + + // Find and convert an IPv4 address in the final field, if any. + i := strings.LastIndex(s, ":") + if i == -1 { + return "", fmt.Errorf("netaddr.ParseIP(%q): invalid IP address", orig) + } + if strings.Contains(s[i+1:], ".") { + ip, err := parseIPv4Slow(s[i+1:]) + if err != nil { + return "", err + } + a4 := ip.As4() + s = fmt.Sprintf("%s:%02x%02x:%02x%02x", s[:i], a4[0], a4[1], a4[2], a4[3]) + } + + // Find and expand a ::, if any. + fs := strings.Split(s, "::") + switch len(fs) { + case 1: + // No ::, nothing to do. + case 2: + lhs, rhs := fs[0], fs[1] + // Found a ::, figure out how many zero blocks need to be + // inserted. + nblocks := strings.Count(lhs, ":") + strings.Count(rhs, ":") + if lhs != "" { + nblocks++ + } + if rhs != "" { + nblocks++ + } + if nblocks > 7 { + return "", fmt.Errorf("netaddr.ParseIP(%q): address too long", orig) + } + fs = nil + // Either side of the :: can be empty. We don't want empty + // fields to feature in the final normalized address. + if lhs != "" { + fs = append(fs, lhs) + } + fs = append(fs, zeros[:8-nblocks]...) + if rhs != "" { + fs = append(fs, rhs) + } + s = strings.Join(fs, ":") + default: + // Too many :: + return "", fmt.Errorf("netaddr.ParseIP(%q): invalid IP address", orig) + } + + return s, nil +} + +// parseIPv4Slow parses and returns an IPv4 address in dotted quad +// form, e.g. "192.168.0.1". It is slow but easy to read, and the +// reference implementation against which we compare faster +// implementations for correctness. +func parseIPv4Slow(s string) (Addr, error) { + fs := strings.Split(s, ".") + if len(fs) != 4 { + return Addr{}, fmt.Errorf("netaddr.ParseIP(%q): invalid IP address", s) + } + var ret [4]byte + for i := range ret { + val, err := strconv.ParseUint(fs[i], 10, 8) + if err != nil { + return Addr{}, err + } + ret[i] = uint8(val) + } + return AddrFrom4([4]byte{ret[0], ret[1], ret[2], ret[3]}), nil +} + +// parseWord converts a 16-bit hex string into its corresponding +// two-byte value. +func parseWord(s string) (byte, byte, error) { + ret, err := strconv.ParseUint(s, 16, 16) + if err != nil { + return 0, 0, err + } + return uint8(ret >> 8), uint8(ret), nil +} diff --git a/src/net/netip/uint128.go b/src/net/netip/uint128.go new file mode 100644 index 0000000000..738939d7de --- /dev/null +++ b/src/net/netip/uint128.go @@ -0,0 +1,92 @@ +// 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 netip + +import "math/bits" + +// uint128 represents a uint128 using two uint64s. +// +// When the methods below mention a bit number, bit 0 is the most +// significant bit (in hi) and bit 127 is the lowest (lo&1). +type uint128 struct { + hi uint64 + lo uint64 +} + +// mask6 returns a uint128 bitmask with the topmost n bits of a +// 128-bit number. +func mask6(n int) uint128 { + return uint128{^(^uint64(0) >> n), ^uint64(0) << (128 - n)} +} + +// isZero reports whether u == 0. +// +// It's faster than u == (uint128{}) because the compiler (as of Go +// 1.15/1.16b1) doesn't do this trick and instead inserts a branch in +// its eq alg's generated code. +func (u uint128) isZero() bool { return u.hi|u.lo == 0 } + +// and returns the bitwise AND of u and m (u&m). +func (u uint128) and(m uint128) uint128 { + return uint128{u.hi & m.hi, u.lo & m.lo} +} + +// xor returns the bitwise XOR of u and m (u^m). +func (u uint128) xor(m uint128) uint128 { + return uint128{u.hi ^ m.hi, u.lo ^ m.lo} +} + +// or returns the bitwise OR of u and m (u|m). +func (u uint128) or(m uint128) uint128 { + return uint128{u.hi | m.hi, u.lo | m.lo} +} + +// not returns the bitwise NOT of u. +func (u uint128) not() uint128 { + return uint128{^u.hi, ^u.lo} +} + +// subOne returns u - 1. +func (u uint128) subOne() uint128 { + lo, borrow := bits.Sub64(u.lo, 1, 0) + return uint128{u.hi - borrow, lo} +} + +// addOne returns u + 1. +func (u uint128) addOne() uint128 { + lo, carry := bits.Add64(u.lo, 1, 0) + return uint128{u.hi + carry, lo} +} + +func u64CommonPrefixLen(a, b uint64) uint8 { + return uint8(bits.LeadingZeros64(a ^ b)) +} + +func (u uint128) commonPrefixLen(v uint128) (n uint8) { + if n = u64CommonPrefixLen(u.hi, v.hi); n == 64 { + n += u64CommonPrefixLen(u.lo, v.lo) + } + return +} + +// halves returns the two uint64 halves of the uint128. +// +// Logically, think of it as returning two uint64s. +// It only returns pointers for inlining reasons on 32-bit platforms. +func (u *uint128) halves() [2]*uint64 { + return [2]*uint64{&u.hi, &u.lo} +} + +// bitsSetFrom returns a copy of u with the given bit +// and all subsequent ones set. +func (u uint128) bitsSetFrom(bit uint8) uint128 { + return u.or(mask6(int(bit)).not()) +} + +// bitsClearedFrom returns a copy of u with the given bit +// and all subsequent ones cleared. +func (u uint128) bitsClearedFrom(bit uint8) uint128 { + return u.and(mask6(int(bit))) +} diff --git a/src/net/netip/uint128_test.go b/src/net/netip/uint128_test.go new file mode 100644 index 0000000000..dd1ae0ec79 --- /dev/null +++ b/src/net/netip/uint128_test.go @@ -0,0 +1,89 @@ +// 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 netip + +import ( + "testing" +) + +func TestUint128AddSub(t *testing.T) { + const add1 = 1 + const sub1 = -1 + tests := []struct { + in uint128 + op int // +1 or -1 to add vs subtract + want uint128 + }{ + {uint128{0, 0}, add1, uint128{0, 1}}, + {uint128{0, 1}, add1, uint128{0, 2}}, + {uint128{1, 0}, add1, uint128{1, 1}}, + {uint128{0, ^uint64(0)}, add1, uint128{1, 0}}, + {uint128{^uint64(0), ^uint64(0)}, add1, uint128{0, 0}}, + + {uint128{0, 0}, sub1, uint128{^uint64(0), ^uint64(0)}}, + {uint128{0, 1}, sub1, uint128{0, 0}}, + {uint128{0, 2}, sub1, uint128{0, 1}}, + {uint128{1, 0}, sub1, uint128{0, ^uint64(0)}}, + {uint128{1, 1}, sub1, uint128{1, 0}}, + } + for _, tt := range tests { + var got uint128 + switch tt.op { + case add1: + got = tt.in.addOne() + case sub1: + got = tt.in.subOne() + default: + panic("bogus op") + } + if got != tt.want { + t.Errorf("%v add %d = %v; want %v", tt.in, tt.op, got, tt.want) + } + } +} + +func TestBitsSetFrom(t *testing.T) { + tests := []struct { + bit uint8 + want uint128 + }{ + {0, uint128{^uint64(0), ^uint64(0)}}, + {1, uint128{^uint64(0) >> 1, ^uint64(0)}}, + {63, uint128{1, ^uint64(0)}}, + {64, uint128{0, ^uint64(0)}}, + {65, uint128{0, ^uint64(0) >> 1}}, + {127, uint128{0, 1}}, + {128, uint128{0, 0}}, + } + for _, tt := range tests { + var zero uint128 + got := zero.bitsSetFrom(tt.bit) + if got != tt.want { + t.Errorf("0.bitsSetFrom(%d) = %064b want %064b", tt.bit, got, tt.want) + } + } +} + +func TestBitsClearedFrom(t *testing.T) { + tests := []struct { + bit uint8 + want uint128 + }{ + {0, uint128{0, 0}}, + {1, uint128{1 << 63, 0}}, + {63, uint128{^uint64(0) &^ 1, 0}}, + {64, uint128{^uint64(0), 0}}, + {65, uint128{^uint64(0), 1 << 63}}, + {127, uint128{^uint64(0), ^uint64(0) &^ 1}}, + {128, uint128{^uint64(0), ^uint64(0)}}, + } + for _, tt := range tests { + ones := uint128{^uint64(0), ^uint64(0)} + got := ones.bitsClearedFrom(tt.bit) + if got != tt.want { + t.Errorf("ones.bitsClearedFrom(%d) = %064b want %064b", tt.bit, got, tt.want) + } + } +} diff --git a/src/net/parse.go b/src/net/parse.go index 0d7cce12e6..ee2890fe2c 100644 --- a/src/net/parse.go +++ b/src/net/parse.go @@ -341,26 +341,3 @@ func readFull(r io.Reader) (all []byte, err error) { } } } - -// goDebugString returns the value of the named GODEBUG key. -// GODEBUG is of the form "key=val,key2=val2" -func goDebugString(key string) string { - s := os.Getenv("GODEBUG") - for i := 0; i < len(s)-len(key)-1; i++ { - if i > 0 && s[i-1] != ',' { - continue - } - afterKey := s[i+len(key):] - if afterKey[0] != '=' || s[i:i+len(key)] != key { - continue - } - val := afterKey[1:] - for i, b := range val { - if b == ',' { - return val[:i] - } - } - return val - } - return "" -} diff --git a/src/net/parse_test.go b/src/net/parse_test.go index c5f8bfd198..97716d769a 100644 --- a/src/net/parse_test.go +++ b/src/net/parse_test.go @@ -51,33 +51,6 @@ func TestReadLine(t *testing.T) { } } -func TestGoDebugString(t *testing.T) { - defer os.Setenv("GODEBUG", os.Getenv("GODEBUG")) - tests := []struct { - godebug string - key string - want string - }{ - {"", "foo", ""}, - {"foo=", "foo", ""}, - {"foo=bar", "foo", "bar"}, - {"foo=bar,", "foo", "bar"}, - {"foo,foo=bar,", "foo", "bar"}, - {"foo1=bar,foo=bar,", "foo", "bar"}, - {"foo=bar,foo=bar,", "foo", "bar"}, - {"foo=", "foo", ""}, - {"foo", "foo", ""}, - {",foo", "foo", ""}, - {"foo=bar,baz", "loooooooong", ""}, - } - for _, tt := range tests { - os.Setenv("GODEBUG", tt.godebug) - if got := goDebugString(tt.key); got != tt.want { - t.Errorf("for %q, goDebugString(%q) = %q; want %q", tt.godebug, tt.key, got, tt.want) - } - } -} - func TestDtoi(t *testing.T) { for _, tt := range []struct { in string diff --git a/src/net/tcpsock.go b/src/net/tcpsock.go index 19a90143f3..fddb018aab 100644 --- a/src/net/tcpsock.go +++ b/src/net/tcpsock.go @@ -8,6 +8,7 @@ import ( "context" "internal/itoa" "io" + "net/netip" "os" "syscall" "time" @@ -23,6 +24,20 @@ type TCPAddr struct { Zone string // IPv6 scoped addressing zone } +// AddrPort returns the TCPAddr a as a netip.AddrPort. +// +// If a.Port does not fit in a uint16, it's silently truncated. +// +// If a is nil, a zero value is returned. +func (a *TCPAddr) AddrPort() netip.AddrPort { + if a == nil { + return netip.AddrPort{} + } + na, _ := netip.AddrFromSlice(a.IP) + na = na.WithZone(a.Zone) + return netip.AddrPortFrom(na, uint16(a.Port)) +} + // Network returns the address's network name, "tcp". func (a *TCPAddr) Network() string { return "tcp" } diff --git a/src/net/udpsock.go b/src/net/udpsock.go index 70f2ce226a..622b1f83fb 100644 --- a/src/net/udpsock.go +++ b/src/net/udpsock.go @@ -7,6 +7,7 @@ package net import ( "context" "internal/itoa" + "net/netip" "syscall" ) @@ -26,6 +27,20 @@ type UDPAddr struct { Zone string // IPv6 scoped addressing zone } +// AddrPort returns the UDPAddr a as a netip.AddrPort. +// +// If a.Port does not fit in a uint16, it's silently truncated. +// +// If a is nil, a zero value is returned. +func (a *UDPAddr) AddrPort() netip.AddrPort { + if a == nil { + return netip.AddrPort{} + } + na, _ := netip.AddrFromSlice(a.IP) + na = na.WithZone(a.Zone) + return netip.AddrPortFrom(na, uint16(a.Port)) +} + // Network returns the address's network name, "udp". func (a *UDPAddr) Network() string { return "udp" } @@ -84,6 +99,28 @@ func ResolveUDPAddr(network, address string) (*UDPAddr, error) { return addrs.forResolve(network, address).(*UDPAddr), nil } +// UDPAddrFromAddrPort returns addr as a UDPAddr. +// +// If addr is not valid, it returns nil. +func UDPAddrFromAddrPort(addr netip.AddrPort) *UDPAddr { + if !addr.IsValid() { + return nil + } + ip16 := addr.Addr().As16() + return &UDPAddr{ + IP: IP(ip16[:]), + Zone: addr.Addr().Zone(), + Port: int(addr.Port()), + } +} + +// An addrPortUDPAddr is a netip.AddrPort-based UDP address that satisfies the Addr interface. +type addrPortUDPAddr struct { + netip.AddrPort +} + +func (addrPortUDPAddr) Network() string { return "udp" } + // UDPConn is the implementation of the Conn and PacketConn interfaces // for UDP network connections. type UDPConn struct { @@ -130,6 +167,18 @@ func (c *UDPConn) ReadFrom(b []byte) (int, Addr, error) { return n, addr, err } +// ReadFromUDPAddrPort acts like ReadFrom but returns a netip.AddrPort. +func (c *UDPConn) ReadFromUDPAddrPort(b []byte) (n int, addr netip.AddrPort, err error) { + if !c.ok() { + return 0, netip.AddrPort{}, syscall.EINVAL + } + n, addr, err = c.readFromAddrPort(b) + if err != nil { + err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err} + } + return n, addr, err +} + // ReadMsgUDP reads a message from c, copying the payload into b and // the associated out-of-band data into oob. It returns the number of // bytes copied into b, the number of bytes copied into oob, the flags @@ -138,8 +187,16 @@ func (c *UDPConn) ReadFrom(b []byte) (int, Addr, error) { // The packages golang.org/x/net/ipv4 and golang.org/x/net/ipv6 can be // used to manipulate IP-level socket options in oob. func (c *UDPConn) ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *UDPAddr, err error) { + var ap netip.AddrPort + n, oobn, flags, ap, err = c.ReadMsgUDPAddrPort(b, oob) + addr = UDPAddrFromAddrPort(ap) + return +} + +// ReadMsgUDPAddrPort is like ReadMsgUDP but returns an netip.AddrPort instead of a UDPAddr. +func (c *UDPConn) ReadMsgUDPAddrPort(b, oob []byte) (n, oobn, flags int, addr netip.AddrPort, err error) { if !c.ok() { - return 0, 0, 0, nil, syscall.EINVAL + return 0, 0, 0, netip.AddrPort{}, syscall.EINVAL } n, oobn, flags, addr, err = c.readMsg(b, oob) if err != nil { @@ -160,6 +217,18 @@ func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (int, error) { return n, err } +// WriteToUDPAddrPort acts like WriteTo but takes a netip.AddrPort. +func (c *UDPConn) WriteToUDPAddrPort(b []byte, addr netip.AddrPort) (int, error) { + if !c.ok() { + return 0, syscall.EINVAL + } + n, err := c.writeToAddrPort(b, addr) + if err != nil { + err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addrPortUDPAddr{addr}, Err: err} + } + return n, err +} + // WriteTo implements the PacketConn WriteTo method. func (c *UDPConn) WriteTo(b []byte, addr Addr) (int, error) { if !c.ok() { @@ -195,6 +264,18 @@ func (c *UDPConn) WriteMsgUDP(b, oob []byte, addr *UDPAddr) (n, oobn int, err er return } +// WriteMsgUDPAddrPort is like WriteMsgUDP but takes a netip.AddrPort instead of a UDPAddr. +func (c *UDPConn) WriteMsgUDPAddrPort(b, oob []byte, addr netip.AddrPort) (n, oobn int, err error) { + if !c.ok() { + return 0, 0, syscall.EINVAL + } + n, oobn, err = c.writeMsgAddrPort(b, oob, addr) + if err != nil { + err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addrPortUDPAddr{addr}, Err: err} + } + return +} + func newUDPConn(fd *netFD) *UDPConn { return &UDPConn{conn{fd}} } // DialUDP acts like Dial for UDP networks. diff --git a/src/net/udpsock_plan9.go b/src/net/udpsock_plan9.go index 1df293d1db..732a3b07ee 100644 --- a/src/net/udpsock_plan9.go +++ b/src/net/udpsock_plan9.go @@ -7,6 +7,7 @@ package net import ( "context" "errors" + "net/netip" "os" "syscall" ) @@ -28,8 +29,27 @@ func (c *UDPConn) readFrom(b []byte, addr *UDPAddr) (int, *UDPAddr, error) { return n, addr, nil } -func (c *UDPConn) readMsg(b, oob []byte) (n, oobn, flags int, addr *UDPAddr, err error) { - return 0, 0, 0, nil, syscall.EPLAN9 +func (c *UDPConn) readFromAddrPort(b []byte) (int, netip.AddrPort, error) { + // TODO: optimize. The equivalent code on posix is alloc-free. + buf := make([]byte, udpHeaderSize+len(b)) + m, err := c.fd.Read(buf) + if err != nil { + return 0, netip.AddrPort{}, err + } + if m < udpHeaderSize { + return 0, netip.AddrPort{}, errors.New("short read reading UDP header") + } + buf = buf[:m] + + h, buf := unmarshalUDPHeader(buf) + n := copy(b, buf) + ip, _ := netip.AddrFromSlice(h.raddr) + addr := netip.AddrPortFrom(ip, h.rport) + return n, addr, nil +} + +func (c *UDPConn) readMsg(b, oob []byte) (n, oobn, flags int, addr netip.AddrPort, err error) { + return 0, 0, 0, netip.AddrPort{}, syscall.EPLAN9 } func (c *UDPConn) writeTo(b []byte, addr *UDPAddr) (int, error) { @@ -52,10 +72,18 @@ func (c *UDPConn) writeTo(b []byte, addr *UDPAddr) (int, error) { return len(b), nil } +func (c *UDPConn) writeToAddrPort(b []byte, addr netip.AddrPort) (int, error) { + return c.writeTo(b, UDPAddrFromAddrPort(addr)) // TODO: optimize instead of allocating +} + func (c *UDPConn) writeMsg(b, oob []byte, addr *UDPAddr) (n, oobn int, err error) { return 0, 0, syscall.EPLAN9 } +func (c *UDPConn) writeMsgAddrPort(b, oob []byte, addr netip.AddrPort) (n, oobn int, err error) { + return 0, 0, syscall.EPLAN9 +} + func (sd *sysDialer) dialUDP(ctx context.Context, laddr, raddr *UDPAddr) (*UDPConn, error) { fd, err := dialPlan9(ctx, sd.network, laddr, raddr) if err != nil { diff --git a/src/net/udpsock_posix.go b/src/net/udpsock_posix.go index c3f7ddb77e..6544397673 100644 --- a/src/net/udpsock_posix.go +++ b/src/net/udpsock_posix.go @@ -8,6 +8,7 @@ package net import ( "context" + "net/netip" "syscall" ) @@ -68,14 +69,43 @@ func (c *UDPConn) readFrom(b []byte, addr *UDPAddr) (int, *UDPAddr, error) { return n, addr, err } -func (c *UDPConn) readMsg(b, oob []byte) (n, oobn, flags int, addr *UDPAddr, err error) { - var sa syscall.Sockaddr - n, oobn, flags, sa, err = c.fd.readMsg(b, oob, 0) - switch sa := sa.(type) { - case *syscall.SockaddrInet4: - addr = &UDPAddr{IP: sa.Addr[0:], Port: sa.Port} - case *syscall.SockaddrInet6: - addr = &UDPAddr{IP: sa.Addr[0:], Port: sa.Port, Zone: zoneCache.name(int(sa.ZoneId))} +func (c *UDPConn) readFromAddrPort(b []byte) (n int, addr netip.AddrPort, err error) { + var ip netip.Addr + var port int + switch c.fd.family { + case syscall.AF_INET: + var from syscall.SockaddrInet4 + n, err = c.fd.readFromInet4(b, &from) + if err == nil { + ip = netip.AddrFrom4(from.Addr) + port = from.Port + } + case syscall.AF_INET6: + var from syscall.SockaddrInet6 + n, err = c.fd.readFromInet6(b, &from) + if err == nil { + ip = netip.AddrFrom16(from.Addr).WithZone(zoneCache.name(int(from.ZoneId))) + port = from.Port + } + } + if err == nil { + addr = netip.AddrPortFrom(ip, uint16(port)) + } + return n, addr, err +} + +func (c *UDPConn) readMsg(b, oob []byte) (n, oobn, flags int, addr netip.AddrPort, err error) { + switch c.fd.family { + case syscall.AF_INET: + var sa syscall.SockaddrInet4 + n, oobn, flags, err = c.fd.readMsgInet4(b, oob, 0, &sa) + ip := netip.AddrFrom4(sa.Addr) + addr = netip.AddrPortFrom(ip, uint16(sa.Port)) + case syscall.AF_INET6: + var sa syscall.SockaddrInet6 + n, oobn, flags, err = c.fd.readMsgInet6(b, oob, 0, &sa) + ip := netip.AddrFrom16(sa.Addr).WithZone(zoneCache.name(int(sa.ZoneId))) + addr = netip.AddrPortFrom(ip, uint16(sa.Port)) } return } @@ -94,18 +124,44 @@ func (c *UDPConn) writeTo(b []byte, addr *UDPAddr) (int, error) { if err != nil { return 0, err } - return c.fd.writeToInet4(b, sa) + return c.fd.writeToInet4(b, &sa) case syscall.AF_INET6: sa, err := ipToSockaddrInet6(addr.IP, addr.Port, addr.Zone) if err != nil { return 0, err } - return c.fd.writeToInet6(b, sa) + return c.fd.writeToInet6(b, &sa) default: return 0, &AddrError{Err: "invalid address family", Addr: addr.IP.String()} } } +func (c *UDPConn) writeToAddrPort(b []byte, addr netip.AddrPort) (int, error) { + if c.fd.isConnected { + return 0, ErrWriteToConnected + } + if !addr.IsValid() { + return 0, errMissingAddress + } + + switch c.fd.family { + case syscall.AF_INET: + sa, err := addrPortToSockaddrInet4(addr) + if err != nil { + return 0, err + } + return c.fd.writeToInet4(b, &sa) + case syscall.AF_INET6: + sa, err := addrPortToSockaddrInet6(addr) + if err != nil { + return 0, err + } + return c.fd.writeToInet6(b, &sa) + default: + return 0, &AddrError{Err: "invalid address family", Addr: addr.Addr().String()} + } +} + func (c *UDPConn) writeMsg(b, oob []byte, addr *UDPAddr) (n, oobn int, err error) { if c.fd.isConnected && addr != nil { return 0, 0, ErrWriteToConnected @@ -120,6 +176,32 @@ func (c *UDPConn) writeMsg(b, oob []byte, addr *UDPAddr) (n, oobn int, err error return c.fd.writeMsg(b, oob, sa) } +func (c *UDPConn) writeMsgAddrPort(b, oob []byte, addr netip.AddrPort) (n, oobn int, err error) { + if c.fd.isConnected && addr.IsValid() { + return 0, 0, ErrWriteToConnected + } + if !c.fd.isConnected && !addr.IsValid() { + return 0, 0, errMissingAddress + } + + switch c.fd.family { + case syscall.AF_INET: + sa, err := addrPortToSockaddrInet4(addr) + if err != nil { + return 0, 0, err + } + return c.fd.writeMsgInet4(b, oob, &sa) + case syscall.AF_INET6: + sa, err := addrPortToSockaddrInet6(addr) + if err != nil { + return 0, 0, err + } + return c.fd.writeMsgInet6(b, oob, &sa) + default: + return 0, 0, &AddrError{Err: "invalid address family", Addr: addr.Addr().String()} + } +} + func (sd *sysDialer) dialUDP(ctx context.Context, laddr, raddr *UDPAddr) (*UDPConn, error) { fd, err := internetSocket(ctx, sd.network, laddr, raddr, syscall.SOCK_DGRAM, 0, "dial", sd.Dialer.Control) if err != nil { diff --git a/src/net/udpsock_test.go b/src/net/udpsock_test.go index 0f8f463100..9fe74f47a2 100644 --- a/src/net/udpsock_test.go +++ b/src/net/udpsock_test.go @@ -474,11 +474,98 @@ func TestUDPReadTimeout(t *testing.T) { } } +func TestAllocs(t *testing.T) { + switch runtime.GOOS { + case "plan9": + // Plan9 wasn't optimized. + t.Skipf("skipping on %v", runtime.GOOS) + } + builder := os.Getenv("GO_BUILDER_NAME") + switch builder { + case "linux-amd64-noopt": + // Optimizations are required to remove the allocs. + t.Skipf("skipping on %v", builder) + } + conn, err := ListenUDP("udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)}) + if err != nil { + t.Fatal(err) + } + defer conn.Close() + addr := conn.LocalAddr() + addrPort := addr.(*UDPAddr).AddrPort() + buf := make([]byte, 8) + + allocs := testing.AllocsPerRun(1000, func() { + _, _, err := conn.WriteMsgUDPAddrPort(buf, nil, addrPort) + if err != nil { + t.Fatal(err) + } + _, _, _, _, err = conn.ReadMsgUDPAddrPort(buf, nil) + if err != nil { + t.Fatal(err) + } + }) + if got := int(allocs); got != 0 { + t.Errorf("WriteMsgUDPAddrPort/ReadMsgUDPAddrPort allocated %d objects", got) + } + + allocs = testing.AllocsPerRun(1000, func() { + _, err := conn.WriteToUDPAddrPort(buf, addrPort) + if err != nil { + t.Fatal(err) + } + _, _, err = conn.ReadFromUDPAddrPort(buf) + if err != nil { + t.Fatal(err) + } + }) + if got := int(allocs); got != 0 { + t.Errorf("WriteToUDPAddrPort/ReadFromUDPAddrPort allocated %d objects", got) + } + + allocs = testing.AllocsPerRun(1000, func() { + _, err := conn.WriteTo(buf, addr) + if err != nil { + t.Fatal(err) + } + _, _, err = conn.ReadFromUDP(buf) + if err != nil { + t.Fatal(err) + } + }) + if got := int(allocs); got != 1 { + t.Errorf("WriteTo/ReadFromUDP allocated %d objects", got) + } +} + +func BenchmarkReadWriteMsgUDPAddrPort(b *testing.B) { + conn, err := ListenUDP("udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)}) + if err != nil { + b.Fatal(err) + } + defer conn.Close() + addr := conn.LocalAddr().(*UDPAddr).AddrPort() + buf := make([]byte, 8) + b.ResetTimer() + b.ReportAllocs() + for i := 0; i < b.N; i++ { + _, _, err := conn.WriteMsgUDPAddrPort(buf, nil, addr) + if err != nil { + b.Fatal(err) + } + _, _, _, _, err = conn.ReadMsgUDPAddrPort(buf, nil) + if err != nil { + b.Fatal(err) + } + } +} + func BenchmarkWriteToReadFromUDP(b *testing.B) { conn, err := ListenUDP("udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)}) if err != nil { b.Fatal(err) } + defer conn.Close() addr := conn.LocalAddr() buf := make([]byte, 8) b.ResetTimer() @@ -494,3 +581,25 @@ func BenchmarkWriteToReadFromUDP(b *testing.B) { } } } + +func BenchmarkWriteToReadFromUDPAddrPort(b *testing.B) { + conn, err := ListenUDP("udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)}) + if err != nil { + b.Fatal(err) + } + defer conn.Close() + addr := conn.LocalAddr().(*UDPAddr).AddrPort() + buf := make([]byte, 8) + b.ResetTimer() + b.ReportAllocs() + for i := 0; i < b.N; i++ { + _, err := conn.WriteToUDPAddrPort(buf, addr) + if err != nil { + b.Fatal(err) + } + _, _, err = conn.ReadFromUDPAddrPort(buf) + if err != nil { + b.Fatal(err) + } + } +} diff --git a/src/net/url/url.go b/src/net/url/url.go index d571ab2fc4..f31aa08b59 100644 --- a/src/net/url/url.go +++ b/src/net/url/url.go @@ -1083,7 +1083,7 @@ func (u *URL) ResolveReference(ref *URL) *URL { url.Path = "" return &url } - if ref.Path == "" && ref.RawQuery == "" { + if ref.Path == "" && !ref.ForceQuery && ref.RawQuery == "" { url.RawQuery = u.RawQuery if ref.Fragment == "" { url.Fragment = u.Fragment diff --git a/src/net/url/url_test.go b/src/net/url/url_test.go index 6807d58f1a..7c807d7a38 100644 --- a/src/net/url/url_test.go +++ b/src/net/url/url_test.go @@ -1244,6 +1244,9 @@ var resolveReferenceTests = []struct { {"https://a/b/c/d;p?q", "//g/d/e/f?y#s", "https://g/d/e/f?y#s"}, {"https://a/b/c/d;p#s", "?y", "https://a/b/c/d;p?y"}, {"https://a/b/c/d;p?q#s", "?y", "https://a/b/c/d;p?y"}, + + // Empty path and query but with ForceQuery (issue 46033). + {"https://a/b/c/d;p?q#s", "?", "https://a/b/c/d;p?"}, } func TestResolveReference(t *testing.T) { diff --git a/src/runtime/asan/asan.go b/src/runtime/asan/asan.go index ac71466b71..eb66b3aab5 100644 --- a/src/runtime/asan/asan.go +++ b/src/runtime/asan/asan.go @@ -10,9 +10,21 @@ package asan #cgo CFLAGS: -fsanitize=address #cgo LDFLAGS: -fsanitize=address +#include #include #include +extern void __asan_report_load1(void*); +extern void __asan_report_load2(void*); +extern void __asan_report_load4(void*); +extern void __asan_report_load8(void*); +extern void __asan_report_load_n(void*, uintptr_t); +extern void __asan_report_store1(void*); +extern void __asan_report_store2(void*); +extern void __asan_report_store4(void*); +extern void __asan_report_store8(void*); +extern void __asan_report_store_n(void*, uintptr_t); + void __asan_read_go(void *addr, uintptr_t sz) { if (__asan_region_is_poisoned(addr, sz)) { switch (sz) { diff --git a/src/runtime/asm_amd64.s b/src/runtime/asm_amd64.s index 3ab6060ec0..0f0e5be21a 100644 --- a/src/runtime/asm_amd64.s +++ b/src/runtime/asm_amd64.s @@ -78,6 +78,87 @@ GLOBL _rt0_amd64_lib_argc<>(SB),NOPTR, $8 DATA _rt0_amd64_lib_argv<>(SB)/8, $0 GLOBL _rt0_amd64_lib_argv<>(SB),NOPTR, $8 +#ifdef GOAMD64_v2 +DATA bad_cpu_msg<>+0x00(SB)/84, $"This program can only be run on AMD64 processors with v2 microarchitecture support.\n" +#endif + +#ifdef GOAMD64_v3 +DATA bad_cpu_msg<>+0x00(SB)/84, $"This program can only be run on AMD64 processors with v3 microarchitecture support.\n" +#endif + +#ifdef GOAMD64_v4 +DATA bad_cpu_msg<>+0x00(SB)/84, $"This program can only be run on AMD64 processors with v4 microarchitecture support.\n" +#endif + +GLOBL bad_cpu_msg<>(SB), RODATA, $84 + +// Define a list of AMD64 microarchitecture level features +// https://en.wikipedia.org/wiki/X86-64#Microarchitecture_levels + + // SSE3 SSSE3 CMPXCHNG16 SSE4.1 SSE4.2 POPCNT +#define V2_FEATURES_CX (1 << 0 | 1 << 9 | 1 << 13 | 1 << 19 | 1 << 20 | 1 << 23) + // LAHF/SAHF +#define V2_EXT_FEATURES_CX (1 << 0) + // FMA MOVBE OSXSAVE AVX F16C +#define V3_FEATURES_CX (V2_FEATURES_CX | 1 << 12 | 1 << 22 | 1 << 27 | 1 << 28 | 1 << 29) + // ABM (FOR LZNCT) +#define V3_EXT_FEATURES_CX (V2_EXT_FEATURES_CX | 1 << 5) + // BMI1 AVX2 BMI2 +#define V3_EXT_FEATURES_BX (1 << 3 | 1 << 5 | 1 << 8) + // XMM YMM +#define V3_OS_SUPPORT_AX (1 << 1 | 1 << 2) + +#define V4_FEATURES_CX V3_FEATURES_CX + +#define V4_EXT_FEATURES_CX V3_EXT_FEATURES_CX + // AVX512F AVX512DQ AVX512CD AVX512BW AVX512VL +#define V4_EXT_FEATURES_BX (V3_EXT_FEATURES_BX | 1 << 16 | 1 << 17 | 1 << 28 | 1 << 30 | 1 << 31) + // OPMASK ZMM +#define V4_OS_SUPPORT_AX (V3_OS_SUPPORT_AX | 1 << 5 | (1 << 6 | 1 << 7)) + +#ifdef GOAMD64_v2 +#define NEED_MAX_CPUID 0x80000001 +#define NEED_FEATURES_CX V2_FEATURES_CX +#define NEED_EXT_FEATURES_CX V2_EXT_FEATURES_CX +#endif + +#ifdef GOAMD64_v3 +#define NEED_MAX_CPUID 0x80000001 +#define NEED_FEATURES_CX V3_FEATURES_CX +#define NEED_EXT_FEATURES_CX V3_EXT_FEATURES_CX +#define NEED_EXT_FEATURES_BX V3_EXT_FEATURES_BX +#define NEED_OS_SUPPORT_AX V3_OS_SUPPORT_AX +#endif + +#ifdef GOAMD64_v4 +#define NEED_MAX_CPUID 0x80000001 +#define NEED_FEATURES_CX V4_FEATURES_CX +#define NEED_EXT_FEATURES_CX V4_EXT_FEATURES_CX +#define NEED_EXT_FEATURES_BX V4_EXT_FEATURES_BX + +// Downgrading v4 OS checks on Darwin for now, see CL 285572. +#ifdef GOOS_darwin +#define NEED_OS_SUPPORT_AX V3_OS_SUPPORT_AX +#else +#define NEED_OS_SUPPORT_AX V4_OS_SUPPORT_AX +#endif + +#endif + +#ifdef GOAMD64_v1 +#define SKIP_GOAMD64_CHECK +#endif + +#ifndef GOAMD64_v1 +#ifndef GOAMD64_v2 +#ifndef GOAMD64_v3 +#ifndef GOAMD64_v4 +#define SKIP_GOAMD64_CHECK +#endif +#endif +#endif +#endif + TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0 // copy arguments forward on an even stack MOVQ DI, AX // argc @@ -99,10 +180,24 @@ TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0 // find out information about the processor we're on MOVL $0, AX CPUID - MOVL AX, SI CMPL AX, $0 +#ifdef SKIP_GOAMD64_CHECK JE nocpuinfo +#else + JNE has_cpuinfo +bad_cpu: // show that the program requires a certain microarchitecture level. + MOVQ $2, 0(SP) + MOVQ $bad_cpu_msg<>(SB), AX + MOVQ AX, 8(SP) + MOVQ $84, 16(SP) + CALL runtime·write(SB) + MOVQ $1, 0(SP) + CALL runtime·exit(SB) + CALL runtime·abort(SB) +#endif + +has_cpuinfo: CMPL BX, $0x756E6547 // "Genu" JNE notintel CMPL DX, $0x49656E69 // "ineI" @@ -110,13 +205,51 @@ TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0 CMPL CX, $0x6C65746E // "ntel" JNE notintel MOVB $1, runtime·isIntel(SB) -notintel: +notintel: // Load EAX=1 cpuid flags MOVL $1, AX CPUID MOVL AX, runtime·processorVersionInfo(SB) +#ifdef NEED_FEATURES_CX + ANDL $NEED_FEATURES_CX, CX + CMPL CX, $NEED_FEATURES_CX + JNE bad_cpu +#endif + +#ifdef NEED_MAX_CPUID + MOVL $0x80000000, AX + CPUID + CMPL AX, $NEED_MAX_CPUID + JL bad_cpu +#endif + +#ifdef NEED_EXT_FEATURES_BX + MOVL $7, AX + MOVL $0, CX + CPUID + ANDL $NEED_EXT_FEATURES_BX, BX + CMPL BX, $NEED_EXT_FEATURES_BX + JNE bad_cpu +#endif + +#ifdef NEED_EXT_FEATURES_CX + MOVL $0x80000001, AX + CPUID + ANDL $NEED_EXT_FEATURES_CX, CX + CMPL CX, $NEED_EXT_FEATURES_CX + JNE bad_cpu +#endif + +#ifdef NEED_OS_SUPPORT_AX + XORL CX, CX + XGETBV + ANDL $NEED_OS_SUPPORT_AX, AX + CMPL AX, $NEED_OS_SUPPORT_AX + JNE bad_cpu +#endif + nocpuinfo: // if there is an _cgo_init, call it. MOVQ _cgo_init(SB), AX diff --git a/src/runtime/asm_riscv64.s b/src/runtime/asm_riscv64.s index 531b46927c..0e813189d4 100644 --- a/src/runtime/asm_riscv64.s +++ b/src/runtime/asm_riscv64.s @@ -631,10 +631,10 @@ TEXT ·checkASM(SB),NOSPLIT,$0-1 // The act of CALLing gcWriteBarrier will clobber RA (LR). // It does not clobber any other general-purpose registers, // but may clobber others (e.g., floating point registers). -TEXT runtime·gcWriteBarrier(SB),NOSPLIT,$216 +TEXT runtime·gcWriteBarrier(SB),NOSPLIT,$208 // Save the registers clobbered by the fast path. - MOV A0, 25*8(X2) - MOV A1, 26*8(X2) + MOV A0, 24*8(X2) + MOV A1, 25*8(X2) MOV g_m(g), A0 MOV m_p(A0), A0 MOV (p_wbBuf+wbBuf_next)(A0), A1 @@ -650,8 +650,8 @@ TEXT runtime·gcWriteBarrier(SB),NOSPLIT,$216 // Is the buffer full? BEQ A1, T6, flush ret: - MOV 25*8(X2), A0 - MOV 26*8(X2), A1 + MOV 24*8(X2), A0 + MOV 25*8(X2), A1 // Do the write. MOV T1, (T0) RET @@ -664,34 +664,34 @@ flush: // X0 is zero register // X1 is LR, saved by prologue // X2 is SP - MOV X3, 3*8(X2) + // X3 is GP // X4 is TP // X5 is first arg to wbBufFlush (T0) // X6 is second arg to wbBufFlush (T1) - MOV X7, 4*8(X2) - MOV X8, 5*8(X2) - MOV X9, 6*8(X2) + MOV X7, 3*8(X2) + MOV X8, 4*8(X2) + MOV X9, 5*8(X2) // X10 already saved (A0) // X11 already saved (A1) - MOV X12, 7*8(X2) - MOV X13, 8*8(X2) - MOV X14, 9*8(X2) - MOV X15, 10*8(X2) - MOV X16, 11*8(X2) - MOV X17, 12*8(X2) - MOV X18, 13*8(X2) - MOV X19, 14*8(X2) - MOV X20, 15*8(X2) - MOV X21, 16*8(X2) - MOV X22, 17*8(X2) - MOV X23, 18*8(X2) - MOV X24, 19*8(X2) - MOV X25, 20*8(X2) - MOV X26, 21*8(X2) + MOV X12, 6*8(X2) + MOV X13, 7*8(X2) + MOV X14, 8*8(X2) + MOV X15, 9*8(X2) + MOV X16, 10*8(X2) + MOV X17, 11*8(X2) + MOV X18, 12*8(X2) + MOV X19, 13*8(X2) + MOV X20, 14*8(X2) + MOV X21, 15*8(X2) + MOV X22, 16*8(X2) + MOV X23, 17*8(X2) + MOV X24, 18*8(X2) + MOV X25, 19*8(X2) + MOV X26, 20*8(X2) // X27 is g. - MOV X28, 22*8(X2) - MOV X29, 23*8(X2) - MOV X30, 24*8(X2) + MOV X28, 21*8(X2) + MOV X29, 22*8(X2) + MOV X30, 23*8(X2) // X31 is tmp register. // This takes arguments T0 and T1. @@ -699,28 +699,27 @@ flush: MOV 1*8(X2), T0 MOV 2*8(X2), T1 - MOV 3*8(X2), X3 - MOV 4*8(X2), X7 - MOV 5*8(X2), X8 - MOV 6*8(X2), X9 - MOV 7*8(X2), X12 - MOV 8*8(X2), X13 - MOV 9*8(X2), X14 - MOV 10*8(X2), X15 - MOV 11*8(X2), X16 - MOV 12*8(X2), X17 - MOV 13*8(X2), X18 - MOV 14*8(X2), X19 - MOV 15*8(X2), X20 - MOV 16*8(X2), X21 - MOV 17*8(X2), X22 - MOV 18*8(X2), X23 - MOV 19*8(X2), X24 - MOV 20*8(X2), X25 - MOV 21*8(X2), X26 - MOV 22*8(X2), X28 - MOV 23*8(X2), X29 - MOV 24*8(X2), X30 + MOV 3*8(X2), X7 + MOV 4*8(X2), X8 + MOV 5*8(X2), X9 + MOV 6*8(X2), X12 + MOV 7*8(X2), X13 + MOV 8*8(X2), X14 + MOV 9*8(X2), X15 + MOV 10*8(X2), X16 + MOV 11*8(X2), X17 + MOV 12*8(X2), X18 + MOV 13*8(X2), X19 + MOV 14*8(X2), X20 + MOV 15*8(X2), X21 + MOV 16*8(X2), X22 + MOV 17*8(X2), X23 + MOV 18*8(X2), X24 + MOV 19*8(X2), X25 + MOV 20*8(X2), X26 + MOV 21*8(X2), X28 + MOV 22*8(X2), X29 + MOV 23*8(X2), X30 JMP ret diff --git a/src/runtime/cgo/asm_riscv64.s b/src/runtime/cgo/asm_riscv64.s index fcd1d36ca8..45151bf02b 100644 --- a/src/runtime/cgo/asm_riscv64.s +++ b/src/runtime/cgo/asm_riscv64.s @@ -14,7 +14,7 @@ TEXT crosscall2(SB),NOSPLIT|NOFRAME,$0 * registers. Note that at procedure entry the first argument is at * 8(X2). */ - ADD $(-8*31), X2 + ADD $(-8*29), X2 MOV X10, (8*1)(X2) // fn unsafe.Pointer MOV X11, (8*2)(X2) // a unsafe.Pointer MOV X13, (8*3)(X2) // ctxt uintptr @@ -30,21 +30,19 @@ TEXT crosscall2(SB),NOSPLIT|NOFRAME,$0 MOV X25, (8*13)(X2) MOV X26, (8*14)(X2) MOV g, (8*15)(X2) - MOV X3, (8*16)(X2) - MOV X4, (8*17)(X2) - MOV X1, (8*18)(X2) - MOVD F8, (8*19)(X2) - MOVD F9, (8*20)(X2) - MOVD F18, (8*21)(X2) - MOVD F19, (8*22)(X2) - MOVD F20, (8*23)(X2) - MOVD F21, (8*24)(X2) - MOVD F22, (8*25)(X2) - MOVD F23, (8*26)(X2) - MOVD F24, (8*27)(X2) - MOVD F25, (8*28)(X2) - MOVD F26, (8*29)(X2) - MOVD F27, (8*30)(X2) + MOV X1, (8*16)(X2) + MOVD F8, (8*17)(X2) + MOVD F9, (8*18)(X2) + MOVD F18, (8*19)(X2) + MOVD F19, (8*20)(X2) + MOVD F20, (8*21)(X2) + MOVD F21, (8*22)(X2) + MOVD F22, (8*23)(X2) + MOVD F23, (8*24)(X2) + MOVD F24, (8*25)(X2) + MOVD F25, (8*26)(X2) + MOVD F26, (8*27)(X2) + MOVD F27, (8*28)(X2) // Initialize Go ABI environment CALL runtime·load_g(SB) @@ -62,21 +60,19 @@ TEXT crosscall2(SB),NOSPLIT|NOFRAME,$0 MOV (8*13)(X2), X25 MOV (8*14)(X2), X26 MOV (8*15)(X2), g - MOV (8*16)(X2), X3 - MOV (8*17)(X2), X4 - MOV (8*18)(X2), X1 - MOVD (8*19)(X2), F8 - MOVD (8*20)(X2), F9 - MOVD (8*21)(X2), F18 - MOVD (8*22)(X2), F19 - MOVD (8*23)(X2), F20 - MOVD (8*24)(X2), F21 - MOVD (8*25)(X2), F22 - MOVD (8*26)(X2), F23 - MOVD (8*27)(X2), F24 - MOVD (8*28)(X2), F25 - MOVD (8*29)(X2), F26 - MOVD (8*30)(X2), F27 - ADD $(8*31), X2 + MOV (8*16)(X2), X1 + MOVD (8*17)(X2), F8 + MOVD (8*18)(X2), F9 + MOVD (8*19)(X2), F18 + MOVD (8*20)(X2), F19 + MOVD (8*21)(X2), F20 + MOVD (8*22)(X2), F21 + MOVD (8*23)(X2), F22 + MOVD (8*24)(X2), F23 + MOVD (8*25)(X2), F24 + MOVD (8*26)(X2), F25 + MOVD (8*27)(X2), F26 + MOVD (8*28)(X2), F27 + ADD $(8*29), X2 RET diff --git a/src/runtime/cgo/gcc_riscv64.S b/src/runtime/cgo/gcc_riscv64.S index fdc77496d9..f429dc64ee 100644 --- a/src/runtime/cgo/gcc_riscv64.S +++ b/src/runtime/cgo/gcc_riscv64.S @@ -8,38 +8,36 @@ * Calling into the gc tool chain, where all registers are caller save. * Called from standard RISCV ELF psABI, where x8-x9, x18-x27, f8-f9 and * f18-f27 are callee-save, so they must be saved explicitly, along with - * x1 (LR), x3 (GP) and x4 (TP). + * x1 (LR). */ .globl crosscall1 crosscall1: - sd x1, -216(sp) - addi sp, sp, -216 - sd x3, 8(sp) - sd x4, 16(sp) - sd x8, 24(sp) - sd x9, 32(sp) - sd x18, 40(sp) - sd x19, 48(sp) - sd x20, 56(sp) - sd x21, 64(sp) - sd x22, 72(sp) - sd x23, 80(sp) - sd x24, 88(sp) - sd x25, 96(sp) - sd x26, 104(sp) - sd x27, 112(sp) - fsd f8, 120(sp) - fsd f9, 128(sp) - fsd f18, 136(sp) - fsd f19, 144(sp) - fsd f20, 152(sp) - fsd f21, 160(sp) - fsd f22, 168(sp) - fsd f23, 176(sp) - fsd f24, 184(sp) - fsd f25, 192(sp) - fsd f26, 200(sp) - fsd f27, 208(sp) + sd x1, -200(sp) + addi sp, sp, -200 + sd x8, 8(sp) + sd x9, 16(sp) + sd x18, 24(sp) + sd x19, 32(sp) + sd x20, 40(sp) + sd x21, 48(sp) + sd x22, 56(sp) + sd x23, 64(sp) + sd x24, 72(sp) + sd x25, 80(sp) + sd x26, 88(sp) + sd x27, 96(sp) + fsd f8, 104(sp) + fsd f9, 112(sp) + fsd f18, 120(sp) + fsd f19, 128(sp) + fsd f20, 136(sp) + fsd f21, 144(sp) + fsd f22, 152(sp) + fsd f23, 160(sp) + fsd f24, 168(sp) + fsd f25, 176(sp) + fsd f26, 184(sp) + fsd f27, 192(sp) // a0 = *fn, a1 = *setg_gcc, a2 = *g mv s1, a0 @@ -49,33 +47,31 @@ crosscall1: jalr ra, s1 // call fn ld x1, 0(sp) - ld x3, 8(sp) - ld x4, 16(sp) - ld x8, 24(sp) - ld x9, 32(sp) - ld x18, 40(sp) - ld x19, 48(sp) - ld x20, 56(sp) - ld x21, 64(sp) - ld x22, 72(sp) - ld x23, 80(sp) - ld x24, 88(sp) - ld x25, 96(sp) - ld x26, 104(sp) - ld x27, 112(sp) - fld f8, 120(sp) - fld f9, 128(sp) - fld f18, 136(sp) - fld f19, 144(sp) - fld f20, 152(sp) - fld f21, 160(sp) - fld f22, 168(sp) - fld f23, 176(sp) - fld f24, 184(sp) - fld f25, 192(sp) - fld f26, 200(sp) - fld f27, 208(sp) - addi sp, sp, 216 + ld x8, 8(sp) + ld x9, 16(sp) + ld x18, 24(sp) + ld x19, 32(sp) + ld x20, 40(sp) + ld x21, 48(sp) + ld x22, 56(sp) + ld x23, 64(sp) + ld x24, 72(sp) + ld x25, 80(sp) + ld x26, 88(sp) + ld x27, 96(sp) + fld f8, 104(sp) + fld f9, 112(sp) + fld f18, 120(sp) + fld f19, 128(sp) + fld f20, 136(sp) + fld f21, 144(sp) + fld f22, 152(sp) + fld f23, 160(sp) + fld f24, 168(sp) + fld f25, 176(sp) + fld f26, 184(sp) + fld f27, 192(sp) + addi sp, sp, 200 jr ra diff --git a/src/runtime/cgo_sigaction.go b/src/runtime/cgo_sigaction.go index 7e8ae28275..a2e12f0f0e 100644 --- a/src/runtime/cgo_sigaction.go +++ b/src/runtime/cgo_sigaction.go @@ -27,7 +27,9 @@ func sigaction(sig uint32, new, old *sigactiont) { if msanenabled && new != nil { msanwrite(unsafe.Pointer(new), unsafe.Sizeof(*new)) } - + if asanenabled && new != nil { + asanwrite(unsafe.Pointer(new), unsafe.Sizeof(*new)) + } if _cgo_sigaction == nil || inForkedChild { sysSigaction(sig, new, old) } else { @@ -79,6 +81,9 @@ func sigaction(sig uint32, new, old *sigactiont) { if msanenabled && old != nil { msanread(unsafe.Pointer(old), unsafe.Sizeof(*old)) } + if asanenabled && old != nil { + asanread(unsafe.Pointer(old), unsafe.Sizeof(*old)) + } } // callCgoSigaction calls the sigaction function in the runtime/cgo package diff --git a/src/runtime/chan_test.go b/src/runtime/chan_test.go index c9ce3ac643..355267c5e3 100644 --- a/src/runtime/chan_test.go +++ b/src/runtime/chan_test.go @@ -624,6 +624,10 @@ func TestShrinkStackDuringBlockedSend(t *testing.T) { } func TestNoShrinkStackWhileParking(t *testing.T) { + if runtime.GOOS == "netbsd" && runtime.GOARCH == "arm64" { + testenv.SkipFlaky(t, 49382) + } + // The goal of this test is to trigger a "racy sudog adjustment" // throw. Basically, there's a window between when a goroutine // becomes available for preemption for stack scanning (and thus, diff --git a/src/runtime/debug.go b/src/runtime/debug.go index 82deefa200..2703a0ce01 100644 --- a/src/runtime/debug.go +++ b/src/runtime/debug.go @@ -61,3 +61,56 @@ func NumGoroutine() int { func debug_modinfo() string { return modinfo } + +// mayMoreStackPreempt is a maymorestack hook that forces a preemption +// at every possible cooperative preemption point. +// +// This is valuable to apply to the runtime, which can be sensitive to +// preemption points. To apply this to all preemption points in the +// runtime and runtime-like code, use the following in bash or zsh: +// +// X=(-{gc,asm}flags={runtime/...,reflect,sync}=-d=maymorestack=runtime.mayMoreStackPreempt) GOFLAGS=${X[@]} +// +// This must be deeply nosplit because it is called from a function +// prologue before the stack is set up and because the compiler will +// call it from any splittable prologue (leading to infinite +// recursion). +// +// Ideally it should also use very little stack because the linker +// doesn't currently account for this in nosplit stack depth checking. +// +//go:nosplit +// +// Ensure mayMoreStackPreempt can be called for all ABIs. +// +//go:linkname mayMoreStackPreempt +func mayMoreStackPreempt() { + // Don't do anything on the g0 or gsignal stack. + g := getg() + if g == g.m.g0 || g == g.m.gsignal { + return + } + // Force a preemption, unless the stack is already poisoned. + if g.stackguard0 < stackPoisonMin { + g.stackguard0 = stackPreempt + } +} + +// mayMoreStackMove is a maymorestack hook that forces stack movement +// at every possible point. +// +// See mayMoreStackPreempt. +// +//go:nosplit +//go:linkname mayMoreStackMove +func mayMoreStackMove() { + // Don't do anything on the g0 or gsignal stack. + g := getg() + if g == g.m.g0 || g == g.m.gsignal { + return + } + // Force stack movement, unless the stack is already poisoned. + if g.stackguard0 < stackPoisonMin { + g.stackguard0 = stackForceMove + } +} diff --git a/src/runtime/defs_linux_386.go b/src/runtime/defs_linux_386.go index d8b546cb4c..24fb58bbf8 100644 --- a/src/runtime/defs_linux_386.go +++ b/src/runtime/defs_linux_386.go @@ -3,6 +3,8 @@ package runtime +import "unsafe" + const ( _EINTR = 0x4 _EAGAIN = 0xb @@ -166,7 +168,7 @@ type sigactiont struct { sa_mask uint64 } -type siginfo struct { +type siginfoFields struct { si_signo int32 si_errno int32 si_code int32 @@ -174,6 +176,13 @@ type siginfo struct { si_addr uint32 } +type siginfo struct { + siginfoFields + + // Pad struct to the max size in the kernel. + _ [_si_max_size - unsafe.Sizeof(siginfoFields{})]byte +} + type stackt struct { ss_sp *byte ss_flags int32 @@ -229,7 +238,7 @@ type itimerval struct { it_value timeval } -type sigevent struct { +type sigeventFields struct { value uintptr signo int32 notify int32 @@ -237,6 +246,13 @@ type sigevent struct { sigev_notify_thread_id int32 } +type sigevent struct { + sigeventFields + + // Pad struct to the max size in the kernel. + _ [_sigev_max_size - unsafe.Sizeof(sigeventFields{})]byte +} + type epollevent struct { events uint32 data [8]byte // to match amd64 diff --git a/src/runtime/defs_linux_amd64.go b/src/runtime/defs_linux_amd64.go index 6afb67f77f..36da22f8ce 100644 --- a/src/runtime/defs_linux_amd64.go +++ b/src/runtime/defs_linux_amd64.go @@ -3,6 +3,8 @@ package runtime +import "unsafe" + const ( _EINTR = 0x4 _EAGAIN = 0xb @@ -128,7 +130,7 @@ type sigactiont struct { sa_mask uint64 } -type siginfo struct { +type siginfoFields struct { si_signo int32 si_errno int32 si_code int32 @@ -136,6 +138,13 @@ type siginfo struct { si_addr uint64 } +type siginfo struct { + siginfoFields + + // Pad struct to the max size in the kernel. + _ [_si_max_size - unsafe.Sizeof(siginfoFields{})]byte +} + type itimerspec struct { it_interval timespec it_value timespec @@ -146,7 +155,7 @@ type itimerval struct { it_value timeval } -type sigevent struct { +type sigeventFields struct { value uintptr signo int32 notify int32 @@ -154,6 +163,13 @@ type sigevent struct { sigev_notify_thread_id int32 } +type sigevent struct { + sigeventFields + + // Pad struct to the max size in the kernel. + _ [_sigev_max_size - unsafe.Sizeof(sigeventFields{})]byte +} + type epollevent struct { events uint32 data [8]byte // unaligned uintptr diff --git a/src/runtime/defs_linux_arm.go b/src/runtime/defs_linux_arm.go index ec24d76326..13d06969e3 100644 --- a/src/runtime/defs_linux_arm.go +++ b/src/runtime/defs_linux_arm.go @@ -4,6 +4,8 @@ package runtime +import "unsafe" + // Constants const ( _EINTR = 0x4 @@ -169,7 +171,7 @@ type itimerval struct { it_value timeval } -type sigevent struct { +type sigeventFields struct { value uintptr signo int32 notify int32 @@ -177,7 +179,14 @@ type sigevent struct { sigev_notify_thread_id int32 } -type siginfo struct { +type sigevent struct { + sigeventFields + + // Pad struct to the max size in the kernel. + _ [_sigev_max_size - unsafe.Sizeof(sigeventFields{})]byte +} + +type siginfoFields struct { si_signo int32 si_errno int32 si_code int32 @@ -185,6 +194,13 @@ type siginfo struct { si_addr uint32 } +type siginfo struct { + siginfoFields + + // Pad struct to the max size in the kernel. + _ [_si_max_size - unsafe.Sizeof(siginfoFields{})]byte +} + type sigactiont struct { sa_handler uintptr sa_flags uint32 diff --git a/src/runtime/defs_linux_arm64.go b/src/runtime/defs_linux_arm64.go index f9f175004b..f9ee9cbc35 100644 --- a/src/runtime/defs_linux_arm64.go +++ b/src/runtime/defs_linux_arm64.go @@ -3,6 +3,8 @@ package runtime +import "unsafe" + const ( _EINTR = 0x4 _EAGAIN = 0xb @@ -128,7 +130,7 @@ type sigactiont struct { sa_mask uint64 } -type siginfo struct { +type siginfoFields struct { si_signo int32 si_errno int32 si_code int32 @@ -136,6 +138,13 @@ type siginfo struct { si_addr uint64 } +type siginfo struct { + siginfoFields + + // Pad struct to the max size in the kernel. + _ [_si_max_size - unsafe.Sizeof(siginfoFields{})]byte +} + type itimerspec struct { it_interval timespec it_value timespec @@ -146,7 +155,7 @@ type itimerval struct { it_value timeval } -type sigevent struct { +type sigeventFields struct { value uintptr signo int32 notify int32 @@ -154,6 +163,13 @@ type sigevent struct { sigev_notify_thread_id int32 } +type sigevent struct { + sigeventFields + + // Pad struct to the max size in the kernel. + _ [_sigev_max_size - unsafe.Sizeof(sigeventFields{})]byte +} + type epollevent struct { events uint32 _pad uint32 diff --git a/src/runtime/defs_linux_mips64x.go b/src/runtime/defs_linux_mips64x.go index 63433cb9be..2601082ee1 100644 --- a/src/runtime/defs_linux_mips64x.go +++ b/src/runtime/defs_linux_mips64x.go @@ -6,6 +6,8 @@ package runtime +import "unsafe" + const ( _EINTR = 0x4 _EAGAIN = 0xb @@ -134,7 +136,7 @@ type sigactiont struct { sa_restorer uintptr } -type siginfo struct { +type siginfoFields struct { si_signo int32 si_code int32 si_errno int32 @@ -143,6 +145,13 @@ type siginfo struct { si_addr uint64 } +type siginfo struct { + siginfoFields + + // Pad struct to the max size in the kernel. + _ [_si_max_size - unsafe.Sizeof(siginfoFields{})]byte +} + type itimerspec struct { it_interval timespec it_value timespec @@ -153,7 +162,7 @@ type itimerval struct { it_value timeval } -type sigevent struct { +type sigeventFields struct { value uintptr signo int32 notify int32 @@ -161,6 +170,13 @@ type sigevent struct { sigev_notify_thread_id int32 } +type sigevent struct { + sigeventFields + + // Pad struct to the max size in the kernel. + _ [_sigev_max_size - unsafe.Sizeof(sigeventFields{})]byte +} + type epollevent struct { events uint32 pad_cgo_0 [4]byte diff --git a/src/runtime/defs_linux_mipsx.go b/src/runtime/defs_linux_mipsx.go index ffbf5051eb..37651ef7e4 100644 --- a/src/runtime/defs_linux_mipsx.go +++ b/src/runtime/defs_linux_mipsx.go @@ -6,6 +6,8 @@ package runtime +import "unsafe" + const ( _EINTR = 0x4 _EAGAIN = 0xb @@ -129,7 +131,7 @@ type sigactiont struct { sa_restorer uintptr } -type siginfo struct { +type siginfoFields struct { si_signo int32 si_code int32 si_errno int32 @@ -137,6 +139,13 @@ type siginfo struct { si_addr uint32 } +type siginfo struct { + siginfoFields + + // Pad struct to the max size in the kernel. + _ [_si_max_size - unsafe.Sizeof(siginfoFields{})]byte +} + type itimerspec struct { it_interval timespec it_value timespec @@ -147,7 +156,7 @@ type itimerval struct { it_value timeval } -type sigevent struct { +type sigeventFields struct { value uintptr signo int32 notify int32 @@ -155,6 +164,13 @@ type sigevent struct { sigev_notify_thread_id int32 } +type sigevent struct { + sigeventFields + + // Pad struct to the max size in the kernel. + _ [_sigev_max_size - unsafe.Sizeof(sigeventFields{})]byte +} + type epollevent struct { events uint32 pad_cgo_0 [4]byte diff --git a/src/runtime/defs_linux_ppc64.go b/src/runtime/defs_linux_ppc64.go index e0775e2974..c7aa7234c1 100644 --- a/src/runtime/defs_linux_ppc64.go +++ b/src/runtime/defs_linux_ppc64.go @@ -3,6 +3,8 @@ package runtime +import "unsafe" + const ( _EINTR = 0x4 _EAGAIN = 0xb @@ -129,7 +131,7 @@ type sigactiont struct { sa_mask uint64 } -type siginfo struct { +type siginfoFields struct { si_signo int32 si_errno int32 si_code int32 @@ -137,6 +139,13 @@ type siginfo struct { si_addr uint64 } +type siginfo struct { + siginfoFields + + // Pad struct to the max size in the kernel. + _ [_si_max_size - unsafe.Sizeof(siginfoFields{})]byte +} + type itimerspec struct { it_interval timespec it_value timespec @@ -147,7 +156,7 @@ type itimerval struct { it_value timeval } -type sigevent struct { +type sigeventFields struct { value uintptr signo int32 notify int32 @@ -155,6 +164,13 @@ type sigevent struct { sigev_notify_thread_id int32 } +type sigevent struct { + sigeventFields + + // Pad struct to the max size in the kernel. + _ [_sigev_max_size - unsafe.Sizeof(sigeventFields{})]byte +} + type epollevent struct { events uint32 pad_cgo_0 [4]byte diff --git a/src/runtime/defs_linux_ppc64le.go b/src/runtime/defs_linux_ppc64le.go index e0775e2974..c7aa7234c1 100644 --- a/src/runtime/defs_linux_ppc64le.go +++ b/src/runtime/defs_linux_ppc64le.go @@ -3,6 +3,8 @@ package runtime +import "unsafe" + const ( _EINTR = 0x4 _EAGAIN = 0xb @@ -129,7 +131,7 @@ type sigactiont struct { sa_mask uint64 } -type siginfo struct { +type siginfoFields struct { si_signo int32 si_errno int32 si_code int32 @@ -137,6 +139,13 @@ type siginfo struct { si_addr uint64 } +type siginfo struct { + siginfoFields + + // Pad struct to the max size in the kernel. + _ [_si_max_size - unsafe.Sizeof(siginfoFields{})]byte +} + type itimerspec struct { it_interval timespec it_value timespec @@ -147,7 +156,7 @@ type itimerval struct { it_value timeval } -type sigevent struct { +type sigeventFields struct { value uintptr signo int32 notify int32 @@ -155,6 +164,13 @@ type sigevent struct { sigev_notify_thread_id int32 } +type sigevent struct { + sigeventFields + + // Pad struct to the max size in the kernel. + _ [_sigev_max_size - unsafe.Sizeof(sigeventFields{})]byte +} + type epollevent struct { events uint32 pad_cgo_0 [4]byte diff --git a/src/runtime/defs_linux_riscv64.go b/src/runtime/defs_linux_riscv64.go index 1052213a4c..332720a8c8 100644 --- a/src/runtime/defs_linux_riscv64.go +++ b/src/runtime/defs_linux_riscv64.go @@ -4,6 +4,8 @@ package runtime +import "unsafe" + const ( _EINTR = 0x4 _EAGAIN = 0xb @@ -126,7 +128,7 @@ type sigactiont struct { sa_mask uint64 } -type siginfo struct { +type siginfoFields struct { si_signo int32 si_errno int32 si_code int32 @@ -134,6 +136,13 @@ type siginfo struct { si_addr uint64 } +type siginfo struct { + siginfoFields + + // Pad struct to the max size in the kernel. + _ [_si_max_size - unsafe.Sizeof(siginfoFields{})]byte +} + type itimerspec struct { it_interval timespec it_value timespec @@ -144,7 +153,7 @@ type itimerval struct { it_value timeval } -type sigevent struct { +type sigeventFields struct { value uintptr signo int32 notify int32 @@ -152,6 +161,13 @@ type sigevent struct { sigev_notify_thread_id int32 } +type sigevent struct { + sigeventFields + + // Pad struct to the max size in the kernel. + _ [_sigev_max_size - unsafe.Sizeof(sigeventFields{})]byte +} + type epollevent struct { events uint32 pad_cgo_0 [4]byte diff --git a/src/runtime/defs_linux_s390x.go b/src/runtime/defs_linux_s390x.go index b072955d4a..740d8100c5 100644 --- a/src/runtime/defs_linux_s390x.go +++ b/src/runtime/defs_linux_s390x.go @@ -4,6 +4,8 @@ package runtime +import "unsafe" + const ( _EINTR = 0x4 _EAGAIN = 0xb @@ -125,7 +127,7 @@ type sigactiont struct { sa_mask uint64 } -type siginfo struct { +type siginfoFields struct { si_signo int32 si_errno int32 si_code int32 @@ -133,6 +135,13 @@ type siginfo struct { si_addr uint64 } +type siginfo struct { + siginfoFields + + // Pad struct to the max size in the kernel. + _ [_si_max_size - unsafe.Sizeof(siginfoFields{})]byte +} + type itimerspec struct { it_interval timespec it_value timespec @@ -143,7 +152,7 @@ type itimerval struct { it_value timeval } -type sigevent struct { +type sigeventFields struct { value uintptr signo int32 notify int32 @@ -151,6 +160,13 @@ type sigevent struct { sigev_notify_thread_id int32 } +type sigevent struct { + sigeventFields + + // Pad struct to the max size in the kernel. + _ [_sigev_max_size - unsafe.Sizeof(sigeventFields{})]byte +} + type epollevent struct { events uint32 pad_cgo_0 [4]byte diff --git a/src/runtime/export_linux_test.go b/src/runtime/export_linux_test.go index b7c901f238..dea94a934c 100644 --- a/src/runtime/export_linux_test.go +++ b/src/runtime/export_linux_test.go @@ -8,11 +8,16 @@ package runtime import "unsafe" +const SiginfoMaxSize = _si_max_size +const SigeventMaxSize = _sigev_max_size + var NewOSProc0 = newosproc0 var Mincore = mincore var Add = add type EpollEvent epollevent +type Siginfo siginfo +type Sigevent sigevent func Epollctl(epfd, op, fd int32, ev unsafe.Pointer) int32 { return epollctl(epfd, op, fd, (*epollevent)(ev)) diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go index 2cc89e7121..b2e64f14ad 100644 --- a/src/runtime/export_test.go +++ b/src/runtime/export_test.go @@ -796,21 +796,17 @@ func (p *PageAlloc) Free(base, npages uintptr) { // None of the tests need any higher-level locking, so we just // take the lock internally. lock(pp.mheapLock) - pp.free(base, npages) + pp.free(base, npages, true) unlock(pp.mheapLock) }) } func (p *PageAlloc) Bounds() (ChunkIdx, ChunkIdx) { return ChunkIdx((*pageAlloc)(p).start), ChunkIdx((*pageAlloc)(p).end) } -func (p *PageAlloc) Scavenge(nbytes uintptr, mayUnlock bool) (r uintptr) { +func (p *PageAlloc) Scavenge(nbytes uintptr) (r uintptr) { pp := (*pageAlloc)(p) systemstack(func() { - // None of the tests need any higher-level locking, so we just - // take the lock internally. - lock(pp.mheapLock) - r = pp.scavenge(nbytes, mayUnlock) - unlock(pp.mheapLock) + r = pp.scavenge(nbytes) }) return } @@ -1246,6 +1242,7 @@ func NewGCController(gcPercent int) *GCController { // on a 32-bit architecture, it may get allocated unaligned // space. g := escape(new(GCController)).(*GCController) + g.gcControllerState.test = true // Mark it as a test copy. g.init(int32(gcPercent)) return g } @@ -1289,7 +1286,9 @@ type GCControllerReviseDelta struct { func (c *GCController) Revise(d GCControllerReviseDelta) { c.heapLive += uint64(d.HeapLive) c.heapScan += uint64(d.HeapScan) - c.scanWork += d.HeapScanWork + d.StackScanWork + d.GlobalsScanWork + c.heapScanWork.Add(d.HeapScanWork) + c.stackScanWork.Add(d.StackScanWork) + c.globalsScanWork.Add(d.GlobalsScanWork) c.revise() } diff --git a/src/runtime/extern.go b/src/runtime/extern.go index b2003ba543..f1f6ea5123 100644 --- a/src/runtime/extern.go +++ b/src/runtime/extern.go @@ -78,6 +78,11 @@ It is a comma-separated list of name=val pairs setting these named variables: If the line ends with "(forced)", this GC was forced by a runtime.GC() call. + harddecommit: setting harddecommit=1 causes memory that is returned to the OS to + also have protections removed on it. This is the only mode of operation on Windows, + but is helpful in debugging scavenger-related issues on other platforms. Currently, + only supported on Linux. + inittrace: setting inittrace=1 causes the runtime to emit a single line to standard error for each package with init work, summarizing the execution time and memory allocation. No information is printed for inits executed as part of plugin loading diff --git a/src/runtime/iface.go b/src/runtime/iface.go index 3d1d9d6ba1..e2bec10948 100644 --- a/src/runtime/iface.go +++ b/src/runtime/iface.go @@ -325,6 +325,9 @@ func convT(t *_type, v unsafe.Pointer) unsafe.Pointer { if msanenabled { msanread(v, t.size) } + if asanenabled { + asanread(v, t.size) + } x := mallocgc(t.size, t, true) typedmemmove(t, x, v) return x @@ -337,6 +340,10 @@ func convTnoptr(t *_type, v unsafe.Pointer) unsafe.Pointer { if msanenabled { msanread(v, t.size) } + if asanenabled { + asanread(v, t.size) + } + x := mallocgc(t.size, t, false) memmove(x, v, t.size) return x diff --git a/src/runtime/lockrank.go b/src/runtime/lockrank.go index dde9f7c21a..4a16bc0ddb 100644 --- a/src/runtime/lockrank.go +++ b/src/runtime/lockrank.go @@ -51,9 +51,9 @@ const ( lockRankItab lockRankReflectOffs lockRankHchan // Multiple hchans acquired in lock order in syncadjustsudogs() + lockRankTraceBuf lockRankFin lockRankNotifyList - lockRankTraceBuf lockRankTraceStrings lockRankMspanSpecial lockRankProf @@ -80,6 +80,7 @@ const ( // Memory-related leaf locks lockRankGlobalAlloc + lockRankPageAllocScav // Other leaf locks lockRankGFree @@ -131,9 +132,9 @@ var lockNames = []string{ lockRankReflectOffs: "reflectOffs", lockRankHchan: "hchan", + lockRankTraceBuf: "traceBuf", lockRankFin: "fin", lockRankNotifyList: "notifyList", - lockRankTraceBuf: "traceBuf", lockRankTraceStrings: "traceStrings", lockRankMspanSpecial: "mspanSpecial", lockRankProf: "prof", @@ -157,7 +158,8 @@ var lockNames = []string{ lockRankMheap: "mheap", lockRankMheapSpecial: "mheapSpecial", - lockRankGlobalAlloc: "globalAlloc.mutex", + lockRankGlobalAlloc: "globalAlloc.mutex", + lockRankPageAllocScav: "pageAlloc.scav.lock", lockRankGFree: "gFree", lockRankHchanLeaf: "hchanLeaf", @@ -208,31 +210,32 @@ var lockPartialOrder [][]lockRank = [][]lockRank{ lockRankItab: {}, lockRankReflectOffs: {lockRankItab}, lockRankHchan: {lockRankScavenge, lockRankSweep, lockRankHchan}, - lockRankFin: {lockRankSysmon, lockRankScavenge, lockRankSched, lockRankAllg, lockRankTimers, lockRankHchan}, - lockRankNotifyList: {}, lockRankTraceBuf: {lockRankSysmon, lockRankScavenge}, + lockRankFin: {lockRankSysmon, lockRankScavenge, lockRankSched, lockRankAllg, lockRankTimers, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf}, + lockRankNotifyList: {}, lockRankTraceStrings: {lockRankTraceBuf}, - lockRankMspanSpecial: {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings}, - lockRankProf: {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings}, - lockRankGcBitsArenas: {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSched, lockRankAllg, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings}, + lockRankMspanSpecial: {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf, lockRankNotifyList, lockRankTraceStrings}, + lockRankProf: {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf, lockRankNotifyList, lockRankTraceStrings}, + lockRankGcBitsArenas: {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSched, lockRankAllg, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf, lockRankNotifyList, lockRankTraceStrings}, lockRankRoot: {}, lockRankTrace: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankAssistQueue, lockRankSweep, lockRankSched, lockRankHchan, lockRankTraceBuf, lockRankTraceStrings, lockRankRoot}, - lockRankTraceStackTab: {lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankSched, lockRankAllg, lockRankTimers, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankRoot, lockRankTrace}, + lockRankTraceStackTab: {lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankSched, lockRankAllg, lockRankTimers, lockRankHchan, lockRankTraceBuf, lockRankFin, lockRankNotifyList, lockRankTraceStrings, lockRankRoot, lockRankTrace}, lockRankNetpollInit: {lockRankTimers}, lockRankRwmutexW: {}, lockRankRwmutexR: {lockRankSysmon, lockRankRwmutexW}, - lockRankSpanSetSpine: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings}, - lockRankGscan: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankTrace, lockRankTraceStackTab, lockRankNetpollInit, lockRankSpanSetSpine}, - lockRankStackpool: {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankTrace, lockRankTraceStackTab, lockRankNetpollInit, lockRankRwmutexR, lockRankSpanSetSpine, lockRankGscan}, - lockRankStackLarge: {lockRankSysmon, lockRankAssistQueue, lockRankSched, lockRankItab, lockRankHchan, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankSpanSetSpine, lockRankGscan}, - lockRankDefer: {}, - lockRankSudog: {lockRankHchan, lockRankNotifyList}, - lockRankWbufSpans: {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceStrings, lockRankMspanSpecial, lockRankProf, lockRankRoot, lockRankGscan, lockRankDefer, lockRankSudog}, - lockRankMheap: {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankMspanSpecial, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankSpanSetSpine, lockRankGscan, lockRankStackpool, lockRankStackLarge, lockRankDefer, lockRankSudog, lockRankWbufSpans}, - lockRankMheapSpecial: {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings}, - lockRankGlobalAlloc: {lockRankProf, lockRankSpanSetSpine, lockRankMheap, lockRankMheapSpecial}, + lockRankSpanSetSpine: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf, lockRankNotifyList, lockRankTraceStrings}, + lockRankGscan: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf, lockRankFin, lockRankNotifyList, lockRankTraceStrings, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankTrace, lockRankTraceStackTab, lockRankNetpollInit, lockRankSpanSetSpine}, + lockRankStackpool: {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf, lockRankFin, lockRankNotifyList, lockRankTraceStrings, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankTrace, lockRankTraceStackTab, lockRankNetpollInit, lockRankRwmutexR, lockRankSpanSetSpine, lockRankGscan}, + lockRankStackLarge: {lockRankSysmon, lockRankAssistQueue, lockRankSched, lockRankItab, lockRankHchan, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankSpanSetSpine, lockRankGscan}, + lockRankDefer: {}, + lockRankSudog: {lockRankHchan, lockRankNotifyList}, + lockRankWbufSpans: {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceStrings, lockRankMspanSpecial, lockRankProf, lockRankRoot, lockRankGscan, lockRankDefer, lockRankSudog}, + lockRankMheap: {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf, lockRankFin, lockRankNotifyList, lockRankTraceStrings, lockRankMspanSpecial, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankSpanSetSpine, lockRankGscan, lockRankStackpool, lockRankStackLarge, lockRankDefer, lockRankSudog, lockRankWbufSpans}, + lockRankMheapSpecial: {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf, lockRankNotifyList, lockRankTraceStrings}, + lockRankGlobalAlloc: {lockRankProf, lockRankSpanSetSpine, lockRankMheap, lockRankMheapSpecial}, + lockRankPageAllocScav: {lockRankMheap}, lockRankGFree: {lockRankSched}, lockRankHchanLeaf: {lockRankGscan, lockRankHchanLeaf}, diff --git a/src/runtime/malloc.go b/src/runtime/malloc.go index 8af1d96f1a..e267e2df23 100644 --- a/src/runtime/malloc.go +++ b/src/runtime/malloc.go @@ -908,6 +908,14 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer { if size == 0 { return unsafe.Pointer(&zerobase) } + userSize := size + if asanenabled { + // Refer to ASAN runtime library, the malloc() function allocates extra memory, + // the redzone, around the user requested memory region. And the redzones are marked + // as unaddressable. We perform the same operations in Go to detect the overflows or + // underflows. + size += computeRZlog(size) + } if debug.malloc { if debug.sbrk != 0 { @@ -971,7 +979,7 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer { mp.mallocing = 1 shouldhelpgc := false - dataSize := size + dataSize := userSize c := getMCache(mp) if c == nil { throw("mallocgc called without a P or outside bootstrapping") @@ -1138,6 +1146,17 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer { msanmalloc(x, size) } + if asanenabled { + // We should only read/write the memory with the size asked by the user. + // The rest of the allocated memory should be poisoned, so that we can report + // errors when accessing poisoned memory. + // The allocated memory is larger than required userSize, it will also include + // redzone and some other padding bytes. + rzBeg := unsafe.Add(x, userSize) + asanpoison(rzBeg, size-userSize) + asanunpoison(x, userSize) + } + if rate := MemProfileRate; rate > 0 { // Note cache c only valid while m acquired; see #47302 if rate != 1 && size < c.nextSample { @@ -1514,3 +1533,26 @@ type notInHeap struct{} func (p *notInHeap) add(bytes uintptr) *notInHeap { return (*notInHeap)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + bytes)) } + +// computeRZlog computes the size of the redzone. +// Refer to the implementation of the compiler-rt. +func computeRZlog(userSize uintptr) uintptr { + switch { + case userSize <= (64 - 16): + return 16 << 0 + case userSize <= (128 - 32): + return 16 << 1 + case userSize <= (512 - 64): + return 16 << 2 + case userSize <= (4096 - 128): + return 16 << 3 + case userSize <= (1<<14)-256: + return 16 << 4 + case userSize <= (1<<15)-512: + return 16 << 5 + case userSize <= (1<<16)-1024: + return 16 << 6 + default: + return 16 << 7 + } +} diff --git a/src/runtime/map.go b/src/runtime/map.go index 985c297cd4..e91b25eaec 100644 --- a/src/runtime/map.go +++ b/src/runtime/map.go @@ -402,6 +402,9 @@ func mapaccess1(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer { if msanenabled && h != nil { msanread(key, t.key.size) } + if asanenabled && h != nil { + asanread(key, t.key.size) + } if h == nil || h.count == 0 { if t.hashMightPanic() { t.hasher(key, 0) // see issue 23734 @@ -460,6 +463,9 @@ func mapaccess2(t *maptype, h *hmap, key unsafe.Pointer) (unsafe.Pointer, bool) if msanenabled && h != nil { msanread(key, t.key.size) } + if asanenabled && h != nil { + asanread(key, t.key.size) + } if h == nil || h.count == 0 { if t.hashMightPanic() { t.hasher(key, 0) // see issue 23734 @@ -582,6 +588,9 @@ func mapassign(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer { if msanenabled { msanread(key, t.key.size) } + if asanenabled { + asanread(key, t.key.size) + } if h.flags&hashWriting != 0 { throw("concurrent map writes") } @@ -693,6 +702,9 @@ func mapdelete(t *maptype, h *hmap, key unsafe.Pointer) { if msanenabled && h != nil { msanread(key, t.key.size) } + if asanenabled && h != nil { + asanread(key, t.key.size) + } if h == nil || h.count == 0 { if t.hashMightPanic() { t.hasher(key, 0) // see issue 23734 diff --git a/src/runtime/mbarrier.go b/src/runtime/mbarrier.go index 3fd1cca42c..0f8b2af5fa 100644 --- a/src/runtime/mbarrier.go +++ b/src/runtime/mbarrier.go @@ -184,6 +184,10 @@ func reflect_typedmemmove(typ *_type, dst, src unsafe.Pointer) { msanwrite(dst, typ.size) msanread(src, typ.size) } + if asanenabled { + asanwrite(dst, typ.size) + asanread(src, typ.size) + } typedmemmove(typ, dst, src) } @@ -262,6 +266,10 @@ func typedslicecopy(typ *_type, dstPtr unsafe.Pointer, dstLen int, srcPtr unsafe msanwrite(dstPtr, uintptr(n)*typ.size) msanread(srcPtr, uintptr(n)*typ.size) } + if asanenabled { + asanwrite(dstPtr, uintptr(n)*typ.size) + asanread(srcPtr, uintptr(n)*typ.size) + } if writeBarrier.cgo { cgoCheckSliceCopy(typ, dstPtr, srcPtr, n) diff --git a/src/runtime/mem_linux.go b/src/runtime/mem_linux.go index 3436851091..f8f9c53170 100644 --- a/src/runtime/mem_linux.go +++ b/src/runtime/mem_linux.go @@ -114,9 +114,29 @@ func sysUnused(v unsafe.Pointer, n uintptr) { atomic.Store(&adviseUnused, _MADV_DONTNEED) madvise(v, n, _MADV_DONTNEED) } + + if debug.harddecommit > 0 { + p, err := mmap(v, n, _PROT_NONE, _MAP_ANON|_MAP_FIXED|_MAP_PRIVATE, -1, 0) + if p != v || err != 0 { + throw("runtime: cannot disable permissions in address space") + } + } } func sysUsed(v unsafe.Pointer, n uintptr) { + if debug.harddecommit > 0 { + p, err := mmap(v, n, _PROT_READ|_PROT_WRITE, _MAP_ANON|_MAP_FIXED|_MAP_PRIVATE, -1, 0) + if err == _ENOMEM { + throw("runtime: out of memory") + } + if p != v || err != 0 { + throw("runtime: cannot remap pages in address space") + } + return + + // Don't do the sysHugePage optimization in hard decommit mode. + // We're breaking up pages everywhere, there's no point. + } // Partially undo the NOHUGEPAGE marks from sysUnused // for whole huge pages between v and v+n. This may // leave huge pages off at the end points v and v+n diff --git a/src/runtime/mgc.go b/src/runtime/mgc.go index 03711a9617..96f4157b59 100644 --- a/src/runtime/mgc.go +++ b/src/runtime/mgc.go @@ -1084,6 +1084,8 @@ func gcMarkTermination(nextTriggerRatio float64) { print(" ms cpu, ", work.heap0>>20, "->", work.heap1>>20, "->", work.heap2>>20, " MB, ", work.heapGoal>>20, " MB goal, ", + gcController.stackScan>>20, " MB stacks, ", + gcController.globalsScan>>20, " MB globals, ", work.maxprocs, " P") if work.userForced { print(" (forced)") diff --git a/src/runtime/mgcmark.go b/src/runtime/mgcmark.go index efda65fe1e..a5129bd1ee 100644 --- a/src/runtime/mgcmark.go +++ b/src/runtime/mgcmark.go @@ -8,6 +8,7 @@ package runtime import ( "internal/goarch" + "internal/goexperiment" "runtime/internal/atomic" "runtime/internal/sys" "unsafe" @@ -151,20 +152,28 @@ var oneptrmask = [...]uint8{1} // // Preemption must be disabled (because this uses a gcWork). // +// Returns the amount of GC work credit produced by the operation. +// If flushBgCredit is true, then that credit is also flushed +// to the background credit pool. +// // nowritebarrier is only advisory here. // //go:nowritebarrier -func markroot(gcw *gcWork, i uint32) { +func markroot(gcw *gcWork, i uint32, flushBgCredit bool) int64 { // Note: if you add a case here, please also update heapdump.go:dumproots. + var workDone int64 + var workCounter *atomic.Int64 switch { case work.baseData <= i && i < work.baseBSS: + workCounter = &gcController.globalsScanWork for _, datap := range activeModules() { - markrootBlock(datap.data, datap.edata-datap.data, datap.gcdatamask.bytedata, gcw, int(i-work.baseData)) + workDone += markrootBlock(datap.data, datap.edata-datap.data, datap.gcdatamask.bytedata, gcw, int(i-work.baseData)) } case work.baseBSS <= i && i < work.baseSpans: + workCounter = &gcController.globalsScanWork for _, datap := range activeModules() { - markrootBlock(datap.bss, datap.ebss-datap.bss, datap.gcbssmask.bytedata, gcw, int(i-work.baseBSS)) + workDone += markrootBlock(datap.bss, datap.ebss-datap.bss, datap.gcbssmask.bytedata, gcw, int(i-work.baseBSS)) } case i == fixedRootFinalizers: @@ -184,6 +193,7 @@ func markroot(gcw *gcWork, i uint32) { default: // the rest is scanning goroutine stacks + workCounter = &gcController.stackScanWork var gp *g if work.baseStacks <= i && i < work.baseEnd { // N.B. Atomic read of allglen in gcMarkRootPrepare @@ -230,7 +240,7 @@ func markroot(gcw *gcWork, i uint32) { if gp.gcscandone { throw("g already scanned") } - scanstack(gp, gcw) + workDone += scanstack(gp, gcw) gp.gcscandone = true resumeG(stopped) @@ -239,13 +249,24 @@ func markroot(gcw *gcWork, i uint32) { } }) } + if goexperiment.PacerRedesign { + if workCounter != nil && workDone != 0 { + workCounter.Add(workDone) + if flushBgCredit { + gcFlushBgCredit(workDone) + } + } + } + return workDone } // markrootBlock scans the shard'th shard of the block of memory [b0, // b0+n0), with the given pointer mask. // +// Returns the amount of work done. +// //go:nowritebarrier -func markrootBlock(b0, n0 uintptr, ptrmask0 *uint8, gcw *gcWork, shard int) { +func markrootBlock(b0, n0 uintptr, ptrmask0 *uint8, gcw *gcWork, shard int) int64 { if rootBlockBytes%(8*goarch.PtrSize) != 0 { // This is necessary to pick byte offsets in ptrmask0. throw("rootBlockBytes must be a multiple of 8*ptrSize") @@ -256,7 +277,7 @@ func markrootBlock(b0, n0 uintptr, ptrmask0 *uint8, gcw *gcWork, shard int) { // These tests are written to avoid any possible overflow. off := uintptr(shard) * rootBlockBytes if off >= n0 { - return + return 0 } b := b0 + off ptrmask := (*uint8)(add(unsafe.Pointer(ptrmask0), uintptr(shard)*(rootBlockBytes/(8*goarch.PtrSize)))) @@ -267,6 +288,7 @@ func markrootBlock(b0, n0 uintptr, ptrmask0 *uint8, gcw *gcWork, shard int) { // Scan this shard. scanblock(b, n, ptrmask, gcw, nil) + return int64(n) } // markrootFreeGStacks frees stacks of dead Gs. @@ -681,6 +703,13 @@ func gcFlushBgCredit(scanWork int64) { // scanstack scans gp's stack, greying all pointers found on the stack. // +// For goexperiment.PacerRedesign: +// Returns the amount of scan work performed, but doesn't update +// gcController.stackScanWork or flush any credit. Any background credit produced +// by this function should be flushed by its caller. scanstack itself can't +// safely flush because it may result in trying to wake up a goroutine that +// was just scanned, resulting in a self-deadlock. +// // scanstack will also shrink the stack if it is safe to do so. If it // is not, it schedules a stack shrink for the next synchronous safe // point. @@ -690,7 +719,7 @@ func gcFlushBgCredit(scanWork int64) { // //go:nowritebarrier //go:systemstack -func scanstack(gp *g, gcw *gcWork) { +func scanstack(gp *g, gcw *gcWork) int64 { if readgstatus(gp)&_Gscan == 0 { print("runtime:scanstack: gp=", gp, ", goid=", gp.goid, ", gp->atomicstatus=", hex(readgstatus(gp)), "\n") throw("scanstack - bad status") @@ -701,7 +730,7 @@ func scanstack(gp *g, gcw *gcWork) { print("runtime: gp=", gp, ", goid=", gp.goid, ", gp->atomicstatus=", readgstatus(gp), "\n") throw("mark - bad status") case _Gdead: - return + return 0 case _Grunning: print("runtime: gp=", gp, ", goid=", gp.goid, ", gp->atomicstatus=", readgstatus(gp), "\n") throw("scanstack: goroutine not stopped") @@ -713,6 +742,15 @@ func scanstack(gp *g, gcw *gcWork) { throw("can't scan our own stack") } + // stackSize is the amount of work we'll be reporting. + // + // We report the total stack size, more than we scan, + // because this number needs to line up with gcControllerState's + // stackScan and scannableStackSize fields. + // + // See the documentation on those fields for more information. + stackSize := gp.stack.hi - gp.stack.lo + if isShrinkStackSafe(gp) { // Shrink the stack if not much of it is being used. shrinkstack(gp) @@ -852,6 +890,7 @@ func scanstack(gp *g, gcw *gcWork) { if state.buf != nil || state.cbuf != nil || state.freeBuf != nil { throw("remaining pointer buffers") } + return int64(stackSize) } // Scan a stack frame: local variables and function arguments/results. @@ -984,7 +1023,7 @@ func gcDrain(gcw *gcWork, flags gcDrainFlags) { flushBgCredit := flags&gcDrainFlushBgCredit != 0 idle := flags&gcDrainIdle != 0 - initScanWork := gcw.scanWork + initScanWork := gcw.heapScanWork // checkWork is the scan work before performing the next // self-preempt check. @@ -1007,7 +1046,7 @@ func gcDrain(gcw *gcWork, flags gcDrainFlags) { if job >= work.markrootJobs { break } - markroot(gcw, job) + markroot(gcw, job, flushBgCredit) if check != nil && check() { goto done } @@ -1046,14 +1085,14 @@ func gcDrain(gcw *gcWork, flags gcDrainFlags) { // Flush background scan work credit to the global // account if we've accumulated enough locally so // mutator assists can draw on it. - if gcw.scanWork >= gcCreditSlack { - atomic.Xaddint64(&gcController.scanWork, gcw.scanWork) + if gcw.heapScanWork >= gcCreditSlack { + gcController.heapScanWork.Add(gcw.heapScanWork) if flushBgCredit { - gcFlushBgCredit(gcw.scanWork - initScanWork) + gcFlushBgCredit(gcw.heapScanWork - initScanWork) initScanWork = 0 } - checkWork -= gcw.scanWork - gcw.scanWork = 0 + checkWork -= gcw.heapScanWork + gcw.heapScanWork = 0 if checkWork <= 0 { checkWork += drainCheckThreshold @@ -1066,12 +1105,12 @@ func gcDrain(gcw *gcWork, flags gcDrainFlags) { done: // Flush remaining scan work credit. - if gcw.scanWork > 0 { - atomic.Xaddint64(&gcController.scanWork, gcw.scanWork) + if gcw.heapScanWork > 0 { + gcController.heapScanWork.Add(gcw.heapScanWork) if flushBgCredit { - gcFlushBgCredit(gcw.scanWork - initScanWork) + gcFlushBgCredit(gcw.heapScanWork - initScanWork) } - gcw.scanWork = 0 + gcw.heapScanWork = 0 } } @@ -1095,10 +1134,10 @@ func gcDrainN(gcw *gcWork, scanWork int64) int64 { // There may already be scan work on the gcw, which we don't // want to claim was done by this call. - workFlushed := -gcw.scanWork + workFlushed := -gcw.heapScanWork gp := getg().m.curg - for !gp.preempt && workFlushed+gcw.scanWork < scanWork { + for !gp.preempt && workFlushed+gcw.heapScanWork < scanWork { // See gcDrain comment. if work.full == 0 { gcw.balance() @@ -1117,13 +1156,13 @@ func gcDrainN(gcw *gcWork, scanWork int64) int64 { if b == 0 { // Try to do a root job. - // - // TODO: Assists should get credit for this - // work. if work.markrootNext < work.markrootJobs { job := atomic.Xadd(&work.markrootNext, +1) - 1 if job < work.markrootJobs { - markroot(gcw, job) + work := markroot(gcw, job, false) + if goexperiment.PacerRedesign { + workFlushed += work + } continue } } @@ -1134,10 +1173,10 @@ func gcDrainN(gcw *gcWork, scanWork int64) int64 { scanobject(b, gcw) // Flush background scan work credit. - if gcw.scanWork >= gcCreditSlack { - atomic.Xaddint64(&gcController.scanWork, gcw.scanWork) - workFlushed += gcw.scanWork - gcw.scanWork = 0 + if gcw.heapScanWork >= gcCreditSlack { + gcController.heapScanWork.Add(gcw.heapScanWork) + workFlushed += gcw.heapScanWork + gcw.heapScanWork = 0 } } @@ -1145,14 +1184,14 @@ func gcDrainN(gcw *gcWork, scanWork int64) int64 { // here because this never flushes to bgScanCredit and // gcw.dispose will flush any remaining work to scanWork. - return workFlushed + gcw.scanWork + return workFlushed + gcw.heapScanWork } // scanblock scans b as scanobject would, but using an explicit // pointer bitmap instead of the heap bitmap. // // This is used to scan non-heap roots, so it does not update -// gcw.bytesMarked or gcw.scanWork. +// gcw.bytesMarked or gcw.heapScanWork. // // If stk != nil, possible stack pointers are also reported to stk.putPtr. //go:nowritebarrier @@ -1282,7 +1321,7 @@ func scanobject(b uintptr, gcw *gcWork) { } } gcw.bytesMarked += uint64(n) - gcw.scanWork += int64(i) + gcw.heapScanWork += int64(i) } // scanConservative scans block [b, b+n) conservatively, treating any @@ -1521,7 +1560,19 @@ func gcmarknewobject(span *mspan, obj, size, scanSize uintptr) { gcw := &getg().m.p.ptr().gcw gcw.bytesMarked += uint64(size) - gcw.scanWork += int64(scanSize) + if !goexperiment.PacerRedesign { + // The old pacer counts newly allocated memory toward + // heapScanWork because heapScan is continuously updated + // throughout the GC cyle with newly allocated memory. However, + // these objects are never actually scanned, so we need + // to account for them in heapScanWork here, "faking" their work. + // Otherwise the pacer will think it's always behind, potentially + // by a large margin. + // + // The new pacer doesn't care about this because it ceases to updated + // heapScan once a GC cycle starts, effectively snapshotting it. + gcw.heapScanWork += int64(scanSize) + } } // gcMarkTinyAllocs greys all active tiny alloc blocks. diff --git a/src/runtime/mgcpacer.go b/src/runtime/mgcpacer.go index 160383db43..5b699cb298 100644 --- a/src/runtime/mgcpacer.go +++ b/src/runtime/mgcpacer.go @@ -6,6 +6,7 @@ package runtime import ( "internal/cpu" + "internal/goexperiment" "runtime/internal/atomic" "unsafe" ) @@ -13,7 +14,8 @@ import ( const ( // gcGoalUtilization is the goal CPU utilization for // marking as a fraction of GOMAXPROCS. - gcGoalUtilization = 0.30 + gcGoalUtilization = goexperiment.PacerRedesignInt*gcBackgroundUtilization + + (1-goexperiment.PacerRedesignInt)*(gcBackgroundUtilization+0.05) // gcBackgroundUtilization is the fixed CPU utilization for background // marking. It must be <= gcGoalUtilization. The difference between @@ -26,10 +28,15 @@ const ( // better control CPU and heap growth. However, the larger the gap, // the more mutator assists are expected to happen, which impact // mutator latency. + // + // If goexperiment.PacerRedesign, the trigger feedback controller + // is replaced with an estimate of the mark/cons ratio that doesn't + // have the same saturation issues, so this is set equal to + // gcGoalUtilization. gcBackgroundUtilization = 0.25 // gcCreditSlack is the amount of scan work credit that can - // accumulate locally before updating gcController.scanWork and, + // accumulate locally before updating gcController.heapScanWork and, // optionally, gcController.bgScanCredit. Lower values give a more // accurate assist ratio and make it more likely that assists will // successfully steal background credit. Higher values reduce memory @@ -46,7 +53,8 @@ const ( gcOverAssistWork = 64 << 10 // defaultHeapMinimum is the value of heapMinimum for GOGC==100. - defaultHeapMinimum = 4 << 20 + defaultHeapMinimum = goexperiment.PacerRedesignInt*(512<<10) + + (1-goexperiment.PacerRedesignInt)*(4<<20) // scannableStackSizeSlack is the bytes of stack space allocated or freed // that can accumulate on a P before updating gcController.stackSize. @@ -108,6 +116,8 @@ type gcControllerState struct { // during mark termination for the next cycle's trigger. // // Protected by mheap_.lock or a STW. + // + // Used if !goexperiment.PacerRedesign. triggerRatio float64 // trigger is the heap size that triggers marking. @@ -122,6 +132,31 @@ type gcControllerState struct { // Protected by mheap_.lock or a STW. trigger uint64 + // consMark is the estimated per-CPU consMark ratio for the application. + // + // It represents the ratio between the application's allocation + // rate, as bytes allocated per CPU-time, and the GC's scan rate, + // as bytes scanned per CPU-time. + // The units of this ratio are (B / cpu-ns) / (B / cpu-ns). + // + // At a high level, this value is computed as the bytes of memory + // allocated (cons) per unit of scan work completed (mark) in a GC + // cycle, divided by the CPU time spent on each activity. + // + // Updated at the end of each GC cycle, in endCycle. + // + // For goexperiment.PacerRedesign. + consMark float64 + + // consMarkController holds the state for the mark-cons ratio + // estimation over time. + // + // Its purpose is to smooth out noisiness in the computation of + // consMark; see consMark for details. + // + // For goexperiment.PacerRedesign. + consMarkController piController + // heapGoal is the goal heapLive for when next GC ends. // Set to ^uint64(0) if disabled. // @@ -164,12 +199,23 @@ type gcControllerState struct { // is the live heap (as counted by heapLive), but omitting // no-scan objects and no-scan tails of objects. // - // Whenever this is updated, call this gcControllerState's - // revise() method. + // For !goexperiment.PacerRedesign: Whenever this is updated, + // call this gcControllerState's revise() method. It is read + // and written atomically or with the world stopped. // - // Read and written atomically or with the world stopped. + // For goexperiment.PacerRedesign: This value is fixed at the + // start of a GC cycle, so during a GC cycle it is safe to + // read without atomics, and it represents the maximum scannable + // heap. heapScan uint64 + // lastHeapScan is the number of bytes of heap that were scanned + // last GC cycle. It is the same as heapMarked, but only + // includes the "scannable" parts of objects. + // + // Updated when the world is stopped. + lastHeapScan uint64 + // stackScan is a snapshot of scannableStackSize taken at each GC // STW pause and is used in pacing decisions. // @@ -179,6 +225,12 @@ type gcControllerState struct { // scannableStackSize is the amount of allocated goroutine stack space in // use by goroutines. // + // This number tracks allocated goroutine stack space rather than used + // goroutine stack space (i.e. what is actually scanned) because used + // goroutine stack space is much harder to measure cheaply. By using + // allocated space, we make an overestimate; this is OK, it's better + // to conservatively overcount than undercount. + // // Read and updated atomically. scannableStackSize uint64 @@ -194,16 +246,26 @@ type gcControllerState struct { // next mark termination. heapMarked uint64 - // scanWork is the total scan work performed this cycle. This - // is updated atomically during the cycle. Updates occur in - // bounded batches, since it is both written and read - // throughout the cycle. At the end of the cycle, this is how + // heapScanWork is the total heap scan work performed this cycle. + // stackScanWork is the total stack scan work performed this cycle. + // globalsScanWork is the total globals scan work performed this cycle. + // + // These are updated atomically during the cycle. Updates occur in + // bounded batches, since they are both written and read + // throughout the cycle. At the end of the cycle, heapScanWork is how // much of the retained heap is scannable. // - // Currently this is the bytes of heap scanned. For most uses, - // this is an opaque unit of work, but for estimation the - // definition is important. - scanWork int64 + // Currently these are measured in bytes. For most uses, this is an + // opaque unit of work, but for estimation the definition is important. + // + // Note that stackScanWork includes all allocated space, not just the + // size of the stack itself, mirroring stackSize. + // + // For !goexperiment.PacerRedesign, stackScanWork and globalsScanWork + // are always zero. + heapScanWork atomic.Int64 + stackScanWork atomic.Int64 + globalsScanWork atomic.Int64 // bgScanCredit is the scan work credit accumulated by the // concurrent background scan. This credit is accumulated by @@ -269,19 +331,45 @@ type gcControllerState struct { // If this is zero, no fractional workers are needed. fractionalUtilizationGoal float64 + // test indicates that this is a test-only copy of gcControllerState. + test bool + _ cpu.CacheLinePad } func (c *gcControllerState) init(gcPercent int32) { c.heapMinimum = defaultHeapMinimum - // Set a reasonable initial GC trigger. - c.triggerRatio = 7 / 8.0 + if goexperiment.PacerRedesign { + c.consMarkController = piController{ + // Tuned first via the Ziegler-Nichols process in simulation, + // then the integral time was manually tuned against real-world + // applications to deal with noisiness in the measured cons/mark + // ratio. + kp: 0.9, + ti: 4.0, - // Fake a heapMarked value so it looks like a trigger at - // heapMinimum is the appropriate growth from heapMarked. - // This will go into computing the initial GC goal. - c.heapMarked = uint64(float64(c.heapMinimum) / (1 + c.triggerRatio)) + // Set a high reset time in GC cycles. + // This is inversely proportional to the rate at which we + // accumulate error from clipping. By making this very high + // we make the accumulation slow. In general, clipping is + // OK in our situation, hence the choice. + // + // Tune this if we get unintended effects from clipping for + // a long time. + tt: 1000, + min: -1000, + max: 1000, + } + } else { + // Set a reasonable initial GC trigger. + c.triggerRatio = 7 / 8.0 + + // Fake a heapMarked value so it looks like a trigger at + // heapMinimum is the appropriate growth from heapMarked. + // This will go into computing the initial GC goal. + c.heapMarked = uint64(float64(c.heapMinimum) / (1 + c.triggerRatio)) + } // This will also compute and set the GC trigger and goal. c.setGCPercent(gcPercent) @@ -291,7 +379,9 @@ func (c *gcControllerState) init(gcPercent int32) { // for a new GC cycle. The caller must hold worldsema and the world // must be stopped. func (c *gcControllerState) startCycle(markStartTime int64, procs int) { - c.scanWork = 0 + c.heapScanWork.Store(0) + c.stackScanWork.Store(0) + c.globalsScanWork.Store(0) c.bgScanCredit = 0 c.assistTime = 0 c.dedicatedMarkTime = 0 @@ -307,8 +397,14 @@ func (c *gcControllerState) startCycle(markStartTime int64, procs int) { // GOGC. Assist is proportional to this distance, so enforce a // minimum distance, even if it means going over the GOGC goal // by a tiny bit. - if c.heapGoal < c.heapLive+1024*1024 { - c.heapGoal = c.heapLive + 1024*1024 + if goexperiment.PacerRedesign { + if c.heapGoal < c.heapLive+64<<10 { + c.heapGoal = c.heapLive + 64<<10 + } + } else { + if c.heapGoal < c.heapLive+1<<20 { + c.heapGoal = c.heapLive + 1<<20 + } } // Compute the background mark utilization goal. In general, @@ -391,32 +487,80 @@ func (c *gcControllerState) revise() { } live := atomic.Load64(&c.heapLive) scan := atomic.Load64(&c.heapScan) - work := atomic.Loadint64(&c.scanWork) + work := c.heapScanWork.Load() + c.stackScanWork.Load() + c.globalsScanWork.Load() // Assume we're under the soft goal. Pace GC to complete at // heapGoal assuming the heap is in steady-state. heapGoal := int64(atomic.Load64(&c.heapGoal)) - // Compute the expected scan work remaining. - // - // This is estimated based on the expected - // steady-state scannable heap. For example, with - // GOGC=100, only half of the scannable heap is - // expected to be live, so that's what we target. - // - // (This is a float calculation to avoid overflowing on - // 100*heapScan.) - scanWorkExpected := int64(float64(scan) * 100 / float64(100+gcPercent)) + var scanWorkExpected int64 + if goexperiment.PacerRedesign { + // The expected scan work is computed as the amount of bytes scanned last + // GC cycle, plus our estimate of stacks and globals work for this cycle. + scanWorkExpected = int64(c.lastHeapScan + c.stackScan + c.globalsScan) - if int64(live) > heapGoal || work > scanWorkExpected { - // We're past the soft goal, or we've already done more scan - // work than we expected. Pace GC so that in the worst case it - // will complete by the hard goal. - const maxOvershoot = 1.1 - heapGoal = int64(float64(heapGoal) * maxOvershoot) + // maxScanWork is a worst-case estimate of the amount of scan work that + // needs to be performed in this GC cycle. Specifically, it represents + // the case where *all* scannable memory turns out to be live. + maxScanWork := int64(scan + c.stackScan + c.globalsScan) + if work > scanWorkExpected { + // We've already done more scan work than expected. Because our expectation + // is based on a steady-state scannable heap size, we assume this means our + // heap is growing. Compute a new heap goal that takes our existing runway + // computed for scanWorkExpected and extrapolates it to maxScanWork, the worst-case + // scan work. This keeps our assist ratio stable if the heap continues to grow. + // + // The effect of this mechanism is that assists stay flat in the face of heap + // growths. It's OK to use more memory this cycle to scan all the live heap, + // because the next GC cycle is inevitably going to use *at least* that much + // memory anyway. + extHeapGoal := int64(float64(heapGoal-int64(c.trigger))/float64(scanWorkExpected)*float64(maxScanWork)) + int64(c.trigger) + scanWorkExpected = maxScanWork - // Compute the upper bound on the scan work remaining. - scanWorkExpected = int64(scan) + // hardGoal is a hard limit on the amount that we're willing to push back the + // heap goal, and that's twice the heap goal (i.e. if GOGC=100 and the heap and/or + // stacks and/or globals grow to twice their size, this limits the current GC cycle's + // growth to 4x the original live heap's size). + // + // This maintains the invariant that we use no more memory than the next GC cycle + // will anyway. + hardGoal := int64((1.0 + float64(gcPercent)/100.0) * float64(heapGoal)) + if extHeapGoal > hardGoal { + extHeapGoal = hardGoal + } + heapGoal = extHeapGoal + } + if int64(live) > heapGoal { + // We're already past our heap goal, even the extrapolated one. + // Leave ourselves some extra runway, so in the worst case we + // finish by that point. + const maxOvershoot = 1.1 + heapGoal = int64(float64(heapGoal) * maxOvershoot) + + // Compute the upper bound on the scan work remaining. + scanWorkExpected = maxScanWork + } + } else { + // Compute the expected scan work remaining. + // + // This is estimated based on the expected + // steady-state scannable heap. For example, with + // GOGC=100, only half of the scannable heap is + // expected to be live, so that's what we target. + // + // (This is a float calculation to avoid overflowing on + // 100*heapScan.) + scanWorkExpected = int64(float64(scan) * 100 / float64(100+gcPercent)) + if int64(live) > heapGoal || work > scanWorkExpected { + // We're past the soft goal, or we've already done more scan + // work than we expected. Pace GC so that in the worst case it + // will complete by the hard goal. + const maxOvershoot = 1.1 + heapGoal = int64(float64(heapGoal) * maxOvershoot) + + // Compute the upper bound on the scan work remaining. + scanWorkExpected = int64(scan) + } } // Compute the remaining scan work estimate. @@ -461,7 +605,9 @@ func (c *gcControllerState) revise() { c.assistBytesPerWork.Store(assistBytesPerWork) } -// endCycle computes the trigger ratio for the next cycle. +// endCycle computes the trigger ratio (!goexperiment.PacerRedesign) +// or the consMark estimate (goexperiment.PacerRedesign) for the next cycle. +// Returns the trigger ratio if application, or 0 (goexperiment.PacerRedesign). // userForced indicates whether the current GC cycle was forced // by the application. func (c *gcControllerState) endCycle(now int64, procs int, userForced bool) float64 { @@ -469,6 +615,82 @@ func (c *gcControllerState) endCycle(now int64, procs int, userForced bool) floa // We'll be updating the heap goal soon. gcController.lastHeapGoal = gcController.heapGoal + // Compute the duration of time for which assists were turned on. + assistDuration := now - c.markStartTime + + // Assume background mark hit its utilization goal. + utilization := gcBackgroundUtilization + // Add assist utilization; avoid divide by zero. + if assistDuration > 0 { + utilization += float64(c.assistTime) / float64(assistDuration*int64(procs)) + } + + if goexperiment.PacerRedesign { + if c.heapLive <= c.trigger { + // Shouldn't happen, but let's be very safe about this in case the + // GC is somehow extremely short. + // + // In this case though, the only reasonable value for c.heapLive-c.trigger + // would be 0, which isn't really all that useful, i.e. the GC was so short + // that it didn't matter. + // + // Ignore this case and don't update anything. + return 0 + } + idleUtilization := 0.0 + if assistDuration > 0 { + idleUtilization = float64(c.idleMarkTime) / float64(assistDuration*int64(procs)) + } + // Determine the cons/mark ratio. + // + // The units we want for the numerator and denominator are both B / cpu-ns. + // We get this by taking the bytes allocated or scanned, and divide by the amount of + // CPU time it took for those operations. For allocations, that CPU time is + // + // assistDuration * procs * (1 - utilization) + // + // Where utilization includes just background GC workers and assists. It does *not* + // include idle GC work time, because in theory the mutator is free to take that at + // any point. + // + // For scanning, that CPU time is + // + // assistDuration * procs * (utilization + idleUtilization) + // + // In this case, we *include* idle utilization, because that is additional CPU time that the + // the GC had available to it. + // + // In effect, idle GC time is sort of double-counted here, but it's very weird compared + // to other kinds of GC work, because of how fluid it is. Namely, because the mutator is + // *always* free to take it. + // + // So this calculation is really: + // (heapLive-trigger) / (assistDuration * procs * (1-utilization)) / + // (scanWork) / (assistDuration * procs * (utilization+idleUtilization) + // + // Note that because we only care about the ratio, assistDuration and procs cancel out. + scanWork := c.heapScanWork.Load() + c.stackScanWork.Load() + c.globalsScanWork.Load() + currentConsMark := (float64(c.heapLive-c.trigger) * (utilization + idleUtilization)) / + (float64(scanWork) * (1 - utilization)) + + // Update cons/mark controller. + // Period for this is 1 GC cycle. + oldConsMark := c.consMark + c.consMark = c.consMarkController.next(c.consMark, currentConsMark, 1.0) + + if debug.gcpacertrace > 0 { + printlock() + print("pacer: ", int(utilization*100), "% CPU (", int(gcGoalUtilization*100), " exp.) for ") + print(c.heapScanWork.Load(), "+", c.stackScanWork.Load(), "+", c.globalsScanWork.Load(), " B work (", c.lastHeapScan+c.stackScan+c.globalsScan, " B exp.) ") + print("in ", c.trigger, " B -> ", c.heapLive, " B (∆goal ", int64(c.heapLive)-int64(c.heapGoal), ", cons/mark ", oldConsMark, ")") + println() + printunlock() + } + return 0 + } + + // !goexperiment.PacerRedesign below. + if userForced { // Forced GC means this cycle didn't start at the // trigger, so where it finished isn't good @@ -495,15 +717,6 @@ func (c *gcControllerState) endCycle(now int64, procs int, userForced bool) floa // heap growth is the error. goalGrowthRatio := c.effectiveGrowthRatio() actualGrowthRatio := float64(c.heapLive)/float64(c.heapMarked) - 1 - assistDuration := now - c.markStartTime - - // Assume background mark hit its utilization goal. - utilization := gcBackgroundUtilization - // Add assist utilization; avoid divide by zero. - if assistDuration > 0 { - utilization += float64(c.assistTime) / float64(assistDuration*int64(procs)) - } - triggerError := goalGrowthRatio - c.triggerRatio - utilization/gcGoalUtilization*(actualGrowthRatio-c.triggerRatio) // Finally, we adjust the trigger for next time by this error, @@ -522,7 +735,7 @@ func (c *gcControllerState) endCycle(now int64, procs int, userForced bool) floa H_g := int64(float64(H_m_prev) * (1 + h_g)) u_a := utilization u_g := gcGoalUtilization - W_a := c.scanWork + W_a := c.heapScanWork.Load() print("pacer: H_m_prev=", H_m_prev, " h_t=", h_t, " H_T=", H_T, " h_a=", h_a, " H_a=", H_a, @@ -666,7 +879,8 @@ func (c *gcControllerState) findRunnableGCWorker(_p_ *p) *g { func (c *gcControllerState) resetLive(bytesMarked uint64) { c.heapMarked = bytesMarked c.heapLive = bytesMarked - c.heapScan = uint64(c.scanWork) + c.heapScan = uint64(c.heapScanWork.Load()) + c.lastHeapScan = uint64(c.heapScanWork.Load()) // heapLive was updated, so emit a trace event. if trace.enabled { @@ -700,8 +914,12 @@ func (c *gcControllerState) update(dHeapLive, dHeapScan int64) { traceHeapAlloc() } } - if dHeapScan != 0 { - atomic.Xadd64(&gcController.heapScan, dHeapScan) + // Only update heapScan in the new pacer redesign if we're not + // currently in a GC. + if !goexperiment.PacerRedesign || gcBlackenEnabled == 0 { + if dHeapScan != 0 { + atomic.Xadd64(&gcController.heapScan, dHeapScan) + } } if gcBlackenEnabled != 0 { // gcController.heapLive and heapScan changed. @@ -725,9 +943,10 @@ func (c *gcControllerState) addGlobals(amount int64) { atomic.Xadd64(&c.globalsScan, amount) } -// commit sets the trigger ratio and updates everything -// derived from it: the absolute trigger, the heap goal, mark pacing, -// and sweep pacing. +// commit recomputes all pacing parameters from scratch, namely +// absolute trigger, the heap goal, mark pacing, and sweep pacing. +// +// If goexperiment.PacerRedesign is true, triggerRatio is ignored. // // This can be called any time. If GC is the in the middle of a // concurrent phase, it will adjust the pacing of that phase. @@ -737,8 +956,134 @@ func (c *gcControllerState) addGlobals(amount int64) { // // mheap_.lock must be held or the world must be stopped. func (c *gcControllerState) commit(triggerRatio float64) { - assertWorldStoppedOrLockHeld(&mheap_.lock) + if !c.test { + assertWorldStoppedOrLockHeld(&mheap_.lock) + } + if !goexperiment.PacerRedesign { + c.oldCommit(triggerRatio) + return + } + + // Compute the next GC goal, which is when the allocated heap + // has grown by GOGC/100 over where it started the last cycle, + // plus additional runway for non-heap sources of GC work. + goal := ^uint64(0) + if c.gcPercent >= 0 { + goal = c.heapMarked + (c.heapMarked+atomic.Load64(&c.stackScan)+atomic.Load64(&c.globalsScan))*uint64(c.gcPercent)/100 + } + + // Don't trigger below the minimum heap size. + minTrigger := c.heapMinimum + if !isSweepDone() { + // Concurrent sweep happens in the heap growth + // from gcController.heapLive to trigger, so ensure + // that concurrent sweep has some heap growth + // in which to perform sweeping before we + // start the next GC cycle. + sweepMin := atomic.Load64(&c.heapLive) + sweepMinHeapDistance + if sweepMin > minTrigger { + minTrigger = sweepMin + } + } + + // If we let the trigger go too low, then if the application + // is allocating very rapidly we might end up in a situation + // where we're allocating black during a nearly always-on GC. + // The result of this is a growing heap and ultimately an + // increase in RSS. By capping us at a point >0, we're essentially + // saying that we're OK using more CPU during the GC to prevent + // this growth in RSS. + // + // The current constant was chosen empirically: given a sufficiently + // fast/scalable allocator with 48 Ps that could drive the trigger ratio + // to <0.05, this constant causes applications to retain the same peak + // RSS compared to not having this allocator. + if triggerBound := uint64(0.7*float64(goal-c.heapMarked)) + c.heapMarked; minTrigger < triggerBound { + minTrigger = triggerBound + } + + // For small heaps, set the max trigger point at 95% of the heap goal. + // This ensures we always have *some* headroom when the GC actually starts. + // For larger heaps, set the max trigger point at the goal, minus the + // minimum heap size. + // This choice follows from the fact that the minimum heap size is chosen + // to reflect the costs of a GC with no work to do. With a large heap but + // very little scan work to perform, this gives us exactly as much runway + // as we would need, in the worst case. + maxRunway := uint64(0.95 * float64(goal-c.heapMarked)) + if largeHeapMaxRunway := goal - c.heapMinimum; goal > c.heapMinimum && maxRunway < largeHeapMaxRunway { + maxRunway = largeHeapMaxRunway + } + maxTrigger := maxRunway + c.heapMarked + if maxTrigger < minTrigger { + maxTrigger = minTrigger + } + + // Compute the trigger by using our estimate of the cons/mark ratio. + // + // The idea is to take our expected scan work, and multiply it by + // the cons/mark ratio to determine how long it'll take to complete + // that scan work in terms of bytes allocated. This gives us our GC's + // runway. + // + // However, the cons/mark ratio is a ratio of rates per CPU-second, but + // here we care about the relative rates for some division of CPU + // resources among the mutator and the GC. + // + // To summarize, we have B / cpu-ns, and we want B / ns. We get that + // by multiplying by our desired division of CPU resources. We choose + // to express CPU resources as GOMAPROCS*fraction. Note that because + // we're working with a ratio here, we can omit the number of CPU cores, + // because they'll appear in the numerator and denominator and cancel out. + // As a result, this is basically just "weighing" the cons/mark ratio by + // our desired division of resources. + // + // Furthermore, by setting the trigger so that CPU resources are divided + // this way, assuming that the cons/mark ratio is correct, we make that + // division a reality. + var trigger uint64 + runway := uint64((c.consMark * (1 - gcGoalUtilization) / (gcGoalUtilization)) * float64(c.lastHeapScan+c.stackScan+c.globalsScan)) + if runway > goal { + trigger = minTrigger + } else { + trigger = goal - runway + } + if trigger < minTrigger { + trigger = minTrigger + } + if trigger > maxTrigger { + trigger = maxTrigger + } + if trigger > goal { + goal = trigger + } + + // Commit to the trigger and goal. + c.trigger = trigger + atomic.Store64(&c.heapGoal, goal) + if trace.enabled { + traceHeapGoal() + } + + // Update mark pacing. + if gcphase != _GCoff { + c.revise() + } +} + +// oldCommit sets the trigger ratio and updates everything +// derived from it: the absolute trigger, the heap goal, mark pacing, +// and sweep pacing. +// +// This can be called any time. If GC is the in the middle of a +// concurrent phase, it will adjust the pacing of that phase. +// +// This depends on gcPercent, gcController.heapMarked, and +// gcController.heapLive. These must be up to date. +// +// For !goexperiment.PacerRedesign. +func (c *gcControllerState) oldCommit(triggerRatio float64) { // Compute the next GC goal, which is when the allocated heap // has grown by GOGC/100 over the heap marked by the last // cycle. @@ -842,7 +1187,9 @@ func (c *gcControllerState) commit(triggerRatio float64) { // // mheap_.lock must be held or the world must be stopped. func (c *gcControllerState) effectiveGrowthRatio() float64 { - assertWorldStoppedOrLockHeld(&mheap_.lock) + if !c.test { + assertWorldStoppedOrLockHeld(&mheap_.lock) + } egogc := float64(atomic.Load64(&c.heapGoal)-c.heapMarked) / float64(c.heapMarked) if egogc < 0 { @@ -859,7 +1206,9 @@ func (c *gcControllerState) effectiveGrowthRatio() float64 { // // The world must be stopped, or mheap_.lock must be held. func (c *gcControllerState) setGCPercent(in int32) int32 { - assertWorldStoppedOrLockHeld(&mheap_.lock) + if !c.test { + assertWorldStoppedOrLockHeld(&mheap_.lock) + } out := c.gcPercent if in < 0 { @@ -904,3 +1253,35 @@ func readGOGC() int32 { } return 100 } + +type piController struct { + kp float64 // Proportional constant. + ti float64 // Integral time constant. + tt float64 // Reset time. + + min, max float64 // Output boundaries. + + // PI controller state. + + errIntegral float64 // Integral of the error from t=0 to now. +} + +func (c *piController) next(input, setpoint, period float64) float64 { + // Compute the raw output value. + prop := c.kp * (setpoint - input) + rawOutput := prop + c.errIntegral + + // Clamp rawOutput into output. + output := rawOutput + if output < c.min { + output = c.min + } else if output > c.max { + output = c.max + } + + // Update the controller's state. + if c.ti != 0 && c.tt != 0 { + c.errIntegral += (c.kp*period/c.ti)*(setpoint-input) + (period/c.tt)*(output-rawOutput) + } + return output +} diff --git a/src/runtime/mgcpacer_test.go b/src/runtime/mgcpacer_test.go index 5a9f46c6d1..9ec0e5172b 100644 --- a/src/runtime/mgcpacer_test.go +++ b/src/runtime/mgcpacer_test.go @@ -6,6 +6,7 @@ package runtime_test import ( "fmt" + "internal/goexperiment" "math" "math/rand" . "runtime" @@ -34,12 +35,76 @@ func TestGcPacer(t *testing.T) { checker: func(t *testing.T, c []gcCycleResult) { n := len(c) if n >= 25 { + if goexperiment.PacerRedesign { + // For the pacer redesign, assert something even stronger: at this alloc/scan rate, + // it should be extremely close to the goal utilization. + assertInEpsilon(t, "GC utilization", c[n-1].gcUtilization, GCGoalUtilization, 0.005) + } + // Make sure the pacer settles into a non-degenerate state in at least 25 GC cycles. assertInEpsilon(t, "GC utilization", c[n-1].gcUtilization, c[n-2].gcUtilization, 0.005) assertInRange(t, "goal ratio", c[n-1].goalRatio(), 0.95, 1.05) } }, }, + { + // Same as the steady-state case, but lots of stacks to scan relative to the heap size. + name: "SteadyBigStacks", + gcPercent: 100, + globalsBytes: 32 << 10, + nCores: 8, + allocRate: constant(132.0), + scanRate: constant(1024.0), + growthRate: constant(2.0).sum(ramp(-1.0, 12)), + scannableFrac: constant(1.0), + stackBytes: constant(2048).sum(ramp(128<<20, 8)), + length: 50, + checker: func(t *testing.T, c []gcCycleResult) { + // Check the same conditions as the steady-state case, except the old pacer can't + // really handle this well, so don't check the goal ratio for it. + n := len(c) + if n >= 25 { + if goexperiment.PacerRedesign { + // For the pacer redesign, assert something even stronger: at this alloc/scan rate, + // it should be extremely close to the goal utilization. + assertInEpsilon(t, "GC utilization", c[n-1].gcUtilization, GCGoalUtilization, 0.005) + assertInRange(t, "goal ratio", c[n-1].goalRatio(), 0.95, 1.05) + } + + // Make sure the pacer settles into a non-degenerate state in at least 25 GC cycles. + assertInEpsilon(t, "GC utilization", c[n-1].gcUtilization, c[n-2].gcUtilization, 0.005) + } + }, + }, + { + // Same as the steady-state case, but lots of globals to scan relative to the heap size. + name: "SteadyBigGlobals", + gcPercent: 100, + globalsBytes: 128 << 20, + nCores: 8, + allocRate: constant(132.0), + scanRate: constant(1024.0), + growthRate: constant(2.0).sum(ramp(-1.0, 12)), + scannableFrac: constant(1.0), + stackBytes: constant(8192), + length: 50, + checker: func(t *testing.T, c []gcCycleResult) { + // Check the same conditions as the steady-state case, except the old pacer can't + // really handle this well, so don't check the goal ratio for it. + n := len(c) + if n >= 25 { + if goexperiment.PacerRedesign { + // For the pacer redesign, assert something even stronger: at this alloc/scan rate, + // it should be extremely close to the goal utilization. + assertInEpsilon(t, "GC utilization", c[n-1].gcUtilization, GCGoalUtilization, 0.005) + assertInRange(t, "goal ratio", c[n-1].goalRatio(), 0.95, 1.05) + } + + // Make sure the pacer settles into a non-degenerate state in at least 25 GC cycles. + assertInEpsilon(t, "GC utilization", c[n-1].gcUtilization, c[n-2].gcUtilization, 0.005) + } + }, + }, { // This tests the GC pacer's response to a small change in allocation rate. name: "StepAlloc", @@ -106,6 +171,47 @@ func TestGcPacer(t *testing.T) { } }, }, + { + // Tests the pacer for a high GOGC value with a large heap growth happening + // in the middle. The purpose of the large heap growth is to check if GC + // utilization ends up sensitive + name: "HighGOGC", + gcPercent: 1500, + globalsBytes: 32 << 10, + nCores: 8, + allocRate: random(7, 0x53).offset(165), + scanRate: constant(1024.0), + growthRate: constant(2.0).sum(ramp(-1.0, 12), random(0.01, 0x1), unit(14).delay(25)), + scannableFrac: constant(1.0), + stackBytes: constant(8192), + length: 50, + checker: func(t *testing.T, c []gcCycleResult) { + n := len(c) + if goexperiment.PacerRedesign && n > 12 { + if n == 26 { + // In the 26th cycle there's a heap growth. Overshoot is expected to maintain + // a stable utilization, but we should *never* overshoot more than GOGC of + // the next cycle. + assertInRange(t, "goal ratio", c[n-1].goalRatio(), 0.90, 15) + } else { + // Give a wider goal range here. With such a high GOGC value we're going to be + // forced to undershoot. + // + // TODO(mknyszek): Instead of placing a 0.95 limit on the trigger, make the limit + // based on absolute bytes, that's based somewhat in how the minimum heap size + // is determined. + assertInRange(t, "goal ratio", c[n-1].goalRatio(), 0.90, 1.05) + } + + // Ensure utilization remains stable despite a growth in live heap size + // at GC #25. This test fails prior to the GC pacer redesign. + // + // Because GOGC is so large, we should also be really close to the goal utilization. + assertInEpsilon(t, "GC utilization", c[n-1].gcUtilization, GCGoalUtilization, GCGoalUtilization+0.03) + assertInEpsilon(t, "GC utilization", c[n-1].gcUtilization, c[n-2].gcUtilization, 0.03) + } + }, + }, { // This test makes sure that in the face of a varying (in this case, oscillating) allocation // rate, the pacer does a reasonably good job of staying abreast of the changes. @@ -126,7 +232,12 @@ func TestGcPacer(t *testing.T) { // 1. Utilization isn't varying _too_ much, and // 2. The pacer is mostly keeping up with the goal. assertInRange(t, "goal ratio", c[n-1].goalRatio(), 0.95, 1.05) - assertInRange(t, "GC utilization", c[n-1].gcUtilization, 0.25, 0.4) + if goexperiment.PacerRedesign { + assertInRange(t, "GC utilization", c[n-1].gcUtilization, 0.25, 0.3) + } else { + // The old pacer is messier here, and needs a lot more tolerance. + assertInRange(t, "GC utilization", c[n-1].gcUtilization, 0.25, 0.4) + } } }, }, @@ -149,7 +260,12 @@ func TestGcPacer(t *testing.T) { // 1. Utilization isn't varying _too_ much, and // 2. The pacer is mostly keeping up with the goal. assertInRange(t, "goal ratio", c[n-1].goalRatio(), 0.95, 1.05) - assertInRange(t, "GC utilization", c[n-1].gcUtilization, 0.25, 0.4) + if goexperiment.PacerRedesign { + assertInRange(t, "GC utilization", c[n-1].gcUtilization, 0.25, 0.3) + } else { + // The old pacer is messier here, and needs a lot more tolerance. + assertInRange(t, "GC utilization", c[n-1].gcUtilization, 0.25, 0.4) + } } }, }, @@ -177,10 +293,21 @@ func TestGcPacer(t *testing.T) { // Unlike the other tests, GC utilization here will vary more and tend higher. // Just make sure it's not going too crazy. assertInEpsilon(t, "GC utilization", c[n-1].gcUtilization, c[n-2].gcUtilization, 0.05) - assertInEpsilon(t, "GC utilization", c[n-1].gcUtilization, c[11].gcUtilization, 0.07) + if goexperiment.PacerRedesign { + assertInEpsilon(t, "GC utilization", c[n-1].gcUtilization, c[11].gcUtilization, 0.05) + } else { + // The old pacer is messier here, and needs a little more tolerance. + assertInEpsilon(t, "GC utilization", c[n-1].gcUtilization, c[11].gcUtilization, 0.07) + } } }, }, + // TODO(mknyszek): Write a test that exercises the pacer's hard goal. + // This is difficult in the idealized model this testing framework places + // the pacer in, because the calculated overshoot is directly proportional + // to the runway for the case of the expected work. + // However, it is still possible to trigger this case if something exceptional + // happens between calls to revise; the framework just doesn't support this yet. } { e := e t.Run(e.name, func(t *testing.T) { diff --git a/src/runtime/mgcscavenge.go b/src/runtime/mgcscavenge.go index fb9b5c8694..4a7f2465fd 100644 --- a/src/runtime/mgcscavenge.go +++ b/src/runtime/mgcscavenge.go @@ -125,7 +125,7 @@ func gcPaceScavenger(heapGoal, lastHeapGoal uint64) { // information about the heap yet) so this is fine, and avoids a fault // or garbage data later. if lastHeapGoal == 0 { - mheap_.scavengeGoal = ^uint64(0) + atomic.Store64(&mheap_.scavengeGoal, ^uint64(0)) return } // Compute our scavenging goal. @@ -157,10 +157,10 @@ func gcPaceScavenger(heapGoal, lastHeapGoal uint64) { // the background scavenger. We disable the background scavenger if there's // less than one physical page of work to do because it's not worth it. if retainedNow <= retainedGoal || retainedNow-retainedGoal < uint64(physPageSize) { - mheap_.scavengeGoal = ^uint64(0) + atomic.Store64(&mheap_.scavengeGoal, ^uint64(0)) return } - mheap_.scavengeGoal = retainedGoal + atomic.Store64(&mheap_.scavengeGoal, retainedGoal) } // Sleep/wait state of the background scavenger. @@ -270,49 +270,80 @@ func bgscavenge(c chan int) { c <- 1 goparkunlock(&scavenge.lock, waitReasonGCScavengeWait, traceEvGoBlock, 1) - // Exponentially-weighted moving average of the fraction of time this - // goroutine spends scavenging (that is, percent of a single CPU). - // It represents a measure of scheduling overheads which might extend - // the sleep or the critical time beyond what's expected. Assume no - // overhead to begin with. - // - // TODO(mknyszek): Consider making this based on total CPU time of the - // application (i.e. scavengePercent * GOMAXPROCS). This isn't really - // feasible now because the scavenger acquires the heap lock over the - // scavenging operation, which means scavenging effectively blocks - // allocators and isn't scalable. However, given a scalable allocator, - // it makes sense to also make the scavenger scale with it; if you're - // allocating more frequently, then presumably you're also generating - // more work for the scavenger. - const idealFraction = scavengePercent / 100.0 - scavengeEWMA := float64(idealFraction) + // idealFraction is the ideal % of overall application CPU time that we + // spend scavenging. + idealFraction := float64(scavengePercent) / 100.0 + // Input: fraction of CPU time used. + // Setpoint: idealFraction. + // Output: ratio of critical time to sleep time (determines sleep time). + // + // The output of this controller is somewhat indirect to what we actually + // want to achieve: how much time to sleep for. The reason for this definition + // is to ensure that the controller's outputs have a direct relationship with + // its inputs (as opposed to an inverse relationship), making it somewhat + // easier to reason about for tuning purposes. + critSleepController := piController{ + // Tuned loosely via Ziegler-Nichols process. + kp: 0.3375, + ti: 3.2e6, + tt: 1e9, // 1 second reset time. + + // These ranges seem wide, but we want to give the controller plenty of + // room to hunt for the optimal value. + min: 0.001, // 1:1000 + max: 1000.0, // 1000:1 + } + // It doesn't really matter what value we start at, but we can't be zero, because + // that'll cause divide-by-zero issues. + critSleepRatio := 0.001 for { released := uintptr(0) - - // Time in scavenging critical section. crit := float64(0) - // Run on the system stack since we grab the heap lock, - // and a stack growth with the heap lock means a deadlock. - systemstack(func() { - lock(&mheap_.lock) - + // Spend at least 1 ms scavenging, otherwise the corresponding + // sleep time to maintain our desired utilization is too low to + // be reliable. + const minCritTime = 1e6 + for crit < minCritTime { // If background scavenging is disabled or if there's no work to do just park. - retained, goal := heapRetained(), mheap_.scavengeGoal + retained, goal := heapRetained(), atomic.Load64(&mheap_.scavengeGoal) if retained <= goal { - unlock(&mheap_.lock) - return + break } - // Scavenge one page, and measure the amount of time spent scavenging. - start := nanotime() - released = mheap_.pages.scavenge(physPageSize, true) - mheap_.pages.scav.released += released - crit = float64(nanotime() - start) + // scavengeQuantum is the amount of memory we try to scavenge + // in one go. A smaller value means the scavenger is more responsive + // to the scheduler in case of e.g. preemption. A larger value means + // that the overheads of scavenging are better amortized, so better + // scavenging throughput. + // + // The current value is chosen assuming a cost of ~10µs/physical page + // (this is somewhat pessimistic), which implies a worst-case latency of + // about 160µs for 4 KiB physical pages. The current value is biased + // toward latency over throughput. + const scavengeQuantum = 64 << 10 - unlock(&mheap_.lock) - }) + // Accumulate the amount of time spent scavenging. + start := nanotime() + released = mheap_.pages.scavenge(scavengeQuantum) + atomic.Xadduintptr(&mheap_.pages.scav.released, released) + end := nanotime() + + // On some platforms we may see end >= start if the time it takes to scavenge + // memory is less than the minimum granularity of its clock (e.g. Windows) or + // due to clock bugs. + // + // In this case, just assume scavenging takes 10 µs per regular physical page + // (determined empirically), and conservatively ignore the impact of huge pages + // on timing. + const approxCritNSPerPhysicalPage = 10e3 + if end <= start { + crit += approxCritNSPerPhysicalPage * float64(released/physPageSize) + } else { + crit += float64(end - start) + } + } if released == 0 { lock(&scavenge.lock) @@ -329,18 +360,13 @@ func bgscavenge(c chan int) { throw("released less than one physical page of memory") } - // On some platforms we may see crit as zero if the time it takes to scavenge - // memory is less than the minimum granularity of its clock (e.g. Windows). - // In this case, just assume scavenging takes 10 µs per regular physical page - // (determined empirically), and conservatively ignore the impact of huge pages - // on timing. - // - // We shouldn't ever see a crit value less than zero unless there's a bug of - // some kind, either on our side or in the platform we're running on, but be - // defensive in that case as well. - const approxCritNSPerPhysicalPage = 10e3 - if crit <= 0 { - crit = approxCritNSPerPhysicalPage * float64(released/physPageSize) + if crit < minCritTime { + // This means there wasn't enough work to actually fill up minCritTime. + // That's fine; we shouldn't try to do anything with this information + // because it's going result in a short enough sleep request that things + // will get messy. Just assume we did at least this much work. + // All this means is that we'll sleep longer than we otherwise would have. + crit = minCritTime } // Multiply the critical time by 1 + the ratio of the costs of using @@ -351,41 +377,19 @@ func bgscavenge(c chan int) { // because of the additional overheads of using scavenged memory. crit *= 1 + scavengeCostRatio - // If we spent more than 10 ms (for example, if the OS scheduled us away, or someone - // put their machine to sleep) in the critical section, bound the time we use to - // calculate at 10 ms to avoid letting the sleep time get arbitrarily high. - const maxCrit = 10e6 - if crit > maxCrit { - crit = maxCrit - } + // Go to sleep for our current sleepNS. + slept := scavengeSleep(int64(crit / critSleepRatio)) - // Compute the amount of time to sleep, assuming we want to use at most - // scavengePercent of CPU time. Take into account scheduling overheads - // that may extend the length of our sleep by multiplying by how far - // off we are from the ideal ratio. For example, if we're sleeping too - // much, then scavengeEMWA < idealFraction, so we'll adjust the sleep time - // down. - adjust := scavengeEWMA / idealFraction - sleepTime := int64(adjust * crit / (scavengePercent / 100.0)) + // Calculate the CPU time spent. + // + // This may be slightly inaccurate with respect to GOMAXPROCS, but we're + // recomputing this often enough relative to GOMAXPROCS changes in general + // (it only changes when the world is stopped, and not during a GC) that + // that small inaccuracy is in the noise. + cpuFraction := float64(crit) / ((float64(slept) + crit) * float64(gomaxprocs)) - // Go to sleep. - slept := scavengeSleep(sleepTime) - - // Compute the new ratio. - fraction := crit / (crit + float64(slept)) - - // Set a lower bound on the fraction. - // Due to OS-related anomalies we may "sleep" for an inordinate amount - // of time. Let's avoid letting the ratio get out of hand by bounding - // the sleep time we use in our EWMA. - const minFraction = 1.0 / 1000.0 - if fraction < minFraction { - fraction = minFraction - } - - // Update scavengeEWMA by merging in the new crit/slept ratio. - const alpha = 0.5 - scavengeEWMA = alpha*fraction + (1-alpha)*scavengeEWMA + // Update the critSleepRatio, adjusting until we reach our ideal fraction. + critSleepRatio = critSleepController.next(cpuFraction, idealFraction, float64(slept)+crit) } } @@ -395,16 +399,7 @@ func bgscavenge(c chan int) { // back to the top of the heap. // // Returns the amount of memory scavenged in bytes. -// -// p.mheapLock must be held, but may be temporarily released if -// mayUnlock == true. -// -// Must run on the system stack because p.mheapLock must be held. -// -//go:systemstack -func (p *pageAlloc) scavenge(nbytes uintptr, mayUnlock bool) uintptr { - assertLockHeld(p.mheapLock) - +func (p *pageAlloc) scavenge(nbytes uintptr) uintptr { var ( addrs addrRange gen uint32 @@ -416,9 +411,11 @@ func (p *pageAlloc) scavenge(nbytes uintptr, mayUnlock bool) uintptr { break } } - r, a := p.scavengeOne(addrs, nbytes-released, mayUnlock) - released += r - addrs = a + systemstack(func() { + r, a := p.scavengeOne(addrs, nbytes-released) + released += r + addrs = a + }) } // Only unreserve the space which hasn't been scavenged or searched // to ensure we always make progress. @@ -456,8 +453,9 @@ func printScavTrace(gen uint32, released uintptr, forced bool) { func (p *pageAlloc) scavengeStartGen() { assertLockHeld(p.mheapLock) + lock(&p.scav.lock) if debug.scavtrace > 0 { - printScavTrace(p.scav.gen, p.scav.released, false) + printScavTrace(p.scav.gen, atomic.Loaduintptr(&p.scav.released), false) } p.inUse.cloneInto(&p.scav.inUse) @@ -487,9 +485,10 @@ func (p *pageAlloc) scavengeStartGen() { // arena in size, so virtually every heap has the scavenger on. p.scav.reservationBytes = alignUp(p.inUse.totalBytes, pallocChunkBytes) / scavengeReservationShards p.scav.gen++ - p.scav.released = 0 + atomic.Storeuintptr(&p.scav.released, 0) p.scav.freeHWM = minOffAddr p.scav.scavLWM = maxOffAddr + unlock(&p.scav.lock) } // scavengeReserve reserves a contiguous range of the address space @@ -498,14 +497,9 @@ func (p *pageAlloc) scavengeStartGen() { // first. // // Returns the reserved range and the scavenge generation number for it. -// -// p.mheapLock must be held. -// -// Must run on the system stack because p.mheapLock must be held. -// -//go:systemstack func (p *pageAlloc) scavengeReserve() (addrRange, uint32) { - assertLockHeld(p.mheapLock) + lock(&p.scav.lock) + gen := p.scav.gen // Start by reserving the minimum. r := p.scav.inUse.removeLast(p.scav.reservationBytes) @@ -513,7 +507,8 @@ func (p *pageAlloc) scavengeReserve() (addrRange, uint32) { // Return early if the size is zero; we don't want to use // the bogus address below. if r.size() == 0 { - return r, p.scav.gen + unlock(&p.scav.lock) + return r, gen } // The scavenger requires that base be aligned to a @@ -524,28 +519,26 @@ func (p *pageAlloc) scavengeReserve() (addrRange, uint32) { // Remove from inUse however much extra we just pulled out. p.scav.inUse.removeGreaterEqual(newBase) + unlock(&p.scav.lock) + r.base = offAddr{newBase} - return r, p.scav.gen + return r, gen } // scavengeUnreserve returns an unscavenged portion of a range that was // previously reserved with scavengeReserve. -// -// p.mheapLock must be held. -// -// Must run on the system stack because p.mheapLock must be held. -// -//go:systemstack func (p *pageAlloc) scavengeUnreserve(r addrRange, gen uint32) { - assertLockHeld(p.mheapLock) - - if r.size() == 0 || gen != p.scav.gen { + if r.size() == 0 { return } if r.base.addr()%pallocChunkBytes != 0 { throw("unreserving unaligned region") } - p.scav.inUse.add(r) + lock(&p.scav.lock) + if gen == p.scav.gen { + p.scav.inUse.add(r) + } + unlock(&p.scav.lock) } // scavengeOne walks over address range work until it finds @@ -559,15 +552,10 @@ func (p *pageAlloc) scavengeUnreserve(r addrRange, gen uint32) { // // work's base address must be aligned to pallocChunkBytes. // -// p.mheapLock must be held, but may be temporarily released if -// mayUnlock == true. -// -// Must run on the system stack because p.mheapLock must be held. +// Must run on the systemstack because it acquires p.mheapLock. // //go:systemstack -func (p *pageAlloc) scavengeOne(work addrRange, max uintptr, mayUnlock bool) (uintptr, addrRange) { - assertLockHeld(p.mheapLock) - +func (p *pageAlloc) scavengeOne(work addrRange, max uintptr) (uintptr, addrRange) { // Defensively check if we've received an empty address range. // If so, just return. if work.size() == 0 { @@ -599,40 +587,12 @@ func (p *pageAlloc) scavengeOne(work addrRange, max uintptr, mayUnlock bool) (ui minPages = 1 } - // Helpers for locking and unlocking only if mayUnlock == true. - lockHeap := func() { - if mayUnlock { - lock(p.mheapLock) - } + // Fast path: check the chunk containing the top-most address in work. + if r, w := p.scavengeOneFast(work, minPages, maxPages); r != 0 { + return r, w + } else { + work = w } - unlockHeap := func() { - if mayUnlock { - unlock(p.mheapLock) - } - } - - // Fast path: check the chunk containing the top-most address in work, - // starting at that address's page index in the chunk. - // - // Note that work.end() is exclusive, so get the chunk we care about - // by subtracting 1. - maxAddr := work.limit.addr() - 1 - maxChunk := chunkIndex(maxAddr) - if p.summary[len(p.summary)-1][maxChunk].max() >= uint(minPages) { - // We only bother looking for a candidate if there at least - // minPages free pages at all. - base, npages := p.chunkOf(maxChunk).findScavengeCandidate(chunkPageIndex(maxAddr), minPages, maxPages) - - // If we found something, scavenge it and return! - if npages != 0 { - work.limit = offAddr{p.scavengeRangeLocked(maxChunk, base, npages)} - - assertLockHeld(p.mheapLock) // Must be locked on return. - return uintptr(npages) * pageSize, work - } - } - // Update the limit to reflect the fact that we checked maxChunk already. - work.limit = offAddr{chunkBase(maxChunk)} // findCandidate finds the next scavenge candidate in work optimistically. // @@ -671,37 +631,61 @@ func (p *pageAlloc) scavengeOne(work addrRange, max uintptr, mayUnlock bool) (ui // looking for any free and unscavenged page. If we think we see something, // lock and verify it! for work.size() != 0 { - unlockHeap() // Search for the candidate. candidateChunkIdx, ok := findCandidate(work) - - // Lock the heap. We need to do this now if we found a candidate or not. - // If we did, we'll verify it. If not, we need to lock before returning - // anyway. - lockHeap() - if !ok { // We didn't find a candidate, so we're done. work.limit = work.base break } + // Lock, so we can verify what we found. + lock(p.mheapLock) + // Find, verify, and scavenge if we can. chunk := p.chunkOf(candidateChunkIdx) base, npages := chunk.findScavengeCandidate(pallocChunkPages-1, minPages, maxPages) if npages > 0 { work.limit = offAddr{p.scavengeRangeLocked(candidateChunkIdx, base, npages)} - - assertLockHeld(p.mheapLock) // Must be locked on return. + unlock(p.mheapLock) return uintptr(npages) * pageSize, work } + unlock(p.mheapLock) // We were fooled, so let's continue from where we left off. work.limit = offAddr{chunkBase(candidateChunkIdx)} } + return 0, work +} - assertLockHeld(p.mheapLock) // Must be locked on return. +// scavengeOneFast is the fast path for scavengeOne, which just checks the top +// chunk of work for some pages to scavenge. +// +// Must run on the system stack because it acquires the heap lock. +// +//go:systemstack +func (p *pageAlloc) scavengeOneFast(work addrRange, minPages, maxPages uintptr) (uintptr, addrRange) { + maxAddr := work.limit.addr() - 1 + maxChunk := chunkIndex(maxAddr) + + lock(p.mheapLock) + if p.summary[len(p.summary)-1][maxChunk].max() >= uint(minPages) { + // We only bother looking for a candidate if there at least + // minPages free pages at all. + base, npages := p.chunkOf(maxChunk).findScavengeCandidate(chunkPageIndex(maxAddr), minPages, maxPages) + + // If we found something, scavenge it and return! + if npages != 0 { + work.limit = offAddr{p.scavengeRangeLocked(maxChunk, base, npages)} + unlock(p.mheapLock) + return uintptr(npages) * pageSize, work + } + } + unlock(p.mheapLock) + + // Update the limit to reflect the fact that we checked maxChunk already. + work.limit = offAddr{chunkBase(maxChunk)} return 0, work } @@ -712,38 +696,57 @@ func (p *pageAlloc) scavengeOne(work addrRange, max uintptr, mayUnlock bool) (ui // // Returns the base address of the scavenged region. // -// p.mheapLock must be held. +// p.mheapLock must be held. Unlocks p.mheapLock but reacquires +// it before returning. Must be run on the systemstack as a result. +// +//go:systemstack func (p *pageAlloc) scavengeRangeLocked(ci chunkIdx, base, npages uint) uintptr { assertLockHeld(p.mheapLock) - p.chunkOf(ci).scavenged.setRange(base, npages) - // Compute the full address for the start of the range. addr := chunkBase(ci) + uintptr(base)*pageSize + // Mark the range we're about to scavenge as allocated, because + // we don't want any allocating goroutines to grab it while + // the scavenging is in progress. + if scav := p.allocRange(addr, uintptr(npages)); scav != 0 { + throw("double scavenge") + } + + // With that done, it's safe to unlock. + unlock(p.mheapLock) + // Update the scavenge low watermark. + lock(&p.scav.lock) if oAddr := (offAddr{addr}); oAddr.lessThan(p.scav.scavLWM) { p.scav.scavLWM = oAddr } + unlock(&p.scav.lock) - // Only perform the actual scavenging if we're not in a test. - // It's dangerous to do so otherwise. - if p.test { - return addr + if !p.test { + // Only perform the actual scavenging if we're not in a test. + // It's dangerous to do so otherwise. + sysUnused(unsafe.Pointer(addr), uintptr(npages)*pageSize) + + // Update global accounting only when not in test, otherwise + // the runtime's accounting will be wrong. + nbytes := int64(npages) * pageSize + atomic.Xadd64(&memstats.heap_released, nbytes) + + // Update consistent accounting too. + stats := memstats.heapStats.acquire() + atomic.Xaddint64(&stats.committed, -nbytes) + atomic.Xaddint64(&stats.released, nbytes) + memstats.heapStats.release() } - sysUnused(unsafe.Pointer(addr), uintptr(npages)*pageSize) - // Update global accounting only when not in test, otherwise - // the runtime's accounting will be wrong. - nbytes := int64(npages) * pageSize - atomic.Xadd64(&memstats.heap_released, nbytes) - - // Update consistent accounting too. - stats := memstats.heapStats.acquire() - atomic.Xaddint64(&stats.committed, -nbytes) - atomic.Xaddint64(&stats.released, nbytes) - memstats.heapStats.release() + // Relock the heap, because now we need to make these pages + // available allocation. Free them back to the page allocator. + lock(p.mheapLock) + p.free(addr, uintptr(npages), true) + // Mark the range as scavenged. + p.chunkOf(ci).scavenged.setRange(base, npages) return addr } diff --git a/src/runtime/mgcscavenge_test.go b/src/runtime/mgcscavenge_test.go index 3b12a2e1e6..b186cad2f4 100644 --- a/src/runtime/mgcscavenge_test.go +++ b/src/runtime/mgcscavenge_test.go @@ -430,12 +430,12 @@ func TestPageAllocScavenge(t *testing.T) { } for name, v := range tests { v := v - runTest := func(t *testing.T, mayUnlock bool) { + t.Run(name, func(t *testing.T) { b := NewPageAlloc(v.beforeAlloc, v.beforeScav) defer FreePageAlloc(b) for iter, h := range v.expect { - if got := b.Scavenge(h.request, mayUnlock); got != h.expect { + if got := b.Scavenge(h.request); got != h.expect { t.Fatalf("bad scavenge #%d: want %d, got %d", iter+1, h.expect, got) } } @@ -443,12 +443,6 @@ func TestPageAllocScavenge(t *testing.T) { defer FreePageAlloc(want) checkPageAlloc(t, want, b) - } - t.Run(name, func(t *testing.T) { - runTest(t, false) - }) - t.Run(name+"MayUnlock", func(t *testing.T) { - runTest(t, true) }) } } diff --git a/src/runtime/mgcsweep.go b/src/runtime/mgcsweep.go index b06df32b20..fdbec30cf1 100644 --- a/src/runtime/mgcsweep.go +++ b/src/runtime/mgcsweep.go @@ -563,7 +563,7 @@ func (sl *sweepLocked) sweep(preserve bool) bool { spanHasNoSpecials(s) } - if debug.allocfreetrace != 0 || debug.clobberfree != 0 || raceenabled || msanenabled { + if debug.allocfreetrace != 0 || debug.clobberfree != 0 || raceenabled || msanenabled || asanenabled { // Find all newly freed objects. This doesn't have to // efficient; allocfreetrace has massive overhead. mbits := s.markBitsForBase() @@ -583,6 +583,9 @@ func (sl *sweepLocked) sweep(preserve bool) bool { if msanenabled { msanfree(unsafe.Pointer(x), size) } + if asanenabled { + asanpoison(unsafe.Pointer(x), size) + } } mbits.advance() abits.advance() diff --git a/src/runtime/mgcwork.go b/src/runtime/mgcwork.go index 8787d93d87..9c3f7fd223 100644 --- a/src/runtime/mgcwork.go +++ b/src/runtime/mgcwork.go @@ -77,9 +77,10 @@ type gcWork struct { // into work.bytesMarked by dispose. bytesMarked uint64 - // Scan work performed on this gcWork. This is aggregated into + // Heap scan work performed on this gcWork. This is aggregated into // gcController by dispose and may also be flushed by callers. - scanWork int64 + // Other types of scan work are flushed immediately. + heapScanWork int64 // flushedWork indicates that a non-empty work buffer was // flushed to the global work list since the last gcMarkDone @@ -274,9 +275,9 @@ func (w *gcWork) dispose() { atomic.Xadd64(&work.bytesMarked, int64(w.bytesMarked)) w.bytesMarked = 0 } - if w.scanWork != 0 { - atomic.Xaddint64(&gcController.scanWork, w.scanWork) - w.scanWork = 0 + if w.heapScanWork != 0 { + gcController.heapScanWork.Add(w.heapScanWork) + w.heapScanWork = 0 } } diff --git a/src/runtime/mheap.go b/src/runtime/mheap.go index 5fd036c1b3..ecbd0a3a49 100644 --- a/src/runtime/mheap.go +++ b/src/runtime/mheap.go @@ -80,7 +80,7 @@ type mheap struct { // access (since that may free the backing store). allspans []*mspan // all spans out there - _ uint32 // align uint64 fields on 32-bit for atomics + // _ uint32 // align uint64 fields on 32-bit for atomics // Proportional sweep // @@ -111,6 +111,8 @@ type mheap struct { // scavengeGoal is the amount of total retained heap memory (measured by // heapRetained) that the runtime will try to maintain by returning memory // to the OS. + // + // Accessed atomically. scavengeGoal uint64 // Page reclaimer state @@ -1118,6 +1120,7 @@ func (h *mheap) allocSpan(npages uintptr, typ spanAllocType, spanclass spanClass // Function-global state. gp := getg() base, scav := uintptr(0), uintptr(0) + growth := uintptr(0) // On some platforms we need to provide physical page aligned stack // allocations. Where the page size is less than the physical page @@ -1163,7 +1166,9 @@ func (h *mheap) allocSpan(npages uintptr, typ spanAllocType, spanclass spanClass // Try to acquire a base address. base, scav = h.pages.alloc(npages) if base == 0 { - if !h.grow(npages) { + var ok bool + growth, ok = h.grow(npages) + if !ok { unlock(&h.lock) return nil } @@ -1187,16 +1192,35 @@ func (h *mheap) allocSpan(npages uintptr, typ spanAllocType, spanclass spanClass // Return memory around the aligned allocation. spaceBefore := base - allocBase if spaceBefore > 0 { - h.pages.free(allocBase, spaceBefore/pageSize) + h.pages.free(allocBase, spaceBefore/pageSize, false) } spaceAfter := (allocPages-npages)*pageSize - spaceBefore if spaceAfter > 0 { - h.pages.free(base+npages*pageSize, spaceAfter/pageSize) + h.pages.free(base+npages*pageSize, spaceAfter/pageSize, false) } } unlock(&h.lock) + if growth > 0 { + // We just caused a heap growth, so scavenge down what will soon be used. + // By scavenging inline we deal with the failure to allocate out of + // memory fragments by scavenging the memory fragments that are least + // likely to be re-used. + scavengeGoal := atomic.Load64(&h.scavengeGoal) + if retained := heapRetained(); retained+uint64(growth) > scavengeGoal { + // The scavenging algorithm requires the heap lock to be dropped so it + // can acquire it only sparingly. This is a potentially expensive operation + // so it frees up other goroutines to allocate in the meanwhile. In fact, + // they can make use of the growth we just created. + todo := growth + if overage := uintptr(retained + uint64(growth) - scavengeGoal); todo > overage { + todo = overage + } + h.pages.scavenge(todo) + } + } + HaveSpan: // At this point, both s != nil and base != 0, and the heap // lock is no longer held. Initialize the span. @@ -1309,10 +1333,10 @@ HaveSpan: } // Try to add at least npage pages of memory to the heap, -// returning whether it worked. +// returning how much the heap grew by and whether it worked. // // h.lock must be held. -func (h *mheap) grow(npage uintptr) bool { +func (h *mheap) grow(npage uintptr) (uintptr, bool) { assertLockHeld(&h.lock) // We must grow the heap in whole palloc chunks. @@ -1334,7 +1358,7 @@ func (h *mheap) grow(npage uintptr) bool { av, asize := h.sysAlloc(ask) if av == nil { print("runtime: out of memory: cannot allocate ", ask, "-byte block (", memstats.heap_sys, " in use)\n") - return false + return 0, false } if uintptr(av) == h.curArena.end { @@ -1394,19 +1418,7 @@ func (h *mheap) grow(npage uintptr) bool { // space ready for allocation. h.pages.grow(v, nBase-v) totalGrowth += nBase - v - - // We just caused a heap growth, so scavenge down what will soon be used. - // By scavenging inline we deal with the failure to allocate out of - // memory fragments by scavenging the memory fragments that are least - // likely to be re-used. - if retained := heapRetained(); retained+uint64(totalGrowth) > h.scavengeGoal { - todo := totalGrowth - if overage := uintptr(retained + uint64(totalGrowth) - h.scavengeGoal); todo > overage { - todo = overage - } - h.pages.scavenge(todo, false) - } - return true + return totalGrowth, true } // Free the span back into the heap. @@ -1419,6 +1431,12 @@ func (h *mheap) freeSpan(s *mspan) { bytes := s.npages << _PageShift msanfree(base, bytes) } + if asanenabled { + // Tell asan that this entire span is no longer in use. + base := unsafe.Pointer(s.base()) + bytes := s.npages << _PageShift + asanpoison(base, bytes) + } h.freeSpanLocked(s, spanAllocHeap) unlock(&h.lock) }) @@ -1490,7 +1508,7 @@ func (h *mheap) freeSpanLocked(s *mspan, typ spanAllocType) { memstats.heapStats.release() // Mark the space as free. - h.pages.free(s.base(), s.npages) + h.pages.free(s.base(), s.npages, false) // Free the span structure. We no longer have a use for it. s.state.set(mSpanDead) @@ -1506,13 +1524,19 @@ func (h *mheap) scavengeAll() { // the mheap API. gp := getg() gp.m.mallocing++ + lock(&h.lock) // Start a new scavenge generation so we have a chance to walk // over the whole heap. h.pages.scavengeStartGen() - released := h.pages.scavenge(^uintptr(0), false) - gen := h.pages.scav.gen unlock(&h.lock) + + released := h.pages.scavenge(^uintptr(0)) + + lock(&h.pages.scav.lock) + gen := h.pages.scav.gen + unlock(&h.pages.scav.lock) + gp.m.mallocing-- if debug.scavtrace > 0 { diff --git a/src/runtime/mkpreempt.go b/src/runtime/mkpreempt.go index d662e73813..e8c23d485a 100644 --- a/src/runtime/mkpreempt.go +++ b/src/runtime/mkpreempt.go @@ -504,12 +504,12 @@ func genPPC64() { } func genRISCV64() { - // X0 (zero), X1 (LR), X2 (SP), X4 (TP), X27 (g), X31 (TMP) are special. + // X0 (zero), X1 (LR), X2 (SP), X3 (GP), X4 (TP), X27 (g), X31 (TMP) are special. var l = layout{sp: "X2", stack: 8} - // Add integer registers (X3, X5-X26, X28-30). - for i := 3; i < 31; i++ { - if i == 4 || i == 27 { + // Add integer registers (X5-X26, X28-30). + for i := 5; i < 31; i++ { + if i == 27 { continue } reg := fmt.Sprintf("X%d", i) diff --git a/src/runtime/mpagealloc.go b/src/runtime/mpagealloc.go index 862882cd82..2725e3b7c7 100644 --- a/src/runtime/mpagealloc.go +++ b/src/runtime/mpagealloc.go @@ -226,6 +226,8 @@ type pageAlloc struct { // are currently available. Otherwise one might iterate over unused // ranges. // + // Protected by mheapLock. + // // TODO(mknyszek): Consider changing the definition of the bitmap // such that 1 means free and 0 means in-use so that summaries and // the bitmaps align better on zero-values. @@ -261,29 +263,41 @@ type pageAlloc struct { inUse addrRanges // scav stores the scavenger state. - // - // All fields are protected by mheapLock. scav struct { + lock mutex + // inUse is a slice of ranges of address space which have not // yet been looked at by the scavenger. + // + // Protected by lock. inUse addrRanges // gen is the scavenge generation number. + // + // Protected by lock. gen uint32 // reservationBytes is how large of a reservation should be made // in bytes of address space for each scavenge iteration. + // + // Protected by lock. reservationBytes uintptr // released is the amount of memory released this generation. + // + // Updated atomically. released uintptr // scavLWM is the lowest (offset) address that the scavenger reached this // scavenge generation. + // + // Protected by lock. scavLWM offAddr // freeHWM is the highest (offset) address of a page that was freed to // the page allocator this scavenge generation. + // + // Protected by mheapLock. freeHWM offAddr } @@ -864,17 +878,19 @@ Found: // Must run on the system stack because p.mheapLock must be held. // //go:systemstack -func (p *pageAlloc) free(base, npages uintptr) { +func (p *pageAlloc) free(base, npages uintptr, scavenged bool) { assertLockHeld(p.mheapLock) // If we're freeing pages below the p.searchAddr, update searchAddr. if b := (offAddr{base}); b.lessThan(p.searchAddr) { p.searchAddr = b } - // Update the free high watermark for the scavenger. limit := base + npages*pageSize - 1 - if offLimit := (offAddr{limit}); p.scav.freeHWM.lessThan(offLimit) { - p.scav.freeHWM = offLimit + if !scavenged { + // Update the free high watermark for the scavenger. + if offLimit := (offAddr{limit}); p.scav.freeHWM.lessThan(offLimit) { + p.scav.freeHWM = offLimit + } } if npages == 1 { // Fast path: we're clearing a single bit, and we know exactly diff --git a/src/runtime/mpagecache.go b/src/runtime/mpagecache.go index 4b5c66d8d6..7206e2dbdb 100644 --- a/src/runtime/mpagecache.go +++ b/src/runtime/mpagecache.go @@ -123,9 +123,10 @@ func (p *pageAlloc) allocToCache() pageCache { } c := pageCache{} ci := chunkIndex(p.searchAddr.addr()) // chunk index + var chunk *pallocData if p.summary[len(p.summary)-1][ci] != 0 { // Fast path: there's free pages at or near the searchAddr address. - chunk := p.chunkOf(ci) + chunk = p.chunkOf(ci) j, _ := chunk.find(1, chunkPageIndex(p.searchAddr.addr())) if j == ^uint(0) { throw("bad summary data") @@ -146,7 +147,7 @@ func (p *pageAlloc) allocToCache() pageCache { return pageCache{} } ci := chunkIndex(addr) - chunk := p.chunkOf(ci) + chunk = p.chunkOf(ci) c = pageCache{ base: alignDown(addr, 64*pageSize), cache: ^chunk.pages64(chunkPageIndex(addr)), @@ -154,8 +155,11 @@ func (p *pageAlloc) allocToCache() pageCache { } } - // Set the bits as allocated and clear the scavenged bits. - p.allocRange(c.base, pageCachePages) + // Set the page bits as allocated and clear the scavenged bits, but + // be careful to only set and clear the relevant bits. + cpi := chunkPageIndex(c.base) + chunk.allocPages64(cpi, c.cache) + chunk.scavenged.clearBlock64(cpi, c.cache&c.scav /* free and scavenged */) // Update as an allocation, but note that it's not contiguous. p.update(c.base, pageCachePages, false, true) diff --git a/src/runtime/mpagecache_test.go b/src/runtime/mpagecache_test.go index 2ed0c0aa6a..69084f9a84 100644 --- a/src/runtime/mpagecache_test.go +++ b/src/runtime/mpagecache_test.go @@ -261,17 +261,18 @@ func TestPageAllocAllocToCache(t *testing.T) { t.Skip("skipping because virtual memory is limited; see #36210") } type test struct { - before map[ChunkIdx][]BitRange - scav map[ChunkIdx][]BitRange - hits []PageCache // expected base addresses and patterns - after map[ChunkIdx][]BitRange + beforeAlloc map[ChunkIdx][]BitRange + beforeScav map[ChunkIdx][]BitRange + hits []PageCache // expected base addresses and patterns + afterAlloc map[ChunkIdx][]BitRange + afterScav map[ChunkIdx][]BitRange } tests := map[string]test{ "AllFree": { - before: map[ChunkIdx][]BitRange{ + beforeAlloc: map[ChunkIdx][]BitRange{ BaseChunkIdx: {}, }, - scav: map[ChunkIdx][]BitRange{ + beforeScav: map[ChunkIdx][]BitRange{ BaseChunkIdx: {{1, 1}, {64, 64}}, }, hits: []PageCache{ @@ -280,17 +281,17 @@ func TestPageAllocAllocToCache(t *testing.T) { NewPageCache(PageBase(BaseChunkIdx, 128), ^uint64(0), 0), NewPageCache(PageBase(BaseChunkIdx, 192), ^uint64(0), 0), }, - after: map[ChunkIdx][]BitRange{ + afterAlloc: map[ChunkIdx][]BitRange{ BaseChunkIdx: {{0, 256}}, }, }, "ManyArena": { - before: map[ChunkIdx][]BitRange{ + beforeAlloc: map[ChunkIdx][]BitRange{ BaseChunkIdx: {{0, PallocChunkPages}}, BaseChunkIdx + 1: {{0, PallocChunkPages}}, BaseChunkIdx + 2: {{0, PallocChunkPages - 64}}, }, - scav: map[ChunkIdx][]BitRange{ + beforeScav: map[ChunkIdx][]BitRange{ BaseChunkIdx: {{0, PallocChunkPages}}, BaseChunkIdx + 1: {{0, PallocChunkPages}}, BaseChunkIdx + 2: {}, @@ -298,46 +299,50 @@ func TestPageAllocAllocToCache(t *testing.T) { hits: []PageCache{ NewPageCache(PageBase(BaseChunkIdx+2, PallocChunkPages-64), ^uint64(0), 0), }, - after: map[ChunkIdx][]BitRange{ + afterAlloc: map[ChunkIdx][]BitRange{ BaseChunkIdx: {{0, PallocChunkPages}}, BaseChunkIdx + 1: {{0, PallocChunkPages}}, BaseChunkIdx + 2: {{0, PallocChunkPages}}, }, }, "NotContiguous": { - before: map[ChunkIdx][]BitRange{ + beforeAlloc: map[ChunkIdx][]BitRange{ BaseChunkIdx: {{0, PallocChunkPages}}, BaseChunkIdx + 0xff: {{0, 0}}, }, - scav: map[ChunkIdx][]BitRange{ + beforeScav: map[ChunkIdx][]BitRange{ BaseChunkIdx: {{0, PallocChunkPages}}, BaseChunkIdx + 0xff: {{31, 67}}, }, hits: []PageCache{ NewPageCache(PageBase(BaseChunkIdx+0xff, 0), ^uint64(0), ((uint64(1)<<33)-1)<<31), }, - after: map[ChunkIdx][]BitRange{ + afterAlloc: map[ChunkIdx][]BitRange{ BaseChunkIdx: {{0, PallocChunkPages}}, BaseChunkIdx + 0xff: {{0, 64}}, }, + afterScav: map[ChunkIdx][]BitRange{ + BaseChunkIdx: {{0, PallocChunkPages}}, + BaseChunkIdx + 0xff: {{64, 34}}, + }, }, "First": { - before: map[ChunkIdx][]BitRange{ + beforeAlloc: map[ChunkIdx][]BitRange{ BaseChunkIdx: {{0, 32}, {33, 31}, {96, 32}}, }, - scav: map[ChunkIdx][]BitRange{ + beforeScav: map[ChunkIdx][]BitRange{ BaseChunkIdx: {{1, 4}, {31, 5}, {66, 2}}, }, hits: []PageCache{ NewPageCache(PageBase(BaseChunkIdx, 0), 1<<32, 1<<32), NewPageCache(PageBase(BaseChunkIdx, 64), (uint64(1)<<32)-1, 0x3<<2), }, - after: map[ChunkIdx][]BitRange{ + afterAlloc: map[ChunkIdx][]BitRange{ BaseChunkIdx: {{0, 128}}, }, }, "Fail": { - before: map[ChunkIdx][]BitRange{ + beforeAlloc: map[ChunkIdx][]BitRange{ BaseChunkIdx: {{0, PallocChunkPages}}, }, hits: []PageCache{ @@ -345,10 +350,27 @@ func TestPageAllocAllocToCache(t *testing.T) { NewPageCache(0, 0, 0), NewPageCache(0, 0, 0), }, - after: map[ChunkIdx][]BitRange{ + afterAlloc: map[ChunkIdx][]BitRange{ BaseChunkIdx: {{0, PallocChunkPages}}, }, }, + "RetainScavBits": { + beforeAlloc: map[ChunkIdx][]BitRange{ + BaseChunkIdx: {{0, 1}, {10, 2}}, + }, + beforeScav: map[ChunkIdx][]BitRange{ + BaseChunkIdx: {{0, 4}, {11, 1}}, + }, + hits: []PageCache{ + NewPageCache(PageBase(BaseChunkIdx, 0), ^uint64(0x1|(0x3<<10)), 0x7<<1), + }, + afterAlloc: map[ChunkIdx][]BitRange{ + BaseChunkIdx: {{0, 64}}, + }, + afterScav: map[ChunkIdx][]BitRange{ + BaseChunkIdx: {{0, 1}, {11, 1}}, + }, + }, } if PageAlloc64Bit != 0 { const chunkIdxBigJump = 0x100000 // chunk index offset which translates to O(TiB) @@ -359,11 +381,11 @@ func TestPageAllocAllocToCache(t *testing.T) { sumsPerPhysPage := ChunkIdx(PhysPageSize / PallocSumBytes) baseChunkIdx := BaseChunkIdx &^ (sumsPerPhysPage - 1) tests["DiscontiguousMappedSumBoundary"] = test{ - before: map[ChunkIdx][]BitRange{ + beforeAlloc: map[ChunkIdx][]BitRange{ baseChunkIdx + sumsPerPhysPage - 1: {{0, PallocChunkPages - 1}}, baseChunkIdx + chunkIdxBigJump: {{1, PallocChunkPages - 1}}, }, - scav: map[ChunkIdx][]BitRange{ + beforeScav: map[ChunkIdx][]BitRange{ baseChunkIdx + sumsPerPhysPage - 1: {}, baseChunkIdx + chunkIdxBigJump: {}, }, @@ -372,7 +394,7 @@ func TestPageAllocAllocToCache(t *testing.T) { NewPageCache(PageBase(baseChunkIdx+chunkIdxBigJump, 0), 1, 0), NewPageCache(0, 0, 0), }, - after: map[ChunkIdx][]BitRange{ + afterAlloc: map[ChunkIdx][]BitRange{ baseChunkIdx + sumsPerPhysPage - 1: {{0, PallocChunkPages}}, baseChunkIdx + chunkIdxBigJump: {{0, PallocChunkPages}}, }, @@ -381,7 +403,7 @@ func TestPageAllocAllocToCache(t *testing.T) { for name, v := range tests { v := v t.Run(name, func(t *testing.T) { - b := NewPageAlloc(v.before, v.scav) + b := NewPageAlloc(v.beforeAlloc, v.beforeScav) defer FreePageAlloc(b) for _, expect := range v.hits { @@ -390,7 +412,7 @@ func TestPageAllocAllocToCache(t *testing.T) { return } } - want := NewPageAlloc(v.after, v.scav) + want := NewPageAlloc(v.afterAlloc, v.afterScav) defer FreePageAlloc(want) checkPageAlloc(t, want, b) diff --git a/src/runtime/mpallocbits.go b/src/runtime/mpallocbits.go index ff112300c3..f63164becd 100644 --- a/src/runtime/mpallocbits.go +++ b/src/runtime/mpallocbits.go @@ -57,6 +57,12 @@ func (b *pageBits) setAll() { } } +// setBlock64 sets the 64-bit aligned block of bits containing the i'th bit that +// are set in v. +func (b *pageBits) setBlock64(i uint, v uint64) { + b[i/64] |= v +} + // clear clears bit i of pageBits. func (b *pageBits) clear(i uint) { b[i/64] &^= 1 << (i % 64) @@ -93,6 +99,12 @@ func (b *pageBits) clearAll() { } } +// clearBlock64 clears the 64-bit aligned block of bits containing the i'th bit that +// are set in v. +func (b *pageBits) clearBlock64(i uint, v uint64) { + b[i/64] &^= v +} + // popcntRange counts the number of set bits in the // range [i, i+n). func (b *pageBits) popcntRange(i, n uint) (s uint) { @@ -367,6 +379,12 @@ func (b *pallocBits) pages64(i uint) uint64 { return (*pageBits)(b).block64(i) } +// allocPages64 allocates a 64-bit block of 64 pages aligned to 64 pages according +// to the bits set in alloc. The block set is the one containing the i'th page. +func (b *pallocBits) allocPages64(i uint, alloc uint64) { + (*pageBits)(b).setBlock64(i, alloc) +} + // findBitRange64 returns the bit index of the first set of // n consecutive 1 bits. If no consecutive set of 1 bits of // size n may be found in c, then it returns an integer >= 64. diff --git a/src/runtime/mprof.go b/src/runtime/mprof.go index 0e6043cf2a..b4de8f53a9 100644 --- a/src/runtime/mprof.go +++ b/src/runtime/mprof.go @@ -627,6 +627,9 @@ func record(r *MemProfileRecord, b *bucket) { if msanenabled { msanwrite(unsafe.Pointer(&r.Stack0[0]), unsafe.Sizeof(r.Stack0)) } + if asanenabled { + asanwrite(unsafe.Pointer(&r.Stack0[0]), unsafe.Sizeof(r.Stack0)) + } copy(r.Stack0[:], b.stk()) for i := int(b.nstk); i < len(r.Stack0); i++ { r.Stack0[i] = 0 @@ -680,6 +683,9 @@ func BlockProfile(p []BlockProfileRecord) (n int, ok bool) { if msanenabled { msanwrite(unsafe.Pointer(&r.Stack0[0]), unsafe.Sizeof(r.Stack0)) } + if asanenabled { + asanwrite(unsafe.Pointer(&r.Stack0[0]), unsafe.Sizeof(r.Stack0)) + } i := copy(r.Stack0[:], b.stk()) for ; i < len(r.Stack0); i++ { r.Stack0[i] = 0 diff --git a/src/runtime/mstats.go b/src/runtime/mstats.go index 341ba9a936..c2303e5b8e 100644 --- a/src/runtime/mstats.go +++ b/src/runtime/mstats.go @@ -790,7 +790,15 @@ type consistentHeapStats struct { // // The caller's P must not change between acquire and // release. This also means that the caller should not -// acquire a P or release its P in between. +// acquire a P or release its P in between. A P also must +// not acquire a given consistentHeapStats if it hasn't +// yet released it. +// +// nosplit because a stack growth in this function could +// lead to a stack allocation that could reenter the +// function. +// +//go:nosplit func (m *consistentHeapStats) acquire() *heapStatsDelta { if pp := getg().m.p.ptr(); pp != nil { seq := atomic.Xadd(&pp.statsSeq, 1) @@ -814,6 +822,12 @@ func (m *consistentHeapStats) acquire() *heapStatsDelta { // The caller's P must not change between acquire and // release. This also means that the caller should not // acquire a P or release its P in between. +// +// nosplit because a stack growth in this function could +// lead to a stack allocation that causes another acquire +// before this operation has completed. +// +//go:nosplit func (m *consistentHeapStats) release() { if pp := getg().m.p.ptr(); pp != nil { seq := atomic.Xadd(&pp.statsSeq, 1) diff --git a/src/runtime/os_linux.go b/src/runtime/os_linux.go index 06773c2193..32a1e1b4f7 100644 --- a/src/runtime/os_linux.go +++ b/src/runtime/os_linux.go @@ -440,6 +440,11 @@ func pipe() (r, w int32, errno int32) func pipe2(flags int32) (r, w int32, errno int32) func setNonblock(fd int32) +const ( + _si_max_size = 128 + _sigev_max_size = 64 +) + //go:nosplit //go:nowritebarrierrec func setsig(i uint32, fn uintptr) { @@ -636,12 +641,11 @@ func setThreadCPUProfiler(hz int32) { spec.it_interval.setNsec(1e9 / int64(hz)) var timerid int32 - sevp := &sigevent{ - notify: _SIGEV_THREAD_ID, - signo: _SIGPROF, - sigev_notify_thread_id: int32(mp.procid), - } - ret := timer_create(_CLOCK_THREAD_CPUTIME_ID, sevp, &timerid) + var sevp sigevent + sevp.notify = _SIGEV_THREAD_ID + sevp.signo = _SIGPROF + sevp.sigev_notify_thread_id = int32(mp.procid) + ret := timer_create(_CLOCK_THREAD_CPUTIME_ID, &sevp, &timerid) if ret != 0 { // If we cannot create a timer for this M, leave profileTimerValid false // to fall back to the process-wide setitimer profiler. diff --git a/src/runtime/pprof/pprof_test.go b/src/runtime/pprof/pprof_test.go index 06e0274e9a..417d5034a6 100644 --- a/src/runtime/pprof/pprof_test.go +++ b/src/runtime/pprof/pprof_test.go @@ -20,6 +20,7 @@ import ( "os/exec" "regexp" "runtime" + "runtime/debug" "strings" "sync" "sync/atomic" @@ -133,6 +134,14 @@ func TestCPUProfileMultithreadMagnitude(t *testing.T) { parallelism := runtime.GOMAXPROCS(0) + // This test compares the process's total CPU time against the CPU + // profiler's view of time spent in direct execution of user code. + // Background work, especially from the garbage collector, adds noise to + // that measurement. Disable automatic triggering of the GC, and then + // request a complete GC cycle (up through sweep termination). + defer debug.SetGCPercent(debug.SetGCPercent(-1)) + runtime.GC() + var cpuTime1, cpuTimeN time.Duration p := testCPUProfile(t, stackContains, []string{"runtime/pprof.cpuHog1", "runtime/pprof.cpuHog3"}, avoidFunctions(), func(dur time.Duration) { cpuTime1 = diffCPUTime(t, func() { diff --git a/src/runtime/preempt_riscv64.s b/src/runtime/preempt_riscv64.s index eb68dcba2b..56df6c30e0 100644 --- a/src/runtime/preempt_riscv64.s +++ b/src/runtime/preempt_riscv64.s @@ -4,126 +4,124 @@ #include "textflag.h" TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0 - MOV X1, -472(X2) - ADD $-472, X2 - MOV X3, 8(X2) - MOV X5, 16(X2) - MOV X6, 24(X2) - MOV X7, 32(X2) - MOV X8, 40(X2) - MOV X9, 48(X2) - MOV X10, 56(X2) - MOV X11, 64(X2) - MOV X12, 72(X2) - MOV X13, 80(X2) - MOV X14, 88(X2) - MOV X15, 96(X2) - MOV X16, 104(X2) - MOV X17, 112(X2) - MOV X18, 120(X2) - MOV X19, 128(X2) - MOV X20, 136(X2) - MOV X21, 144(X2) - MOV X22, 152(X2) - MOV X23, 160(X2) - MOV X24, 168(X2) - MOV X25, 176(X2) - MOV X26, 184(X2) - MOV X28, 192(X2) - MOV X29, 200(X2) - MOV X30, 208(X2) - MOVD F0, 216(X2) - MOVD F1, 224(X2) - MOVD F2, 232(X2) - MOVD F3, 240(X2) - MOVD F4, 248(X2) - MOVD F5, 256(X2) - MOVD F6, 264(X2) - MOVD F7, 272(X2) - MOVD F8, 280(X2) - MOVD F9, 288(X2) - MOVD F10, 296(X2) - MOVD F11, 304(X2) - MOVD F12, 312(X2) - MOVD F13, 320(X2) - MOVD F14, 328(X2) - MOVD F15, 336(X2) - MOVD F16, 344(X2) - MOVD F17, 352(X2) - MOVD F18, 360(X2) - MOVD F19, 368(X2) - MOVD F20, 376(X2) - MOVD F21, 384(X2) - MOVD F22, 392(X2) - MOVD F23, 400(X2) - MOVD F24, 408(X2) - MOVD F25, 416(X2) - MOVD F26, 424(X2) - MOVD F27, 432(X2) - MOVD F28, 440(X2) - MOVD F29, 448(X2) - MOVD F30, 456(X2) - MOVD F31, 464(X2) + MOV X1, -464(X2) + ADD $-464, X2 + MOV X5, 8(X2) + MOV X6, 16(X2) + MOV X7, 24(X2) + MOV X8, 32(X2) + MOV X9, 40(X2) + MOV X10, 48(X2) + MOV X11, 56(X2) + MOV X12, 64(X2) + MOV X13, 72(X2) + MOV X14, 80(X2) + MOV X15, 88(X2) + MOV X16, 96(X2) + MOV X17, 104(X2) + MOV X18, 112(X2) + MOV X19, 120(X2) + MOV X20, 128(X2) + MOV X21, 136(X2) + MOV X22, 144(X2) + MOV X23, 152(X2) + MOV X24, 160(X2) + MOV X25, 168(X2) + MOV X26, 176(X2) + MOV X28, 184(X2) + MOV X29, 192(X2) + MOV X30, 200(X2) + MOVD F0, 208(X2) + MOVD F1, 216(X2) + MOVD F2, 224(X2) + MOVD F3, 232(X2) + MOVD F4, 240(X2) + MOVD F5, 248(X2) + MOVD F6, 256(X2) + MOVD F7, 264(X2) + MOVD F8, 272(X2) + MOVD F9, 280(X2) + MOVD F10, 288(X2) + MOVD F11, 296(X2) + MOVD F12, 304(X2) + MOVD F13, 312(X2) + MOVD F14, 320(X2) + MOVD F15, 328(X2) + MOVD F16, 336(X2) + MOVD F17, 344(X2) + MOVD F18, 352(X2) + MOVD F19, 360(X2) + MOVD F20, 368(X2) + MOVD F21, 376(X2) + MOVD F22, 384(X2) + MOVD F23, 392(X2) + MOVD F24, 400(X2) + MOVD F25, 408(X2) + MOVD F26, 416(X2) + MOVD F27, 424(X2) + MOVD F28, 432(X2) + MOVD F29, 440(X2) + MOVD F30, 448(X2) + MOVD F31, 456(X2) CALL ·asyncPreempt2(SB) - MOVD 464(X2), F31 - MOVD 456(X2), F30 - MOVD 448(X2), F29 - MOVD 440(X2), F28 - MOVD 432(X2), F27 - MOVD 424(X2), F26 - MOVD 416(X2), F25 - MOVD 408(X2), F24 - MOVD 400(X2), F23 - MOVD 392(X2), F22 - MOVD 384(X2), F21 - MOVD 376(X2), F20 - MOVD 368(X2), F19 - MOVD 360(X2), F18 - MOVD 352(X2), F17 - MOVD 344(X2), F16 - MOVD 336(X2), F15 - MOVD 328(X2), F14 - MOVD 320(X2), F13 - MOVD 312(X2), F12 - MOVD 304(X2), F11 - MOVD 296(X2), F10 - MOVD 288(X2), F9 - MOVD 280(X2), F8 - MOVD 272(X2), F7 - MOVD 264(X2), F6 - MOVD 256(X2), F5 - MOVD 248(X2), F4 - MOVD 240(X2), F3 - MOVD 232(X2), F2 - MOVD 224(X2), F1 - MOVD 216(X2), F0 - MOV 208(X2), X30 - MOV 200(X2), X29 - MOV 192(X2), X28 - MOV 184(X2), X26 - MOV 176(X2), X25 - MOV 168(X2), X24 - MOV 160(X2), X23 - MOV 152(X2), X22 - MOV 144(X2), X21 - MOV 136(X2), X20 - MOV 128(X2), X19 - MOV 120(X2), X18 - MOV 112(X2), X17 - MOV 104(X2), X16 - MOV 96(X2), X15 - MOV 88(X2), X14 - MOV 80(X2), X13 - MOV 72(X2), X12 - MOV 64(X2), X11 - MOV 56(X2), X10 - MOV 48(X2), X9 - MOV 40(X2), X8 - MOV 32(X2), X7 - MOV 24(X2), X6 - MOV 16(X2), X5 - MOV 8(X2), X3 - MOV 472(X2), X1 + MOVD 456(X2), F31 + MOVD 448(X2), F30 + MOVD 440(X2), F29 + MOVD 432(X2), F28 + MOVD 424(X2), F27 + MOVD 416(X2), F26 + MOVD 408(X2), F25 + MOVD 400(X2), F24 + MOVD 392(X2), F23 + MOVD 384(X2), F22 + MOVD 376(X2), F21 + MOVD 368(X2), F20 + MOVD 360(X2), F19 + MOVD 352(X2), F18 + MOVD 344(X2), F17 + MOVD 336(X2), F16 + MOVD 328(X2), F15 + MOVD 320(X2), F14 + MOVD 312(X2), F13 + MOVD 304(X2), F12 + MOVD 296(X2), F11 + MOVD 288(X2), F10 + MOVD 280(X2), F9 + MOVD 272(X2), F8 + MOVD 264(X2), F7 + MOVD 256(X2), F6 + MOVD 248(X2), F5 + MOVD 240(X2), F4 + MOVD 232(X2), F3 + MOVD 224(X2), F2 + MOVD 216(X2), F1 + MOVD 208(X2), F0 + MOV 200(X2), X30 + MOV 192(X2), X29 + MOV 184(X2), X28 + MOV 176(X2), X26 + MOV 168(X2), X25 + MOV 160(X2), X24 + MOV 152(X2), X23 + MOV 144(X2), X22 + MOV 136(X2), X21 + MOV 128(X2), X20 + MOV 120(X2), X19 + MOV 112(X2), X18 + MOV 104(X2), X17 + MOV 96(X2), X16 + MOV 88(X2), X15 + MOV 80(X2), X14 + MOV 72(X2), X13 + MOV 64(X2), X12 + MOV 56(X2), X11 + MOV 48(X2), X10 + MOV 40(X2), X9 + MOV 32(X2), X8 + MOV 24(X2), X7 + MOV 16(X2), X6 + MOV 8(X2), X5 + MOV 464(X2), X1 MOV (X2), X31 - ADD $480, X2 + ADD $472, X2 JMP (X31) diff --git a/src/runtime/proc.go b/src/runtime/proc.go index 615f53d31f..bf5fa8e4fc 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -2233,6 +2233,9 @@ func newm1(mp *m) { if msanenabled { msanwrite(unsafe.Pointer(&ts), unsafe.Sizeof(ts)) } + if asanenabled { + asanwrite(unsafe.Pointer(&ts), unsafe.Sizeof(ts)) + } execLock.rlock() // Prevent process clone. asmcgocall(_cgo_thread_start, unsafe.Pointer(&ts)) execLock.runlock() @@ -4435,6 +4438,9 @@ retry: if msanenabled { msanmalloc(unsafe.Pointer(gp.stack.lo), gp.stack.hi-gp.stack.lo) } + if asanenabled { + asanunpoison(unsafe.Pointer(gp.stack.lo), gp.stack.hi-gp.stack.lo) + } } return gp } diff --git a/src/runtime/rt0_linux_riscv64.s b/src/runtime/rt0_linux_riscv64.s index f31f7f75e5..d6b8ac85dc 100644 --- a/src/runtime/rt0_linux_riscv64.s +++ b/src/runtime/rt0_linux_riscv64.s @@ -9,6 +9,104 @@ TEXT _rt0_riscv64_linux(SB),NOSPLIT|NOFRAME,$0 ADD $8, X2, A1 // argv JMP main(SB) +// When building with -buildmode=c-shared, this symbol is called when the shared +// library is loaded. +TEXT _rt0_riscv64_linux_lib(SB),NOSPLIT,$224 + // Preserve callee-save registers, along with X1 (LR). + MOV X1, (8*3)(X2) + MOV X8, (8*4)(X2) + MOV X9, (8*5)(X2) + MOV X18, (8*6)(X2) + MOV X19, (8*7)(X2) + MOV X20, (8*8)(X2) + MOV X21, (8*9)(X2) + MOV X22, (8*10)(X2) + MOV X23, (8*11)(X2) + MOV X24, (8*12)(X2) + MOV X25, (8*13)(X2) + MOV X26, (8*14)(X2) + MOV g, (8*15)(X2) + MOVD F8, (8*16)(X2) + MOVD F9, (8*17)(X2) + MOVD F18, (8*18)(X2) + MOVD F19, (8*19)(X2) + MOVD F20, (8*20)(X2) + MOVD F21, (8*21)(X2) + MOVD F22, (8*22)(X2) + MOVD F23, (8*23)(X2) + MOVD F24, (8*24)(X2) + MOVD F25, (8*25)(X2) + MOVD F26, (8*26)(X2) + MOVD F27, (8*27)(X2) + + // Initialize g as nil in case of using g later e.g. sigaction in cgo_sigaction.go + MOV X0, g + + MOV A0, _rt0_riscv64_linux_lib_argc<>(SB) + MOV A1, _rt0_riscv64_linux_lib_argv<>(SB) + + // Synchronous initialization. + MOV $runtime·libpreinit(SB), T0 + JALR RA, T0 + + // Create a new thread to do the runtime initialization and return. + MOV _cgo_sys_thread_create(SB), T0 + BEQZ T0, nocgo + MOV $_rt0_riscv64_linux_lib_go(SB), A0 + MOV $0, A1 + JALR RA, T0 + JMP restore + +nocgo: + MOV $0x800000, A0 // stacksize = 8192KB + MOV $_rt0_riscv64_linux_lib_go(SB), A1 + MOV A0, 8(X2) + MOV A1, 16(X2) + MOV $runtime·newosproc0(SB), T0 + JALR RA, T0 + +restore: + // Restore callee-save registers, along with X1 (LR). + MOV (8*3)(X2), X1 + MOV (8*4)(X2), X8 + MOV (8*5)(X2), X9 + MOV (8*6)(X2), X18 + MOV (8*7)(X2), X19 + MOV (8*8)(X2), X20 + MOV (8*9)(X2), X21 + MOV (8*10)(X2), X22 + MOV (8*11)(X2), X23 + MOV (8*12)(X2), X24 + MOV (8*13)(X2), X25 + MOV (8*14)(X2), X26 + MOV (8*15)(X2), g + MOVD (8*16)(X2), F8 + MOVD (8*17)(X2), F9 + MOVD (8*18)(X2), F18 + MOVD (8*19)(X2), F19 + MOVD (8*20)(X2), F20 + MOVD (8*21)(X2), F21 + MOVD (8*22)(X2), F22 + MOVD (8*23)(X2), F23 + MOVD (8*24)(X2), F24 + MOVD (8*25)(X2), F25 + MOVD (8*26)(X2), F26 + MOVD (8*27)(X2), F27 + + RET + +TEXT _rt0_riscv64_linux_lib_go(SB),NOSPLIT,$0 + MOV _rt0_riscv64_linux_lib_argc<>(SB), A0 + MOV _rt0_riscv64_linux_lib_argv<>(SB), A1 + MOV $runtime·rt0_go(SB), T0 + JALR ZERO, T0 + +DATA _rt0_riscv64_linux_lib_argc<>(SB)/8, $0 +GLOBL _rt0_riscv64_linux_lib_argc<>(SB),NOPTR, $8 +DATA _rt0_riscv64_linux_lib_argv<>(SB)/8, $0 +GLOBL _rt0_riscv64_linux_lib_argv<>(SB),NOPTR, $8 + + TEXT main(SB),NOSPLIT|NOFRAME,$0 MOV $runtime·rt0_go(SB), T0 JALR ZERO, T0 diff --git a/src/runtime/runtime1.go b/src/runtime/runtime1.go index b6c3cbfff4..65e1e0eebc 100644 --- a/src/runtime/runtime1.go +++ b/src/runtime/runtime1.go @@ -315,6 +315,7 @@ var debug struct { schedtrace int32 tracebackancestors int32 asyncpreemptoff int32 + harddecommit int32 // debug.malloc is used as a combined debug check // in the malloc function and should be set @@ -344,6 +345,7 @@ var dbgvars = []dbgVar{ {"tracebackancestors", &debug.tracebackancestors}, {"asyncpreemptoff", &debug.asyncpreemptoff}, {"inittrace", &debug.inittrace}, + {"harddecommit", &debug.harddecommit}, } func parsedebugvars() { diff --git a/src/runtime/runtime_linux_test.go b/src/runtime/runtime_linux_test.go index cd59368cb2..a753aeea58 100644 --- a/src/runtime/runtime_linux_test.go +++ b/src/runtime/runtime_linux_test.go @@ -61,3 +61,14 @@ func TestEpollctlErrorSign(t *testing.T) { t.Errorf("epollctl = %v, want %v", v, -EBADF) } } + +func TestKernelStructSize(t *testing.T) { + // Check that the Go definitions of structures exchanged with the kernel are + // the same size as what the kernel defines. + if have, want := unsafe.Sizeof(Siginfo{}), uintptr(SiginfoMaxSize); have != want { + t.Errorf("Go's siginfo struct is %d bytes long; kernel expects %d", have, want) + } + if have, want := unsafe.Sizeof(Sigevent{}), uintptr(SigeventMaxSize); have != want { + t.Errorf("Go's sigevent struct is %d bytes long; kernel expects %d", have, want) + } +} diff --git a/src/runtime/select.go b/src/runtime/select.go index ee1f95ffa9..e18b2f14c0 100644 --- a/src/runtime/select.go +++ b/src/runtime/select.go @@ -406,6 +406,13 @@ func selectgo(cas0 *scase, order0 *uint16, pc0 *uintptr, nsends, nrecvs int, blo msanwrite(cas.elem, c.elemtype.size) } } + if asanenabled { + if casi < nsends { + asanread(cas.elem, c.elemtype.size) + } else if cas.elem != nil { + asanwrite(cas.elem, c.elemtype.size) + } + } selunlock(scases, lockorder) goto retc @@ -421,6 +428,9 @@ bufrecv: if msanenabled && cas.elem != nil { msanwrite(cas.elem, c.elemtype.size) } + if asanenabled && cas.elem != nil { + asanwrite(cas.elem, c.elemtype.size) + } recvOK = true qp = chanbuf(c, c.recvx) if cas.elem != nil { @@ -444,6 +454,9 @@ bufsend: if msanenabled { msanread(cas.elem, c.elemtype.size) } + if asanenabled { + asanread(cas.elem, c.elemtype.size) + } typedmemmove(c.elemtype, chanbuf(c, c.sendx), cas.elem) c.sendx++ if c.sendx == c.dataqsiz { @@ -482,6 +495,9 @@ send: if msanenabled { msanread(cas.elem, c.elemtype.size) } + if asanenabled { + asanread(cas.elem, c.elemtype.size) + } send(c, sg, cas.elem, func() { selunlock(scases, lockorder) }, 2) if debugSelect { print("syncsend: cas0=", cas0, " c=", c, "\n") diff --git a/src/runtime/signal_unix.go b/src/runtime/signal_unix.go index 7c454437e4..dbcbfc67bc 100644 --- a/src/runtime/signal_unix.go +++ b/src/runtime/signal_unix.go @@ -167,8 +167,8 @@ func sigInstallGoHandler(sig uint32) bool { } // When built using c-archive or c-shared, only install signal - // handlers for synchronous signals and SIGPIPE. - if (isarchive || islibrary) && t.flags&_SigPanic == 0 && sig != _SIGPIPE { + // handlers for synchronous signals and SIGPIPE and sigPreempt. + if (isarchive || islibrary) && t.flags&_SigPanic == 0 && sig != _SIGPIPE && sig != sigPreempt { return false } diff --git a/src/runtime/signal_windows.go b/src/runtime/signal_windows.go index ca4a9ea451..b036f3c965 100644 --- a/src/runtime/signal_windows.go +++ b/src/runtime/signal_windows.go @@ -22,8 +22,16 @@ func disableWER() { stdcall1(_SetErrorMode, uintptr(errormode)|SEM_FAILCRITICALERRORS|SEM_NOGPFAULTERRORBOX|SEM_NOOPENFILEERRORBOX) } +// isWin7 returns true on Windows 7. Otherwise it returns false. +// +//go:nosplit +func isWin7() bool { + var maj, min, build uint32 + stdcall3(_RtlGetNtVersionNumbers, uintptr(unsafe.Pointer(&maj)), uintptr(unsafe.Pointer(&min)), uintptr(unsafe.Pointer(&build))) + return maj < 6 || (maj == 6 && min <= 1) +} + // enableWERNoUI re-enables Windows error reporting without fault reporting UI. -// It returns false on older Windows versions (XP and earlier) where WerSetFlags() is not supported. // // This is marked nosplit since it is used during crash. // @@ -224,9 +232,14 @@ func lastcontinuehandler(info *exceptionrecord, r *context, gp *g) int32 { _, _, docrash := gotraceback() if docrash { - // trigger crash dump creation - if enableWERNoUI() { - return _EXCEPTION_CONTINUE_SEARCH + // Windows 7 apears to ignore WER_FAULT_REPORTING_NO_UI + // WerSetFlags API flag. So do not call enableWERNoUI + // on Windows 7. + if !isWin7() { + // trigger crash dump creation + if enableWERNoUI() { + return _EXCEPTION_CONTINUE_SEARCH + } } } exit(2) diff --git a/src/runtime/slice.go b/src/runtime/slice.go index aab8a598c5..ac0b7d5fef 100644 --- a/src/runtime/slice.go +++ b/src/runtime/slice.go @@ -76,6 +76,9 @@ func makeslicecopy(et *_type, tolen int, fromlen int, from unsafe.Pointer) unsaf if msanenabled { msanread(from, copymem) } + if asanenabled { + asanread(from, copymem) + } memmove(to, from, copymem) @@ -168,6 +171,9 @@ func growslice(et *_type, old slice, cap int) slice { if msanenabled { msanread(old.array, uintptr(old.len*int(et.size))) } + if asanenabled { + asanread(old.array, uintptr(old.len*int(et.size))) + } if cap < old.cap { panic(errorString("growslice: cap out of range")) @@ -311,6 +317,10 @@ func slicecopy(toPtr unsafe.Pointer, toLen int, fromPtr unsafe.Pointer, fromLen msanread(fromPtr, size) msanwrite(toPtr, size) } + if asanenabled { + asanread(fromPtr, size) + asanwrite(toPtr, size) + } if size == 1 { // common case worth about 2x to do here // TODO: is this still worth it with new memmove impl? diff --git a/src/runtime/stack.go b/src/runtime/stack.go index 8ae9c1e698..25a6f5bbb4 100644 --- a/src/runtime/stack.go +++ b/src/runtime/stack.go @@ -144,6 +144,9 @@ const ( // Force a stack movement. Used for debugging. // 0xfffffeed in hex. stackForceMove = uintptrMask & -275 + + // stackPoisonMin is the lowest allowed stack poison value. + stackPoisonMin = uintptrMask & -4096 ) // Global pool of spans that have free stacks. @@ -424,6 +427,9 @@ func stackalloc(n uint32) stack { if msanenabled { msanmalloc(v, uintptr(n)) } + if asanenabled { + asanunpoison(v, uintptr(n)) + } if stackDebug >= 1 { print(" allocated ", v, "\n") } @@ -461,6 +467,9 @@ func stackfree(stk stack) { if msanenabled { msanfree(v, n) } + if asanenabled { + asanpoison(v, n) + } if n < _FixedStack<<_NumStackOrders && n < _StackCacheSize { order := uint8(0) n2 := n @@ -993,7 +1002,7 @@ func newstack() { // NOTE: stackguard0 may change underfoot, if another thread // is about to try to preempt gp. Read it just once and use that same // value now and below. - preempt := atomic.Loaduintptr(&gp.stackguard0) == stackPreempt + stackguard0 := atomic.Loaduintptr(&gp.stackguard0) // Be conservative about where we preempt. // We are interested in preempting user Go code, not runtime code. @@ -1007,6 +1016,7 @@ func newstack() { // If the GC is in some way dependent on this goroutine (for example, // it needs a lock held by the goroutine), that small preemption turns // into a real deadlock. + preempt := stackguard0 == stackPreempt if preempt { if !canPreemptM(thisg.m) { // Let the goroutine keep running for now. @@ -1074,7 +1084,7 @@ func newstack() { } } - if gp.stackguard0 == stackForceMove { + if stackguard0 == stackForceMove { // Forced stack movement used for debugging. // Don't double the stack (or we may quickly run out // if this is done repeatedly). diff --git a/src/runtime/string.go b/src/runtime/string.go index d6990dab9a..980a9866e6 100644 --- a/src/runtime/string.go +++ b/src/runtime/string.go @@ -94,6 +94,9 @@ func slicebytetostring(buf *tmpBuf, ptr *byte, n int) (str string) { if msanenabled { msanread(unsafe.Pointer(ptr), uintptr(n)) } + if asanenabled { + asanread(unsafe.Pointer(ptr), uintptr(n)) + } if n == 1 { p := unsafe.Pointer(&staticuint64s[*ptr]) if goarch.BigEndian { @@ -158,6 +161,9 @@ func slicebytetostringtmp(ptr *byte, n int) (str string) { if msanenabled && n > 0 { msanread(unsafe.Pointer(ptr), uintptr(n)) } + if asanenabled && n > 0 { + asanread(unsafe.Pointer(ptr), uintptr(n)) + } stringStructOf(&str).str = unsafe.Pointer(ptr) stringStructOf(&str).len = n return @@ -209,6 +215,9 @@ func slicerunetostring(buf *tmpBuf, a []rune) string { if msanenabled && len(a) > 0 { msanread(unsafe.Pointer(&a[0]), uintptr(len(a))*unsafe.Sizeof(a[0])) } + if asanenabled && len(a) > 0 { + asanread(unsafe.Pointer(&a[0]), uintptr(len(a))*unsafe.Sizeof(a[0])) + } var dum [4]byte size1 := 0 for _, r := range a { diff --git a/src/runtime/sys_linux_arm.s b/src/runtime/sys_linux_arm.s index 3f30da7b54..65935de99f 100644 --- a/src/runtime/sys_linux_arm.s +++ b/src/runtime/sys_linux_arm.s @@ -360,6 +360,7 @@ finish: MOVW R1, m_vdsoPC(R5) MOVW R0, sec_lo+0(FP) + MOVW $0, R1 MOVW R1, sec_hi+4(FP) MOVW R2, nsec+8(FP) RET diff --git a/src/runtime/sys_plan9_amd64.s b/src/runtime/sys_plan9_amd64.s index 39fc4c68e4..638300dfb9 100644 --- a/src/runtime/sys_plan9_amd64.s +++ b/src/runtime/sys_plan9_amd64.s @@ -94,7 +94,7 @@ TEXT runtime·walltime(SB),NOSPLIT,$8-12 MOVQ 0(SP), AX // generated code for - // func f(x uint64) (uint64, uint64) { return x/1000000000, x%100000000 } + // func f(x uint64) (uint64, uint64) { return x/1000000000, x%1000000000 } // adapted to reduce duplication MOVQ AX, CX MOVQ $1360296554856532783, AX diff --git a/src/runtime/sys_windows_amd64.s b/src/runtime/sys_windows_amd64.s index 1e4c1d2b61..1467b4d57b 100644 --- a/src/runtime/sys_windows_amd64.s +++ b/src/runtime/sys_windows_amd64.s @@ -344,16 +344,9 @@ TEXT runtime·nanotime1(SB),NOSPLIT,$0-8 CMPB runtime·useQPCTime(SB), $0 JNE useQPC MOVQ $_INTERRUPT_TIME, DI -loop: - MOVL time_hi1(DI), AX - MOVL time_lo(DI), BX - MOVL time_hi2(DI), CX - CMPL AX, CX - JNE loop - SHLQ $32, CX - ORQ BX, CX - IMULQ $100, CX - MOVQ CX, ret+0(FP) + MOVQ time_lo(DI), AX + IMULQ $100, AX + MOVQ AX, ret+0(FP) RET useQPC: JMP runtime·nanotimeQPC(SB) diff --git a/src/runtime/sys_windows_arm.s b/src/runtime/sys_windows_arm.s index c9e96cb652..e5b1b7e9f3 100644 --- a/src/runtime/sys_windows_arm.s +++ b/src/runtime/sys_windows_arm.s @@ -350,7 +350,9 @@ TEXT runtime·nanotime1(SB),NOSPLIT|NOFRAME,$0-8 MOVW $_INTERRUPT_TIME, R3 loop: MOVW time_hi1(R3), R1 + DMB MB_ISH MOVW time_lo(R3), R0 + DMB MB_ISH MOVW time_hi2(R3), R2 CMP R1, R2 BNE loop diff --git a/src/runtime/sys_windows_arm64.s b/src/runtime/sys_windows_arm64.s index 44145c53fb..87f8f0d218 100644 --- a/src/runtime/sys_windows_arm64.s +++ b/src/runtime/sys_windows_arm64.s @@ -415,15 +415,7 @@ TEXT runtime·nanotime1(SB),NOSPLIT|NOFRAME,$0-8 CMP $0, R0 BNE useQPC MOVD $_INTERRUPT_TIME, R3 -loop: - MOVWU time_hi1(R3), R1 - MOVWU time_lo(R3), R0 - MOVWU time_hi2(R3), R2 - CMP R1, R2 - BNE loop - - // wintime = R1:R0, multiply by 100 - ORR R1<<32, R0 + MOVD time_lo(R3), R0 MOVD $100, R1 MUL R1, R0 MOVD R0, ret+0(FP) diff --git a/src/runtime/time_nofake.go b/src/runtime/time_nofake.go index 2b85c5aa01..70a2102b22 100644 --- a/src/runtime/time_nofake.go +++ b/src/runtime/time_nofake.go @@ -19,9 +19,14 @@ func nanotime() int64 { return nanotime1() } +var overrideWrite func(fd uintptr, p unsafe.Pointer, n int32) int32 + // write must be nosplit on Windows (see write1) // //go:nosplit func write(fd uintptr, p unsafe.Pointer, n int32) int32 { + if overrideWrite != nil { + return overrideWrite(fd, noescape(p), n) + } return write1(fd, p, n) } diff --git a/src/runtime/time_windows.h b/src/runtime/time_windows.h index cd16fd163b..7c2e65c328 100644 --- a/src/runtime/time_windows.h +++ b/src/runtime/time_windows.h @@ -9,6 +9,7 @@ // http://web.archive.org/web/20210411000829/https://wrkhpi.wordpress.com/2007/08/09/getting-os-information-the-kuser_shared_data-structure/ // Must read hi1, then lo, then hi2. The snapshot is valid if hi1 == hi2. +// Or, on 64-bit, just read lo:hi1 all at once atomically. #define _INTERRUPT_TIME 0x7ffe0008 #define _SYSTEM_TIME 0x7ffe0014 #define time_lo 0 diff --git a/src/runtime/time_windows_amd64.s b/src/runtime/time_windows_amd64.s index 93ab960b06..70f6a008cd 100644 --- a/src/runtime/time_windows_amd64.s +++ b/src/runtime/time_windows_amd64.s @@ -12,33 +12,20 @@ TEXT time·now(SB),NOSPLIT,$0-24 CMPB runtime·useQPCTime(SB), $0 JNE useQPC + MOVQ $_INTERRUPT_TIME, DI -loop: - MOVL time_hi1(DI), AX - MOVL time_lo(DI), BX - MOVL time_hi2(DI), CX - CMPL AX, CX - JNE loop - SHLQ $32, AX - ORQ BX, AX + MOVQ time_lo(DI), AX IMULQ $100, AX MOVQ AX, mono+16(FP) MOVQ $_SYSTEM_TIME, DI -wall: - MOVL time_hi1(DI), AX - MOVL time_lo(DI), BX - MOVL time_hi2(DI), CX - CMPL AX, CX - JNE wall - SHLQ $32, AX - ORQ BX, AX + MOVQ time_lo(DI), AX MOVQ $116444736000000000, DI SUBQ DI, AX IMULQ $100, AX // generated code for - // func f(x uint64) (uint64, uint64) { return x/1000000000, x%100000000 } + // func f(x uint64) (uint64, uint64) { return x/1000000000, x%1000000000 } // adapted to reduce duplication MOVQ AX, CX MOVQ $1360296554856532783, AX diff --git a/src/runtime/time_windows_arm.s b/src/runtime/time_windows_arm.s index 7c763b66ed..6552d75ff1 100644 --- a/src/runtime/time_windows_arm.s +++ b/src/runtime/time_windows_arm.s @@ -17,7 +17,9 @@ TEXT time·now(SB),NOSPLIT|NOFRAME,$0-20 MOVW $_INTERRUPT_TIME, R3 loop: MOVW time_hi1(R3), R1 + DMB MB_ISH MOVW time_lo(R3), R0 + DMB MB_ISH MOVW time_hi2(R3), R2 CMP R1, R2 BNE loop @@ -34,7 +36,9 @@ loop: MOVW $_SYSTEM_TIME, R3 wall: MOVW time_hi1(R3), R1 + DMB MB_ISH MOVW time_lo(R3), R0 + DMB MB_ISH MOVW time_hi2(R3), R2 CMP R1, R2 BNE wall diff --git a/src/runtime/time_windows_arm64.s b/src/runtime/time_windows_arm64.s index ef52ce4c99..ef5b848473 100644 --- a/src/runtime/time_windows_arm64.s +++ b/src/runtime/time_windows_arm64.s @@ -13,34 +13,18 @@ TEXT time·now(SB),NOSPLIT|NOFRAME,$0-24 MOVB runtime·useQPCTime(SB), R0 CMP $0, R0 BNE useQPC - MOVD $_INTERRUPT_TIME, R3 -loop: - MOVWU time_hi1(R3), R1 - MOVWU time_lo(R3), R0 - MOVWU time_hi2(R3), R2 - CMP R1, R2 - BNE loop - // wintime = R1:R0, multiply by 100 - ORR R1<<32, R0 + MOVD $_INTERRUPT_TIME, R3 + MOVD time_lo(R3), R0 MOVD $100, R1 MUL R1, R0 MOVD R0, mono+16(FP) MOVD $_SYSTEM_TIME, R3 -wall: - MOVWU time_hi1(R3), R1 - MOVWU time_lo(R3), R0 - MOVWU time_hi2(R3), R2 - CMP R1, R2 - BNE wall - - // w = R1:R0 in 100ns units + MOVD time_lo(R3), R0 // convert to Unix epoch (but still 100ns units) #define delta 116444736000000000 - ORR R1<<32, R0 SUB $delta, R0 - // Convert to nSec MOVD $100, R1 MUL R1, R0 @@ -48,17 +32,14 @@ wall: // Code stolen from compiler output for: // // var x uint64 - // func f() (sec uint64, nsec uint32) { return x / 1000000000, uint32(x % 100000000) } + // func f() (sec uint64, nsec uint32) { return x / 1000000000, uint32(x % 1000000000) } // LSR $1, R0, R1 MOVD $-8543223759426509416, R2 - UMULH R2, R1, R1 + UMULH R1, R2, R1 LSR $28, R1, R1 MOVD R1, sec+0(FP) - MOVD $-6067343680855748867, R1 - UMULH R0, R1, R1 - LSR $26, R1, R1 - MOVD $100000000, R2 + MOVD $1000000000, R2 MSUB R1, R0, R2, R0 MOVW R0, nsec+8(FP) RET diff --git a/src/runtime/tls_riscv64.s b/src/runtime/tls_riscv64.s index 22b550b761..397919aeba 100644 --- a/src/runtime/tls_riscv64.s +++ b/src/runtime/tls_riscv64.s @@ -15,7 +15,7 @@ TEXT runtime·save_g(SB),NOSPLIT|NOFRAME,$0-0 BEQ X0, X31, nocgo MOV runtime·tls_g(SB), X31 - ADD X4, X31 // add offset to thread pointer (X4) + ADD TP, X31 // add offset to thread pointer (X4) MOV g, (X31) nocgo: @@ -23,7 +23,7 @@ nocgo: TEXT runtime·load_g(SB),NOSPLIT|NOFRAME,$0-0 MOV runtime·tls_g(SB), X31 - ADD X4, X31 // add offset to thread pointer (X4) + ADD TP, X31 // add offset to thread pointer (X4) MOV (X31), g RET diff --git a/src/runtime/traceback.go b/src/runtime/traceback.go index 5de1abce9a..36627a6735 100644 --- a/src/runtime/traceback.go +++ b/src/runtime/traceback.go @@ -1390,6 +1390,9 @@ func callCgoSymbolizer(arg *cgoSymbolizerArg) { if msanenabled { msanwrite(unsafe.Pointer(arg), unsafe.Sizeof(cgoSymbolizerArg{})) } + if asanenabled { + asanwrite(unsafe.Pointer(arg), unsafe.Sizeof(cgoSymbolizerArg{})) + } call(cgoSymbolizer, noescape(unsafe.Pointer(arg))) } @@ -1412,5 +1415,8 @@ func cgoContextPCs(ctxt uintptr, buf []uintptr) { if msanenabled { msanwrite(unsafe.Pointer(&arg), unsafe.Sizeof(arg)) } + if asanenabled { + asanwrite(unsafe.Pointer(&arg), unsafe.Sizeof(arg)) + } call(cgoTraceback, noescape(unsafe.Pointer(&arg))) } diff --git a/src/runtime/traceback_test.go b/src/runtime/traceback_test.go index 0333b85c56..7d8b04e14b 100644 --- a/src/runtime/traceback_test.go +++ b/src/runtime/traceback_test.go @@ -353,6 +353,9 @@ func testTracebackArgs8d(a testArgsType8d) int { return n } +// nosplit to avoid preemption or morestack spilling registers. +// +//go:nosplit //go:noinline func testTracebackArgs9(a int64, b int32, c int16, d int8, x [2]int, y int) int { if a < 0 { @@ -366,6 +369,9 @@ func testTracebackArgs9(a int64, b int32, c int16, d int8, x [2]int, y int) int return n } +// nosplit to avoid preemption or morestack spilling registers. +// +//go:nosplit //go:noinline func testTracebackArgs10(a, b, c, d, e int32) int { // no use of any args @@ -373,8 +379,10 @@ func testTracebackArgs10(a, b, c, d, e int32) int { } // norace to avoid race instrumentation changing spill locations. +// nosplit to avoid preemption or morestack spilling registers. // //go:norace +//go:nosplit //go:noinline func testTracebackArgs11a(a, b, c int32) int { if a < 0 { @@ -387,8 +395,10 @@ func testTracebackArgs11a(a, b, c int32) int { } // norace to avoid race instrumentation changing spill locations. +// nosplit to avoid preemption or morestack spilling registers. // //go:norace +//go:nosplit //go:noinline func testTracebackArgs11b(a, b, c, d int32) int { var x int32 diff --git a/src/strings/clone.go b/src/strings/clone.go index 6097c6cc88..edd1497d9e 100644 --- a/src/strings/clone.go +++ b/src/strings/clone.go @@ -16,7 +16,12 @@ import ( // overuse of Clone can make programs use more memory. // Clone should typically be used only rarely, and only when // profiling indicates that it is needed. +// For strings of length zero the string "" will be returned +// and no allocation is made. func Clone(s string) string { + if len(s) == 0 { + return "" + } b := make([]byte, len(s)) copy(b, s) return *(*string)(unsafe.Pointer(&b)) diff --git a/src/strings/clone_test.go b/src/strings/clone_test.go index 5396771047..a9ba8add23 100644 --- a/src/strings/clone_test.go +++ b/src/strings/clone_test.go @@ -11,9 +11,13 @@ import ( "unsafe" ) +var emptyString string + func TestClone(t *testing.T) { var cloneTests = []string{ "", + strings.Clone(""), + strings.Repeat("a", 42)[:0], "short", strings.Repeat("a", 42), } @@ -25,9 +29,14 @@ func TestClone(t *testing.T) { inputHeader := (*reflect.StringHeader)(unsafe.Pointer(&input)) cloneHeader := (*reflect.StringHeader)(unsafe.Pointer(&clone)) - if inputHeader.Data == cloneHeader.Data { + if len(input) != 0 && cloneHeader.Data == inputHeader.Data { t.Errorf("Clone(%q) return value should not reference inputs backing memory.", input) } + + emptyHeader := (*reflect.StringHeader)(unsafe.Pointer(&emptyString)) + if len(input) == 0 && cloneHeader.Data != emptyHeader.Data { + t.Errorf("Clone(%#v) return value should be equal to empty string.", inputHeader) + } } } diff --git a/src/strings/compare.go b/src/strings/compare.go index 1fe6b8d89a..2bd4a243db 100644 --- a/src/strings/compare.go +++ b/src/strings/compare.go @@ -5,7 +5,7 @@ package strings // Compare returns an integer comparing two strings lexicographically. -// The result will be 0 if a==b, -1 if a < b, and +1 if a > b. +// The result will be 0 if a == b, -1 if a < b, and +1 if a > b. // // Compare is included only for symmetry with package bytes. // It is usually clearer and always faster to use the built-in diff --git a/src/strings/strings.go b/src/strings/strings.go index bc734048c3..c5a29e95f6 100644 --- a/src/strings/strings.go +++ b/src/strings/strings.go @@ -706,7 +706,8 @@ func isSeparator(r rune) bool { // Title returns a copy of the string s with all Unicode letters that begin words // mapped to their Unicode title case. // -// BUG(rsc): The rule Title uses for word boundaries does not handle Unicode punctuation properly. +// Deprecated: The rule Title uses for word boundaries does not handle Unicode +// punctuation properly. Use golang.org/x/text/cases instead. func Title(s string) string { // Use a closure here to remember state. // Hackish but effective. Depends on Map scanning in order and calling diff --git a/src/sync/atomic/atomic_test.go b/src/sync/atomic/atomic_test.go index eadc962f70..4b8c2a58f3 100644 --- a/src/sync/atomic/atomic_test.go +++ b/src/sync/atomic/atomic_test.go @@ -7,6 +7,7 @@ package atomic_test import ( "fmt" "runtime" + "runtime/debug" "strings" . "sync/atomic" "testing" @@ -1196,6 +1197,11 @@ func TestHammerStoreLoad(t *testing.T) { } const procs = 8 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(procs)) + // Disable the GC because hammerStoreLoadPointer invokes + // write barriers on values that aren't real pointers. + defer debug.SetGCPercent(debug.SetGCPercent(-1)) + // Ensure any in-progress GC is finished. + runtime.GC() for _, tt := range tests { c := make(chan int) var val uint64 diff --git a/src/sync/pool_test.go b/src/sync/pool_test.go index f94153c8d7..d991621624 100644 --- a/src/sync/pool_test.go +++ b/src/sync/pool_test.go @@ -270,6 +270,26 @@ func BenchmarkPoolOverflow(b *testing.B) { }) } +// Simulate object starvation in order to force Ps to steal objects +// from other Ps. +func BenchmarkPoolStarvation(b *testing.B) { + var p Pool + count := 100 + // Reduce number of putted objects by 33 %. It creates objects starvation + // that force P-local storage to steal objects from other Ps. + countStarved := count - int(float32(count)*0.33) + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + for b := 0; b < countStarved; b++ { + p.Put(1) + } + for b := 0; b < count; b++ { + p.Get() + } + } + }) +} + var globalSink interface{} func BenchmarkPoolSTW(b *testing.B) { diff --git a/src/syscall/asan.go b/src/syscall/asan.go new file mode 100644 index 0000000000..3199130211 --- /dev/null +++ b/src/syscall/asan.go @@ -0,0 +1,23 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build asan +// +build asan + +package syscall + +import ( + "runtime" + "unsafe" +) + +const asanenabled = true + +func asanRead(addr unsafe.Pointer, len int) { + runtime.ASanRead(addr, len) +} + +func asanWrite(addr unsafe.Pointer, len int) { + runtime.ASanWrite(addr, len) +} diff --git a/src/syscall/asan0.go b/src/syscall/asan0.go new file mode 100644 index 0000000000..7b69f4a64b --- /dev/null +++ b/src/syscall/asan0.go @@ -0,0 +1,20 @@ +// 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:build !asan +// +build !asan + +package syscall + +import ( + "unsafe" +) + +const asanenabled = false + +func asanRead(addr unsafe.Pointer, len int) { +} + +func asanWrite(addr unsafe.Pointer, len int) { +} diff --git a/src/syscall/exec_unix_test.go b/src/syscall/exec_unix_test.go index 55f5f7025a..b7ae77552b 100644 --- a/src/syscall/exec_unix_test.go +++ b/src/syscall/exec_unix_test.go @@ -13,7 +13,6 @@ import ( "os" "os/exec" "os/signal" - "runtime" "syscall" "testing" "time" @@ -327,7 +326,6 @@ func TestExecHelper(t *testing.T) { // We don't have to worry about restoring these values. // We are in a child process that only runs this test, // and we are going to call syscall.Exec anyhow. - runtime.GOMAXPROCS(50) os.Setenv("GO_WANT_HELPER_PROCESS", "3") stop := time.Now().Add(time.Second) diff --git a/src/syscall/mkall.sh b/src/syscall/mkall.sh index dffb52864b..5fc91d3815 100755 --- a/src/syscall/mkall.sh +++ b/src/syscall/mkall.sh @@ -283,7 +283,7 @@ netbsd_arm64) mktypes="GOARCH=$GOARCH go tool cgo -godefs" ;; openbsd_386) - GOOSARCH_in="syscall_openbsd1.go syscall_openbsd_$GOARCH.go" + GOOSARCH_in="syscall_openbsd_libc.go syscall_openbsd_$GOARCH.go" mkerrors="$mkerrors -m32" mksyscall="./mksyscall.pl -l32 -openbsd -libc" mksysctl="./mksysctl_openbsd.pl" diff --git a/src/syscall/net_js.go b/src/syscall/net_js.go index 4f8258ddb3..253ab22dd9 100644 --- a/src/syscall/net_js.go +++ b/src/syscall/net_js.go @@ -91,26 +91,10 @@ func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) { return 0, nil, ENOSYS } -func RecvfromInet4(fd int, p []byte, flags int, from *SockaddrInet4) (n int, err error) { - return 0, ENOSYS -} - -func RecvfromInet6(fd int, p []byte, flags int, from *SockaddrInet6) (n int, err error) { - return 0, ENOSYS -} - func Sendto(fd int, p []byte, flags int, to Sockaddr) error { return ENOSYS } -func SendtoInet4(fd int, p []byte, flags int, to SockaddrInet4) error { - return ENOSYS -} - -func SendtoInet6(fd int, p []byte, flags int, to SockaddrInet6) error { - return ENOSYS -} - func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn, recvflags int, from Sockaddr, err error) { return 0, 0, 0, nil, ENOSYS } diff --git a/src/syscall/syscall_aix.go b/src/syscall/syscall_aix.go index 20e77ac875..0f5101999f 100644 --- a/src/syscall/syscall_aix.go +++ b/src/syscall/syscall_aix.go @@ -255,9 +255,7 @@ func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) { p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), SizeofSockaddrInet4, nil } @@ -270,9 +268,7 @@ func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) { p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) sa.raw.Scope_id = sa.ZoneId - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), SizeofSockaddrInet6, nil } @@ -325,10 +321,9 @@ func Accept(fd int) (nfd int, sa Sockaddr, err error) { return } -func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) { +func recvmsgRaw(fd int, p, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn int, recvflags int, err error) { var msg Msghdr - var rsa RawSockaddrAny - msg.Name = (*byte)(unsafe.Pointer(&rsa)) + msg.Name = (*byte)(unsafe.Pointer(rsa)) msg.Namelen = uint32(SizeofSockaddrAny) var iov Iovec if len(p) > 0 { @@ -357,27 +352,10 @@ func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from } oobn = int(msg.Controllen) recvflags = int(msg.Flags) - // source address is only specified if the socket is unconnected - if rsa.Addr.Family != AF_UNSPEC { - from, err = anyToSockaddr(&rsa) - } return } -func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) { - _, err = SendmsgN(fd, p, oob, to, flags) - return -} - -func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) { - var ptr unsafe.Pointer - var salen _Socklen - if to != nil { - ptr, salen, err = to.sockaddr() - if err != nil { - return 0, err - } - } +func sendmsgN(fd int, p, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags int) (n int, err error) { var msg Msghdr msg.Name = (*byte)(unsafe.Pointer(ptr)) msg.Namelen = uint32(salen) @@ -443,9 +421,7 @@ func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) { sa := new(SockaddrInet4) p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil case AF_INET6: @@ -453,9 +429,7 @@ func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) { sa := new(SockaddrInet6) p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil } return nil, EAFNOSUPPORT diff --git a/src/syscall/syscall_bsd.go b/src/syscall/syscall_bsd.go index ebe99ff230..5e636d5258 100644 --- a/src/syscall/syscall_bsd.go +++ b/src/syscall/syscall_bsd.go @@ -167,9 +167,7 @@ func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) { p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil } @@ -183,9 +181,7 @@ func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) { p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) sa.raw.Scope_id = sa.ZoneId - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil } @@ -214,9 +210,7 @@ func (sa *SockaddrDatalink) sockaddr() (unsafe.Pointer, _Socklen, error) { sa.raw.Nlen = sa.Nlen sa.raw.Alen = sa.Alen sa.raw.Slen = sa.Slen - for i := 0; i < len(sa.raw.Data); i++ { - sa.raw.Data[i] = sa.Data[i] - } + sa.raw.Data = sa.Data return unsafe.Pointer(&sa.raw), SizeofSockaddrDatalink, nil } @@ -232,9 +226,7 @@ func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) { sa.Nlen = pp.Nlen sa.Alen = pp.Alen sa.Slen = pp.Slen - for i := 0; i < len(sa.Data); i++ { - sa.Data[i] = pp.Data[i] - } + sa.Data = pp.Data return sa, nil case AF_UNIX: @@ -266,9 +258,7 @@ func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) { sa := new(SockaddrInet4) p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil case AF_INET6: @@ -277,9 +267,7 @@ func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) { p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) sa.ZoneId = pp.Scope_id - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil } return nil, EAFNOSUPPORT @@ -370,10 +358,9 @@ func GetsockoptICMPv6Filter(fd, level, opt int) (*ICMPv6Filter, error) { //sys sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) //sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error) -func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) { +func recvmsgRaw(fd int, p, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn int, recvflags int, err error) { var msg Msghdr - var rsa RawSockaddrAny - msg.Name = (*byte)(unsafe.Pointer(&rsa)) + msg.Name = (*byte)(unsafe.Pointer(rsa)) msg.Namelen = uint32(SizeofSockaddrAny) var iov Iovec if len(p) > 0 { @@ -397,29 +384,12 @@ func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from } oobn = int(msg.Controllen) recvflags = int(msg.Flags) - // source address is only specified if the socket is unconnected - if rsa.Addr.Family != AF_UNSPEC { - from, err = anyToSockaddr(&rsa) - } return } //sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error) -func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) { - _, err = SendmsgN(fd, p, oob, to, flags) - return -} - -func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) { - var ptr unsafe.Pointer - var salen _Socklen - if to != nil { - ptr, salen, err = to.sockaddr() - if err != nil { - return 0, err - } - } +func sendmsgN(fd int, p, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags int) (n int, err error) { var msg Msghdr msg.Name = (*byte)(unsafe.Pointer(ptr)) msg.Namelen = uint32(salen) diff --git a/src/syscall/syscall_linux.go b/src/syscall/syscall_linux.go index f02fa45a89..c002299641 100644 --- a/src/syscall/syscall_linux.go +++ b/src/syscall/syscall_linux.go @@ -393,9 +393,7 @@ func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) { p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), SizeofSockaddrInet4, nil } @@ -408,9 +406,7 @@ func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) { p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) sa.raw.Scope_id = sa.ZoneId - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), SizeofSockaddrInet6, nil } @@ -461,9 +457,7 @@ func (sa *SockaddrLinklayer) sockaddr() (unsafe.Pointer, _Socklen, error) { sa.raw.Hatype = sa.Hatype sa.raw.Pkttype = sa.Pkttype sa.raw.Halen = sa.Halen - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), SizeofSockaddrLinklayer, nil } @@ -502,9 +496,7 @@ func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) { sa.Hatype = pp.Hatype sa.Pkttype = pp.Pkttype sa.Halen = pp.Halen - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil case AF_UNIX: @@ -537,9 +529,7 @@ func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) { sa := new(SockaddrInet4) p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil case AF_INET6: @@ -548,9 +538,7 @@ func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) { p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) sa.ZoneId = pp.Scope_id - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil } return nil, EAFNOSUPPORT @@ -650,10 +638,9 @@ func SetsockoptIPMreqn(fd, level, opt int, mreq *IPMreqn) (err error) { return setsockopt(fd, level, opt, unsafe.Pointer(mreq), unsafe.Sizeof(*mreq)) } -func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) { +func recvmsgRaw(fd int, p, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn int, recvflags int, err error) { var msg Msghdr - var rsa RawSockaddrAny - msg.Name = (*byte)(unsafe.Pointer(&rsa)) + msg.Name = (*byte)(unsafe.Pointer(rsa)) msg.Namelen = uint32(SizeofSockaddrAny) var iov Iovec if len(p) > 0 { @@ -684,28 +671,10 @@ func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from } oobn = int(msg.Controllen) recvflags = int(msg.Flags) - // source address is only specified if the socket is unconnected - if rsa.Addr.Family != AF_UNSPEC { - from, err = anyToSockaddr(&rsa) - } return } -func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) { - _, err = SendmsgN(fd, p, oob, to, flags) - return -} - -func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) { - var ptr unsafe.Pointer - var salen _Socklen - if to != nil { - var err error - ptr, salen, err = to.sockaddr() - if err != nil { - return 0, err - } - } +func sendmsgN(fd int, p, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags int) (n int, err error) { var msg Msghdr msg.Name = (*byte)(ptr) msg.Namelen = uint32(salen) diff --git a/src/syscall/syscall_solaris.go b/src/syscall/syscall_solaris.go index dedfbd03c0..5f12f229c4 100644 --- a/src/syscall/syscall_solaris.go +++ b/src/syscall/syscall_solaris.go @@ -69,9 +69,7 @@ func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) { p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), SizeofSockaddrInet4, nil } @@ -84,9 +82,7 @@ func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) { p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) sa.raw.Scope_id = sa.ZoneId - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), SizeofSockaddrInet6, nil } @@ -304,9 +300,7 @@ func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) { sa := new(SockaddrInet4) p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil case AF_INET6: @@ -315,9 +309,7 @@ func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) { p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) sa.ZoneId = pp.Scope_id - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil } return nil, EAFNOSUPPORT @@ -340,10 +332,9 @@ func Accept(fd int) (nfd int, sa Sockaddr, err error) { return } -func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) { +func recvmsgRaw(fd int, p, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn int, recvflags int, err error) { var msg Msghdr - var rsa RawSockaddrAny - msg.Name = (*byte)(unsafe.Pointer(&rsa)) + msg.Name = (*byte)(unsafe.Pointer(rsa)) msg.Namelen = uint32(SizeofSockaddrAny) var iov Iovec if len(p) > 0 { @@ -366,29 +357,12 @@ func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from return } oobn = int(msg.Accrightslen) - // source address is only specified if the socket is unconnected - if rsa.Addr.Family != AF_UNSPEC { - from, err = anyToSockaddr(&rsa) - } - return -} - -func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) { - _, err = SendmsgN(fd, p, oob, to, flags) return } //sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error) = libsocket.__xnet_sendmsg -func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) { - var ptr unsafe.Pointer - var salen _Socklen - if to != nil { - ptr, salen, err = to.sockaddr() - if err != nil { - return 0, err - } - } +func sendmsgN(fd int, p, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags int) (n int, err error) { var msg Msghdr msg.Name = (*byte)(unsafe.Pointer(ptr)) msg.Namelen = uint32(salen) diff --git a/src/syscall/syscall_unix.go b/src/syscall/syscall_unix.go index 9413db3832..5ee938115d 100644 --- a/src/syscall/syscall_unix.go +++ b/src/syscall/syscall_unix.go @@ -197,6 +197,9 @@ func Read(fd int, p []byte) (n int, err error) { if msanenabled && n > 0 { msanWrite(unsafe.Pointer(&p[0]), n) } + if asanenabled && n > 0 { + asanWrite(unsafe.Pointer(&p[0]), n) + } return } @@ -218,6 +221,9 @@ func Write(fd int, p []byte) (n int, err error) { if msanenabled && n > 0 { msanRead(unsafe.Pointer(&p[0]), n) } + if asanenabled && n > 0 { + asanRead(unsafe.Pointer(&p[0]), n) + } return } @@ -291,7 +297,7 @@ func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) { return } -func RecvfromInet4(fd int, p []byte, flags int, from *SockaddrInet4) (n int, err error) { +func recvfromInet4(fd int, p []byte, flags int, from *SockaddrInet4) (n int, err error) { var rsa RawSockaddrAny var socklen _Socklen = SizeofSockaddrAny if n, err = recvfrom(fd, p, flags, &rsa, &socklen); err != nil { @@ -304,7 +310,7 @@ func RecvfromInet4(fd int, p []byte, flags int, from *SockaddrInet4) (n int, err return } -func RecvfromInet6(fd int, p []byte, flags int, from *SockaddrInet6) (n int, err error) { +func recvfromInet6(fd int, p []byte, flags int, from *SockaddrInet6) (n int, err error) { var rsa RawSockaddrAny var socklen _Socklen = SizeofSockaddrAny if n, err = recvfrom(fd, p, flags, &rsa, &socklen); err != nil { @@ -318,7 +324,77 @@ func RecvfromInet6(fd int, p []byte, flags int, from *SockaddrInet6) (n int, err return } -func SendtoInet4(fd int, p []byte, flags int, to SockaddrInet4) (err error) { +func recvmsgInet4(fd int, p, oob []byte, flags int, from *SockaddrInet4) (n, oobn int, recvflags int, err error) { + var rsa RawSockaddrAny + n, oobn, recvflags, err = recvmsgRaw(fd, p, oob, flags, &rsa) + if err != nil { + return + } + pp := (*RawSockaddrInet4)(unsafe.Pointer(&rsa)) + port := (*[2]byte)(unsafe.Pointer(&pp.Port)) + from.Port = int(port[0])<<8 + int(port[1]) + from.Addr = pp.Addr + return +} + +func recvmsgInet6(fd int, p, oob []byte, flags int, from *SockaddrInet6) (n, oobn int, recvflags int, err error) { + var rsa RawSockaddrAny + n, oobn, recvflags, err = recvmsgRaw(fd, p, oob, flags, &rsa) + if err != nil { + return + } + pp := (*RawSockaddrInet6)(unsafe.Pointer(&rsa)) + port := (*[2]byte)(unsafe.Pointer(&pp.Port)) + from.Port = int(port[0])<<8 + int(port[1]) + from.ZoneId = pp.Scope_id + from.Addr = pp.Addr + return +} + +func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) { + var rsa RawSockaddrAny + n, oobn, recvflags, err = recvmsgRaw(fd, p, oob, flags, &rsa) + // source address is only specified if the socket is unconnected + if rsa.Addr.Family != AF_UNSPEC { + from, err = anyToSockaddr(&rsa) + } + return +} + +func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) { + _, err = SendmsgN(fd, p, oob, to, flags) + return +} + +func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) { + var ptr unsafe.Pointer + var salen _Socklen + if to != nil { + ptr, salen, err = to.sockaddr() + if err != nil { + return 0, err + } + } + return sendmsgN(fd, p, oob, ptr, salen, flags) +} + +func sendmsgNInet4(fd int, p, oob []byte, to *SockaddrInet4, flags int) (n int, err error) { + ptr, salen, err := to.sockaddr() + if err != nil { + return 0, err + } + return sendmsgN(fd, p, oob, ptr, salen, flags) +} + +func sendmsgNInet6(fd int, p, oob []byte, to *SockaddrInet6, flags int) (n int, err error) { + ptr, salen, err := to.sockaddr() + if err != nil { + return 0, err + } + return sendmsgN(fd, p, oob, ptr, salen, flags) +} + +func sendtoInet4(fd int, p []byte, flags int, to *SockaddrInet4) (err error) { ptr, n, err := to.sockaddr() if err != nil { return err @@ -326,7 +402,7 @@ func SendtoInet4(fd int, p []byte, flags int, to SockaddrInet4) (err error) { return sendto(fd, p, flags, ptr, n) } -func SendtoInet6(fd int, p []byte, flags int, to SockaddrInet6) (err error) { +func sendtoInet6(fd int, p []byte, flags int, to *SockaddrInet6) (err error) { ptr, n, err := to.sockaddr() if err != nil { return err diff --git a/src/syscall/syscall_unix_test.go b/src/syscall/syscall_unix_test.go index 7cc78c2147..e4af0ba4a5 100644 --- a/src/syscall/syscall_unix_test.go +++ b/src/syscall/syscall_unix_test.go @@ -84,16 +84,24 @@ func TestFcntlFlock(t *testing.T) { if err != nil { t.Fatalf("Open failed: %v", err) } - defer syscall.Close(fd) - if err := syscall.Ftruncate(fd, 1<<20); err != nil { + // f takes ownership of fd, and will close it. + // + // N.B. This defer is also necessary to keep f alive + // while we use its fd, preventing its finalizer from + // executing. + f := os.NewFile(uintptr(fd), name) + defer f.Close() + + if err := syscall.Ftruncate(int(f.Fd()), 1<<20); err != nil { t.Fatalf("Ftruncate(1<<20) failed: %v", err) } - if err := syscall.FcntlFlock(uintptr(fd), syscall.F_SETLK, &flock); err != nil { + if err := syscall.FcntlFlock(f.Fd(), syscall.F_SETLK, &flock); err != nil { t.Fatalf("FcntlFlock(F_SETLK) failed: %v", err) } + cmd := exec.Command(os.Args[0], "-test.run=^TestFcntlFlock$") cmd.Env = append(os.Environ(), "GO_WANT_HELPER_PROCESS=1") - cmd.ExtraFiles = []*os.File{os.NewFile(uintptr(fd), name)} + cmd.ExtraFiles = []*os.File{f} out, err := cmd.CombinedOutput() if len(out) > 0 || err != nil { t.Fatalf("child process: %q, %v", out, err) @@ -251,6 +259,10 @@ func passFDChild() { fmt.Printf("TempFile: %v", err) return } + // N.B. This defer is also necessary to keep f alive + // while we use its fd, preventing its finalizer from + // executing. + defer f.Close() f.Write([]byte("Hello from child process!\n")) f.Seek(0, io.SeekStart) diff --git a/src/syscall/syscall_windows.go b/src/syscall/syscall_windows.go index d4e51e541d..ecb1eeecf6 100644 --- a/src/syscall/syscall_windows.go +++ b/src/syscall/syscall_windows.go @@ -279,7 +279,7 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys RegOpenKeyEx(key Handle, subkey *uint16, options uint32, desiredAccess uint32, result *Handle) (regerrno error) = advapi32.RegOpenKeyExW //sys RegCloseKey(key Handle) (regerrno error) = advapi32.RegCloseKey //sys RegQueryInfoKey(key Handle, class *uint16, classLen *uint32, reserved *uint32, subkeysLen *uint32, maxSubkeyLen *uint32, maxClassLen *uint32, valuesLen *uint32, maxValueNameLen *uint32, maxValueLen *uint32, saLen *uint32, lastWriteTime *Filetime) (regerrno error) = advapi32.RegQueryInfoKeyW -//sys RegEnumKeyEx(key Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, classLen *uint32, lastWriteTime *Filetime) (regerrno error) = advapi32.RegEnumKeyExW +//sys regEnumKeyEx(key Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, classLen *uint32, lastWriteTime *Filetime) (regerrno error) = advapi32.RegEnumKeyExW //sys RegQueryValueEx(key Handle, name *uint16, reserved *uint32, valtype *uint32, buf *byte, buflen *uint32) (regerrno error) = advapi32.RegQueryValueExW //sys getCurrentProcessId() (pid uint32) = kernel32.GetCurrentProcessId //sys GetConsoleMode(console Handle, mode *uint32) (err error) = kernel32.GetConsoleMode @@ -394,6 +394,9 @@ func Read(fd Handle, p []byte) (n int, err error) { if msanenabled && done > 0 { msanWrite(unsafe.Pointer(&p[0]), int(done)) } + if asanenabled && done > 0 { + asanWrite(unsafe.Pointer(&p[0]), int(done)) + } return int(done), nil } @@ -412,6 +415,9 @@ func Write(fd Handle, p []byte) (n int, err error) { if msanenabled && done > 0 { msanRead(unsafe.Pointer(&p[0]), int(done)) } + if asanenabled && done > 0 { + asanRead(unsafe.Pointer(&p[0]), int(done)) + } return int(done), nil } @@ -738,9 +744,7 @@ func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, int32, error) { p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), int32(unsafe.Sizeof(sa.raw)), nil } @@ -760,9 +764,7 @@ func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, int32, error) { p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) sa.raw.Scope_id = sa.ZoneId - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), int32(unsafe.Sizeof(sa.raw)), nil } @@ -835,9 +837,7 @@ func (rsa *RawSockaddrAny) Sockaddr() (Sockaddr, error) { sa := new(SockaddrInet4) p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil case AF_INET6: @@ -846,9 +846,7 @@ func (rsa *RawSockaddrAny) Sockaddr() (Sockaddr, error) { p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) sa.ZoneId = pp.Scope_id - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil } return nil, EAFNOSUPPORT @@ -924,7 +922,7 @@ func WSASendto(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32 return err } -func WSASendtoInet4(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to SockaddrInet4, overlapped *Overlapped, croutine *byte) (err error) { +func wsaSendtoInet4(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *SockaddrInet4, overlapped *Overlapped, croutine *byte) (err error) { rsa, len, err := to.sockaddr() if err != nil { return err @@ -940,7 +938,7 @@ func WSASendtoInet4(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags u return err } -func WSASendtoInet6(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to SockaddrInet6, overlapped *Overlapped, croutine *byte) (err error) { +func wsaSendtoInet6(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *SockaddrInet6, overlapped *Overlapped, croutine *byte) (err error) { rsa, len, err := to.sockaddr() if err != nil { return err @@ -1303,3 +1301,31 @@ func newProcThreadAttributeList(maxAttrCount uint32) (*_PROC_THREAD_ATTRIBUTE_LI } return al, nil } + +// RegEnumKeyEx enumerates the subkeys of an open registry key. +// Each call retrieves information about one subkey. name is +// a buffer that should be large enough to hold the name of the +// subkey plus a null terminating character. nameLen is its +// length. On return, nameLen will contain the actual length of the +// subkey. +// +// Should name not be large enough to hold the subkey, this function +// will return ERROR_MORE_DATA, and must be called again with an +// appropriately sized buffer. +// +// reserved must be nil. class and classLen behave like name and nameLen +// but for the class of the subkey, except that they are optional. +// lastWriteTime, if not nil, will be populated with the time the subkey +// was last written. +// +// The caller must enumerate all subkeys in order. That is +// RegEnumKeyEx must be called with index starting at 0, incrementing +// the index until the function returns ERROR_NO_MORE_ITEMS, or with +// the index of the last subkey (obtainable from RegQueryInfoKey), +// decrementing until index 0 is enumerated. +// +// Successive calls to this API must happen on the same OS thread, +// so call runtime.LockOSThread before calling this function. +func RegEnumKeyEx(key Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, classLen *uint32, lastWriteTime *Filetime) (regerrno error) { + return regEnumKeyEx(key, index, name, nameLen, reserved, class, classLen, lastWriteTime) +} diff --git a/src/syscall/zsyscall_windows.go b/src/syscall/zsyscall_windows.go index 7bfff16be6..2d6f34e059 100644 --- a/src/syscall/zsyscall_windows.go +++ b/src/syscall/zsyscall_windows.go @@ -305,7 +305,7 @@ func RegCloseKey(key Handle) (regerrno error) { return } -func RegEnumKeyEx(key Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, classLen *uint32, lastWriteTime *Filetime) (regerrno error) { +func regEnumKeyEx(key Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, classLen *uint32, lastWriteTime *Filetime) (regerrno error) { r0, _, _ := Syscall9(procRegEnumKeyExW.Addr(), 8, uintptr(key), uintptr(index), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(nameLen)), uintptr(unsafe.Pointer(reserved)), uintptr(unsafe.Pointer(class)), uintptr(unsafe.Pointer(classLen)), uintptr(unsafe.Pointer(lastWriteTime)), 0) if r0 != 0 { regerrno = Errno(r0) diff --git a/src/time/example_test.go b/src/time/example_test.go index 0afb18aba6..ec2259b1ba 100644 --- a/src/time/example_test.go +++ b/src/time/example_test.go @@ -344,6 +344,23 @@ func ExampleTime_Format_pad() { } +func ExampleTime_GoString() { + t := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC) + fmt.Println(t.GoString()) + t = t.Add(1 * time.Minute) + fmt.Println(t.GoString()) + t = t.AddDate(0, 1, 0) + fmt.Println(t.GoString()) + t, _ = time.Parse("Jan 2, 2006 at 3:04pm (MST)", "Feb 3, 2013 at 7:54pm (UTC)") + fmt.Println(t.GoString()) + + // Output: + // time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC) + // time.Date(2009, time.November, 10, 23, 1, 0, 0, time.UTC) + // time.Date(2009, time.December, 10, 23, 1, 0, 0, time.UTC) + // time.Date(2013, time.February, 3, 19, 54, 0, 0, time.UTC) +} + func ExampleParse() { // See the example for Time.Format for a thorough description of how // to define the layout string to parse a time.Time value; Parse and @@ -401,6 +418,39 @@ func ExampleParseInLocation() { // 2012-07-09 00:00:00 +0200 CEST } +func ExampleUnix() { + unixTime := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC) + fmt.Println(unixTime.Unix()) + t := time.Unix(unixTime.Unix(), 0).UTC() + fmt.Println(t) + + // Output: + // 1257894000 + // 2009-11-10 23:00:00 +0000 UTC +} + +func ExampleUnixMicro() { + umt := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC) + fmt.Println(umt.UnixMicro()) + t := time.UnixMicro(umt.UnixMicro()).UTC() + fmt.Println(t) + + // Output: + // 1257894000000000 + // 2009-11-10 23:00:00 +0000 UTC +} + +func ExampleUnixMilli() { + umt := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC) + fmt.Println(umt.UnixMilli()) + t := time.UnixMilli(umt.UnixMilli()).UTC() + fmt.Println(t) + + // Output: + // 1257894000000 + // 2009-11-10 23:00:00 +0000 UTC +} + func ExampleTime_Unix() { // 1 billion seconds of Unix, three ways. fmt.Println(time.Unix(1e9, 0).UTC()) // 1e9 seconds diff --git a/src/time/tick.go b/src/time/tick.go index f9522b0b75..babf865aeb 100644 --- a/src/time/tick.go +++ b/src/time/tick.go @@ -48,8 +48,12 @@ func (t *Ticker) Stop() { } // Reset stops a ticker and resets its period to the specified duration. -// The next tick will arrive after the new period elapses. +// The next tick will arrive after the new period elapses. The duration d +// must be greater than zero; if not, Reset will panic. func (t *Ticker) Reset(d Duration) { + if d <= 0 { + panic("non-positive interval for Ticker.Reset") + } if t.r.f == nil { panic("time: Reset called on uninitialized Ticker") } diff --git a/src/time/tick_test.go b/src/time/tick_test.go index d8cd59228f..f539091869 100644 --- a/src/time/tick_test.go +++ b/src/time/tick_test.go @@ -134,6 +134,17 @@ func TestNewTickerLtZeroDuration(t *testing.T) { NewTicker(-1) } +// Test that Ticker.Reset panics when given a duration less than zero. +func TestTickerResetLtZeroDuration(t *testing.T) { + defer func() { + if err := recover(); err == nil { + t.Errorf("Ticker.Reset(0) should have panicked") + } + }() + tk := NewTicker(Second) + tk.Reset(0) +} + func BenchmarkTicker(b *testing.B) { benchmark(b, func(n int) { ticker := NewTicker(Nanosecond) diff --git a/src/time/time.go b/src/time/time.go index edf0c62610..8046ff508b 100644 --- a/src/time/time.go +++ b/src/time/time.go @@ -1433,17 +1433,17 @@ func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) T unix := int64(abs) + (absoluteToInternal + internalToUnix) - // Look for zone offset for t, so we can adjust to UTC. - // The lookup function expects UTC, so we pass t in the + // Look for zone offset for expected time, so we can adjust to UTC. + // The lookup function expects UTC, so first we pass unix in the // hope that it will not be too close to a zone transition, // and then adjust if it is. _, offset, start, end, _ := loc.lookup(unix) if offset != 0 { - switch utc := unix - int64(offset); { - case utc < start: - _, offset, _, _, _ = loc.lookup(start - 1) - case utc >= end: - _, offset, _, _, _ = loc.lookup(end) + utc := unix - int64(offset) + // If utc is valid for the time zone we found, then we have the right offset. + // If not, we get the correct offset by looking up utc in the location. + if utc < start || utc >= end { + _, offset, _, _, _ = loc.lookup(utc) } unix -= int64(offset) } diff --git a/src/time/time_test.go b/src/time/time_test.go index 5007b6e723..6a4049617c 100644 --- a/src/time/time_test.go +++ b/src/time/time_test.go @@ -1616,3 +1616,45 @@ func TestTimeAddSecOverflow(t *testing.T) { } } } + +// Issue 49284: time: ParseInLocation incorrectly because of Daylight Saving Time +func TestTimeWithZoneTransition(t *testing.T) { + ForceZipFileForTesting(true) + defer ForceZipFileForTesting(false) + + loc, err := LoadLocation("Asia/Shanghai") + if err != nil { + t.Fatal(err) + } + + tests := [...]struct { + give Time + want Time + }{ + // 14 Apr 1991 - Daylight Saving Time Started + // When time of "Asia/Shanghai" was about to reach + // Sunday, 14 April 1991, 02:00:00 clocks were turned forward 1 hour to + // Sunday, 14 April 1991, 03:00:00 local daylight time instead. + // The UTC time was 13 April 1991, 18:00:00 + 0: {Date(1991, April, 13, 17, 50, 0, 0, loc), Date(1991, April, 13, 9, 50, 0, 0, UTC)}, + 1: {Date(1991, April, 13, 18, 0, 0, 0, loc), Date(1991, April, 13, 10, 0, 0, 0, UTC)}, + 2: {Date(1991, April, 14, 1, 50, 0, 0, loc), Date(1991, April, 13, 17, 50, 0, 0, UTC)}, + 3: {Date(1991, April, 14, 3, 0, 0, 0, loc), Date(1991, April, 13, 18, 0, 0, 0, UTC)}, + + // 15 Sep 1991 - Daylight Saving Time Ended + // When local daylight time of "Asia/Shanghai" was about to reach + // Sunday, 15 September 1991, 02:00:00 clocks were turned backward 1 hour to + // Sunday, 15 September 1991, 01:00:00 local standard time instead. + // The UTC time was 14 September 1991, 17:00:00 + 4: {Date(1991, September, 14, 16, 50, 0, 0, loc), Date(1991, September, 14, 7, 50, 0, 0, UTC)}, + 5: {Date(1991, September, 14, 17, 0, 0, 0, loc), Date(1991, September, 14, 8, 0, 0, 0, UTC)}, + 6: {Date(1991, September, 15, 0, 50, 0, 0, loc), Date(1991, September, 14, 15, 50, 0, 0, UTC)}, + 7: {Date(1991, September, 15, 2, 00, 0, 0, loc), Date(1991, September, 14, 18, 00, 0, 0, UTC)}, + } + + for i, tt := range tests { + if !tt.give.Equal(tt.want) { + t.Errorf("#%d:: %#v is not equal to %#v", i, tt.give.Format(RFC3339), tt.want.Format(RFC3339)) + } + } +} diff --git a/src/unicode/utf8/example_test.go b/src/unicode/utf8/example_test.go index 5cd931d242..fe434c9476 100644 --- a/src/unicode/utf8/example_test.go +++ b/src/unicode/utf8/example_test.go @@ -214,3 +214,13 @@ func ExampleValidString() { // true // false } + +func ExampleAppendRune() { + buf1 := utf8.AppendRune(nil, 0x10000) + buf2 := utf8.AppendRune([]byte("init"), 0x10000) + fmt.Println(string(buf1)) + fmt.Println(string(buf2)) + // Output: + // 𐀀 + // init𐀀 +} diff --git a/src/unicode/utf8/utf8_test.go b/src/unicode/utf8/utf8_test.go index a60040ecfd..e9be4d2d63 100644 --- a/src/unicode/utf8/utf8_test.go +++ b/src/unicode/utf8/utf8_test.go @@ -133,7 +133,7 @@ func TestAppendRune(t *testing.T) { t.Errorf("AppendRune(nil, %#04x) = %s, want %s", m.r, buf, m.str) } if buf := AppendRune([]byte("init"), m.r); string(buf) != "init"+m.str { - t.Errorf("AppendRune(nil, %#04x) = %s, want %s", m.r, buf, "init"+m.str) + t.Errorf("AppendRune(init, %#04x) = %s, want %s", m.r, buf, "init"+m.str) } } } diff --git a/src/vendor/modules.txt b/src/vendor/modules.txt index 683040db9b..770a08e1fb 100644 --- a/src/vendor/modules.txt +++ b/src/vendor/modules.txt @@ -19,7 +19,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-20210831042530-f4d43177bf5e +# golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac ## explicit; go 1.17 golang.org/x/sys/cpu # golang.org/x/text v0.3.7 diff --git a/test/codegen/arithmetic.go b/test/codegen/arithmetic.go index 8b8c8ed64b..00841d52ae 100644 --- a/test/codegen/arithmetic.go +++ b/test/codegen/arithmetic.go @@ -86,24 +86,32 @@ func NegAddFromConstNeg(a int) int { func SubSubNegSimplify(a, b int) int { // amd64:"NEGQ" + // ppc64:"NEG" + // ppc64le:"NEG" r := (a - b) - a return r } func SubAddSimplify(a, b int) int { // amd64:-"SUBQ",-"ADDQ" + // ppc64:-"SUB",-"ADD" + // ppc64le:-"SUB",-"ADD" r := a + (b - a) return r } func SubAddNegSimplify(a, b int) int { // amd64:"NEGQ",-"ADDQ",-"SUBQ" + // ppc64:"NEG",-"ADD",-"SUB" + // ppc64le:"NEG",-"ADD",-"SUB" r := a - (b + a) return r } func AddAddSubSimplify(a, b, c int) int { // amd64:-"SUBQ" + // ppc64:-"SUB" + // ppc64le:-"SUB" r := a + (b + (c - a)) return r } @@ -159,30 +167,40 @@ func MulMemSrc(a []uint32, b []float32) { func MergeMuls1(n int) int { // amd64:"IMUL3Q\t[$]46" // 386:"IMUL3L\t[$]46" + // ppc64le:"MULLD\t[$]46" + // ppc64:"MULLD\t[$]46" return 15*n + 31*n // 46n } func MergeMuls2(n int) int { // amd64:"IMUL3Q\t[$]23","(ADDQ\t[$]29)|(LEAQ\t29)" // 386:"IMUL3L\t[$]23","ADDL\t[$]29" + // ppc64le/power9:"MADDLD",-"MULLD\t[$]23",-"ADD\t[$]29" + // ppc64le/power8:"MULLD\t[$]23","ADD\t[$]29" return 5*n + 7*(n+1) + 11*(n+2) // 23n + 29 } func MergeMuls3(a, n int) int { // amd64:"ADDQ\t[$]19",-"IMULQ\t[$]19" // 386:"ADDL\t[$]19",-"IMULL\t[$]19" + // ppc64:"ADD\t[$]19",-"MULLD\t[$]19" + // ppc64le:"ADD\t[$]19",-"MULLD\t[$]19" return a*n + 19*n // (a+19)n } func MergeMuls4(n int) int { // amd64:"IMUL3Q\t[$]14" // 386:"IMUL3L\t[$]14" + // ppc64:"MULLD\t[$]14" + // ppc64le:"MULLD\t[$]14" return 23*n - 9*n // 14n } func MergeMuls5(a, n int) int { // amd64:"ADDQ\t[$]-19",-"IMULQ\t[$]19" // 386:"ADDL\t[$]-19",-"IMULL\t[$]19" + // ppc64:"ADD\t[$]-19",-"MULLD\t[$]19" + // ppc64le:"ADD\t[$]-19",-"MULLD\t[$]19" return a*n - 19*n // (a-19)n } @@ -507,6 +525,8 @@ func MULA(a, b, c uint32) (uint32, uint32, uint32) { r1 := c*79 + a // arm:`ADD`,-`MULA`,-`MUL\s` // arm64:`ADD`,-`MADD`,-`MULW` + // ppc64:`ADD`,-`MULLD` + // ppc64le:`ADD`,-`MULLD` r2 := b*64 + c return r0, r1, r2 } @@ -522,6 +542,8 @@ func MULS(a, b, c uint32) (uint32, uint32, uint32) { r1 := a - c*79 // arm/7:`SUB`,-`MULS`,-`MUL\s` // arm64:`SUB`,-`MSUBW`,-`MULW` + // ppc64:`SUB`,-`MULLD` + // ppc64le:`SUB`,-`MULLD` r2 := c - b*64 return r0, r1, r2 } @@ -550,12 +572,20 @@ func divInt(v int64) int64 { // "(z + C) -x -> C + (z - x)" can optimize the following cases. func constantFold1(i0, j0, i1, j1, i2, j2, i3, j3 int) (int, int, int, int) { // arm64:"SUB","ADD\t[$]2" + // ppc64:"SUB","ADD\t[$]2" + // ppc64le:"SUB","ADD\t[$]2" r0 := (i0 + 3) - (j0 + 1) // arm64:"SUB","SUB\t[$]4" + // ppc64:"SUB","ADD\t[$]-4" + // ppc64le:"SUB","ADD\t[$]-4" r1 := (i1 - 3) - (j1 + 1) // arm64:"SUB","ADD\t[$]4" + // ppc64:"SUB","ADD\t[$]4" + // ppc64le:"SUB","ADD\t[$]4" r2 := (i2 + 3) - (j2 - 1) // arm64:"SUB","SUB\t[$]2" + // ppc64:"SUB","ADD\t[$]-2" + // ppc64le:"SUB","ADD\t[$]-2" r3 := (i3 - 3) - (j3 - 1) return r0, r1, r2, r3 } @@ -564,14 +594,20 @@ func constantFold1(i0, j0, i1, j1, i2, j2, i3, j3 int) (int, int, int, int) { // "(C - z) - x -> C - (z + x)" can optimize the following cases. func constantFold2(i0, j0, i1, j1 int) (int, int) { // arm64:"ADD","MOVD\t[$]2","SUB" + // ppc64le: `SUBC\tR[0-9]+,\s[$]2,\sR` + // ppc64: `SUBC\tR[0-9]+,\s[$]2,\sR` r0 := (3 - i0) - (j0 + 1) // arm64:"ADD","MOVD\t[$]4","SUB" + // ppc64le: `SUBC\tR[0-9]+,\s[$]4,\sR` + // ppc64: `SUBC\tR[0-9]+,\s[$]4,\sR` r1 := (3 - i1) - (j1 - 1) return r0, r1 } func constantFold3(i, j int) int { // arm64: "MOVD\t[$]30","MUL",-"ADD",-"LSL" + // ppc64:"MULLD\t[$]30","MULLD" + // ppc64le:"MULLD\t[$]30","MULLD" r := (5 * i) * (6 * j) return r } diff --git a/test/fixedbugs/issue49240.go b/test/fixedbugs/issue49240.go new file mode 100644 index 0000000000..26929fe1a2 --- /dev/null +++ b/test/fixedbugs/issue49240.go @@ -0,0 +1,11 @@ +// compile + +// Copyright 2021 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 + +func f() { + go copy([]int{1: 0}, []int{}) +} diff --git a/test/fixedbugs/issue49249.go b/test/fixedbugs/issue49249.go new file mode 100644 index 0000000000..f152a5a701 --- /dev/null +++ b/test/fixedbugs/issue49249.go @@ -0,0 +1,55 @@ +// compile -l + +// Copyright 2021 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 + +func f() int { + var a, b struct { + s struct { + s struct { + byte + float32 + } + } + } + _ = a + + return func() int { + return func() int { + a = struct { + s struct { + s struct { + byte + float32 + } + } + }{b.s} + return 0 + }() + }() +} + +func g() int { + var a, b struct { + s [1][1]struct { + byte + float32 + } + } + _ = a + + return func() int { + return func() int { + a = struct { + s [1][1]struct { + byte + float32 + } + }{b.s} + return 0 + }() + }() +} diff --git a/test/fixedbugs/issue49378.go b/test/fixedbugs/issue49378.go new file mode 100644 index 0000000000..70f466c929 --- /dev/null +++ b/test/fixedbugs/issue49378.go @@ -0,0 +1,25 @@ +// compile + +// Copyright 2021 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 + +func f(i int) { + var s1 struct { + s struct{ s struct{ i int } } + } + var s2, s3 struct { + a struct{ i int } + b int + } + func() { + i = 1 + 2*i + s3.a.i + func() int { + s2.a, s2.b = s3.a, s3.b + return 0 + }() + func(*int) int { + return s1.s.s.i + }(new(int)) + }() +} diff --git a/test/maymorestack.go b/test/maymorestack.go new file mode 100644 index 0000000000..ec84ad44bc --- /dev/null +++ b/test/maymorestack.go @@ -0,0 +1,47 @@ +// run -gcflags=-d=maymorestack=main.mayMoreStack + +// Copyright 2021 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. + +// Test the maymorestack testing hook by injecting a hook that counts +// how many times it is called and checking that count. + +package main + +import "runtime" + +var count uint32 + +//go:nosplit +func mayMoreStack() { + count++ +} + +func main() { + const wantCount = 128 + + anotherFunc(wantCount - 1) // -1 because the call to main already counted + + if count == 0 { + panic("mayMoreStack not called") + } else if count != wantCount { + println(count, "!=", wantCount) + panic("wrong number of calls to mayMoreStack") + } +} + +//go:noinline +func anotherFunc(n int) { + // Trigger a stack growth on at least some calls to + // anotherFunc to test that mayMoreStack is called outside the + // morestack loop. It's also important that it is called + // before (not after) morestack, but that's hard to test. + var x [1 << 10]byte + + if n > 1 { + anotherFunc(n - 1) + } + + runtime.KeepAlive(x) +} diff --git a/test/typeparam/index2.go b/test/typeparam/index2.go new file mode 100644 index 0000000000..683b76f76d --- /dev/null +++ b/test/typeparam/index2.go @@ -0,0 +1,67 @@ +// run -gcflags=-G=3 + +// Copyright 2021 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. + +// Testing various generic uses of indexing, both for reads and writes. + +package main + +import "fmt" + +// Can index an argument (read/write) constrained to be a slice or an array. +func Index1[T interface{ []int64 | [5]int64 }](x T) int64 { + x[2] = 5 + return x[3] +} + +// Can index an argument (read) constrained to be a byte array or a string. +func Index2[T interface{ []byte | string }](x T) byte { + return x[3] +} + +// Can index an argument (write) constrained to be a byte array, but not a string. +func Index2a[T interface{ []byte }](x T) byte { + x[2] = 'b' + return x[3] +} + +// Can index an argument (read/write) constrained to be a map. Maps can't +// be combined with any other type for indexing purposes. +func Index3[T interface{ map[int]int64 }](x T) int64 { + x[2] = 43 + return x[3] +} + +// But the type of the map keys or values can be parameterized. +func Index4[T any](x map[int]T) T { + var zero T + x[2] = zero + return x[3] +} + +func test[T comparable](got, want T) { + if got != want { + panic(fmt.Sprintf("got %v, want %v", got, want)) + } +} + +func main() { + x := make([]int64, 4) + x[3] = 2 + y := [5]int64{1, 2, 3, 4, 5} + z := "abcd" + w := make([]byte, 4) + w[3] = 5 + v := make(map[int]int64) + v[3] = 18 + + test(Index1(x), int64(2)) + test(Index1(y), int64(4)) + test(Index2(z), byte(100)) + test(Index2(w), byte(5)) + test(Index2a(w), byte(5)) + test(Index3(v), int64(18)) + test(Index4(v), int64(18)) +} diff --git a/test/typeparam/issue48962.go b/test/typeparam/issue48962.go new file mode 100644 index 0000000000..de9a23cdd2 --- /dev/null +++ b/test/typeparam/issue48962.go @@ -0,0 +1,15 @@ +// errorcheck -G=3 + +// Copyright 2021 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 + +type T0[P any] struct { // ERROR "invalid recursive type" + f P +} + +type T1 struct { + _ T0[T1] +} diff --git a/test/typeparam/issue49241.dir/a.go b/test/typeparam/issue49241.dir/a.go new file mode 100644 index 0000000000..34c99657d4 --- /dev/null +++ b/test/typeparam/issue49241.dir/a.go @@ -0,0 +1,13 @@ +// Copyright 2021 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 + +type T[P any] struct { + x P +} + +type U struct { + a,b int +} diff --git a/test/typeparam/issue49241.dir/b.go b/test/typeparam/issue49241.dir/b.go new file mode 100644 index 0000000000..45c1afbaf1 --- /dev/null +++ b/test/typeparam/issue49241.dir/b.go @@ -0,0 +1,17 @@ +// Copyright 2021 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 b + +import "a" + +//go:noinline +func F() interface {} { + return a.T[int]{} +} + +//go:noinline +func G() interface{} { + return struct{X,Y a.U}{} +} diff --git a/test/typeparam/issue49241.dir/c.go b/test/typeparam/issue49241.dir/c.go new file mode 100644 index 0000000000..ea3bab2954 --- /dev/null +++ b/test/typeparam/issue49241.dir/c.go @@ -0,0 +1,17 @@ +// Copyright 2021 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 c + +import "a" + +//go:noinline +func F() interface {} { + return a.T[int]{} +} + +//go:noinline +func G() interface{} { + return struct{X,Y a.U}{} +} diff --git a/test/typeparam/issue49241.dir/main.go b/test/typeparam/issue49241.dir/main.go new file mode 100644 index 0000000000..7c8a8b1acd --- /dev/null +++ b/test/typeparam/issue49241.dir/main.go @@ -0,0 +1,21 @@ +// Copyright 2021 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 ( + "b" + "c" +) + +func main() { + if b.G() != c.G() { + println(b.G(), c.G()) + panic("bad") + } + if b.F() != c.F() { + println(b.F(), c.F()) + panic("bad") + } +} diff --git a/test/typeparam/issue49241.go b/test/typeparam/issue49241.go new file mode 100644 index 0000000000..76930e5e4f --- /dev/null +++ b/test/typeparam/issue49241.go @@ -0,0 +1,7 @@ +// rundir -G=3 + +// Copyright 2021 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 ignored diff --git a/test/typeparam/issue49246.dir/a.go b/test/typeparam/issue49246.dir/a.go new file mode 100644 index 0000000000..97459ee748 --- /dev/null +++ b/test/typeparam/issue49246.dir/a.go @@ -0,0 +1,20 @@ +// Copyright 2021 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 + +type R[T any] struct{ v T } + +func (r R[T]) Self() R[T] { return R[T]{} } + +type Fn[T any] func() R[T] + +func X() (r R[int]) { return r.Self() } + +func Y[T any](a Fn[T]) Fn[int] { + return func() (r R[int]) { + // No crash: return R[int]{} + return r.Self() + } +} diff --git a/test/typeparam/issue49246.dir/b.go b/test/typeparam/issue49246.dir/b.go new file mode 100644 index 0000000000..5141b72fd4 --- /dev/null +++ b/test/typeparam/issue49246.dir/b.go @@ -0,0 +1,9 @@ +// Copyright 2021 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 b + +import "./a" + +func Crash() { a.Y(a.X)() } diff --git a/test/typeparam/issue49246.go b/test/typeparam/issue49246.go new file mode 100644 index 0000000000..87b4ff46c1 --- /dev/null +++ b/test/typeparam/issue49246.go @@ -0,0 +1,7 @@ +// compiledir -G=3 + +// Copyright 2021 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 ignored diff --git a/test/typeparam/issue49295.go b/test/typeparam/issue49295.go new file mode 100644 index 0000000000..435b44d10c --- /dev/null +++ b/test/typeparam/issue49295.go @@ -0,0 +1,30 @@ +// run -gcflags=-G=3 + +// Copyright 2021 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 "io" + +type Reader struct { + buf []byte +} +type Token *[16]byte + +func Read[T interface{ ~*[16]byte }](r *Reader) (t T, err error) { + if n := len(t); len(r.buf) >= n { + t = T(r.buf[:n]) + r.buf = r.buf[n:] + return + } + err = io.EOF + return +} + +func main() { + r := &Reader{buf: []byte("0123456789abcdef")} + token, err := Read[Token](r) + _, _ = token, err +} diff --git a/test/typeparam/issue49309.go b/test/typeparam/issue49309.go new file mode 100644 index 0000000000..36da86a9c3 --- /dev/null +++ b/test/typeparam/issue49309.go @@ -0,0 +1,25 @@ +// run -gcflags=-G=3 + +// Copyright 2021 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 + +func genfunc[T any](f func(c T)) { + var r T + + f(r) +} + +func myfunc(c string) { + test2(c) +} + +//go:noinline +func test2(a interface{}) { +} + +func main() { + genfunc(myfunc) +}