detached cce0ae8

purego: use go:nosplit and map to proper implementation (#6)

This commit also adds windows support to purego
commit
cce0ae8e7ec8f56ec142abf1fff514dbc7a2fd54
author
TotallyGamerJet · · 2022-06-13 03:09 UTC
committer
GitHub · · 2022-06-13 03:09 UTC
parent
119eb37
signature
GPG Unverified4AEE18F83AFDEB23 The key is unknown
3 files · +72 -28
M syscall.go +18 -28
@@ -1,15 +1,27 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebiten Authors
33
4-//go:build darwin
5-// +build darwin
4+//go:build darwin || windows
5+// +build darwin windows
66
77 package purego
88
9-import "unsafe"
10-
119 const maxArgs = 9
1210
11+// f matches argument numbers to a Syscall implementation that can take that many
12+var f = map[int]func(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr){
13+ 0: syscall_syscallX3,
14+ 1: syscall_syscallX3,
15+ 2: syscall_syscallX3,
16+ 3: syscall_syscallX3,
17+ 4: syscall_syscallX6,
18+ 5: syscall_syscallX6,
19+ 6: syscall_syscallX6,
20+ 7: syscall_syscall9X,
21+ 8: syscall_syscall9X,
22+ 9: syscall_syscall9X,
23+}
24+
1325 // SyscallN takes fn, a C function pointer and a list of arguments as uintptr.
1426 // There is an internal maximum number of arguments that SyscallN can take. It panics
1527 // when the maximum is exceeded. It returns the result and the libc error code if there is one.
@@ -20,6 +32,7 @@ const maxArgs = 9
2032 //
2133 // On amd64, if there are more than 8 floats the 9th and so on will be placed incorrectly on the
2234 // stack.
35+//go:nosplit
2336 func SyscallN(fn uintptr, args ...uintptr) (r1, r2, err uintptr) {
2437 if len(args) > maxArgs {
2538 panic("too many arguments to SyscallN")
@@ -27,28 +40,5 @@ func SyscallN(fn uintptr, args ...uintptr) (r1, r2, err uintptr) {
2740 // add padding so there is no out-of-bounds slicing
2841 var tmp [maxArgs]uintptr
2942 copy(tmp[:], args)
30- if len(args) <= 6 {
31- // use the 6 argument version because
32- // gl.GenFramebuffersEXT would fail with the 9 version
33- // See https://github.com/hajimehoshi/ebiten/issues/2102#issuecomment-1134679352
34- return syscall_syscall6X(fn, tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5])
35- }
36- return syscall_syscall9X(fn, tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7], tmp[8])
37-}
38-
39-func callc(fn uintptr, args unsafe.Pointer) {
40- runtime_entersyscall()
41- runtime_libcCall(unsafe.Pointer(fn), args)
42- runtime_exitsyscall()
43-}
44-
45-var syscall9XABI0 uintptr
46-
47-func syscall9X() // implemented in assembly
48-
49-func syscall_syscall9X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) {
50- args := struct{ fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, r1, r2, err uintptr }{
51- fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, r1, r2, err}
52- callc(syscall9XABI0, unsafe.Pointer(&args))
53- return args.r1, args.r2, args.err
43+ return f[len(args)](fn, tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7], tmp[8])
5444 }
@@ -1,15 +1,27 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebiten Authors2 // SPDX-FileCopyrightText: 2022 The Ebiten Authors
3 3
4-//go:build darwin4+//go:build darwin || windows
5-// +build darwin5+// +build darwin windows
6 6
7 package purego7 package purego
8 8
9-import "unsafe"
10-
11 const maxArgs = 99 const maxArgs = 9
12 10
11+// f matches argument numbers to a Syscall implementation that can take that many
12+var f = map[int]func(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr){
13+ 0: syscall_syscallX3,
14+ 1: syscall_syscallX3,
15+ 2: syscall_syscallX3,
16+ 3: syscall_syscallX3,
17+ 4: syscall_syscallX6,
18+ 5: syscall_syscallX6,
19+ 6: syscall_syscallX6,
20+ 7: syscall_syscall9X,
21+ 8: syscall_syscall9X,
22+ 9: syscall_syscall9X,
23+}
24+
13 // SyscallN takes fn, a C function pointer and a list of arguments as uintptr.25 // SyscallN takes fn, a C function pointer and a list of arguments as uintptr.
14 // There is an internal maximum number of arguments that SyscallN can take. It panics26 // There is an internal maximum number of arguments that SyscallN can take. It panics
15 // when the maximum is exceeded. It returns the result and the libc error code if there is one.27 // when the maximum is exceeded. It returns the result and the libc error code if there is one.
@@ -20,6 +32,7 @@ const maxArgs = 9
20 //32 //
21 // On amd64, if there are more than 8 floats the 9th and so on will be placed incorrectly on the33 // On amd64, if there are more than 8 floats the 9th and so on will be placed incorrectly on the
22 // stack.34 // stack.
35+//go:nosplit
23 func SyscallN(fn uintptr, args ...uintptr) (r1, r2, err uintptr) {36 func SyscallN(fn uintptr, args ...uintptr) (r1, r2, err uintptr) {
24 if len(args) > maxArgs {37 if len(args) > maxArgs {
25 panic("too many arguments to SyscallN")38 panic("too many arguments to SyscallN")
@@ -27,28 +40,5 @@ func SyscallN(fn uintptr, args ...uintptr) (r1, r2, err uintptr) {
27 // add padding so there is no out-of-bounds slicing40 // add padding so there is no out-of-bounds slicing
28 var tmp [maxArgs]uintptr41 var tmp [maxArgs]uintptr
29 copy(tmp[:], args)42 copy(tmp[:], args)
30- if len(args) <= 6 {43+ return f[len(args)](fn, tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7], tmp[8])
31- // use the 6 argument version because
32- // gl.GenFramebuffersEXT would fail with the 9 version
33- // See https://github.com/hajimehoshi/ebiten/issues/2102#issuecomment-1134679352
34- return syscall_syscall6X(fn, tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5])
35- }
36- return syscall_syscall9X(fn, tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7], tmp[8])
37-}
38-
39-func callc(fn uintptr, args unsafe.Pointer) {
40- runtime_entersyscall()
41- runtime_libcCall(unsafe.Pointer(fn), args)
42- runtime_exitsyscall()
43-}
44-
45-var syscall9XABI0 uintptr
46-
47-func syscall9X() // implemented in assembly
48-
49-func syscall_syscall9X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) {
50- args := struct{ fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, r1, r2, err uintptr }{
51- fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, r1, r2, err}
52- callc(syscall9XABI0, unsafe.Pointer(&args))
53- return args.r1, args.r2, args.err
54 }44 }
A syscall_darwin.go +31 -0
@@ -0,0 +1,31 @@
1+package purego
2+
3+import "unsafe"
4+
5+func callc(fn uintptr, args unsafe.Pointer) {
6+ runtime_entersyscall()
7+ runtime_libcCall(unsafe.Pointer(fn), args)
8+ runtime_exitsyscall()
9+}
10+
11+//go:nosplit
12+func syscall_syscallX3(fn, a1, a2, a3, _, _, _, _, _, _ uintptr) (r1, r2, err uintptr) {
13+ return syscall_syscall6X(fn, a1, a2, a3, 0, 0, 0)
14+}
15+
16+//go:nosplit
17+func syscall_syscallX6(fn, a1, a2, a3, a4, a5, a6, _, _, _ uintptr) (r1, r2, err uintptr) {
18+ return syscall_syscall6X(fn, a1, a2, a3, a4, a5, a6)
19+}
20+
21+var syscall9XABI0 uintptr
22+
23+func syscall9X() // implemented in assembly
24+
25+//go:nosplit
26+func syscall_syscall9X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) {
27+ args := struct{ fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, r1, r2, err uintptr }{
28+ fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, r1, r2, err}
29+ callc(syscall9XABI0, unsafe.Pointer(&args))
30+ return args.r1, args.r2, args.err
31+}
@@ -0,0 +1,31 @@
1+package purego
2+
3+import "unsafe"
4+
5+func callc(fn uintptr, args unsafe.Pointer) {
6+ runtime_entersyscall()
7+ runtime_libcCall(unsafe.Pointer(fn), args)
8+ runtime_exitsyscall()
9+}
10+
11+//go:nosplit
12+func syscall_syscallX3(fn, a1, a2, a3, _, _, _, _, _, _ uintptr) (r1, r2, err uintptr) {
13+ return syscall_syscall6X(fn, a1, a2, a3, 0, 0, 0)
14+}
15+
16+//go:nosplit
17+func syscall_syscallX6(fn, a1, a2, a3, a4, a5, a6, _, _, _ uintptr) (r1, r2, err uintptr) {
18+ return syscall_syscall6X(fn, a1, a2, a3, a4, a5, a6)
19+}
20+
21+var syscall9XABI0 uintptr
22+
23+func syscall9X() // implemented in assembly
24+
25+//go:nosplit
26+func syscall_syscall9X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) {
27+ args := struct{ fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, r1, r2, err uintptr }{
28+ fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, r1, r2, err}
29+ callc(syscall9XABI0, unsafe.Pointer(&args))
30+ return args.r1, args.r2, args.err
31+}
A syscall_windows.go +23 -0
@@ -0,0 +1,23 @@
1+package purego
2+
3+import (
4+ "syscall"
5+)
6+
7+//go:nosplit
8+func syscall_syscallX3(fn, a1, a2, a3, _, _, _, _, _, _ uintptr) (r1, r2, err uintptr) {
9+ r1, r2, errno := syscall.Syscall(fn, 3, a1, a2, a3)
10+ return r1, r2, uintptr(errno)
11+}
12+
13+//go:nosplit
14+func syscall_syscallX6(fn, a1, a2, a3, a4, a5, a6, _, _, _ uintptr) (r1, r2, err uintptr) {
15+ r1, r2, errno := syscall.Syscall6(fn, 6, a1, a2, a3, a4, a5, a6)
16+ return r1, r2, uintptr(errno)
17+}
18+
19+//go:nosplit
20+func syscall_syscall9X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) {
21+ r1, r2, errno := syscall.Syscall9(fn, 9, a1, a2, a3, a4, a5, a6, a7, a8, a9)
22+ return r1, r2, uintptr(errno)
23+}
@@ -0,0 +1,23 @@
1+package purego
2+
3+import (
4+ "syscall"
5+)
6+
7+//go:nosplit
8+func syscall_syscallX3(fn, a1, a2, a3, _, _, _, _, _, _ uintptr) (r1, r2, err uintptr) {
9+ r1, r2, errno := syscall.Syscall(fn, 3, a1, a2, a3)
10+ return r1, r2, uintptr(errno)
11+}
12+
13+//go:nosplit
14+func syscall_syscallX6(fn, a1, a2, a3, a4, a5, a6, _, _, _ uintptr) (r1, r2, err uintptr) {
15+ r1, r2, errno := syscall.Syscall6(fn, 6, a1, a2, a3, a4, a5, a6)
16+ return r1, r2, uintptr(errno)
17+}
18+
19+//go:nosplit
20+func syscall_syscall9X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) {
21+ r1, r2, errno := syscall.Syscall9(fn, 9, a1, a2, a3, a4, a5, a6, a7, a8, a9)
22+ return r1, r2, uintptr(errno)
23+}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 1

Tags 102

↑↓ moveenter openesc close