purego: cleanup (#10)
* remove unused forward declarations * check if fn is nil in SyscallN * rename runtime.go to go_runtime.go * use go offsets in assembly * avoid copying null terminated string * runtime_libcCall now takes fn as uintptr * format assembly with asmfmt * make README.md useful * separate dl files into os and non-os dependent parts * remove call to non-portable libc_error (__error)
- commit
- 0a7163731eabf0571fdba41d6b8c3e27adfec5b1
- author
- TotallyGamerJet · · 2022-06-29 14:38 UTC
- committer
- GitHub · · 2022-06-29 14:38 UTC
- parent
- 08db4d0
- signature
- GPG Unverified
4AEE18F83AFDEB23The key is unknown
9 files · +63 -75
M README.md +4 -0
| @@ -0,0 +1,4 @@ | |||
| 1 | + | # purego | |
| 2 | + | [](https://pkg.go.dev/github.com/ebitengine/purego?GOOS=darwin) | |
| 3 | + | ||
| 4 | + | A library for calling C functions from Go without Cgo. | |
| @@ -0,0 +1,4 @@ | |||||
| 1 | + | # purego | |||
| 2 | + | [](https://pkg.go.dev/github.com/ebitengine/purego?GOOS=darwin) | |||
| 3 | + | ||||
| 4 | + | A library for calling C functions from Go without Cgo. | |||
R dl_darwin.go → dlfcn.go +5 -9 renamed, 78% similar
| @@ -1,6 +1,9 @@ | |||
| 1 | 1 | // SPDX-License-Identifier: Apache-2.0 | |
| 2 | 2 | // SPDX-FileCopyrightText: 2022 The Ebiten Authors | |
| 3 | 3 | ||
| 4 | + | //go:build darwin | |
| 5 | + | // +build darwin | |
| 6 | + | ||
| 4 | 7 | package purego | |
| 5 | 8 | ||
| 6 | 9 | import ( | |
| @@ -19,7 +22,7 @@ func hasSuffix(s, suffix string) bool { | |||
| 19 | 22 | ||
| 20 | 23 | func cString(name string) *byte { | |
| 21 | 24 | if hasSuffix(name, "\x00") { | |
| 22 | - | return &[]byte(name)[0] | |
| 25 | + | return &(*(*[]byte)(unsafe.Pointer(&name)))[0] | |
| 23 | 26 | } | |
| 24 | 27 | var b = make([]byte, len(name)+1) | |
| 25 | 28 | copy(b, name) | |
| @@ -40,13 +43,6 @@ func Dlsym(handle uintptr, name string) uintptr { | |||
| 40 | 43 | return ret | |
| 41 | 44 | } | |
| 42 | 45 | ||
| 43 | - | //go:cgo_import_dynamic _dlopen dlopen "/usr/lib/libSystem.B.dylib" | |
| 44 | - | //go:cgo_import_dynamic _dlsym dlsym "/usr/lib/libSystem.B.dylib" | |
| 45 | - | ||
| 46 | + | // these functions exist in dlfcn_stubs.s and are calling C functions linked to in dlfcn_GOOS.go | |
| 46 | 47 | var dlopenABI0 uintptr | |
| 47 | - | ||
| 48 | - | func dlopen() // implemented in assembly | |
| 49 | - | ||
| 50 | 48 | var dlsymABI0 uintptr | |
| 51 | - | ||
| 52 | - | func dlsym() // implemented in assembly | |
| @@ -1,6 +1,9 @@ | |||||
| 1 | // SPDX-License-Identifier: Apache-2.0 | 1 | // SPDX-License-Identifier: Apache-2.0 | ||
| 2 | // SPDX-FileCopyrightText: 2022 The Ebiten Authors | 2 | // SPDX-FileCopyrightText: 2022 The Ebiten Authors | ||
| 3 | 3 | ||||
| 4 | + | //go:build darwin | |||
| 5 | + | // +build darwin | |||
| 6 | + | ||||
| 4 | package purego | 7 | package purego | ||
| 5 | 8 | ||||
| 6 | import ( | 9 | import ( | ||
| @@ -19,7 +22,7 @@ func hasSuffix(s, suffix string) bool { | |||||
| 19 | 22 | ||||
| 20 | func cString(name string) *byte { | 23 | func cString(name string) *byte { | ||
| 21 | if hasSuffix(name, "\x00") { | 24 | if hasSuffix(name, "\x00") { | ||
| 22 | - | return &[]byte(name)[0] | 25 | + | return &(*(*[]byte)(unsafe.Pointer(&name)))[0] |
| 23 | } | 26 | } | ||
| 24 | var b = make([]byte, len(name)+1) | 27 | var b = make([]byte, len(name)+1) | ||
| 25 | copy(b, name) | 28 | copy(b, name) | ||
| @@ -40,13 +43,6 @@ func Dlsym(handle uintptr, name string) uintptr { | |||||
| 40 | return ret | 43 | return ret | ||
| 41 | } | 44 | } | ||
| 42 | 45 | ||||
| 43 | - | //go:cgo_import_dynamic _dlopen dlopen "/usr/lib/libSystem.B.dylib" | 46 | + | // these functions exist in dlfcn_stubs.s and are calling C functions linked to in dlfcn_GOOS.go |
| 44 | - | //go:cgo_import_dynamic _dlsym dlsym "/usr/lib/libSystem.B.dylib" | |||
| 45 | - | ||||
| 46 | var dlopenABI0 uintptr | 47 | var dlopenABI0 uintptr | ||
| 47 | - | ||||
| 48 | - | func dlopen() // implemented in assembly | |||
| 49 | - | ||||
| 50 | var dlsymABI0 uintptr | 48 | var dlsymABI0 uintptr | ||
| 51 | - | ||||
| 52 | - | func dlsym() // implemented in assembly | |||
A dlfcn_darwin.go +7 -0
| @@ -0,0 +1,7 @@ | |||
| 1 | + | // SPDX-License-Identifier: Apache-2.0 | |
| 2 | + | // SPDX-FileCopyrightText: 2022 The Ebiten Authors | |
| 3 | + | ||
| 4 | + | package purego | |
| 5 | + | ||
| 6 | + | //go:cgo_import_dynamic _dlopen dlopen "/usr/lib/libSystem.B.dylib" | |
| 7 | + | //go:cgo_import_dynamic _dlsym dlsym "/usr/lib/libSystem.B.dylib" | |
| @@ -0,0 +1,7 @@ | |||||
| 1 | + | // SPDX-License-Identifier: Apache-2.0 | |||
| 2 | + | // SPDX-FileCopyrightText: 2022 The Ebiten Authors | |||
| 3 | + | ||||
| 4 | + | package purego | |||
| 5 | + | ||||
| 6 | + | //go:cgo_import_dynamic _dlopen dlopen "/usr/lib/libSystem.B.dylib" | |||
| 7 | + | //go:cgo_import_dynamic _dlsym dlsym "/usr/lib/libSystem.B.dylib" | |||
R stubs.s → dlfcn_stubs.s +4 -4 renamed, 73% similar
| @@ -8,15 +8,15 @@ | |||
| 8 | 8 | ||
| 9 | 9 | // func dlopen(path *byte, mode int) (ret uintptr) | |
| 10 | 10 | GLOBL ·dlopenABI0(SB), NOPTR|RODATA, $8 | |
| 11 | - | DATA ·dlopenABI0(SB)/8, $·dlopen(SB) | |
| 12 | - | TEXT ·dlopen(SB), NOSPLIT, $0-0 | |
| 11 | + | DATA ·dlopenABI0(SB)/8, $dlopen(SB) | |
| 12 | + | TEXT dlopen(SB), NOSPLIT, $0-0 | |
| 13 | 13 | JMP _dlopen(SB) | |
| 14 | 14 | RET | |
| 15 | 15 | ||
| 16 | 16 | // func dlsym(handle uintptr, symbol *byte) (ret uintptr) | |
| 17 | 17 | GLOBL ·dlsymABI0(SB), NOPTR|RODATA, $8 | |
| 18 | - | DATA ·dlsymABI0(SB)/8, $·dlsym(SB) | |
| 19 | - | TEXT ·dlsym(SB), NOSPLIT, $0-0 | |
| 18 | + | DATA ·dlsymABI0(SB)/8, $dlsym(SB) | |
| 19 | + | TEXT dlsym(SB), NOSPLIT, $0-0 | |
| 20 | 20 | JMP _dlsym(SB) | |
| 21 | 21 | RET | |
| 22 | 22 | ||
| @@ -8,15 +8,15 @@ | |||||
| 8 | 8 | ||||
| 9 | // func dlopen(path *byte, mode int) (ret uintptr) | 9 | // func dlopen(path *byte, mode int) (ret uintptr) | ||
| 10 | GLOBL ·dlopenABI0(SB), NOPTR|RODATA, $8 | 10 | GLOBL ·dlopenABI0(SB), NOPTR|RODATA, $8 | ||
| 11 | - | DATA ·dlopenABI0(SB)/8, $·dlopen(SB) | 11 | + | DATA ·dlopenABI0(SB)/8, $dlopen(SB) |
| 12 | - | TEXT ·dlopen(SB), NOSPLIT, $0-0 | 12 | + | TEXT dlopen(SB), NOSPLIT, $0-0 |
| 13 | JMP _dlopen(SB) | 13 | JMP _dlopen(SB) | ||
| 14 | RET | 14 | RET | ||
| 15 | 15 | ||||
| 16 | // func dlsym(handle uintptr, symbol *byte) (ret uintptr) | 16 | // func dlsym(handle uintptr, symbol *byte) (ret uintptr) | ||
| 17 | GLOBL ·dlsymABI0(SB), NOPTR|RODATA, $8 | 17 | GLOBL ·dlsymABI0(SB), NOPTR|RODATA, $8 | ||
| 18 | - | DATA ·dlsymABI0(SB)/8, $·dlsym(SB) | 18 | + | DATA ·dlsymABI0(SB)/8, $dlsym(SB) |
| 19 | - | TEXT ·dlsym(SB), NOSPLIT, $0-0 | 19 | + | TEXT dlsym(SB), NOSPLIT, $0-0 |
| 20 | JMP _dlsym(SB) | 20 | JMP _dlsym(SB) | ||
| 21 | RET | 21 | RET | ||
| 22 | 22 | ||||
R runtime.go → go_runtime.go +3 -3 renamed, 55% similar
| @@ -13,6 +13,6 @@ import ( | |||
| 13 | 13 | //go:linkname runtime_libcCall runtime.libcCall | |
| 14 | 14 | //go:linkname runtime_entersyscall runtime.entersyscall | |
| 15 | 15 | //go:linkname runtime_exitsyscall runtime.exitsyscall | |
| 16 | - | func runtime_libcCall(fn, arg unsafe.Pointer) int32 // from runtime/sys_libc.go | |
| 17 | - | func runtime_entersyscall() // from runtime/proc.go | |
| 18 | - | func runtime_exitsyscall() // from runtime/proc.go | |
| 16 | + | func runtime_libcCall(fn uintptr, arg unsafe.Pointer) int32 // from runtime/sys_libc.go | |
| 17 | + | func runtime_entersyscall() // from runtime/proc.go | |
| 18 | + | func runtime_exitsyscall() // from runtime/proc.go | |
| @@ -13,6 +13,6 @@ import ( | |||||
| 13 | //go:linkname runtime_libcCall runtime.libcCall | 13 | //go:linkname runtime_libcCall runtime.libcCall | ||
| 14 | //go:linkname runtime_entersyscall runtime.entersyscall | 14 | //go:linkname runtime_entersyscall runtime.entersyscall | ||
| 15 | //go:linkname runtime_exitsyscall runtime.exitsyscall | 15 | //go:linkname runtime_exitsyscall runtime.exitsyscall | ||
| 16 | - | func runtime_libcCall(fn, arg unsafe.Pointer) int32 // from runtime/sys_libc.go | 16 | + | func runtime_libcCall(fn uintptr, arg unsafe.Pointer) int32 // from runtime/sys_libc.go |
| 17 | - | func runtime_entersyscall() // from runtime/proc.go | 17 | + | func runtime_entersyscall() // from runtime/proc.go |
| 18 | - | func runtime_exitsyscall() // from runtime/proc.go | 18 | + | func runtime_exitsyscall() // from runtime/proc.go |
M sys_darwin_amd64.s +17 -28
| @@ -2,6 +2,7 @@ | |||
| 2 | 2 | // SPDX-FileCopyrightText: 2022 The Ebiten Authors | |
| 3 | 3 | ||
| 4 | 4 | #include "textflag.h" | |
| 5 | + | #include "go_asm.h" | |
| 5 | 6 | ||
| 6 | 7 | // syscall9X calls a function in libc on behalf of the syscall package. | |
| 7 | 8 | // syscall9X takes a pointer to a struct like: | |
| @@ -23,22 +24,22 @@ | |||
| 23 | 24 | // syscall9X must be called on the g0 stack with the | |
| 24 | 25 | // C calling convention (use libcCall). | |
| 25 | 26 | GLOBL ·syscall9XABI0(SB), NOPTR|RODATA, $8 | |
| 26 | - | DATA ·syscall9XABI0(SB)/8, $·syscall9X(SB) | |
| 27 | - | TEXT ·syscall9X(SB), NOSPLIT, $0 | |
| 27 | + | DATA ·syscall9XABI0(SB)/8, $syscall9X(SB) | |
| 28 | + | TEXT syscall9X(SB), NOSPLIT, $0 | |
| 28 | 29 | PUSHQ BP | |
| 29 | 30 | MOVQ SP, BP | |
| 30 | 31 | SUBQ $32, SP | |
| 31 | - | MOVQ DI, 24(BP) // save the pointer | |
| 32 | - | MOVQ (0*8)(DI), R10 // fn | |
| 33 | - | MOVQ (2*8)(DI), SI // a2 | |
| 34 | - | MOVQ (3*8)(DI), DX // a3 | |
| 35 | - | MOVQ (4*8)(DI), CX // a4 | |
| 36 | - | MOVQ (5*8)(DI), R8 // a5 | |
| 37 | - | MOVQ (6*8)(DI), R9 // a6 | |
| 38 | - | MOVQ (7*8)(DI), R11 // a7 | |
| 39 | - | MOVQ (8*8)(DI), R12 // a8 | |
| 40 | - | MOVQ (9*8)(DI), R13 // a9 | |
| 41 | - | MOVQ (1*8)(DI), DI // a1 | |
| 32 | + | MOVQ DI, 24(BP) // save the pointer | |
| 33 | + | MOVQ syscall9Args_fn(DI), R10 // fn | |
| 34 | + | MOVQ syscall9Args_a2(DI), SI // a2 | |
| 35 | + | MOVQ syscall9Args_a3(DI), DX // a3 | |
| 36 | + | MOVQ syscall9Args_a4(DI), CX // a4 | |
| 37 | + | MOVQ syscall9Args_a5(DI), R8 // a5 | |
| 38 | + | MOVQ syscall9Args_a6(DI), R9 // a6 | |
| 39 | + | MOVQ syscall9Args_a7(DI), R11 // a7 | |
| 40 | + | MOVQ syscall9Args_a8(DI), R12 // a8 | |
| 41 | + | MOVQ syscall9Args_a9(DI), R13 // a9 | |
| 42 | + | MOVQ syscall9Args_a1(DI), DI // a1 | |
| 42 | 43 | ||
| 43 | 44 | // these may be float arguments | |
| 44 | 45 | // so we put them also where C expects floats | |
| @@ -59,22 +60,10 @@ TEXT ·syscall9X(SB), NOSPLIT, $0 | |||
| 59 | 60 | ||
| 60 | 61 | CALL R10 | |
| 61 | 62 | ||
| 62 | - | MOVQ 24(BP), DI // get the pointer back | |
| 63 | - | MOVQ AX, (10*8)(DI) // r1 | |
| 64 | - | MOVQ DX, (11*8)(DI) // r2 | |
| 63 | + | MOVQ 24(BP), DI // get the pointer back | |
| 64 | + | MOVQ AX, syscall9Args_r1(DI) // r1 | |
| 65 | + | MOVQ DX, syscall9Args_r2(DI) // r2 | |
| 65 | 66 | ||
| 66 | - | // Standard libc functions return -1 on error | |
| 67 | - | // and set errno. | |
| 68 | - | CMPQ AX, $-1 | |
| 69 | - | JNE ok | |
| 70 | - | ||
| 71 | - | // Get error code from libc. | |
| 72 | - | CALL libc_error(SB) | |
| 73 | - | MOVLQSX (AX), AX | |
| 74 | - | MOVQ (SP), DI | |
| 75 | - | MOVQ AX, (12*8)(DI) // err | |
| 76 | - | ||
| 77 | - | ok: | |
| 78 | 67 | XORL AX, AX // no error (it's ignored anyway) | |
| 79 | 68 | ADDQ $32, SP | |
| 80 | 69 | MOVQ BP, SP | |
| @@ -2,6 +2,7 @@ | |||||
| 2 | // SPDX-FileCopyrightText: 2022 The Ebiten Authors | 2 | // SPDX-FileCopyrightText: 2022 The Ebiten Authors | ||
| 3 | 3 | ||||
| 4 | #include "textflag.h" | 4 | #include "textflag.h" | ||
| 5 | + | #include "go_asm.h" | |||
| 5 | 6 | ||||
| 6 | // syscall9X calls a function in libc on behalf of the syscall package. | 7 | // syscall9X calls a function in libc on behalf of the syscall package. | ||
| 7 | // syscall9X takes a pointer to a struct like: | 8 | // syscall9X takes a pointer to a struct like: | ||
| @@ -23,22 +24,22 @@ | |||||
| 23 | // syscall9X must be called on the g0 stack with the | 24 | // syscall9X must be called on the g0 stack with the | ||
| 24 | // C calling convention (use libcCall). | 25 | // C calling convention (use libcCall). | ||
| 25 | GLOBL ·syscall9XABI0(SB), NOPTR|RODATA, $8 | 26 | GLOBL ·syscall9XABI0(SB), NOPTR|RODATA, $8 | ||
| 26 | - | DATA ·syscall9XABI0(SB)/8, $·syscall9X(SB) | 27 | + | DATA ·syscall9XABI0(SB)/8, $syscall9X(SB) |
| 27 | - | TEXT ·syscall9X(SB), NOSPLIT, $0 | 28 | + | TEXT syscall9X(SB), NOSPLIT, $0 |
| 28 | PUSHQ BP | 29 | PUSHQ BP | ||
| 29 | MOVQ SP, BP | 30 | MOVQ SP, BP | ||
| 30 | SUBQ $32, SP | 31 | SUBQ $32, SP | ||
| 31 | - | MOVQ DI, 24(BP) // save the pointer | 32 | + | MOVQ DI, 24(BP) // save the pointer |
| 32 | - | MOVQ (0*8)(DI), R10 // fn | 33 | + | MOVQ syscall9Args_fn(DI), R10 // fn |
| 33 | - | MOVQ (2*8)(DI), SI // a2 | 34 | + | MOVQ syscall9Args_a2(DI), SI // a2 |
| 34 | - | MOVQ (3*8)(DI), DX // a3 | 35 | + | MOVQ syscall9Args_a3(DI), DX // a3 |
| 35 | - | MOVQ (4*8)(DI), CX // a4 | 36 | + | MOVQ syscall9Args_a4(DI), CX // a4 |
| 36 | - | MOVQ (5*8)(DI), R8 // a5 | 37 | + | MOVQ syscall9Args_a5(DI), R8 // a5 |
| 37 | - | MOVQ (6*8)(DI), R9 // a6 | 38 | + | MOVQ syscall9Args_a6(DI), R9 // a6 |
| 38 | - | MOVQ (7*8)(DI), R11 // a7 | 39 | + | MOVQ syscall9Args_a7(DI), R11 // a7 |
| 39 | - | MOVQ (8*8)(DI), R12 // a8 | 40 | + | MOVQ syscall9Args_a8(DI), R12 // a8 |
| 40 | - | MOVQ (9*8)(DI), R13 // a9 | 41 | + | MOVQ syscall9Args_a9(DI), R13 // a9 |
| 41 | - | MOVQ (1*8)(DI), DI // a1 | 42 | + | MOVQ syscall9Args_a1(DI), DI // a1 |
| 42 | 43 | ||||
| 43 | // these may be float arguments | 44 | // these may be float arguments | ||
| 44 | // so we put them also where C expects floats | 45 | // so we put them also where C expects floats | ||
| @@ -59,22 +60,10 @@ TEXT ·syscall9X(SB), NOSPLIT, $0 | |||||
| 59 | 60 | ||||
| 60 | CALL R10 | 61 | CALL R10 | ||
| 61 | 62 | ||||
| 62 | - | MOVQ 24(BP), DI // get the pointer back | 63 | + | MOVQ 24(BP), DI // get the pointer back |
| 63 | - | MOVQ AX, (10*8)(DI) // r1 | 64 | + | MOVQ AX, syscall9Args_r1(DI) // r1 |
| 64 | - | MOVQ DX, (11*8)(DI) // r2 | 65 | + | MOVQ DX, syscall9Args_r2(DI) // r2 |
| 65 | 66 | ||||
| 66 | - | // Standard libc functions return -1 on error | |||
| 67 | - | // and set errno. | |||
| 68 | - | CMPQ AX, $-1 | |||
| 69 | - | JNE ok | |||
| 70 | - | ||||
| 71 | - | // Get error code from libc. | |||
| 72 | - | CALL libc_error(SB) | |||
| 73 | - | MOVLQSX (AX), AX | |||
| 74 | - | MOVQ (SP), DI | |||
| 75 | - | MOVQ AX, (12*8)(DI) // err | |||
| 76 | - | ||||
| 77 | - | ok: | |||
| 78 | XORL AX, AX // no error (it's ignored anyway) | 67 | XORL AX, AX // no error (it's ignored anyway) | ||
| 79 | ADDQ $32, SP | 68 | ADDQ $32, SP | ||
| 80 | MOVQ BP, SP | 69 | MOVQ BP, SP | ||
M sys_darwin_arm64.s +16 -26
| @@ -2,6 +2,7 @@ | |||
| 2 | 2 | // SPDX-FileCopyrightText: 2022 The Ebiten Authors | |
| 3 | 3 | ||
| 4 | 4 | #include "textflag.h" | |
| 5 | + | #include "go_asm.h" | |
| 5 | 6 | ||
| 6 | 7 | // syscall9X calls a function in libc on behalf of the syscall package. | |
| 7 | 8 | // syscall9X takes a pointer to a struct like: | |
| @@ -23,21 +24,21 @@ | |||
| 23 | 24 | // syscall9X must be called on the g0 stack with the | |
| 24 | 25 | // C calling convention (use libcCall). | |
| 25 | 26 | GLOBL ·syscall9XABI0(SB), NOPTR|RODATA, $8 | |
| 26 | - | DATA ·syscall9XABI0(SB)/8, $·syscall9X(SB) | |
| 27 | - | TEXT ·syscall9X(SB), NOSPLIT, $0 | |
| 27 | + | DATA ·syscall9XABI0(SB)/8, $syscall9X(SB) | |
| 28 | + | TEXT syscall9X(SB), NOSPLIT, $0 | |
| 28 | 29 | SUB $16, RSP // push structure pointer | |
| 29 | 30 | MOVD R0, 8(RSP) | |
| 30 | 31 | ||
| 31 | - | MOVD 0(R0), R12 // fn | |
| 32 | - | MOVD 16(R0), R1 // a2 | |
| 33 | - | MOVD 24(R0), R2 // a3 | |
| 34 | - | MOVD 32(R0), R3 // a4 | |
| 35 | - | MOVD 40(R0), R4 // a5 | |
| 36 | - | MOVD 48(R0), R5 // a6 | |
| 37 | - | MOVD 56(R0), R6 // a7 | |
| 38 | - | MOVD 64(R0), R7 // a8 | |
| 39 | - | MOVD 72(R0), R8 // a9 | |
| 40 | - | MOVD 8(R0), R0 // a1 | |
| 32 | + | MOVD syscall9Args_fn(R0), R12 // fn | |
| 33 | + | MOVD syscall9Args_a2(R0), R1 // a2 | |
| 34 | + | MOVD syscall9Args_a3(R0), R2 // a3 | |
| 35 | + | MOVD syscall9Args_a4(R0), R3 // a4 | |
| 36 | + | MOVD syscall9Args_a5(R0), R4 // a5 | |
| 37 | + | MOVD syscall9Args_a6(R0), R5 // a6 | |
| 38 | + | MOVD syscall9Args_a7(R0), R6 // a7 | |
| 39 | + | MOVD syscall9Args_a8(R0), R7 // a8 | |
| 40 | + | MOVD syscall9Args_a9(R0), R8 // a9 | |
| 41 | + | MOVD syscall9Args_a1(R0), R0 // a1 | |
| 41 | 42 | ||
| 42 | 43 | // these may be float arguments | |
| 43 | 44 | // so we put them also where C expects floats | |
| @@ -54,19 +55,8 @@ TEXT ·syscall9X(SB), NOSPLIT, $0 | |||
| 54 | 55 | ||
| 55 | 56 | BL (R12) | |
| 56 | 57 | ||
| 57 | - | MOVD 8(RSP), R2 // pop structure pointer | |
| 58 | + | MOVD 8(RSP), R2 // pop structure pointer | |
| 58 | 59 | ADD $16, RSP | |
| 59 | - | MOVD R0, 80(R2) // save r1 | |
| 60 | - | MOVD R1, 88(R2) // save r2 | |
| 61 | - | CMP $-1, R0 | |
| 62 | - | BNE ok | |
| 63 | - | SUB $16, RSP // push structure pointer | |
| 64 | - | MOVD R2, (RSP) | |
| 65 | - | BL libc_error(SB) | |
| 66 | - | MOVW (R0), R0 | |
| 67 | - | MOVD (RSP), R2 // pop structure pointer | |
| 68 | - | ADD $16, RSP | |
| 69 | - | MOVD R0, 96(R2) // save err | |
| 70 | - | ||
| 71 | - | ok: | |
| 60 | + | MOVD R0, syscall9Args_r1(R2) // save r1 | |
| 61 | + | MOVD R1, syscall9Args_r2(R2) // save r2 | |
| 72 | 62 | RET | |
| @@ -2,6 +2,7 @@ | |||||
| 2 | // SPDX-FileCopyrightText: 2022 The Ebiten Authors | 2 | // SPDX-FileCopyrightText: 2022 The Ebiten Authors | ||
| 3 | 3 | ||||
| 4 | #include "textflag.h" | 4 | #include "textflag.h" | ||
| 5 | + | #include "go_asm.h" | |||
| 5 | 6 | ||||
| 6 | // syscall9X calls a function in libc on behalf of the syscall package. | 7 | // syscall9X calls a function in libc on behalf of the syscall package. | ||
| 7 | // syscall9X takes a pointer to a struct like: | 8 | // syscall9X takes a pointer to a struct like: | ||
| @@ -23,21 +24,21 @@ | |||||
| 23 | // syscall9X must be called on the g0 stack with the | 24 | // syscall9X must be called on the g0 stack with the | ||
| 24 | // C calling convention (use libcCall). | 25 | // C calling convention (use libcCall). | ||
| 25 | GLOBL ·syscall9XABI0(SB), NOPTR|RODATA, $8 | 26 | GLOBL ·syscall9XABI0(SB), NOPTR|RODATA, $8 | ||
| 26 | - | DATA ·syscall9XABI0(SB)/8, $·syscall9X(SB) | 27 | + | DATA ·syscall9XABI0(SB)/8, $syscall9X(SB) |
| 27 | - | TEXT ·syscall9X(SB), NOSPLIT, $0 | 28 | + | TEXT syscall9X(SB), NOSPLIT, $0 |
| 28 | SUB $16, RSP // push structure pointer | 29 | SUB $16, RSP // push structure pointer | ||
| 29 | MOVD R0, 8(RSP) | 30 | MOVD R0, 8(RSP) | ||
| 30 | 31 | ||||
| 31 | - | MOVD 0(R0), R12 // fn | 32 | + | MOVD syscall9Args_fn(R0), R12 // fn |
| 32 | - | MOVD 16(R0), R1 // a2 | 33 | + | MOVD syscall9Args_a2(R0), R1 // a2 |
| 33 | - | MOVD 24(R0), R2 // a3 | 34 | + | MOVD syscall9Args_a3(R0), R2 // a3 |
| 34 | - | MOVD 32(R0), R3 // a4 | 35 | + | MOVD syscall9Args_a4(R0), R3 // a4 |
| 35 | - | MOVD 40(R0), R4 // a5 | 36 | + | MOVD syscall9Args_a5(R0), R4 // a5 |
| 36 | - | MOVD 48(R0), R5 // a6 | 37 | + | MOVD syscall9Args_a6(R0), R5 // a6 |
| 37 | - | MOVD 56(R0), R6 // a7 | 38 | + | MOVD syscall9Args_a7(R0), R6 // a7 |
| 38 | - | MOVD 64(R0), R7 // a8 | 39 | + | MOVD syscall9Args_a8(R0), R7 // a8 |
| 39 | - | MOVD 72(R0), R8 // a9 | 40 | + | MOVD syscall9Args_a9(R0), R8 // a9 |
| 40 | - | MOVD 8(R0), R0 // a1 | 41 | + | MOVD syscall9Args_a1(R0), R0 // a1 |
| 41 | 42 | ||||
| 42 | // these may be float arguments | 43 | // these may be float arguments | ||
| 43 | // so we put them also where C expects floats | 44 | // so we put them also where C expects floats | ||
| @@ -54,19 +55,8 @@ TEXT ·syscall9X(SB), NOSPLIT, $0 | |||||
| 54 | 55 | ||||
| 55 | BL (R12) | 56 | BL (R12) | ||
| 56 | 57 | ||||
| 57 | - | MOVD 8(RSP), R2 // pop structure pointer | 58 | + | MOVD 8(RSP), R2 // pop structure pointer |
| 58 | ADD $16, RSP | 59 | ADD $16, RSP | ||
| 59 | - | MOVD R0, 80(R2) // save r1 | 60 | + | MOVD R0, syscall9Args_r1(R2) // save r1 |
| 60 | - | MOVD R1, 88(R2) // save r2 | 61 | + | MOVD R1, syscall9Args_r2(R2) // save r2 |
| 61 | - | CMP $-1, R0 | |||
| 62 | - | BNE ok | |||
| 63 | - | SUB $16, RSP // push structure pointer | |||
| 64 | - | MOVD R2, (RSP) | |||
| 65 | - | BL libc_error(SB) | |||
| 66 | - | MOVW (R0), R0 | |||
| 67 | - | MOVD (RSP), R2 // pop structure pointer | |||
| 68 | - | ADD $16, RSP | |||
| 69 | - | MOVD R0, 96(R2) // save err | |||
| 70 | - | ||||
| 71 | - | ok: | |||
| 72 | RET | 62 | RET | ||
M syscall.go +4 -1
| @@ -21,8 +21,11 @@ const maxArgs = 9 | |||
| 21 | 21 | //go:nosplit | |
| 22 | 22 | //go:uintptrescapes | |
| 23 | 23 | func SyscallN(fn uintptr, args ...uintptr) (r1, r2, err uintptr) { | |
| 24 | + | if fn == 0 { | |
| 25 | + | panic("purego: fn is nil") | |
| 26 | + | } | |
| 24 | 27 | if len(args) > maxArgs { | |
| 25 | - | panic("too many arguments to SyscallN") | |
| 28 | + | panic("purego: too many arguments to SyscallN") | |
| 26 | 29 | } | |
| 27 | 30 | // add padding so there is no out-of-bounds slicing | |
| 28 | 31 | var tmp [maxArgs]uintptr | |
| @@ -21,8 +21,11 @@ const maxArgs = 9 | |||||
| 21 | //go:nosplit | 21 | //go:nosplit | ||
| 22 | //go:uintptrescapes | 22 | //go:uintptrescapes | ||
| 23 | func SyscallN(fn uintptr, args ...uintptr) (r1, r2, err uintptr) { | 23 | func SyscallN(fn uintptr, args ...uintptr) (r1, r2, err uintptr) { | ||
| 24 | + | if fn == 0 { | |||
| 25 | + | panic("purego: fn is nil") | |||
| 26 | + | } | |||
| 24 | if len(args) > maxArgs { | 27 | if len(args) > maxArgs { | ||
| 25 | - | panic("too many arguments to SyscallN") | 28 | + | panic("purego: too many arguments to SyscallN") |
| 26 | } | 29 | } | ||
| 27 | // add padding so there is no out-of-bounds slicing | 30 | // add padding so there is no out-of-bounds slicing | ||
| 28 | var tmp [maxArgs]uintptr | 31 | var tmp [maxArgs]uintptr | ||
M syscall_darwin.go +3 -4
| @@ -4,18 +4,17 @@ import "unsafe" | |||
| 4 | 4 | ||
| 5 | 5 | func callc(fn uintptr, args unsafe.Pointer) { | |
| 6 | 6 | runtime_entersyscall() | |
| 7 | - | runtime_libcCall(unsafe.Pointer(fn), args) | |
| 7 | + | runtime_libcCall(fn, args) | |
| 8 | 8 | runtime_exitsyscall() | |
| 9 | 9 | } | |
| 10 | 10 | ||
| 11 | 11 | var syscall9XABI0 uintptr | |
| 12 | 12 | ||
| 13 | - | func syscall9X() // implemented in assembly | |
| 13 | + | type syscall9Args struct{ fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, r1, r2, err uintptr } | |
| 14 | 14 | ||
| 15 | 15 | //go:nosplit | |
| 16 | 16 | func syscall_syscall9X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) { | |
| 17 | - | args := struct{ fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, r1, r2, err uintptr }{ | |
| 18 | - | fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, r1, r2, err} | |
| 17 | + | args := syscall9Args{fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, r1, r2, err} | |
| 19 | 18 | callc(syscall9XABI0, unsafe.Pointer(&args)) | |
| 20 | 19 | return args.r1, args.r2, args.err | |
| 21 | 20 | } | |
| @@ -4,18 +4,17 @@ import "unsafe" | |||||
| 4 | 4 | ||||
| 5 | func callc(fn uintptr, args unsafe.Pointer) { | 5 | func callc(fn uintptr, args unsafe.Pointer) { | ||
| 6 | runtime_entersyscall() | 6 | runtime_entersyscall() | ||
| 7 | - | runtime_libcCall(unsafe.Pointer(fn), args) | 7 | + | runtime_libcCall(fn, args) |
| 8 | runtime_exitsyscall() | 8 | runtime_exitsyscall() | ||
| 9 | } | 9 | } | ||
| 10 | 10 | ||||
| 11 | var syscall9XABI0 uintptr | 11 | var syscall9XABI0 uintptr | ||
| 12 | 12 | ||||
| 13 | - | func syscall9X() // implemented in assembly | 13 | + | type syscall9Args struct{ fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, r1, r2, err uintptr } |
| 14 | 14 | ||||
| 15 | //go:nosplit | 15 | //go:nosplit | ||
| 16 | func syscall_syscall9X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) { | 16 | func syscall_syscall9X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) { | ||
| 17 | - | args := struct{ fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, r1, r2, err uintptr }{ | 17 | + | args := syscall9Args{fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, r1, r2, err} |
| 18 | - | fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, r1, r2, err} | |||
| 19 | callc(syscall9XABI0, unsafe.Pointer(&args)) | 18 | callc(syscall9XABI0, unsafe.Pointer(&args)) | ||
| 20 | return args.r1, args.r2, args.err | 19 | return args.r1, args.r2, args.err | ||
| 21 | } | 20 | } | ||