2016-03-01 22:57:46 +00:00
|
|
|
// Copyright 2014 The Go Authors. All rights reserved.
|
2014-08-25 15:59:13 +10:00
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
|
|
package runtime
|
|
|
|
|
|
|
|
|
|
import (
|
2020-10-22 16:29:04 +00:00
|
|
|
"internal/abi"
|
runtime,cmd/cgo: simplify C -> Go call path
This redesigns the way calls work from C to exported Go functions. It
removes several steps from the call path, makes cmd/cgo no longer
sensitive to the Go calling convention, and eliminates the use of
reflectcall from cgo.
In order to avoid generating a large amount of FFI glue between the C
and Go ABIs, the cgo tool has long depended on generating a C function
that marshals the arguments into a struct, and then the actual ABI
switch happens in functions with fixed signatures that simply take a
pointer to this struct. In a way, this CL simply pushes this idea
further.
Currently, the cgo tool generates this argument struct in the exact
layout of the Go stack frame and depends on reflectcall to unpack it
into the appropriate Go call (even though it's actually
reflectcall'ing a function generated by cgo).
In this CL, we decouple this struct from the Go stack layout. Instead,
cgo generates a Go function that takes the struct, unpacks it, and
calls the exported function. Since this generated function has a
generic signature (like the rest of the call path), we don't need
reflectcall and can instead depend on the Go compiler itself to
implement the call to the exported Go function.
One complication is that syscall.NewCallback on Windows, which
converts a Go function into a C function pointer, depends on
cgocallback's current dynamic calling approach since the signatures of
the callbacks aren't known statically. For this specific case, we
continue to depend on reflectcall. Really, the current approach makes
some overly simplistic assumptions about translating the C ABI to the
Go ABI. Now we're at least in a much better position to do a proper
ABI translation.
For comparison, the current cgo call path looks like:
GoF (generated C function) ->
crosscall2 (in cgo/asm_*.s) ->
_cgoexp_GoF (generated Go function) ->
cgocallback (in asm_*.s) ->
cgocallback_gofunc (in asm_*.s) ->
cgocallbackg (in cgocall.go) ->
cgocallbackg1 (in cgocall.go) ->
reflectcall (in asm_*.s) ->
_cgoexpwrap_GoF (generated Go function) ->
p.GoF
Now the call path looks like:
GoF (generated C function) ->
crosscall2 (in cgo/asm_*.s) ->
cgocallback (in asm_*.s) ->
cgocallbackg (in cgocall.go) ->
cgocallbackg1 (in cgocall.go) ->
_cgoexp_GoF (generated Go function) ->
p.GoF
Notably:
1. We combine _cgoexp_GoF and _cgoexpwrap_GoF and move the combined
operation to the end of the sequence. This combined function also
handles reflectcall's previous role.
2. We combined cgocallback and cgocallback_gofunc since the only
purpose of having both was to convert a raw PC into a Go function
value. We instead construct the Go function value in cgocallbackg1.
3. cgocallbackg1 no longer reaches backwards through the stack to get
the arguments to cgocallback_gofunc. Instead, we just pass the
arguments down.
4. Currently, we need an explicit msanwrite to mark the results struct
as written because reflectcall doesn't do this. Now, the results are
written by regular Go assignments, so the Go compiler generates the
necessary MSAN annotations. This also means we no longer need to track
the size of the arguments frame.
Updates #40724, since now we don't need to teach cgo about the
register ABI or change how it uses reflectcall.
Change-Id: I7840489a2597962aeb670e0c1798a16a7359c94f
Reviewed-on: https://go-review.googlesource.com/c/go/+/258938
Trust: Austin Clements <austin@google.com>
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
2020-10-01 17:22:38 -04:00
|
|
|
"runtime/internal/sys"
|
2014-08-25 15:59:13 +10:00
|
|
|
"unsafe"
|
|
|
|
|
)
|
|
|
|
|
|
2020-10-03 19:52:08 -04:00
|
|
|
// cbs stores all registered Go callbacks.
|
|
|
|
|
var cbs struct {
|
|
|
|
|
lock mutex
|
|
|
|
|
ctxt [cb_max]winCallback
|
|
|
|
|
index map[winCallbackKey]int
|
|
|
|
|
n int
|
2014-08-25 15:59:13 +10:00
|
|
|
}
|
|
|
|
|
|
2020-10-03 19:52:08 -04:00
|
|
|
// winCallback records information about a registered Go callback.
|
|
|
|
|
type winCallback struct {
|
runtime: fix sub-uintptr-sized Windows callback arguments
The Windows callback support accepts Go functions with arguments that
are uintptr-sized or smaller. However, it doesn't implement smaller
arguments correctly. It assumes the Windows arguments layout is
equivalent to the Go argument layout. This is often true, but because
Windows C ABIs pad arguments to word size, while Go packs arguments,
the layout is different if there are multiple sub-word-size arguments
in a row. For example, a function with two uint16 arguments will have
a two-word C argument frame, but only a 4 byte Go argument frame.
There are also subtleties surrounding floating-point register
arguments that it doesn't handle correctly.
To fix this, when constructing a callback, we examine the Go
function's signature to construct a mapping between the C argument
frame and the Go argument frame. When the callback is invoked, we use
this mapping to build the Go argument frame and copy the result back.
This adds several test cases to TestStdcallAndCDeclCallbacks that
exercise more complex function signatures. These all fail with the
current code, but work with this CL.
In addition to fixing these callback types, this is also a step toward
the Go register ABI (#40724), which is going to make the ABI
translation more complex.
Change-Id: I19fb1681b659d9fd528ffd5e88912bebb95da052
Reviewed-on: https://go-review.googlesource.com/c/go/+/263271
Trust: Austin Clements <austin@google.com>
Trust: Alex Brainman <alex.brainman@gmail.com>
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
2020-10-17 18:42:03 -04:00
|
|
|
fn *funcval // Go function
|
|
|
|
|
retPop uintptr // For 386 cdecl, how many bytes to pop on return
|
|
|
|
|
|
|
|
|
|
// abiMap specifies how to translate from a C frame to a Go
|
|
|
|
|
// frame. This does not specify how to translate back because
|
|
|
|
|
// the result is always a uintptr. If the C ABI is fastcall,
|
|
|
|
|
// this assumes the four fastcall registers were first spilled
|
|
|
|
|
// to the shadow space.
|
|
|
|
|
abiMap []abiPart
|
|
|
|
|
// retOffset is the offset of the uintptr-sized result in the Go
|
|
|
|
|
// frame.
|
|
|
|
|
retOffset uintptr
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// abiPart encodes a step in translating between calling ABIs.
|
|
|
|
|
type abiPart struct {
|
|
|
|
|
src, dst uintptr
|
|
|
|
|
len uintptr
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (a *abiPart) tryMerge(b abiPart) bool {
|
|
|
|
|
if a.src+a.len == b.src && a.dst+a.len == b.dst {
|
|
|
|
|
a.len += b.len
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
return false
|
2014-08-25 15:59:13 +10:00
|
|
|
}
|
|
|
|
|
|
2020-10-03 19:52:08 -04:00
|
|
|
type winCallbackKey struct {
|
|
|
|
|
fn *funcval
|
|
|
|
|
cdecl bool
|
2014-08-25 15:59:13 +10:00
|
|
|
}
|
|
|
|
|
|
2018-08-08 14:44:42 -07:00
|
|
|
func callbackasm()
|
|
|
|
|
|
2014-08-25 15:59:13 +10:00
|
|
|
// callbackasmAddr returns address of runtime.callbackasm
|
|
|
|
|
// function adjusted by i.
|
2018-08-08 14:44:42 -07:00
|
|
|
// On x86 and amd64, runtime.callbackasm is a series of CALL instructions,
|
|
|
|
|
// and we want callback to arrive at
|
2014-08-25 15:59:13 +10:00
|
|
|
// correspondent call instruction instead of start of
|
|
|
|
|
// runtime.callbackasm.
|
2018-08-08 14:44:42 -07:00
|
|
|
// On ARM, runtime.callbackasm is a series of mov and branch instructions.
|
|
|
|
|
// R12 is loaded with the callback index. Each entry is two instructions,
|
|
|
|
|
// hence 8 bytes.
|
2014-08-25 15:59:13 +10:00
|
|
|
func callbackasmAddr(i int) uintptr {
|
2018-08-08 14:44:42 -07:00
|
|
|
var entrySize int
|
|
|
|
|
switch GOARCH {
|
|
|
|
|
default:
|
|
|
|
|
panic("unsupported architecture")
|
|
|
|
|
case "386", "amd64":
|
|
|
|
|
entrySize = 5
|
2021-01-22 15:16:13 -05:00
|
|
|
case "arm", "arm64":
|
|
|
|
|
// On ARM and ARM64, each entry is a MOV instruction
|
2018-08-08 14:44:42 -07:00
|
|
|
// followed by a branch instruction
|
|
|
|
|
entrySize = 8
|
|
|
|
|
}
|
|
|
|
|
return funcPC(callbackasm) + uintptr(i*entrySize)
|
2014-08-25 15:59:13 +10:00
|
|
|
}
|
|
|
|
|
|
runtime: fix sub-uintptr-sized Windows callback arguments
The Windows callback support accepts Go functions with arguments that
are uintptr-sized or smaller. However, it doesn't implement smaller
arguments correctly. It assumes the Windows arguments layout is
equivalent to the Go argument layout. This is often true, but because
Windows C ABIs pad arguments to word size, while Go packs arguments,
the layout is different if there are multiple sub-word-size arguments
in a row. For example, a function with two uint16 arguments will have
a two-word C argument frame, but only a 4 byte Go argument frame.
There are also subtleties surrounding floating-point register
arguments that it doesn't handle correctly.
To fix this, when constructing a callback, we examine the Go
function's signature to construct a mapping between the C argument
frame and the Go argument frame. When the callback is invoked, we use
this mapping to build the Go argument frame and copy the result back.
This adds several test cases to TestStdcallAndCDeclCallbacks that
exercise more complex function signatures. These all fail with the
current code, but work with this CL.
In addition to fixing these callback types, this is also a step toward
the Go register ABI (#40724), which is going to make the ABI
translation more complex.
Change-Id: I19fb1681b659d9fd528ffd5e88912bebb95da052
Reviewed-on: https://go-review.googlesource.com/c/go/+/263271
Trust: Austin Clements <austin@google.com>
Trust: Alex Brainman <alex.brainman@gmail.com>
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
2020-10-17 18:42:03 -04:00
|
|
|
const callbackMaxFrame = 64 * sys.PtrSize
|
runtime,cmd/cgo: simplify C -> Go call path
This redesigns the way calls work from C to exported Go functions. It
removes several steps from the call path, makes cmd/cgo no longer
sensitive to the Go calling convention, and eliminates the use of
reflectcall from cgo.
In order to avoid generating a large amount of FFI glue between the C
and Go ABIs, the cgo tool has long depended on generating a C function
that marshals the arguments into a struct, and then the actual ABI
switch happens in functions with fixed signatures that simply take a
pointer to this struct. In a way, this CL simply pushes this idea
further.
Currently, the cgo tool generates this argument struct in the exact
layout of the Go stack frame and depends on reflectcall to unpack it
into the appropriate Go call (even though it's actually
reflectcall'ing a function generated by cgo).
In this CL, we decouple this struct from the Go stack layout. Instead,
cgo generates a Go function that takes the struct, unpacks it, and
calls the exported function. Since this generated function has a
generic signature (like the rest of the call path), we don't need
reflectcall and can instead depend on the Go compiler itself to
implement the call to the exported Go function.
One complication is that syscall.NewCallback on Windows, which
converts a Go function into a C function pointer, depends on
cgocallback's current dynamic calling approach since the signatures of
the callbacks aren't known statically. For this specific case, we
continue to depend on reflectcall. Really, the current approach makes
some overly simplistic assumptions about translating the C ABI to the
Go ABI. Now we're at least in a much better position to do a proper
ABI translation.
For comparison, the current cgo call path looks like:
GoF (generated C function) ->
crosscall2 (in cgo/asm_*.s) ->
_cgoexp_GoF (generated Go function) ->
cgocallback (in asm_*.s) ->
cgocallback_gofunc (in asm_*.s) ->
cgocallbackg (in cgocall.go) ->
cgocallbackg1 (in cgocall.go) ->
reflectcall (in asm_*.s) ->
_cgoexpwrap_GoF (generated Go function) ->
p.GoF
Now the call path looks like:
GoF (generated C function) ->
crosscall2 (in cgo/asm_*.s) ->
cgocallback (in asm_*.s) ->
cgocallbackg (in cgocall.go) ->
cgocallbackg1 (in cgocall.go) ->
_cgoexp_GoF (generated Go function) ->
p.GoF
Notably:
1. We combine _cgoexp_GoF and _cgoexpwrap_GoF and move the combined
operation to the end of the sequence. This combined function also
handles reflectcall's previous role.
2. We combined cgocallback and cgocallback_gofunc since the only
purpose of having both was to convert a raw PC into a Go function
value. We instead construct the Go function value in cgocallbackg1.
3. cgocallbackg1 no longer reaches backwards through the stack to get
the arguments to cgocallback_gofunc. Instead, we just pass the
arguments down.
4. Currently, we need an explicit msanwrite to mark the results struct
as written because reflectcall doesn't do this. Now, the results are
written by regular Go assignments, so the Go compiler generates the
necessary MSAN annotations. This also means we no longer need to track
the size of the arguments frame.
Updates #40724, since now we don't need to teach cgo about the
register ABI or change how it uses reflectcall.
Change-Id: I7840489a2597962aeb670e0c1798a16a7359c94f
Reviewed-on: https://go-review.googlesource.com/c/go/+/258938
Trust: Austin Clements <austin@google.com>
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
2020-10-01 17:22:38 -04:00
|
|
|
|
2020-10-03 19:52:08 -04:00
|
|
|
// compileCallback converts a Go function fn into a C function pointer
|
|
|
|
|
// that can be passed to Windows APIs.
|
|
|
|
|
//
|
|
|
|
|
// On 386, if cdecl is true, the returned C function will use the
|
|
|
|
|
// cdecl calling convention; otherwise, it will use stdcall. On amd64,
|
|
|
|
|
// it always uses fastcall. On arm, it always uses the ARM convention.
|
|
|
|
|
//
|
2014-12-23 15:33:51 +11:00
|
|
|
//go:linkname compileCallback syscall.compileCallback
|
2020-10-03 19:52:08 -04:00
|
|
|
func compileCallback(fn eface, cdecl bool) (code uintptr) {
|
|
|
|
|
if GOARCH != "386" {
|
|
|
|
|
// cdecl is only meaningful on 386.
|
|
|
|
|
cdecl = false
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-25 15:59:13 +10:00
|
|
|
if fn._type == nil || (fn._type.kind&kindMask) != kindFunc {
|
2018-07-27 15:52:36 +00:00
|
|
|
panic("compileCallback: expected function with one uintptr-sized result")
|
2014-08-25 15:59:13 +10:00
|
|
|
}
|
|
|
|
|
ft := (*functype)(unsafe.Pointer(fn._type))
|
runtime: fix sub-uintptr-sized Windows callback arguments
The Windows callback support accepts Go functions with arguments that
are uintptr-sized or smaller. However, it doesn't implement smaller
arguments correctly. It assumes the Windows arguments layout is
equivalent to the Go argument layout. This is often true, but because
Windows C ABIs pad arguments to word size, while Go packs arguments,
the layout is different if there are multiple sub-word-size arguments
in a row. For example, a function with two uint16 arguments will have
a two-word C argument frame, but only a 4 byte Go argument frame.
There are also subtleties surrounding floating-point register
arguments that it doesn't handle correctly.
To fix this, when constructing a callback, we examine the Go
function's signature to construct a mapping between the C argument
frame and the Go argument frame. When the callback is invoked, we use
this mapping to build the Go argument frame and copy the result back.
This adds several test cases to TestStdcallAndCDeclCallbacks that
exercise more complex function signatures. These all fail with the
current code, but work with this CL.
In addition to fixing these callback types, this is also a step toward
the Go register ABI (#40724), which is going to make the ABI
translation more complex.
Change-Id: I19fb1681b659d9fd528ffd5e88912bebb95da052
Reviewed-on: https://go-review.googlesource.com/c/go/+/263271
Trust: Austin Clements <austin@google.com>
Trust: Alex Brainman <alex.brainman@gmail.com>
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
2020-10-17 18:42:03 -04:00
|
|
|
|
|
|
|
|
// Check arguments and construct ABI translation.
|
|
|
|
|
var abiMap []abiPart
|
|
|
|
|
var src, dst uintptr
|
|
|
|
|
for _, t := range ft.in() {
|
|
|
|
|
if t.size > sys.PtrSize {
|
|
|
|
|
// We don't support this right now. In
|
|
|
|
|
// stdcall/cdecl, 64-bit ints and doubles are
|
|
|
|
|
// passed as two words (little endian); and
|
|
|
|
|
// structs are pushed on the stack. In
|
|
|
|
|
// fastcall, arguments larger than the word
|
2020-11-18 21:38:57 +01:00
|
|
|
// size are passed by reference. On arm,
|
|
|
|
|
// 8-byte aligned arguments round up to the
|
|
|
|
|
// next even register and can be split across
|
|
|
|
|
// registers and the stack.
|
runtime: fix sub-uintptr-sized Windows callback arguments
The Windows callback support accepts Go functions with arguments that
are uintptr-sized or smaller. However, it doesn't implement smaller
arguments correctly. It assumes the Windows arguments layout is
equivalent to the Go argument layout. This is often true, but because
Windows C ABIs pad arguments to word size, while Go packs arguments,
the layout is different if there are multiple sub-word-size arguments
in a row. For example, a function with two uint16 arguments will have
a two-word C argument frame, but only a 4 byte Go argument frame.
There are also subtleties surrounding floating-point register
arguments that it doesn't handle correctly.
To fix this, when constructing a callback, we examine the Go
function's signature to construct a mapping between the C argument
frame and the Go argument frame. When the callback is invoked, we use
this mapping to build the Go argument frame and copy the result back.
This adds several test cases to TestStdcallAndCDeclCallbacks that
exercise more complex function signatures. These all fail with the
current code, but work with this CL.
In addition to fixing these callback types, this is also a step toward
the Go register ABI (#40724), which is going to make the ABI
translation more complex.
Change-Id: I19fb1681b659d9fd528ffd5e88912bebb95da052
Reviewed-on: https://go-review.googlesource.com/c/go/+/263271
Trust: Austin Clements <austin@google.com>
Trust: Alex Brainman <alex.brainman@gmail.com>
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
2020-10-17 18:42:03 -04:00
|
|
|
panic("compileCallback: argument size is larger than uintptr")
|
|
|
|
|
}
|
2021-01-28 09:23:35 -05:00
|
|
|
if k := t.kind & kindMask; GOARCH != "386" && (k == kindFloat32 || k == kindFloat64) {
|
runtime: fix sub-uintptr-sized Windows callback arguments
The Windows callback support accepts Go functions with arguments that
are uintptr-sized or smaller. However, it doesn't implement smaller
arguments correctly. It assumes the Windows arguments layout is
equivalent to the Go argument layout. This is often true, but because
Windows C ABIs pad arguments to word size, while Go packs arguments,
the layout is different if there are multiple sub-word-size arguments
in a row. For example, a function with two uint16 arguments will have
a two-word C argument frame, but only a 4 byte Go argument frame.
There are also subtleties surrounding floating-point register
arguments that it doesn't handle correctly.
To fix this, when constructing a callback, we examine the Go
function's signature to construct a mapping between the C argument
frame and the Go argument frame. When the callback is invoked, we use
this mapping to build the Go argument frame and copy the result back.
This adds several test cases to TestStdcallAndCDeclCallbacks that
exercise more complex function signatures. These all fail with the
current code, but work with this CL.
In addition to fixing these callback types, this is also a step toward
the Go register ABI (#40724), which is going to make the ABI
translation more complex.
Change-Id: I19fb1681b659d9fd528ffd5e88912bebb95da052
Reviewed-on: https://go-review.googlesource.com/c/go/+/263271
Trust: Austin Clements <austin@google.com>
Trust: Alex Brainman <alex.brainman@gmail.com>
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
2020-10-17 18:42:03 -04:00
|
|
|
// In fastcall, floating-point arguments in
|
|
|
|
|
// the first four positions are passed in
|
|
|
|
|
// floating-point registers, which we don't
|
2020-11-18 21:38:57 +01:00
|
|
|
// currently spill. arm passes floating-point
|
|
|
|
|
// arguments in VFP registers, which we also
|
|
|
|
|
// don't support.
|
2021-01-28 09:23:35 -05:00
|
|
|
// So basically we only support 386.
|
runtime: fix sub-uintptr-sized Windows callback arguments
The Windows callback support accepts Go functions with arguments that
are uintptr-sized or smaller. However, it doesn't implement smaller
arguments correctly. It assumes the Windows arguments layout is
equivalent to the Go argument layout. This is often true, but because
Windows C ABIs pad arguments to word size, while Go packs arguments,
the layout is different if there are multiple sub-word-size arguments
in a row. For example, a function with two uint16 arguments will have
a two-word C argument frame, but only a 4 byte Go argument frame.
There are also subtleties surrounding floating-point register
arguments that it doesn't handle correctly.
To fix this, when constructing a callback, we examine the Go
function's signature to construct a mapping between the C argument
frame and the Go argument frame. When the callback is invoked, we use
this mapping to build the Go argument frame and copy the result back.
This adds several test cases to TestStdcallAndCDeclCallbacks that
exercise more complex function signatures. These all fail with the
current code, but work with this CL.
In addition to fixing these callback types, this is also a step toward
the Go register ABI (#40724), which is going to make the ABI
translation more complex.
Change-Id: I19fb1681b659d9fd528ffd5e88912bebb95da052
Reviewed-on: https://go-review.googlesource.com/c/go/+/263271
Trust: Austin Clements <austin@google.com>
Trust: Alex Brainman <alex.brainman@gmail.com>
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
2020-10-17 18:42:03 -04:00
|
|
|
panic("compileCallback: float arguments not supported")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The Go ABI aligns arguments.
|
|
|
|
|
dst = alignUp(dst, uintptr(t.align))
|
|
|
|
|
// In the C ABI, we're already on a word boundary.
|
|
|
|
|
// Also, sub-word-sized fastcall register arguments
|
|
|
|
|
// are stored to the least-significant bytes of the
|
|
|
|
|
// argument word and all supported Windows
|
|
|
|
|
// architectures are little endian, so src is already
|
|
|
|
|
// pointing to the right place for smaller arguments.
|
2020-11-18 21:38:57 +01:00
|
|
|
// The same is true on arm.
|
runtime: fix sub-uintptr-sized Windows callback arguments
The Windows callback support accepts Go functions with arguments that
are uintptr-sized or smaller. However, it doesn't implement smaller
arguments correctly. It assumes the Windows arguments layout is
equivalent to the Go argument layout. This is often true, but because
Windows C ABIs pad arguments to word size, while Go packs arguments,
the layout is different if there are multiple sub-word-size arguments
in a row. For example, a function with two uint16 arguments will have
a two-word C argument frame, but only a 4 byte Go argument frame.
There are also subtleties surrounding floating-point register
arguments that it doesn't handle correctly.
To fix this, when constructing a callback, we examine the Go
function's signature to construct a mapping between the C argument
frame and the Go argument frame. When the callback is invoked, we use
this mapping to build the Go argument frame and copy the result back.
This adds several test cases to TestStdcallAndCDeclCallbacks that
exercise more complex function signatures. These all fail with the
current code, but work with this CL.
In addition to fixing these callback types, this is also a step toward
the Go register ABI (#40724), which is going to make the ABI
translation more complex.
Change-Id: I19fb1681b659d9fd528ffd5e88912bebb95da052
Reviewed-on: https://go-review.googlesource.com/c/go/+/263271
Trust: Austin Clements <austin@google.com>
Trust: Alex Brainman <alex.brainman@gmail.com>
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
2020-10-17 18:42:03 -04:00
|
|
|
|
|
|
|
|
// Copy just the size of the argument. Note that this
|
|
|
|
|
// could be a small by-value struct, but C and Go
|
|
|
|
|
// struct layouts are compatible, so we can copy these
|
|
|
|
|
// directly, too.
|
|
|
|
|
part := abiPart{src, dst, t.size}
|
|
|
|
|
// Add this step to the adapter.
|
|
|
|
|
if len(abiMap) == 0 || !abiMap[len(abiMap)-1].tryMerge(part) {
|
|
|
|
|
abiMap = append(abiMap, part)
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-18 21:38:57 +01:00
|
|
|
// cdecl, stdcall, fastcall, and arm pad arguments to word size.
|
2021-02-01 15:12:08 -05:00
|
|
|
// TODO(rsc): On arm and arm64 do we need to skip the caller's saved LR?
|
runtime: fix sub-uintptr-sized Windows callback arguments
The Windows callback support accepts Go functions with arguments that
are uintptr-sized or smaller. However, it doesn't implement smaller
arguments correctly. It assumes the Windows arguments layout is
equivalent to the Go argument layout. This is often true, but because
Windows C ABIs pad arguments to word size, while Go packs arguments,
the layout is different if there are multiple sub-word-size arguments
in a row. For example, a function with two uint16 arguments will have
a two-word C argument frame, but only a 4 byte Go argument frame.
There are also subtleties surrounding floating-point register
arguments that it doesn't handle correctly.
To fix this, when constructing a callback, we examine the Go
function's signature to construct a mapping between the C argument
frame and the Go argument frame. When the callback is invoked, we use
this mapping to build the Go argument frame and copy the result back.
This adds several test cases to TestStdcallAndCDeclCallbacks that
exercise more complex function signatures. These all fail with the
current code, but work with this CL.
In addition to fixing these callback types, this is also a step toward
the Go register ABI (#40724), which is going to make the ABI
translation more complex.
Change-Id: I19fb1681b659d9fd528ffd5e88912bebb95da052
Reviewed-on: https://go-review.googlesource.com/c/go/+/263271
Trust: Austin Clements <austin@google.com>
Trust: Alex Brainman <alex.brainman@gmail.com>
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
2020-10-17 18:42:03 -04:00
|
|
|
src += sys.PtrSize
|
|
|
|
|
// The Go ABI packs arguments.
|
|
|
|
|
dst += t.size
|
|
|
|
|
}
|
|
|
|
|
// The Go ABI aligns the result to the word size. src is
|
|
|
|
|
// already aligned.
|
|
|
|
|
dst = alignUp(dst, sys.PtrSize)
|
|
|
|
|
retOffset := dst
|
|
|
|
|
|
2016-02-23 11:31:13 -05:00
|
|
|
if len(ft.out()) != 1 {
|
2018-07-27 15:52:36 +00:00
|
|
|
panic("compileCallback: expected function with one uintptr-sized result")
|
2014-08-25 15:59:13 +10:00
|
|
|
}
|
runtime: fix sub-uintptr-sized Windows callback arguments
The Windows callback support accepts Go functions with arguments that
are uintptr-sized or smaller. However, it doesn't implement smaller
arguments correctly. It assumes the Windows arguments layout is
equivalent to the Go argument layout. This is often true, but because
Windows C ABIs pad arguments to word size, while Go packs arguments,
the layout is different if there are multiple sub-word-size arguments
in a row. For example, a function with two uint16 arguments will have
a two-word C argument frame, but only a 4 byte Go argument frame.
There are also subtleties surrounding floating-point register
arguments that it doesn't handle correctly.
To fix this, when constructing a callback, we examine the Go
function's signature to construct a mapping between the C argument
frame and the Go argument frame. When the callback is invoked, we use
this mapping to build the Go argument frame and copy the result back.
This adds several test cases to TestStdcallAndCDeclCallbacks that
exercise more complex function signatures. These all fail with the
current code, but work with this CL.
In addition to fixing these callback types, this is also a step toward
the Go register ABI (#40724), which is going to make the ABI
translation more complex.
Change-Id: I19fb1681b659d9fd528ffd5e88912bebb95da052
Reviewed-on: https://go-review.googlesource.com/c/go/+/263271
Trust: Austin Clements <austin@google.com>
Trust: Alex Brainman <alex.brainman@gmail.com>
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
2020-10-17 18:42:03 -04:00
|
|
|
if ft.out()[0].size != sys.PtrSize {
|
2018-07-27 15:52:36 +00:00
|
|
|
panic("compileCallback: expected function with one uintptr-sized result")
|
2014-08-25 15:59:13 +10:00
|
|
|
}
|
runtime: fix sub-uintptr-sized Windows callback arguments
The Windows callback support accepts Go functions with arguments that
are uintptr-sized or smaller. However, it doesn't implement smaller
arguments correctly. It assumes the Windows arguments layout is
equivalent to the Go argument layout. This is often true, but because
Windows C ABIs pad arguments to word size, while Go packs arguments,
the layout is different if there are multiple sub-word-size arguments
in a row. For example, a function with two uint16 arguments will have
a two-word C argument frame, but only a 4 byte Go argument frame.
There are also subtleties surrounding floating-point register
arguments that it doesn't handle correctly.
To fix this, when constructing a callback, we examine the Go
function's signature to construct a mapping between the C argument
frame and the Go argument frame. When the callback is invoked, we use
this mapping to build the Go argument frame and copy the result back.
This adds several test cases to TestStdcallAndCDeclCallbacks that
exercise more complex function signatures. These all fail with the
current code, but work with this CL.
In addition to fixing these callback types, this is also a step toward
the Go register ABI (#40724), which is going to make the ABI
translation more complex.
Change-Id: I19fb1681b659d9fd528ffd5e88912bebb95da052
Reviewed-on: https://go-review.googlesource.com/c/go/+/263271
Trust: Austin Clements <austin@google.com>
Trust: Alex Brainman <alex.brainman@gmail.com>
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
2020-10-17 18:42:03 -04:00
|
|
|
if k := ft.out()[0].kind & kindMask; k == kindFloat32 || k == kindFloat64 {
|
|
|
|
|
// In cdecl and stdcall, float results are returned in
|
|
|
|
|
// ST(0). In fastcall, they're returned in XMM0.
|
|
|
|
|
// Either way, it's not AX.
|
|
|
|
|
panic("compileCallback: float results not supported")
|
runtime,cmd/cgo: simplify C -> Go call path
This redesigns the way calls work from C to exported Go functions. It
removes several steps from the call path, makes cmd/cgo no longer
sensitive to the Go calling convention, and eliminates the use of
reflectcall from cgo.
In order to avoid generating a large amount of FFI glue between the C
and Go ABIs, the cgo tool has long depended on generating a C function
that marshals the arguments into a struct, and then the actual ABI
switch happens in functions with fixed signatures that simply take a
pointer to this struct. In a way, this CL simply pushes this idea
further.
Currently, the cgo tool generates this argument struct in the exact
layout of the Go stack frame and depends on reflectcall to unpack it
into the appropriate Go call (even though it's actually
reflectcall'ing a function generated by cgo).
In this CL, we decouple this struct from the Go stack layout. Instead,
cgo generates a Go function that takes the struct, unpacks it, and
calls the exported function. Since this generated function has a
generic signature (like the rest of the call path), we don't need
reflectcall and can instead depend on the Go compiler itself to
implement the call to the exported Go function.
One complication is that syscall.NewCallback on Windows, which
converts a Go function into a C function pointer, depends on
cgocallback's current dynamic calling approach since the signatures of
the callbacks aren't known statically. For this specific case, we
continue to depend on reflectcall. Really, the current approach makes
some overly simplistic assumptions about translating the C ABI to the
Go ABI. Now we're at least in a much better position to do a proper
ABI translation.
For comparison, the current cgo call path looks like:
GoF (generated C function) ->
crosscall2 (in cgo/asm_*.s) ->
_cgoexp_GoF (generated Go function) ->
cgocallback (in asm_*.s) ->
cgocallback_gofunc (in asm_*.s) ->
cgocallbackg (in cgocall.go) ->
cgocallbackg1 (in cgocall.go) ->
reflectcall (in asm_*.s) ->
_cgoexpwrap_GoF (generated Go function) ->
p.GoF
Now the call path looks like:
GoF (generated C function) ->
crosscall2 (in cgo/asm_*.s) ->
cgocallback (in asm_*.s) ->
cgocallbackg (in cgocall.go) ->
cgocallbackg1 (in cgocall.go) ->
_cgoexp_GoF (generated Go function) ->
p.GoF
Notably:
1. We combine _cgoexp_GoF and _cgoexpwrap_GoF and move the combined
operation to the end of the sequence. This combined function also
handles reflectcall's previous role.
2. We combined cgocallback and cgocallback_gofunc since the only
purpose of having both was to convert a raw PC into a Go function
value. We instead construct the Go function value in cgocallbackg1.
3. cgocallbackg1 no longer reaches backwards through the stack to get
the arguments to cgocallback_gofunc. Instead, we just pass the
arguments down.
4. Currently, we need an explicit msanwrite to mark the results struct
as written because reflectcall doesn't do this. Now, the results are
written by regular Go assignments, so the Go compiler generates the
necessary MSAN annotations. This also means we no longer need to track
the size of the arguments frame.
Updates #40724, since now we don't need to teach cgo about the
register ABI or change how it uses reflectcall.
Change-Id: I7840489a2597962aeb670e0c1798a16a7359c94f
Reviewed-on: https://go-review.googlesource.com/c/go/+/258938
Trust: Austin Clements <austin@google.com>
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
2020-10-01 17:22:38 -04:00
|
|
|
}
|
runtime: fix sub-uintptr-sized Windows callback arguments
The Windows callback support accepts Go functions with arguments that
are uintptr-sized or smaller. However, it doesn't implement smaller
arguments correctly. It assumes the Windows arguments layout is
equivalent to the Go argument layout. This is often true, but because
Windows C ABIs pad arguments to word size, while Go packs arguments,
the layout is different if there are multiple sub-word-size arguments
in a row. For example, a function with two uint16 arguments will have
a two-word C argument frame, but only a 4 byte Go argument frame.
There are also subtleties surrounding floating-point register
arguments that it doesn't handle correctly.
To fix this, when constructing a callback, we examine the Go
function's signature to construct a mapping between the C argument
frame and the Go argument frame. When the callback is invoked, we use
this mapping to build the Go argument frame and copy the result back.
This adds several test cases to TestStdcallAndCDeclCallbacks that
exercise more complex function signatures. These all fail with the
current code, but work with this CL.
In addition to fixing these callback types, this is also a step toward
the Go register ABI (#40724), which is going to make the ABI
translation more complex.
Change-Id: I19fb1681b659d9fd528ffd5e88912bebb95da052
Reviewed-on: https://go-review.googlesource.com/c/go/+/263271
Trust: Austin Clements <austin@google.com>
Trust: Alex Brainman <alex.brainman@gmail.com>
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
2020-10-17 18:42:03 -04:00
|
|
|
// Make room for the uintptr-sized result.
|
|
|
|
|
dst += sys.PtrSize
|
|
|
|
|
|
|
|
|
|
if dst > callbackMaxFrame {
|
|
|
|
|
panic("compileCallback: function argument frame too large")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// For cdecl, the callee is responsible for popping its
|
|
|
|
|
// arguments from the C stack.
|
|
|
|
|
var retPop uintptr
|
|
|
|
|
if cdecl {
|
|
|
|
|
retPop = src
|
2014-08-25 15:59:13 +10:00
|
|
|
}
|
|
|
|
|
|
2020-10-03 19:52:08 -04:00
|
|
|
key := winCallbackKey{(*funcval)(fn.data), cdecl}
|
|
|
|
|
|
2019-08-27 06:46:16 -06:00
|
|
|
lock(&cbs.lock) // We don't unlock this in a defer because this is used from the system stack.
|
2014-08-25 15:59:13 +10:00
|
|
|
|
2020-10-03 19:52:08 -04:00
|
|
|
// Check if this callback is already registered.
|
|
|
|
|
if n, ok := cbs.index[key]; ok {
|
2019-08-27 06:46:16 -06:00
|
|
|
unlock(&cbs.lock)
|
2020-10-03 19:52:08 -04:00
|
|
|
return callbackasmAddr(n)
|
2014-08-25 15:59:13 +10:00
|
|
|
}
|
|
|
|
|
|
2020-10-03 19:52:08 -04:00
|
|
|
// Register the callback.
|
|
|
|
|
if cbs.index == nil {
|
|
|
|
|
cbs.index = make(map[winCallbackKey]int)
|
2014-08-25 15:59:13 +10:00
|
|
|
}
|
2020-10-03 19:52:08 -04:00
|
|
|
n := cbs.n
|
|
|
|
|
if n >= len(cbs.ctxt) {
|
|
|
|
|
unlock(&cbs.lock)
|
|
|
|
|
throw("too many callback functions")
|
|
|
|
|
}
|
runtime: fix sub-uintptr-sized Windows callback arguments
The Windows callback support accepts Go functions with arguments that
are uintptr-sized or smaller. However, it doesn't implement smaller
arguments correctly. It assumes the Windows arguments layout is
equivalent to the Go argument layout. This is often true, but because
Windows C ABIs pad arguments to word size, while Go packs arguments,
the layout is different if there are multiple sub-word-size arguments
in a row. For example, a function with two uint16 arguments will have
a two-word C argument frame, but only a 4 byte Go argument frame.
There are also subtleties surrounding floating-point register
arguments that it doesn't handle correctly.
To fix this, when constructing a callback, we examine the Go
function's signature to construct a mapping between the C argument
frame and the Go argument frame. When the callback is invoked, we use
this mapping to build the Go argument frame and copy the result back.
This adds several test cases to TestStdcallAndCDeclCallbacks that
exercise more complex function signatures. These all fail with the
current code, but work with this CL.
In addition to fixing these callback types, this is also a step toward
the Go register ABI (#40724), which is going to make the ABI
translation more complex.
Change-Id: I19fb1681b659d9fd528ffd5e88912bebb95da052
Reviewed-on: https://go-review.googlesource.com/c/go/+/263271
Trust: Austin Clements <austin@google.com>
Trust: Alex Brainman <alex.brainman@gmail.com>
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
2020-10-17 18:42:03 -04:00
|
|
|
c := winCallback{key.fn, retPop, abiMap, retOffset}
|
2014-08-25 15:59:13 +10:00
|
|
|
cbs.ctxt[n] = c
|
2020-10-03 19:52:08 -04:00
|
|
|
cbs.index[key] = n
|
2014-08-25 15:59:13 +10:00
|
|
|
cbs.n++
|
|
|
|
|
|
2019-08-27 06:46:16 -06:00
|
|
|
unlock(&cbs.lock)
|
2020-10-03 19:52:08 -04:00
|
|
|
return callbackasmAddr(n)
|
2014-08-25 15:59:13 +10:00
|
|
|
}
|
2014-09-14 21:25:44 -04:00
|
|
|
|
runtime,cmd/cgo: simplify C -> Go call path
This redesigns the way calls work from C to exported Go functions. It
removes several steps from the call path, makes cmd/cgo no longer
sensitive to the Go calling convention, and eliminates the use of
reflectcall from cgo.
In order to avoid generating a large amount of FFI glue between the C
and Go ABIs, the cgo tool has long depended on generating a C function
that marshals the arguments into a struct, and then the actual ABI
switch happens in functions with fixed signatures that simply take a
pointer to this struct. In a way, this CL simply pushes this idea
further.
Currently, the cgo tool generates this argument struct in the exact
layout of the Go stack frame and depends on reflectcall to unpack it
into the appropriate Go call (even though it's actually
reflectcall'ing a function generated by cgo).
In this CL, we decouple this struct from the Go stack layout. Instead,
cgo generates a Go function that takes the struct, unpacks it, and
calls the exported function. Since this generated function has a
generic signature (like the rest of the call path), we don't need
reflectcall and can instead depend on the Go compiler itself to
implement the call to the exported Go function.
One complication is that syscall.NewCallback on Windows, which
converts a Go function into a C function pointer, depends on
cgocallback's current dynamic calling approach since the signatures of
the callbacks aren't known statically. For this specific case, we
continue to depend on reflectcall. Really, the current approach makes
some overly simplistic assumptions about translating the C ABI to the
Go ABI. Now we're at least in a much better position to do a proper
ABI translation.
For comparison, the current cgo call path looks like:
GoF (generated C function) ->
crosscall2 (in cgo/asm_*.s) ->
_cgoexp_GoF (generated Go function) ->
cgocallback (in asm_*.s) ->
cgocallback_gofunc (in asm_*.s) ->
cgocallbackg (in cgocall.go) ->
cgocallbackg1 (in cgocall.go) ->
reflectcall (in asm_*.s) ->
_cgoexpwrap_GoF (generated Go function) ->
p.GoF
Now the call path looks like:
GoF (generated C function) ->
crosscall2 (in cgo/asm_*.s) ->
cgocallback (in asm_*.s) ->
cgocallbackg (in cgocall.go) ->
cgocallbackg1 (in cgocall.go) ->
_cgoexp_GoF (generated Go function) ->
p.GoF
Notably:
1. We combine _cgoexp_GoF and _cgoexpwrap_GoF and move the combined
operation to the end of the sequence. This combined function also
handles reflectcall's previous role.
2. We combined cgocallback and cgocallback_gofunc since the only
purpose of having both was to convert a raw PC into a Go function
value. We instead construct the Go function value in cgocallbackg1.
3. cgocallbackg1 no longer reaches backwards through the stack to get
the arguments to cgocallback_gofunc. Instead, we just pass the
arguments down.
4. Currently, we need an explicit msanwrite to mark the results struct
as written because reflectcall doesn't do this. Now, the results are
written by regular Go assignments, so the Go compiler generates the
necessary MSAN annotations. This also means we no longer need to track
the size of the arguments frame.
Updates #40724, since now we don't need to teach cgo about the
register ABI or change how it uses reflectcall.
Change-Id: I7840489a2597962aeb670e0c1798a16a7359c94f
Reviewed-on: https://go-review.googlesource.com/c/go/+/258938
Trust: Austin Clements <austin@google.com>
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
2020-10-01 17:22:38 -04:00
|
|
|
type callbackArgs struct {
|
|
|
|
|
index uintptr
|
2020-11-18 21:38:57 +01:00
|
|
|
// args points to the argument block.
|
|
|
|
|
//
|
|
|
|
|
// For cdecl and stdcall, all arguments are on the stack.
|
|
|
|
|
//
|
|
|
|
|
// For fastcall, the trampoline spills register arguments to
|
|
|
|
|
// the reserved spill slots below the stack arguments,
|
|
|
|
|
// resulting in a layout equivalent to stdcall.
|
|
|
|
|
//
|
|
|
|
|
// For arm, the trampoline stores the register arguments just
|
|
|
|
|
// below the stack arguments, so again we can treat it as one
|
|
|
|
|
// big stack arguments frame.
|
|
|
|
|
args unsafe.Pointer
|
runtime,cmd/cgo: simplify C -> Go call path
This redesigns the way calls work from C to exported Go functions. It
removes several steps from the call path, makes cmd/cgo no longer
sensitive to the Go calling convention, and eliminates the use of
reflectcall from cgo.
In order to avoid generating a large amount of FFI glue between the C
and Go ABIs, the cgo tool has long depended on generating a C function
that marshals the arguments into a struct, and then the actual ABI
switch happens in functions with fixed signatures that simply take a
pointer to this struct. In a way, this CL simply pushes this idea
further.
Currently, the cgo tool generates this argument struct in the exact
layout of the Go stack frame and depends on reflectcall to unpack it
into the appropriate Go call (even though it's actually
reflectcall'ing a function generated by cgo).
In this CL, we decouple this struct from the Go stack layout. Instead,
cgo generates a Go function that takes the struct, unpacks it, and
calls the exported function. Since this generated function has a
generic signature (like the rest of the call path), we don't need
reflectcall and can instead depend on the Go compiler itself to
implement the call to the exported Go function.
One complication is that syscall.NewCallback on Windows, which
converts a Go function into a C function pointer, depends on
cgocallback's current dynamic calling approach since the signatures of
the callbacks aren't known statically. For this specific case, we
continue to depend on reflectcall. Really, the current approach makes
some overly simplistic assumptions about translating the C ABI to the
Go ABI. Now we're at least in a much better position to do a proper
ABI translation.
For comparison, the current cgo call path looks like:
GoF (generated C function) ->
crosscall2 (in cgo/asm_*.s) ->
_cgoexp_GoF (generated Go function) ->
cgocallback (in asm_*.s) ->
cgocallback_gofunc (in asm_*.s) ->
cgocallbackg (in cgocall.go) ->
cgocallbackg1 (in cgocall.go) ->
reflectcall (in asm_*.s) ->
_cgoexpwrap_GoF (generated Go function) ->
p.GoF
Now the call path looks like:
GoF (generated C function) ->
crosscall2 (in cgo/asm_*.s) ->
cgocallback (in asm_*.s) ->
cgocallbackg (in cgocall.go) ->
cgocallbackg1 (in cgocall.go) ->
_cgoexp_GoF (generated Go function) ->
p.GoF
Notably:
1. We combine _cgoexp_GoF and _cgoexpwrap_GoF and move the combined
operation to the end of the sequence. This combined function also
handles reflectcall's previous role.
2. We combined cgocallback and cgocallback_gofunc since the only
purpose of having both was to convert a raw PC into a Go function
value. We instead construct the Go function value in cgocallbackg1.
3. cgocallbackg1 no longer reaches backwards through the stack to get
the arguments to cgocallback_gofunc. Instead, we just pass the
arguments down.
4. Currently, we need an explicit msanwrite to mark the results struct
as written because reflectcall doesn't do this. Now, the results are
written by regular Go assignments, so the Go compiler generates the
necessary MSAN annotations. This also means we no longer need to track
the size of the arguments frame.
Updates #40724, since now we don't need to teach cgo about the
register ABI or change how it uses reflectcall.
Change-Id: I7840489a2597962aeb670e0c1798a16a7359c94f
Reviewed-on: https://go-review.googlesource.com/c/go/+/258938
Trust: Austin Clements <austin@google.com>
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
2020-10-01 17:22:38 -04:00
|
|
|
// Below are out-args from callbackWrap
|
|
|
|
|
result uintptr
|
|
|
|
|
retPop uintptr // For 386 cdecl, how many bytes to pop on return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// callbackWrap is called by callbackasm to invoke a registered C callback.
|
|
|
|
|
func callbackWrap(a *callbackArgs) {
|
|
|
|
|
c := cbs.ctxt[a.index]
|
runtime: fix sub-uintptr-sized Windows callback arguments
The Windows callback support accepts Go functions with arguments that
are uintptr-sized or smaller. However, it doesn't implement smaller
arguments correctly. It assumes the Windows arguments layout is
equivalent to the Go argument layout. This is often true, but because
Windows C ABIs pad arguments to word size, while Go packs arguments,
the layout is different if there are multiple sub-word-size arguments
in a row. For example, a function with two uint16 arguments will have
a two-word C argument frame, but only a 4 byte Go argument frame.
There are also subtleties surrounding floating-point register
arguments that it doesn't handle correctly.
To fix this, when constructing a callback, we examine the Go
function's signature to construct a mapping between the C argument
frame and the Go argument frame. When the callback is invoked, we use
this mapping to build the Go argument frame and copy the result back.
This adds several test cases to TestStdcallAndCDeclCallbacks that
exercise more complex function signatures. These all fail with the
current code, but work with this CL.
In addition to fixing these callback types, this is also a step toward
the Go register ABI (#40724), which is going to make the ABI
translation more complex.
Change-Id: I19fb1681b659d9fd528ffd5e88912bebb95da052
Reviewed-on: https://go-review.googlesource.com/c/go/+/263271
Trust: Austin Clements <austin@google.com>
Trust: Alex Brainman <alex.brainman@gmail.com>
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
2020-10-17 18:42:03 -04:00
|
|
|
a.retPop = c.retPop
|
runtime,cmd/cgo: simplify C -> Go call path
This redesigns the way calls work from C to exported Go functions. It
removes several steps from the call path, makes cmd/cgo no longer
sensitive to the Go calling convention, and eliminates the use of
reflectcall from cgo.
In order to avoid generating a large amount of FFI glue between the C
and Go ABIs, the cgo tool has long depended on generating a C function
that marshals the arguments into a struct, and then the actual ABI
switch happens in functions with fixed signatures that simply take a
pointer to this struct. In a way, this CL simply pushes this idea
further.
Currently, the cgo tool generates this argument struct in the exact
layout of the Go stack frame and depends on reflectcall to unpack it
into the appropriate Go call (even though it's actually
reflectcall'ing a function generated by cgo).
In this CL, we decouple this struct from the Go stack layout. Instead,
cgo generates a Go function that takes the struct, unpacks it, and
calls the exported function. Since this generated function has a
generic signature (like the rest of the call path), we don't need
reflectcall and can instead depend on the Go compiler itself to
implement the call to the exported Go function.
One complication is that syscall.NewCallback on Windows, which
converts a Go function into a C function pointer, depends on
cgocallback's current dynamic calling approach since the signatures of
the callbacks aren't known statically. For this specific case, we
continue to depend on reflectcall. Really, the current approach makes
some overly simplistic assumptions about translating the C ABI to the
Go ABI. Now we're at least in a much better position to do a proper
ABI translation.
For comparison, the current cgo call path looks like:
GoF (generated C function) ->
crosscall2 (in cgo/asm_*.s) ->
_cgoexp_GoF (generated Go function) ->
cgocallback (in asm_*.s) ->
cgocallback_gofunc (in asm_*.s) ->
cgocallbackg (in cgocall.go) ->
cgocallbackg1 (in cgocall.go) ->
reflectcall (in asm_*.s) ->
_cgoexpwrap_GoF (generated Go function) ->
p.GoF
Now the call path looks like:
GoF (generated C function) ->
crosscall2 (in cgo/asm_*.s) ->
cgocallback (in asm_*.s) ->
cgocallbackg (in cgocall.go) ->
cgocallbackg1 (in cgocall.go) ->
_cgoexp_GoF (generated Go function) ->
p.GoF
Notably:
1. We combine _cgoexp_GoF and _cgoexpwrap_GoF and move the combined
operation to the end of the sequence. This combined function also
handles reflectcall's previous role.
2. We combined cgocallback and cgocallback_gofunc since the only
purpose of having both was to convert a raw PC into a Go function
value. We instead construct the Go function value in cgocallbackg1.
3. cgocallbackg1 no longer reaches backwards through the stack to get
the arguments to cgocallback_gofunc. Instead, we just pass the
arguments down.
4. Currently, we need an explicit msanwrite to mark the results struct
as written because reflectcall doesn't do this. Now, the results are
written by regular Go assignments, so the Go compiler generates the
necessary MSAN annotations. This also means we no longer need to track
the size of the arguments frame.
Updates #40724, since now we don't need to teach cgo about the
register ABI or change how it uses reflectcall.
Change-Id: I7840489a2597962aeb670e0c1798a16a7359c94f
Reviewed-on: https://go-review.googlesource.com/c/go/+/258938
Trust: Austin Clements <austin@google.com>
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
2020-10-01 17:22:38 -04:00
|
|
|
|
2020-11-18 21:38:57 +01:00
|
|
|
// Convert from C to Go ABI.
|
runtime: fix sub-uintptr-sized Windows callback arguments
The Windows callback support accepts Go functions with arguments that
are uintptr-sized or smaller. However, it doesn't implement smaller
arguments correctly. It assumes the Windows arguments layout is
equivalent to the Go argument layout. This is often true, but because
Windows C ABIs pad arguments to word size, while Go packs arguments,
the layout is different if there are multiple sub-word-size arguments
in a row. For example, a function with two uint16 arguments will have
a two-word C argument frame, but only a 4 byte Go argument frame.
There are also subtleties surrounding floating-point register
arguments that it doesn't handle correctly.
To fix this, when constructing a callback, we examine the Go
function's signature to construct a mapping between the C argument
frame and the Go argument frame. When the callback is invoked, we use
this mapping to build the Go argument frame and copy the result back.
This adds several test cases to TestStdcallAndCDeclCallbacks that
exercise more complex function signatures. These all fail with the
current code, but work with this CL.
In addition to fixing these callback types, this is also a step toward
the Go register ABI (#40724), which is going to make the ABI
translation more complex.
Change-Id: I19fb1681b659d9fd528ffd5e88912bebb95da052
Reviewed-on: https://go-review.googlesource.com/c/go/+/263271
Trust: Austin Clements <austin@google.com>
Trust: Alex Brainman <alex.brainman@gmail.com>
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
2020-10-17 18:42:03 -04:00
|
|
|
var frame [callbackMaxFrame]byte
|
|
|
|
|
goArgs := unsafe.Pointer(&frame)
|
|
|
|
|
for _, part := range c.abiMap {
|
|
|
|
|
memmove(add(goArgs, part.dst), add(a.args, part.src), part.len)
|
|
|
|
|
}
|
runtime,cmd/cgo: simplify C -> Go call path
This redesigns the way calls work from C to exported Go functions. It
removes several steps from the call path, makes cmd/cgo no longer
sensitive to the Go calling convention, and eliminates the use of
reflectcall from cgo.
In order to avoid generating a large amount of FFI glue between the C
and Go ABIs, the cgo tool has long depended on generating a C function
that marshals the arguments into a struct, and then the actual ABI
switch happens in functions with fixed signatures that simply take a
pointer to this struct. In a way, this CL simply pushes this idea
further.
Currently, the cgo tool generates this argument struct in the exact
layout of the Go stack frame and depends on reflectcall to unpack it
into the appropriate Go call (even though it's actually
reflectcall'ing a function generated by cgo).
In this CL, we decouple this struct from the Go stack layout. Instead,
cgo generates a Go function that takes the struct, unpacks it, and
calls the exported function. Since this generated function has a
generic signature (like the rest of the call path), we don't need
reflectcall and can instead depend on the Go compiler itself to
implement the call to the exported Go function.
One complication is that syscall.NewCallback on Windows, which
converts a Go function into a C function pointer, depends on
cgocallback's current dynamic calling approach since the signatures of
the callbacks aren't known statically. For this specific case, we
continue to depend on reflectcall. Really, the current approach makes
some overly simplistic assumptions about translating the C ABI to the
Go ABI. Now we're at least in a much better position to do a proper
ABI translation.
For comparison, the current cgo call path looks like:
GoF (generated C function) ->
crosscall2 (in cgo/asm_*.s) ->
_cgoexp_GoF (generated Go function) ->
cgocallback (in asm_*.s) ->
cgocallback_gofunc (in asm_*.s) ->
cgocallbackg (in cgocall.go) ->
cgocallbackg1 (in cgocall.go) ->
reflectcall (in asm_*.s) ->
_cgoexpwrap_GoF (generated Go function) ->
p.GoF
Now the call path looks like:
GoF (generated C function) ->
crosscall2 (in cgo/asm_*.s) ->
cgocallback (in asm_*.s) ->
cgocallbackg (in cgocall.go) ->
cgocallbackg1 (in cgocall.go) ->
_cgoexp_GoF (generated Go function) ->
p.GoF
Notably:
1. We combine _cgoexp_GoF and _cgoexpwrap_GoF and move the combined
operation to the end of the sequence. This combined function also
handles reflectcall's previous role.
2. We combined cgocallback and cgocallback_gofunc since the only
purpose of having both was to convert a raw PC into a Go function
value. We instead construct the Go function value in cgocallbackg1.
3. cgocallbackg1 no longer reaches backwards through the stack to get
the arguments to cgocallback_gofunc. Instead, we just pass the
arguments down.
4. Currently, we need an explicit msanwrite to mark the results struct
as written because reflectcall doesn't do this. Now, the results are
written by regular Go assignments, so the Go compiler generates the
necessary MSAN annotations. This also means we no longer need to track
the size of the arguments frame.
Updates #40724, since now we don't need to teach cgo about the
register ABI or change how it uses reflectcall.
Change-Id: I7840489a2597962aeb670e0c1798a16a7359c94f
Reviewed-on: https://go-review.googlesource.com/c/go/+/258938
Trust: Austin Clements <austin@google.com>
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
2020-10-01 17:22:38 -04:00
|
|
|
|
|
|
|
|
// Even though this is copying back results, we can pass a nil
|
|
|
|
|
// type because those results must not require write barriers.
|
2020-10-22 16:29:04 +00:00
|
|
|
//
|
|
|
|
|
// Pass a dummy RegArgs for now.
|
|
|
|
|
// TODO(mknyszek): Pass arguments in registers.
|
|
|
|
|
var regs abi.RegArgs
|
|
|
|
|
reflectcall(nil, unsafe.Pointer(c.fn), noescape(goArgs), uint32(c.retOffset)+sys.PtrSize, uint32(c.retOffset), uint32(c.retOffset)+sys.PtrSize, ®s)
|
runtime,cmd/cgo: simplify C -> Go call path
This redesigns the way calls work from C to exported Go functions. It
removes several steps from the call path, makes cmd/cgo no longer
sensitive to the Go calling convention, and eliminates the use of
reflectcall from cgo.
In order to avoid generating a large amount of FFI glue between the C
and Go ABIs, the cgo tool has long depended on generating a C function
that marshals the arguments into a struct, and then the actual ABI
switch happens in functions with fixed signatures that simply take a
pointer to this struct. In a way, this CL simply pushes this idea
further.
Currently, the cgo tool generates this argument struct in the exact
layout of the Go stack frame and depends on reflectcall to unpack it
into the appropriate Go call (even though it's actually
reflectcall'ing a function generated by cgo).
In this CL, we decouple this struct from the Go stack layout. Instead,
cgo generates a Go function that takes the struct, unpacks it, and
calls the exported function. Since this generated function has a
generic signature (like the rest of the call path), we don't need
reflectcall and can instead depend on the Go compiler itself to
implement the call to the exported Go function.
One complication is that syscall.NewCallback on Windows, which
converts a Go function into a C function pointer, depends on
cgocallback's current dynamic calling approach since the signatures of
the callbacks aren't known statically. For this specific case, we
continue to depend on reflectcall. Really, the current approach makes
some overly simplistic assumptions about translating the C ABI to the
Go ABI. Now we're at least in a much better position to do a proper
ABI translation.
For comparison, the current cgo call path looks like:
GoF (generated C function) ->
crosscall2 (in cgo/asm_*.s) ->
_cgoexp_GoF (generated Go function) ->
cgocallback (in asm_*.s) ->
cgocallback_gofunc (in asm_*.s) ->
cgocallbackg (in cgocall.go) ->
cgocallbackg1 (in cgocall.go) ->
reflectcall (in asm_*.s) ->
_cgoexpwrap_GoF (generated Go function) ->
p.GoF
Now the call path looks like:
GoF (generated C function) ->
crosscall2 (in cgo/asm_*.s) ->
cgocallback (in asm_*.s) ->
cgocallbackg (in cgocall.go) ->
cgocallbackg1 (in cgocall.go) ->
_cgoexp_GoF (generated Go function) ->
p.GoF
Notably:
1. We combine _cgoexp_GoF and _cgoexpwrap_GoF and move the combined
operation to the end of the sequence. This combined function also
handles reflectcall's previous role.
2. We combined cgocallback and cgocallback_gofunc since the only
purpose of having both was to convert a raw PC into a Go function
value. We instead construct the Go function value in cgocallbackg1.
3. cgocallbackg1 no longer reaches backwards through the stack to get
the arguments to cgocallback_gofunc. Instead, we just pass the
arguments down.
4. Currently, we need an explicit msanwrite to mark the results struct
as written because reflectcall doesn't do this. Now, the results are
written by regular Go assignments, so the Go compiler generates the
necessary MSAN annotations. This also means we no longer need to track
the size of the arguments frame.
Updates #40724, since now we don't need to teach cgo about the
register ABI or change how it uses reflectcall.
Change-Id: I7840489a2597962aeb670e0c1798a16a7359c94f
Reviewed-on: https://go-review.googlesource.com/c/go/+/258938
Trust: Austin Clements <austin@google.com>
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
2020-10-01 17:22:38 -04:00
|
|
|
|
|
|
|
|
// Extract the result.
|
runtime: fix sub-uintptr-sized Windows callback arguments
The Windows callback support accepts Go functions with arguments that
are uintptr-sized or smaller. However, it doesn't implement smaller
arguments correctly. It assumes the Windows arguments layout is
equivalent to the Go argument layout. This is often true, but because
Windows C ABIs pad arguments to word size, while Go packs arguments,
the layout is different if there are multiple sub-word-size arguments
in a row. For example, a function with two uint16 arguments will have
a two-word C argument frame, but only a 4 byte Go argument frame.
There are also subtleties surrounding floating-point register
arguments that it doesn't handle correctly.
To fix this, when constructing a callback, we examine the Go
function's signature to construct a mapping between the C argument
frame and the Go argument frame. When the callback is invoked, we use
this mapping to build the Go argument frame and copy the result back.
This adds several test cases to TestStdcallAndCDeclCallbacks that
exercise more complex function signatures. These all fail with the
current code, but work with this CL.
In addition to fixing these callback types, this is also a step toward
the Go register ABI (#40724), which is going to make the ABI
translation more complex.
Change-Id: I19fb1681b659d9fd528ffd5e88912bebb95da052
Reviewed-on: https://go-review.googlesource.com/c/go/+/263271
Trust: Austin Clements <austin@google.com>
Trust: Alex Brainman <alex.brainman@gmail.com>
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
2020-10-17 18:42:03 -04:00
|
|
|
a.result = *(*uintptr)(unsafe.Pointer(&frame[c.retOffset]))
|
runtime,cmd/cgo: simplify C -> Go call path
This redesigns the way calls work from C to exported Go functions. It
removes several steps from the call path, makes cmd/cgo no longer
sensitive to the Go calling convention, and eliminates the use of
reflectcall from cgo.
In order to avoid generating a large amount of FFI glue between the C
and Go ABIs, the cgo tool has long depended on generating a C function
that marshals the arguments into a struct, and then the actual ABI
switch happens in functions with fixed signatures that simply take a
pointer to this struct. In a way, this CL simply pushes this idea
further.
Currently, the cgo tool generates this argument struct in the exact
layout of the Go stack frame and depends on reflectcall to unpack it
into the appropriate Go call (even though it's actually
reflectcall'ing a function generated by cgo).
In this CL, we decouple this struct from the Go stack layout. Instead,
cgo generates a Go function that takes the struct, unpacks it, and
calls the exported function. Since this generated function has a
generic signature (like the rest of the call path), we don't need
reflectcall and can instead depend on the Go compiler itself to
implement the call to the exported Go function.
One complication is that syscall.NewCallback on Windows, which
converts a Go function into a C function pointer, depends on
cgocallback's current dynamic calling approach since the signatures of
the callbacks aren't known statically. For this specific case, we
continue to depend on reflectcall. Really, the current approach makes
some overly simplistic assumptions about translating the C ABI to the
Go ABI. Now we're at least in a much better position to do a proper
ABI translation.
For comparison, the current cgo call path looks like:
GoF (generated C function) ->
crosscall2 (in cgo/asm_*.s) ->
_cgoexp_GoF (generated Go function) ->
cgocallback (in asm_*.s) ->
cgocallback_gofunc (in asm_*.s) ->
cgocallbackg (in cgocall.go) ->
cgocallbackg1 (in cgocall.go) ->
reflectcall (in asm_*.s) ->
_cgoexpwrap_GoF (generated Go function) ->
p.GoF
Now the call path looks like:
GoF (generated C function) ->
crosscall2 (in cgo/asm_*.s) ->
cgocallback (in asm_*.s) ->
cgocallbackg (in cgocall.go) ->
cgocallbackg1 (in cgocall.go) ->
_cgoexp_GoF (generated Go function) ->
p.GoF
Notably:
1. We combine _cgoexp_GoF and _cgoexpwrap_GoF and move the combined
operation to the end of the sequence. This combined function also
handles reflectcall's previous role.
2. We combined cgocallback and cgocallback_gofunc since the only
purpose of having both was to convert a raw PC into a Go function
value. We instead construct the Go function value in cgocallbackg1.
3. cgocallbackg1 no longer reaches backwards through the stack to get
the arguments to cgocallback_gofunc. Instead, we just pass the
arguments down.
4. Currently, we need an explicit msanwrite to mark the results struct
as written because reflectcall doesn't do this. Now, the results are
written by regular Go assignments, so the Go compiler generates the
necessary MSAN annotations. This also means we no longer need to track
the size of the arguments frame.
Updates #40724, since now we don't need to teach cgo about the
register ABI or change how it uses reflectcall.
Change-Id: I7840489a2597962aeb670e0c1798a16a7359c94f
Reviewed-on: https://go-review.googlesource.com/c/go/+/258938
Trust: Austin Clements <austin@google.com>
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
2020-10-01 17:22:38 -04:00
|
|
|
}
|
|
|
|
|
|
2016-03-25 06:40:58 +00:00
|
|
|
const _LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800
|
|
|
|
|
|
2019-03-06 19:26:29 +01:00
|
|
|
// When available, this function will use LoadLibraryEx with the filename
|
|
|
|
|
// parameter and the important SEARCH_SYSTEM32 argument. But on systems that
|
|
|
|
|
// do not have that option, absoluteFilepath should contain a fallback
|
|
|
|
|
// to the full path inside of system32 for use with vanilla LoadLibrary.
|
2016-03-25 06:40:58 +00:00
|
|
|
//go:linkname syscall_loadsystemlibrary syscall.loadsystemlibrary
|
|
|
|
|
//go:nosplit
|
2021-03-12 18:38:02 -05:00
|
|
|
//go:cgo_unsafe_args
|
2019-03-06 19:26:29 +01:00
|
|
|
func syscall_loadsystemlibrary(filename *uint16, absoluteFilepath *uint16) (handle, err uintptr) {
|
2017-09-13 15:53:47 -07:00
|
|
|
lockOSThread()
|
2016-03-25 06:40:58 +00:00
|
|
|
c := &getg().m.syscall
|
|
|
|
|
|
|
|
|
|
if useLoadLibraryEx {
|
|
|
|
|
c.fn = getLoadLibraryEx()
|
|
|
|
|
c.n = 3
|
|
|
|
|
args := struct {
|
|
|
|
|
lpFileName *uint16
|
|
|
|
|
hFile uintptr // always 0
|
|
|
|
|
flags uint32
|
|
|
|
|
}{filename, 0, _LOAD_LIBRARY_SEARCH_SYSTEM32}
|
|
|
|
|
c.args = uintptr(noescape(unsafe.Pointer(&args)))
|
|
|
|
|
} else {
|
|
|
|
|
c.fn = getLoadLibrary()
|
|
|
|
|
c.n = 1
|
2019-03-06 19:26:29 +01:00
|
|
|
c.args = uintptr(noescape(unsafe.Pointer(&absoluteFilepath)))
|
2016-03-25 06:40:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cgocall(asmstdcallAddr, unsafe.Pointer(c))
|
|
|
|
|
handle = c.r1
|
|
|
|
|
if handle == 0 {
|
|
|
|
|
err = c.err
|
|
|
|
|
}
|
2019-06-08 17:20:57 +00:00
|
|
|
unlockOSThread() // not defer'd after the lockOSThread above to save stack frame size.
|
2016-03-25 06:40:58 +00:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-23 15:33:51 +11:00
|
|
|
//go:linkname syscall_loadlibrary syscall.loadlibrary
|
2014-09-14 21:25:44 -04:00
|
|
|
//go:nosplit
|
2021-03-12 18:38:02 -05:00
|
|
|
//go:cgo_unsafe_args
|
2014-09-14 21:25:44 -04:00
|
|
|
func syscall_loadlibrary(filename *uint16) (handle, err uintptr) {
|
2017-09-13 15:53:47 -07:00
|
|
|
lockOSThread()
|
|
|
|
|
defer unlockOSThread()
|
2015-05-22 10:58:57 +10:00
|
|
|
c := &getg().m.syscall
|
2014-09-14 21:25:44 -04:00
|
|
|
c.fn = getLoadLibrary()
|
|
|
|
|
c.n = 1
|
2015-05-22 10:58:57 +10:00
|
|
|
c.args = uintptr(noescape(unsafe.Pointer(&filename)))
|
|
|
|
|
cgocall(asmstdcallAddr, unsafe.Pointer(c))
|
2014-09-14 21:25:44 -04:00
|
|
|
handle = c.r1
|
|
|
|
|
if handle == 0 {
|
|
|
|
|
err = c.err
|
|
|
|
|
}
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-23 15:33:51 +11:00
|
|
|
//go:linkname syscall_getprocaddress syscall.getprocaddress
|
2014-09-14 21:25:44 -04:00
|
|
|
//go:nosplit
|
2021-03-12 18:38:02 -05:00
|
|
|
//go:cgo_unsafe_args
|
2014-09-14 21:25:44 -04:00
|
|
|
func syscall_getprocaddress(handle uintptr, procname *byte) (outhandle, err uintptr) {
|
2017-09-13 15:53:47 -07:00
|
|
|
lockOSThread()
|
|
|
|
|
defer unlockOSThread()
|
2015-05-22 10:58:57 +10:00
|
|
|
c := &getg().m.syscall
|
2014-09-14 21:25:44 -04:00
|
|
|
c.fn = getGetProcAddress()
|
|
|
|
|
c.n = 2
|
2015-05-22 10:58:57 +10:00
|
|
|
c.args = uintptr(noescape(unsafe.Pointer(&handle)))
|
|
|
|
|
cgocall(asmstdcallAddr, unsafe.Pointer(c))
|
2014-09-14 21:25:44 -04:00
|
|
|
outhandle = c.r1
|
|
|
|
|
if outhandle == 0 {
|
|
|
|
|
err = c.err
|
|
|
|
|
}
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-23 15:33:51 +11:00
|
|
|
//go:linkname syscall_Syscall syscall.Syscall
|
2014-09-14 21:25:44 -04:00
|
|
|
//go:nosplit
|
2021-03-12 18:38:02 -05:00
|
|
|
//go:cgo_unsafe_args
|
2014-09-14 21:25:44 -04:00
|
|
|
func syscall_Syscall(fn, nargs, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
|
2017-09-13 15:53:47 -07:00
|
|
|
lockOSThread()
|
|
|
|
|
defer unlockOSThread()
|
2015-05-22 10:58:57 +10:00
|
|
|
c := &getg().m.syscall
|
2014-09-14 21:25:44 -04:00
|
|
|
c.fn = fn
|
|
|
|
|
c.n = nargs
|
2015-05-22 10:58:57 +10:00
|
|
|
c.args = uintptr(noescape(unsafe.Pointer(&a1)))
|
|
|
|
|
cgocall(asmstdcallAddr, unsafe.Pointer(c))
|
2014-09-14 21:25:44 -04:00
|
|
|
return c.r1, c.r2, c.err
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-23 15:33:51 +11:00
|
|
|
//go:linkname syscall_Syscall6 syscall.Syscall6
|
2014-09-14 21:25:44 -04:00
|
|
|
//go:nosplit
|
2021-03-12 18:38:02 -05:00
|
|
|
//go:cgo_unsafe_args
|
2014-09-14 21:25:44 -04:00
|
|
|
func syscall_Syscall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
|
2017-09-13 15:53:47 -07:00
|
|
|
lockOSThread()
|
|
|
|
|
defer unlockOSThread()
|
2015-05-22 10:58:57 +10:00
|
|
|
c := &getg().m.syscall
|
2014-09-14 21:25:44 -04:00
|
|
|
c.fn = fn
|
|
|
|
|
c.n = nargs
|
2015-05-22 10:58:57 +10:00
|
|
|
c.args = uintptr(noescape(unsafe.Pointer(&a1)))
|
|
|
|
|
cgocall(asmstdcallAddr, unsafe.Pointer(c))
|
2014-09-14 21:25:44 -04:00
|
|
|
return c.r1, c.r2, c.err
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-23 15:33:51 +11:00
|
|
|
//go:linkname syscall_Syscall9 syscall.Syscall9
|
2014-09-14 21:25:44 -04:00
|
|
|
//go:nosplit
|
2021-03-12 18:38:02 -05:00
|
|
|
//go:cgo_unsafe_args
|
2014-09-14 21:25:44 -04:00
|
|
|
func syscall_Syscall9(fn, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) {
|
2017-09-13 15:53:47 -07:00
|
|
|
lockOSThread()
|
|
|
|
|
defer unlockOSThread()
|
2015-05-22 10:58:57 +10:00
|
|
|
c := &getg().m.syscall
|
2014-09-14 21:25:44 -04:00
|
|
|
c.fn = fn
|
|
|
|
|
c.n = nargs
|
2015-05-22 10:58:57 +10:00
|
|
|
c.args = uintptr(noescape(unsafe.Pointer(&a1)))
|
|
|
|
|
cgocall(asmstdcallAddr, unsafe.Pointer(c))
|
2014-09-14 21:25:44 -04:00
|
|
|
return c.r1, c.r2, c.err
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-23 15:33:51 +11:00
|
|
|
//go:linkname syscall_Syscall12 syscall.Syscall12
|
2014-09-14 21:25:44 -04:00
|
|
|
//go:nosplit
|
2021-03-12 18:38:02 -05:00
|
|
|
//go:cgo_unsafe_args
|
2014-09-14 21:25:44 -04:00
|
|
|
func syscall_Syscall12(fn, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12 uintptr) (r1, r2, err uintptr) {
|
2017-09-13 15:53:47 -07:00
|
|
|
lockOSThread()
|
|
|
|
|
defer unlockOSThread()
|
2015-05-22 10:58:57 +10:00
|
|
|
c := &getg().m.syscall
|
2014-09-14 21:25:44 -04:00
|
|
|
c.fn = fn
|
|
|
|
|
c.n = nargs
|
2015-05-22 10:58:57 +10:00
|
|
|
c.args = uintptr(noescape(unsafe.Pointer(&a1)))
|
|
|
|
|
cgocall(asmstdcallAddr, unsafe.Pointer(c))
|
2014-09-14 21:25:44 -04:00
|
|
|
return c.r1, c.r2, c.err
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-23 15:33:51 +11:00
|
|
|
//go:linkname syscall_Syscall15 syscall.Syscall15
|
2014-09-14 21:25:44 -04:00
|
|
|
//go:nosplit
|
2021-03-12 18:38:02 -05:00
|
|
|
//go:cgo_unsafe_args
|
2014-09-14 21:25:44 -04:00
|
|
|
func syscall_Syscall15(fn, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr) (r1, r2, err uintptr) {
|
2017-09-13 15:53:47 -07:00
|
|
|
lockOSThread()
|
|
|
|
|
defer unlockOSThread()
|
2015-05-22 10:58:57 +10:00
|
|
|
c := &getg().m.syscall
|
2014-09-14 21:25:44 -04:00
|
|
|
c.fn = fn
|
|
|
|
|
c.n = nargs
|
2015-05-22 10:58:57 +10:00
|
|
|
c.args = uintptr(noescape(unsafe.Pointer(&a1)))
|
|
|
|
|
cgocall(asmstdcallAddr, unsafe.Pointer(c))
|
2014-09-14 21:25:44 -04:00
|
|
|
return c.r1, c.r2, c.err
|
|
|
|
|
}
|
2018-11-03 02:19:47 +09:00
|
|
|
|
|
|
|
|
//go:linkname syscall_Syscall18 syscall.Syscall18
|
|
|
|
|
//go:nosplit
|
2021-03-12 18:38:02 -05:00
|
|
|
//go:cgo_unsafe_args
|
2018-11-03 02:19:47 +09:00
|
|
|
func syscall_Syscall18(fn, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18 uintptr) (r1, r2, err uintptr) {
|
|
|
|
|
lockOSThread()
|
|
|
|
|
defer unlockOSThread()
|
|
|
|
|
c := &getg().m.syscall
|
|
|
|
|
c.fn = fn
|
|
|
|
|
c.n = nargs
|
|
|
|
|
c.args = uintptr(noescape(unsafe.Pointer(&a1)))
|
|
|
|
|
cgocall(asmstdcallAddr, unsafe.Pointer(c))
|
|
|
|
|
return c.r1, c.r2, c.err
|
|
|
|
|
}
|