purego: simplify code by merging darwin and linux (#98)
- commit
- 086b819e2f9a7c69be0911a894e4a4d639c38d5d
- author
- TotallyGamerJet · · 2023-02-13 04:27 UTC
- committer
- GitHub · · 2023-02-13 04:27 UTC
- parent
- 804e759
- signature
- GPG Unverified
4AEE18F83AFDEB23The key is unknown
11 files · +72 -180
M dlfcn_test.go +53 -0
| @@ -9,6 +9,7 @@ import ( | |||
| 9 | 9 | "fmt" | |
| 10 | 10 | "runtime" | |
| 11 | 11 | "testing" | |
| 12 | + | "unsafe" | |
| 12 | 13 | ||
| 13 | 14 | "github.com/ebitengine/purego" | |
| 14 | 15 | ) | |
| @@ -37,3 +38,55 @@ func TestRegisterFunc(t *testing.T) { | |||
| 37 | 38 | purego.RegisterLibFunc(&puts, libc, "puts") | |
| 38 | 39 | puts("Calling C from from Go without Cgo!") | |
| 39 | 40 | } | |
| 41 | + | ||
| 42 | + | func ExampleNewCallback() { | |
| 43 | + | if runtime.GOOS == "linux" { | |
| 44 | + | // TODO: enable once callbacks are working properly on Linux | |
| 45 | + | fmt.Println("1 2 3 4 5 6 7 8 9\n45") | |
| 46 | + | return | |
| 47 | + | } | |
| 48 | + | ||
| 49 | + | cb := purego.NewCallback(func(a1, a2, a3, a4, a5, a6, a7, a8, a9 int) int { | |
| 50 | + | fmt.Println(a1, a2, a3, a4, a5, a6, a7, a8, a9) | |
| 51 | + | return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 | |
| 52 | + | }) | |
| 53 | + | ||
| 54 | + | var fn func(a1, a2, a3, a4, a5, a6, a7, a8, a9 int) int | |
| 55 | + | purego.RegisterFunc(&fn, cb) | |
| 56 | + | ||
| 57 | + | ret := fn(1, 2, 3, 4, 5, 6, 7, 8, 9) | |
| 58 | + | fmt.Println(ret) | |
| 59 | + | ||
| 60 | + | //Output: 1 2 3 4 5 6 7 8 9 | |
| 61 | + | // 45 | |
| 62 | + | } | |
| 63 | + | ||
| 64 | + | func Test_qsort(t *testing.T) { | |
| 65 | + | if runtime.GOOS == "linux" { | |
| 66 | + | // TODO: enable once callbacks are working properly on Linux | |
| 67 | + | t.SkipNow() | |
| 68 | + | } | |
| 69 | + | ||
| 70 | + | library, err := getSystemLibrary() | |
| 71 | + | if err != nil { | |
| 72 | + | t.Errorf("couldn't get system library: %s", err) | |
| 73 | + | } | |
| 74 | + | libc := purego.Dlopen(library, purego.RTLD_NOW|purego.RTLD_GLOBAL) | |
| 75 | + | if err := purego.Dlerror(); err != "" { | |
| 76 | + | t.Errorf("failed to dlopen: %s", err) | |
| 77 | + | } | |
| 78 | + | ||
| 79 | + | var data = []int{88, 56, 100, 2, 25} | |
| 80 | + | var sorted = []int{2, 25, 56, 88, 100} | |
| 81 | + | compare := func(a, b *int) int { | |
| 82 | + | return *a - *b | |
| 83 | + | } | |
| 84 | + | var qsort func(data []int, nitms uintptr, size uintptr, compar func(a, b *int) int) | |
| 85 | + | purego.RegisterLibFunc(&qsort, libc, "qsort") | |
| 86 | + | qsort(data, uintptr(len(data)), unsafe.Sizeof(int(0)), compare) | |
| 87 | + | for i := range data { | |
| 88 | + | if data[i] != sorted[i] { | |
| 89 | + | t.Errorf("got %d wanted %d at %d", data[i], sorted[i], i) | |
| 90 | + | } | |
| 91 | + | } | |
| 92 | + | } | |
| @@ -9,6 +9,7 @@ import ( | |||||
| 9 | "fmt" | 9 | "fmt" | ||
| 10 | "runtime" | 10 | "runtime" | ||
| 11 | "testing" | 11 | "testing" | ||
| 12 | + | "unsafe" | |||
| 12 | 13 | ||||
| 13 | "github.com/ebitengine/purego" | 14 | "github.com/ebitengine/purego" | ||
| 14 | ) | 15 | ) | ||
| @@ -37,3 +38,55 @@ func TestRegisterFunc(t *testing.T) { | |||||
| 37 | purego.RegisterLibFunc(&puts, libc, "puts") | 38 | purego.RegisterLibFunc(&puts, libc, "puts") | ||
| 38 | puts("Calling C from from Go without Cgo!") | 39 | puts("Calling C from from Go without Cgo!") | ||
| 39 | } | 40 | } | ||
| 41 | + | ||||
| 42 | + | func ExampleNewCallback() { | |||
| 43 | + | if runtime.GOOS == "linux" { | |||
| 44 | + | // TODO: enable once callbacks are working properly on Linux | |||
| 45 | + | fmt.Println("1 2 3 4 5 6 7 8 9\n45") | |||
| 46 | + | return | |||
| 47 | + | } | |||
| 48 | + | ||||
| 49 | + | cb := purego.NewCallback(func(a1, a2, a3, a4, a5, a6, a7, a8, a9 int) int { | |||
| 50 | + | fmt.Println(a1, a2, a3, a4, a5, a6, a7, a8, a9) | |||
| 51 | + | return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 | |||
| 52 | + | }) | |||
| 53 | + | ||||
| 54 | + | var fn func(a1, a2, a3, a4, a5, a6, a7, a8, a9 int) int | |||
| 55 | + | purego.RegisterFunc(&fn, cb) | |||
| 56 | + | ||||
| 57 | + | ret := fn(1, 2, 3, 4, 5, 6, 7, 8, 9) | |||
| 58 | + | fmt.Println(ret) | |||
| 59 | + | ||||
| 60 | + | //Output: 1 2 3 4 5 6 7 8 9 | |||
| 61 | + | // 45 | |||
| 62 | + | } | |||
| 63 | + | ||||
| 64 | + | func Test_qsort(t *testing.T) { | |||
| 65 | + | if runtime.GOOS == "linux" { | |||
| 66 | + | // TODO: enable once callbacks are working properly on Linux | |||
| 67 | + | t.SkipNow() | |||
| 68 | + | } | |||
| 69 | + | ||||
| 70 | + | library, err := getSystemLibrary() | |||
| 71 | + | if err != nil { | |||
| 72 | + | t.Errorf("couldn't get system library: %s", err) | |||
| 73 | + | } | |||
| 74 | + | libc := purego.Dlopen(library, purego.RTLD_NOW|purego.RTLD_GLOBAL) | |||
| 75 | + | if err := purego.Dlerror(); err != "" { | |||
| 76 | + | t.Errorf("failed to dlopen: %s", err) | |||
| 77 | + | } | |||
| 78 | + | ||||
| 79 | + | var data = []int{88, 56, 100, 2, 25} | |||
| 80 | + | var sorted = []int{2, 25, 56, 88, 100} | |||
| 81 | + | compare := func(a, b *int) int { | |||
| 82 | + | return *a - *b | |||
| 83 | + | } | |||
| 84 | + | var qsort func(data []int, nitms uintptr, size uintptr, compar func(a, b *int) int) | |||
| 85 | + | purego.RegisterLibFunc(&qsort, libc, "qsort") | |||
| 86 | + | qsort(data, uintptr(len(data)), unsafe.Sizeof(int(0)), compare) | |||
| 87 | + | for i := range data { | |||
| 88 | + | if data[i] != sorted[i] { | |||
| 89 | + | t.Errorf("got %d wanted %d at %d", data[i], sorted[i], i) | |||
| 90 | + | } | |||
| 91 | + | } | |||
| 92 | + | } | |||
M internal/cgo/syscall_cgo_linux.go +1 -3
| @@ -35,9 +35,7 @@ import "C" | |||
| 35 | 35 | import "unsafe" | |
| 36 | 36 | ||
| 37 | 37 | // assign purego.syscall9XABI0 to the C version of this function. | |
| 38 | - | // | |
| 39 | - | //go:linkname internal_syscall9XABI0 purego.syscall9XABI0 | |
| 40 | - | var internal_syscall9XABI0 = unsafe.Pointer(C.syscall9) | |
| 38 | + | var Syscall9XABI0 = unsafe.Pointer(C.syscall9) | |
| 41 | 39 | ||
| 42 | 40 | // all that is needed is to assign each dl function because then its | |
| 43 | 41 | // symbol will then be made available to the linker and linked to inside dlfcn.go | |
| @@ -35,9 +35,7 @@ import "C" | |||||
| 35 | import "unsafe" | 35 | import "unsafe" | ||
| 36 | 36 | ||||
| 37 | // assign purego.syscall9XABI0 to the C version of this function. | 37 | // assign purego.syscall9XABI0 to the C version of this function. | ||
| 38 | - | // | 38 | + | var Syscall9XABI0 = unsafe.Pointer(C.syscall9) |
| 39 | - | //go:linkname internal_syscall9XABI0 purego.syscall9XABI0 | |||
| 40 | - | var internal_syscall9XABI0 = unsafe.Pointer(C.syscall9) | |||
| 41 | 39 | ||||
| 42 | // all that is needed is to assign each dl function because then its | 40 | // all that is needed is to assign each dl function because then its | ||
| 43 | // symbol will then be made available to the linker and linked to inside dlfcn.go | 41 | // symbol will then be made available to the linker and linked to inside dlfcn.go | ||
R sys_darwin_amd64.s → sys_amd64.s +2 -0 renamed, 99% similar
| @@ -1,6 +1,8 @@ | |||
| 1 | 1 | // SPDX-License-Identifier: Apache-2.0 | |
| 2 | 2 | // SPDX-FileCopyrightText: 2022 The Ebitengine Authors | |
| 3 | 3 | ||
| 4 | + | //go:build darwin || (!cgo && linux) | |
| 5 | + | ||
| 4 | 6 | #include "textflag.h" | |
| 5 | 7 | #include "internal/abi/abi_amd64.h" | |
| 6 | 8 | #include "go_asm.h" | |
| @@ -1,6 +1,8 @@ | |||||
| 1 | // SPDX-License-Identifier: Apache-2.0 | 1 | // SPDX-License-Identifier: Apache-2.0 | ||
| 2 | // SPDX-FileCopyrightText: 2022 The Ebitengine Authors | 2 | // SPDX-FileCopyrightText: 2022 The Ebitengine Authors | ||
| 3 | 3 | ||||
| 4 | + | //go:build darwin || (!cgo && linux) | |||
| 5 | + | ||||
| 4 | #include "textflag.h" | 6 | #include "textflag.h" | ||
| 5 | #include "internal/abi/abi_amd64.h" | 7 | #include "internal/abi/abi_amd64.h" | ||
| 6 | #include "go_asm.h" | 8 | #include "go_asm.h" | ||
R sys_darwin_arm64.s → sys_arm64.s +2 -0 renamed, 98% similar
| @@ -1,6 +1,8 @@ | |||
| 1 | 1 | // SPDX-License-Identifier: Apache-2.0 | |
| 2 | 2 | // SPDX-FileCopyrightText: 2022 The Ebitengine Authors | |
| 3 | 3 | ||
| 4 | + | //go:build darwin || (!cgo && linux) | |
| 5 | + | ||
| 4 | 6 | #include "textflag.h" | |
| 5 | 7 | #include "go_asm.h" | |
| 6 | 8 | #include "funcdata.h" | |
| @@ -1,6 +1,8 @@ | |||||
| 1 | // SPDX-License-Identifier: Apache-2.0 | 1 | // SPDX-License-Identifier: Apache-2.0 | ||
| 2 | // SPDX-FileCopyrightText: 2022 The Ebitengine Authors | 2 | // SPDX-FileCopyrightText: 2022 The Ebitengine Authors | ||
| 3 | 3 | ||||
| 4 | + | //go:build darwin || (!cgo && linux) | |||
| 5 | + | ||||
| 4 | #include "textflag.h" | 6 | #include "textflag.h" | ||
| 5 | #include "go_asm.h" | 7 | #include "go_asm.h" | ||
| 6 | #include "funcdata.h" | 8 | #include "funcdata.h" | ||
D sys_linux_amd64.s +0 -70
| @@ -1,70 +0,0 @@ | |||
| 1 | - | // SPDX-License-Identifier: Apache-2.0 | |
| 2 | - | // SPDX-FileCopyrightText: 2022 The Ebitengine Authors | |
| 3 | - | ||
| 4 | - | #include "textflag.h" | |
| 5 | - | #include "go_asm.h" | |
| 6 | - | ||
| 7 | - | // syscall9X calls a function in libc on behalf of the syscall package. | |
| 8 | - | // syscall9X takes a pointer to a struct like: | |
| 9 | - | // struct { | |
| 10 | - | // fn uintptr | |
| 11 | - | // a1 uintptr | |
| 12 | - | // a2 uintptr | |
| 13 | - | // a3 uintptr | |
| 14 | - | // a4 uintptr | |
| 15 | - | // a5 uintptr | |
| 16 | - | // a6 uintptr | |
| 17 | - | // a7 uintptr | |
| 18 | - | // a8 uintptr | |
| 19 | - | // a9 uintptr | |
| 20 | - | // r1 uintptr | |
| 21 | - | // r2 uintptr | |
| 22 | - | // err uintptr | |
| 23 | - | // } | |
| 24 | - | // syscall9X must be called on the g0 stack with the | |
| 25 | - | // C calling convention (use libcCall). | |
| 26 | - | GLOBL ·syscall9XABI0(SB), NOPTR|RODATA, $8 | |
| 27 | - | DATA ·syscall9XABI0(SB)/8, $syscall9X(SB) | |
| 28 | - | TEXT syscall9X(SB), NOSPLIT, $0 | |
| 29 | - | PUSHQ BP | |
| 30 | - | MOVQ SP, BP | |
| 31 | - | SUBQ $32, SP | |
| 32 | - | MOVQ DI, 24(BP) // save the pointer | |
| 33 | - | ||
| 34 | - | MOVQ syscall9Args_f1(DI), X0 // f1 | |
| 35 | - | MOVQ syscall9Args_f2(DI), X1 // f2 | |
| 36 | - | MOVQ syscall9Args_f3(DI), X2 // f3 | |
| 37 | - | MOVQ syscall9Args_f4(DI), X3 // f4 | |
| 38 | - | MOVQ syscall9Args_f5(DI), X4 // f5 | |
| 39 | - | MOVQ syscall9Args_f6(DI), X5 // f6 | |
| 40 | - | MOVQ syscall9Args_f7(DI), X6 // f7 | |
| 41 | - | MOVQ syscall9Args_f8(DI), X7 // f8 | |
| 42 | - | ||
| 43 | - | MOVQ syscall9Args_fn(DI), R10 // fn | |
| 44 | - | MOVQ syscall9Args_a2(DI), SI // a2 | |
| 45 | - | MOVQ syscall9Args_a3(DI), DX // a3 | |
| 46 | - | MOVQ syscall9Args_a4(DI), CX // a4 | |
| 47 | - | MOVQ syscall9Args_a5(DI), R8 // a5 | |
| 48 | - | MOVQ syscall9Args_a6(DI), R9 // a6 | |
| 49 | - | MOVQ syscall9Args_a7(DI), R11 // a7 | |
| 50 | - | MOVQ syscall9Args_a8(DI), R12 // a8 | |
| 51 | - | MOVQ syscall9Args_a9(DI), R13 // a9 | |
| 52 | - | MOVQ syscall9Args_a1(DI), DI // a1 | |
| 53 | - | ||
| 54 | - | // push the remaining paramters onto the stack | |
| 55 | - | MOVQ R11, 0(SP) // push a7 | |
| 56 | - | MOVQ R12, 8(SP) // push a8 | |
| 57 | - | MOVQ R13, 16(SP) // push a9 | |
| 58 | - | XORL AX, AX // vararg: say "no float args" | |
| 59 | - | ||
| 60 | - | CALL R10 | |
| 61 | - | ||
| 62 | - | MOVQ 24(BP), DI // get the pointer back | |
| 63 | - | MOVQ AX, syscall9Args_r1(DI) // r1 | |
| 64 | - | MOVQ DX, syscall9Args_r2(DI) // r2 | |
| 65 | - | ||
| 66 | - | XORL AX, AX // no error (it's ignored anyway) | |
| 67 | - | ADDQ $32, SP | |
| 68 | - | MOVQ BP, SP | |
| 69 | - | POPQ BP | |
| 70 | - | RET | |
| @@ -1,70 +0,0 @@ | |||||
| 1 | - | // SPDX-License-Identifier: Apache-2.0 | |||
| 2 | - | // SPDX-FileCopyrightText: 2022 The Ebitengine Authors | |||
| 3 | - | ||||
| 4 | - | #include "textflag.h" | |||
| 5 | - | #include "go_asm.h" | |||
| 6 | - | ||||
| 7 | - | // syscall9X calls a function in libc on behalf of the syscall package. | |||
| 8 | - | // syscall9X takes a pointer to a struct like: | |||
| 9 | - | // struct { | |||
| 10 | - | // fn uintptr | |||
| 11 | - | // a1 uintptr | |||
| 12 | - | // a2 uintptr | |||
| 13 | - | // a3 uintptr | |||
| 14 | - | // a4 uintptr | |||
| 15 | - | // a5 uintptr | |||
| 16 | - | // a6 uintptr | |||
| 17 | - | // a7 uintptr | |||
| 18 | - | // a8 uintptr | |||
| 19 | - | // a9 uintptr | |||
| 20 | - | // r1 uintptr | |||
| 21 | - | // r2 uintptr | |||
| 22 | - | // err uintptr | |||
| 23 | - | // } | |||
| 24 | - | // syscall9X must be called on the g0 stack with the | |||
| 25 | - | // C calling convention (use libcCall). | |||
| 26 | - | GLOBL ·syscall9XABI0(SB), NOPTR|RODATA, $8 | |||
| 27 | - | DATA ·syscall9XABI0(SB)/8, $syscall9X(SB) | |||
| 28 | - | TEXT syscall9X(SB), NOSPLIT, $0 | |||
| 29 | - | PUSHQ BP | |||
| 30 | - | MOVQ SP, BP | |||
| 31 | - | SUBQ $32, SP | |||
| 32 | - | MOVQ DI, 24(BP) // save the pointer | |||
| 33 | - | ||||
| 34 | - | MOVQ syscall9Args_f1(DI), X0 // f1 | |||
| 35 | - | MOVQ syscall9Args_f2(DI), X1 // f2 | |||
| 36 | - | MOVQ syscall9Args_f3(DI), X2 // f3 | |||
| 37 | - | MOVQ syscall9Args_f4(DI), X3 // f4 | |||
| 38 | - | MOVQ syscall9Args_f5(DI), X4 // f5 | |||
| 39 | - | MOVQ syscall9Args_f6(DI), X5 // f6 | |||
| 40 | - | MOVQ syscall9Args_f7(DI), X6 // f7 | |||
| 41 | - | MOVQ syscall9Args_f8(DI), X7 // f8 | |||
| 42 | - | ||||
| 43 | - | MOVQ syscall9Args_fn(DI), R10 // fn | |||
| 44 | - | MOVQ syscall9Args_a2(DI), SI // a2 | |||
| 45 | - | MOVQ syscall9Args_a3(DI), DX // a3 | |||
| 46 | - | MOVQ syscall9Args_a4(DI), CX // a4 | |||
| 47 | - | MOVQ syscall9Args_a5(DI), R8 // a5 | |||
| 48 | - | MOVQ syscall9Args_a6(DI), R9 // a6 | |||
| 49 | - | MOVQ syscall9Args_a7(DI), R11 // a7 | |||
| 50 | - | MOVQ syscall9Args_a8(DI), R12 // a8 | |||
| 51 | - | MOVQ syscall9Args_a9(DI), R13 // a9 | |||
| 52 | - | MOVQ syscall9Args_a1(DI), DI // a1 | |||
| 53 | - | ||||
| 54 | - | // push the remaining paramters onto the stack | |||
| 55 | - | MOVQ R11, 0(SP) // push a7 | |||
| 56 | - | MOVQ R12, 8(SP) // push a8 | |||
| 57 | - | MOVQ R13, 16(SP) // push a9 | |||
| 58 | - | XORL AX, AX // vararg: say "no float args" | |||
| 59 | - | ||||
| 60 | - | CALL R10 | |||
| 61 | - | ||||
| 62 | - | MOVQ 24(BP), DI // get the pointer back | |||
| 63 | - | MOVQ AX, syscall9Args_r1(DI) // r1 | |||
| 64 | - | MOVQ DX, syscall9Args_r2(DI) // r2 | |||
| 65 | - | ||||
| 66 | - | XORL AX, AX // no error (it's ignored anyway) | |||
| 67 | - | ADDQ $32, SP | |||
| 68 | - | MOVQ BP, SP | |||
| 69 | - | POPQ BP | |||
| 70 | - | RET | |||
D sys_linux_arm64.s +0 -71
| @@ -1,71 +0,0 @@ | |||
| 1 | - | // SPDX-License-Identifier: Apache-2.0 | |
| 2 | - | // SPDX-FileCopyrightText: 2022 The Ebitengine Authors | |
| 3 | - | ||
| 4 | - | #include "textflag.h" | |
| 5 | - | #include "go_asm.h" | |
| 6 | - | ||
| 7 | - | // syscall9X calls a function in libc on behalf of the syscall package. | |
| 8 | - | // syscall9X takes a pointer to a struct like: | |
| 9 | - | // struct { | |
| 10 | - | // fn uintptr | |
| 11 | - | // a1 uintptr | |
| 12 | - | // a2 uintptr | |
| 13 | - | // a3 uintptr | |
| 14 | - | // a4 uintptr | |
| 15 | - | // a5 uintptr | |
| 16 | - | // a6 uintptr | |
| 17 | - | // a7 uintptr | |
| 18 | - | // a8 uintptr | |
| 19 | - | // a9 uintptr | |
| 20 | - | // r1 uintptr | |
| 21 | - | // r2 uintptr | |
| 22 | - | // err uintptr | |
| 23 | - | // } | |
| 24 | - | // syscall9X must be called on the g0 stack with the | |
| 25 | - | // C calling convention (use libcCall). | |
| 26 | - | GLOBL ·syscall9XABI0(SB), NOPTR|RODATA, $8 | |
| 27 | - | DATA ·syscall9XABI0(SB)/8, $syscall9X(SB) | |
| 28 | - | TEXT syscall9X(SB), NOSPLIT, $0 | |
| 29 | - | SUB $16, RSP // push structure pointer | |
| 30 | - | MOVD R0, 8(RSP) | |
| 31 | - | ||
| 32 | - | FMOVD syscall9Args_f1(R0), F0 // f1 | |
| 33 | - | FMOVD syscall9Args_f2(R0), F1 // f2 | |
| 34 | - | FMOVD syscall9Args_f3(R0), F2 // f3 | |
| 35 | - | FMOVD syscall9Args_f4(R0), F3 // f4 | |
| 36 | - | FMOVD syscall9Args_f5(R0), F4 // f5 | |
| 37 | - | FMOVD syscall9Args_f6(R0), F5 // f6 | |
| 38 | - | FMOVD syscall9Args_f7(R0), F6 // f7 | |
| 39 | - | FMOVD syscall9Args_f8(R0), F7 // f8 | |
| 40 | - | ||
| 41 | - | MOVD syscall9Args_fn(R0), R12 // fn | |
| 42 | - | MOVD syscall9Args_a2(R0), R1 // a2 | |
| 43 | - | MOVD syscall9Args_a3(R0), R2 // a3 | |
| 44 | - | MOVD syscall9Args_a4(R0), R3 // a4 | |
| 45 | - | MOVD syscall9Args_a5(R0), R4 // a5 | |
| 46 | - | MOVD syscall9Args_a6(R0), R5 // a6 | |
| 47 | - | MOVD syscall9Args_a7(R0), R6 // a7 | |
| 48 | - | MOVD syscall9Args_a8(R0), R7 // a8 | |
| 49 | - | MOVD syscall9Args_a9(R0), R8 // a9 | |
| 50 | - | MOVD syscall9Args_a1(R0), R0 // a1 | |
| 51 | - | ||
| 52 | - | // these may be float arguments | |
| 53 | - | // so we put them also where C expects floats | |
| 54 | - | FMOVD R0, F0 // a1 | |
| 55 | - | FMOVD R1, F1 // a2 | |
| 56 | - | FMOVD R2, F2 // a3 | |
| 57 | - | FMOVD R3, F3 // a4 | |
| 58 | - | FMOVD R4, F4 // a5 | |
| 59 | - | FMOVD R5, F5 // a6 | |
| 60 | - | FMOVD R6, F6 // a7 | |
| 61 | - | FMOVD R7, F7 // a8 | |
| 62 | - | ||
| 63 | - | MOVD R8, (RSP) // push a9 onto stack | |
| 64 | - | ||
| 65 | - | BL (R12) | |
| 66 | - | ||
| 67 | - | MOVD 8(RSP), R2 // pop structure pointer | |
| 68 | - | ADD $16, RSP | |
| 69 | - | MOVD R0, syscall9Args_r1(R2) // save r1 | |
| 70 | - | MOVD R1, syscall9Args_r2(R2) // save r2 | |
| 71 | - | RET | |
| @@ -1,71 +0,0 @@ | |||||
| 1 | - | // SPDX-License-Identifier: Apache-2.0 | |||
| 2 | - | // SPDX-FileCopyrightText: 2022 The Ebitengine Authors | |||
| 3 | - | ||||
| 4 | - | #include "textflag.h" | |||
| 5 | - | #include "go_asm.h" | |||
| 6 | - | ||||
| 7 | - | // syscall9X calls a function in libc on behalf of the syscall package. | |||
| 8 | - | // syscall9X takes a pointer to a struct like: | |||
| 9 | - | // struct { | |||
| 10 | - | // fn uintptr | |||
| 11 | - | // a1 uintptr | |||
| 12 | - | // a2 uintptr | |||
| 13 | - | // a3 uintptr | |||
| 14 | - | // a4 uintptr | |||
| 15 | - | // a5 uintptr | |||
| 16 | - | // a6 uintptr | |||
| 17 | - | // a7 uintptr | |||
| 18 | - | // a8 uintptr | |||
| 19 | - | // a9 uintptr | |||
| 20 | - | // r1 uintptr | |||
| 21 | - | // r2 uintptr | |||
| 22 | - | // err uintptr | |||
| 23 | - | // } | |||
| 24 | - | // syscall9X must be called on the g0 stack with the | |||
| 25 | - | // C calling convention (use libcCall). | |||
| 26 | - | GLOBL ·syscall9XABI0(SB), NOPTR|RODATA, $8 | |||
| 27 | - | DATA ·syscall9XABI0(SB)/8, $syscall9X(SB) | |||
| 28 | - | TEXT syscall9X(SB), NOSPLIT, $0 | |||
| 29 | - | SUB $16, RSP // push structure pointer | |||
| 30 | - | MOVD R0, 8(RSP) | |||
| 31 | - | ||||
| 32 | - | FMOVD syscall9Args_f1(R0), F0 // f1 | |||
| 33 | - | FMOVD syscall9Args_f2(R0), F1 // f2 | |||
| 34 | - | FMOVD syscall9Args_f3(R0), F2 // f3 | |||
| 35 | - | FMOVD syscall9Args_f4(R0), F3 // f4 | |||
| 36 | - | FMOVD syscall9Args_f5(R0), F4 // f5 | |||
| 37 | - | FMOVD syscall9Args_f6(R0), F5 // f6 | |||
| 38 | - | FMOVD syscall9Args_f7(R0), F6 // f7 | |||
| 39 | - | FMOVD syscall9Args_f8(R0), F7 // f8 | |||
| 40 | - | ||||
| 41 | - | MOVD syscall9Args_fn(R0), R12 // fn | |||
| 42 | - | MOVD syscall9Args_a2(R0), R1 // a2 | |||
| 43 | - | MOVD syscall9Args_a3(R0), R2 // a3 | |||
| 44 | - | MOVD syscall9Args_a4(R0), R3 // a4 | |||
| 45 | - | MOVD syscall9Args_a5(R0), R4 // a5 | |||
| 46 | - | MOVD syscall9Args_a6(R0), R5 // a6 | |||
| 47 | - | MOVD syscall9Args_a7(R0), R6 // a7 | |||
| 48 | - | MOVD syscall9Args_a8(R0), R7 // a8 | |||
| 49 | - | MOVD syscall9Args_a9(R0), R8 // a9 | |||
| 50 | - | MOVD syscall9Args_a1(R0), R0 // a1 | |||
| 51 | - | ||||
| 52 | - | // these may be float arguments | |||
| 53 | - | // so we put them also where C expects floats | |||
| 54 | - | FMOVD R0, F0 // a1 | |||
| 55 | - | FMOVD R1, F1 // a2 | |||
| 56 | - | FMOVD R2, F2 // a3 | |||
| 57 | - | FMOVD R3, F3 // a4 | |||
| 58 | - | FMOVD R4, F4 // a5 | |||
| 59 | - | FMOVD R5, F5 // a6 | |||
| 60 | - | FMOVD R6, F6 // a7 | |||
| 61 | - | FMOVD R7, F7 // a8 | |||
| 62 | - | ||||
| 63 | - | MOVD R8, (RSP) // push a9 onto stack | |||
| 64 | - | ||||
| 65 | - | BL (R12) | |||
| 66 | - | ||||
| 67 | - | MOVD 8(RSP), R2 // pop structure pointer | |||
| 68 | - | ADD $16, RSP | |||
| 69 | - | MOVD R0, syscall9Args_r1(R2) // save r1 | |||
| 70 | - | MOVD R1, syscall9Args_r2(R2) // save r2 | |||
| 71 | - | RET | |||
M syscall_cgo_linux.go +3 -2
| @@ -6,11 +6,12 @@ | |||
| 6 | 6 | package purego | |
| 7 | 7 | ||
| 8 | 8 | import ( | |
| 9 | + | _ "unsafe" // for go:linkname | |
| 10 | + | ||
| 9 | 11 | "github.com/ebitengine/purego/internal/cgo" | |
| 10 | 12 | ) | |
| 11 | 13 | ||
| 12 | - | // this is linked to a C function from internal/cgo | |
| 13 | - | var syscall9XABI0 uintptr | |
| 14 | + | var syscall9XABI0 = uintptr(cgo.Syscall9XABI0) | |
| 14 | 15 | ||
| 15 | 16 | // this is only here to make the assembly files happy :) | |
| 16 | 17 | type syscall9Args struct { | |
| @@ -6,11 +6,12 @@ | |||||
| 6 | package purego | 6 | package purego | ||
| 7 | 7 | ||||
| 8 | import ( | 8 | import ( | ||
| 9 | + | _ "unsafe" // for go:linkname | |||
| 10 | + | ||||
| 9 | "github.com/ebitengine/purego/internal/cgo" | 11 | "github.com/ebitengine/purego/internal/cgo" | ||
| 10 | ) | 12 | ) | ||
| 11 | 13 | ||||
| 12 | - | // this is linked to a C function from internal/cgo | 14 | + | var syscall9XABI0 = uintptr(cgo.Syscall9XABI0) |
| 13 | - | var syscall9XABI0 uintptr | |||
| 14 | 15 | ||||
| 15 | // this is only here to make the assembly files happy :) | 16 | // this is only here to make the assembly files happy :) | ||
| 16 | type syscall9Args struct { | 17 | type syscall9Args struct { | ||
D syscall_nocgo_linux.go +0 -34
| @@ -1,34 +0,0 @@ | |||
| 1 | - | // SPDX-License-Identifier: Apache-2.0 | |
| 2 | - | // SPDX-FileCopyrightText: 2022 The Ebitengine Authors | |
| 3 | - | ||
| 4 | - | //go:build !cgo && (amd64 || arm64) | |
| 5 | - | ||
| 6 | - | package purego | |
| 7 | - | ||
| 8 | - | import ( | |
| 9 | - | "math" | |
| 10 | - | "unsafe" | |
| 11 | - | ) | |
| 12 | - | ||
| 13 | - | var syscall9XABI0 uintptr | |
| 14 | - | ||
| 15 | - | type syscall9Args struct { | |
| 16 | - | fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr | |
| 17 | - | f1, f2, f3, f4, f5, f6, f7, f8 float64 | |
| 18 | - | r1, r2, err uintptr | |
| 19 | - | } | |
| 20 | - | ||
| 21 | - | //go:nosplit | |
| 22 | - | func syscall_syscall9X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) { | |
| 23 | - | args := syscall9Args{fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, | |
| 24 | - | math.Float64frombits(uint64(a1)), math.Float64frombits(uint64(a2)), math.Float64frombits(uint64(a3)), | |
| 25 | - | math.Float64frombits(uint64(a4)), math.Float64frombits(uint64(a5)), math.Float64frombits(uint64(a6)), | |
| 26 | - | math.Float64frombits(uint64(a7)), math.Float64frombits(uint64(a8)), | |
| 27 | - | r1, r2, err} | |
| 28 | - | runtime_cgocall(syscall9XABI0, unsafe.Pointer(&args)) | |
| 29 | - | return args.r1, args.r2, args.err | |
| 30 | - | } | |
| 31 | - | ||
| 32 | - | func NewCallback(_ interface{}) uintptr { | |
| 33 | - | panic("purego: NewCallback not supported") | |
| 34 | - | } | |
| @@ -1,34 +0,0 @@ | |||||
| 1 | - | // SPDX-License-Identifier: Apache-2.0 | |||
| 2 | - | // SPDX-FileCopyrightText: 2022 The Ebitengine Authors | |||
| 3 | - | ||||
| 4 | - | //go:build !cgo && (amd64 || arm64) | |||
| 5 | - | ||||
| 6 | - | package purego | |||
| 7 | - | ||||
| 8 | - | import ( | |||
| 9 | - | "math" | |||
| 10 | - | "unsafe" | |||
| 11 | - | ) | |||
| 12 | - | ||||
| 13 | - | var syscall9XABI0 uintptr | |||
| 14 | - | ||||
| 15 | - | type syscall9Args struct { | |||
| 16 | - | fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr | |||
| 17 | - | f1, f2, f3, f4, f5, f6, f7, f8 float64 | |||
| 18 | - | r1, r2, err uintptr | |||
| 19 | - | } | |||
| 20 | - | ||||
| 21 | - | //go:nosplit | |||
| 22 | - | func syscall_syscall9X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) { | |||
| 23 | - | args := syscall9Args{fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, | |||
| 24 | - | math.Float64frombits(uint64(a1)), math.Float64frombits(uint64(a2)), math.Float64frombits(uint64(a3)), | |||
| 25 | - | math.Float64frombits(uint64(a4)), math.Float64frombits(uint64(a5)), math.Float64frombits(uint64(a6)), | |||
| 26 | - | math.Float64frombits(uint64(a7)), math.Float64frombits(uint64(a8)), | |||
| 27 | - | r1, r2, err} | |||
| 28 | - | runtime_cgocall(syscall9XABI0, unsafe.Pointer(&args)) | |||
| 29 | - | return args.r1, args.r2, args.err | |||
| 30 | - | } | |||
| 31 | - | ||||
| 32 | - | func NewCallback(_ interface{}) uintptr { | |||
| 33 | - | panic("purego: NewCallback not supported") | |||
| 34 | - | } | |||
R syscall_darwin.go → syscall_sysv.go +7 -0 renamed, 96% similar
| @@ -1,6 +1,8 @@ | |||
| 1 | 1 | // SPDX-License-Identifier: Apache-2.0 | |
| 2 | 2 | // SPDX-FileCopyrightText: 2022 The Ebitengine Authors | |
| 3 | 3 | ||
| 4 | + | //go:build darwin || (!cgo && linux && (amd64 || arm64)) | |
| 5 | + | ||
| 4 | 6 | package purego | |
| 5 | 7 | ||
| 6 | 8 | import ( | |
| @@ -36,7 +38,12 @@ func syscall_syscall9X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, | |||
| 36 | 38 | // of uintptr. Only a limited number of callbacks may be created in a single Go process, and any memory allocated | |
| 37 | 39 | // for these callbacks is never released. At least 2000 callbacks can always be created. Although this function | |
| 38 | 40 | // provides similar functionality to windows.NewCallback it is distinct. | |
| 41 | + | // | |
| 42 | + | // NOTE: Linux is currently not supported and will panic if called. | |
| 39 | 43 | func NewCallback(fn interface{}) uintptr { | |
| 44 | + | if runtime.GOOS == "linux" { | |
| 45 | + | panic("purego: NewCallback not supported") | |
| 46 | + | } | |
| 40 | 47 | return compileCallback(fn) | |
| 41 | 48 | } | |
| 42 | 49 | ||
| @@ -1,6 +1,8 @@ | |||||
| 1 | // SPDX-License-Identifier: Apache-2.0 | 1 | // SPDX-License-Identifier: Apache-2.0 | ||
| 2 | // SPDX-FileCopyrightText: 2022 The Ebitengine Authors | 2 | // SPDX-FileCopyrightText: 2022 The Ebitengine Authors | ||
| 3 | 3 | ||||
| 4 | + | //go:build darwin || (!cgo && linux && (amd64 || arm64)) | |||
| 5 | + | ||||
| 4 | package purego | 6 | package purego | ||
| 5 | 7 | ||||
| 6 | import ( | 8 | import ( | ||
| @@ -36,7 +38,12 @@ func syscall_syscall9X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, | |||||
| 36 | // of uintptr. Only a limited number of callbacks may be created in a single Go process, and any memory allocated | 38 | // of uintptr. Only a limited number of callbacks may be created in a single Go process, and any memory allocated | ||
| 37 | // for these callbacks is never released. At least 2000 callbacks can always be created. Although this function | 39 | // for these callbacks is never released. At least 2000 callbacks can always be created. Although this function | ||
| 38 | // provides similar functionality to windows.NewCallback it is distinct. | 40 | // provides similar functionality to windows.NewCallback it is distinct. | ||
| 41 | + | // | |||
| 42 | + | // NOTE: Linux is currently not supported and will panic if called. | |||
| 39 | func NewCallback(fn interface{}) uintptr { | 43 | func NewCallback(fn interface{}) uintptr { | ||
| 44 | + | if runtime.GOOS == "linux" { | |||
| 45 | + | panic("purego: NewCallback not supported") | |||
| 46 | + | } | |||
| 40 | return compileCallback(fn) | 47 | return compileCallback(fn) | ||
| 41 | } | 48 | } | ||
| 42 | 49 | ||||
R zcallback_darwin_amd64.s → zcallback_amd64.s +2 -0 renamed, 99% similar
| @@ -1,5 +1,7 @@ | |||
| 1 | 1 | // Code generated by wincallback.go using 'go generate'. DO NOT EDIT. | |
| 2 | 2 | ||
| 3 | + | //go:build darwin || (!cgo && linux) | |
| 4 | + | ||
| 3 | 5 | // runtime·callbackasm is called by external code to | |
| 4 | 6 | // execute Go implemented callback function. It is not | |
| 5 | 7 | // called from the start, instead runtime·compilecallback | |
| @@ -1,5 +1,7 @@ | |||||
| 1 | // Code generated by wincallback.go using 'go generate'. DO NOT EDIT. | 1 | // Code generated by wincallback.go using 'go generate'. DO NOT EDIT. | ||
| 2 | 2 | ||||
| 3 | + | //go:build darwin || (!cgo && linux) | |||
| 4 | + | ||||
| 3 | // runtime·callbackasm is called by external code to | 5 | // runtime·callbackasm is called by external code to | ||
| 4 | // execute Go implemented callback function. It is not | 6 | // execute Go implemented callback function. It is not | ||
| 5 | // called from the start, instead runtime·compilecallback | 7 | // called from the start, instead runtime·compilecallback | ||
R zcallback_darwin_arm64.s → zcallback_arm64.s +2 -0 renamed, 99% similar
| @@ -1,5 +1,7 @@ | |||
| 1 | 1 | // Code generated by wincallback.go using 'go generate'. DO NOT EDIT. | |
| 2 | 2 | ||
| 3 | + | //go:build darwin || (!cgo && linux) | |
| 4 | + | ||
| 3 | 5 | // External code calls into callbackasm at an offset corresponding | |
| 4 | 6 | // to the callback index. Callbackasm is a table of MOV and B instructions. | |
| 5 | 7 | // The MOV instruction loads R12 with the callback index, and the | |
| @@ -1,5 +1,7 @@ | |||||
| 1 | // Code generated by wincallback.go using 'go generate'. DO NOT EDIT. | 1 | // Code generated by wincallback.go using 'go generate'. DO NOT EDIT. | ||
| 2 | 2 | ||||
| 3 | + | //go:build darwin || (!cgo && linux) | |||
| 4 | + | ||||
| 3 | // External code calls into callbackasm at an offset corresponding | 5 | // External code calls into callbackasm at an offset corresponding | ||
| 4 | // to the callback index. Callbackasm is a table of MOV and B instructions. | 6 | // to the callback index. Callbackasm is a table of MOV and B instructions. | ||
| 5 | // The MOV instruction loads R12 with the callback index, and the | 7 | // The MOV instruction loads R12 with the callback index, and the | ||