mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[dev.typeparams] all: merge dev.regabi (23b0c1f) into dev.typeparams
Merge List: + 2021-02-0223b0c1f76e[dev.regabi] all: merge master (fca94ab) into dev.regabi + 2021-02-02fca94ab3abspec: improve the example in Type assertions section + 2021-02-0298f8454a73cmd/link: don't decode type symbol in shared library in deadcode + 2021-02-021426a571b7cmd/link: fix off-by-1 error in findShlibSection + 2021-02-0132e789f4fbtest: fix incorrectly laid out instructions in issue11656.go + 2021-02-01ca6999e27c[dev.regabi] test: add a test for inlining closures + 2021-02-010b6cfea634doc/go1.16: document that on OpenBSD syscalls are now made through libc + 2021-02-0126e29aa15acmd/link: disable TestPIESize if CGO isn't enabled + 2021-02-016ac91e460cdoc/go1.16: minor markup fixes + 2021-01-2944361140c0embed: update docs for proposal tweaks + 2021-01-2968058edc39runtime: document pointer write atomicity for memclrNoHeapPointers + 2021-01-28c8bd8010ffsyscall: generate readlen/writelen for openbsd libc + 2021-01-2841bb49b878cmd/go: revert TestScript/build_trimpath to use ioutil.ReadFile + 2021-01-28725a642c2druntime: correct syscall10/syscall10X on openbsd/amd64 + 2021-01-284b068cafb5doc/go1.16: document go/build/constraint package + 2021-01-28376518d77fruntime,syscall: convert syscall on openbsd/arm64 to libc + 2021-01-27aca22bddf2[dev.regabi] cmd/compile: remove nested functions from expands_calls.go + 2021-01-27667e08ba8c[dev.regabi] cmd/go: Use GOMAXPROCS to limit default build, compile parallelism + 2021-01-2700f2ff5c94api/go1.16: add go/build/constraint APIs + 2021-01-2735334caf18crypto/x509: remove leftover CertificateRequest field + 2021-01-27a5a5e2c968runtime: make sure to remove open-coded defer entries in all cases after a recover + 2021-01-278cfa01943aruntime: block console ctrlhandler when the signal is handled + 2021-01-27ff9e8364c6cmd/go: skip issue33139 when the 'cc' script command is unavailable + 2021-01-27cd176b3615runtime: switch runtime to libc for openbsd/arm64 + 2021-01-276c8fbfbdcfruntime: convert openbsd/arm64 locking to libc + 2021-01-275cdf0da1bfsyscall: clean up mkasm related changes + 2021-01-27210f70e298doc/go1.16: fix closing brace in .Export format + 2021-01-270f797f168dmath: fix typo in sqrt.go code comment + 2021-01-269b636feafe[dev.regabi] cmd/compile: missing last patch set for cl286013 + 2021-01-26f7dad5eae4[dev.regabi] cmd/compile: remove leftover code form late call lowering work + 2021-01-268634a234dfruntime,syscall: convert syscall on openbsd/amd64 to libc + 2021-01-261d5e14632eos: further document limitations around naked file descriptors + 2021-01-26cf263e9f77os: correct names in CreateTemp and MkdirTemp doc comments + 2021-01-26ce8b318624net/http/fcgi: remove locking added to prevent a test-only race Change-Id: Ibd38d559c8a5b0aa32dd0d3a8cdf6876368a3aeb
This commit is contained in:
commit
0d2d6c7464
84 changed files with 4499 additions and 2007 deletions
|
|
@ -232,6 +232,35 @@ pkg go/build, type Package struct, TestEmbedPatterns []string
|
||||||
pkg go/build, type Package struct, TestEmbedPatternPos map[string][]token.Position
|
pkg go/build, type Package struct, TestEmbedPatternPos map[string][]token.Position
|
||||||
pkg go/build, type Package struct, XTestEmbedPatterns []string
|
pkg go/build, type Package struct, XTestEmbedPatterns []string
|
||||||
pkg go/build, type Package struct, XTestEmbedPatternPos map[string][]token.Position
|
pkg go/build, type Package struct, XTestEmbedPatternPos map[string][]token.Position
|
||||||
|
pkg go/build/constraint, func IsGoBuild(string) bool
|
||||||
|
pkg go/build/constraint, func IsPlusBuild(string) bool
|
||||||
|
pkg go/build/constraint, func Parse(string) (Expr, error)
|
||||||
|
pkg go/build/constraint, func PlusBuildLines(Expr) ([]string, error)
|
||||||
|
pkg go/build/constraint, method (*AndExpr) Eval(func(string) bool) bool
|
||||||
|
pkg go/build/constraint, method (*AndExpr) String() string
|
||||||
|
pkg go/build/constraint, method (*NotExpr) Eval(func(string) bool) bool
|
||||||
|
pkg go/build/constraint, method (*NotExpr) String() string
|
||||||
|
pkg go/build/constraint, method (*OrExpr) Eval(func(string) bool) bool
|
||||||
|
pkg go/build/constraint, method (*OrExpr) String() string
|
||||||
|
pkg go/build/constraint, method (*SyntaxError) Error() string
|
||||||
|
pkg go/build/constraint, method (*TagExpr) Eval(func(string) bool) bool
|
||||||
|
pkg go/build/constraint, method (*TagExpr) String() string
|
||||||
|
pkg go/build/constraint, type AndExpr struct
|
||||||
|
pkg go/build/constraint, type AndExpr struct, X Expr
|
||||||
|
pkg go/build/constraint, type AndExpr struct, Y Expr
|
||||||
|
pkg go/build/constraint, type Expr interface, Eval(func(string) bool) bool
|
||||||
|
pkg go/build/constraint, type Expr interface, String() string
|
||||||
|
pkg go/build/constraint, type Expr interface, unexported methods
|
||||||
|
pkg go/build/constraint, type NotExpr struct
|
||||||
|
pkg go/build/constraint, type NotExpr struct, X Expr
|
||||||
|
pkg go/build/constraint, type OrExpr struct
|
||||||
|
pkg go/build/constraint, type OrExpr struct, X Expr
|
||||||
|
pkg go/build/constraint, type OrExpr struct, Y Expr
|
||||||
|
pkg go/build/constraint, type SyntaxError struct
|
||||||
|
pkg go/build/constraint, type SyntaxError struct, Err string
|
||||||
|
pkg go/build/constraint, type SyntaxError struct, Offset int
|
||||||
|
pkg go/build/constraint, type TagExpr struct
|
||||||
|
pkg go/build/constraint, type TagExpr struct, Tag string
|
||||||
pkg html/template, func ParseFS(fs.FS, ...string) (*Template, error)
|
pkg html/template, func ParseFS(fs.FS, ...string) (*Template, error)
|
||||||
pkg html/template, method (*Template) ParseFS(fs.FS, ...string) (*Template, error)
|
pkg html/template, method (*Template) ParseFS(fs.FS, ...string) (*Template, error)
|
||||||
pkg io, func NopCloser(Reader) ReadCloser
|
pkg io, func NopCloser(Reader) ReadCloser
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,16 @@ Do not send CLs removing the interior tags from such phrases.
|
||||||
support cgo.
|
support cgo.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<p><!-- golang.org/issue/36435, many CLs -->
|
||||||
|
On the 64-bit x86 and 64-bit ARM architectures on OpenBSD (the
|
||||||
|
<code>openbsd/amd64</code> and <code>openbsd/arm64</code> ports), system
|
||||||
|
calls are now made through <code>libc</code>, instead of directly using
|
||||||
|
the <code>SYSCALL</code>/<code>SVC</code> instruction. This ensures
|
||||||
|
forward-compatibility with future versions of OpenBSD. In particular,
|
||||||
|
OpenBSD 6.9 onwards will require system calls to be made through
|
||||||
|
<code>libc</code> for non-static Go binaries.
|
||||||
|
</p>
|
||||||
|
|
||||||
<h3 id="386">386</h3>
|
<h3 id="386">386</h3>
|
||||||
|
|
||||||
<p><!-- golang.org/issue/40255, golang.org/issue/41848, CL 258957, and CL 260017 -->
|
<p><!-- golang.org/issue/40255, golang.org/issue/41848, CL 258957, and CL 260017 -->
|
||||||
|
|
@ -146,7 +156,7 @@ Do not send CLs removing the interior tags from such phrases.
|
||||||
<code>retract</code> directives may now be used in a <code>go.mod</code> file
|
<code>retract</code> directives may now be used in a <code>go.mod</code> file
|
||||||
to indicate that certain published versions of the module should not be used
|
to indicate that certain published versions of the module should not be used
|
||||||
by other modules. A module author may retract a version after a severe problem
|
by other modules. A module author may retract a version after a severe problem
|
||||||
is discovered or if the version was published unintentionally.<br>
|
is discovered or if the version was published unintentionally.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><!-- golang.org/issue/26603 -->
|
<p><!-- golang.org/issue/26603 -->
|
||||||
|
|
@ -275,7 +285,7 @@ Do not send CLs removing the interior tags from such phrases.
|
||||||
When the <code>-export</code> flag is specified, the <code>BuildID</code>
|
When the <code>-export</code> flag is specified, the <code>BuildID</code>
|
||||||
field is now set to the build ID of the compiled package. This is equivalent
|
field is now set to the build ID of the compiled package. This is equivalent
|
||||||
to running <code>go</code> <code>tool</code> <code>buildid</code> on
|
to running <code>go</code> <code>tool</code> <code>buildid</code> on
|
||||||
<code>go</code> <code>list</code> <code>-exported</code> <code>-f</code> <code>{{.Export}</code>,
|
<code>go</code> <code>list</code> <code>-exported</code> <code>-f</code> <code>{{.Export}}</code>,
|
||||||
but without the extra step.
|
but without the extra step.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
@ -762,6 +772,25 @@ func TestFoo(t *testing.T) {
|
||||||
</dd>
|
</dd>
|
||||||
</dl><!-- go/build -->
|
</dl><!-- go/build -->
|
||||||
|
|
||||||
|
<dl id="go/build/constraint"><dt><a href="/pkg/go/build/constraint/">go/build/constraint</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 240604 -->
|
||||||
|
The new
|
||||||
|
<a href="/pkg/go/build/constraint/"><code>go/build/constraint</code></a>
|
||||||
|
package parses build constraint lines, both the original
|
||||||
|
<code>// +build</code> syntax and the <code>//go:build</code>
|
||||||
|
syntax that will be introduced in Go 1.17.
|
||||||
|
This package exists so that tools built with Go 1.16 will be able
|
||||||
|
to process Go 1.17 source code.
|
||||||
|
See <a href="https://golang.org/design/draft-gobuild">https://golang.org/design/draft-gobuild</a>
|
||||||
|
for details about the build constraint syntaxes and the planned
|
||||||
|
transition to the <code>//go:build</code> syntax.
|
||||||
|
Note that <code>//go:build</code> lines are <b>not</b> supported
|
||||||
|
in Go 1.16 and should not be introduced into Go programs yet.
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
</dl><!-- go/build/constraint -->
|
||||||
|
|
||||||
<dl id="html/template"><dt><a href="/pkg/html/template/">html/template</a></dt>
|
<dl id="html/template"><dt><a href="/pkg/html/template/">html/template</a></dt>
|
||||||
<dd>
|
<dd>
|
||||||
<p><!-- CL 243938 -->
|
<p><!-- CL 243938 -->
|
||||||
|
|
@ -880,7 +909,7 @@ func TestFoo(t *testing.T) {
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><!-- CL 250039 -->
|
<p><!-- CL 250039 -->
|
||||||
The <a href="/pkg/net/http/#Client">Client</a> now sends
|
The <a href="/pkg/net/http/#Client"><code>Client</code></a> now sends
|
||||||
an explicit <code>Content-Length:</code> <code>0</code>
|
an explicit <code>Content-Length:</code> <code>0</code>
|
||||||
header in <code>PATCH</code> requests with empty bodies,
|
header in <code>PATCH</code> requests with empty bodies,
|
||||||
matching the existing behavior of <code>POST</code> and <code>PUT</code>.
|
matching the existing behavior of <code>POST</code> and <code>PUT</code>.
|
||||||
|
|
@ -927,7 +956,7 @@ func TestFoo(t *testing.T) {
|
||||||
<dl id="net/smtp"><dt><a href="/pkg/net/smtp/">net/smtp</a></dt>
|
<dl id="net/smtp"><dt><a href="/pkg/net/smtp/">net/smtp</a></dt>
|
||||||
<dd>
|
<dd>
|
||||||
<p><!-- CL 247257 -->
|
<p><!-- CL 247257 -->
|
||||||
The <a href="/pkg/net/smtp/#Client">Client</a>'s
|
The <a href="/pkg/net/smtp/#Client"><code>Client</code></a>'s
|
||||||
<a href="/pkg/net/smtp/#Client.Mail"><code>Mail</code></a>
|
<a href="/pkg/net/smtp/#Client.Mail"><code>Mail</code></a>
|
||||||
method now sends the <code>SMTPUTF8</code> directive to
|
method now sends the <code>SMTPUTF8</code> directive to
|
||||||
servers that support it, signaling that addresses are encoded in UTF-8.
|
servers that support it, signaling that addresses are encoded in UTF-8.
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<!--{
|
<!--{
|
||||||
"Title": "The Go Programming Language Specification",
|
"Title": "The Go Programming Language Specification",
|
||||||
"Subtitle": "Version of Oct 7, 2020",
|
"Subtitle": "Version of Feb 2, 2021",
|
||||||
"Path": "/ref/spec"
|
"Path": "/ref/spec"
|
||||||
}-->
|
}-->
|
||||||
|
|
||||||
|
|
@ -3400,7 +3400,7 @@ A type assertion used in an <a href="#Assignments">assignment</a> or initializat
|
||||||
v, ok = x.(T)
|
v, ok = x.(T)
|
||||||
v, ok := x.(T)
|
v, ok := x.(T)
|
||||||
var v, ok = x.(T)
|
var v, ok = x.(T)
|
||||||
var v, ok T1 = x.(T)
|
var v, ok interface{} = x.(T) // dynamic types of v and ok are T and bool
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
|
||||||
|
|
@ -1063,3 +1063,11 @@ func TestGCData(t *testing.T) {
|
||||||
goCmd(t, "build", "-linkshared", "./gcdata/main")
|
goCmd(t, "build", "-linkshared", "./gcdata/main")
|
||||||
runWithEnv(t, "running gcdata/main", []string{"GODEBUG=clobberfree=1"}, "./main")
|
runWithEnv(t, "running gcdata/main", []string{"GODEBUG=clobberfree=1"}, "./main")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test that we don't decode type symbols from shared libraries (which has no data,
|
||||||
|
// causing panic). See issue 44031.
|
||||||
|
func TestIssue44031(t *testing.T) {
|
||||||
|
goCmd(t, "install", "-buildmode=shared", "-linkshared", "./issue44031/a")
|
||||||
|
goCmd(t, "install", "-buildmode=shared", "-linkshared", "./issue44031/b")
|
||||||
|
goCmd(t, "run", "-linkshared", "./issue44031/main")
|
||||||
|
}
|
||||||
|
|
|
||||||
9
misc/cgo/testshared/testdata/issue44031/a/a.go
vendored
Normal file
9
misc/cgo/testshared/testdata/issue44031/a/a.go
vendored
Normal file
|
|
@ -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 a
|
||||||
|
|
||||||
|
type ATypeWithALoooooongName interface { // a long name, so the type descriptor symbol name is mangled
|
||||||
|
M()
|
||||||
|
}
|
||||||
17
misc/cgo/testshared/testdata/issue44031/b/b.go
vendored
Normal file
17
misc/cgo/testshared/testdata/issue44031/b/b.go
vendored
Normal file
|
|
@ -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 "testshared/issue44031/a"
|
||||||
|
|
||||||
|
type T int
|
||||||
|
|
||||||
|
func (T) M() {}
|
||||||
|
|
||||||
|
var i = a.ATypeWithALoooooongName(T(0))
|
||||||
|
|
||||||
|
func F() {
|
||||||
|
i.M()
|
||||||
|
}
|
||||||
20
misc/cgo/testshared/testdata/issue44031/main/main.go
vendored
Normal file
20
misc/cgo/testshared/testdata/issue44031/main/main.go
vendored
Normal file
|
|
@ -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
|
||||||
|
|
||||||
|
import "testshared/issue44031/b"
|
||||||
|
|
||||||
|
type t int
|
||||||
|
|
||||||
|
func (t) m() {}
|
||||||
|
|
||||||
|
type i interface{ m() } // test that unexported method is correctly marked
|
||||||
|
|
||||||
|
var v interface{} = t(0)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
b.F()
|
||||||
|
v.(i).m()
|
||||||
|
}
|
||||||
|
|
@ -431,7 +431,6 @@ var passes = [...]pass{
|
||||||
{name: "early copyelim", fn: copyelim},
|
{name: "early copyelim", fn: copyelim},
|
||||||
{name: "early deadcode", fn: deadcode}, // remove generated dead code to avoid doing pointless work during opt
|
{name: "early deadcode", fn: deadcode}, // remove generated dead code to avoid doing pointless work during opt
|
||||||
{name: "short circuit", fn: shortcircuit},
|
{name: "short circuit", fn: shortcircuit},
|
||||||
{name: "decompose args", fn: decomposeArgs, required: !go116lateCallExpansion, disabled: go116lateCallExpansion}, // handled by late call lowering
|
|
||||||
{name: "decompose user", fn: decomposeUser, required: true},
|
{name: "decompose user", fn: decomposeUser, required: true},
|
||||||
{name: "pre-opt deadcode", fn: deadcode},
|
{name: "pre-opt deadcode", fn: deadcode},
|
||||||
{name: "opt", fn: opt, required: true}, // NB: some generic rules know the name of the opt pass. TODO: split required rules and optimizing rules
|
{name: "opt", fn: opt, required: true}, // NB: some generic rules know the name of the opt pass. TODO: split required rules and optimizing rules
|
||||||
|
|
|
||||||
|
|
@ -179,14 +179,6 @@ type Frontend interface {
|
||||||
MyImportPath() string
|
MyImportPath() string
|
||||||
}
|
}
|
||||||
|
|
||||||
const go116lateCallExpansion = true
|
|
||||||
|
|
||||||
// LateCallExpansionEnabledWithin returns true if late call expansion should be tested
|
|
||||||
// within compilation of a function/method.
|
|
||||||
func LateCallExpansionEnabledWithin(f *Func) bool {
|
|
||||||
return go116lateCallExpansion
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewConfig returns a new configuration object for the given architecture.
|
// NewConfig returns a new configuration object for the given architecture.
|
||||||
func NewConfig(arch string, types Types, ctxt *obj.Link, optimize bool) *Config {
|
func NewConfig(arch string, types Types, ctxt *obj.Link, optimize bool) *Config {
|
||||||
c := &Config{arch: arch, Types: types}
|
c := &Config{arch: arch, Types: types}
|
||||||
|
|
|
||||||
|
|
@ -219,10 +219,6 @@ func decomposeInterfacePhi(v *Value) {
|
||||||
v.AddArg(data)
|
v.AddArg(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func decomposeArgs(f *Func) {
|
|
||||||
applyRewrite(f, rewriteBlockdecArgs, rewriteValuedecArgs, removeDeadValues)
|
|
||||||
}
|
|
||||||
|
|
||||||
func decomposeUser(f *Func) {
|
func decomposeUser(f *Func) {
|
||||||
for _, b := range f.Blocks {
|
for _, b := range f.Blocks {
|
||||||
for _, v := range b.Values {
|
for _, v := range b.Values {
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -42,20 +42,20 @@
|
||||||
(Store {hi.Type} dst hi mem))
|
(Store {hi.Type} dst hi mem))
|
||||||
|
|
||||||
// These are not enabled during decomposeBuiltin if late call expansion, but they are always enabled for softFloat
|
// These are not enabled during decomposeBuiltin if late call expansion, but they are always enabled for softFloat
|
||||||
(Arg {n} [off]) && is64BitInt(v.Type) && !config.BigEndian && v.Type.IsSigned() && !(go116lateCallExpansion && b.Func.pass.name == "decompose builtin") =>
|
(Arg {n} [off]) && is64BitInt(v.Type) && !config.BigEndian && v.Type.IsSigned() && !(b.Func.pass.name == "decompose builtin") =>
|
||||||
(Int64Make
|
(Int64Make
|
||||||
(Arg <typ.Int32> {n} [off+4])
|
(Arg <typ.Int32> {n} [off+4])
|
||||||
(Arg <typ.UInt32> {n} [off]))
|
(Arg <typ.UInt32> {n} [off]))
|
||||||
(Arg {n} [off]) && is64BitInt(v.Type) && !config.BigEndian && !v.Type.IsSigned() && !(go116lateCallExpansion && b.Func.pass.name == "decompose builtin") =>
|
(Arg {n} [off]) && is64BitInt(v.Type) && !config.BigEndian && !v.Type.IsSigned() && !(b.Func.pass.name == "decompose builtin") =>
|
||||||
(Int64Make
|
(Int64Make
|
||||||
(Arg <typ.UInt32> {n} [off+4])
|
(Arg <typ.UInt32> {n} [off+4])
|
||||||
(Arg <typ.UInt32> {n} [off]))
|
(Arg <typ.UInt32> {n} [off]))
|
||||||
|
|
||||||
(Arg {n} [off]) && is64BitInt(v.Type) && config.BigEndian && v.Type.IsSigned() && !(go116lateCallExpansion && b.Func.pass.name == "decompose builtin") =>
|
(Arg {n} [off]) && is64BitInt(v.Type) && config.BigEndian && v.Type.IsSigned() && !(b.Func.pass.name == "decompose builtin") =>
|
||||||
(Int64Make
|
(Int64Make
|
||||||
(Arg <typ.Int32> {n} [off])
|
(Arg <typ.Int32> {n} [off])
|
||||||
(Arg <typ.UInt32> {n} [off+4]))
|
(Arg <typ.UInt32> {n} [off+4]))
|
||||||
(Arg {n} [off]) && is64BitInt(v.Type) && config.BigEndian && !v.Type.IsSigned() && !(go116lateCallExpansion && b.Func.pass.name == "decompose builtin") =>
|
(Arg {n} [off]) && is64BitInt(v.Type) && config.BigEndian && !v.Type.IsSigned() && !(b.Func.pass.name == "decompose builtin") =>
|
||||||
(Int64Make
|
(Int64Make
|
||||||
(Arg <typ.UInt32> {n} [off])
|
(Arg <typ.UInt32> {n} [off])
|
||||||
(Arg <typ.UInt32> {n} [off+4]))
|
(Arg <typ.UInt32> {n} [off+4]))
|
||||||
|
|
|
||||||
|
|
@ -1,58 +0,0 @@
|
||||||
// Copyright 2018 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// Decompose compound argument values
|
|
||||||
// Do this early to simplify tracking names for debugging.
|
|
||||||
|
|
||||||
(Arg {n} [off]) && v.Type.IsString() =>
|
|
||||||
(StringMake
|
|
||||||
(Arg <typ.BytePtr> {n} [off])
|
|
||||||
(Arg <typ.Int> {n} [off+int32(config.PtrSize)]))
|
|
||||||
|
|
||||||
(Arg {n} [off]) && v.Type.IsSlice() =>
|
|
||||||
(SliceMake
|
|
||||||
(Arg <v.Type.Elem().PtrTo()> {n} [off])
|
|
||||||
(Arg <typ.Int> {n} [off+int32(config.PtrSize)])
|
|
||||||
(Arg <typ.Int> {n} [off+2*int32(config.PtrSize)]))
|
|
||||||
|
|
||||||
(Arg {n} [off]) && v.Type.IsInterface() =>
|
|
||||||
(IMake
|
|
||||||
(Arg <typ.Uintptr> {n} [off])
|
|
||||||
(Arg <typ.BytePtr> {n} [off+int32(config.PtrSize)]))
|
|
||||||
|
|
||||||
(Arg {n} [off]) && v.Type.IsComplex() && v.Type.Size() == 16 =>
|
|
||||||
(ComplexMake
|
|
||||||
(Arg <typ.Float64> {n} [off])
|
|
||||||
(Arg <typ.Float64> {n} [off+8]))
|
|
||||||
|
|
||||||
(Arg {n} [off]) && v.Type.IsComplex() && v.Type.Size() == 8 =>
|
|
||||||
(ComplexMake
|
|
||||||
(Arg <typ.Float32> {n} [off])
|
|
||||||
(Arg <typ.Float32> {n} [off+4]))
|
|
||||||
|
|
||||||
(Arg <t>) && t.IsStruct() && t.NumFields() == 0 && fe.CanSSA(t) =>
|
|
||||||
(StructMake0)
|
|
||||||
(Arg <t> {n} [off]) && t.IsStruct() && t.NumFields() == 1 && fe.CanSSA(t) =>
|
|
||||||
(StructMake1
|
|
||||||
(Arg <t.FieldType(0)> {n} [off+int32(t.FieldOff(0))]))
|
|
||||||
(Arg <t> {n} [off]) && t.IsStruct() && t.NumFields() == 2 && fe.CanSSA(t) =>
|
|
||||||
(StructMake2
|
|
||||||
(Arg <t.FieldType(0)> {n} [off+int32(t.FieldOff(0))])
|
|
||||||
(Arg <t.FieldType(1)> {n} [off+int32(t.FieldOff(1))]))
|
|
||||||
(Arg <t> {n} [off]) && t.IsStruct() && t.NumFields() == 3 && fe.CanSSA(t) =>
|
|
||||||
(StructMake3
|
|
||||||
(Arg <t.FieldType(0)> {n} [off+int32(t.FieldOff(0))])
|
|
||||||
(Arg <t.FieldType(1)> {n} [off+int32(t.FieldOff(1))])
|
|
||||||
(Arg <t.FieldType(2)> {n} [off+int32(t.FieldOff(2))]))
|
|
||||||
(Arg <t> {n} [off]) && t.IsStruct() && t.NumFields() == 4 && fe.CanSSA(t) =>
|
|
||||||
(StructMake4
|
|
||||||
(Arg <t.FieldType(0)> {n} [off+int32(t.FieldOff(0))])
|
|
||||||
(Arg <t.FieldType(1)> {n} [off+int32(t.FieldOff(1))])
|
|
||||||
(Arg <t.FieldType(2)> {n} [off+int32(t.FieldOff(2))])
|
|
||||||
(Arg <t.FieldType(3)> {n} [off+int32(t.FieldOff(3))]))
|
|
||||||
|
|
||||||
(Arg <t>) && t.IsArray() && t.NumElem() == 0 =>
|
|
||||||
(ArrayMake0)
|
|
||||||
(Arg <t> {n} [off]) && t.IsArray() && t.NumElem() == 1 && fe.CanSSA(t) =>
|
|
||||||
(ArrayMake1 (Arg <t.Elem()> {n} [off]))
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
// Copyright 2018 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
var decArgsOps = []opData{}
|
|
||||||
|
|
||||||
var decArgsBlocks = []blockData{}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
archs = append(archs, arch{
|
|
||||||
name: "decArgs",
|
|
||||||
ops: decArgsOps,
|
|
||||||
blocks: decArgsBlocks,
|
|
||||||
generic: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
@ -184,12 +184,12 @@ func rewriteValuedec64_OpArg(v *Value) bool {
|
||||||
config := b.Func.Config
|
config := b.Func.Config
|
||||||
typ := &b.Func.Config.Types
|
typ := &b.Func.Config.Types
|
||||||
// match: (Arg {n} [off])
|
// match: (Arg {n} [off])
|
||||||
// cond: is64BitInt(v.Type) && !config.BigEndian && v.Type.IsSigned() && !(go116lateCallExpansion && b.Func.pass.name == "decompose builtin")
|
// cond: is64BitInt(v.Type) && !config.BigEndian && v.Type.IsSigned() && !(b.Func.pass.name == "decompose builtin")
|
||||||
// result: (Int64Make (Arg <typ.Int32> {n} [off+4]) (Arg <typ.UInt32> {n} [off]))
|
// result: (Int64Make (Arg <typ.Int32> {n} [off+4]) (Arg <typ.UInt32> {n} [off]))
|
||||||
for {
|
for {
|
||||||
off := auxIntToInt32(v.AuxInt)
|
off := auxIntToInt32(v.AuxInt)
|
||||||
n := auxToSym(v.Aux)
|
n := auxToSym(v.Aux)
|
||||||
if !(is64BitInt(v.Type) && !config.BigEndian && v.Type.IsSigned() && !(go116lateCallExpansion && b.Func.pass.name == "decompose builtin")) {
|
if !(is64BitInt(v.Type) && !config.BigEndian && v.Type.IsSigned() && !(b.Func.pass.name == "decompose builtin")) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.reset(OpInt64Make)
|
v.reset(OpInt64Make)
|
||||||
|
|
@ -203,12 +203,12 @@ func rewriteValuedec64_OpArg(v *Value) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (Arg {n} [off])
|
// match: (Arg {n} [off])
|
||||||
// cond: is64BitInt(v.Type) && !config.BigEndian && !v.Type.IsSigned() && !(go116lateCallExpansion && b.Func.pass.name == "decompose builtin")
|
// cond: is64BitInt(v.Type) && !config.BigEndian && !v.Type.IsSigned() && !(b.Func.pass.name == "decompose builtin")
|
||||||
// result: (Int64Make (Arg <typ.UInt32> {n} [off+4]) (Arg <typ.UInt32> {n} [off]))
|
// result: (Int64Make (Arg <typ.UInt32> {n} [off+4]) (Arg <typ.UInt32> {n} [off]))
|
||||||
for {
|
for {
|
||||||
off := auxIntToInt32(v.AuxInt)
|
off := auxIntToInt32(v.AuxInt)
|
||||||
n := auxToSym(v.Aux)
|
n := auxToSym(v.Aux)
|
||||||
if !(is64BitInt(v.Type) && !config.BigEndian && !v.Type.IsSigned() && !(go116lateCallExpansion && b.Func.pass.name == "decompose builtin")) {
|
if !(is64BitInt(v.Type) && !config.BigEndian && !v.Type.IsSigned() && !(b.Func.pass.name == "decompose builtin")) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.reset(OpInt64Make)
|
v.reset(OpInt64Make)
|
||||||
|
|
@ -222,12 +222,12 @@ func rewriteValuedec64_OpArg(v *Value) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (Arg {n} [off])
|
// match: (Arg {n} [off])
|
||||||
// cond: is64BitInt(v.Type) && config.BigEndian && v.Type.IsSigned() && !(go116lateCallExpansion && b.Func.pass.name == "decompose builtin")
|
// cond: is64BitInt(v.Type) && config.BigEndian && v.Type.IsSigned() && !(b.Func.pass.name == "decompose builtin")
|
||||||
// result: (Int64Make (Arg <typ.Int32> {n} [off]) (Arg <typ.UInt32> {n} [off+4]))
|
// result: (Int64Make (Arg <typ.Int32> {n} [off]) (Arg <typ.UInt32> {n} [off+4]))
|
||||||
for {
|
for {
|
||||||
off := auxIntToInt32(v.AuxInt)
|
off := auxIntToInt32(v.AuxInt)
|
||||||
n := auxToSym(v.Aux)
|
n := auxToSym(v.Aux)
|
||||||
if !(is64BitInt(v.Type) && config.BigEndian && v.Type.IsSigned() && !(go116lateCallExpansion && b.Func.pass.name == "decompose builtin")) {
|
if !(is64BitInt(v.Type) && config.BigEndian && v.Type.IsSigned() && !(b.Func.pass.name == "decompose builtin")) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.reset(OpInt64Make)
|
v.reset(OpInt64Make)
|
||||||
|
|
@ -241,12 +241,12 @@ func rewriteValuedec64_OpArg(v *Value) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (Arg {n} [off])
|
// match: (Arg {n} [off])
|
||||||
// cond: is64BitInt(v.Type) && config.BigEndian && !v.Type.IsSigned() && !(go116lateCallExpansion && b.Func.pass.name == "decompose builtin")
|
// cond: is64BitInt(v.Type) && config.BigEndian && !v.Type.IsSigned() && !(b.Func.pass.name == "decompose builtin")
|
||||||
// result: (Int64Make (Arg <typ.UInt32> {n} [off]) (Arg <typ.UInt32> {n} [off+4]))
|
// result: (Int64Make (Arg <typ.UInt32> {n} [off]) (Arg <typ.UInt32> {n} [off+4]))
|
||||||
for {
|
for {
|
||||||
off := auxIntToInt32(v.AuxInt)
|
off := auxIntToInt32(v.AuxInt)
|
||||||
n := auxToSym(v.Aux)
|
n := auxToSym(v.Aux)
|
||||||
if !(is64BitInt(v.Type) && config.BigEndian && !v.Type.IsSigned() && !(go116lateCallExpansion && b.Func.pass.name == "decompose builtin")) {
|
if !(is64BitInt(v.Type) && config.BigEndian && !v.Type.IsSigned() && !(b.Func.pass.name == "decompose builtin")) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.reset(OpInt64Make)
|
v.reset(OpInt64Make)
|
||||||
|
|
|
||||||
|
|
@ -1,247 +0,0 @@
|
||||||
// Code generated from gen/decArgs.rules; DO NOT EDIT.
|
|
||||||
// generated with: cd gen; go run *.go
|
|
||||||
|
|
||||||
package ssa
|
|
||||||
|
|
||||||
func rewriteValuedecArgs(v *Value) bool {
|
|
||||||
switch v.Op {
|
|
||||||
case OpArg:
|
|
||||||
return rewriteValuedecArgs_OpArg(v)
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
func rewriteValuedecArgs_OpArg(v *Value) bool {
|
|
||||||
b := v.Block
|
|
||||||
config := b.Func.Config
|
|
||||||
fe := b.Func.fe
|
|
||||||
typ := &b.Func.Config.Types
|
|
||||||
// match: (Arg {n} [off])
|
|
||||||
// cond: v.Type.IsString()
|
|
||||||
// result: (StringMake (Arg <typ.BytePtr> {n} [off]) (Arg <typ.Int> {n} [off+int32(config.PtrSize)]))
|
|
||||||
for {
|
|
||||||
off := auxIntToInt32(v.AuxInt)
|
|
||||||
n := auxToSym(v.Aux)
|
|
||||||
if !(v.Type.IsString()) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
v.reset(OpStringMake)
|
|
||||||
v0 := b.NewValue0(v.Pos, OpArg, typ.BytePtr)
|
|
||||||
v0.AuxInt = int32ToAuxInt(off)
|
|
||||||
v0.Aux = symToAux(n)
|
|
||||||
v1 := b.NewValue0(v.Pos, OpArg, typ.Int)
|
|
||||||
v1.AuxInt = int32ToAuxInt(off + int32(config.PtrSize))
|
|
||||||
v1.Aux = symToAux(n)
|
|
||||||
v.AddArg2(v0, v1)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
// match: (Arg {n} [off])
|
|
||||||
// cond: v.Type.IsSlice()
|
|
||||||
// result: (SliceMake (Arg <v.Type.Elem().PtrTo()> {n} [off]) (Arg <typ.Int> {n} [off+int32(config.PtrSize)]) (Arg <typ.Int> {n} [off+2*int32(config.PtrSize)]))
|
|
||||||
for {
|
|
||||||
off := auxIntToInt32(v.AuxInt)
|
|
||||||
n := auxToSym(v.Aux)
|
|
||||||
if !(v.Type.IsSlice()) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
v.reset(OpSliceMake)
|
|
||||||
v0 := b.NewValue0(v.Pos, OpArg, v.Type.Elem().PtrTo())
|
|
||||||
v0.AuxInt = int32ToAuxInt(off)
|
|
||||||
v0.Aux = symToAux(n)
|
|
||||||
v1 := b.NewValue0(v.Pos, OpArg, typ.Int)
|
|
||||||
v1.AuxInt = int32ToAuxInt(off + int32(config.PtrSize))
|
|
||||||
v1.Aux = symToAux(n)
|
|
||||||
v2 := b.NewValue0(v.Pos, OpArg, typ.Int)
|
|
||||||
v2.AuxInt = int32ToAuxInt(off + 2*int32(config.PtrSize))
|
|
||||||
v2.Aux = symToAux(n)
|
|
||||||
v.AddArg3(v0, v1, v2)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
// match: (Arg {n} [off])
|
|
||||||
// cond: v.Type.IsInterface()
|
|
||||||
// result: (IMake (Arg <typ.Uintptr> {n} [off]) (Arg <typ.BytePtr> {n} [off+int32(config.PtrSize)]))
|
|
||||||
for {
|
|
||||||
off := auxIntToInt32(v.AuxInt)
|
|
||||||
n := auxToSym(v.Aux)
|
|
||||||
if !(v.Type.IsInterface()) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
v.reset(OpIMake)
|
|
||||||
v0 := b.NewValue0(v.Pos, OpArg, typ.Uintptr)
|
|
||||||
v0.AuxInt = int32ToAuxInt(off)
|
|
||||||
v0.Aux = symToAux(n)
|
|
||||||
v1 := b.NewValue0(v.Pos, OpArg, typ.BytePtr)
|
|
||||||
v1.AuxInt = int32ToAuxInt(off + int32(config.PtrSize))
|
|
||||||
v1.Aux = symToAux(n)
|
|
||||||
v.AddArg2(v0, v1)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
// match: (Arg {n} [off])
|
|
||||||
// cond: v.Type.IsComplex() && v.Type.Size() == 16
|
|
||||||
// result: (ComplexMake (Arg <typ.Float64> {n} [off]) (Arg <typ.Float64> {n} [off+8]))
|
|
||||||
for {
|
|
||||||
off := auxIntToInt32(v.AuxInt)
|
|
||||||
n := auxToSym(v.Aux)
|
|
||||||
if !(v.Type.IsComplex() && v.Type.Size() == 16) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
v.reset(OpComplexMake)
|
|
||||||
v0 := b.NewValue0(v.Pos, OpArg, typ.Float64)
|
|
||||||
v0.AuxInt = int32ToAuxInt(off)
|
|
||||||
v0.Aux = symToAux(n)
|
|
||||||
v1 := b.NewValue0(v.Pos, OpArg, typ.Float64)
|
|
||||||
v1.AuxInt = int32ToAuxInt(off + 8)
|
|
||||||
v1.Aux = symToAux(n)
|
|
||||||
v.AddArg2(v0, v1)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
// match: (Arg {n} [off])
|
|
||||||
// cond: v.Type.IsComplex() && v.Type.Size() == 8
|
|
||||||
// result: (ComplexMake (Arg <typ.Float32> {n} [off]) (Arg <typ.Float32> {n} [off+4]))
|
|
||||||
for {
|
|
||||||
off := auxIntToInt32(v.AuxInt)
|
|
||||||
n := auxToSym(v.Aux)
|
|
||||||
if !(v.Type.IsComplex() && v.Type.Size() == 8) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
v.reset(OpComplexMake)
|
|
||||||
v0 := b.NewValue0(v.Pos, OpArg, typ.Float32)
|
|
||||||
v0.AuxInt = int32ToAuxInt(off)
|
|
||||||
v0.Aux = symToAux(n)
|
|
||||||
v1 := b.NewValue0(v.Pos, OpArg, typ.Float32)
|
|
||||||
v1.AuxInt = int32ToAuxInt(off + 4)
|
|
||||||
v1.Aux = symToAux(n)
|
|
||||||
v.AddArg2(v0, v1)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
// match: (Arg <t>)
|
|
||||||
// cond: t.IsStruct() && t.NumFields() == 0 && fe.CanSSA(t)
|
|
||||||
// result: (StructMake0)
|
|
||||||
for {
|
|
||||||
t := v.Type
|
|
||||||
if !(t.IsStruct() && t.NumFields() == 0 && fe.CanSSA(t)) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
v.reset(OpStructMake0)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
// match: (Arg <t> {n} [off])
|
|
||||||
// cond: t.IsStruct() && t.NumFields() == 1 && fe.CanSSA(t)
|
|
||||||
// result: (StructMake1 (Arg <t.FieldType(0)> {n} [off+int32(t.FieldOff(0))]))
|
|
||||||
for {
|
|
||||||
t := v.Type
|
|
||||||
off := auxIntToInt32(v.AuxInt)
|
|
||||||
n := auxToSym(v.Aux)
|
|
||||||
if !(t.IsStruct() && t.NumFields() == 1 && fe.CanSSA(t)) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
v.reset(OpStructMake1)
|
|
||||||
v0 := b.NewValue0(v.Pos, OpArg, t.FieldType(0))
|
|
||||||
v0.AuxInt = int32ToAuxInt(off + int32(t.FieldOff(0)))
|
|
||||||
v0.Aux = symToAux(n)
|
|
||||||
v.AddArg(v0)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
// match: (Arg <t> {n} [off])
|
|
||||||
// cond: t.IsStruct() && t.NumFields() == 2 && fe.CanSSA(t)
|
|
||||||
// result: (StructMake2 (Arg <t.FieldType(0)> {n} [off+int32(t.FieldOff(0))]) (Arg <t.FieldType(1)> {n} [off+int32(t.FieldOff(1))]))
|
|
||||||
for {
|
|
||||||
t := v.Type
|
|
||||||
off := auxIntToInt32(v.AuxInt)
|
|
||||||
n := auxToSym(v.Aux)
|
|
||||||
if !(t.IsStruct() && t.NumFields() == 2 && fe.CanSSA(t)) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
v.reset(OpStructMake2)
|
|
||||||
v0 := b.NewValue0(v.Pos, OpArg, t.FieldType(0))
|
|
||||||
v0.AuxInt = int32ToAuxInt(off + int32(t.FieldOff(0)))
|
|
||||||
v0.Aux = symToAux(n)
|
|
||||||
v1 := b.NewValue0(v.Pos, OpArg, t.FieldType(1))
|
|
||||||
v1.AuxInt = int32ToAuxInt(off + int32(t.FieldOff(1)))
|
|
||||||
v1.Aux = symToAux(n)
|
|
||||||
v.AddArg2(v0, v1)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
// match: (Arg <t> {n} [off])
|
|
||||||
// cond: t.IsStruct() && t.NumFields() == 3 && fe.CanSSA(t)
|
|
||||||
// result: (StructMake3 (Arg <t.FieldType(0)> {n} [off+int32(t.FieldOff(0))]) (Arg <t.FieldType(1)> {n} [off+int32(t.FieldOff(1))]) (Arg <t.FieldType(2)> {n} [off+int32(t.FieldOff(2))]))
|
|
||||||
for {
|
|
||||||
t := v.Type
|
|
||||||
off := auxIntToInt32(v.AuxInt)
|
|
||||||
n := auxToSym(v.Aux)
|
|
||||||
if !(t.IsStruct() && t.NumFields() == 3 && fe.CanSSA(t)) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
v.reset(OpStructMake3)
|
|
||||||
v0 := b.NewValue0(v.Pos, OpArg, t.FieldType(0))
|
|
||||||
v0.AuxInt = int32ToAuxInt(off + int32(t.FieldOff(0)))
|
|
||||||
v0.Aux = symToAux(n)
|
|
||||||
v1 := b.NewValue0(v.Pos, OpArg, t.FieldType(1))
|
|
||||||
v1.AuxInt = int32ToAuxInt(off + int32(t.FieldOff(1)))
|
|
||||||
v1.Aux = symToAux(n)
|
|
||||||
v2 := b.NewValue0(v.Pos, OpArg, t.FieldType(2))
|
|
||||||
v2.AuxInt = int32ToAuxInt(off + int32(t.FieldOff(2)))
|
|
||||||
v2.Aux = symToAux(n)
|
|
||||||
v.AddArg3(v0, v1, v2)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
// match: (Arg <t> {n} [off])
|
|
||||||
// cond: t.IsStruct() && t.NumFields() == 4 && fe.CanSSA(t)
|
|
||||||
// result: (StructMake4 (Arg <t.FieldType(0)> {n} [off+int32(t.FieldOff(0))]) (Arg <t.FieldType(1)> {n} [off+int32(t.FieldOff(1))]) (Arg <t.FieldType(2)> {n} [off+int32(t.FieldOff(2))]) (Arg <t.FieldType(3)> {n} [off+int32(t.FieldOff(3))]))
|
|
||||||
for {
|
|
||||||
t := v.Type
|
|
||||||
off := auxIntToInt32(v.AuxInt)
|
|
||||||
n := auxToSym(v.Aux)
|
|
||||||
if !(t.IsStruct() && t.NumFields() == 4 && fe.CanSSA(t)) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
v.reset(OpStructMake4)
|
|
||||||
v0 := b.NewValue0(v.Pos, OpArg, t.FieldType(0))
|
|
||||||
v0.AuxInt = int32ToAuxInt(off + int32(t.FieldOff(0)))
|
|
||||||
v0.Aux = symToAux(n)
|
|
||||||
v1 := b.NewValue0(v.Pos, OpArg, t.FieldType(1))
|
|
||||||
v1.AuxInt = int32ToAuxInt(off + int32(t.FieldOff(1)))
|
|
||||||
v1.Aux = symToAux(n)
|
|
||||||
v2 := b.NewValue0(v.Pos, OpArg, t.FieldType(2))
|
|
||||||
v2.AuxInt = int32ToAuxInt(off + int32(t.FieldOff(2)))
|
|
||||||
v2.Aux = symToAux(n)
|
|
||||||
v3 := b.NewValue0(v.Pos, OpArg, t.FieldType(3))
|
|
||||||
v3.AuxInt = int32ToAuxInt(off + int32(t.FieldOff(3)))
|
|
||||||
v3.Aux = symToAux(n)
|
|
||||||
v.AddArg4(v0, v1, v2, v3)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
// match: (Arg <t>)
|
|
||||||
// cond: t.IsArray() && t.NumElem() == 0
|
|
||||||
// result: (ArrayMake0)
|
|
||||||
for {
|
|
||||||
t := v.Type
|
|
||||||
if !(t.IsArray() && t.NumElem() == 0) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
v.reset(OpArrayMake0)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
// match: (Arg <t> {n} [off])
|
|
||||||
// cond: t.IsArray() && t.NumElem() == 1 && fe.CanSSA(t)
|
|
||||||
// result: (ArrayMake1 (Arg <t.Elem()> {n} [off]))
|
|
||||||
for {
|
|
||||||
t := v.Type
|
|
||||||
off := auxIntToInt32(v.AuxInt)
|
|
||||||
n := auxToSym(v.Aux)
|
|
||||||
if !(t.IsArray() && t.NumElem() == 1 && fe.CanSSA(t)) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
v.reset(OpArrayMake1)
|
|
||||||
v0 := b.NewValue0(v.Pos, OpArg, t.Elem())
|
|
||||||
v0.AuxInt = int32ToAuxInt(off)
|
|
||||||
v0.Aux = symToAux(n)
|
|
||||||
v.AddArg(v0)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
func rewriteBlockdecArgs(b *Block) bool {
|
|
||||||
switch b.Kind {
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
@ -1803,7 +1803,7 @@ const shareDeferExits = false
|
||||||
// It returns a BlockRet block that ends the control flow. Its control value
|
// It returns a BlockRet block that ends the control flow. Its control value
|
||||||
// will be set to the final memory state.
|
// will be set to the final memory state.
|
||||||
func (s *state) exit() *ssa.Block {
|
func (s *state) exit() *ssa.Block {
|
||||||
lateResultLowering := s.f.DebugTest && ssa.LateCallExpansionEnabledWithin(s.f)
|
lateResultLowering := s.f.DebugTest
|
||||||
if s.hasdefer {
|
if s.hasdefer {
|
||||||
if s.hasOpenDefers {
|
if s.hasOpenDefers {
|
||||||
if shareDeferExits && s.lastDeferExit != nil && len(s.openDefers) == s.lastDeferCount {
|
if shareDeferExits && s.lastDeferExit != nil && len(s.openDefers) == s.lastDeferCount {
|
||||||
|
|
@ -4628,7 +4628,6 @@ func (s *state) openDeferExit() {
|
||||||
s.lastDeferExit = deferExit
|
s.lastDeferExit = deferExit
|
||||||
s.lastDeferCount = len(s.openDefers)
|
s.lastDeferCount = len(s.openDefers)
|
||||||
zeroval := s.constInt8(types.Types[types.TUINT8], 0)
|
zeroval := s.constInt8(types.Types[types.TUINT8], 0)
|
||||||
testLateExpansion := ssa.LateCallExpansionEnabledWithin(s.f)
|
|
||||||
// Test for and run defers in reverse order
|
// Test for and run defers in reverse order
|
||||||
for i := len(s.openDefers) - 1; i >= 0; i-- {
|
for i := len(s.openDefers) - 1; i >= 0; i-- {
|
||||||
r := s.openDefers[i]
|
r := s.openDefers[i]
|
||||||
|
|
@ -4670,19 +4669,12 @@ func (s *state) openDeferExit() {
|
||||||
if r.rcvr != nil {
|
if r.rcvr != nil {
|
||||||
// rcvr in case of OCALLINTER
|
// rcvr in case of OCALLINTER
|
||||||
v := s.load(r.rcvr.Type.Elem(), r.rcvr)
|
v := s.load(r.rcvr.Type.Elem(), r.rcvr)
|
||||||
addr := s.constOffPtrSP(s.f.Config.Types.UintptrPtr, argStart)
|
|
||||||
ACArgs = append(ACArgs, ssa.Param{Type: types.Types[types.TUINTPTR], Offset: int32(argStart)})
|
ACArgs = append(ACArgs, ssa.Param{Type: types.Types[types.TUINTPTR], Offset: int32(argStart)})
|
||||||
if testLateExpansion {
|
|
||||||
callArgs = append(callArgs, v)
|
callArgs = append(callArgs, v)
|
||||||
} else {
|
|
||||||
s.store(types.Types[types.TUINTPTR], addr, v)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
for j, argAddrVal := range r.argVals {
|
for j, argAddrVal := range r.argVals {
|
||||||
f := getParam(r.n, j)
|
f := getParam(r.n, j)
|
||||||
pt := types.NewPtr(f.Type)
|
|
||||||
ACArgs = append(ACArgs, ssa.Param{Type: f.Type, Offset: int32(argStart + f.Offset)})
|
ACArgs = append(ACArgs, ssa.Param{Type: f.Type, Offset: int32(argStart + f.Offset)})
|
||||||
if testLateExpansion {
|
|
||||||
var a *ssa.Value
|
var a *ssa.Value
|
||||||
if !TypeOK(f.Type) {
|
if !TypeOK(f.Type) {
|
||||||
a = s.newValue2(ssa.OpDereference, f.Type, argAddrVal, s.mem())
|
a = s.newValue2(ssa.OpDereference, f.Type, argAddrVal, s.mem())
|
||||||
|
|
@ -4690,15 +4682,6 @@ func (s *state) openDeferExit() {
|
||||||
a = s.load(f.Type, argAddrVal)
|
a = s.load(f.Type, argAddrVal)
|
||||||
}
|
}
|
||||||
callArgs = append(callArgs, a)
|
callArgs = append(callArgs, a)
|
||||||
} else {
|
|
||||||
addr := s.constOffPtrSP(pt, argStart+f.Offset)
|
|
||||||
if !TypeOK(f.Type) {
|
|
||||||
s.move(f.Type, addr, argAddrVal)
|
|
||||||
} else {
|
|
||||||
argVal := s.load(f.Type, argAddrVal)
|
|
||||||
s.storeType(f.Type, addr, argVal, 0, false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
var call *ssa.Value
|
var call *ssa.Value
|
||||||
if r.closure != nil {
|
if r.closure != nil {
|
||||||
|
|
@ -4706,30 +4689,15 @@ func (s *state) openDeferExit() {
|
||||||
s.maybeNilCheckClosure(v, callDefer)
|
s.maybeNilCheckClosure(v, callDefer)
|
||||||
codeptr := s.rawLoad(types.Types[types.TUINTPTR], v)
|
codeptr := s.rawLoad(types.Types[types.TUINTPTR], v)
|
||||||
aux := ssa.ClosureAuxCall(ACArgs, ACResults)
|
aux := ssa.ClosureAuxCall(ACArgs, ACResults)
|
||||||
if testLateExpansion {
|
|
||||||
callArgs = append(callArgs, s.mem())
|
|
||||||
call = s.newValue2A(ssa.OpClosureLECall, aux.LateExpansionResultType(), aux, codeptr, v)
|
call = s.newValue2A(ssa.OpClosureLECall, aux.LateExpansionResultType(), aux, codeptr, v)
|
||||||
call.AddArgs(callArgs...)
|
|
||||||
} else {
|
|
||||||
call = s.newValue3A(ssa.OpClosureCall, types.TypeMem, aux, codeptr, v, s.mem())
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
aux := ssa.StaticAuxCall(fn.(*ir.Name).Linksym(), ACArgs, ACResults)
|
aux := ssa.StaticAuxCall(fn.(*ir.Name).Linksym(), ACArgs, ACResults)
|
||||||
if testLateExpansion {
|
|
||||||
callArgs = append(callArgs, s.mem())
|
|
||||||
call = s.newValue0A(ssa.OpStaticLECall, aux.LateExpansionResultType(), aux)
|
call = s.newValue0A(ssa.OpStaticLECall, aux.LateExpansionResultType(), aux)
|
||||||
|
}
|
||||||
|
callArgs = append(callArgs, s.mem())
|
||||||
call.AddArgs(callArgs...)
|
call.AddArgs(callArgs...)
|
||||||
} else {
|
|
||||||
// Do a static call if the original call was a static function or method
|
|
||||||
call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, aux, s.mem())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
call.AuxInt = stksize
|
call.AuxInt = stksize
|
||||||
if testLateExpansion {
|
|
||||||
s.vars[memVar] = s.newValue1I(ssa.OpSelectN, types.TypeMem, int64(len(ACResults)), call)
|
s.vars[memVar] = s.newValue1I(ssa.OpSelectN, types.TypeMem, int64(len(ACResults)), call)
|
||||||
} else {
|
|
||||||
s.vars[memVar] = call
|
|
||||||
}
|
|
||||||
// Make sure that the stack slots with pointers are kept live
|
// Make sure that the stack slots with pointers are kept live
|
||||||
// through the call (which is a pre-emption point). Also, we will
|
// through the call (which is a pre-emption point). Also, we will
|
||||||
// use the first call of the last defer exit to compute liveness
|
// use the first call of the last defer exit to compute liveness
|
||||||
|
|
@ -4782,12 +4750,10 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool) *ssa.Val
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
testLateExpansion := false
|
|
||||||
inRegisters := false
|
inRegisters := false
|
||||||
|
|
||||||
switch n.Op() {
|
switch n.Op() {
|
||||||
case ir.OCALLFUNC:
|
case ir.OCALLFUNC:
|
||||||
testLateExpansion = k != callDeferStack && ssa.LateCallExpansionEnabledWithin(s.f)
|
|
||||||
if k == callNormal && fn.Op() == ir.ONAME && fn.(*ir.Name).Class == ir.PFUNC {
|
if k == callNormal && fn.Op() == ir.ONAME && fn.(*ir.Name).Class == ir.PFUNC {
|
||||||
fn := fn.(*ir.Name)
|
fn := fn.(*ir.Name)
|
||||||
callee = fn
|
callee = fn
|
||||||
|
|
@ -4813,7 +4779,6 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool) *ssa.Val
|
||||||
s.Fatalf("OCALLINTER: n.Left not an ODOTINTER: %v", fn.Op())
|
s.Fatalf("OCALLINTER: n.Left not an ODOTINTER: %v", fn.Op())
|
||||||
}
|
}
|
||||||
fn := fn.(*ir.SelectorExpr)
|
fn := fn.(*ir.SelectorExpr)
|
||||||
testLateExpansion = k != callDeferStack && ssa.LateCallExpansionEnabledWithin(s.f)
|
|
||||||
var iclosure *ssa.Value
|
var iclosure *ssa.Value
|
||||||
iclosure, rcvr = s.getClosureAndRcvr(fn)
|
iclosure, rcvr = s.getClosureAndRcvr(fn)
|
||||||
if k == callNormal {
|
if k == callNormal {
|
||||||
|
|
@ -4827,7 +4792,6 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool) *ssa.Val
|
||||||
|
|
||||||
var call *ssa.Value
|
var call *ssa.Value
|
||||||
if k == callDeferStack {
|
if k == callDeferStack {
|
||||||
testLateExpansion = ssa.LateCallExpansionEnabledWithin(s.f)
|
|
||||||
// Make a defer struct d on the stack.
|
// Make a defer struct d on the stack.
|
||||||
t := deferstruct(stksize)
|
t := deferstruct(stksize)
|
||||||
d := typecheck.TempAt(n.Pos(), s.curfn, t)
|
d := typecheck.TempAt(n.Pos(), s.curfn, t)
|
||||||
|
|
@ -4878,15 +4842,9 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool) *ssa.Val
|
||||||
// Call runtime.deferprocStack with pointer to _defer record.
|
// Call runtime.deferprocStack with pointer to _defer record.
|
||||||
ACArgs = append(ACArgs, ssa.Param{Type: types.Types[types.TUINTPTR], Offset: int32(base.Ctxt.FixedFrameSize())})
|
ACArgs = append(ACArgs, ssa.Param{Type: types.Types[types.TUINTPTR], Offset: int32(base.Ctxt.FixedFrameSize())})
|
||||||
aux := ssa.StaticAuxCall(ir.Syms.DeferprocStack, ACArgs, ACResults)
|
aux := ssa.StaticAuxCall(ir.Syms.DeferprocStack, ACArgs, ACResults)
|
||||||
if testLateExpansion {
|
|
||||||
callArgs = append(callArgs, addr, s.mem())
|
callArgs = append(callArgs, addr, s.mem())
|
||||||
call = s.newValue0A(ssa.OpStaticLECall, aux.LateExpansionResultType(), aux)
|
call = s.newValue0A(ssa.OpStaticLECall, aux.LateExpansionResultType(), aux)
|
||||||
call.AddArgs(callArgs...)
|
call.AddArgs(callArgs...)
|
||||||
} else {
|
|
||||||
arg0 := s.constOffPtrSP(types.Types[types.TUINTPTR], base.Ctxt.FixedFrameSize())
|
|
||||||
s.store(types.Types[types.TUINTPTR], arg0, addr)
|
|
||||||
call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, aux, s.mem())
|
|
||||||
}
|
|
||||||
if stksize < int64(types.PtrSize) {
|
if stksize < int64(types.PtrSize) {
|
||||||
// We need room for both the call to deferprocStack and the call to
|
// We need room for both the call to deferprocStack and the call to
|
||||||
// the deferred function.
|
// the deferred function.
|
||||||
|
|
@ -4903,32 +4861,17 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool) *ssa.Val
|
||||||
// Write argsize and closure (args to newproc/deferproc).
|
// Write argsize and closure (args to newproc/deferproc).
|
||||||
argsize := s.constInt32(types.Types[types.TUINT32], int32(stksize))
|
argsize := s.constInt32(types.Types[types.TUINT32], int32(stksize))
|
||||||
ACArgs = append(ACArgs, ssa.Param{Type: types.Types[types.TUINT32], Offset: int32(argStart)})
|
ACArgs = append(ACArgs, ssa.Param{Type: types.Types[types.TUINT32], Offset: int32(argStart)})
|
||||||
if testLateExpansion {
|
|
||||||
callArgs = append(callArgs, argsize)
|
callArgs = append(callArgs, argsize)
|
||||||
} else {
|
|
||||||
addr := s.constOffPtrSP(s.f.Config.Types.UInt32Ptr, argStart)
|
|
||||||
s.store(types.Types[types.TUINT32], addr, argsize)
|
|
||||||
}
|
|
||||||
ACArgs = append(ACArgs, ssa.Param{Type: types.Types[types.TUINTPTR], Offset: int32(argStart) + int32(types.PtrSize)})
|
ACArgs = append(ACArgs, ssa.Param{Type: types.Types[types.TUINTPTR], Offset: int32(argStart) + int32(types.PtrSize)})
|
||||||
if testLateExpansion {
|
|
||||||
callArgs = append(callArgs, closure)
|
callArgs = append(callArgs, closure)
|
||||||
} else {
|
|
||||||
addr := s.constOffPtrSP(s.f.Config.Types.UintptrPtr, argStart+int64(types.PtrSize))
|
|
||||||
s.store(types.Types[types.TUINTPTR], addr, closure)
|
|
||||||
}
|
|
||||||
stksize += 2 * int64(types.PtrSize)
|
stksize += 2 * int64(types.PtrSize)
|
||||||
argStart += 2 * int64(types.PtrSize)
|
argStart += 2 * int64(types.PtrSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set receiver (for interface calls).
|
// Set receiver (for interface calls).
|
||||||
if rcvr != nil {
|
if rcvr != nil {
|
||||||
addr := s.constOffPtrSP(s.f.Config.Types.UintptrPtr, argStart)
|
|
||||||
ACArgs = append(ACArgs, ssa.Param{Type: types.Types[types.TUINTPTR], Offset: int32(argStart)})
|
ACArgs = append(ACArgs, ssa.Param{Type: types.Types[types.TUINTPTR], Offset: int32(argStart)})
|
||||||
if testLateExpansion {
|
|
||||||
callArgs = append(callArgs, rcvr)
|
callArgs = append(callArgs, rcvr)
|
||||||
} else {
|
|
||||||
s.store(types.Types[types.TUINTPTR], addr, rcvr)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write args.
|
// Write args.
|
||||||
|
|
@ -4939,7 +4882,7 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool) *ssa.Val
|
||||||
}
|
}
|
||||||
for i, n := range args {
|
for i, n := range args {
|
||||||
f := t.Params().Field(i)
|
f := t.Params().Field(i)
|
||||||
ACArg, arg := s.putArg(n, f.Type, argStart+f.Offset, testLateExpansion)
|
ACArg, arg := s.putArg(n, f.Type, argStart+f.Offset)
|
||||||
ACArgs = append(ACArgs, ACArg)
|
ACArgs = append(ACArgs, ACArg)
|
||||||
callArgs = append(callArgs, arg)
|
callArgs = append(callArgs, arg)
|
||||||
}
|
}
|
||||||
|
|
@ -4950,20 +4893,10 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool) *ssa.Val
|
||||||
switch {
|
switch {
|
||||||
case k == callDefer:
|
case k == callDefer:
|
||||||
aux := ssa.StaticAuxCall(ir.Syms.Deferproc, ACArgs, ACResults)
|
aux := ssa.StaticAuxCall(ir.Syms.Deferproc, ACArgs, ACResults)
|
||||||
if testLateExpansion {
|
|
||||||
call = s.newValue0A(ssa.OpStaticLECall, aux.LateExpansionResultType(), aux)
|
call = s.newValue0A(ssa.OpStaticLECall, aux.LateExpansionResultType(), aux)
|
||||||
call.AddArgs(callArgs...)
|
|
||||||
} else {
|
|
||||||
call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, aux, s.mem())
|
|
||||||
}
|
|
||||||
case k == callGo:
|
case k == callGo:
|
||||||
aux := ssa.StaticAuxCall(ir.Syms.Newproc, ACArgs, ACResults)
|
aux := ssa.StaticAuxCall(ir.Syms.Newproc, ACArgs, ACResults)
|
||||||
if testLateExpansion {
|
|
||||||
call = s.newValue0A(ssa.OpStaticLECall, aux.LateExpansionResultType(), aux)
|
call = s.newValue0A(ssa.OpStaticLECall, aux.LateExpansionResultType(), aux)
|
||||||
call.AddArgs(callArgs...)
|
|
||||||
} else {
|
|
||||||
call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, aux, s.mem())
|
|
||||||
}
|
|
||||||
case closure != nil:
|
case closure != nil:
|
||||||
// rawLoad because loading the code pointer from a
|
// rawLoad because loading the code pointer from a
|
||||||
// closure is always safe, but IsSanitizerSafeAddr
|
// closure is always safe, but IsSanitizerSafeAddr
|
||||||
|
|
@ -4971,40 +4904,22 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool) *ssa.Val
|
||||||
// critical that we not clobber any arguments already
|
// critical that we not clobber any arguments already
|
||||||
// stored onto the stack.
|
// stored onto the stack.
|
||||||
codeptr = s.rawLoad(types.Types[types.TUINTPTR], closure)
|
codeptr = s.rawLoad(types.Types[types.TUINTPTR], closure)
|
||||||
if testLateExpansion {
|
|
||||||
aux := ssa.ClosureAuxCall(ACArgs, ACResults)
|
aux := ssa.ClosureAuxCall(ACArgs, ACResults)
|
||||||
call = s.newValue2A(ssa.OpClosureLECall, aux.LateExpansionResultType(), aux, codeptr, closure)
|
call = s.newValue2A(ssa.OpClosureLECall, aux.LateExpansionResultType(), aux, codeptr, closure)
|
||||||
call.AddArgs(callArgs...)
|
|
||||||
} else {
|
|
||||||
call = s.newValue3A(ssa.OpClosureCall, types.TypeMem, ssa.ClosureAuxCall(ACArgs, ACResults), codeptr, closure, s.mem())
|
|
||||||
}
|
|
||||||
case codeptr != nil:
|
case codeptr != nil:
|
||||||
if testLateExpansion {
|
|
||||||
aux := ssa.InterfaceAuxCall(ACArgs, ACResults)
|
aux := ssa.InterfaceAuxCall(ACArgs, ACResults)
|
||||||
call = s.newValue1A(ssa.OpInterLECall, aux.LateExpansionResultType(), aux, codeptr)
|
call = s.newValue1A(ssa.OpInterLECall, aux.LateExpansionResultType(), aux, codeptr)
|
||||||
call.AddArgs(callArgs...)
|
|
||||||
} else {
|
|
||||||
call = s.newValue2A(ssa.OpInterCall, types.TypeMem, ssa.InterfaceAuxCall(ACArgs, ACResults), codeptr, s.mem())
|
|
||||||
}
|
|
||||||
case callee != nil:
|
case callee != nil:
|
||||||
if testLateExpansion {
|
|
||||||
aux := ssa.StaticAuxCall(callTargetLSym(callee, s.curfn.LSym), ACArgs, ACResults)
|
aux := ssa.StaticAuxCall(callTargetLSym(callee, s.curfn.LSym), ACArgs, ACResults)
|
||||||
call = s.newValue0A(ssa.OpStaticLECall, aux.LateExpansionResultType(), aux)
|
call = s.newValue0A(ssa.OpStaticLECall, aux.LateExpansionResultType(), aux)
|
||||||
call.AddArgs(callArgs...)
|
|
||||||
} else {
|
|
||||||
call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, ssa.StaticAuxCall(callTargetLSym(callee, s.curfn.LSym), ACArgs, ACResults), s.mem())
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
s.Fatalf("bad call type %v %v", n.Op(), n)
|
s.Fatalf("bad call type %v %v", n.Op(), n)
|
||||||
}
|
}
|
||||||
|
call.AddArgs(callArgs...)
|
||||||
call.AuxInt = stksize // Call operations carry the argsize of the callee along with them
|
call.AuxInt = stksize // Call operations carry the argsize of the callee along with them
|
||||||
}
|
}
|
||||||
if testLateExpansion {
|
|
||||||
s.prevCall = call
|
s.prevCall = call
|
||||||
s.vars[memVar] = s.newValue1I(ssa.OpSelectN, types.TypeMem, int64(len(ACResults)), call)
|
s.vars[memVar] = s.newValue1I(ssa.OpSelectN, types.TypeMem, int64(len(ACResults)), call)
|
||||||
} else {
|
|
||||||
s.vars[memVar] = call
|
|
||||||
}
|
|
||||||
// Insert OVARLIVE nodes
|
// Insert OVARLIVE nodes
|
||||||
for _, name := range n.KeepAlive {
|
for _, name := range n.KeepAlive {
|
||||||
s.stmt(ir.NewUnaryExpr(n.Pos(), ir.OVARLIVE, name))
|
s.stmt(ir.NewUnaryExpr(n.Pos(), ir.OVARLIVE, name))
|
||||||
|
|
@ -5033,17 +4948,11 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool) *ssa.Val
|
||||||
fp := res.Field(0)
|
fp := res.Field(0)
|
||||||
if returnResultAddr {
|
if returnResultAddr {
|
||||||
pt := types.NewPtr(fp.Type)
|
pt := types.NewPtr(fp.Type)
|
||||||
if testLateExpansion {
|
|
||||||
return s.newValue1I(ssa.OpSelectNAddr, pt, 0, call)
|
return s.newValue1I(ssa.OpSelectNAddr, pt, 0, call)
|
||||||
}
|
}
|
||||||
return s.constOffPtrSP(pt, fp.Offset+base.Ctxt.FixedFrameSize())
|
|
||||||
}
|
|
||||||
|
|
||||||
if testLateExpansion {
|
|
||||||
return s.newValue1I(ssa.OpSelectN, fp.Type, 0, call)
|
return s.newValue1I(ssa.OpSelectN, fp.Type, 0, call)
|
||||||
}
|
}
|
||||||
return s.load(n.Type(), s.constOffPtrSP(types.NewPtr(fp.Type), fp.Offset+base.Ctxt.FixedFrameSize()))
|
|
||||||
}
|
|
||||||
|
|
||||||
// maybeNilCheckClosure checks if a nil check of a closure is needed in some
|
// maybeNilCheckClosure checks if a nil check of a closure is needed in some
|
||||||
// architecture-dependent situations and, if so, emits the nil check.
|
// architecture-dependent situations and, if so, emits the nil check.
|
||||||
|
|
@ -5458,7 +5367,6 @@ func (s *state) rtcall(fn *obj.LSym, returns bool, results []*types.Type, args .
|
||||||
s.prevCall = nil
|
s.prevCall = nil
|
||||||
// Write args to the stack
|
// Write args to the stack
|
||||||
off := base.Ctxt.FixedFrameSize()
|
off := base.Ctxt.FixedFrameSize()
|
||||||
testLateExpansion := ssa.LateCallExpansionEnabledWithin(s.f)
|
|
||||||
var ACArgs []ssa.Param
|
var ACArgs []ssa.Param
|
||||||
var ACResults []ssa.Param
|
var ACResults []ssa.Param
|
||||||
var callArgs []*ssa.Value
|
var callArgs []*ssa.Value
|
||||||
|
|
@ -5468,12 +5376,7 @@ func (s *state) rtcall(fn *obj.LSym, returns bool, results []*types.Type, args .
|
||||||
off = types.Rnd(off, t.Alignment())
|
off = types.Rnd(off, t.Alignment())
|
||||||
size := t.Size()
|
size := t.Size()
|
||||||
ACArgs = append(ACArgs, ssa.Param{Type: t, Offset: int32(off)})
|
ACArgs = append(ACArgs, ssa.Param{Type: t, Offset: int32(off)})
|
||||||
if testLateExpansion {
|
|
||||||
callArgs = append(callArgs, arg)
|
callArgs = append(callArgs, arg)
|
||||||
} else {
|
|
||||||
ptr := s.constOffPtrSP(t.PtrTo(), off)
|
|
||||||
s.store(t, ptr, arg)
|
|
||||||
}
|
|
||||||
off += size
|
off += size
|
||||||
}
|
}
|
||||||
off = types.Rnd(off, int64(types.RegSize))
|
off = types.Rnd(off, int64(types.RegSize))
|
||||||
|
|
@ -5489,15 +5392,10 @@ func (s *state) rtcall(fn *obj.LSym, returns bool, results []*types.Type, args .
|
||||||
// Issue call
|
// Issue call
|
||||||
var call *ssa.Value
|
var call *ssa.Value
|
||||||
aux := ssa.StaticAuxCall(fn, ACArgs, ACResults)
|
aux := ssa.StaticAuxCall(fn, ACArgs, ACResults)
|
||||||
if testLateExpansion {
|
|
||||||
callArgs = append(callArgs, s.mem())
|
callArgs = append(callArgs, s.mem())
|
||||||
call = s.newValue0A(ssa.OpStaticLECall, aux.LateExpansionResultType(), aux)
|
call = s.newValue0A(ssa.OpStaticLECall, aux.LateExpansionResultType(), aux)
|
||||||
call.AddArgs(callArgs...)
|
call.AddArgs(callArgs...)
|
||||||
s.vars[memVar] = s.newValue1I(ssa.OpSelectN, types.TypeMem, int64(len(ACResults)), call)
|
s.vars[memVar] = s.newValue1I(ssa.OpSelectN, types.TypeMem, int64(len(ACResults)), call)
|
||||||
} else {
|
|
||||||
call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, aux, s.mem())
|
|
||||||
s.vars[memVar] = call
|
|
||||||
}
|
|
||||||
|
|
||||||
if !returns {
|
if !returns {
|
||||||
// Finish block
|
// Finish block
|
||||||
|
|
@ -5513,7 +5411,6 @@ func (s *state) rtcall(fn *obj.LSym, returns bool, results []*types.Type, args .
|
||||||
|
|
||||||
// Load results
|
// Load results
|
||||||
res := make([]*ssa.Value, len(results))
|
res := make([]*ssa.Value, len(results))
|
||||||
if testLateExpansion {
|
|
||||||
for i, t := range results {
|
for i, t := range results {
|
||||||
off = types.Rnd(off, t.Alignment())
|
off = types.Rnd(off, t.Alignment())
|
||||||
if TypeOK(t) {
|
if TypeOK(t) {
|
||||||
|
|
@ -5524,14 +5421,6 @@ func (s *state) rtcall(fn *obj.LSym, returns bool, results []*types.Type, args .
|
||||||
}
|
}
|
||||||
off += t.Size()
|
off += t.Size()
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
for i, t := range results {
|
|
||||||
off = types.Rnd(off, t.Alignment())
|
|
||||||
ptr := s.constOffPtrSP(types.NewPtr(t), off)
|
|
||||||
res[i] = s.load(t, ptr)
|
|
||||||
off += t.Size()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
off = types.Rnd(off, int64(types.PtrSize))
|
off = types.Rnd(off, int64(types.PtrSize))
|
||||||
|
|
||||||
// Remember how much callee stack space we needed.
|
// Remember how much callee stack space we needed.
|
||||||
|
|
@ -5650,20 +5539,14 @@ func (s *state) storeTypePtrs(t *types.Type, left, right *ssa.Value) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// putArg evaluates n for the purpose of passing it as an argument to a function and returns the corresponding Param for the call.
|
// putArg evaluates n for the purpose of passing it as an argument to a function and returns the corresponding Param and value for the call.
|
||||||
// If forLateExpandedCall is true, it returns the argument value to pass to the call operation.
|
func (s *state) putArg(n ir.Node, t *types.Type, off int64) (ssa.Param, *ssa.Value) {
|
||||||
// If forLateExpandedCall is false, then the value is stored at the specified stack offset, and the returned value is nil.
|
|
||||||
func (s *state) putArg(n ir.Node, t *types.Type, off int64, forLateExpandedCall bool) (ssa.Param, *ssa.Value) {
|
|
||||||
var a *ssa.Value
|
var a *ssa.Value
|
||||||
if forLateExpandedCall {
|
|
||||||
if !TypeOK(t) {
|
if !TypeOK(t) {
|
||||||
a = s.newValue2(ssa.OpDereference, t, s.addr(n), s.mem())
|
a = s.newValue2(ssa.OpDereference, t, s.addr(n), s.mem())
|
||||||
} else {
|
} else {
|
||||||
a = s.expr(n)
|
a = s.expr(n)
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
s.storeArgWithBase(n, t, s.sp, off)
|
|
||||||
}
|
|
||||||
return ssa.Param{Type: t, Offset: int32(off)}, a
|
return ssa.Param{Type: t, Offset: int32(off)}, a
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,7 @@
|
||||||
// -p n
|
// -p n
|
||||||
// the number of programs, such as build commands or
|
// the number of programs, such as build commands or
|
||||||
// test binaries, that can be run in parallel.
|
// test binaries, that can be run in parallel.
|
||||||
// The default is the number of CPUs available.
|
// The default is GOMAXPROCS, normally the number of CPUs available.
|
||||||
// -race
|
// -race
|
||||||
// enable data race detection.
|
// enable data race detection.
|
||||||
// Supported only on linux/amd64, freebsd/amd64, darwin/amd64, windows/amd64,
|
// Supported only on linux/amd64, freebsd/amd64, darwin/amd64, windows/amd64,
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ var (
|
||||||
BuildMSan bool // -msan flag
|
BuildMSan bool // -msan flag
|
||||||
BuildN bool // -n flag
|
BuildN bool // -n flag
|
||||||
BuildO string // -o flag
|
BuildO string // -o flag
|
||||||
BuildP = runtime.NumCPU() // -p flag
|
BuildP = runtime.GOMAXPROCS(0) // -p flag
|
||||||
BuildPkgdir string // -pkgdir flag
|
BuildPkgdir string // -pkgdir flag
|
||||||
BuildRace bool // -race flag
|
BuildRace bool // -race flag
|
||||||
BuildToolexec []string // -toolexec flag
|
BuildToolexec []string // -toolexec flag
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ and test commands:
|
||||||
-p n
|
-p n
|
||||||
the number of programs, such as build commands or
|
the number of programs, such as build commands or
|
||||||
test binaries, that can be run in parallel.
|
test binaries, that can be run in parallel.
|
||||||
The default is the number of CPUs available.
|
The default is GOMAXPROCS, normally the number of CPUs available.
|
||||||
-race
|
-race
|
||||||
enable data race detection.
|
enable data race detection.
|
||||||
Supported only on linux/amd64, freebsd/amd64, darwin/amd64, windows/amd64,
|
Supported only on linux/amd64, freebsd/amd64, darwin/amd64, windows/amd64,
|
||||||
|
|
|
||||||
|
|
@ -239,16 +239,19 @@ CheckFlags:
|
||||||
// - it has no successor packages to compile (usually package main)
|
// - it has no successor packages to compile (usually package main)
|
||||||
// - all paths through the build graph pass through it
|
// - all paths through the build graph pass through it
|
||||||
// - critical path scheduling says it is high priority
|
// - critical path scheduling says it is high priority
|
||||||
// and in such a case, set c to runtime.NumCPU.
|
// and in such a case, set c to runtime.GOMAXPROCS(0).
|
||||||
|
// By default this is the same as runtime.NumCPU.
|
||||||
// We do this now when p==1.
|
// We do this now when p==1.
|
||||||
|
// To limit parallelism, set GOMAXPROCS below numCPU; this may be useful
|
||||||
|
// on a low-memory builder, or if a deterministic build order is required.
|
||||||
|
c := runtime.GOMAXPROCS(0)
|
||||||
if cfg.BuildP == 1 {
|
if cfg.BuildP == 1 {
|
||||||
// No process parallelism. Max out c.
|
// No process parallelism, do not cap compiler parallelism.
|
||||||
return runtime.NumCPU()
|
return c
|
||||||
}
|
}
|
||||||
// Some process parallelism. Set c to min(4, numcpu).
|
// Some process parallelism. Set c to min(4, maxprocs).
|
||||||
c := 4
|
if c > 4 {
|
||||||
if ncpu := runtime.NumCPU(); ncpu < c {
|
c = 4
|
||||||
c = ncpu
|
|
||||||
}
|
}
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -121,6 +121,7 @@ package main
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
|
@ -130,7 +131,7 @@ import (
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
exe := os.Args[1]
|
exe := os.Args[1]
|
||||||
data, err := os.ReadFile(exe)
|
data, err := ioutil.ReadFile(exe)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
# embedded in a package, that is referenced by a Go assembly function.
|
# embedded in a package, that is referenced by a Go assembly function.
|
||||||
# See issue 33139.
|
# See issue 33139.
|
||||||
[!gc] skip
|
[!gc] skip
|
||||||
[!exec:cc] skip
|
[!cgo] skip
|
||||||
|
|
||||||
# External linking is not supported on linux/ppc64.
|
# External linking is not supported on linux/ppc64.
|
||||||
# See: https://github.com/golang/go/issues/8912
|
# See: https://github.com/golang/go/issues/8912
|
||||||
|
|
|
||||||
|
|
@ -226,6 +226,12 @@ func main() {
|
||||||
|
|
||||||
func TestPIESize(t *testing.T) {
|
func TestPIESize(t *testing.T) {
|
||||||
testenv.MustHaveGoBuild(t)
|
testenv.MustHaveGoBuild(t)
|
||||||
|
|
||||||
|
// We don't want to test -linkmode=external if cgo is not supported.
|
||||||
|
// On some systems -buildmode=pie implies -linkmode=external, so just
|
||||||
|
// always skip the test if cgo is not supported.
|
||||||
|
testenv.MustHaveCGO(t)
|
||||||
|
|
||||||
if !sys.BuildModeSupported(runtime.Compiler, "pie", runtime.GOOS, runtime.GOARCH) {
|
if !sys.BuildModeSupported(runtime.Compiler, "pie", runtime.GOOS, runtime.GOARCH) {
|
||||||
t.Skip("-buildmode=pie not supported")
|
t.Skip("-buildmode=pie not supported")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -165,13 +165,17 @@ func (d *deadcodePass) flood() {
|
||||||
// R_USEIFACEMETHOD is a marker relocation that marks an interface
|
// R_USEIFACEMETHOD is a marker relocation that marks an interface
|
||||||
// method as used.
|
// method as used.
|
||||||
rs := r.Sym()
|
rs := r.Sym()
|
||||||
if d.ldr.SymType(rs) != sym.SDYNIMPORT { // don't decode DYNIMPORT symbol (we'll mark all exported methods anyway)
|
if d.ctxt.linkShared && (d.ldr.SymType(rs) == sym.SDYNIMPORT || d.ldr.SymType(rs) == sym.Sxxx) {
|
||||||
|
// Don't decode symbol from shared library (we'll mark all exported methods anyway).
|
||||||
|
// We check for both SDYNIMPORT and Sxxx because name-mangled symbols haven't
|
||||||
|
// been resolved at this point.
|
||||||
|
continue
|
||||||
|
}
|
||||||
m := d.decodeIfaceMethod(d.ldr, d.ctxt.Arch, rs, r.Add())
|
m := d.decodeIfaceMethod(d.ldr, d.ctxt.Arch, rs, r.Add())
|
||||||
if d.ctxt.Debugvlog > 1 {
|
if d.ctxt.Debugvlog > 1 {
|
||||||
d.ctxt.Logf("reached iface method: %v\n", m)
|
d.ctxt.Logf("reached iface method: %v\n", m)
|
||||||
}
|
}
|
||||||
d.ifaceMethod[m] = true
|
d.ifaceMethod[m] = true
|
||||||
}
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
rs := r.Sym()
|
rs := r.Sym()
|
||||||
|
|
|
||||||
|
|
@ -279,7 +279,7 @@ func findShlibSection(ctxt *Link, path string, addr uint64) *elf.Section {
|
||||||
for _, shlib := range ctxt.Shlibs {
|
for _, shlib := range ctxt.Shlibs {
|
||||||
if shlib.Path == path {
|
if shlib.Path == path {
|
||||||
for _, sect := range shlib.File.Sections[1:] { // skip the NULL section
|
for _, sect := range shlib.File.Sections[1:] { // skip the NULL section
|
||||||
if sect.Addr <= addr && addr <= sect.Addr+sect.Size {
|
if sect.Addr <= addr && addr < sect.Addr+sect.Size {
|
||||||
return sect
|
return sect
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1997,15 +1997,6 @@ func buildCSRExtensions(template *CertificateRequest) ([]pkix.Extension, error)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if template.KeyUsage != 0 &&
|
|
||||||
!oidInExtensions(oidExtensionKeyUsage, template.ExtraExtensions) {
|
|
||||||
ext, err := marshalKeyUsage(template.KeyUsage)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
ret = append(ret, ext)
|
|
||||||
}
|
|
||||||
|
|
||||||
return append(ret, template.ExtraExtensions...), nil
|
return append(ret, template.ExtraExtensions...), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2371,7 +2362,6 @@ type CertificateRequest struct {
|
||||||
Version int
|
Version int
|
||||||
Signature []byte
|
Signature []byte
|
||||||
SignatureAlgorithm SignatureAlgorithm
|
SignatureAlgorithm SignatureAlgorithm
|
||||||
KeyUsage KeyUsage
|
|
||||||
|
|
||||||
PublicKeyAlgorithm PublicKeyAlgorithm
|
PublicKeyAlgorithm PublicKeyAlgorithm
|
||||||
PublicKey interface{}
|
PublicKey interface{}
|
||||||
|
|
@ -2501,15 +2491,6 @@ func parseCSRExtensions(rawAttributes []asn1.RawValue) ([]pkix.Extension, error)
|
||||||
// - EmailAddresses
|
// - EmailAddresses
|
||||||
// - IPAddresses
|
// - IPAddresses
|
||||||
// - URIs
|
// - URIs
|
||||||
// - KeyUsage
|
|
||||||
// - ExtKeyUsage
|
|
||||||
// - UnknownExtKeyUsage
|
|
||||||
// - BasicConstraintsValid
|
|
||||||
// - IsCA
|
|
||||||
// - MaxPathLen
|
|
||||||
// - MaxPathLenZero
|
|
||||||
// - SubjectKeyId
|
|
||||||
// - PolicyIdentifiers
|
|
||||||
// - ExtraExtensions
|
// - ExtraExtensions
|
||||||
// - Attributes (deprecated)
|
// - Attributes (deprecated)
|
||||||
//
|
//
|
||||||
|
|
@ -2734,11 +2715,6 @@ func parseCertificateRequest(in *certificateRequest) (*CertificateRequest, error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
case extension.Id.Equal(oidExtensionKeyUsage):
|
|
||||||
out.KeyUsage, err = parseKeyUsageExtension(extension.Value)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2977,7 +2977,6 @@ func TestCertificateRequestRoundtripFields(t *testing.T) {
|
||||||
EmailAddresses: []string{"a@example.com", "b@example.com"},
|
EmailAddresses: []string{"a@example.com", "b@example.com"},
|
||||||
IPAddresses: []net.IP{net.IPv4(192, 0, 2, 0), net.IPv6loopback},
|
IPAddresses: []net.IP{net.IPv4(192, 0, 2, 0), net.IPv6loopback},
|
||||||
URIs: []*url.URL{urlA, urlB},
|
URIs: []*url.URL{urlA, urlB},
|
||||||
KeyUsage: KeyUsageCertSign,
|
|
||||||
}
|
}
|
||||||
out := marshalAndParseCSR(t, in)
|
out := marshalAndParseCSR(t, in)
|
||||||
|
|
||||||
|
|
@ -2995,7 +2994,4 @@ func TestCertificateRequestRoundtripFields(t *testing.T) {
|
||||||
if !reflect.DeepEqual(in.URIs, out.URIs) {
|
if !reflect.DeepEqual(in.URIs, out.URIs) {
|
||||||
t.Fatalf("Unexpected URIs: got %v, want %v", out.URIs, in.URIs)
|
t.Fatalf("Unexpected URIs: got %v, want %v", out.URIs, in.URIs)
|
||||||
}
|
}
|
||||||
if in.KeyUsage != out.KeyUsage {
|
|
||||||
t.Fatalf("Unexpected KeyUsage: got %v, want %v", out.KeyUsage, in.KeyUsage)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,18 +9,28 @@
|
||||||
// files read from the package directory or subdirectories at compile time.
|
// files read from the package directory or subdirectories at compile time.
|
||||||
//
|
//
|
||||||
// For example, here are three ways to embed a file named hello.txt
|
// For example, here are three ways to embed a file named hello.txt
|
||||||
// and then print its contents at run time:
|
// and then print its contents at run time.
|
||||||
//
|
//
|
||||||
// import "embed"
|
// Embedding one file into a string:
|
||||||
|
//
|
||||||
|
// import _ "embed"
|
||||||
//
|
//
|
||||||
// //go:embed hello.txt
|
// //go:embed hello.txt
|
||||||
// var s string
|
// var s string
|
||||||
// print(s)
|
// print(s)
|
||||||
//
|
//
|
||||||
|
// Embedding one file into a slice of bytes:
|
||||||
|
//
|
||||||
|
// import _ "embed"
|
||||||
|
//
|
||||||
// //go:embed hello.txt
|
// //go:embed hello.txt
|
||||||
// var b []byte
|
// var b []byte
|
||||||
// print(string(b))
|
// print(string(b))
|
||||||
//
|
//
|
||||||
|
// Embedded one or more files into a file system:
|
||||||
|
//
|
||||||
|
// import "embed"
|
||||||
|
//
|
||||||
// //go:embed hello.txt
|
// //go:embed hello.txt
|
||||||
// var f embed.FS
|
// var f embed.FS
|
||||||
// data, _ := f.ReadFile("hello.txt")
|
// data, _ := f.ReadFile("hello.txt")
|
||||||
|
|
@ -34,8 +44,8 @@
|
||||||
// The directive must immediately precede a line containing the declaration of a single variable.
|
// The directive must immediately precede a line containing the declaration of a single variable.
|
||||||
// Only blank lines and ‘//’ line comments are permitted between the directive and the declaration.
|
// Only blank lines and ‘//’ line comments are permitted between the directive and the declaration.
|
||||||
//
|
//
|
||||||
// The variable must be of type string, []byte, or FS exactly. Named types or type aliases
|
// The type of the variable must be a string type, or a slice of a byte type,
|
||||||
// derived from those types are not allowed.
|
// or FS (or an alias of FS).
|
||||||
//
|
//
|
||||||
// For example:
|
// For example:
|
||||||
//
|
//
|
||||||
|
|
@ -70,8 +80,8 @@
|
||||||
//
|
//
|
||||||
// The //go:embed directive can be used with both exported and unexported variables,
|
// The //go:embed directive can be used with both exported and unexported variables,
|
||||||
// depending on whether the package wants to make the data available to other packages.
|
// depending on whether the package wants to make the data available to other packages.
|
||||||
// Similarly, it can be used with both global and function-local variables,
|
// It can only be used with global variables at package scope,
|
||||||
// depending on what is more convenient in context.
|
// not with local variables.
|
||||||
//
|
//
|
||||||
// Patterns must not match files outside the package's module, such as ‘.git/*’ or symbolic links.
|
// Patterns must not match files outside the package's module, such as ‘.git/*’ or symbolic links.
|
||||||
// Matches for empty directories are ignored. After that, each pattern in a //go:embed line
|
// Matches for empty directories are ignored. After that, each pattern in a //go:embed line
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ package math
|
||||||
//
|
//
|
||||||
// One may easily use induction to prove (4) and (5).
|
// One may easily use induction to prove (4) and (5).
|
||||||
// Note. Since the left hand side of (3) contain only i+2 bits,
|
// Note. Since the left hand side of (3) contain only i+2 bits,
|
||||||
// it does not necessary to do a full (53-bit) comparison
|
// it is not necessary to do a full (53-bit) comparison
|
||||||
// in (3).
|
// in (3).
|
||||||
// 3. Final rounding
|
// 3. Final rounding
|
||||||
// After generating the 53 bits result, we compute one more bit.
|
// After generating the 53 bits result, we compute one more bit.
|
||||||
|
|
|
||||||
|
|
@ -171,12 +171,9 @@ func (c *child) serve() {
|
||||||
defer c.cleanUp()
|
defer c.cleanUp()
|
||||||
var rec record
|
var rec record
|
||||||
for {
|
for {
|
||||||
c.conn.mutex.Lock()
|
|
||||||
if err := rec.read(c.conn.rwc); err != nil {
|
if err := rec.read(c.conn.rwc); err != nil {
|
||||||
c.conn.mutex.Unlock()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.conn.mutex.Unlock()
|
|
||||||
if err := c.handleRecord(&rec); err != nil {
|
if err := c.handleRecord(&rec); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -221,7 +221,11 @@ var cleanUpTests = []struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type nopWriteCloser struct {
|
type nopWriteCloser struct {
|
||||||
io.ReadWriter
|
io.Reader
|
||||||
|
}
|
||||||
|
|
||||||
|
func (nopWriteCloser) Write(buf []byte) (int, error) {
|
||||||
|
return len(buf), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (nopWriteCloser) Close() error {
|
func (nopWriteCloser) Close() error {
|
||||||
|
|
@ -235,7 +239,7 @@ func TestChildServeCleansUp(t *testing.T) {
|
||||||
for _, tt := range cleanUpTests {
|
for _, tt := range cleanUpTests {
|
||||||
input := make([]byte, len(tt.input))
|
input := make([]byte, len(tt.input))
|
||||||
copy(input, tt.input)
|
copy(input, tt.input)
|
||||||
rc := nopWriteCloser{bytes.NewBuffer(input)}
|
rc := nopWriteCloser{bytes.NewReader(input)}
|
||||||
done := make(chan bool)
|
done := make(chan bool)
|
||||||
c := newChild(rc, http.HandlerFunc(func(
|
c := newChild(rc, http.HandlerFunc(func(
|
||||||
w http.ResponseWriter,
|
w http.ResponseWriter,
|
||||||
|
|
@ -325,7 +329,7 @@ func TestChildServeReadsEnvVars(t *testing.T) {
|
||||||
for _, tt := range envVarTests {
|
for _, tt := range envVarTests {
|
||||||
input := make([]byte, len(tt.input))
|
input := make([]byte, len(tt.input))
|
||||||
copy(input, tt.input)
|
copy(input, tt.input)
|
||||||
rc := nopWriteCloser{bytes.NewBuffer(input)}
|
rc := nopWriteCloser{bytes.NewReader(input)}
|
||||||
done := make(chan bool)
|
done := make(chan bool)
|
||||||
c := newChild(rc, http.HandlerFunc(func(
|
c := newChild(rc, http.HandlerFunc(func(
|
||||||
w http.ResponseWriter,
|
w http.ResponseWriter,
|
||||||
|
|
@ -375,7 +379,7 @@ func TestResponseWriterSniffsContentType(t *testing.T) {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
input := make([]byte, len(streamFullRequestStdin))
|
input := make([]byte, len(streamFullRequestStdin))
|
||||||
copy(input, streamFullRequestStdin)
|
copy(input, streamFullRequestStdin)
|
||||||
rc := nopWriteCloser{bytes.NewBuffer(input)}
|
rc := nopWriteCloser{bytes.NewReader(input)}
|
||||||
done := make(chan bool)
|
done := make(chan bool)
|
||||||
var resp *response
|
var resp *response
|
||||||
c := newChild(rc, http.HandlerFunc(func(
|
c := newChild(rc, http.HandlerFunc(func(
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,10 @@ type file struct {
|
||||||
// making it invalid; see runtime.SetFinalizer for more information on when
|
// making it invalid; see runtime.SetFinalizer for more information on when
|
||||||
// a finalizer might be run. On Unix systems this will cause the SetDeadline
|
// a finalizer might be run. On Unix systems this will cause the SetDeadline
|
||||||
// methods to stop working.
|
// methods to stop working.
|
||||||
|
// Because file descriptors can be reused, the returned file descriptor may
|
||||||
|
// only be closed through the Close method of f, or by its finalizer during
|
||||||
|
// garbage collection. Otherwise, during garbage collection the finalizer
|
||||||
|
// may close an unrelated file descriptor with the same (reused) number.
|
||||||
//
|
//
|
||||||
// As an alternative, see the f.SyscallConn method.
|
// As an alternative, see the f.SyscallConn method.
|
||||||
func (f *File) Fd() uintptr {
|
func (f *File) Fd() uintptr {
|
||||||
|
|
@ -90,6 +94,10 @@ func (f *File) Fd() uintptr {
|
||||||
// descriptor. On Unix systems, if the file descriptor is in
|
// descriptor. On Unix systems, if the file descriptor is in
|
||||||
// non-blocking mode, NewFile will attempt to return a pollable File
|
// non-blocking mode, NewFile will attempt to return a pollable File
|
||||||
// (one for which the SetDeadline methods work).
|
// (one for which the SetDeadline methods work).
|
||||||
|
//
|
||||||
|
// After passing it to NewFile, fd may become invalid under the same
|
||||||
|
// conditions described in the comments of the Fd method, and the same
|
||||||
|
// constraints apply.
|
||||||
func NewFile(fd uintptr, name string) *File {
|
func NewFile(fd uintptr, name string) *File {
|
||||||
kind := kindNewFile
|
kind := kindNewFile
|
||||||
if nb, err := unix.IsNonblock(int(fd)); err == nil && nb {
|
if nb, err := unix.IsNonblock(int(fd)); err == nil && nb {
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ func nextRandom() string {
|
||||||
// opens the file for reading and writing, and returns the resulting file.
|
// opens the file for reading and writing, and returns the resulting file.
|
||||||
// The filename is generated by taking pattern and adding a random string to the end.
|
// The filename is generated by taking pattern and adding a random string to the end.
|
||||||
// If pattern includes a "*", the random string replaces the last "*".
|
// If pattern includes a "*", the random string replaces the last "*".
|
||||||
// If dir is the empty string, TempFile uses the default directory for temporary files, as returned by TempDir.
|
// If dir is the empty string, CreateTemp uses the default directory for temporary files, as returned by TempDir.
|
||||||
// Multiple programs or goroutines calling CreateTemp simultaneously will not choose the same file.
|
// Multiple programs or goroutines calling CreateTemp simultaneously will not choose the same file.
|
||||||
// The caller can use the file's Name method to find the pathname of the file.
|
// The caller can use the file's Name method to find the pathname of the file.
|
||||||
// It is the caller's responsibility to remove the file when it is no longer needed.
|
// It is the caller's responsibility to remove the file when it is no longer needed.
|
||||||
|
|
@ -71,7 +71,7 @@ func prefixAndSuffix(pattern string) (prefix, suffix string, err error) {
|
||||||
// and returns the pathname of the new directory.
|
// and returns the pathname of the new directory.
|
||||||
// The new directory's name is generated by adding a random string to the end of pattern.
|
// The new directory's name is generated by adding a random string to the end of pattern.
|
||||||
// If pattern includes a "*", the random string replaces the last "*" instead.
|
// If pattern includes a "*", the random string replaces the last "*" instead.
|
||||||
// If dir is the empty string, TempFile uses the default directory for temporary files, as returned by TempDir.
|
// If dir is the empty string, MkdirTemp uses the default directory for temporary files, as returned by TempDir.
|
||||||
// Multiple programs or goroutines calling MkdirTemp simultaneously will not choose the same directory.
|
// Multiple programs or goroutines calling MkdirTemp simultaneously will not choose the same directory.
|
||||||
// It is the caller's responsibility to remove the directory when it is no longer needed.
|
// It is the caller's responsibility to remove the directory when it is no longer needed.
|
||||||
func MkdirTemp(dir, pattern string) (string, error) {
|
func MkdirTemp(dir, pattern string) (string, error) {
|
||||||
|
|
|
||||||
|
|
@ -294,6 +294,18 @@ func TestRecursivePanic4(t *testing.T) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRecursivePanic5(t *testing.T) {
|
||||||
|
output := runTestProg(t, "testprog", "RecursivePanic5")
|
||||||
|
want := `first panic
|
||||||
|
second panic
|
||||||
|
panic: third panic
|
||||||
|
`
|
||||||
|
if !strings.HasPrefix(output, want) {
|
||||||
|
t.Fatalf("output does not start with %q:\n%s", want, output)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func TestGoexitCrash(t *testing.T) {
|
func TestGoexitCrash(t *testing.T) {
|
||||||
// External linking brings in cgo, causing deadlock detection not working.
|
// External linking brings in cgo, causing deadlock detection not working.
|
||||||
testenv.MustInternalLink(t)
|
testenv.MustInternalLink(t)
|
||||||
|
|
|
||||||
|
|
@ -410,3 +410,31 @@ func rec1(max int) {
|
||||||
rec1(max - 1)
|
rec1(max - 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIssue43921(t *testing.T) {
|
||||||
|
defer func() {
|
||||||
|
expect(t, 1, recover())
|
||||||
|
}()
|
||||||
|
func() {
|
||||||
|
// Prevent open-coded defers
|
||||||
|
for {
|
||||||
|
defer func() {}()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
defer func() {
|
||||||
|
expect(t, 4, recover())
|
||||||
|
}()
|
||||||
|
panic(4)
|
||||||
|
}()
|
||||||
|
panic(1)
|
||||||
|
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func expect(t *testing.T, n int, err interface{}) {
|
||||||
|
if n != err {
|
||||||
|
t.Fatalf("have %v, want %v", err, n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,11 @@ const (
|
||||||
|
|
||||||
_PTHREAD_CREATE_DETACHED = 0x1
|
_PTHREAD_CREATE_DETACHED = 0x1
|
||||||
|
|
||||||
|
_F_SETFD = 0x2
|
||||||
|
_F_GETFL = 0x3
|
||||||
|
_F_SETFL = 0x4
|
||||||
|
_FD_CLOEXEC = 0x1
|
||||||
|
|
||||||
_SIGHUP = 0x1
|
_SIGHUP = 0x1
|
||||||
_SIGINT = 0x2
|
_SIGINT = 0x2
|
||||||
_SIGQUIT = 0x3
|
_SIGQUIT = 0x3
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,8 @@
|
||||||
|
|
||||||
// NOTE: Windows externalthreadhandler expects memclr to preserve DX.
|
// NOTE: Windows externalthreadhandler expects memclr to preserve DX.
|
||||||
|
|
||||||
|
// See memclrNoHeapPointers Go doc for important implementation constraints.
|
||||||
|
|
||||||
// func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
|
// func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
|
||||||
TEXT runtime·memclrNoHeapPointers(SB), NOSPLIT, $0-8
|
TEXT runtime·memclrNoHeapPointers(SB), NOSPLIT, $0-8
|
||||||
MOVL ptr+0(FP), DI
|
MOVL ptr+0(FP), DI
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,8 @@
|
||||||
|
|
||||||
// NOTE: Windows externalthreadhandler expects memclr to preserve DX.
|
// NOTE: Windows externalthreadhandler expects memclr to preserve DX.
|
||||||
|
|
||||||
|
// See memclrNoHeapPointers Go doc for important implementation constraints.
|
||||||
|
|
||||||
// func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
|
// func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
|
||||||
TEXT runtime·memclrNoHeapPointers(SB), NOSPLIT, $0-16
|
TEXT runtime·memclrNoHeapPointers(SB), NOSPLIT, $0-16
|
||||||
MOVQ ptr+0(FP), DI
|
MOVQ ptr+0(FP), DI
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,8 @@
|
||||||
#define N R12
|
#define N R12
|
||||||
#define TMP R12 /* N and TMP don't overlap */
|
#define TMP R12 /* N and TMP don't overlap */
|
||||||
|
|
||||||
|
// See memclrNoHeapPointers Go doc for important implementation constraints.
|
||||||
|
|
||||||
// func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
|
// func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
|
||||||
TEXT runtime·memclrNoHeapPointers(SB),NOSPLIT,$0-8
|
TEXT runtime·memclrNoHeapPointers(SB),NOSPLIT,$0-8
|
||||||
MOVW ptr+0(FP), TO
|
MOVW ptr+0(FP), TO
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
// See memclrNoHeapPointers Go doc for important implementation constraints.
|
||||||
|
|
||||||
// func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
|
// func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
|
||||||
TEXT runtime·memclrNoHeapPointers(SB),NOSPLIT,$0-16
|
TEXT runtime·memclrNoHeapPointers(SB),NOSPLIT,$0-16
|
||||||
MOVD ptr+0(FP), R0
|
MOVD ptr+0(FP), R0
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@
|
||||||
#include "go_asm.h"
|
#include "go_asm.h"
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
// See memclrNoHeapPointers Go doc for important implementation constraints.
|
||||||
|
|
||||||
// func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
|
// func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
|
||||||
TEXT runtime·memclrNoHeapPointers(SB),NOSPLIT,$0-16
|
TEXT runtime·memclrNoHeapPointers(SB),NOSPLIT,$0-16
|
||||||
MOVV ptr+0(FP), R1
|
MOVV ptr+0(FP), R1
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,8 @@
|
||||||
#define MOVWLO MOVWL
|
#define MOVWLO MOVWL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// See memclrNoHeapPointers Go doc for important implementation constraints.
|
||||||
|
|
||||||
// func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
|
// func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
|
||||||
TEXT runtime·memclrNoHeapPointers(SB),NOSPLIT,$0-8
|
TEXT runtime·memclrNoHeapPointers(SB),NOSPLIT,$0-8
|
||||||
MOVW n+4(FP), R2
|
MOVW n+4(FP), R2
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
// See memclrNoHeapPointers Go doc for important implementation constraints.
|
||||||
|
|
||||||
// func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
|
// func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
|
||||||
TEXT runtime·memclrNoHeapPointers(SB), NOSPLIT, $0-8
|
TEXT runtime·memclrNoHeapPointers(SB), NOSPLIT, $0-8
|
||||||
MOVL ptr+0(FP), DI
|
MOVL ptr+0(FP), DI
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
// See memclrNoHeapPointers Go doc for important implementation constraints.
|
||||||
|
|
||||||
// func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
|
// func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
|
||||||
TEXT runtime·memclrNoHeapPointers(SB),NOSPLIT,$0-16
|
TEXT runtime·memclrNoHeapPointers(SB),NOSPLIT,$0-16
|
||||||
MOVQ ptr+0(FP), DI
|
MOVQ ptr+0(FP), DI
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
// See memclrNoHeapPointers Go doc for important implementation constraints.
|
||||||
|
|
||||||
// func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
|
// func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
|
||||||
TEXT runtime·memclrNoHeapPointers(SB), NOSPLIT|NOFRAME, $0-16
|
TEXT runtime·memclrNoHeapPointers(SB), NOSPLIT|NOFRAME, $0-16
|
||||||
MOVD ptr+0(FP), R3
|
MOVD ptr+0(FP), R3
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
// See memclrNoHeapPointers Go doc for important implementation constraints.
|
||||||
|
|
||||||
// void runtime·memclrNoHeapPointers(void*, uintptr)
|
// void runtime·memclrNoHeapPointers(void*, uintptr)
|
||||||
TEXT runtime·memclrNoHeapPointers(SB),NOSPLIT,$0-16
|
TEXT runtime·memclrNoHeapPointers(SB),NOSPLIT,$0-16
|
||||||
MOV ptr+0(FP), T1
|
MOV ptr+0(FP), T1
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
// See memclrNoHeapPointers Go doc for important implementation constraints.
|
||||||
|
|
||||||
// func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
|
// func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
|
||||||
TEXT runtime·memclrNoHeapPointers(SB),NOSPLIT|NOFRAME,$0-16
|
TEXT runtime·memclrNoHeapPointers(SB),NOSPLIT|NOFRAME,$0-16
|
||||||
MOVD ptr+0(FP), R4
|
MOVD ptr+0(FP), R4
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
// See memclrNoHeapPointers Go doc for important implementation constraints.
|
||||||
|
|
||||||
// func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
|
// func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
|
||||||
TEXT runtime·memclrNoHeapPointers(SB), NOSPLIT, $0-16
|
TEXT runtime·memclrNoHeapPointers(SB), NOSPLIT, $0-16
|
||||||
MOVD ptr+0(FP), R0
|
MOVD ptr+0(FP), R0
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build openbsd,!amd64
|
// +build openbsd,!amd64,!arm64
|
||||||
|
|
||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build openbsd,!amd64
|
// +build openbsd,!amd64,!arm64
|
||||||
|
|
||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ const (
|
||||||
//go:cgo_import_dynamic runtime._SetThreadPriority SetThreadPriority%2 "kernel32.dll"
|
//go:cgo_import_dynamic runtime._SetThreadPriority SetThreadPriority%2 "kernel32.dll"
|
||||||
//go:cgo_import_dynamic runtime._SetUnhandledExceptionFilter SetUnhandledExceptionFilter%1 "kernel32.dll"
|
//go:cgo_import_dynamic runtime._SetUnhandledExceptionFilter SetUnhandledExceptionFilter%1 "kernel32.dll"
|
||||||
//go:cgo_import_dynamic runtime._SetWaitableTimer SetWaitableTimer%6 "kernel32.dll"
|
//go:cgo_import_dynamic runtime._SetWaitableTimer SetWaitableTimer%6 "kernel32.dll"
|
||||||
|
//go:cgo_import_dynamic runtime._Sleep Sleep%1 "kernel32.dll"
|
||||||
//go:cgo_import_dynamic runtime._SuspendThread SuspendThread%1 "kernel32.dll"
|
//go:cgo_import_dynamic runtime._SuspendThread SuspendThread%1 "kernel32.dll"
|
||||||
//go:cgo_import_dynamic runtime._SwitchToThread SwitchToThread%0 "kernel32.dll"
|
//go:cgo_import_dynamic runtime._SwitchToThread SwitchToThread%0 "kernel32.dll"
|
||||||
//go:cgo_import_dynamic runtime._TlsAlloc TlsAlloc%0 "kernel32.dll"
|
//go:cgo_import_dynamic runtime._TlsAlloc TlsAlloc%0 "kernel32.dll"
|
||||||
|
|
@ -97,6 +98,7 @@ var (
|
||||||
_SetThreadPriority,
|
_SetThreadPriority,
|
||||||
_SetUnhandledExceptionFilter,
|
_SetUnhandledExceptionFilter,
|
||||||
_SetWaitableTimer,
|
_SetWaitableTimer,
|
||||||
|
_Sleep,
|
||||||
_SuspendThread,
|
_SuspendThread,
|
||||||
_SwitchToThread,
|
_SwitchToThread,
|
||||||
_TlsAlloc,
|
_TlsAlloc,
|
||||||
|
|
@ -1094,6 +1096,11 @@ func ctrlhandler1(_type uint32) uint32 {
|
||||||
}
|
}
|
||||||
|
|
||||||
if sigsend(s) {
|
if sigsend(s) {
|
||||||
|
if s == _SIGTERM {
|
||||||
|
// Windows terminates the process after this handler returns.
|
||||||
|
// Block indefinitely to give signal handlers a chance to clean up.
|
||||||
|
stdcall1(_Sleep, uintptr(_INFINITE))
|
||||||
|
}
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
|
|
|
||||||
|
|
@ -1000,7 +1000,6 @@ func gopanic(e interface{}) {
|
||||||
}
|
}
|
||||||
atomic.Xadd(&runningPanicDefers, -1)
|
atomic.Xadd(&runningPanicDefers, -1)
|
||||||
|
|
||||||
if done {
|
|
||||||
// Remove any remaining non-started, open-coded
|
// Remove any remaining non-started, open-coded
|
||||||
// defer entries after a recover, since the
|
// defer entries after a recover, since the
|
||||||
// corresponding defers will be executed normally
|
// corresponding defers will be executed normally
|
||||||
|
|
@ -1009,8 +1008,14 @@ func gopanic(e interface{}) {
|
||||||
// the associated stack frame.
|
// the associated stack frame.
|
||||||
d := gp._defer
|
d := gp._defer
|
||||||
var prev *_defer
|
var prev *_defer
|
||||||
|
if !done {
|
||||||
|
// Skip our current frame, if not done. It is
|
||||||
|
// needed to complete any remaining defers in
|
||||||
|
// deferreturn()
|
||||||
|
prev = d
|
||||||
|
d = d.link
|
||||||
|
}
|
||||||
for d != nil {
|
for d != nil {
|
||||||
if d.openDefer {
|
|
||||||
if d.started {
|
if d.started {
|
||||||
// This defer is started but we
|
// This defer is started but we
|
||||||
// are in the middle of a
|
// are in the middle of a
|
||||||
|
|
@ -1019,6 +1024,7 @@ func gopanic(e interface{}) {
|
||||||
// further defer entries
|
// further defer entries
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
if d.openDefer {
|
||||||
if prev == nil {
|
if prev == nil {
|
||||||
gp._defer = d.link
|
gp._defer = d.link
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1032,7 +1038,6 @@ func gopanic(e interface{}) {
|
||||||
d = d.link
|
d = d.link
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
gp._panic = p.link
|
gp._panic = p.link
|
||||||
// Aborted panics are marked but remain on the g.panic list.
|
// Aborted panics are marked but remain on the g.panic list.
|
||||||
|
|
|
||||||
|
|
@ -1213,7 +1213,7 @@ func usesLibcall() bool {
|
||||||
case "aix", "darwin", "illumos", "ios", "solaris", "windows":
|
case "aix", "darwin", "illumos", "ios", "solaris", "windows":
|
||||||
return true
|
return true
|
||||||
case "openbsd":
|
case "openbsd":
|
||||||
return GOARCH == "amd64"
|
return GOARCH == "amd64" || GOARCH == "arm64"
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
@ -79,6 +80,69 @@ func sendCtrlBreak(pid int) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestCtrlHandler tests that Go can gracefully handle closing the console window.
|
||||||
|
// See https://golang.org/issues/41884.
|
||||||
|
func TestCtrlHandler(t *testing.T) {
|
||||||
|
testenv.MustHaveGoBuild(t)
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
// build go program
|
||||||
|
exe := filepath.Join(t.TempDir(), "test.exe")
|
||||||
|
cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", exe, "testdata/testwinsignal/main.go")
|
||||||
|
out, err := testenv.CleanCmdEnv(cmd).CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to build go exe: %v\n%s", err, out)
|
||||||
|
}
|
||||||
|
|
||||||
|
// run test program
|
||||||
|
cmd = exec.Command(exe)
|
||||||
|
var stderr bytes.Buffer
|
||||||
|
cmd.Stderr = &stderr
|
||||||
|
outPipe, err := cmd.StdoutPipe()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create stdout pipe: %v", err)
|
||||||
|
}
|
||||||
|
outReader := bufio.NewReader(outPipe)
|
||||||
|
|
||||||
|
// in a new command window
|
||||||
|
const _CREATE_NEW_CONSOLE = 0x00000010
|
||||||
|
cmd.SysProcAttr = &syscall.SysProcAttr{
|
||||||
|
CreationFlags: _CREATE_NEW_CONSOLE,
|
||||||
|
HideWindow: true,
|
||||||
|
}
|
||||||
|
if err := cmd.Start(); err != nil {
|
||||||
|
t.Fatalf("Start failed: %v", err)
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
cmd.Process.Kill()
|
||||||
|
cmd.Wait()
|
||||||
|
}()
|
||||||
|
|
||||||
|
// wait for child to be ready to receive signals
|
||||||
|
if line, err := outReader.ReadString('\n'); err != nil {
|
||||||
|
t.Fatalf("could not read stdout: %v", err)
|
||||||
|
} else if strings.TrimSpace(line) != "ready" {
|
||||||
|
t.Fatalf("unexpected message: %s", line)
|
||||||
|
}
|
||||||
|
|
||||||
|
// gracefully kill pid, this closes the command window
|
||||||
|
if err := exec.Command("taskkill.exe", "/pid", strconv.Itoa(cmd.Process.Pid)).Run(); err != nil {
|
||||||
|
t.Fatalf("failed to kill: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// check child received, handled SIGTERM
|
||||||
|
if line, err := outReader.ReadString('\n'); err != nil {
|
||||||
|
t.Fatalf("could not read stdout: %v", err)
|
||||||
|
} else if expected, got := syscall.SIGTERM.String(), strings.TrimSpace(line); expected != got {
|
||||||
|
t.Fatalf("Expected '%s' got: %s", expected, got)
|
||||||
|
}
|
||||||
|
|
||||||
|
// check child exited gracefully, did not timeout
|
||||||
|
if err := cmd.Wait(); err != nil {
|
||||||
|
t.Fatalf("Program exited with error: %v\n%s", err, &stderr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TestLibraryCtrlHandler tests that Go DLL allows calling program to handle console control events.
|
// TestLibraryCtrlHandler tests that Go DLL allows calling program to handle console control events.
|
||||||
// See https://golang.org/issues/35965.
|
// See https://golang.org/issues/35965.
|
||||||
func TestLibraryCtrlHandler(t *testing.T) {
|
func TestLibraryCtrlHandler(t *testing.T) {
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,15 @@ func badsystemstack() {
|
||||||
// *ptr is uninitialized memory (e.g., memory that's being reused
|
// *ptr is uninitialized memory (e.g., memory that's being reused
|
||||||
// for a new allocation) and hence contains only "junk".
|
// for a new allocation) and hence contains only "junk".
|
||||||
//
|
//
|
||||||
|
// memclrNoHeapPointers ensures that if ptr is pointer-aligned, and n
|
||||||
|
// is a multiple of the pointer size, then any pointer-aligned,
|
||||||
|
// pointer-sized portion is cleared atomically. Despite the function
|
||||||
|
// name, this is necessary because this function is the underlying
|
||||||
|
// implementation of typedmemclr and memclrHasPointers. See the doc of
|
||||||
|
// memmove for more details.
|
||||||
|
//
|
||||||
// The (CPU-specific) implementations of this function are in memclr_*.s.
|
// The (CPU-specific) implementations of this function are in memclr_*.s.
|
||||||
|
//
|
||||||
//go:noescape
|
//go:noescape
|
||||||
func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
|
func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build openbsd,amd64
|
// +build openbsd,amd64 openbsd,arm64
|
||||||
|
|
||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build openbsd,amd64
|
// +build openbsd,amd64 openbsd,arm64
|
||||||
|
|
||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
|
|
|
||||||
113
src/runtime/sys_openbsd3.go
Normal file
113
src/runtime/sys_openbsd3.go
Normal file
|
|
@ -0,0 +1,113 @@
|
||||||
|
// Copyright 2020 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build openbsd,amd64 openbsd,arm64
|
||||||
|
|
||||||
|
package runtime
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
// The X versions of syscall expect the libc call to return a 64-bit result.
|
||||||
|
// Otherwise (the non-X version) expects a 32-bit result.
|
||||||
|
// This distinction is required because an error is indicated by returning -1,
|
||||||
|
// and we need to know whether to check 32 or 64 bits of the result.
|
||||||
|
// (Some libc functions that return 32 bits put junk in the upper 32 bits of AX.)
|
||||||
|
|
||||||
|
//go:linkname syscall_syscall syscall.syscall
|
||||||
|
//go:nosplit
|
||||||
|
//go:cgo_unsafe_args
|
||||||
|
func syscall_syscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
|
||||||
|
entersyscall()
|
||||||
|
libcCall(unsafe.Pointer(funcPC(syscall)), unsafe.Pointer(&fn))
|
||||||
|
exitsyscall()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
func syscall()
|
||||||
|
|
||||||
|
//go:linkname syscall_syscallX syscall.syscallX
|
||||||
|
//go:nosplit
|
||||||
|
//go:cgo_unsafe_args
|
||||||
|
func syscall_syscallX(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
|
||||||
|
entersyscall()
|
||||||
|
libcCall(unsafe.Pointer(funcPC(syscallX)), unsafe.Pointer(&fn))
|
||||||
|
exitsyscall()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
func syscallX()
|
||||||
|
|
||||||
|
//go:linkname syscall_syscall6 syscall.syscall6
|
||||||
|
//go:nosplit
|
||||||
|
//go:cgo_unsafe_args
|
||||||
|
func syscall_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
|
||||||
|
entersyscall()
|
||||||
|
libcCall(unsafe.Pointer(funcPC(syscall6)), unsafe.Pointer(&fn))
|
||||||
|
exitsyscall()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
func syscall6()
|
||||||
|
|
||||||
|
//go:linkname syscall_syscall6X syscall.syscall6X
|
||||||
|
//go:nosplit
|
||||||
|
//go:cgo_unsafe_args
|
||||||
|
func syscall_syscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
|
||||||
|
entersyscall()
|
||||||
|
libcCall(unsafe.Pointer(funcPC(syscall6X)), unsafe.Pointer(&fn))
|
||||||
|
exitsyscall()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
func syscall6X()
|
||||||
|
|
||||||
|
//go:linkname syscall_syscall10 syscall.syscall10
|
||||||
|
//go:nosplit
|
||||||
|
//go:cgo_unsafe_args
|
||||||
|
func syscall_syscall10(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 uintptr) (r1, r2, err uintptr) {
|
||||||
|
entersyscall()
|
||||||
|
libcCall(unsafe.Pointer(funcPC(syscall10)), unsafe.Pointer(&fn))
|
||||||
|
exitsyscall()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
func syscall10()
|
||||||
|
|
||||||
|
//go:linkname syscall_syscall10X syscall.syscall10X
|
||||||
|
//go:nosplit
|
||||||
|
//go:cgo_unsafe_args
|
||||||
|
func syscall_syscall10X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 uintptr) (r1, r2, err uintptr) {
|
||||||
|
entersyscall()
|
||||||
|
libcCall(unsafe.Pointer(funcPC(syscall10X)), unsafe.Pointer(&fn))
|
||||||
|
exitsyscall()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
func syscall10X()
|
||||||
|
|
||||||
|
//go:linkname syscall_rawSyscall syscall.rawSyscall
|
||||||
|
//go:nosplit
|
||||||
|
//go:cgo_unsafe_args
|
||||||
|
func syscall_rawSyscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
|
||||||
|
libcCall(unsafe.Pointer(funcPC(syscall)), unsafe.Pointer(&fn))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:linkname syscall_rawSyscall6 syscall.rawSyscall6
|
||||||
|
//go:nosplit
|
||||||
|
//go:cgo_unsafe_args
|
||||||
|
func syscall_rawSyscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
|
||||||
|
libcCall(unsafe.Pointer(funcPC(syscall6)), unsafe.Pointer(&fn))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:linkname syscall_rawSyscall6X syscall.rawSyscall6X
|
||||||
|
//go:nosplit
|
||||||
|
//go:cgo_unsafe_args
|
||||||
|
func syscall_rawSyscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
|
||||||
|
libcCall(unsafe.Pointer(funcPC(syscall6X)), unsafe.Pointer(&fn))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:linkname syscall_rawSyscall10X syscall.rawSyscall10X
|
||||||
|
//go:nosplit
|
||||||
|
//go:cgo_unsafe_args
|
||||||
|
func syscall_rawSyscall10X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 uintptr) (r1, r2, err uintptr) {
|
||||||
|
libcCall(unsafe.Pointer(funcPC(syscall10X)), unsafe.Pointer(&fn))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
@ -445,3 +445,344 @@ TEXT runtime·sigaltstack_trampoline(SB),NOSPLIT,$0
|
||||||
MOVL $0xf1, 0xf1 // crash
|
MOVL $0xf1, 0xf1 // crash
|
||||||
POPQ BP
|
POPQ BP
|
||||||
RET
|
RET
|
||||||
|
|
||||||
|
// syscall calls a function in libc on behalf of the syscall package.
|
||||||
|
// syscall takes a pointer to a struct like:
|
||||||
|
// struct {
|
||||||
|
// fn uintptr
|
||||||
|
// a1 uintptr
|
||||||
|
// a2 uintptr
|
||||||
|
// a3 uintptr
|
||||||
|
// r1 uintptr
|
||||||
|
// r2 uintptr
|
||||||
|
// err uintptr
|
||||||
|
// }
|
||||||
|
// syscall must be called on the g0 stack with the
|
||||||
|
// C calling convention (use libcCall).
|
||||||
|
//
|
||||||
|
// syscall expects a 32-bit result and tests for 32-bit -1
|
||||||
|
// to decide there was an error.
|
||||||
|
TEXT runtime·syscall(SB),NOSPLIT,$0
|
||||||
|
PUSHQ BP
|
||||||
|
MOVQ SP, BP
|
||||||
|
SUBQ $16, SP
|
||||||
|
MOVQ (0*8)(DI), CX // fn
|
||||||
|
MOVQ (2*8)(DI), SI // a2
|
||||||
|
MOVQ (3*8)(DI), DX // a3
|
||||||
|
MOVQ DI, (SP)
|
||||||
|
MOVQ (1*8)(DI), DI // a1
|
||||||
|
XORL AX, AX // vararg: say "no float args"
|
||||||
|
|
||||||
|
CALL CX
|
||||||
|
|
||||||
|
MOVQ (SP), DI
|
||||||
|
MOVQ AX, (4*8)(DI) // r1
|
||||||
|
MOVQ DX, (5*8)(DI) // r2
|
||||||
|
|
||||||
|
// Standard libc functions return -1 on error
|
||||||
|
// and set errno.
|
||||||
|
CMPL AX, $-1 // Note: high 32 bits are junk
|
||||||
|
JNE ok
|
||||||
|
|
||||||
|
// Get error code from libc.
|
||||||
|
CALL libc_errno(SB)
|
||||||
|
MOVLQSX (AX), AX
|
||||||
|
MOVQ (SP), DI
|
||||||
|
MOVQ AX, (6*8)(DI) // err
|
||||||
|
|
||||||
|
ok:
|
||||||
|
XORL AX, AX // no error (it's ignored anyway)
|
||||||
|
MOVQ BP, SP
|
||||||
|
POPQ BP
|
||||||
|
RET
|
||||||
|
|
||||||
|
// syscallX calls a function in libc on behalf of the syscall package.
|
||||||
|
// syscallX takes a pointer to a struct like:
|
||||||
|
// struct {
|
||||||
|
// fn uintptr
|
||||||
|
// a1 uintptr
|
||||||
|
// a2 uintptr
|
||||||
|
// a3 uintptr
|
||||||
|
// r1 uintptr
|
||||||
|
// r2 uintptr
|
||||||
|
// err uintptr
|
||||||
|
// }
|
||||||
|
// syscallX must be called on the g0 stack with the
|
||||||
|
// C calling convention (use libcCall).
|
||||||
|
//
|
||||||
|
// syscallX is like syscall but expects a 64-bit result
|
||||||
|
// and tests for 64-bit -1 to decide there was an error.
|
||||||
|
TEXT runtime·syscallX(SB),NOSPLIT,$0
|
||||||
|
PUSHQ BP
|
||||||
|
MOVQ SP, BP
|
||||||
|
SUBQ $16, SP
|
||||||
|
MOVQ (0*8)(DI), CX // fn
|
||||||
|
MOVQ (2*8)(DI), SI // a2
|
||||||
|
MOVQ (3*8)(DI), DX // a3
|
||||||
|
MOVQ DI, (SP)
|
||||||
|
MOVQ (1*8)(DI), DI // a1
|
||||||
|
XORL AX, AX // vararg: say "no float args"
|
||||||
|
|
||||||
|
CALL CX
|
||||||
|
|
||||||
|
MOVQ (SP), DI
|
||||||
|
MOVQ AX, (4*8)(DI) // r1
|
||||||
|
MOVQ DX, (5*8)(DI) // r2
|
||||||
|
|
||||||
|
// Standard libc functions return -1 on error
|
||||||
|
// and set errno.
|
||||||
|
CMPQ AX, $-1
|
||||||
|
JNE ok
|
||||||
|
|
||||||
|
// Get error code from libc.
|
||||||
|
CALL libc_errno(SB)
|
||||||
|
MOVLQSX (AX), AX
|
||||||
|
MOVQ (SP), DI
|
||||||
|
MOVQ AX, (6*8)(DI) // err
|
||||||
|
|
||||||
|
ok:
|
||||||
|
XORL AX, AX // no error (it's ignored anyway)
|
||||||
|
MOVQ BP, SP
|
||||||
|
POPQ BP
|
||||||
|
RET
|
||||||
|
|
||||||
|
// syscall6 calls a function in libc on behalf of the syscall package.
|
||||||
|
// syscall6 takes a pointer to a struct like:
|
||||||
|
// struct {
|
||||||
|
// fn uintptr
|
||||||
|
// a1 uintptr
|
||||||
|
// a2 uintptr
|
||||||
|
// a3 uintptr
|
||||||
|
// a4 uintptr
|
||||||
|
// a5 uintptr
|
||||||
|
// a6 uintptr
|
||||||
|
// r1 uintptr
|
||||||
|
// r2 uintptr
|
||||||
|
// err uintptr
|
||||||
|
// }
|
||||||
|
// syscall6 must be called on the g0 stack with the
|
||||||
|
// C calling convention (use libcCall).
|
||||||
|
//
|
||||||
|
// syscall6 expects a 32-bit result and tests for 32-bit -1
|
||||||
|
// to decide there was an error.
|
||||||
|
TEXT runtime·syscall6(SB),NOSPLIT,$0
|
||||||
|
PUSHQ BP
|
||||||
|
MOVQ SP, BP
|
||||||
|
SUBQ $16, SP
|
||||||
|
MOVQ (0*8)(DI), R11// fn
|
||||||
|
MOVQ (2*8)(DI), SI // a2
|
||||||
|
MOVQ (3*8)(DI), DX // a3
|
||||||
|
MOVQ (4*8)(DI), CX // a4
|
||||||
|
MOVQ (5*8)(DI), R8 // a5
|
||||||
|
MOVQ (6*8)(DI), R9 // a6
|
||||||
|
MOVQ DI, (SP)
|
||||||
|
MOVQ (1*8)(DI), DI // a1
|
||||||
|
XORL AX, AX // vararg: say "no float args"
|
||||||
|
|
||||||
|
CALL R11
|
||||||
|
|
||||||
|
MOVQ (SP), DI
|
||||||
|
MOVQ AX, (7*8)(DI) // r1
|
||||||
|
MOVQ DX, (8*8)(DI) // r2
|
||||||
|
|
||||||
|
CMPL AX, $-1
|
||||||
|
JNE ok
|
||||||
|
|
||||||
|
CALL libc_errno(SB)
|
||||||
|
MOVLQSX (AX), AX
|
||||||
|
MOVQ (SP), DI
|
||||||
|
MOVQ AX, (9*8)(DI) // err
|
||||||
|
|
||||||
|
ok:
|
||||||
|
XORL AX, AX // no error (it's ignored anyway)
|
||||||
|
MOVQ BP, SP
|
||||||
|
POPQ BP
|
||||||
|
RET
|
||||||
|
|
||||||
|
// syscall6X calls a function in libc on behalf of the syscall package.
|
||||||
|
// syscall6X takes a pointer to a struct like:
|
||||||
|
// struct {
|
||||||
|
// fn uintptr
|
||||||
|
// a1 uintptr
|
||||||
|
// a2 uintptr
|
||||||
|
// a3 uintptr
|
||||||
|
// a4 uintptr
|
||||||
|
// a5 uintptr
|
||||||
|
// a6 uintptr
|
||||||
|
// r1 uintptr
|
||||||
|
// r2 uintptr
|
||||||
|
// err uintptr
|
||||||
|
// }
|
||||||
|
// syscall6X must be called on the g0 stack with the
|
||||||
|
// C calling convention (use libcCall).
|
||||||
|
//
|
||||||
|
// syscall6X is like syscall6 but expects a 64-bit result
|
||||||
|
// and tests for 64-bit -1 to decide there was an error.
|
||||||
|
TEXT runtime·syscall6X(SB),NOSPLIT,$0
|
||||||
|
PUSHQ BP
|
||||||
|
MOVQ SP, BP
|
||||||
|
SUBQ $16, SP
|
||||||
|
MOVQ (0*8)(DI), R11// fn
|
||||||
|
MOVQ (2*8)(DI), SI // a2
|
||||||
|
MOVQ (3*8)(DI), DX // a3
|
||||||
|
MOVQ (4*8)(DI), CX // a4
|
||||||
|
MOVQ (5*8)(DI), R8 // a5
|
||||||
|
MOVQ (6*8)(DI), R9 // a6
|
||||||
|
MOVQ DI, (SP)
|
||||||
|
MOVQ (1*8)(DI), DI // a1
|
||||||
|
XORL AX, AX // vararg: say "no float args"
|
||||||
|
|
||||||
|
CALL R11
|
||||||
|
|
||||||
|
MOVQ (SP), DI
|
||||||
|
MOVQ AX, (7*8)(DI) // r1
|
||||||
|
MOVQ DX, (8*8)(DI) // r2
|
||||||
|
|
||||||
|
CMPQ AX, $-1
|
||||||
|
JNE ok
|
||||||
|
|
||||||
|
CALL libc_errno(SB)
|
||||||
|
MOVLQSX (AX), AX
|
||||||
|
MOVQ (SP), DI
|
||||||
|
MOVQ AX, (9*8)(DI) // err
|
||||||
|
|
||||||
|
ok:
|
||||||
|
XORL AX, AX // no error (it's ignored anyway)
|
||||||
|
MOVQ BP, SP
|
||||||
|
POPQ BP
|
||||||
|
RET
|
||||||
|
|
||||||
|
// syscall10 calls a function in libc on behalf of the syscall package.
|
||||||
|
// syscall10 takes a pointer to a struct like:
|
||||||
|
// struct {
|
||||||
|
// fn uintptr
|
||||||
|
// a1 uintptr
|
||||||
|
// a2 uintptr
|
||||||
|
// a3 uintptr
|
||||||
|
// a4 uintptr
|
||||||
|
// a5 uintptr
|
||||||
|
// a6 uintptr
|
||||||
|
// a7 uintptr
|
||||||
|
// a8 uintptr
|
||||||
|
// a9 uintptr
|
||||||
|
// a10 uintptr
|
||||||
|
// r1 uintptr
|
||||||
|
// r2 uintptr
|
||||||
|
// err uintptr
|
||||||
|
// }
|
||||||
|
// syscall10 must be called on the g0 stack with the
|
||||||
|
// C calling convention (use libcCall).
|
||||||
|
TEXT runtime·syscall10(SB),NOSPLIT,$0
|
||||||
|
PUSHQ BP
|
||||||
|
MOVQ SP, BP
|
||||||
|
SUBQ $48, SP
|
||||||
|
|
||||||
|
// Arguments a1 to a6 get passed in registers, with a7 onwards being
|
||||||
|
// passed via the stack per the x86-64 System V ABI
|
||||||
|
// (https://github.com/hjl-tools/x86-psABI/wiki/x86-64-psABI-1.0.pdf).
|
||||||
|
MOVQ (7*8)(DI), R10 // a7
|
||||||
|
MOVQ (8*8)(DI), R11 // a8
|
||||||
|
MOVQ (9*8)(DI), R12 // a9
|
||||||
|
MOVQ (10*8)(DI), R13 // a10
|
||||||
|
MOVQ R10, (0*8)(SP) // a7
|
||||||
|
MOVQ R11, (1*8)(SP) // a8
|
||||||
|
MOVQ R12, (2*8)(SP) // a9
|
||||||
|
MOVQ R13, (3*8)(SP) // a10
|
||||||
|
MOVQ (0*8)(DI), R11 // fn
|
||||||
|
MOVQ (2*8)(DI), SI // a2
|
||||||
|
MOVQ (3*8)(DI), DX // a3
|
||||||
|
MOVQ (4*8)(DI), CX // a4
|
||||||
|
MOVQ (5*8)(DI), R8 // a5
|
||||||
|
MOVQ (6*8)(DI), R9 // a6
|
||||||
|
MOVQ DI, (4*8)(SP)
|
||||||
|
MOVQ (1*8)(DI), DI // a1
|
||||||
|
XORL AX, AX // vararg: say "no float args"
|
||||||
|
|
||||||
|
CALL R11
|
||||||
|
|
||||||
|
MOVQ (4*8)(SP), DI
|
||||||
|
MOVQ AX, (11*8)(DI) // r1
|
||||||
|
MOVQ DX, (12*8)(DI) // r2
|
||||||
|
|
||||||
|
CMPL AX, $-1
|
||||||
|
JNE ok
|
||||||
|
|
||||||
|
CALL libc_errno(SB)
|
||||||
|
MOVLQSX (AX), AX
|
||||||
|
MOVQ (4*8)(SP), DI
|
||||||
|
MOVQ AX, (13*8)(DI) // err
|
||||||
|
|
||||||
|
ok:
|
||||||
|
XORL AX, AX // no error (it's ignored anyway)
|
||||||
|
MOVQ BP, SP
|
||||||
|
POPQ BP
|
||||||
|
RET
|
||||||
|
|
||||||
|
// syscall10X calls a function in libc on behalf of the syscall package.
|
||||||
|
// syscall10X takes a pointer to a struct like:
|
||||||
|
// struct {
|
||||||
|
// fn uintptr
|
||||||
|
// a1 uintptr
|
||||||
|
// a2 uintptr
|
||||||
|
// a3 uintptr
|
||||||
|
// a4 uintptr
|
||||||
|
// a5 uintptr
|
||||||
|
// a6 uintptr
|
||||||
|
// a7 uintptr
|
||||||
|
// a8 uintptr
|
||||||
|
// a9 uintptr
|
||||||
|
// a10 uintptr
|
||||||
|
// r1 uintptr
|
||||||
|
// r2 uintptr
|
||||||
|
// err uintptr
|
||||||
|
// }
|
||||||
|
// syscall10X must be called on the g0 stack with the
|
||||||
|
// C calling convention (use libcCall).
|
||||||
|
//
|
||||||
|
// syscall10X is like syscall10 but expects a 64-bit result
|
||||||
|
// and tests for 64-bit -1 to decide there was an error.
|
||||||
|
TEXT runtime·syscall10X(SB),NOSPLIT,$0
|
||||||
|
PUSHQ BP
|
||||||
|
MOVQ SP, BP
|
||||||
|
SUBQ $48, SP
|
||||||
|
|
||||||
|
// Arguments a1 to a6 get passed in registers, with a7 onwards being
|
||||||
|
// passed via the stack per the x86-64 System V ABI
|
||||||
|
// (https://github.com/hjl-tools/x86-psABI/wiki/x86-64-psABI-1.0.pdf).
|
||||||
|
MOVQ (7*8)(DI), R10 // a7
|
||||||
|
MOVQ (8*8)(DI), R11 // a8
|
||||||
|
MOVQ (9*8)(DI), R12 // a9
|
||||||
|
MOVQ (10*8)(DI), R13 // a10
|
||||||
|
MOVQ R10, (0*8)(SP) // a7
|
||||||
|
MOVQ R11, (1*8)(SP) // a8
|
||||||
|
MOVQ R12, (2*8)(SP) // a9
|
||||||
|
MOVQ R13, (3*8)(SP) // a10
|
||||||
|
MOVQ (0*8)(DI), R11 // fn
|
||||||
|
MOVQ (2*8)(DI), SI // a2
|
||||||
|
MOVQ (3*8)(DI), DX // a3
|
||||||
|
MOVQ (4*8)(DI), CX // a4
|
||||||
|
MOVQ (5*8)(DI), R8 // a5
|
||||||
|
MOVQ (6*8)(DI), R9 // a6
|
||||||
|
MOVQ DI, (4*8)(SP)
|
||||||
|
MOVQ (1*8)(DI), DI // a1
|
||||||
|
XORL AX, AX // vararg: say "no float args"
|
||||||
|
|
||||||
|
CALL R11
|
||||||
|
|
||||||
|
MOVQ (4*8)(SP), DI
|
||||||
|
MOVQ AX, (11*8)(DI) // r1
|
||||||
|
MOVQ DX, (12*8)(DI) // r2
|
||||||
|
|
||||||
|
CMPQ AX, $-1
|
||||||
|
JNE ok
|
||||||
|
|
||||||
|
CALL libc_errno(SB)
|
||||||
|
MOVLQSX (AX), AX
|
||||||
|
MOVQ (4*8)(SP), DI
|
||||||
|
MOVQ AX, (13*8)(DI) // err
|
||||||
|
|
||||||
|
ok:
|
||||||
|
XORL AX, AX // no error (it's ignored anyway)
|
||||||
|
MOVQ BP, SP
|
||||||
|
POPQ BP
|
||||||
|
RET
|
||||||
|
|
|
||||||
|
|
@ -15,17 +15,6 @@
|
||||||
#define CLOCK_REALTIME $0
|
#define CLOCK_REALTIME $0
|
||||||
#define CLOCK_MONOTONIC $3
|
#define CLOCK_MONOTONIC $3
|
||||||
|
|
||||||
// With OpenBSD 6.7 onwards, an arm64 syscall returns two instructions
|
|
||||||
// after the SVC instruction, to allow for a speculative execution
|
|
||||||
// barrier to be placed after the SVC without impacting performance.
|
|
||||||
// For now use hardware no-ops as this works with both older and newer
|
|
||||||
// kernels. After OpenBSD 6.8 is released this should be changed to
|
|
||||||
// speculation barriers.
|
|
||||||
#define INVOKE_SYSCALL \
|
|
||||||
SVC; \
|
|
||||||
NOOP; \
|
|
||||||
NOOP
|
|
||||||
|
|
||||||
// mstart_stub is the first function executed on a new thread started by pthread_create.
|
// mstart_stub is the first function executed on a new thread started by pthread_create.
|
||||||
// It just does some low-level setup and then calls mstart.
|
// It just does some low-level setup and then calls mstart.
|
||||||
// Note: called with the C calling convention.
|
// Note: called with the C calling convention.
|
||||||
|
|
@ -188,322 +177,524 @@ TEXT runtime·pthread_create_trampoline(SB),NOSPLIT,$0
|
||||||
ADD $16, RSP
|
ADD $16, RSP
|
||||||
RET
|
RET
|
||||||
|
|
||||||
// Exit the entire program (like C exit)
|
TEXT runtime·thrkill_trampoline(SB),NOSPLIT,$0
|
||||||
TEXT runtime·exit(SB),NOSPLIT|NOFRAME,$0
|
MOVW 8(R0), R1 // arg 2 - signal
|
||||||
MOVW code+0(FP), R0 // arg 1 - status
|
MOVD $0, R2 // arg 3 - tcb
|
||||||
MOVD $1, R8 // sys_exit
|
MOVW 0(R0), R0 // arg 1 - tid
|
||||||
INVOKE_SYSCALL
|
CALL libc_thrkill(SB)
|
||||||
BCC 3(PC)
|
RET
|
||||||
MOVD $0, R0 // crash on syscall failure
|
|
||||||
|
TEXT runtime·thrsleep_trampoline(SB),NOSPLIT,$0
|
||||||
|
MOVW 8(R0), R1 // arg 2 - clock_id
|
||||||
|
MOVD 16(R0), R2 // arg 3 - abstime
|
||||||
|
MOVD 24(R0), R3 // arg 4 - lock
|
||||||
|
MOVD 32(R0), R4 // arg 5 - abort
|
||||||
|
MOVD 0(R0), R0 // arg 1 - id
|
||||||
|
CALL libc_thrsleep(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT runtime·thrwakeup_trampoline(SB),NOSPLIT,$0
|
||||||
|
MOVW 8(R0), R1 // arg 2 - count
|
||||||
|
MOVD 0(R0), R0 // arg 1 - id
|
||||||
|
CALL libc_thrwakeup(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT runtime·exit_trampoline(SB),NOSPLIT,$0
|
||||||
|
MOVW 0(R0), R0 // arg 1 - status
|
||||||
|
CALL libc_exit(SB)
|
||||||
|
MOVD $0, R0 // crash on failure
|
||||||
MOVD R0, (R0)
|
MOVD R0, (R0)
|
||||||
RET
|
RET
|
||||||
|
|
||||||
// func exitThread(wait *uint32)
|
TEXT runtime·getthrid_trampoline(SB),NOSPLIT,$0
|
||||||
TEXT runtime·exitThread(SB),NOSPLIT,$0
|
MOVD R0, R19 // pointer to args
|
||||||
MOVD wait+0(FP), R0 // arg 1 - notdead
|
CALL libc_getthrid(SB)
|
||||||
MOVD $302, R8 // sys___threxit
|
MOVW R0, 0(R19) // return value
|
||||||
INVOKE_SYSCALL
|
|
||||||
MOVD $0, R0 // crash on syscall failure
|
|
||||||
MOVD R0, (R0)
|
|
||||||
JMP 0(PC)
|
|
||||||
|
|
||||||
TEXT runtime·open(SB),NOSPLIT|NOFRAME,$0
|
|
||||||
MOVD name+0(FP), R0 // arg 1 - path
|
|
||||||
MOVW mode+8(FP), R1 // arg 2 - mode
|
|
||||||
MOVW perm+12(FP), R2 // arg 3 - perm
|
|
||||||
MOVD $5, R8 // sys_open
|
|
||||||
INVOKE_SYSCALL
|
|
||||||
BCC 2(PC)
|
|
||||||
MOVW $-1, R0
|
|
||||||
MOVW R0, ret+16(FP)
|
|
||||||
RET
|
RET
|
||||||
|
|
||||||
TEXT runtime·closefd(SB),NOSPLIT|NOFRAME,$0
|
TEXT runtime·raiseproc_trampoline(SB),NOSPLIT,$0
|
||||||
MOVW fd+0(FP), R0 // arg 1 - fd
|
MOVD R0, R19 // pointer to args
|
||||||
MOVD $6, R8 // sys_close
|
CALL libc_getpid(SB) // arg 1 - pid
|
||||||
INVOKE_SYSCALL
|
MOVW 0(R19), R1 // arg 2 - signal
|
||||||
BCC 2(PC)
|
CALL libc_kill(SB)
|
||||||
MOVW $-1, R0
|
|
||||||
MOVW R0, ret+8(FP)
|
|
||||||
RET
|
RET
|
||||||
|
|
||||||
TEXT runtime·read(SB),NOSPLIT|NOFRAME,$0
|
TEXT runtime·sched_yield_trampoline(SB),NOSPLIT,$0
|
||||||
MOVW fd+0(FP), R0 // arg 1 - fd
|
CALL libc_sched_yield(SB)
|
||||||
MOVD p+8(FP), R1 // arg 2 - buf
|
|
||||||
MOVW n+16(FP), R2 // arg 3 - nbyte
|
|
||||||
MOVD $3, R8 // sys_read
|
|
||||||
INVOKE_SYSCALL
|
|
||||||
BCC 2(PC)
|
|
||||||
NEG R0, R0
|
|
||||||
MOVW R0, ret+24(FP)
|
|
||||||
RET
|
RET
|
||||||
|
|
||||||
// func pipe() (r, w int32, errno int32)
|
TEXT runtime·mmap_trampoline(SB),NOSPLIT,$0
|
||||||
TEXT runtime·pipe(SB),NOSPLIT|NOFRAME,$0-12
|
MOVD R0, R19 // pointer to args
|
||||||
MOVD $r+0(FP), R0
|
MOVD 0(R19), R0 // arg 1 - addr
|
||||||
MOVW $0, R1
|
MOVD 8(R19), R1 // arg 2 - len
|
||||||
MOVD $101, R8 // sys_pipe2
|
MOVW 16(R19), R2 // arg 3 - prot
|
||||||
INVOKE_SYSCALL
|
MOVW 20(R19), R3 // arg 4 - flags
|
||||||
BCC 2(PC)
|
MOVW 24(R19), R4 // arg 5 - fid
|
||||||
NEG R0, R0
|
MOVW 28(R19), R5 // arg 6 - offset
|
||||||
MOVW R0, errno+8(FP)
|
CALL libc_mmap(SB)
|
||||||
RET
|
|
||||||
|
|
||||||
// func pipe2(flags int32) (r, w int32, errno int32)
|
|
||||||
TEXT runtime·pipe2(SB),NOSPLIT|NOFRAME,$0-20
|
|
||||||
MOVD $r+8(FP), R0
|
|
||||||
MOVW flags+0(FP), R1
|
|
||||||
MOVD $101, R8 // sys_pipe2
|
|
||||||
INVOKE_SYSCALL
|
|
||||||
BCC 2(PC)
|
|
||||||
NEG R0, R0
|
|
||||||
MOVW R0, errno+16(FP)
|
|
||||||
RET
|
|
||||||
|
|
||||||
TEXT runtime·write1(SB),NOSPLIT|NOFRAME,$0
|
|
||||||
MOVD fd+0(FP), R0 // arg 1 - fd
|
|
||||||
MOVD p+8(FP), R1 // arg 2 - buf
|
|
||||||
MOVW n+16(FP), R2 // arg 3 - nbyte
|
|
||||||
MOVD $4, R8 // sys_write
|
|
||||||
INVOKE_SYSCALL
|
|
||||||
BCC 2(PC)
|
|
||||||
NEG R0, R0
|
|
||||||
MOVW R0, ret+24(FP)
|
|
||||||
RET
|
|
||||||
|
|
||||||
TEXT runtime·usleep(SB),NOSPLIT,$24-4
|
|
||||||
MOVWU usec+0(FP), R3
|
|
||||||
MOVD R3, R5
|
|
||||||
MOVW $1000000, R4
|
|
||||||
UDIV R4, R3
|
|
||||||
MOVD R3, 8(RSP) // tv_sec
|
|
||||||
MUL R3, R4
|
|
||||||
SUB R4, R5
|
|
||||||
MOVW $1000, R4
|
|
||||||
MUL R4, R5
|
|
||||||
MOVD R5, 16(RSP) // tv_nsec
|
|
||||||
|
|
||||||
ADD $8, RSP, R0 // arg 1 - rqtp
|
|
||||||
MOVD $0, R1 // arg 2 - rmtp
|
|
||||||
MOVD $91, R8 // sys_nanosleep
|
|
||||||
INVOKE_SYSCALL
|
|
||||||
RET
|
|
||||||
|
|
||||||
TEXT runtime·getthrid(SB),NOSPLIT,$0-4
|
|
||||||
MOVD $299, R8 // sys_getthrid
|
|
||||||
INVOKE_SYSCALL
|
|
||||||
MOVW R0, ret+0(FP)
|
|
||||||
RET
|
|
||||||
|
|
||||||
TEXT runtime·thrkill(SB),NOSPLIT,$0-16
|
|
||||||
MOVW tid+0(FP), R0 // arg 1 - tid
|
|
||||||
MOVD sig+8(FP), R1 // arg 2 - signum
|
|
||||||
MOVW $0, R2 // arg 3 - tcb
|
|
||||||
MOVD $119, R8 // sys_thrkill
|
|
||||||
INVOKE_SYSCALL
|
|
||||||
RET
|
|
||||||
|
|
||||||
TEXT runtime·raiseproc(SB),NOSPLIT,$0
|
|
||||||
MOVD $20, R8 // sys_getpid
|
|
||||||
INVOKE_SYSCALL
|
|
||||||
// arg 1 - pid, already in R0
|
|
||||||
MOVW sig+0(FP), R1 // arg 2 - signum
|
|
||||||
MOVD $122, R8 // sys_kill
|
|
||||||
INVOKE_SYSCALL
|
|
||||||
RET
|
|
||||||
|
|
||||||
TEXT runtime·mmap(SB),NOSPLIT,$0
|
|
||||||
MOVD addr+0(FP), R0 // arg 1 - addr
|
|
||||||
MOVD n+8(FP), R1 // arg 2 - len
|
|
||||||
MOVW prot+16(FP), R2 // arg 3 - prot
|
|
||||||
MOVW flags+20(FP), R3 // arg 4 - flags
|
|
||||||
MOVW fd+24(FP), R4 // arg 5 - fd
|
|
||||||
MOVW $0, R5 // arg 6 - pad
|
|
||||||
MOVW off+28(FP), R6 // arg 7 - offset
|
|
||||||
MOVD $197, R8 // sys_mmap
|
|
||||||
INVOKE_SYSCALL
|
|
||||||
MOVD $0, R1
|
MOVD $0, R1
|
||||||
BCC 3(PC)
|
CMP $-1, R0
|
||||||
MOVD R0, R1 // if error, move to R1
|
BNE noerr
|
||||||
|
CALL libc_errno(SB)
|
||||||
|
MOVW (R0), R1 // errno
|
||||||
MOVD $0, R0
|
MOVD $0, R0
|
||||||
MOVD R0, p+32(FP)
|
noerr:
|
||||||
MOVD R1, err+40(FP)
|
MOVD R0, 32(R19)
|
||||||
|
MOVD R1, 40(R19)
|
||||||
RET
|
RET
|
||||||
|
|
||||||
TEXT runtime·munmap(SB),NOSPLIT,$0
|
TEXT runtime·munmap_trampoline(SB),NOSPLIT,$0
|
||||||
MOVD addr+0(FP), R0 // arg 1 - addr
|
MOVD 8(R0), R1 // arg 2 - len
|
||||||
MOVD n+8(FP), R1 // arg 2 - len
|
MOVD 0(R0), R0 // arg 1 - addr
|
||||||
MOVD $73, R8 // sys_munmap
|
CALL libc_munmap(SB)
|
||||||
INVOKE_SYSCALL
|
CMP $-1, R0
|
||||||
BCC 3(PC)
|
BNE 3(PC)
|
||||||
|
MOVD $0, R0 // crash on failure
|
||||||
|
MOVD R0, (R0)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT runtime·madvise_trampoline(SB), NOSPLIT, $0
|
||||||
|
MOVD 8(R0), R1 // arg 2 - len
|
||||||
|
MOVW 16(R0), R2 // arg 3 - advice
|
||||||
|
MOVD 0(R0), R0 // arg 1 - addr
|
||||||
|
CALL libc_madvise(SB)
|
||||||
|
// ignore failure - maybe pages are locked
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT runtime·open_trampoline(SB),NOSPLIT,$0
|
||||||
|
MOVW 8(R0), R1 // arg 2 - flags
|
||||||
|
MOVW 12(R0), R2 // arg 3 - mode
|
||||||
|
MOVD 0(R0), R0 // arg 1 - path
|
||||||
|
MOVD $0, R3 // varargs
|
||||||
|
CALL libc_open(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT runtime·close_trampoline(SB),NOSPLIT,$0
|
||||||
|
MOVD 0(R0), R0 // arg 1 - fd
|
||||||
|
CALL libc_close(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT runtime·read_trampoline(SB),NOSPLIT,$0
|
||||||
|
MOVD 8(R0), R1 // arg 2 - buf
|
||||||
|
MOVW 16(R0), R2 // arg 3 - count
|
||||||
|
MOVW 0(R0), R0 // arg 1 - fd
|
||||||
|
CALL libc_read(SB)
|
||||||
|
CMP $-1, R0
|
||||||
|
BNE noerr
|
||||||
|
CALL libc_errno(SB)
|
||||||
|
MOVW (R0), R0 // errno
|
||||||
|
NEG R0, R0 // caller expects negative errno value
|
||||||
|
noerr:
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT runtime·write_trampoline(SB),NOSPLIT,$0
|
||||||
|
MOVD 8(R0), R1 // arg 2 - buf
|
||||||
|
MOVW 16(R0), R2 // arg 3 - count
|
||||||
|
MOVW 0(R0), R0 // arg 1 - fd
|
||||||
|
CALL libc_write(SB)
|
||||||
|
CMP $-1, R0
|
||||||
|
BNE noerr
|
||||||
|
CALL libc_errno(SB)
|
||||||
|
MOVW (R0), R0 // errno
|
||||||
|
NEG R0, R0 // caller expects negative errno value
|
||||||
|
noerr:
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT runtime·pipe2_trampoline(SB),NOSPLIT,$0
|
||||||
|
MOVW 8(R0), R1 // arg 2 - flags
|
||||||
|
MOVD 0(R0), R0 // arg 1 - filedes
|
||||||
|
CALL libc_pipe2(SB)
|
||||||
|
CMP $-1, R0
|
||||||
|
BNE noerr
|
||||||
|
CALL libc_errno(SB)
|
||||||
|
MOVW (R0), R0 // errno
|
||||||
|
NEG R0, R0 // caller expects negative errno value
|
||||||
|
noerr:
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT runtime·setitimer_trampoline(SB),NOSPLIT,$0
|
||||||
|
MOVD 8(R0), R1 // arg 2 - new
|
||||||
|
MOVD 16(R0), R2 // arg 3 - old
|
||||||
|
MOVW 0(R0), R0 // arg 1 - which
|
||||||
|
CALL libc_setitimer(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT runtime·usleep_trampoline(SB),NOSPLIT,$0
|
||||||
|
MOVD 0(R0), R0 // arg 1 - usec
|
||||||
|
CALL libc_usleep(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT runtime·sysctl_trampoline(SB),NOSPLIT,$0
|
||||||
|
MOVW 8(R0), R1 // arg 2 - miblen
|
||||||
|
MOVD 16(R0), R2 // arg 3 - out
|
||||||
|
MOVD 24(R0), R3 // arg 4 - size
|
||||||
|
MOVD 32(R0), R4 // arg 5 - dst
|
||||||
|
MOVD 40(R0), R5 // arg 6 - ndst
|
||||||
|
MOVD 0(R0), R0 // arg 1 - mib
|
||||||
|
CALL libc_sysctl(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT runtime·kqueue_trampoline(SB),NOSPLIT,$0
|
||||||
|
CALL libc_kqueue(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT runtime·kevent_trampoline(SB),NOSPLIT,$0
|
||||||
|
MOVD 8(R0), R1 // arg 2 - keventt
|
||||||
|
MOVW 16(R0), R2 // arg 3 - nch
|
||||||
|
MOVD 24(R0), R3 // arg 4 - ev
|
||||||
|
MOVW 32(R0), R4 // arg 5 - nev
|
||||||
|
MOVD 40(R0), R5 // arg 6 - ts
|
||||||
|
MOVW 0(R0), R0 // arg 1 - kq
|
||||||
|
CALL libc_kevent(SB)
|
||||||
|
CMP $-1, R0
|
||||||
|
BNE noerr
|
||||||
|
CALL libc_errno(SB)
|
||||||
|
MOVW (R0), R0 // errno
|
||||||
|
NEG R0, R0 // caller expects negative errno value
|
||||||
|
noerr:
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT runtime·clock_gettime_trampoline(SB),NOSPLIT,$0
|
||||||
|
MOVD 8(R0), R1 // arg 2 - tp
|
||||||
|
MOVD 0(R0), R0 // arg 1 - clock_id
|
||||||
|
CALL libc_clock_gettime(SB)
|
||||||
|
CMP $-1, R0
|
||||||
|
BNE 3(PC)
|
||||||
|
MOVD $0, R0 // crash on failure
|
||||||
|
MOVD R0, (R0)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT runtime·fcntl_trampoline(SB),NOSPLIT,$0
|
||||||
|
MOVW 4(R0), R1 // arg 2 - cmd
|
||||||
|
MOVW 8(R0), R2 // arg 3 - arg
|
||||||
|
MOVW 0(R0), R0 // arg 1 - fd
|
||||||
|
MOVD $0, R3 // vararg
|
||||||
|
CALL libc_fcntl(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT runtime·sigaction_trampoline(SB),NOSPLIT,$0
|
||||||
|
MOVD 8(R0), R1 // arg 2 - new
|
||||||
|
MOVD 16(R0), R2 // arg 3 - old
|
||||||
|
MOVW 0(R0), R0 // arg 1 - sig
|
||||||
|
CALL libc_sigaction(SB)
|
||||||
|
CMP $-1, R0
|
||||||
|
BNE 3(PC)
|
||||||
MOVD $0, R0 // crash on syscall failure
|
MOVD $0, R0 // crash on syscall failure
|
||||||
MOVD R0, (R0)
|
MOVD R0, (R0)
|
||||||
RET
|
RET
|
||||||
|
|
||||||
TEXT runtime·madvise(SB),NOSPLIT,$0
|
TEXT runtime·sigprocmask_trampoline(SB),NOSPLIT,$0
|
||||||
MOVD addr+0(FP), R0 // arg 1 - addr
|
MOVD 8(R0), R1 // arg 2 - new
|
||||||
MOVD n+8(FP), R1 // arg 2 - len
|
MOVD 16(R0), R2 // arg 3 - old
|
||||||
MOVW flags+16(FP), R2 // arg 2 - flags
|
MOVW 0(R0), R0 // arg 1 - how
|
||||||
MOVD $75, R8 // sys_madvise
|
CALL libc_pthread_sigmask(SB)
|
||||||
INVOKE_SYSCALL
|
CMP $-1, R0
|
||||||
BCC 2(PC)
|
BNE 3(PC)
|
||||||
MOVW $-1, R0
|
MOVD $0, R0 // crash on syscall failure
|
||||||
MOVW R0, ret+24(FP)
|
|
||||||
RET
|
|
||||||
|
|
||||||
TEXT runtime·setitimer(SB),NOSPLIT,$0
|
|
||||||
MOVW mode+0(FP), R0 // arg 1 - mode
|
|
||||||
MOVD new+8(FP), R1 // arg 2 - new value
|
|
||||||
MOVD old+16(FP), R2 // arg 3 - old value
|
|
||||||
MOVD $69, R8 // sys_setitimer
|
|
||||||
INVOKE_SYSCALL
|
|
||||||
RET
|
|
||||||
|
|
||||||
// func walltime1() (sec int64, nsec int32)
|
|
||||||
TEXT runtime·walltime1(SB), NOSPLIT, $32
|
|
||||||
MOVW CLOCK_REALTIME, R0 // arg 1 - clock_id
|
|
||||||
MOVD $8(RSP), R1 // arg 2 - tp
|
|
||||||
MOVD $87, R8 // sys_clock_gettime
|
|
||||||
INVOKE_SYSCALL
|
|
||||||
|
|
||||||
MOVD 8(RSP), R0 // sec
|
|
||||||
MOVD 16(RSP), R1 // nsec
|
|
||||||
MOVD R0, sec+0(FP)
|
|
||||||
MOVW R1, nsec+8(FP)
|
|
||||||
|
|
||||||
RET
|
|
||||||
|
|
||||||
// int64 nanotime1(void) so really
|
|
||||||
// void nanotime1(int64 *nsec)
|
|
||||||
TEXT runtime·nanotime1(SB),NOSPLIT,$32
|
|
||||||
MOVW CLOCK_MONOTONIC, R0 // arg 1 - clock_id
|
|
||||||
MOVD $8(RSP), R1 // arg 2 - tp
|
|
||||||
MOVD $87, R8 // sys_clock_gettime
|
|
||||||
INVOKE_SYSCALL
|
|
||||||
|
|
||||||
MOVW 8(RSP), R3 // sec
|
|
||||||
MOVW 16(RSP), R5 // nsec
|
|
||||||
|
|
||||||
MOVD $1000000000, R4
|
|
||||||
MUL R4, R3
|
|
||||||
ADD R5, R3
|
|
||||||
MOVD R3, ret+0(FP)
|
|
||||||
RET
|
|
||||||
|
|
||||||
TEXT runtime·sigaction(SB),NOSPLIT,$0
|
|
||||||
MOVW sig+0(FP), R0 // arg 1 - signum
|
|
||||||
MOVD new+8(FP), R1 // arg 2 - new sigaction
|
|
||||||
MOVD old+16(FP), R2 // arg 3 - old sigaction
|
|
||||||
MOVD $46, R8 // sys_sigaction
|
|
||||||
INVOKE_SYSCALL
|
|
||||||
BCC 3(PC)
|
|
||||||
MOVD $3, R0 // crash on syscall failure
|
|
||||||
MOVD R0, (R0)
|
MOVD R0, (R0)
|
||||||
RET
|
RET
|
||||||
|
|
||||||
TEXT runtime·obsdsigprocmask(SB),NOSPLIT,$0
|
TEXT runtime·sigaltstack_trampoline(SB),NOSPLIT,$0
|
||||||
MOVW how+0(FP), R0 // arg 1 - mode
|
MOVD 8(R0), R1 // arg 2 - old
|
||||||
MOVW new+4(FP), R1 // arg 2 - new
|
MOVD 0(R0), R0 // arg 1 - new
|
||||||
MOVD $48, R8 // sys_sigprocmask
|
CALL libc_sigaltstack(SB)
|
||||||
INVOKE_SYSCALL
|
CMP $-1, R0
|
||||||
BCC 3(PC)
|
BNE 3(PC)
|
||||||
MOVD $3, R8 // crash on syscall failure
|
MOVD $0, R0 // crash on syscall failure
|
||||||
MOVD R8, (R8)
|
MOVD R0, (R0)
|
||||||
MOVW R0, ret+8(FP)
|
|
||||||
RET
|
RET
|
||||||
|
|
||||||
TEXT runtime·sigaltstack(SB),NOSPLIT,$0
|
// syscall calls a function in libc on behalf of the syscall package.
|
||||||
MOVD new+0(FP), R0 // arg 1 - new sigaltstack
|
// syscall takes a pointer to a struct like:
|
||||||
MOVD old+8(FP), R1 // arg 2 - old sigaltstack
|
// struct {
|
||||||
MOVD $288, R8 // sys_sigaltstack
|
// fn uintptr
|
||||||
INVOKE_SYSCALL
|
// a1 uintptr
|
||||||
BCC 3(PC)
|
// a2 uintptr
|
||||||
MOVD $0, R8 // crash on syscall failure
|
// a3 uintptr
|
||||||
MOVD R8, (R8)
|
// r1 uintptr
|
||||||
|
// r2 uintptr
|
||||||
|
// err uintptr
|
||||||
|
// }
|
||||||
|
// syscall must be called on the g0 stack with the
|
||||||
|
// C calling convention (use libcCall).
|
||||||
|
//
|
||||||
|
// syscall expects a 32-bit result and tests for 32-bit -1
|
||||||
|
// to decide there was an error.
|
||||||
|
TEXT runtime·syscall(SB),NOSPLIT,$0
|
||||||
|
MOVD R0, R19 // pointer to args
|
||||||
|
|
||||||
|
MOVD (0*8)(R19), R11 // fn
|
||||||
|
MOVD (1*8)(R19), R0 // a1
|
||||||
|
MOVD (2*8)(R19), R1 // a2
|
||||||
|
MOVD (3*8)(R19), R2 // a3
|
||||||
|
MOVD $0, R3 // vararg
|
||||||
|
|
||||||
|
CALL R11
|
||||||
|
|
||||||
|
MOVD R0, (4*8)(R19) // r1
|
||||||
|
MOVD R1, (5*8)(R19) // r2
|
||||||
|
|
||||||
|
// Standard libc functions return -1 on error
|
||||||
|
// and set errno.
|
||||||
|
CMPW $-1, R0
|
||||||
|
BNE ok
|
||||||
|
|
||||||
|
// Get error code from libc.
|
||||||
|
CALL libc_errno(SB)
|
||||||
|
MOVW (R0), R0
|
||||||
|
MOVD R0, (6*8)(R19) // err
|
||||||
|
|
||||||
|
ok:
|
||||||
RET
|
RET
|
||||||
|
|
||||||
TEXT runtime·osyield(SB),NOSPLIT,$0
|
// syscallX calls a function in libc on behalf of the syscall package.
|
||||||
MOVD $298, R8 // sys_sched_yield
|
// syscallX takes a pointer to a struct like:
|
||||||
INVOKE_SYSCALL
|
// struct {
|
||||||
|
// fn uintptr
|
||||||
|
// a1 uintptr
|
||||||
|
// a2 uintptr
|
||||||
|
// a3 uintptr
|
||||||
|
// r1 uintptr
|
||||||
|
// r2 uintptr
|
||||||
|
// err uintptr
|
||||||
|
// }
|
||||||
|
// syscallX must be called on the g0 stack with the
|
||||||
|
// C calling convention (use libcCall).
|
||||||
|
//
|
||||||
|
// syscallX is like syscall but expects a 64-bit result
|
||||||
|
// and tests for 64-bit -1 to decide there was an error.
|
||||||
|
TEXT runtime·syscallX(SB),NOSPLIT,$0
|
||||||
|
MOVD R0, R19 // pointer to args
|
||||||
|
|
||||||
|
MOVD (0*8)(R19), R11 // fn
|
||||||
|
MOVD (1*8)(R19), R0 // a1
|
||||||
|
MOVD (2*8)(R19), R1 // a2
|
||||||
|
MOVD (3*8)(R19), R2 // a3
|
||||||
|
MOVD $0, R3 // vararg
|
||||||
|
|
||||||
|
CALL R11
|
||||||
|
|
||||||
|
MOVD R0, (4*8)(R19) // r1
|
||||||
|
MOVD R1, (5*8)(R19) // r2
|
||||||
|
|
||||||
|
// Standard libc functions return -1 on error
|
||||||
|
// and set errno.
|
||||||
|
CMP $-1, R0
|
||||||
|
BNE ok
|
||||||
|
|
||||||
|
// Get error code from libc.
|
||||||
|
CALL libc_errno(SB)
|
||||||
|
MOVW (R0), R0
|
||||||
|
MOVD R0, (6*8)(R19) // err
|
||||||
|
|
||||||
|
ok:
|
||||||
RET
|
RET
|
||||||
|
|
||||||
TEXT runtime·thrsleep(SB),NOSPLIT,$0
|
// syscall6 calls a function in libc on behalf of the syscall package.
|
||||||
MOVD ident+0(FP), R0 // arg 1 - ident
|
// syscall6 takes a pointer to a struct like:
|
||||||
MOVW clock_id+8(FP), R1 // arg 2 - clock_id
|
// struct {
|
||||||
MOVD tsp+16(FP), R2 // arg 3 - tsp
|
// fn uintptr
|
||||||
MOVD lock+24(FP), R3 // arg 4 - lock
|
// a1 uintptr
|
||||||
MOVD abort+32(FP), R4 // arg 5 - abort
|
// a2 uintptr
|
||||||
MOVD $94, R8 // sys___thrsleep
|
// a3 uintptr
|
||||||
INVOKE_SYSCALL
|
// a4 uintptr
|
||||||
MOVW R0, ret+40(FP)
|
// a5 uintptr
|
||||||
|
// a6 uintptr
|
||||||
|
// r1 uintptr
|
||||||
|
// r2 uintptr
|
||||||
|
// err uintptr
|
||||||
|
// }
|
||||||
|
// syscall6 must be called on the g0 stack with the
|
||||||
|
// C calling convention (use libcCall).
|
||||||
|
//
|
||||||
|
// syscall6 expects a 32-bit result and tests for 32-bit -1
|
||||||
|
// to decide there was an error.
|
||||||
|
TEXT runtime·syscall6(SB),NOSPLIT,$0
|
||||||
|
MOVD R0, R19 // pointer to args
|
||||||
|
|
||||||
|
MOVD (0*8)(R19), R11 // fn
|
||||||
|
MOVD (1*8)(R19), R0 // a1
|
||||||
|
MOVD (2*8)(R19), R1 // a2
|
||||||
|
MOVD (3*8)(R19), R2 // a3
|
||||||
|
MOVD (4*8)(R19), R3 // a4
|
||||||
|
MOVD (5*8)(R19), R4 // a5
|
||||||
|
MOVD (6*8)(R19), R5 // a6
|
||||||
|
MOVD $0, R6 // vararg
|
||||||
|
|
||||||
|
CALL R11
|
||||||
|
|
||||||
|
MOVD R0, (7*8)(R19) // r1
|
||||||
|
MOVD R1, (8*8)(R19) // r2
|
||||||
|
|
||||||
|
// Standard libc functions return -1 on error
|
||||||
|
// and set errno.
|
||||||
|
CMPW $-1, R0
|
||||||
|
BNE ok
|
||||||
|
|
||||||
|
// Get error code from libc.
|
||||||
|
CALL libc_errno(SB)
|
||||||
|
MOVW (R0), R0
|
||||||
|
MOVD R0, (9*8)(R19) // err
|
||||||
|
|
||||||
|
ok:
|
||||||
RET
|
RET
|
||||||
|
|
||||||
TEXT runtime·thrwakeup(SB),NOSPLIT,$0
|
// syscall6X calls a function in libc on behalf of the syscall package.
|
||||||
MOVD ident+0(FP), R0 // arg 1 - ident
|
// syscall6X takes a pointer to a struct like:
|
||||||
MOVW n+8(FP), R1 // arg 2 - n
|
// struct {
|
||||||
MOVD $301, R8 // sys___thrwakeup
|
// fn uintptr
|
||||||
INVOKE_SYSCALL
|
// a1 uintptr
|
||||||
MOVW R0, ret+16(FP)
|
// a2 uintptr
|
||||||
|
// a3 uintptr
|
||||||
|
// a4 uintptr
|
||||||
|
// a5 uintptr
|
||||||
|
// a6 uintptr
|
||||||
|
// r1 uintptr
|
||||||
|
// r2 uintptr
|
||||||
|
// err uintptr
|
||||||
|
// }
|
||||||
|
// syscall6X must be called on the g0 stack with the
|
||||||
|
// C calling convention (use libcCall).
|
||||||
|
//
|
||||||
|
// syscall6X is like syscall6 but expects a 64-bit result
|
||||||
|
// and tests for 64-bit -1 to decide there was an error.
|
||||||
|
TEXT runtime·syscall6X(SB),NOSPLIT,$0
|
||||||
|
MOVD R0, R19 // pointer to args
|
||||||
|
|
||||||
|
MOVD (0*8)(R19), R11 // fn
|
||||||
|
MOVD (1*8)(R19), R0 // a1
|
||||||
|
MOVD (2*8)(R19), R1 // a2
|
||||||
|
MOVD (3*8)(R19), R2 // a3
|
||||||
|
MOVD (4*8)(R19), R3 // a4
|
||||||
|
MOVD (5*8)(R19), R4 // a5
|
||||||
|
MOVD (6*8)(R19), R5 // a6
|
||||||
|
MOVD $0, R6 // vararg
|
||||||
|
|
||||||
|
CALL R11
|
||||||
|
|
||||||
|
MOVD R0, (7*8)(R19) // r1
|
||||||
|
MOVD R1, (8*8)(R19) // r2
|
||||||
|
|
||||||
|
// Standard libc functions return -1 on error
|
||||||
|
// and set errno.
|
||||||
|
CMP $-1, R0
|
||||||
|
BNE ok
|
||||||
|
|
||||||
|
// Get error code from libc.
|
||||||
|
CALL libc_errno(SB)
|
||||||
|
MOVW (R0), R0
|
||||||
|
MOVD R0, (9*8)(R19) // err
|
||||||
|
|
||||||
|
ok:
|
||||||
RET
|
RET
|
||||||
|
|
||||||
TEXT runtime·sysctl(SB),NOSPLIT,$0
|
// syscall10 calls a function in libc on behalf of the syscall package.
|
||||||
MOVD mib+0(FP), R0 // arg 1 - mib
|
// syscall10 takes a pointer to a struct like:
|
||||||
MOVW miblen+8(FP), R1 // arg 2 - miblen
|
// struct {
|
||||||
MOVD out+16(FP), R2 // arg 3 - out
|
// fn uintptr
|
||||||
MOVD size+24(FP), R3 // arg 4 - size
|
// a1 uintptr
|
||||||
MOVD dst+32(FP), R4 // arg 5 - dest
|
// a2 uintptr
|
||||||
MOVD ndst+40(FP), R5 // arg 6 - newlen
|
// a3 uintptr
|
||||||
MOVD $202, R8 // sys___sysctl
|
// a4 uintptr
|
||||||
INVOKE_SYSCALL
|
// a5 uintptr
|
||||||
BCC 2(PC)
|
// a6 uintptr
|
||||||
NEG R0, R0
|
// a7 uintptr
|
||||||
MOVW R0, ret+48(FP)
|
// a8 uintptr
|
||||||
|
// a9 uintptr
|
||||||
|
// a10 uintptr
|
||||||
|
// r1 uintptr
|
||||||
|
// r2 uintptr
|
||||||
|
// err uintptr
|
||||||
|
// }
|
||||||
|
// syscall10 must be called on the g0 stack with the
|
||||||
|
// C calling convention (use libcCall).
|
||||||
|
TEXT runtime·syscall10(SB),NOSPLIT,$0
|
||||||
|
MOVD R0, R19 // pointer to args
|
||||||
|
|
||||||
|
MOVD (0*8)(R19), R11 // fn
|
||||||
|
MOVD (1*8)(R19), R0 // a1
|
||||||
|
MOVD (2*8)(R19), R1 // a2
|
||||||
|
MOVD (3*8)(R19), R2 // a3
|
||||||
|
MOVD (4*8)(R19), R3 // a4
|
||||||
|
MOVD (5*8)(R19), R4 // a5
|
||||||
|
MOVD (6*8)(R19), R5 // a6
|
||||||
|
MOVD (7*8)(R19), R6 // a7
|
||||||
|
MOVD (8*8)(R19), R7 // a8
|
||||||
|
MOVD (9*8)(R19), R8 // a9
|
||||||
|
MOVD (10*8)(R19), R9 // a10
|
||||||
|
MOVD $0, R10 // vararg
|
||||||
|
|
||||||
|
CALL R11
|
||||||
|
|
||||||
|
MOVD R0, (11*8)(R19) // r1
|
||||||
|
MOVD R1, (12*8)(R19) // r2
|
||||||
|
|
||||||
|
// Standard libc functions return -1 on error
|
||||||
|
// and set errno.
|
||||||
|
CMPW $-1, R0
|
||||||
|
BNE ok
|
||||||
|
|
||||||
|
// Get error code from libc.
|
||||||
|
CALL libc_errno(SB)
|
||||||
|
MOVW (R0), R0
|
||||||
|
MOVD R0, (13*8)(R19) // err
|
||||||
|
|
||||||
|
ok:
|
||||||
RET
|
RET
|
||||||
|
|
||||||
// int32 runtime·kqueue(void);
|
// syscall10X calls a function in libc on behalf of the syscall package.
|
||||||
TEXT runtime·kqueue(SB),NOSPLIT,$0
|
// syscall10X takes a pointer to a struct like:
|
||||||
MOVD $269, R8 // sys_kqueue
|
// struct {
|
||||||
INVOKE_SYSCALL
|
// fn uintptr
|
||||||
BCC 2(PC)
|
// a1 uintptr
|
||||||
NEG R0, R0
|
// a2 uintptr
|
||||||
MOVW R0, ret+0(FP)
|
// a3 uintptr
|
||||||
RET
|
// a4 uintptr
|
||||||
|
// a5 uintptr
|
||||||
|
// a6 uintptr
|
||||||
|
// a7 uintptr
|
||||||
|
// a8 uintptr
|
||||||
|
// a9 uintptr
|
||||||
|
// a10 uintptr
|
||||||
|
// r1 uintptr
|
||||||
|
// r2 uintptr
|
||||||
|
// err uintptr
|
||||||
|
// }
|
||||||
|
// syscall10X must be called on the g0 stack with the
|
||||||
|
// C calling convention (use libcCall).
|
||||||
|
//
|
||||||
|
// syscall10X is like syscall10 but expects a 64-bit result
|
||||||
|
// and tests for 64-bit -1 to decide there was an error.
|
||||||
|
TEXT runtime·syscall10X(SB),NOSPLIT,$0
|
||||||
|
MOVD R0, R19 // pointer to args
|
||||||
|
|
||||||
// int32 runtime·kevent(int kq, Kevent *changelist, int nchanges, Kevent *eventlist, int nevents, Timespec *timeout);
|
MOVD (0*8)(R19), R11 // fn
|
||||||
TEXT runtime·kevent(SB),NOSPLIT,$0
|
MOVD (1*8)(R19), R0 // a1
|
||||||
MOVW kq+0(FP), R0 // arg 1 - kq
|
MOVD (2*8)(R19), R1 // a2
|
||||||
MOVD ch+8(FP), R1 // arg 2 - changelist
|
MOVD (3*8)(R19), R2 // a3
|
||||||
MOVW nch+16(FP), R2 // arg 3 - nchanges
|
MOVD (4*8)(R19), R3 // a4
|
||||||
MOVD ev+24(FP), R3 // arg 4 - eventlist
|
MOVD (5*8)(R19), R4 // a5
|
||||||
MOVW nev+32(FP), R4 // arg 5 - nevents
|
MOVD (6*8)(R19), R5 // a6
|
||||||
MOVD ts+40(FP), R5 // arg 6 - timeout
|
MOVD (7*8)(R19), R6 // a7
|
||||||
MOVD $72, R8 // sys_kevent
|
MOVD (8*8)(R19), R7 // a8
|
||||||
INVOKE_SYSCALL
|
MOVD (9*8)(R19), R8 // a9
|
||||||
BCC 2(PC)
|
MOVD (10*8)(R19), R9 // a10
|
||||||
NEG R0, R0
|
MOVD $0, R10 // vararg
|
||||||
MOVW R0, ret+48(FP)
|
|
||||||
RET
|
|
||||||
|
|
||||||
// func closeonexec(fd int32)
|
CALL R11
|
||||||
TEXT runtime·closeonexec(SB),NOSPLIT,$0
|
|
||||||
MOVW fd+0(FP), R0 // arg 1 - fd
|
|
||||||
MOVD $2, R1 // arg 2 - cmd (F_SETFD)
|
|
||||||
MOVD $1, R2 // arg 3 - arg (FD_CLOEXEC)
|
|
||||||
MOVD $92, R8 // sys_fcntl
|
|
||||||
INVOKE_SYSCALL
|
|
||||||
RET
|
|
||||||
|
|
||||||
// func runtime·setNonblock(int32 fd)
|
MOVD R0, (11*8)(R19) // r1
|
||||||
TEXT runtime·setNonblock(SB),NOSPLIT|NOFRAME,$0-4
|
MOVD R1, (12*8)(R19) // r2
|
||||||
MOVW fd+0(FP), R0 // arg 1 - fd
|
|
||||||
MOVD $3, R1 // arg 2 - cmd (F_GETFL)
|
// Standard libc functions return -1 on error
|
||||||
MOVD $0, R2 // arg 3
|
// and set errno.
|
||||||
MOVD $92, R8 // sys_fcntl
|
CMP $-1, R0
|
||||||
INVOKE_SYSCALL
|
BNE ok
|
||||||
MOVD $4, R2 // O_NONBLOCK
|
|
||||||
ORR R0, R2 // arg 3 - flags
|
// Get error code from libc.
|
||||||
MOVW fd+0(FP), R0 // arg 1 - fd
|
CALL libc_errno(SB)
|
||||||
MOVD $4, R1 // arg 2 - cmd (F_SETFL)
|
MOVW (R0), R0
|
||||||
MOVD $92, R8 // sys_fcntl
|
MOVD R0, (13*8)(R19) // err
|
||||||
INVOKE_SYSCALL
|
|
||||||
|
ok:
|
||||||
RET
|
RET
|
||||||
|
|
|
||||||
39
src/runtime/testdata/testprog/deadlock.go
vendored
39
src/runtime/testdata/testprog/deadlock.go
vendored
|
|
@ -25,6 +25,7 @@ func init() {
|
||||||
register("RecursivePanic2", RecursivePanic2)
|
register("RecursivePanic2", RecursivePanic2)
|
||||||
register("RecursivePanic3", RecursivePanic3)
|
register("RecursivePanic3", RecursivePanic3)
|
||||||
register("RecursivePanic4", RecursivePanic4)
|
register("RecursivePanic4", RecursivePanic4)
|
||||||
|
register("RecursivePanic5", RecursivePanic5)
|
||||||
register("GoexitExit", GoexitExit)
|
register("GoexitExit", GoexitExit)
|
||||||
register("GoNil", GoNil)
|
register("GoNil", GoNil)
|
||||||
register("MainGoroutineID", MainGoroutineID)
|
register("MainGoroutineID", MainGoroutineID)
|
||||||
|
|
@ -160,6 +161,44 @@ func RecursivePanic4() {
|
||||||
panic("first panic")
|
panic("first panic")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test case where we have an open-coded defer higher up the stack (in two), and
|
||||||
|
// in the current function (three) we recover in a defer while we still have
|
||||||
|
// another defer to be processed.
|
||||||
|
func RecursivePanic5() {
|
||||||
|
one()
|
||||||
|
panic("third panic")
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:noinline
|
||||||
|
func one() {
|
||||||
|
two()
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:noinline
|
||||||
|
func two() {
|
||||||
|
defer func() {
|
||||||
|
}()
|
||||||
|
|
||||||
|
three()
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:noinline
|
||||||
|
func three() {
|
||||||
|
defer func() {
|
||||||
|
}()
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
fmt.Println(recover())
|
||||||
|
}()
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
fmt.Println(recover())
|
||||||
|
panic("second panic")
|
||||||
|
}()
|
||||||
|
|
||||||
|
panic("first panic")
|
||||||
|
}
|
||||||
|
|
||||||
func GoexitExit() {
|
func GoexitExit() {
|
||||||
println("t1")
|
println("t1")
|
||||||
go func() {
|
go func() {
|
||||||
|
|
|
||||||
19
src/runtime/testdata/testwinsignal/main.go
vendored
Normal file
19
src/runtime/testdata/testwinsignal/main.go
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
c := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(c)
|
||||||
|
|
||||||
|
fmt.Println("ready")
|
||||||
|
sig := <-c
|
||||||
|
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
fmt.Println(sig)
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// +build netbsd openbsd
|
// +build netbsd
|
||||||
|
|
||||||
// Copyright 2016 The Go Authors. All rights reserved.
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
#include "funcdata.h"
|
#include "funcdata.h"
|
||||||
|
|
||||||
//
|
//
|
||||||
// Syscall9 support for AMD64, NetBSD and OpenBSD
|
// Syscall9 support for AMD64, NetBSD
|
||||||
//
|
//
|
||||||
|
|
||||||
// func Syscall9(trap int64, a1, a2, a3, a4, a5, a6, a7, a8, a9 int64) (r1, r2, err int64);
|
// func Syscall9(trap int64, a1, a2, a3, a4, a5, a6, a7, a8, a9 int64) (r1, r2, err int64);
|
||||||
|
|
|
||||||
32
src/syscall/asm_openbsd_amd64.s
Normal file
32
src/syscall/asm_openbsd_amd64.s
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// System call support for AMD64, OpenBSD
|
||||||
|
//
|
||||||
|
|
||||||
|
// Provide these function names via assembly so they are provided as ABI0,
|
||||||
|
// rather than ABIInternal.
|
||||||
|
|
||||||
|
// func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
|
||||||
|
TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||||
|
JMP ·syscallInternal(SB)
|
||||||
|
|
||||||
|
// func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
|
||||||
|
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||||
|
JMP ·syscall6Internal(SB)
|
||||||
|
|
||||||
|
// func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
|
||||||
|
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||||
|
JMP ·rawSyscallInternal(SB)
|
||||||
|
|
||||||
|
// func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
|
||||||
|
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||||
|
JMP ·rawSyscall6Internal(SB)
|
||||||
|
|
||||||
|
// func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno)
|
||||||
|
TEXT ·Syscall9(SB),NOSPLIT,$0-104
|
||||||
|
JMP ·syscall9Internal(SB)
|
||||||
|
|
@ -4,127 +4,29 @@
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
// See comment in runtime/sys_openbsd_arm64.s re this construction.
|
//
|
||||||
#define INVOKE_SYSCALL \
|
// System call support for ARM64, OpenBSD
|
||||||
SVC; \
|
//
|
||||||
NOOP; \
|
|
||||||
NOOP
|
|
||||||
|
|
||||||
// func Syscall(trap int64, a1, a2, a3 int64) (r1, r2, err int64);
|
// Provide these function names via assembly so they are provided as ABI0,
|
||||||
|
// rather than ABIInternal.
|
||||||
|
|
||||||
|
// func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
|
||||||
TEXT ·Syscall(SB),NOSPLIT,$0-56
|
TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||||
BL runtime·entersyscall(SB)
|
JMP ·syscallInternal(SB)
|
||||||
MOVD a1+8(FP), R0
|
|
||||||
MOVD a2+16(FP), R1
|
|
||||||
MOVD a3+24(FP), R2
|
|
||||||
MOVD $0, R3
|
|
||||||
MOVD $0, R4
|
|
||||||
MOVD $0, R5
|
|
||||||
MOVD trap+0(FP), R8 // syscall number
|
|
||||||
INVOKE_SYSCALL
|
|
||||||
BCC ok
|
|
||||||
MOVD $-1, R4
|
|
||||||
MOVD R4, r1+32(FP) // r1
|
|
||||||
MOVD ZR, r2+40(FP) // r2
|
|
||||||
MOVD R0, err+48(FP) // errno
|
|
||||||
BL runtime·exitsyscall(SB)
|
|
||||||
RET
|
|
||||||
ok:
|
|
||||||
MOVD R0, r1+32(FP) // r1
|
|
||||||
MOVD R1, r2+40(FP) // r2
|
|
||||||
MOVD ZR, err+48(FP) // errno
|
|
||||||
BL runtime·exitsyscall(SB)
|
|
||||||
RET
|
|
||||||
|
|
||||||
|
// func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
|
||||||
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||||
BL runtime·entersyscall(SB)
|
JMP ·syscall6Internal(SB)
|
||||||
MOVD a1+8(FP), R0
|
|
||||||
MOVD a2+16(FP), R1
|
|
||||||
MOVD a3+24(FP), R2
|
|
||||||
MOVD a4+32(FP), R3
|
|
||||||
MOVD a5+40(FP), R4
|
|
||||||
MOVD a6+48(FP), R5
|
|
||||||
MOVD trap+0(FP), R8 // syscall number
|
|
||||||
INVOKE_SYSCALL
|
|
||||||
BCC ok
|
|
||||||
MOVD $-1, R4
|
|
||||||
MOVD R4, r1+56(FP) // r1
|
|
||||||
MOVD ZR, r2+64(FP) // r2
|
|
||||||
MOVD R0, err+72(FP) // errno
|
|
||||||
BL runtime·exitsyscall(SB)
|
|
||||||
RET
|
|
||||||
ok:
|
|
||||||
MOVD R0, r1+56(FP) // r1
|
|
||||||
MOVD R1, r2+64(FP) // r2
|
|
||||||
MOVD ZR, err+72(FP) // errno
|
|
||||||
BL runtime·exitsyscall(SB)
|
|
||||||
RET
|
|
||||||
|
|
||||||
TEXT ·Syscall9(SB),NOSPLIT,$0-104
|
|
||||||
BL runtime·entersyscall(SB)
|
|
||||||
MOVD a1+8(FP), R0
|
|
||||||
MOVD a2+16(FP), R1
|
|
||||||
MOVD a3+24(FP), R2
|
|
||||||
MOVD a4+32(FP), R3
|
|
||||||
MOVD a5+40(FP), R4
|
|
||||||
MOVD a6+48(FP), R5
|
|
||||||
MOVD a7+56(FP), R6
|
|
||||||
MOVD a8+64(FP), R7
|
|
||||||
MOVD a9+72(FP), R8 // on stack
|
|
||||||
MOVD R8, 8(RSP)
|
|
||||||
MOVD num+0(FP), R8 // syscall number
|
|
||||||
INVOKE_SYSCALL
|
|
||||||
BCC ok
|
|
||||||
MOVD $-1, R4
|
|
||||||
MOVD R4, r1+80(FP) // r1
|
|
||||||
MOVD ZR, r2+88(FP) // r2
|
|
||||||
MOVD R0, err+96(FP) // errno
|
|
||||||
BL runtime·exitsyscall(SB)
|
|
||||||
RET
|
|
||||||
ok:
|
|
||||||
MOVD R0, r1+80(FP) // r1
|
|
||||||
MOVD R1, r2+88(FP) // r2
|
|
||||||
MOVD ZR, err+96(FP) // errno
|
|
||||||
BL runtime·exitsyscall(SB)
|
|
||||||
RET
|
|
||||||
|
|
||||||
|
// func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
|
||||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||||
MOVD a1+8(FP), R0
|
JMP ·rawSyscallInternal(SB)
|
||||||
MOVD a2+16(FP), R1
|
|
||||||
MOVD a3+24(FP), R2
|
|
||||||
MOVD $0, R3
|
|
||||||
MOVD $0, R4
|
|
||||||
MOVD $0, R5
|
|
||||||
MOVD trap+0(FP), R8 // syscall number
|
|
||||||
INVOKE_SYSCALL
|
|
||||||
BCC ok
|
|
||||||
MOVD $-1, R4
|
|
||||||
MOVD R4, r1+32(FP) // r1
|
|
||||||
MOVD ZR, r2+40(FP) // r2
|
|
||||||
MOVD R0, err+48(FP) // errno
|
|
||||||
RET
|
|
||||||
ok:
|
|
||||||
MOVD R0, r1+32(FP) // r1
|
|
||||||
MOVD R1, r2+40(FP) // r2
|
|
||||||
MOVD ZR, err+48(FP) // errno
|
|
||||||
RET
|
|
||||||
|
|
||||||
|
// func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
|
||||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||||
MOVD a1+8(FP), R0
|
JMP ·rawSyscall6Internal(SB)
|
||||||
MOVD a2+16(FP), R1
|
|
||||||
MOVD a3+24(FP), R2
|
// func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno)
|
||||||
MOVD a4+32(FP), R3
|
TEXT ·Syscall9(SB),NOSPLIT,$0-104
|
||||||
MOVD a5+40(FP), R4
|
JMP ·syscall9Internal(SB)
|
||||||
MOVD a6+48(FP), R5
|
|
||||||
MOVD trap+0(FP), R8 // syscall number
|
|
||||||
INVOKE_SYSCALL
|
|
||||||
BCC ok
|
|
||||||
MOVD $-1, R4
|
|
||||||
MOVD R4, r1+56(FP) // r1
|
|
||||||
MOVD ZR, r2+64(FP) // r2
|
|
||||||
MOVD R0, err+72(FP) // errno
|
|
||||||
RET
|
|
||||||
ok:
|
|
||||||
MOVD R0, r1+56(FP) // r1
|
|
||||||
MOVD R1, r2+64(FP) // r2
|
|
||||||
MOVD ZR, err+72(FP) // errno
|
|
||||||
RET
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// +build netbsd freebsd openbsd dragonfly
|
// +build netbsd freebsd dragonfly
|
||||||
|
|
||||||
// Copyright 2009 The Go Authors. All rights reserved.
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build dragonfly freebsd netbsd openbsd
|
// +build dragonfly freebsd netbsd openbsd,!amd64,!arm64
|
||||||
|
|
||||||
package syscall
|
package syscall
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build darwin openbsd,amd64 openbsd,arm64
|
||||||
|
|
||||||
package syscall
|
package syscall
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
@ -272,6 +272,7 @@ func runtime_AfterExec()
|
||||||
// avoids a build dependency for other platforms.
|
// avoids a build dependency for other platforms.
|
||||||
var execveLibc func(path uintptr, argv uintptr, envp uintptr) Errno
|
var execveLibc func(path uintptr, argv uintptr, envp uintptr) Errno
|
||||||
var execveDarwin func(path *byte, argv **byte, envp **byte) error
|
var execveDarwin func(path *byte, argv **byte, envp **byte) error
|
||||||
|
var execveOpenBSD func(path *byte, argv **byte, envp **byte) error
|
||||||
|
|
||||||
// Exec invokes the execve(2) system call.
|
// Exec invokes the execve(2) system call.
|
||||||
func Exec(argv0 string, argv []string, envv []string) (err error) {
|
func Exec(argv0 string, argv []string, envv []string) (err error) {
|
||||||
|
|
@ -299,6 +300,9 @@ func Exec(argv0 string, argv []string, envv []string) (err error) {
|
||||||
} else if runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
|
} else if runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
|
||||||
// Similarly on Darwin.
|
// Similarly on Darwin.
|
||||||
err1 = execveDarwin(argv0p, &argvp[0], &envvp[0])
|
err1 = execveDarwin(argv0p, &argvp[0], &envvp[0])
|
||||||
|
} else if runtime.GOOS == "openbsd" && runtime.GOARCH == "amd64" {
|
||||||
|
// Similarly on OpenBSD.
|
||||||
|
err1 = execveOpenBSD(argv0p, &argvp[0], &envvp[0])
|
||||||
} else {
|
} else {
|
||||||
_, _, err1 = RawSyscall(SYS_EXECVE,
|
_, _, err1 = RawSyscall(SYS_EXECVE,
|
||||||
uintptr(unsafe.Pointer(argv0p)),
|
uintptr(unsafe.Pointer(argv0p)),
|
||||||
|
|
|
||||||
|
|
@ -125,13 +125,13 @@ darwin_amd64)
|
||||||
mkerrors="$mkerrors -m64"
|
mkerrors="$mkerrors -m64"
|
||||||
mksyscall="./mksyscall.pl -darwin"
|
mksyscall="./mksyscall.pl -darwin"
|
||||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||||
mkasm="go run mkasm_darwin.go"
|
mkasm="go run mkasm.go"
|
||||||
;;
|
;;
|
||||||
darwin_arm64)
|
darwin_arm64)
|
||||||
mkerrors="$mkerrors -m64"
|
mkerrors="$mkerrors -m64"
|
||||||
mksyscall="./mksyscall.pl -darwin"
|
mksyscall="./mksyscall.pl -darwin"
|
||||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||||
mkasm="go run mkasm_darwin.go"
|
mkasm="go run mkasm.go"
|
||||||
;;
|
;;
|
||||||
dragonfly_amd64)
|
dragonfly_amd64)
|
||||||
mkerrors="$mkerrors -m64"
|
mkerrors="$mkerrors -m64"
|
||||||
|
|
@ -283,6 +283,7 @@ netbsd_arm64)
|
||||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||||
;;
|
;;
|
||||||
openbsd_386)
|
openbsd_386)
|
||||||
|
GOOSARCH_in="syscall_openbsd1.go syscall_openbsd_$GOARCH.go"
|
||||||
mkerrors="$mkerrors -m32"
|
mkerrors="$mkerrors -m32"
|
||||||
mksyscall="./mksyscall.pl -l32 -openbsd"
|
mksyscall="./mksyscall.pl -l32 -openbsd"
|
||||||
mksysctl="./mksysctl_openbsd.pl"
|
mksysctl="./mksysctl_openbsd.pl"
|
||||||
|
|
@ -291,14 +292,17 @@ openbsd_386)
|
||||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||||
;;
|
;;
|
||||||
openbsd_amd64)
|
openbsd_amd64)
|
||||||
|
GOOSARCH_in="syscall_openbsd_libc.go syscall_openbsd_$GOARCH.go"
|
||||||
mkerrors="$mkerrors -m64"
|
mkerrors="$mkerrors -m64"
|
||||||
mksyscall="./mksyscall.pl -openbsd"
|
mksyscall="./mksyscall.pl -openbsd -libc"
|
||||||
mksysctl="./mksysctl_openbsd.pl"
|
mksysctl="./mksysctl_openbsd.pl"
|
||||||
zsysctl="zsysctl_openbsd.go"
|
zsysctl="zsysctl_openbsd.go"
|
||||||
mksysnum="curl -s 'http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master' | ./mksysnum_openbsd.pl"
|
mksysnum="curl -s 'http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master' | ./mksysnum_openbsd.pl"
|
||||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||||
|
mkasm="go run mkasm.go"
|
||||||
;;
|
;;
|
||||||
openbsd_arm)
|
openbsd_arm)
|
||||||
|
GOOSARCH_in="syscall_openbsd1.go syscall_openbsd_$GOARCH.go"
|
||||||
mkerrors="$mkerrors"
|
mkerrors="$mkerrors"
|
||||||
mksyscall="./mksyscall.pl -l32 -openbsd -arm"
|
mksyscall="./mksyscall.pl -l32 -openbsd -arm"
|
||||||
mksysctl="./mksysctl_openbsd.pl"
|
mksysctl="./mksysctl_openbsd.pl"
|
||||||
|
|
@ -309,16 +313,19 @@ openbsd_arm)
|
||||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
|
||||||
;;
|
;;
|
||||||
openbsd_arm64)
|
openbsd_arm64)
|
||||||
|
GOOSARCH_in="syscall_openbsd_libc.go syscall_openbsd_$GOARCH.go"
|
||||||
mkerrors="$mkerrors -m64"
|
mkerrors="$mkerrors -m64"
|
||||||
mksyscall="./mksyscall.pl -openbsd"
|
mksyscall="./mksyscall.pl -openbsd -libc"
|
||||||
mksysctl="./mksysctl_openbsd.pl"
|
mksysctl="./mksysctl_openbsd.pl"
|
||||||
zsysctl="zsysctl_openbsd.go"
|
zsysctl="zsysctl_openbsd.go"
|
||||||
mksysnum="curl -s 'http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master' | ./mksysnum_openbsd.pl"
|
mksysnum="curl -s 'http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master' | ./mksysnum_openbsd.pl"
|
||||||
# Let the type of C char be signed to make the bare syscall
|
# Let the type of C char be signed to make the bare syscall
|
||||||
# API consistent between platforms.
|
# API consistent between platforms.
|
||||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
|
||||||
|
mkasm="go run mkasm.go"
|
||||||
;;
|
;;
|
||||||
openbsd_mips64)
|
openbsd_mips64)
|
||||||
|
GOOSARCH_in="syscall_openbsd1.go syscall_openbsd_$GOARCH.go"
|
||||||
mkerrors="$mkerrors -m64"
|
mkerrors="$mkerrors -m64"
|
||||||
mksyscall="./mksyscall.pl -openbsd"
|
mksyscall="./mksyscall.pl -openbsd"
|
||||||
mksysctl="./mksysctl_openbsd.pl"
|
mksysctl="./mksysctl_openbsd.pl"
|
||||||
|
|
@ -327,7 +334,6 @@ openbsd_mips64)
|
||||||
# Let the type of C char be signed to make the bare syscall
|
# Let the type of C char be signed to make the bare syscall
|
||||||
# API consistent between platforms.
|
# API consistent between platforms.
|
||||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
|
||||||
GOOSARCH_in=syscall_openbsd_mips64.go
|
|
||||||
;;
|
;;
|
||||||
plan9_386)
|
plan9_386)
|
||||||
mkerrors=
|
mkerrors=
|
||||||
|
|
@ -367,5 +373,5 @@ esac
|
||||||
# Therefore, "go run" tries to recompile syscall package but ztypes is empty and it fails.
|
# Therefore, "go run" tries to recompile syscall package but ztypes is empty and it fails.
|
||||||
echo "$mktypes types_$GOOS.go |go run mkpost.go >ztypes_$GOOSARCH.go.NEW && mv ztypes_$GOOSARCH.go.NEW ztypes_$GOOSARCH.go";
|
echo "$mktypes types_$GOOS.go |go run mkpost.go >ztypes_$GOOSARCH.go.NEW && mv ztypes_$GOOSARCH.go.NEW ztypes_$GOOSARCH.go";
|
||||||
fi
|
fi
|
||||||
if [ -n "$mkasm" ]; then echo "$mkasm $GOARCH"; fi
|
if [ -n "$mkasm" ]; then echo "$mkasm $GOOS $GOARCH"; fi
|
||||||
) | $run
|
) | $run
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
// +build ignore
|
// +build ignore
|
||||||
|
|
||||||
// mkasm_darwin.go generates assembly trampolines to call libSystem routines from Go.
|
// mkasm.go generates assembly trampolines to call library routines from Go.
|
||||||
// This program must be run after mksyscall.pl.
|
// This program must be run after mksyscall.pl.
|
||||||
package main
|
package main
|
||||||
|
|
||||||
|
|
@ -17,18 +17,25 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
in1, err := os.ReadFile("syscall_darwin.go")
|
if len(os.Args) != 3 {
|
||||||
if err != nil {
|
log.Fatalf("Usage: %s <goos> <arch>", os.Args[0])
|
||||||
log.Fatalf("can't open syscall_darwin.go: %s", err)
|
|
||||||
}
|
}
|
||||||
arch := os.Args[1]
|
goos, arch := os.Args[1], os.Args[2]
|
||||||
in2, err := os.ReadFile(fmt.Sprintf("syscall_darwin_%s.go", arch))
|
|
||||||
|
syscallFilename := fmt.Sprintf("syscall_%s.go", goos)
|
||||||
|
syscallArchFilename := fmt.Sprintf("syscall_%s_%s.go", goos, arch)
|
||||||
|
|
||||||
|
in1, err := os.ReadFile(syscallFilename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("can't open syscall_darwin_%s.go: %s", arch, err)
|
log.Fatalf("can't open syscall file: %s", err)
|
||||||
}
|
}
|
||||||
in3, err := os.ReadFile(fmt.Sprintf("zsyscall_darwin_%s.go", arch))
|
in2, err := os.ReadFile(syscallArchFilename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("can't open zsyscall_darwin_%s.go: %s", arch, err)
|
log.Fatalf("can't open syscall file: %s", err)
|
||||||
|
}
|
||||||
|
in3, err := os.ReadFile("z" + syscallArchFilename)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("can't open syscall file: %s", err)
|
||||||
}
|
}
|
||||||
in := string(in1) + string(in2) + string(in3)
|
in := string(in1) + string(in2) + string(in3)
|
||||||
|
|
||||||
|
|
@ -36,7 +43,7 @@ func main() {
|
||||||
|
|
||||||
var out bytes.Buffer
|
var out bytes.Buffer
|
||||||
|
|
||||||
fmt.Fprintf(&out, "// go run mkasm_darwin.go %s\n", strings.Join(os.Args[1:], " "))
|
fmt.Fprintf(&out, "// go run mkasm.go %s\n", strings.Join(os.Args[1:], " "))
|
||||||
fmt.Fprintf(&out, "// Code generated by the command above; DO NOT EDIT.\n")
|
fmt.Fprintf(&out, "// Code generated by the command above; DO NOT EDIT.\n")
|
||||||
fmt.Fprintf(&out, "#include \"textflag.h\"\n")
|
fmt.Fprintf(&out, "#include \"textflag.h\"\n")
|
||||||
for _, line := range strings.Split(in, "\n") {
|
for _, line := range strings.Split(in, "\n") {
|
||||||
|
|
@ -50,8 +57,8 @@ func main() {
|
||||||
fmt.Fprintf(&out, "\tJMP\t%s(SB)\n", fn)
|
fmt.Fprintf(&out, "\tJMP\t%s(SB)\n", fn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err = os.WriteFile(fmt.Sprintf("zsyscall_darwin_%s.s", arch), out.Bytes(), 0644)
|
err = os.WriteFile(fmt.Sprintf("zsyscall_%s_%s.s", goos, arch), out.Bytes(), 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("can't write zsyscall_darwin_%s.s: %s", arch, err)
|
log.Fatalf("can't write syscall file: %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -30,6 +30,7 @@ my $openbsd = 0;
|
||||||
my $netbsd = 0;
|
my $netbsd = 0;
|
||||||
my $dragonfly = 0;
|
my $dragonfly = 0;
|
||||||
my $arm = 0; # 64-bit value should use (even, odd)-pair
|
my $arm = 0; # 64-bit value should use (even, odd)-pair
|
||||||
|
my $libc = 0;
|
||||||
my $tags = ""; # build tags
|
my $tags = ""; # build tags
|
||||||
|
|
||||||
if($ARGV[0] eq "-b32") {
|
if($ARGV[0] eq "-b32") {
|
||||||
|
|
@ -45,6 +46,7 @@ if($ARGV[0] eq "-plan9") {
|
||||||
}
|
}
|
||||||
if($ARGV[0] eq "-darwin") {
|
if($ARGV[0] eq "-darwin") {
|
||||||
$darwin = 1;
|
$darwin = 1;
|
||||||
|
$libc = 1;
|
||||||
shift;
|
shift;
|
||||||
}
|
}
|
||||||
if($ARGV[0] eq "-openbsd") {
|
if($ARGV[0] eq "-openbsd") {
|
||||||
|
|
@ -63,6 +65,10 @@ if($ARGV[0] eq "-arm") {
|
||||||
$arm = 1;
|
$arm = 1;
|
||||||
shift;
|
shift;
|
||||||
}
|
}
|
||||||
|
if($ARGV[0] eq "-libc") {
|
||||||
|
$libc = 1;
|
||||||
|
shift;
|
||||||
|
}
|
||||||
if($ARGV[0] eq "-tags") {
|
if($ARGV[0] eq "-tags") {
|
||||||
shift;
|
shift;
|
||||||
$tags = $ARGV[0];
|
$tags = $ARGV[0];
|
||||||
|
|
@ -125,7 +131,7 @@ while(<>) {
|
||||||
# without reading the header.
|
# without reading the header.
|
||||||
$text .= "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n";
|
$text .= "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n";
|
||||||
|
|
||||||
if ($darwin && $func eq "ptrace1") {
|
if (($darwin || ($openbsd && $libc)) && $func eq "ptrace") {
|
||||||
# The ptrace function is called from forkAndExecInChild where stack
|
# The ptrace function is called from forkAndExecInChild where stack
|
||||||
# growth is forbidden.
|
# growth is forbidden.
|
||||||
$text .= "//go:nosplit\n"
|
$text .= "//go:nosplit\n"
|
||||||
|
|
@ -176,7 +182,9 @@ while(<>) {
|
||||||
push @args, "uintptr(_p$n)", "uintptr(len($name))";
|
push @args, "uintptr(_p$n)", "uintptr(len($name))";
|
||||||
$n++;
|
$n++;
|
||||||
} elsif($type eq "int64" && ($openbsd || $netbsd)) {
|
} elsif($type eq "int64" && ($openbsd || $netbsd)) {
|
||||||
|
if (!$libc) {
|
||||||
push @args, "0";
|
push @args, "0";
|
||||||
|
}
|
||||||
if($_32bit eq "big-endian") {
|
if($_32bit eq "big-endian") {
|
||||||
push @args, "uintptr($name>>32)", "uintptr($name)";
|
push @args, "uintptr($name>>32)", "uintptr($name)";
|
||||||
} elsif($_32bit eq "little-endian") {
|
} elsif($_32bit eq "little-endian") {
|
||||||
|
|
@ -220,7 +228,7 @@ while(<>) {
|
||||||
$asm = "RawSyscall";
|
$asm = "RawSyscall";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($darwin) {
|
if ($libc) {
|
||||||
# Call unexported syscall functions (which take
|
# Call unexported syscall functions (which take
|
||||||
# libc functions instead of syscall numbers).
|
# libc functions instead of syscall numbers).
|
||||||
$asm = lcfirst($asm);
|
$asm = lcfirst($asm);
|
||||||
|
|
@ -243,7 +251,7 @@ while(<>) {
|
||||||
print STDERR "$ARGV:$.: too many arguments to system call\n";
|
print STDERR "$ARGV:$.: too many arguments to system call\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($darwin) {
|
if ($darwin || ($openbsd && $libc)) {
|
||||||
# Use extended versions for calls that generate a 64-bit result.
|
# Use extended versions for calls that generate a 64-bit result.
|
||||||
my ($name, $type) = parseparam($out[0]);
|
my ($name, $type) = parseparam($out[0]);
|
||||||
if ($type eq "int64" || ($type eq "uintptr" && $_32bit eq "")) {
|
if ($type eq "int64" || ($type eq "uintptr" && $_32bit eq "")) {
|
||||||
|
|
@ -257,13 +265,13 @@ while(<>) {
|
||||||
$sysname = "SYS_$func";
|
$sysname = "SYS_$func";
|
||||||
$sysname =~ s/([a-z])([A-Z])/${1}_$2/g; # turn FooBar into Foo_Bar
|
$sysname =~ s/([a-z])([A-Z])/${1}_$2/g; # turn FooBar into Foo_Bar
|
||||||
$sysname =~ y/a-z/A-Z/;
|
$sysname =~ y/a-z/A-Z/;
|
||||||
if($darwin) {
|
if($libc) {
|
||||||
$sysname =~ y/A-Z/a-z/;
|
$sysname =~ y/A-Z/a-z/;
|
||||||
$sysname = substr $sysname, 4;
|
$sysname = substr $sysname, 4;
|
||||||
$funcname = "libc_$sysname";
|
$funcname = "libc_$sysname";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if($darwin) {
|
if($libc) {
|
||||||
if($funcname eq "") {
|
if($funcname eq "") {
|
||||||
$sysname = substr $sysname, 4;
|
$sysname = substr $sysname, 4;
|
||||||
$funcname = "libc_$sysname";
|
$funcname = "libc_$sysname";
|
||||||
|
|
@ -338,14 +346,18 @@ while(<>) {
|
||||||
}
|
}
|
||||||
$text .= "\treturn\n";
|
$text .= "\treturn\n";
|
||||||
$text .= "}\n\n";
|
$text .= "}\n\n";
|
||||||
if($darwin) {
|
if($libc) {
|
||||||
if (not exists $trampolines{$funcname}) {
|
if (not exists $trampolines{$funcname}) {
|
||||||
$trampolines{$funcname} = 1;
|
$trampolines{$funcname} = 1;
|
||||||
# The assembly trampoline that jumps to the libc routine.
|
# The assembly trampoline that jumps to the libc routine.
|
||||||
$text .= "func ${funcname}_trampoline()\n";
|
$text .= "func ${funcname}_trampoline()\n";
|
||||||
# Tell the linker that funcname can be found in libSystem using varname without the libc_ prefix.
|
# Tell the linker that funcname can be found in libSystem using varname without the libc_ prefix.
|
||||||
my $basename = substr $funcname, 5;
|
my $basename = substr $funcname, 5;
|
||||||
$text .= "//go:cgo_import_dynamic $funcname $basename \"/usr/lib/libSystem.B.dylib\"\n\n";
|
my $libc = "libc.so";
|
||||||
|
if ($darwin) {
|
||||||
|
$libc = "/usr/lib/libSystem.B.dylib";
|
||||||
|
}
|
||||||
|
$text .= "//go:cgo_import_dynamic $funcname $basename \"$libc\"\n\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -182,7 +182,6 @@ func setattrlistTimes(path string, times []Timespec) error {
|
||||||
//sys Rename(from string, to string) (err error)
|
//sys Rename(from string, to string) (err error)
|
||||||
//sys Revoke(path string) (err error)
|
//sys Revoke(path string) (err error)
|
||||||
//sys Rmdir(path string) (err error)
|
//sys Rmdir(path string) (err error)
|
||||||
//sys Seek(fd int, offset int64, whence int) (newoffset int64, err error) = SYS_LSEEK
|
|
||||||
//sys Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error)
|
//sys Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error)
|
||||||
//sysnb Setegid(egid int) (err error)
|
//sysnb Setegid(egid int) (err error)
|
||||||
//sysnb Seteuid(euid int) (err error)
|
//sysnb Seteuid(euid int) (err error)
|
||||||
|
|
@ -207,8 +206,4 @@ func setattrlistTimes(path string, times []Timespec) error {
|
||||||
//sys write(fd int, p []byte) (n int, err error)
|
//sys write(fd int, p []byte) (n int, err error)
|
||||||
//sys mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error)
|
//sys mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error)
|
||||||
//sys munmap(addr uintptr, length uintptr) (err error)
|
//sys munmap(addr uintptr, length uintptr) (err error)
|
||||||
//sys readlen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_READ
|
|
||||||
//sys writelen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_WRITE
|
|
||||||
//sys utimensat(dirfd int, path string, times *[2]Timespec, flag int) (err error)
|
//sys utimensat(dirfd int, path string, times *[2]Timespec, flag int) (err error)
|
||||||
//sys getcwd(buf []byte) (n int, err error) = SYS___GETCWD
|
|
||||||
//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS___SYSCTL
|
|
||||||
|
|
|
||||||
13
src/syscall/syscall_openbsd1.go
Normal file
13
src/syscall/syscall_openbsd1.go
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
// Copyright 2020 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build openbsd,!amd64,!arm64
|
||||||
|
|
||||||
|
package syscall
|
||||||
|
|
||||||
|
//sys readlen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_READ
|
||||||
|
//sys writelen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_WRITE
|
||||||
|
//sys Seek(fd int, offset int64, whence int) (newoffset int64, err error) = SYS_LSEEK
|
||||||
|
//sys getcwd(buf []byte) (n int, err error) = SYS___GETCWD
|
||||||
|
//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS___SYSCTL
|
||||||
77
src/syscall/syscall_openbsd_libc.go
Normal file
77
src/syscall/syscall_openbsd_libc.go
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
// Copyright 2020 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build openbsd,amd64 openbsd,arm64
|
||||||
|
|
||||||
|
package syscall
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
execveOpenBSD = execve
|
||||||
|
}
|
||||||
|
|
||||||
|
//sys directSyscall(trap uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4 uintptr, a5 uintptr) (ret uintptr, err error) = SYS_syscall
|
||||||
|
|
||||||
|
func syscallInternal(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) {
|
||||||
|
return syscall6X(funcPC(libc_syscall_trampoline), trap, a1, a2, a3, 0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func syscall6Internal(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) {
|
||||||
|
return syscall10X(funcPC(libc_syscall_trampoline), trap, a1, a2, a3, a4, a5, a6, 0, 0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func rawSyscallInternal(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) {
|
||||||
|
return rawSyscall6X(funcPC(libc_syscall_trampoline), trap, a1, a2, a3, 0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func rawSyscall6Internal(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) {
|
||||||
|
return rawSyscall10X(funcPC(libc_syscall_trampoline), trap, a1, a2, a3, a4, a5, a6, 0, 0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func syscall9Internal(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno) {
|
||||||
|
return rawSyscall10X(funcPC(libc_syscall_trampoline), trap, a1, a2, a3, a4, a5, a6, a7, a8, a9)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implemented in the runtime package (runtime/sys_openbsd3.go)
|
||||||
|
func syscall(fn, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
|
||||||
|
func syscallX(fn, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
|
||||||
|
func syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
|
||||||
|
func syscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
|
||||||
|
func syscall10(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 uintptr) (r1, r2 uintptr, err Errno)
|
||||||
|
func syscall10X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 uintptr) (r1, r2 uintptr, err Errno)
|
||||||
|
func rawSyscall(fn, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
|
||||||
|
func rawSyscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
|
||||||
|
func rawSyscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
|
||||||
|
func rawSyscall10X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 uintptr) (r1, r2 uintptr, err Errno)
|
||||||
|
|
||||||
|
func syscall9(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno) {
|
||||||
|
return syscall10(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, 0)
|
||||||
|
}
|
||||||
|
func syscall9X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno) {
|
||||||
|
return syscall10X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the entry point for f. See comments in runtime/proc.go for the
|
||||||
|
// function of the same name.
|
||||||
|
//go:nosplit
|
||||||
|
func funcPC(f func()) uintptr {
|
||||||
|
return **(**uintptr)(unsafe.Pointer(&f))
|
||||||
|
}
|
||||||
|
|
||||||
|
//sys readlen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_read
|
||||||
|
//sys writelen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_write
|
||||||
|
//sys Seek(fd int, offset int64, whence int) (newoffset int64, err error) = SYS_lseek
|
||||||
|
//sys getcwd(buf []byte) (n int, err error)
|
||||||
|
//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error)
|
||||||
|
//sysnb fork() (pid int, err error)
|
||||||
|
//sysnb ioctl(fd int, req int, arg int) (err error)
|
||||||
|
//sysnb execve(path *byte, argv **byte, envp **byte) (err error)
|
||||||
|
//sysnb exit(res int) (err error)
|
||||||
|
//sys ptrace(request int, pid int, addr uintptr, data uintptr) (err error)
|
||||||
|
//sysnb getentropy(p []byte) (err error)
|
||||||
|
//sys fstatat(fd int, path string, stat *Stat_t, flags int) (err error)
|
||||||
|
//sys fcntlPtr(fd int, cmd int, arg unsafe.Pointer) (val int, err error) = SYS_fcntl
|
||||||
|
//sys unlinkat(fd int, path string, flags int) (err error)
|
||||||
|
//sys openat(fd int, path string, flags int, perm uint32) (fdret int, err error)
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// go run mkasm_darwin.go amd64
|
// go run mkasm.go darwin amd64
|
||||||
// Code generated by the command above; DO NOT EDIT.
|
// Code generated by the command above; DO NOT EDIT.
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
TEXT ·libc_getfsstat_trampoline(SB),NOSPLIT,$0-0
|
TEXT ·libc_getfsstat_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// go run mkasm_darwin.go arm64
|
// go run mkasm.go darwin arm64
|
||||||
// Code generated by the command above; DO NOT EDIT.
|
// Code generated by the command above; DO NOT EDIT.
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
TEXT ·libc_getfsstat_trampoline(SB),NOSPLIT,$0-0
|
TEXT ·libc_getfsstat_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
233
src/syscall/zsyscall_openbsd_amd64.s
Normal file
233
src/syscall/zsyscall_openbsd_amd64.s
Normal file
|
|
@ -0,0 +1,233 @@
|
||||||
|
// go run mkasm.go openbsd amd64
|
||||||
|
// Code generated by the command above; DO NOT EDIT.
|
||||||
|
#include "textflag.h"
|
||||||
|
TEXT ·libc_getgroups_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_getgroups(SB)
|
||||||
|
TEXT ·libc_setgroups_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_setgroups(SB)
|
||||||
|
TEXT ·libc_wait4_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_wait4(SB)
|
||||||
|
TEXT ·libc_accept_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_accept(SB)
|
||||||
|
TEXT ·libc_bind_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_bind(SB)
|
||||||
|
TEXT ·libc_connect_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_connect(SB)
|
||||||
|
TEXT ·libc_socket_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_socket(SB)
|
||||||
|
TEXT ·libc_getsockopt_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_getsockopt(SB)
|
||||||
|
TEXT ·libc_setsockopt_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_setsockopt(SB)
|
||||||
|
TEXT ·libc_getpeername_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_getpeername(SB)
|
||||||
|
TEXT ·libc_getsockname_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_getsockname(SB)
|
||||||
|
TEXT ·libc_shutdown_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_shutdown(SB)
|
||||||
|
TEXT ·libc_socketpair_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_socketpair(SB)
|
||||||
|
TEXT ·libc_recvfrom_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_recvfrom(SB)
|
||||||
|
TEXT ·libc_sendto_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_sendto(SB)
|
||||||
|
TEXT ·libc_recvmsg_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_recvmsg(SB)
|
||||||
|
TEXT ·libc_sendmsg_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_sendmsg(SB)
|
||||||
|
TEXT ·libc_kevent_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_kevent(SB)
|
||||||
|
TEXT ·libc_utimes_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_utimes(SB)
|
||||||
|
TEXT ·libc_futimes_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_futimes(SB)
|
||||||
|
TEXT ·libc_fcntl_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_fcntl(SB)
|
||||||
|
TEXT ·libc_pipe2_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_pipe2(SB)
|
||||||
|
TEXT ·libc_accept4_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_accept4(SB)
|
||||||
|
TEXT ·libc_getdents_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_getdents(SB)
|
||||||
|
TEXT ·libc_access_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_access(SB)
|
||||||
|
TEXT ·libc_adjtime_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_adjtime(SB)
|
||||||
|
TEXT ·libc_chdir_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_chdir(SB)
|
||||||
|
TEXT ·libc_chflags_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_chflags(SB)
|
||||||
|
TEXT ·libc_chmod_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_chmod(SB)
|
||||||
|
TEXT ·libc_chown_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_chown(SB)
|
||||||
|
TEXT ·libc_chroot_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_chroot(SB)
|
||||||
|
TEXT ·libc_close_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_close(SB)
|
||||||
|
TEXT ·libc_dup_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_dup(SB)
|
||||||
|
TEXT ·libc_dup2_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_dup2(SB)
|
||||||
|
TEXT ·libc_fchdir_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_fchdir(SB)
|
||||||
|
TEXT ·libc_fchflags_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_fchflags(SB)
|
||||||
|
TEXT ·libc_fchmod_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_fchmod(SB)
|
||||||
|
TEXT ·libc_fchown_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_fchown(SB)
|
||||||
|
TEXT ·libc_flock_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_flock(SB)
|
||||||
|
TEXT ·libc_fpathconf_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_fpathconf(SB)
|
||||||
|
TEXT ·libc_fstat_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_fstat(SB)
|
||||||
|
TEXT ·libc_fstatfs_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_fstatfs(SB)
|
||||||
|
TEXT ·libc_fsync_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_fsync(SB)
|
||||||
|
TEXT ·libc_ftruncate_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_ftruncate(SB)
|
||||||
|
TEXT ·libc_getegid_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_getegid(SB)
|
||||||
|
TEXT ·libc_geteuid_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_geteuid(SB)
|
||||||
|
TEXT ·libc_getgid_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_getgid(SB)
|
||||||
|
TEXT ·libc_getpgid_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_getpgid(SB)
|
||||||
|
TEXT ·libc_getpgrp_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_getpgrp(SB)
|
||||||
|
TEXT ·libc_getpid_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_getpid(SB)
|
||||||
|
TEXT ·libc_getppid_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_getppid(SB)
|
||||||
|
TEXT ·libc_getpriority_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_getpriority(SB)
|
||||||
|
TEXT ·libc_getrlimit_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_getrlimit(SB)
|
||||||
|
TEXT ·libc_getrusage_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_getrusage(SB)
|
||||||
|
TEXT ·libc_getsid_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_getsid(SB)
|
||||||
|
TEXT ·libc_gettimeofday_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_gettimeofday(SB)
|
||||||
|
TEXT ·libc_getuid_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_getuid(SB)
|
||||||
|
TEXT ·libc_issetugid_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_issetugid(SB)
|
||||||
|
TEXT ·libc_kill_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_kill(SB)
|
||||||
|
TEXT ·libc_kqueue_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_kqueue(SB)
|
||||||
|
TEXT ·libc_lchown_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_lchown(SB)
|
||||||
|
TEXT ·libc_link_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_link(SB)
|
||||||
|
TEXT ·libc_listen_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_listen(SB)
|
||||||
|
TEXT ·libc_lstat_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_lstat(SB)
|
||||||
|
TEXT ·libc_mkdir_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_mkdir(SB)
|
||||||
|
TEXT ·libc_mkfifo_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_mkfifo(SB)
|
||||||
|
TEXT ·libc_mknod_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_mknod(SB)
|
||||||
|
TEXT ·libc_nanosleep_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_nanosleep(SB)
|
||||||
|
TEXT ·libc_open_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_open(SB)
|
||||||
|
TEXT ·libc_pathconf_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_pathconf(SB)
|
||||||
|
TEXT ·libc_pread_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_pread(SB)
|
||||||
|
TEXT ·libc_pwrite_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_pwrite(SB)
|
||||||
|
TEXT ·libc_read_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_read(SB)
|
||||||
|
TEXT ·libc_readlink_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_readlink(SB)
|
||||||
|
TEXT ·libc_rename_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_rename(SB)
|
||||||
|
TEXT ·libc_revoke_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_revoke(SB)
|
||||||
|
TEXT ·libc_rmdir_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_rmdir(SB)
|
||||||
|
TEXT ·libc_select_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_select(SB)
|
||||||
|
TEXT ·libc_setegid_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_setegid(SB)
|
||||||
|
TEXT ·libc_seteuid_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_seteuid(SB)
|
||||||
|
TEXT ·libc_setgid_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_setgid(SB)
|
||||||
|
TEXT ·libc_setlogin_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_setlogin(SB)
|
||||||
|
TEXT ·libc_setpgid_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_setpgid(SB)
|
||||||
|
TEXT ·libc_setpriority_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_setpriority(SB)
|
||||||
|
TEXT ·libc_setregid_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_setregid(SB)
|
||||||
|
TEXT ·libc_setreuid_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_setreuid(SB)
|
||||||
|
TEXT ·libc_setrlimit_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_setrlimit(SB)
|
||||||
|
TEXT ·libc_setsid_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_setsid(SB)
|
||||||
|
TEXT ·libc_settimeofday_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_settimeofday(SB)
|
||||||
|
TEXT ·libc_setuid_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_setuid(SB)
|
||||||
|
TEXT ·libc_stat_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_stat(SB)
|
||||||
|
TEXT ·libc_statfs_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_statfs(SB)
|
||||||
|
TEXT ·libc_symlink_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_symlink(SB)
|
||||||
|
TEXT ·libc_sync_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_sync(SB)
|
||||||
|
TEXT ·libc_truncate_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_truncate(SB)
|
||||||
|
TEXT ·libc_umask_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_umask(SB)
|
||||||
|
TEXT ·libc_unlink_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_unlink(SB)
|
||||||
|
TEXT ·libc_unmount_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_unmount(SB)
|
||||||
|
TEXT ·libc_write_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_write(SB)
|
||||||
|
TEXT ·libc_mmap_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_mmap(SB)
|
||||||
|
TEXT ·libc_munmap_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_munmap(SB)
|
||||||
|
TEXT ·libc_utimensat_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_utimensat(SB)
|
||||||
|
TEXT ·libc_syscall_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_syscall(SB)
|
||||||
|
TEXT ·libc_lseek_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_lseek(SB)
|
||||||
|
TEXT ·libc_getcwd_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_getcwd(SB)
|
||||||
|
TEXT ·libc_sysctl_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_sysctl(SB)
|
||||||
|
TEXT ·libc_fork_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_fork(SB)
|
||||||
|
TEXT ·libc_ioctl_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_ioctl(SB)
|
||||||
|
TEXT ·libc_execve_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_execve(SB)
|
||||||
|
TEXT ·libc_exit_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_exit(SB)
|
||||||
|
TEXT ·libc_ptrace_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_ptrace(SB)
|
||||||
|
TEXT ·libc_getentropy_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_getentropy(SB)
|
||||||
|
TEXT ·libc_fstatat_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_fstatat(SB)
|
||||||
|
TEXT ·libc_unlinkat_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_unlinkat(SB)
|
||||||
|
TEXT ·libc_openat_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_openat(SB)
|
||||||
File diff suppressed because it is too large
Load diff
233
src/syscall/zsyscall_openbsd_arm64.s
Normal file
233
src/syscall/zsyscall_openbsd_arm64.s
Normal file
|
|
@ -0,0 +1,233 @@
|
||||||
|
// go run mkasm.go openbsd arm64
|
||||||
|
// Code generated by the command above; DO NOT EDIT.
|
||||||
|
#include "textflag.h"
|
||||||
|
TEXT ·libc_getgroups_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_getgroups(SB)
|
||||||
|
TEXT ·libc_setgroups_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_setgroups(SB)
|
||||||
|
TEXT ·libc_wait4_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_wait4(SB)
|
||||||
|
TEXT ·libc_accept_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_accept(SB)
|
||||||
|
TEXT ·libc_bind_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_bind(SB)
|
||||||
|
TEXT ·libc_connect_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_connect(SB)
|
||||||
|
TEXT ·libc_socket_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_socket(SB)
|
||||||
|
TEXT ·libc_getsockopt_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_getsockopt(SB)
|
||||||
|
TEXT ·libc_setsockopt_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_setsockopt(SB)
|
||||||
|
TEXT ·libc_getpeername_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_getpeername(SB)
|
||||||
|
TEXT ·libc_getsockname_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_getsockname(SB)
|
||||||
|
TEXT ·libc_shutdown_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_shutdown(SB)
|
||||||
|
TEXT ·libc_socketpair_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_socketpair(SB)
|
||||||
|
TEXT ·libc_recvfrom_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_recvfrom(SB)
|
||||||
|
TEXT ·libc_sendto_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_sendto(SB)
|
||||||
|
TEXT ·libc_recvmsg_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_recvmsg(SB)
|
||||||
|
TEXT ·libc_sendmsg_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_sendmsg(SB)
|
||||||
|
TEXT ·libc_kevent_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_kevent(SB)
|
||||||
|
TEXT ·libc_utimes_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_utimes(SB)
|
||||||
|
TEXT ·libc_futimes_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_futimes(SB)
|
||||||
|
TEXT ·libc_fcntl_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_fcntl(SB)
|
||||||
|
TEXT ·libc_pipe2_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_pipe2(SB)
|
||||||
|
TEXT ·libc_accept4_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_accept4(SB)
|
||||||
|
TEXT ·libc_getdents_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_getdents(SB)
|
||||||
|
TEXT ·libc_access_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_access(SB)
|
||||||
|
TEXT ·libc_adjtime_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_adjtime(SB)
|
||||||
|
TEXT ·libc_chdir_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_chdir(SB)
|
||||||
|
TEXT ·libc_chflags_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_chflags(SB)
|
||||||
|
TEXT ·libc_chmod_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_chmod(SB)
|
||||||
|
TEXT ·libc_chown_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_chown(SB)
|
||||||
|
TEXT ·libc_chroot_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_chroot(SB)
|
||||||
|
TEXT ·libc_close_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_close(SB)
|
||||||
|
TEXT ·libc_dup_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_dup(SB)
|
||||||
|
TEXT ·libc_dup2_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_dup2(SB)
|
||||||
|
TEXT ·libc_fchdir_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_fchdir(SB)
|
||||||
|
TEXT ·libc_fchflags_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_fchflags(SB)
|
||||||
|
TEXT ·libc_fchmod_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_fchmod(SB)
|
||||||
|
TEXT ·libc_fchown_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_fchown(SB)
|
||||||
|
TEXT ·libc_flock_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_flock(SB)
|
||||||
|
TEXT ·libc_fpathconf_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_fpathconf(SB)
|
||||||
|
TEXT ·libc_fstat_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_fstat(SB)
|
||||||
|
TEXT ·libc_fstatfs_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_fstatfs(SB)
|
||||||
|
TEXT ·libc_fsync_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_fsync(SB)
|
||||||
|
TEXT ·libc_ftruncate_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_ftruncate(SB)
|
||||||
|
TEXT ·libc_getegid_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_getegid(SB)
|
||||||
|
TEXT ·libc_geteuid_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_geteuid(SB)
|
||||||
|
TEXT ·libc_getgid_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_getgid(SB)
|
||||||
|
TEXT ·libc_getpgid_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_getpgid(SB)
|
||||||
|
TEXT ·libc_getpgrp_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_getpgrp(SB)
|
||||||
|
TEXT ·libc_getpid_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_getpid(SB)
|
||||||
|
TEXT ·libc_getppid_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_getppid(SB)
|
||||||
|
TEXT ·libc_getpriority_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_getpriority(SB)
|
||||||
|
TEXT ·libc_getrlimit_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_getrlimit(SB)
|
||||||
|
TEXT ·libc_getrusage_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_getrusage(SB)
|
||||||
|
TEXT ·libc_getsid_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_getsid(SB)
|
||||||
|
TEXT ·libc_gettimeofday_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_gettimeofday(SB)
|
||||||
|
TEXT ·libc_getuid_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_getuid(SB)
|
||||||
|
TEXT ·libc_issetugid_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_issetugid(SB)
|
||||||
|
TEXT ·libc_kill_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_kill(SB)
|
||||||
|
TEXT ·libc_kqueue_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_kqueue(SB)
|
||||||
|
TEXT ·libc_lchown_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_lchown(SB)
|
||||||
|
TEXT ·libc_link_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_link(SB)
|
||||||
|
TEXT ·libc_listen_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_listen(SB)
|
||||||
|
TEXT ·libc_lstat_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_lstat(SB)
|
||||||
|
TEXT ·libc_mkdir_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_mkdir(SB)
|
||||||
|
TEXT ·libc_mkfifo_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_mkfifo(SB)
|
||||||
|
TEXT ·libc_mknod_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_mknod(SB)
|
||||||
|
TEXT ·libc_nanosleep_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_nanosleep(SB)
|
||||||
|
TEXT ·libc_open_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_open(SB)
|
||||||
|
TEXT ·libc_pathconf_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_pathconf(SB)
|
||||||
|
TEXT ·libc_pread_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_pread(SB)
|
||||||
|
TEXT ·libc_pwrite_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_pwrite(SB)
|
||||||
|
TEXT ·libc_read_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_read(SB)
|
||||||
|
TEXT ·libc_readlink_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_readlink(SB)
|
||||||
|
TEXT ·libc_rename_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_rename(SB)
|
||||||
|
TEXT ·libc_revoke_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_revoke(SB)
|
||||||
|
TEXT ·libc_rmdir_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_rmdir(SB)
|
||||||
|
TEXT ·libc_select_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_select(SB)
|
||||||
|
TEXT ·libc_setegid_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_setegid(SB)
|
||||||
|
TEXT ·libc_seteuid_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_seteuid(SB)
|
||||||
|
TEXT ·libc_setgid_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_setgid(SB)
|
||||||
|
TEXT ·libc_setlogin_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_setlogin(SB)
|
||||||
|
TEXT ·libc_setpgid_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_setpgid(SB)
|
||||||
|
TEXT ·libc_setpriority_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_setpriority(SB)
|
||||||
|
TEXT ·libc_setregid_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_setregid(SB)
|
||||||
|
TEXT ·libc_setreuid_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_setreuid(SB)
|
||||||
|
TEXT ·libc_setrlimit_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_setrlimit(SB)
|
||||||
|
TEXT ·libc_setsid_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_setsid(SB)
|
||||||
|
TEXT ·libc_settimeofday_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_settimeofday(SB)
|
||||||
|
TEXT ·libc_setuid_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_setuid(SB)
|
||||||
|
TEXT ·libc_stat_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_stat(SB)
|
||||||
|
TEXT ·libc_statfs_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_statfs(SB)
|
||||||
|
TEXT ·libc_symlink_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_symlink(SB)
|
||||||
|
TEXT ·libc_sync_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_sync(SB)
|
||||||
|
TEXT ·libc_truncate_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_truncate(SB)
|
||||||
|
TEXT ·libc_umask_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_umask(SB)
|
||||||
|
TEXT ·libc_unlink_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_unlink(SB)
|
||||||
|
TEXT ·libc_unmount_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_unmount(SB)
|
||||||
|
TEXT ·libc_write_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_write(SB)
|
||||||
|
TEXT ·libc_mmap_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_mmap(SB)
|
||||||
|
TEXT ·libc_munmap_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_munmap(SB)
|
||||||
|
TEXT ·libc_utimensat_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_utimensat(SB)
|
||||||
|
TEXT ·libc_syscall_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_syscall(SB)
|
||||||
|
TEXT ·libc_lseek_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_lseek(SB)
|
||||||
|
TEXT ·libc_getcwd_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_getcwd(SB)
|
||||||
|
TEXT ·libc_sysctl_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_sysctl(SB)
|
||||||
|
TEXT ·libc_fork_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_fork(SB)
|
||||||
|
TEXT ·libc_ioctl_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_ioctl(SB)
|
||||||
|
TEXT ·libc_execve_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_execve(SB)
|
||||||
|
TEXT ·libc_exit_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_exit(SB)
|
||||||
|
TEXT ·libc_ptrace_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_ptrace(SB)
|
||||||
|
TEXT ·libc_getentropy_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_getentropy(SB)
|
||||||
|
TEXT ·libc_fstatat_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_fstatat(SB)
|
||||||
|
TEXT ·libc_unlinkat_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_unlinkat(SB)
|
||||||
|
TEXT ·libc_openat_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_openat(SB)
|
||||||
28
test/closure7.go
Normal file
28
test/closure7.go
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
// run
|
||||||
|
|
||||||
|
// Copyright 2020 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
func g(f func()) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Must have exportable name
|
||||||
|
func F() {
|
||||||
|
g(func() {
|
||||||
|
ch := make(chan int)
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ch:
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
F()
|
||||||
|
}
|
||||||
|
|
@ -59,10 +59,10 @@ func f(n int) {
|
||||||
ill := make([]byte, 64)
|
ill := make([]byte, 64)
|
||||||
switch runtime.GOARCH {
|
switch runtime.GOARCH {
|
||||||
case "386", "amd64":
|
case "386", "amd64":
|
||||||
ill = append(ill, 0x89, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00) // MOVL AX, 0
|
ill = append(ill[:0], 0x89, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00) // MOVL AX, 0
|
||||||
case "arm":
|
case "arm":
|
||||||
binary.LittleEndian.PutUint32(ill, 0xe3a00000) // MOVW $0, R0
|
binary.LittleEndian.PutUint32(ill[0:4], 0xe3a00000) // MOVW $0, R0
|
||||||
binary.LittleEndian.PutUint32(ill, 0xe5800000) // MOVW R0, (R0)
|
binary.LittleEndian.PutUint32(ill[4:8], 0xe5800000) // MOVW R0, (R0)
|
||||||
case "arm64":
|
case "arm64":
|
||||||
binary.LittleEndian.PutUint32(ill, 0xf90003ff) // MOVD ZR, (ZR)
|
binary.LittleEndian.PutUint32(ill, 0xf90003ff) // MOVD ZR, (ZR)
|
||||||
case "ppc64":
|
case "ppc64":
|
||||||
|
|
@ -74,7 +74,7 @@ func f(n int) {
|
||||||
case "mipsle", "mips64le":
|
case "mipsle", "mips64le":
|
||||||
binary.LittleEndian.PutUint32(ill, 0xfc000000) // MOVV R0, (R0)
|
binary.LittleEndian.PutUint32(ill, 0xfc000000) // MOVV R0, (R0)
|
||||||
case "s390x":
|
case "s390x":
|
||||||
ill = append(ill, 0xa7, 0x09, 0x00, 0x00) // MOVD $0, R0
|
ill = append(ill[:0], 0xa7, 0x09, 0x00, 0x00) // MOVD $0, R0
|
||||||
ill = append(ill, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x24) // MOVD R0, (R0)
|
ill = append(ill, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x24) // MOVD R0, (R0)
|
||||||
case "riscv64":
|
case "riscv64":
|
||||||
binary.LittleEndian.PutUint32(ill, 0x00003023) // MOV X0, (X0)
|
binary.LittleEndian.PutUint32(ill, 0x00003023) // MOV X0, (X0)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue