mirror of
https://github.com/kubenetworks/kubevpn.git
synced 2025-10-07 08:11:01 +08:00
refactor: update go mod library (#210)
refactor: update go mod library and refactor dev logic Co-authored-by: wencaiwulue <895703375@qq.com>
This commit is contained in:
24
vendor/github.com/ebitengine/purego/README.md
generated
vendored
24
vendor/github.com/ebitengine/purego/README.md
generated
vendored
@@ -3,6 +3,10 @@
|
||||
|
||||
A library for calling C functions from Go without Cgo.
|
||||
|
||||
> This is beta software so expect bugs and potentially API breaking changes
|
||||
> but each release will be tagged to avoid breaking people's code.
|
||||
> Bug reports are encouraged.
|
||||
|
||||
## Motivation
|
||||
|
||||
The [Ebitengine](https://github.com/hajimehoshi/ebiten) game engine was ported to use only Go on Windows. This enabled
|
||||
@@ -16,6 +20,18 @@ born to bring that same vision to the other platforms supported by Ebitengine.
|
||||
- **Smaller Binaries**: Using Cgo generates a C wrapper function for each C function called. Purego doesn't!
|
||||
- **Dynamic Linking**: Load symbols at runtime and use it as a plugin system.
|
||||
- **Foreign Function Interface**: Call into other languages that are compiled into shared objects.
|
||||
- **Cgo Fallback**: Works even with CGO_ENABLED=1 so incremental porting is possible.
|
||||
This also means unsupported GOARCHs (freebsd/riscv64, linux/mips, etc.) will still work
|
||||
except for float arguments and return values.
|
||||
|
||||
## Supported Platforms
|
||||
|
||||
- **FreeBSD**: amd64, arm64
|
||||
- **Linux**: amd64, arm64
|
||||
- **macOS / iOS**: amd64, arm64
|
||||
- **Windows**: 386*, amd64, arm*, arm64
|
||||
|
||||
`*` These architectures only support SyscallN and NewCallback
|
||||
|
||||
## Example
|
||||
|
||||
@@ -55,6 +71,11 @@ func main() {
|
||||
|
||||
Then to run: `CGO_ENABLED=0 go run main.go`
|
||||
|
||||
## Questions
|
||||
|
||||
If you have questions about how to incorporate purego in your project or want to discuss
|
||||
how it works join the [Discord](https://discord.com/channels/842049801528016967/1123106378731487345)!
|
||||
|
||||
### External Code
|
||||
|
||||
Purego uses code that originates from the Go runtime. These files are under the BSD-3
|
||||
@@ -71,4 +92,5 @@ This is a list of the copied files:
|
||||
* `internal/fakecgo/setenv.go` from package `runtime/cgo`
|
||||
* `internal/fakecgo/freebsd.go` from package `runtime/cgo`
|
||||
|
||||
The files `abi_*.h` and `internal/fakecgo/abi_*.h` are the same because Bazel does not support cross-package use of `#include` so we need each one once per package. (cf. [issue](https://github.com/bazelbuild/rules_go/issues/3636))
|
||||
The files `abi_*.h` and `internal/fakecgo/abi_*.h` are the same because Bazel does not support cross-package use of
|
||||
`#include` so we need each one once per package. (cf. [issue](https://github.com/bazelbuild/rules_go/issues/3636))
|
||||
|
6
vendor/github.com/ebitengine/purego/cgo.go
generated
vendored
6
vendor/github.com/ebitengine/purego/cgo.go
generated
vendored
@@ -12,4 +12,8 @@ package purego
|
||||
// which will import this package automatically. Normally this isn't an issue since it
|
||||
// usually isn't possible to call into C without using that import. However, with purego
|
||||
// it is since we don't use `import "C"`!
|
||||
import _ "runtime/cgo"
|
||||
import (
|
||||
_ "runtime/cgo"
|
||||
|
||||
_ "github.com/ebitengine/purego/internal/cgo"
|
||||
)
|
||||
|
5
vendor/github.com/ebitengine/purego/dlfcn_darwin.go
generated
vendored
5
vendor/github.com/ebitengine/purego/dlfcn_darwin.go
generated
vendored
@@ -17,3 +17,8 @@ const (
|
||||
//go:cgo_import_dynamic purego_dlsym dlsym "/usr/lib/libSystem.B.dylib"
|
||||
//go:cgo_import_dynamic purego_dlerror dlerror "/usr/lib/libSystem.B.dylib"
|
||||
//go:cgo_import_dynamic purego_dlclose dlclose "/usr/lib/libSystem.B.dylib"
|
||||
|
||||
//go:cgo_import_dynamic purego_dlopen dlopen "/usr/lib/libSystem.B.dylib"
|
||||
//go:cgo_import_dynamic purego_dlsym dlsym "/usr/lib/libSystem.B.dylib"
|
||||
//go:cgo_import_dynamic purego_dlerror dlerror "/usr/lib/libSystem.B.dylib"
|
||||
//go:cgo_import_dynamic purego_dlclose dlclose "/usr/lib/libSystem.B.dylib"
|
||||
|
5
vendor/github.com/ebitengine/purego/dlfcn_freebsd.go
generated
vendored
5
vendor/github.com/ebitengine/purego/dlfcn_freebsd.go
generated
vendored
@@ -11,8 +11,3 @@ const (
|
||||
RTLD_LOCAL = 0x00000 // All symbols are not made available for relocation processing by other modules.
|
||||
RTLD_GLOBAL = 0x00100 // All symbols are available for relocation processing of other modules.
|
||||
)
|
||||
|
||||
//go:cgo_import_dynamic purego_dlopen dlopen "libc.so.7"
|
||||
//go:cgo_import_dynamic purego_dlsym dlsym "libc.so.7"
|
||||
//go:cgo_import_dynamic purego_dlerror dlerror "libc.so.7"
|
||||
//go:cgo_import_dynamic purego_dlclose dlclose "libc.so.7"
|
||||
|
11
vendor/github.com/ebitengine/purego/dlfcn_nocgo_freebsd.go
generated
vendored
Normal file
11
vendor/github.com/ebitengine/purego/dlfcn_nocgo_freebsd.go
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
|
||||
|
||||
//go:build !cgo
|
||||
|
||||
package purego
|
||||
|
||||
//go:cgo_import_dynamic purego_dlopen dlopen "libc.so.7"
|
||||
//go:cgo_import_dynamic purego_dlsym dlsym "libc.so.7"
|
||||
//go:cgo_import_dynamic purego_dlerror dlerror "libc.so.7"
|
||||
//go:cgo_import_dynamic purego_dlclose dlclose "libc.so.7"
|
2
vendor/github.com/ebitengine/purego/dlfcn_stubs.s
generated
vendored
2
vendor/github.com/ebitengine/purego/dlfcn_stubs.s
generated
vendored
@@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
|
||||
|
||||
//go:build darwin || freebsd || (linux && !cgo)
|
||||
//go:build darwin || !cgo && (freebsd || linux)
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
160
vendor/github.com/ebitengine/purego/func.go
generated
vendored
160
vendor/github.com/ebitengine/purego/func.go
generated
vendored
@@ -6,6 +6,7 @@
|
||||
package purego
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"reflect"
|
||||
"runtime"
|
||||
@@ -50,9 +51,9 @@ func RegisterLibFunc(fptr interface{}, handle uintptr, name string) {
|
||||
// int16 <=> int16_t
|
||||
// int32 <=> int32_t
|
||||
// int64 <=> int64_t
|
||||
// float32 <=> float (WIP)
|
||||
// float64 <=> double (WIP)
|
||||
// struct <=> struct (WIP)
|
||||
// float32 <=> float
|
||||
// float64 <=> double
|
||||
// struct <=> struct (WIP - darwin only)
|
||||
// func <=> C function
|
||||
// unsafe.Pointer, *T <=> void*
|
||||
// []T => void*
|
||||
@@ -62,10 +63,6 @@ func RegisterLibFunc(fptr interface{}, handle uintptr, name string) {
|
||||
// This means that using arg ...interface{} is like a cast to the function with the arguments inside arg.
|
||||
// This is not the same as C variadic.
|
||||
//
|
||||
// There are some limitations when using RegisterFunc on Linux. First, there is no support for function arguments.
|
||||
// Second, float32 and float64 arguments and return values do not work when CGO_ENABLED=1. Otherwise, Linux
|
||||
// has the same feature parity as Darwin.
|
||||
//
|
||||
// # Memory
|
||||
//
|
||||
// In general it is not possible for purego to guarantee the lifetimes of objects returned or received from
|
||||
@@ -85,6 +82,12 @@ func RegisterLibFunc(fptr interface{}, handle uintptr, name string) {
|
||||
// using unsafe.Slice. Doing this means that it becomes the responsibility of the caller to care about the lifetime
|
||||
// of the pointer
|
||||
//
|
||||
// # Structs
|
||||
//
|
||||
// Purego can handle the most common structs that have fields of builtin types like int8, uint16, float32, etc. However,
|
||||
// it does not support aligning fields properly. It is therefore the responsibility of the caller to ensure
|
||||
// that all padding is added to the Go struct to match the C one. See `BoolStructFn` in struct_test.go for an example.
|
||||
//
|
||||
// # Example
|
||||
//
|
||||
// All functions below call this C function:
|
||||
@@ -132,15 +135,47 @@ func RegisterFunc(fptr interface{}, cfn uintptr) {
|
||||
stack++
|
||||
}
|
||||
case reflect.Float32, reflect.Float64:
|
||||
if is32bit {
|
||||
panic("purego: floats only supported on 64bit platforms")
|
||||
}
|
||||
if floats < numOfFloats {
|
||||
floats++
|
||||
} else {
|
||||
stack++
|
||||
}
|
||||
case reflect.Struct:
|
||||
if runtime.GOOS != "darwin" || (runtime.GOARCH != "amd64" && runtime.GOARCH != "arm64") {
|
||||
panic("purego: struct arguments are only supported on darwin amd64 & arm64")
|
||||
}
|
||||
if arg.Size() == 0 {
|
||||
continue
|
||||
}
|
||||
addInt := func(u uintptr) {
|
||||
ints++
|
||||
}
|
||||
addFloat := func(u uintptr) {
|
||||
floats++
|
||||
}
|
||||
addStack := func(u uintptr) {
|
||||
stack++
|
||||
}
|
||||
_ = addStruct(reflect.New(arg).Elem(), &ints, &floats, &stack, addInt, addFloat, addStack, nil)
|
||||
default:
|
||||
panic("purego: unsupported kind " + arg.Kind().String())
|
||||
}
|
||||
}
|
||||
if ty.NumOut() == 1 && ty.Out(0).Kind() == reflect.Struct {
|
||||
if runtime.GOOS != "darwin" {
|
||||
panic("purego: struct return values only supported on darwin arm64 & amd64")
|
||||
}
|
||||
outType := ty.Out(0)
|
||||
checkStructFieldsSupported(outType)
|
||||
if runtime.GOARCH == "amd64" && outType.Size() > maxRegAllocStructSize {
|
||||
// on amd64 if struct is bigger than 16 bytes allocate the return struct
|
||||
// and pass it in as a hidden first argument.
|
||||
ints++
|
||||
}
|
||||
}
|
||||
sizeOfStack := maxArgs - numOfIntegerRegisters()
|
||||
if stack > sizeOfStack {
|
||||
panic("purego: too many arguments")
|
||||
@@ -207,6 +242,21 @@ func RegisterFunc(fptr interface{}, cfn uintptr) {
|
||||
runtime.KeepAlive(keepAlive)
|
||||
runtime.KeepAlive(args)
|
||||
}()
|
||||
var syscall syscall15Args
|
||||
if ty.NumOut() == 1 && ty.Out(0).Kind() == reflect.Struct {
|
||||
outType := ty.Out(0)
|
||||
if runtime.GOARCH == "amd64" && outType.Size() > maxRegAllocStructSize {
|
||||
val := reflect.New(outType)
|
||||
keepAlive = append(keepAlive, val)
|
||||
addInt(val.Pointer())
|
||||
} else if runtime.GOARCH == "arm64" && outType.Size() > maxRegAllocStructSize {
|
||||
if !isAllSameFloat(outType) || outType.NumField() > 4 {
|
||||
val := reflect.New(outType)
|
||||
keepAlive = append(keepAlive, val)
|
||||
syscall.arm64_r8 = val.Pointer()
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, v := range args {
|
||||
switch v.Kind() {
|
||||
case reflect.String:
|
||||
@@ -232,25 +282,29 @@ func RegisterFunc(fptr interface{}, cfn uintptr) {
|
||||
addFloat(uintptr(math.Float32bits(float32(v.Float()))))
|
||||
case reflect.Float64:
|
||||
addFloat(uintptr(math.Float64bits(v.Float())))
|
||||
case reflect.Struct:
|
||||
keepAlive = addStruct(v, &numInts, &numFloats, &numStack, addInt, addFloat, addStack, keepAlive)
|
||||
default:
|
||||
panic("purego: unsupported kind: " + v.Kind().String())
|
||||
}
|
||||
}
|
||||
// TODO: support structs
|
||||
var r1, r2 uintptr
|
||||
if runtime.GOARCH == "arm64" || runtime.GOOS != "windows" {
|
||||
// Use the normal arm64 calling convention even on Windows
|
||||
syscall := syscall9Args{
|
||||
syscall = syscall15Args{
|
||||
cfn,
|
||||
sysargs[0], sysargs[1], sysargs[2], sysargs[3], sysargs[4], sysargs[5], sysargs[6], sysargs[7], sysargs[8],
|
||||
sysargs[0], sysargs[1], sysargs[2], sysargs[3], sysargs[4], sysargs[5],
|
||||
sysargs[6], sysargs[7], sysargs[8], sysargs[9], sysargs[10], sysargs[11],
|
||||
sysargs[12], sysargs[13], sysargs[14],
|
||||
floats[0], floats[1], floats[2], floats[3], floats[4], floats[5], floats[6], floats[7],
|
||||
0, 0, 0,
|
||||
syscall.arm64_r8,
|
||||
}
|
||||
runtime_cgocall(syscall9XABI0, unsafe.Pointer(&syscall))
|
||||
r1, r2 = syscall.r1, syscall.r2
|
||||
runtime_cgocall(syscall15XABI0, unsafe.Pointer(&syscall))
|
||||
} else {
|
||||
// This is a fallback for amd64, 386, and arm. Note this may not support floats
|
||||
r1, r2, _ = syscall_syscall9X(cfn, sysargs[0], sysargs[1], sysargs[2], sysargs[3], sysargs[4], sysargs[5], sysargs[6], sysargs[7], sysargs[8])
|
||||
// This is a fallback for Windows amd64, 386, and arm. Note this may not support floats
|
||||
syscall.a1, syscall.a2, _ = syscall_syscall15X(cfn, sysargs[0], sysargs[1], sysargs[2], sysargs[3], sysargs[4],
|
||||
sysargs[5], sysargs[6], sysargs[7], sysargs[8], sysargs[9], sysargs[10], sysargs[11],
|
||||
sysargs[12], sysargs[13], sysargs[14])
|
||||
syscall.f1 = syscall.a2 // on amd64 a2 stores the float return. On 32bit platforms floats aren't support
|
||||
}
|
||||
if ty.NumOut() == 0 {
|
||||
return nil
|
||||
@@ -259,31 +313,33 @@ func RegisterFunc(fptr interface{}, cfn uintptr) {
|
||||
v := reflect.New(outType).Elem()
|
||||
switch outType.Kind() {
|
||||
case reflect.Uintptr, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
v.SetUint(uint64(r1))
|
||||
v.SetUint(uint64(syscall.a1))
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
v.SetInt(int64(r1))
|
||||
v.SetInt(int64(syscall.a1))
|
||||
case reflect.Bool:
|
||||
v.SetBool(byte(r1) != 0)
|
||||
v.SetBool(byte(syscall.a1) != 0)
|
||||
case reflect.UnsafePointer:
|
||||
// We take the address and then dereference it to trick go vet from creating a possible miss-use of unsafe.Pointer
|
||||
v.SetPointer(*(*unsafe.Pointer)(unsafe.Pointer(&r1)))
|
||||
v.SetPointer(*(*unsafe.Pointer)(unsafe.Pointer(&syscall.a1)))
|
||||
case reflect.Ptr:
|
||||
// It is safe to have the address of r1 not escape because it is immediately dereferenced with .Elem()
|
||||
v = reflect.NewAt(outType, runtime_noescape(unsafe.Pointer(&r1))).Elem()
|
||||
// It is safe to have the address of syscall.r1 not escape because it is immediately dereferenced with .Elem()
|
||||
v = reflect.NewAt(outType, runtime_noescape(unsafe.Pointer(&syscall.a1))).Elem()
|
||||
case reflect.Func:
|
||||
// wrap this C function in a nicely typed Go function
|
||||
v = reflect.New(outType)
|
||||
RegisterFunc(v.Interface(), r1)
|
||||
RegisterFunc(v.Interface(), syscall.a1)
|
||||
case reflect.String:
|
||||
v.SetString(strings.GoString(r1))
|
||||
v.SetString(strings.GoString(syscall.a1))
|
||||
case reflect.Float32:
|
||||
// NOTE: r2 is only the floating return value on 64bit platforms.
|
||||
// On 32bit platforms r2 is the upper part of a 64bit return.
|
||||
v.SetFloat(float64(math.Float32frombits(uint32(r2))))
|
||||
// NOTE: syscall.r2 is only the floating return value on 64bit platforms.
|
||||
// On 32bit platforms syscall.r2 is the upper part of a 64bit return.
|
||||
v.SetFloat(float64(math.Float32frombits(uint32(syscall.f1))))
|
||||
case reflect.Float64:
|
||||
// NOTE: r2 is only the floating return value on 64bit platforms.
|
||||
// On 32bit platforms r2 is the upper part of a 64bit return.
|
||||
v.SetFloat(math.Float64frombits(uint64(r2)))
|
||||
// NOTE: syscall.r2 is only the floating return value on 64bit platforms.
|
||||
// On 32bit platforms syscall.r2 is the upper part of a 64bit return.
|
||||
v.SetFloat(math.Float64frombits(uint64(syscall.f1)))
|
||||
case reflect.Struct:
|
||||
v = getStruct(outType, syscall)
|
||||
default:
|
||||
panic("purego: unsupported return kind: " + outType.Kind().String())
|
||||
}
|
||||
@@ -292,6 +348,50 @@ func RegisterFunc(fptr interface{}, cfn uintptr) {
|
||||
fn.Set(v)
|
||||
}
|
||||
|
||||
// maxRegAllocStructSize is the biggest a struct can be while still fitting in registers.
|
||||
// if it is bigger than this than enough space must be allocated on the heap and then passed into
|
||||
// the function as the first parameter on amd64 or in R8 on arm64.
|
||||
const maxRegAllocStructSize = 16
|
||||
|
||||
func isAllSameFloat(ty reflect.Type) bool {
|
||||
first := ty.Field(0).Type.Kind()
|
||||
if first != reflect.Float32 && first != reflect.Float64 {
|
||||
return false
|
||||
}
|
||||
for i := 0; i < ty.NumField(); i++ {
|
||||
f := ty.Field(i)
|
||||
if f.Type.Kind() != first {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func checkStructFieldsSupported(ty reflect.Type) {
|
||||
for i := 0; i < ty.NumField(); i++ {
|
||||
f := ty.Field(i).Type
|
||||
if f.Kind() == reflect.Array {
|
||||
f = f.Elem()
|
||||
} else if f.Kind() == reflect.Struct {
|
||||
checkStructFieldsSupported(f)
|
||||
continue
|
||||
}
|
||||
switch f.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
|
||||
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
|
||||
reflect.Uintptr, reflect.Ptr, reflect.UnsafePointer, reflect.Float64, reflect.Float32:
|
||||
default:
|
||||
panic(fmt.Sprintf("purego: struct field type %s is not supported", f))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const is32bit = unsafe.Sizeof(uintptr(0)) == 4
|
||||
|
||||
func roundUpTo8(val uintptr) uintptr {
|
||||
return (val + 7) &^ 7
|
||||
}
|
||||
|
||||
func numOfIntegerRegisters() int {
|
||||
switch runtime.GOARCH {
|
||||
case "arm64":
|
||||
|
22
vendor/github.com/ebitengine/purego/internal/cgo/dlfcn_cgo_unix.go
generated
vendored
Normal file
22
vendor/github.com/ebitengine/purego/internal/cgo/dlfcn_cgo_unix.go
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2024 The Ebitengine Authors
|
||||
|
||||
//go:build freebsd || linux
|
||||
|
||||
package cgo
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -ldl
|
||||
|
||||
#include <dlfcn.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
// all that is needed is to assign each dl function because then its
|
||||
// symbol will then be made available to the linker and linked to inside dlfcn.go
|
||||
var (
|
||||
_ = C.dlopen
|
||||
_ = C.dlsym
|
||||
_ = C.dlerror
|
||||
_ = C.dlclose
|
||||
)
|
6
vendor/github.com/ebitengine/purego/internal/cgo/empty.go
generated
vendored
Normal file
6
vendor/github.com/ebitengine/purego/internal/cgo/empty.go
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2024 The Ebitengine Authors
|
||||
|
||||
package cgo
|
||||
|
||||
// Empty so that importing this package doesn't cause issue for certain platforms.
|
41
vendor/github.com/ebitengine/purego/internal/cgo/syscall_cgo_unix.go
generated
vendored
41
vendor/github.com/ebitengine/purego/internal/cgo/syscall_cgo_unix.go
generated
vendored
@@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
|
||||
|
||||
//go:build freebsd || linux
|
||||
//go:build freebsd || (linux && !(arm64 || amd64))
|
||||
|
||||
package cgo
|
||||
|
||||
@@ -16,18 +16,21 @@ package cgo
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
typedef struct syscall9Args {
|
||||
typedef struct syscall15Args {
|
||||
uintptr_t fn;
|
||||
uintptr_t a1, a2, a3, a4, a5, a6, a7, a8, a9;
|
||||
uintptr_t a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15;
|
||||
uintptr_t f1, f2, f3, f4, f5, f6, f7, f8;
|
||||
uintptr_t r1, r2, err;
|
||||
} syscall9Args;
|
||||
} syscall15Args;
|
||||
|
||||
void syscall9(struct syscall9Args *args) {
|
||||
void syscall15(struct syscall15Args *args) {
|
||||
assert((args->f1|args->f2|args->f3|args->f4|args->f5|args->f6|args->f7|args->f8) == 0);
|
||||
uintptr_t (*func_name)(uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9);
|
||||
uintptr_t (*func_name)(uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6,
|
||||
uintptr_t a7, uintptr_t a8, uintptr_t a9, uintptr_t a10, uintptr_t a11, uintptr_t a12,
|
||||
uintptr_t a13, uintptr_t a14, uintptr_t a15);
|
||||
*(void**)(&func_name) = (void*)(args->fn);
|
||||
uintptr_t r1 = func_name(args->a1,args->a2,args->a3,args->a4,args->a5,args->a6,args->a7,args->a8,args->a9);
|
||||
uintptr_t r1 = func_name(args->a1,args->a2,args->a3,args->a4,args->a5,args->a6,args->a7,args->a8,args->a9,
|
||||
args->a10,args->a11,args->a12,args->a13,args->a14,args->a15);
|
||||
args->r1 = r1;
|
||||
args->err = errno;
|
||||
}
|
||||
@@ -36,23 +39,17 @@ void syscall9(struct syscall9Args *args) {
|
||||
import "C"
|
||||
import "unsafe"
|
||||
|
||||
// assign purego.syscall9XABI0 to the C version of this function.
|
||||
var Syscall9XABI0 = unsafe.Pointer(C.syscall9)
|
||||
|
||||
// all that is needed is to assign each dl function because then its
|
||||
// symbol will then be made available to the linker and linked to inside dlfcn.go
|
||||
var (
|
||||
_ = C.dlopen
|
||||
_ = C.dlsym
|
||||
_ = C.dlerror
|
||||
_ = C.dlclose
|
||||
)
|
||||
// assign purego.syscall15XABI0 to the C version of this function.
|
||||
var Syscall15XABI0 = unsafe.Pointer(C.syscall15)
|
||||
|
||||
//go:nosplit
|
||||
func Syscall9X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) {
|
||||
args := C.syscall9Args{C.uintptr_t(fn), C.uintptr_t(a1), C.uintptr_t(a2), C.uintptr_t(a3),
|
||||
func Syscall15X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr) (r1, r2, err uintptr) {
|
||||
args := C.syscall15Args{
|
||||
C.uintptr_t(fn), C.uintptr_t(a1), C.uintptr_t(a2), C.uintptr_t(a3),
|
||||
C.uintptr_t(a4), C.uintptr_t(a5), C.uintptr_t(a6),
|
||||
C.uintptr_t(a7), C.uintptr_t(a8), C.uintptr_t(a9), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
C.syscall9(&args)
|
||||
C.uintptr_t(a7), C.uintptr_t(a8), C.uintptr_t(a9), C.uintptr_t(a10), C.uintptr_t(a11), C.uintptr_t(a12),
|
||||
C.uintptr_t(a13), C.uintptr_t(a14), C.uintptr_t(a15), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
}
|
||||
C.syscall15(&args)
|
||||
return uintptr(args.r1), uintptr(args.r2), uintptr(args.err)
|
||||
}
|
||||
|
2
vendor/github.com/ebitengine/purego/internal/fakecgo/asm_amd64.s
generated
vendored
2
vendor/github.com/ebitengine/purego/internal/fakecgo/asm_amd64.s
generated
vendored
@@ -10,7 +10,7 @@
|
||||
// Saves C callee-saved registers and calls cgocallback with three arguments.
|
||||
// fn is the PC of a func(a unsafe.Pointer) function.
|
||||
// This signature is known to SWIG, so we can't change it.
|
||||
TEXT crosscall2(SB), NOSPLIT|NOFRAME, $0-0
|
||||
TEXT crosscall2(SB), NOSPLIT, $0-0
|
||||
PUSH_REGS_HOST_TO_ABI0()
|
||||
|
||||
// Make room for arguments to cgocallback.
|
||||
|
272
vendor/github.com/ebitengine/purego/struct_amd64.go
generated
vendored
Normal file
272
vendor/github.com/ebitengine/purego/struct_amd64.go
generated
vendored
Normal file
@@ -0,0 +1,272 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2024 The Ebitengine Authors
|
||||
|
||||
package purego
|
||||
|
||||
import (
|
||||
"math"
|
||||
"reflect"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func getStruct(outType reflect.Type, syscall syscall15Args) (v reflect.Value) {
|
||||
outSize := outType.Size()
|
||||
switch {
|
||||
case outSize == 0:
|
||||
return reflect.New(outType).Elem()
|
||||
case outSize <= 8:
|
||||
if isAllFloats(outType) {
|
||||
// 2 float32s or 1 float64s are return in the float register
|
||||
return reflect.NewAt(outType, unsafe.Pointer(&struct{ a uintptr }{syscall.f1})).Elem()
|
||||
}
|
||||
// up to 8 bytes is returned in RAX
|
||||
return reflect.NewAt(outType, unsafe.Pointer(&struct{ a uintptr }{syscall.a1})).Elem()
|
||||
case outSize <= 16:
|
||||
r1, r2 := syscall.a1, syscall.a2
|
||||
if isAllFloats(outType) {
|
||||
r1 = syscall.f1
|
||||
r2 = syscall.f2
|
||||
} else {
|
||||
// check first 8 bytes if it's floats
|
||||
hasFirstFloat := false
|
||||
f1 := outType.Field(0).Type
|
||||
if f1.Kind() == reflect.Float64 || f1.Kind() == reflect.Float32 && outType.Field(1).Type.Kind() == reflect.Float32 {
|
||||
r1 = syscall.f1
|
||||
hasFirstFloat = true
|
||||
}
|
||||
|
||||
// find index of the field that starts the second 8 bytes
|
||||
var i int
|
||||
for i = 0; i < outType.NumField(); i++ {
|
||||
if outType.Field(i).Offset == 8 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// check last 8 bytes if they are floats
|
||||
f1 = outType.Field(i).Type
|
||||
if f1.Kind() == reflect.Float64 || f1.Kind() == reflect.Float32 && i+1 == outType.NumField() {
|
||||
r2 = syscall.f1
|
||||
} else if hasFirstFloat {
|
||||
// if the first field was a float then that means the second integer field
|
||||
// comes from the first integer register
|
||||
r2 = syscall.a1
|
||||
}
|
||||
}
|
||||
return reflect.NewAt(outType, unsafe.Pointer(&struct{ a, b uintptr }{r1, r2})).Elem()
|
||||
default:
|
||||
// create struct from the Go pointer created above
|
||||
// weird pointer dereference to circumvent go vet
|
||||
return reflect.NewAt(outType, *(*unsafe.Pointer)(unsafe.Pointer(&syscall.a1))).Elem()
|
||||
}
|
||||
}
|
||||
|
||||
func isAllFloats(ty reflect.Type) bool {
|
||||
for i := 0; i < ty.NumField(); i++ {
|
||||
f := ty.Field(i)
|
||||
switch f.Type.Kind() {
|
||||
case reflect.Float64, reflect.Float32:
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// https://refspecs.linuxbase.org/elf/x86_64-abi-0.99.pdf
|
||||
// https://gitlab.com/x86-psABIs/x86-64-ABI
|
||||
// Class determines where the 8 byte value goes.
|
||||
// Higher value classes win over lower value classes
|
||||
const (
|
||||
_NO_CLASS = 0b0000
|
||||
_SSE = 0b0001
|
||||
_X87 = 0b0011 // long double not used in Go
|
||||
_INTEGER = 0b0111
|
||||
_MEMORY = 0b1111
|
||||
)
|
||||
|
||||
func addStruct(v reflect.Value, numInts, numFloats, numStack *int, addInt, addFloat, addStack func(uintptr), keepAlive []interface{}) []interface{} {
|
||||
if v.Type().Size() == 0 {
|
||||
return keepAlive
|
||||
}
|
||||
|
||||
// if greater than 64 bytes place on stack
|
||||
if v.Type().Size() > 8*8 {
|
||||
placeStack(v, addStack)
|
||||
return keepAlive
|
||||
}
|
||||
var (
|
||||
savedNumFloats = *numFloats
|
||||
savedNumInts = *numInts
|
||||
savedNumStack = *numStack
|
||||
)
|
||||
placeOnStack := postMerger(v.Type()) || !tryPlaceRegister(v, addFloat, addInt)
|
||||
if placeOnStack {
|
||||
// reset any values placed in registers
|
||||
*numFloats = savedNumFloats
|
||||
*numInts = savedNumInts
|
||||
*numStack = savedNumStack
|
||||
placeStack(v, addStack)
|
||||
}
|
||||
return keepAlive
|
||||
}
|
||||
|
||||
func postMerger(t reflect.Type) bool {
|
||||
// (c) If the size of the aggregate exceeds two eightbytes and the first eight- byte isn’t SSE or any other
|
||||
// eightbyte isn’t SSEUP, the whole argument is passed in memory.
|
||||
if t.Kind() != reflect.Struct {
|
||||
return false
|
||||
}
|
||||
if t.Size() <= 2*8 {
|
||||
return false
|
||||
}
|
||||
first := getFirst(t).Kind()
|
||||
if first != reflect.Float32 && first != reflect.Float64 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func getFirst(t reflect.Type) reflect.Type {
|
||||
first := t.Field(0).Type
|
||||
if first.Kind() == reflect.Struct {
|
||||
return getFirst(first)
|
||||
}
|
||||
return first
|
||||
}
|
||||
|
||||
func tryPlaceRegister(v reflect.Value, addFloat func(uintptr), addInt func(uintptr)) (ok bool) {
|
||||
ok = true
|
||||
var val uint64
|
||||
var shift byte // # of bits to shift
|
||||
var flushed bool
|
||||
class := _NO_CLASS
|
||||
flushIfNeeded := func() {
|
||||
if flushed {
|
||||
return
|
||||
}
|
||||
flushed = true
|
||||
if class == _SSE {
|
||||
addFloat(uintptr(val))
|
||||
} else {
|
||||
addInt(uintptr(val))
|
||||
}
|
||||
val = 0
|
||||
shift = 0
|
||||
class = _NO_CLASS
|
||||
}
|
||||
var place func(v reflect.Value)
|
||||
place = func(v reflect.Value) {
|
||||
var numFields int
|
||||
if v.Kind() == reflect.Struct {
|
||||
numFields = v.Type().NumField()
|
||||
} else {
|
||||
numFields = v.Type().Len()
|
||||
}
|
||||
|
||||
for i := 0; i < numFields; i++ {
|
||||
flushed = false
|
||||
var f reflect.Value
|
||||
if v.Kind() == reflect.Struct {
|
||||
f = v.Field(i)
|
||||
} else {
|
||||
f = v.Index(i)
|
||||
}
|
||||
switch f.Kind() {
|
||||
case reflect.Struct:
|
||||
place(f)
|
||||
case reflect.Bool:
|
||||
if f.Bool() {
|
||||
val |= 1
|
||||
}
|
||||
shift += 8
|
||||
class |= _INTEGER
|
||||
case reflect.Pointer:
|
||||
ok = false
|
||||
return
|
||||
case reflect.Int8:
|
||||
val |= uint64(f.Int()&0xFF) << shift
|
||||
shift += 8
|
||||
class |= _INTEGER
|
||||
case reflect.Int16:
|
||||
val |= uint64(f.Int()&0xFFFF) << shift
|
||||
shift += 16
|
||||
class |= _INTEGER
|
||||
case reflect.Int32:
|
||||
val |= uint64(f.Int()&0xFFFF_FFFF) << shift
|
||||
shift += 32
|
||||
class |= _INTEGER
|
||||
case reflect.Int64:
|
||||
val = uint64(f.Int())
|
||||
shift = 64
|
||||
class = _INTEGER
|
||||
case reflect.Uint8:
|
||||
val |= f.Uint() << shift
|
||||
shift += 8
|
||||
class |= _INTEGER
|
||||
case reflect.Uint16:
|
||||
val |= f.Uint() << shift
|
||||
shift += 16
|
||||
class |= _INTEGER
|
||||
case reflect.Uint32:
|
||||
val |= f.Uint() << shift
|
||||
shift += 32
|
||||
class |= _INTEGER
|
||||
case reflect.Uint64:
|
||||
val = f.Uint()
|
||||
shift = 64
|
||||
class = _INTEGER
|
||||
case reflect.Float32:
|
||||
val |= uint64(math.Float32bits(float32(f.Float()))) << shift
|
||||
shift += 32
|
||||
class |= _SSE
|
||||
case reflect.Float64:
|
||||
if v.Type().Size() > 16 {
|
||||
ok = false
|
||||
return
|
||||
}
|
||||
val = uint64(math.Float64bits(f.Float()))
|
||||
shift = 64
|
||||
class = _SSE
|
||||
case reflect.Array:
|
||||
place(f)
|
||||
default:
|
||||
panic("purego: unsupported kind " + f.Kind().String())
|
||||
}
|
||||
|
||||
if shift == 64 {
|
||||
flushIfNeeded()
|
||||
} else if shift > 64 {
|
||||
// Should never happen, but may if we forget to reset shift after flush (or forget to flush),
|
||||
// better fall apart here, than corrupt arguments.
|
||||
panic("purego: tryPlaceRegisters shift > 64")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
place(v)
|
||||
flushIfNeeded()
|
||||
return ok
|
||||
}
|
||||
|
||||
func placeStack(v reflect.Value, addStack func(uintptr)) {
|
||||
for i := 0; i < v.Type().NumField(); i++ {
|
||||
f := v.Field(i)
|
||||
switch f.Kind() {
|
||||
case reflect.Pointer:
|
||||
addStack(f.Pointer())
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
addStack(uintptr(f.Int()))
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
addStack(uintptr(f.Uint()))
|
||||
case reflect.Float32:
|
||||
addStack(uintptr(math.Float32bits(float32(f.Float()))))
|
||||
case reflect.Float64:
|
||||
addStack(uintptr(math.Float64bits(f.Float())))
|
||||
case reflect.Struct:
|
||||
placeStack(f, addStack)
|
||||
default:
|
||||
panic("purego: unsupported kind " + f.Kind().String())
|
||||
}
|
||||
}
|
||||
}
|
274
vendor/github.com/ebitengine/purego/struct_arm64.go
generated
vendored
Normal file
274
vendor/github.com/ebitengine/purego/struct_arm64.go
generated
vendored
Normal file
@@ -0,0 +1,274 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2024 The Ebitengine Authors
|
||||
|
||||
package purego
|
||||
|
||||
import (
|
||||
"math"
|
||||
"reflect"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func getStruct(outType reflect.Type, syscall syscall15Args) (v reflect.Value) {
|
||||
outSize := outType.Size()
|
||||
switch {
|
||||
case outSize == 0:
|
||||
return reflect.New(outType).Elem()
|
||||
case outSize <= 8:
|
||||
r1 := syscall.a1
|
||||
if isAllSameFloat(outType) {
|
||||
r1 = syscall.f1
|
||||
if outType.NumField() == 2 {
|
||||
r1 = syscall.f2<<32 | syscall.f1
|
||||
}
|
||||
}
|
||||
return reflect.NewAt(outType, unsafe.Pointer(&struct{ a uintptr }{r1})).Elem()
|
||||
case outSize <= 16:
|
||||
r1, r2 := syscall.a1, syscall.a2
|
||||
if isAllSameFloat(outType) {
|
||||
switch outType.NumField() {
|
||||
case 4:
|
||||
r1 = syscall.f2<<32 | syscall.f1
|
||||
r2 = syscall.f4<<32 | syscall.f3
|
||||
case 3:
|
||||
r1 = syscall.f2<<32 | syscall.f1
|
||||
r2 = syscall.f3
|
||||
case 2:
|
||||
r1 = syscall.f1
|
||||
r2 = syscall.f2
|
||||
default:
|
||||
panic("unreachable")
|
||||
}
|
||||
}
|
||||
return reflect.NewAt(outType, unsafe.Pointer(&struct{ a, b uintptr }{r1, r2})).Elem()
|
||||
default:
|
||||
if isAllSameFloat(outType) && outType.NumField() <= 4 {
|
||||
switch outType.NumField() {
|
||||
case 4:
|
||||
return reflect.NewAt(outType, unsafe.Pointer(&struct{ a, b, c, d uintptr }{syscall.f1, syscall.f2, syscall.f3, syscall.f4})).Elem()
|
||||
case 3:
|
||||
return reflect.NewAt(outType, unsafe.Pointer(&struct{ a, b, c uintptr }{syscall.f1, syscall.f2, syscall.f3})).Elem()
|
||||
default:
|
||||
panic("unreachable")
|
||||
}
|
||||
}
|
||||
// create struct from the Go pointer created in arm64_r8
|
||||
// weird pointer dereference to circumvent go vet
|
||||
return reflect.NewAt(outType, *(*unsafe.Pointer)(unsafe.Pointer(&syscall.arm64_r8))).Elem()
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/ARM-software/abi-aa/blob/main/sysvabi64/sysvabi64.rst
|
||||
const (
|
||||
_NO_CLASS = 0b00
|
||||
_FLOAT = 0b01
|
||||
_INT = 0b11
|
||||
)
|
||||
|
||||
func addStruct(v reflect.Value, numInts, numFloats, numStack *int, addInt, addFloat, addStack func(uintptr), keepAlive []interface{}) []interface{} {
|
||||
if v.Type().Size() == 0 {
|
||||
return keepAlive
|
||||
}
|
||||
|
||||
if hva, hfa, size := isHVA(v.Type()), isHFA(v.Type()), v.Type().Size(); hva || hfa || size <= 16 {
|
||||
// if this doesn't fit entirely in registers then
|
||||
// each element goes onto the stack
|
||||
if hfa && *numFloats+v.NumField() > numOfFloats {
|
||||
*numFloats = numOfFloats
|
||||
} else if hva && *numInts+v.NumField() > numOfIntegerRegisters() {
|
||||
*numInts = numOfIntegerRegisters()
|
||||
}
|
||||
|
||||
placeRegisters(v, addFloat, addInt)
|
||||
} else {
|
||||
keepAlive = placeStack(v, keepAlive, addInt)
|
||||
}
|
||||
return keepAlive // the struct was allocated so don't panic
|
||||
}
|
||||
|
||||
func placeRegisters(v reflect.Value, addFloat func(uintptr), addInt func(uintptr)) {
|
||||
var val uint64
|
||||
var shift byte
|
||||
var flushed bool
|
||||
class := _NO_CLASS
|
||||
var place func(v reflect.Value)
|
||||
place = func(v reflect.Value) {
|
||||
var numFields int
|
||||
if v.Kind() == reflect.Struct {
|
||||
numFields = v.Type().NumField()
|
||||
} else {
|
||||
numFields = v.Type().Len()
|
||||
}
|
||||
for k := 0; k < numFields; k++ {
|
||||
flushed = false
|
||||
var f reflect.Value
|
||||
if v.Kind() == reflect.Struct {
|
||||
f = v.Field(k)
|
||||
} else {
|
||||
f = v.Index(k)
|
||||
}
|
||||
if shift >= 64 {
|
||||
shift = 0
|
||||
flushed = true
|
||||
if class == _FLOAT {
|
||||
addFloat(uintptr(val))
|
||||
} else {
|
||||
addInt(uintptr(val))
|
||||
}
|
||||
}
|
||||
switch f.Type().Kind() {
|
||||
case reflect.Struct:
|
||||
place(f)
|
||||
case reflect.Bool:
|
||||
if f.Bool() {
|
||||
val |= 1
|
||||
}
|
||||
shift += 8
|
||||
class |= _INT
|
||||
case reflect.Uint8:
|
||||
val |= f.Uint() << shift
|
||||
shift += 8
|
||||
class |= _INT
|
||||
case reflect.Uint16:
|
||||
val |= f.Uint() << shift
|
||||
shift += 16
|
||||
class |= _INT
|
||||
case reflect.Uint32:
|
||||
val |= f.Uint() << shift
|
||||
shift += 32
|
||||
class |= _INT
|
||||
case reflect.Uint64:
|
||||
addInt(uintptr(f.Uint()))
|
||||
shift = 0
|
||||
flushed = true
|
||||
case reflect.Int8:
|
||||
val |= uint64(f.Int()&0xFF) << shift
|
||||
shift += 8
|
||||
class |= _INT
|
||||
case reflect.Int16:
|
||||
val |= uint64(f.Int()&0xFFFF) << shift
|
||||
shift += 16
|
||||
class |= _INT
|
||||
case reflect.Int32:
|
||||
val |= uint64(f.Int()&0xFFFF_FFFF) << shift
|
||||
shift += 32
|
||||
class |= _INT
|
||||
case reflect.Int64:
|
||||
addInt(uintptr(f.Int()))
|
||||
shift = 0
|
||||
flushed = true
|
||||
case reflect.Float32:
|
||||
if class == _FLOAT {
|
||||
addFloat(uintptr(val))
|
||||
val = 0
|
||||
shift = 0
|
||||
}
|
||||
val |= uint64(math.Float32bits(float32(f.Float()))) << shift
|
||||
shift += 32
|
||||
class |= _FLOAT
|
||||
case reflect.Float64:
|
||||
addFloat(uintptr(math.Float64bits(float64(f.Float()))))
|
||||
shift = 0
|
||||
flushed = true
|
||||
case reflect.Array:
|
||||
place(f)
|
||||
default:
|
||||
panic("purego: unsupported kind " + f.Kind().String())
|
||||
}
|
||||
}
|
||||
}
|
||||
place(v)
|
||||
if !flushed {
|
||||
if class == _FLOAT {
|
||||
addFloat(uintptr(val))
|
||||
} else {
|
||||
addInt(uintptr(val))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func placeStack(v reflect.Value, keepAlive []interface{}, addInt func(uintptr)) []interface{} {
|
||||
// Struct is too big to be placed in registers.
|
||||
// Copy to heap and place the pointer in register
|
||||
ptrStruct := reflect.New(v.Type())
|
||||
ptrStruct.Elem().Set(v)
|
||||
ptr := ptrStruct.Elem().Addr().UnsafePointer()
|
||||
keepAlive = append(keepAlive, ptr)
|
||||
addInt(uintptr(ptr))
|
||||
return keepAlive
|
||||
}
|
||||
|
||||
// isHFA reports a Homogeneous Floating-point Aggregate (HFA) which is a Fundamental Data Type that is a
|
||||
// Floating-Point type and at most four uniquely addressable members (5.9.5.1 in [Arm64 Calling Convention]).
|
||||
// This type of struct will be placed more compactly than the individual fields.
|
||||
//
|
||||
// [Arm64 Calling Convention]: https://github.com/ARM-software/abi-aa/blob/main/sysvabi64/sysvabi64.rst
|
||||
func isHFA(t reflect.Type) bool {
|
||||
// round up struct size to nearest 8 see section B.4
|
||||
structSize := roundUpTo8(t.Size())
|
||||
if structSize == 0 || t.NumField() > 4 {
|
||||
return false
|
||||
}
|
||||
first := t.Field(0)
|
||||
switch first.Type.Kind() {
|
||||
case reflect.Float32, reflect.Float64:
|
||||
firstKind := first.Type.Kind()
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
if t.Field(i).Type.Kind() != firstKind {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
case reflect.Array:
|
||||
switch first.Type.Elem().Kind() {
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
case reflect.Struct:
|
||||
for i := 0; i < first.Type.NumField(); i++ {
|
||||
if !isHFA(first.Type) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// isHVA reports a Homogeneous Aggregate with a Fundamental Data Type that is a Short-Vector type
|
||||
// and at most four uniquely addressable members (5.9.5.2 in [Arm64 Calling Convention]).
|
||||
// A short vector is a machine type that is composed of repeated instances of one fundamental integral or
|
||||
// floating-point type. It may be 8 or 16 bytes in total size (5.4 in [Arm64 Calling Convention]).
|
||||
// This type of struct will be placed more compactly than the individual fields.
|
||||
//
|
||||
// [Arm64 Calling Convention]: https://github.com/ARM-software/abi-aa/blob/main/sysvabi64/sysvabi64.rst
|
||||
func isHVA(t reflect.Type) bool {
|
||||
// round up struct size to nearest 8 see section B.4
|
||||
structSize := roundUpTo8(t.Size())
|
||||
if structSize == 0 || (structSize != 8 && structSize != 16) {
|
||||
return false
|
||||
}
|
||||
first := t.Field(0)
|
||||
switch first.Type.Kind() {
|
||||
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Int8, reflect.Int16, reflect.Int32:
|
||||
firstKind := first.Type.Kind()
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
if t.Field(i).Type.Kind() != firstKind {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
case reflect.Array:
|
||||
switch first.Type.Elem().Kind() {
|
||||
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Int8, reflect.Int16, reflect.Int32:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
16
vendor/github.com/ebitengine/purego/struct_other.go
generated
vendored
Normal file
16
vendor/github.com/ebitengine/purego/struct_other.go
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2024 The Ebitengine Authors
|
||||
|
||||
//go:build !amd64 && !arm64
|
||||
|
||||
package purego
|
||||
|
||||
import "reflect"
|
||||
|
||||
func addStruct(v reflect.Value, numInts, numFloats, numStack *int, addInt, addFloat, addStack func(uintptr), keepAlive []interface{}) []interface{} {
|
||||
panic("purego: struct arguments are not supported")
|
||||
}
|
||||
|
||||
func getStruct(outType reflect.Type, syscall syscall15Args) (v reflect.Value) {
|
||||
panic("purego: struct returns are not supported")
|
||||
}
|
109
vendor/github.com/ebitengine/purego/sys_amd64.s
generated
vendored
109
vendor/github.com/ebitengine/purego/sys_amd64.s
generated
vendored
@@ -1,15 +1,18 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
|
||||
|
||||
//go:build darwin || freebsd || (!cgo && linux)
|
||||
//go:build darwin || freebsd || linux
|
||||
|
||||
#include "textflag.h"
|
||||
#include "abi_amd64.h"
|
||||
#include "go_asm.h"
|
||||
#include "funcdata.h"
|
||||
|
||||
// syscall9X calls a function in libc on behalf of the syscall package.
|
||||
// syscall9X takes a pointer to a struct like:
|
||||
#define STACK_SIZE 80
|
||||
#define PTR_ADDRESS (STACK_SIZE - 8)
|
||||
|
||||
// syscall15X calls a function in libc on behalf of the syscall package.
|
||||
// syscall15X takes a pointer to a struct like:
|
||||
// struct {
|
||||
// fn uintptr
|
||||
// a1 uintptr
|
||||
@@ -21,64 +24,83 @@
|
||||
// a7 uintptr
|
||||
// a8 uintptr
|
||||
// a9 uintptr
|
||||
// a10 uintptr
|
||||
// a11 uintptr
|
||||
// a12 uintptr
|
||||
// a13 uintptr
|
||||
// a14 uintptr
|
||||
// a15 uintptr
|
||||
// r1 uintptr
|
||||
// r2 uintptr
|
||||
// err uintptr
|
||||
// }
|
||||
// syscall9X must be called on the g0 stack with the
|
||||
// syscall15X must be called on the g0 stack with the
|
||||
// C calling convention (use libcCall).
|
||||
GLOBL ·syscall9XABI0(SB), NOPTR|RODATA, $8
|
||||
DATA ·syscall9XABI0(SB)/8, $syscall9X(SB)
|
||||
TEXT syscall9X(SB), NOSPLIT|NOFRAME, $0
|
||||
GLOBL ·syscall15XABI0(SB), NOPTR|RODATA, $8
|
||||
DATA ·syscall15XABI0(SB)/8, $syscall15X(SB)
|
||||
TEXT syscall15X(SB), NOSPLIT|NOFRAME, $0
|
||||
PUSHQ BP
|
||||
MOVQ SP, BP
|
||||
SUBQ $32, SP
|
||||
MOVQ DI, 24(BP) // save the pointer
|
||||
SUBQ $STACK_SIZE, SP
|
||||
MOVQ DI, PTR_ADDRESS(BP) // save the pointer
|
||||
MOVQ DI, R11
|
||||
|
||||
MOVQ syscall9Args_f1(DI), X0 // f1
|
||||
MOVQ syscall9Args_f2(DI), X1 // f2
|
||||
MOVQ syscall9Args_f3(DI), X2 // f3
|
||||
MOVQ syscall9Args_f4(DI), X3 // f4
|
||||
MOVQ syscall9Args_f5(DI), X4 // f5
|
||||
MOVQ syscall9Args_f6(DI), X5 // f6
|
||||
MOVQ syscall9Args_f7(DI), X6 // f7
|
||||
MOVQ syscall9Args_f8(DI), X7 // f8
|
||||
MOVQ syscall15Args_f1(R11), X0 // f1
|
||||
MOVQ syscall15Args_f2(R11), X1 // f2
|
||||
MOVQ syscall15Args_f3(R11), X2 // f3
|
||||
MOVQ syscall15Args_f4(R11), X3 // f4
|
||||
MOVQ syscall15Args_f5(R11), X4 // f5
|
||||
MOVQ syscall15Args_f6(R11), X5 // f6
|
||||
MOVQ syscall15Args_f7(R11), X6 // f7
|
||||
MOVQ syscall15Args_f8(R11), X7 // f8
|
||||
|
||||
MOVQ syscall9Args_fn(DI), R10 // fn
|
||||
MOVQ syscall9Args_a2(DI), SI // a2
|
||||
MOVQ syscall9Args_a3(DI), DX // a3
|
||||
MOVQ syscall9Args_a4(DI), CX // a4
|
||||
MOVQ syscall9Args_a5(DI), R8 // a5
|
||||
MOVQ syscall9Args_a6(DI), R9 // a6
|
||||
MOVQ syscall9Args_a7(DI), R11 // a7
|
||||
MOVQ syscall9Args_a8(DI), R12 // a8
|
||||
MOVQ syscall9Args_a9(DI), R13 // a9
|
||||
MOVQ syscall9Args_a1(DI), DI // a1
|
||||
MOVQ syscall15Args_a1(R11), DI // a1
|
||||
MOVQ syscall15Args_a2(R11), SI // a2
|
||||
MOVQ syscall15Args_a3(R11), DX // a3
|
||||
MOVQ syscall15Args_a4(R11), CX // a4
|
||||
MOVQ syscall15Args_a5(R11), R8 // a5
|
||||
MOVQ syscall15Args_a6(R11), R9 // a6
|
||||
|
||||
// push the remaining paramters onto the stack
|
||||
MOVQ R11, 0(SP) // push a7
|
||||
MOVQ R12, 8(SP) // push a8
|
||||
MOVQ R13, 16(SP) // push a9
|
||||
XORL AX, AX // vararg: say "no float args"
|
||||
MOVQ syscall15Args_a7(R11), R12
|
||||
MOVQ R12, 0(SP) // push a7
|
||||
MOVQ syscall15Args_a8(R11), R12
|
||||
MOVQ R12, 8(SP) // push a8
|
||||
MOVQ syscall15Args_a9(R11), R12
|
||||
MOVQ R12, 16(SP) // push a9
|
||||
MOVQ syscall15Args_a10(R11), R12
|
||||
MOVQ R12, 24(SP) // push a10
|
||||
MOVQ syscall15Args_a11(R11), R12
|
||||
MOVQ R12, 32(SP) // push a11
|
||||
MOVQ syscall15Args_a12(R11), R12
|
||||
MOVQ R12, 40(SP) // push a12
|
||||
MOVQ syscall15Args_a13(R11), R12
|
||||
MOVQ R12, 48(SP) // push a13
|
||||
MOVQ syscall15Args_a14(R11), R12
|
||||
MOVQ R12, 56(SP) // push a14
|
||||
MOVQ syscall15Args_a15(R11), R12
|
||||
MOVQ R12, 64(SP) // push a15
|
||||
XORL AX, AX // vararg: say "no float args"
|
||||
|
||||
MOVQ syscall15Args_fn(R11), R10 // fn
|
||||
CALL R10
|
||||
|
||||
MOVQ 24(BP), DI // get the pointer back
|
||||
MOVQ AX, syscall9Args_r1(DI) // r1
|
||||
MOVQ X0, syscall9Args_r2(DI) // r2
|
||||
MOVQ PTR_ADDRESS(BP), DI // get the pointer back
|
||||
MOVQ AX, syscall15Args_a1(DI) // r1
|
||||
MOVQ DX, syscall15Args_a2(DI) // r3
|
||||
MOVQ X0, syscall15Args_f1(DI) // f1
|
||||
MOVQ X1, syscall15Args_f2(DI) // f2
|
||||
|
||||
XORL AX, AX // no error (it's ignored anyway)
|
||||
ADDQ $32, SP
|
||||
XORL AX, AX // no error (it's ignored anyway)
|
||||
ADDQ $STACK_SIZE, SP
|
||||
MOVQ BP, SP
|
||||
POPQ BP
|
||||
RET
|
||||
|
||||
TEXT callbackasm1(SB), NOSPLIT|NOFRAME, $0
|
||||
// remove return address from stack, we are not returning to callbackasm, but to its caller.
|
||||
MOVQ 0(SP), AX
|
||||
ADDQ $8, SP
|
||||
|
||||
MOVQ 0(SP), R10 // get the return SP so that we can align register args with stack args
|
||||
MOVQ 0(SP), AX // save the return address to calculate the cb index
|
||||
MOVQ 8(SP), R10 // get the return SP so that we can align register args with stack args
|
||||
ADDQ $8, SP // remove return address from stack, we are not returning to callbackasm, but to its caller.
|
||||
|
||||
// make space for first six int and 8 float arguments below the frame
|
||||
ADJSP $14*8, SP
|
||||
@@ -98,7 +120,7 @@ TEXT callbackasm1(SB), NOSPLIT|NOFRAME, $0
|
||||
MOVQ R9, (14*8)(SP)
|
||||
LEAQ 8(SP), R8 // R8 = address of args vector
|
||||
|
||||
MOVQ R10, 0(SP) // push the stack pointer below registers
|
||||
PUSHQ R10 // push the stack pointer below registers
|
||||
|
||||
// determine index into runtime·cbs table
|
||||
MOVQ $callbackasm(SB), DX
|
||||
@@ -134,8 +156,7 @@ TEXT callbackasm1(SB), NOSPLIT|NOFRAME, $0
|
||||
|
||||
POP_REGS_HOST_TO_ABI0()
|
||||
|
||||
MOVQ 0(SP), R10 // get the SP back
|
||||
|
||||
POPQ R10 // get the SP back
|
||||
ADJSP $-14*8, SP // remove arguments
|
||||
|
||||
MOVQ R10, 0(SP)
|
||||
|
95
vendor/github.com/ebitengine/purego/sys_arm64.s
generated
vendored
95
vendor/github.com/ebitengine/purego/sys_arm64.s
generated
vendored
@@ -1,14 +1,17 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
|
||||
|
||||
//go:build darwin || freebsd || (!cgo && linux) || windows
|
||||
//go:build darwin || freebsd || linux || windows
|
||||
|
||||
#include "textflag.h"
|
||||
#include "go_asm.h"
|
||||
#include "funcdata.h"
|
||||
|
||||
// syscall9X calls a function in libc on behalf of the syscall package.
|
||||
// syscall9X takes a pointer to a struct like:
|
||||
#define STACK_SIZE 64
|
||||
#define PTR_ADDRESS (STACK_SIZE - 8)
|
||||
|
||||
// syscall15X calls a function in libc on behalf of the syscall package.
|
||||
// syscall15X takes a pointer to a struct like:
|
||||
// struct {
|
||||
// fn uintptr
|
||||
// a1 uintptr
|
||||
@@ -20,44 +23,70 @@
|
||||
// a7 uintptr
|
||||
// a8 uintptr
|
||||
// a9 uintptr
|
||||
// a10 uintptr
|
||||
// a11 uintptr
|
||||
// a12 uintptr
|
||||
// a13 uintptr
|
||||
// a14 uintptr
|
||||
// a15 uintptr
|
||||
// r1 uintptr
|
||||
// r2 uintptr
|
||||
// err uintptr
|
||||
// }
|
||||
// syscall9X must be called on the g0 stack with the
|
||||
// syscall15X must be called on the g0 stack with the
|
||||
// C calling convention (use libcCall).
|
||||
GLOBL ·syscall9XABI0(SB), NOPTR|RODATA, $8
|
||||
DATA ·syscall9XABI0(SB)/8, $syscall9X(SB)
|
||||
TEXT syscall9X(SB), NOSPLIT, $0
|
||||
SUB $16, RSP // push structure pointer
|
||||
MOVD R0, 8(RSP)
|
||||
GLOBL ·syscall15XABI0(SB), NOPTR|RODATA, $8
|
||||
DATA ·syscall15XABI0(SB)/8, $syscall15X(SB)
|
||||
TEXT syscall15X(SB), NOSPLIT, $0
|
||||
SUB $STACK_SIZE, RSP // push structure pointer
|
||||
MOVD R0, PTR_ADDRESS(RSP)
|
||||
MOVD R0, R9
|
||||
|
||||
FMOVD syscall9Args_f1(R0), F0 // f1
|
||||
FMOVD syscall9Args_f2(R0), F1 // f2
|
||||
FMOVD syscall9Args_f3(R0), F2 // f3
|
||||
FMOVD syscall9Args_f4(R0), F3 // f4
|
||||
FMOVD syscall9Args_f5(R0), F4 // f5
|
||||
FMOVD syscall9Args_f6(R0), F5 // f6
|
||||
FMOVD syscall9Args_f7(R0), F6 // f7
|
||||
FMOVD syscall9Args_f8(R0), F7 // f8
|
||||
FMOVD syscall15Args_f1(R9), F0 // f1
|
||||
FMOVD syscall15Args_f2(R9), F1 // f2
|
||||
FMOVD syscall15Args_f3(R9), F2 // f3
|
||||
FMOVD syscall15Args_f4(R9), F3 // f4
|
||||
FMOVD syscall15Args_f5(R9), F4 // f5
|
||||
FMOVD syscall15Args_f6(R9), F5 // f6
|
||||
FMOVD syscall15Args_f7(R9), F6 // f7
|
||||
FMOVD syscall15Args_f8(R9), F7 // f8
|
||||
|
||||
MOVD syscall9Args_fn(R0), R12 // fn
|
||||
MOVD syscall9Args_a2(R0), R1 // a2
|
||||
MOVD syscall9Args_a3(R0), R2 // a3
|
||||
MOVD syscall9Args_a4(R0), R3 // a4
|
||||
MOVD syscall9Args_a5(R0), R4 // a5
|
||||
MOVD syscall9Args_a6(R0), R5 // a6
|
||||
MOVD syscall9Args_a7(R0), R6 // a7
|
||||
MOVD syscall9Args_a8(R0), R7 // a8
|
||||
MOVD syscall9Args_a9(R0), R8 // a9
|
||||
MOVD syscall9Args_a1(R0), R0 // a1
|
||||
MOVD syscall15Args_a1(R9), R0 // a1
|
||||
MOVD syscall15Args_a2(R9), R1 // a2
|
||||
MOVD syscall15Args_a3(R9), R2 // a3
|
||||
MOVD syscall15Args_a4(R9), R3 // a4
|
||||
MOVD syscall15Args_a5(R9), R4 // a5
|
||||
MOVD syscall15Args_a6(R9), R5 // a6
|
||||
MOVD syscall15Args_a7(R9), R6 // a7
|
||||
MOVD syscall15Args_a8(R9), R7 // a8
|
||||
MOVD syscall15Args_arm64_r8(R9), R8 // r8
|
||||
|
||||
MOVD R8, (RSP) // push a9 onto stack
|
||||
MOVD syscall15Args_a9(R9), R10
|
||||
MOVD R10, 0(RSP) // push a9 onto stack
|
||||
MOVD syscall15Args_a10(R9), R10
|
||||
MOVD R10, 8(RSP) // push a10 onto stack
|
||||
MOVD syscall15Args_a11(R9), R10
|
||||
MOVD R10, 16(RSP) // push a11 onto stack
|
||||
MOVD syscall15Args_a12(R9), R10
|
||||
MOVD R10, 24(RSP) // push a12 onto stack
|
||||
MOVD syscall15Args_a13(R9), R10
|
||||
MOVD R10, 32(RSP) // push a13 onto stack
|
||||
MOVD syscall15Args_a14(R9), R10
|
||||
MOVD R10, 40(RSP) // push a14 onto stack
|
||||
MOVD syscall15Args_a15(R9), R10
|
||||
MOVD R10, 48(RSP) // push a15 onto stack
|
||||
|
||||
BL (R12)
|
||||
MOVD syscall15Args_fn(R9), R10 // fn
|
||||
BL (R10)
|
||||
|
||||
MOVD PTR_ADDRESS(RSP), R2 // pop structure pointer
|
||||
ADD $STACK_SIZE, RSP
|
||||
|
||||
MOVD R0, syscall15Args_a1(R2) // save r1
|
||||
MOVD R1, syscall15Args_a2(R2) // save r3
|
||||
FMOVD F0, syscall15Args_f1(R2) // save f0
|
||||
FMOVD F1, syscall15Args_f2(R2) // save f1
|
||||
FMOVD F2, syscall15Args_f3(R2) // save f2
|
||||
FMOVD F3, syscall15Args_f4(R2) // save f3
|
||||
|
||||
MOVD 8(RSP), R2 // pop structure pointer
|
||||
ADD $16, RSP
|
||||
MOVD R0, syscall9Args_r1(R2) // save r1
|
||||
FMOVD F0, syscall9Args_r2(R2) // save r2
|
||||
RET
|
||||
|
2
vendor/github.com/ebitengine/purego/sys_unix_arm64.s
generated
vendored
2
vendor/github.com/ebitengine/purego/sys_unix_arm64.s
generated
vendored
@@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2023 The Ebitengine Authors
|
||||
|
||||
//go:build darwin || freebsd || (!cgo && linux)
|
||||
//go:build darwin || freebsd || linux
|
||||
|
||||
#include "textflag.h"
|
||||
#include "go_asm.h"
|
||||
|
4
vendor/github.com/ebitengine/purego/syscall.go
generated
vendored
4
vendor/github.com/ebitengine/purego/syscall.go
generated
vendored
@@ -6,7 +6,7 @@
|
||||
package purego
|
||||
|
||||
const (
|
||||
maxArgs = 9
|
||||
maxArgs = 15
|
||||
numOfFloats = 8 // arm64 and amd64 both have 8 float registers
|
||||
)
|
||||
|
||||
@@ -36,5 +36,5 @@ func SyscallN(fn uintptr, args ...uintptr) (r1, r2, err uintptr) {
|
||||
// add padding so there is no out-of-bounds slicing
|
||||
var tmp [maxArgs]uintptr
|
||||
copy(tmp[:], args)
|
||||
return syscall_syscall9X(fn, tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7], tmp[8])
|
||||
return syscall_syscall15X(fn, tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7], tmp[8], tmp[9], tmp[10], tmp[11], tmp[12], tmp[13], tmp[14])
|
||||
}
|
||||
|
19
vendor/github.com/ebitengine/purego/syscall_cgo_linux.go
generated
vendored
19
vendor/github.com/ebitengine/purego/syscall_cgo_linux.go
generated
vendored
@@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
|
||||
|
||||
//go:build cgo
|
||||
//go:build cgo && !(amd64 || arm64)
|
||||
|
||||
package purego
|
||||
|
||||
@@ -11,20 +11,21 @@ import (
|
||||
"github.com/ebitengine/purego/internal/cgo"
|
||||
)
|
||||
|
||||
var syscall9XABI0 = uintptr(cgo.Syscall9XABI0)
|
||||
var syscall15XABI0 = uintptr(cgo.Syscall15XABI0)
|
||||
|
||||
// this is only here to make the assembly files happy :)
|
||||
type syscall9Args struct {
|
||||
fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr
|
||||
f1, f2, f3, f4, f5, f6, f7, f8 uintptr
|
||||
r1, r2, err uintptr
|
||||
type syscall15Args struct {
|
||||
fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr
|
||||
f1, f2, f3, f4, f5, f6, f7, f8 uintptr
|
||||
r1, r2, err uintptr
|
||||
arm64_r8 uintptr
|
||||
}
|
||||
|
||||
//go:nosplit
|
||||
func syscall_syscall9X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) {
|
||||
return cgo.Syscall9X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9)
|
||||
func syscall_syscall15X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr) (r1, r2, err uintptr) {
|
||||
return cgo.Syscall15X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15)
|
||||
}
|
||||
|
||||
func NewCallback(_ interface{}) uintptr {
|
||||
panic("purego: NewCallback not supported")
|
||||
panic("purego: NewCallback on Linux is only supported on amd64/arm64")
|
||||
}
|
||||
|
29
vendor/github.com/ebitengine/purego/syscall_sysv.go
generated
vendored
29
vendor/github.com/ebitengine/purego/syscall_sysv.go
generated
vendored
@@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
|
||||
|
||||
//go:build darwin || freebsd || (!cgo && linux && (amd64 || arm64))
|
||||
//go:build darwin || freebsd || (linux && (amd64 || arm64))
|
||||
|
||||
package purego
|
||||
|
||||
@@ -12,23 +12,23 @@ import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var syscall9XABI0 uintptr
|
||||
var syscall15XABI0 uintptr
|
||||
|
||||
type syscall9Args struct {
|
||||
fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr
|
||||
f1, f2, f3, f4, f5, f6, f7, f8 uintptr
|
||||
r1, r2, err uintptr
|
||||
type syscall15Args struct {
|
||||
fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr
|
||||
f1, f2, f3, f4, f5, f6, f7, f8 uintptr
|
||||
arm64_r8 uintptr
|
||||
}
|
||||
|
||||
//go:nosplit
|
||||
func syscall_syscall9X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) {
|
||||
args := syscall9Args{
|
||||
fn, a1, a2, a3, a4, a5, a6, a7, a8, a9,
|
||||
func syscall_syscall15X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr) (r1, r2, err uintptr) {
|
||||
args := syscall15Args{
|
||||
fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15,
|
||||
a1, a2, a3, a4, a5, a6, a7, a8,
|
||||
r1, r2, err,
|
||||
0,
|
||||
}
|
||||
runtime_cgocall(syscall9XABI0, unsafe.Pointer(&args))
|
||||
return args.r1, args.r2, args.err
|
||||
runtime_cgocall(syscall15XABI0, unsafe.Pointer(&args))
|
||||
return args.a1, args.a2, 0
|
||||
}
|
||||
|
||||
// NewCallback converts a Go function to a function pointer conforming to the C calling convention.
|
||||
@@ -37,12 +37,7 @@ func syscall_syscall9X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2,
|
||||
// of uintptr. Only a limited number of callbacks may be created in a single Go process, and any memory allocated
|
||||
// for these callbacks is never released. At least 2000 callbacks can always be created. Although this function
|
||||
// provides similar functionality to windows.NewCallback it is distinct.
|
||||
//
|
||||
// NOTE: Linux is currently not supported and will panic if called.
|
||||
func NewCallback(fn interface{}) uintptr {
|
||||
if runtime.GOOS == "linux" {
|
||||
panic("purego: NewCallback not supported")
|
||||
}
|
||||
return compileCallback(fn)
|
||||
}
|
||||
|
||||
|
14
vendor/github.com/ebitengine/purego/syscall_windows.go
generated
vendored
14
vendor/github.com/ebitengine/purego/syscall_windows.go
generated
vendored
@@ -10,16 +10,16 @@ import (
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
var syscall9XABI0 uintptr
|
||||
var syscall15XABI0 uintptr
|
||||
|
||||
type syscall9Args struct {
|
||||
fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr
|
||||
f1, f2, f3, f4, f5, f6, f7, f8 uintptr
|
||||
r1, r2, err uintptr
|
||||
type syscall15Args struct {
|
||||
fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr
|
||||
f1, f2, f3, f4, f5, f6, f7, f8 uintptr
|
||||
arm64_r8 uintptr
|
||||
}
|
||||
|
||||
func syscall_syscall9X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) {
|
||||
r1, r2, errno := syscall.Syscall9(fn, 9, a1, a2, a3, a4, a5, a6, a7, a8, a9)
|
||||
func syscall_syscall15X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr) (r1, r2, err uintptr) {
|
||||
r1, r2, errno := syscall.Syscall15(fn, 15, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15)
|
||||
return r1, r2, uintptr(errno)
|
||||
}
|
||||
|
||||
|
2
vendor/github.com/ebitengine/purego/zcallback_amd64.s
generated
vendored
2
vendor/github.com/ebitengine/purego/zcallback_amd64.s
generated
vendored
@@ -1,6 +1,6 @@
|
||||
// Code generated by wincallback.go using 'go generate'. DO NOT EDIT.
|
||||
|
||||
//go:build darwin || freebsd || (!cgo && linux)
|
||||
//go:build darwin || freebsd || linux
|
||||
|
||||
// runtime·callbackasm is called by external code to
|
||||
// execute Go implemented callback function. It is not
|
||||
|
2
vendor/github.com/ebitengine/purego/zcallback_arm64.s
generated
vendored
2
vendor/github.com/ebitengine/purego/zcallback_arm64.s
generated
vendored
@@ -1,6 +1,6 @@
|
||||
// Code generated by wincallback.go using 'go generate'. DO NOT EDIT.
|
||||
|
||||
//go:build darwin || freebsd || (!cgo && linux)
|
||||
//go:build darwin || freebsd || linux
|
||||
|
||||
// External code calls into callbackasm at an offset corresponding
|
||||
// to the callback index. Callbackasm is a table of MOV and B instructions.
|
||||
|
Reference in New Issue
Block a user