detached 0a71637

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 Unverified4AEE18F83AFDEB23 The key is unknown
9 files · +63 -75
M README.md +4 -0
@@ -0,0 +1,4 @@
1+# purego
2+[![Go Reference](https://pkg.go.dev/badge/github.com/ebitengine/purego?GOOS=darwin.svg)](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+[![Go Reference](https://pkg.go.dev/badge/github.com/ebitengine/purego?GOOS=darwin.svg)](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 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebiten Authors
33
4+//go:build darwin
5+// +build darwin
6+
47 package purego
58
69 import (
@@ -19,7 +22,7 @@ func hasSuffix(s, suffix string) bool {
1922
2023 func cString(name string) *byte {
2124 if hasSuffix(name, "\x00") {
22- return &[]byte(name)[0]
25+ return &(*(*[]byte)(unsafe.Pointer(&name)))[0]
2326 }
2427 var b = make([]byte, len(name)+1)
2528 copy(b, name)
@@ -40,13 +43,6 @@ func Dlsym(handle uintptr, name string) uintptr {
4043 return ret
4144 }
4245
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
4647 var dlopenABI0 uintptr
47-
48-func dlopen() // implemented in assembly
49-
5048 var dlsymABI0 uintptr
51-
52-func dlsym() // implemented in assembly
@@ -1,6 +1,9 @@
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 darwin
5+// +build darwin
6+
4 package purego7 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 ret43 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 uintptr47 var dlopenABI0 uintptr
47-
48-func dlopen() // implemented in assembly
49-
50 var dlsymABI0 uintptr48 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 @@
88
99 // func dlopen(path *byte, mode int) (ret uintptr)
1010 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
1313 JMP _dlopen(SB)
1414 RET
1515
1616 // func dlsym(handle uintptr, symbol *byte) (ret uintptr)
1717 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
2020 JMP _dlsym(SB)
2121 RET
2222
@@ -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, $810 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-012+TEXT dlopen(SB), NOSPLIT, $0-0
13 JMP _dlopen(SB)13 JMP _dlopen(SB)
14 RET14 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, $817 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-019+TEXT dlsym(SB), NOSPLIT, $0-0
20 JMP _dlsym(SB)20 JMP _dlsym(SB)
21 RET21 RET
22 22
R runtime.go → go_runtime.go +3 -3 renamed, 55% similar
@@ -13,6 +13,6 @@ import (
1313 //go:linkname runtime_libcCall runtime.libcCall
1414 //go:linkname runtime_entersyscall runtime.entersyscall
1515 //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.libcCall13 //go:linkname runtime_libcCall runtime.libcCall
14 //go:linkname runtime_entersyscall runtime.entersyscall14 //go:linkname runtime_entersyscall runtime.entersyscall
15 //go:linkname runtime_exitsyscall runtime.exitsyscall15 //go:linkname runtime_exitsyscall runtime.exitsyscall
16-func runtime_libcCall(fn, arg unsafe.Pointer) int32 // from runtime/sys_libc.go16+func runtime_libcCall(fn uintptr, arg unsafe.Pointer) int32 // from runtime/sys_libc.go
17-func runtime_entersyscall() // from runtime/proc.go17+func runtime_entersyscall() // from runtime/proc.go
18-func runtime_exitsyscall() // from runtime/proc.go18+func runtime_exitsyscall() // from runtime/proc.go
M sys_darwin_amd64.s +17 -28
@@ -2,6 +2,7 @@
22 // SPDX-FileCopyrightText: 2022 The Ebiten Authors
33
44 #include "textflag.h"
5+#include "go_asm.h"
56
67 // syscall9X calls a function in libc on behalf of the syscall package.
78 // syscall9X takes a pointer to a struct like:
@@ -23,22 +24,22 @@
2324 // syscall9X must be called on the g0 stack with the
2425 // C calling convention (use libcCall).
2526 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
2829 PUSHQ BP
2930 MOVQ SP, BP
3031 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
4243
4344 // these may be float arguments
4445 // so we put them also where C expects floats
@@ -59,22 +60,10 @@ TEXT ·syscall9X(SB), NOSPLIT, $0
5960
6061 CALL R10
6162
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
6566
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:
7867 XORL AX, AX // no error (it's ignored anyway)
7968 ADDQ $32, SP
8069 MOVQ BP, SP
@@ -2,6 +2,7 @@
2 // SPDX-FileCopyrightText: 2022 The Ebiten Authors2 // 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 the24 // 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, $826 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, $028+TEXT syscall9X(SB), NOSPLIT, $0
28 PUSHQ BP29 PUSHQ BP
29 MOVQ SP, BP30 MOVQ SP, BP
30 SUBQ $32, SP31 SUBQ $32, SP
31- MOVQ DI, 24(BP) // save the pointer32+ MOVQ DI, 24(BP) // save the pointer
32- MOVQ (0*8)(DI), R10 // fn33+ MOVQ syscall9Args_fn(DI), R10 // fn
33- MOVQ (2*8)(DI), SI // a234+ MOVQ syscall9Args_a2(DI), SI // a2
34- MOVQ (3*8)(DI), DX // a335+ MOVQ syscall9Args_a3(DI), DX // a3
35- MOVQ (4*8)(DI), CX // a436+ MOVQ syscall9Args_a4(DI), CX // a4
36- MOVQ (5*8)(DI), R8 // a537+ MOVQ syscall9Args_a5(DI), R8 // a5
37- MOVQ (6*8)(DI), R9 // a638+ MOVQ syscall9Args_a6(DI), R9 // a6
38- MOVQ (7*8)(DI), R11 // a739+ MOVQ syscall9Args_a7(DI), R11 // a7
39- MOVQ (8*8)(DI), R12 // a840+ MOVQ syscall9Args_a8(DI), R12 // a8
40- MOVQ (9*8)(DI), R13 // a941+ MOVQ syscall9Args_a9(DI), R13 // a9
41- MOVQ (1*8)(DI), DI // a142+ MOVQ syscall9Args_a1(DI), DI // a1
42 43
43 // these may be float arguments44 // these may be float arguments
44 // so we put them also where C expects floats45 // so we put them also where C expects floats
@@ -59,22 +60,10 @@ TEXT ·syscall9X(SB), NOSPLIT, $0
59 60
60 CALL R1061 CALL R10
61 62
62- MOVQ 24(BP), DI // get the pointer back63+ MOVQ 24(BP), DI // get the pointer back
63- MOVQ AX, (10*8)(DI) // r164+ MOVQ AX, syscall9Args_r1(DI) // r1
64- MOVQ DX, (11*8)(DI) // r265+ 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, SP68 ADDQ $32, SP
80 MOVQ BP, SP69 MOVQ BP, SP
M sys_darwin_arm64.s +16 -26
@@ -2,6 +2,7 @@
22 // SPDX-FileCopyrightText: 2022 The Ebiten Authors
33
44 #include "textflag.h"
5+#include "go_asm.h"
56
67 // syscall9X calls a function in libc on behalf of the syscall package.
78 // syscall9X takes a pointer to a struct like:
@@ -23,21 +24,21 @@
2324 // syscall9X must be called on the g0 stack with the
2425 // C calling convention (use libcCall).
2526 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
2829 SUB $16, RSP // push structure pointer
2930 MOVD R0, 8(RSP)
3031
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
4142
4243 // these may be float arguments
4344 // so we put them also where C expects floats
@@ -54,19 +55,8 @@ TEXT ·syscall9X(SB), NOSPLIT, $0
5455
5556 BL (R12)
5657
57- MOVD 8(RSP), R2 // pop structure pointer
58+ MOVD 8(RSP), R2 // pop structure pointer
5859 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
7262 RET
@@ -2,6 +2,7 @@
2 // SPDX-FileCopyrightText: 2022 The Ebiten Authors2 // 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 the24 // 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, $826 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, $028+TEXT syscall9X(SB), NOSPLIT, $0
28 SUB $16, RSP // push structure pointer29 SUB $16, RSP // push structure pointer
29 MOVD R0, 8(RSP)30 MOVD R0, 8(RSP)
30 31
31- MOVD 0(R0), R12 // fn32+ MOVD syscall9Args_fn(R0), R12 // fn
32- MOVD 16(R0), R1 // a233+ MOVD syscall9Args_a2(R0), R1 // a2
33- MOVD 24(R0), R2 // a334+ MOVD syscall9Args_a3(R0), R2 // a3
34- MOVD 32(R0), R3 // a435+ MOVD syscall9Args_a4(R0), R3 // a4
35- MOVD 40(R0), R4 // a536+ MOVD syscall9Args_a5(R0), R4 // a5
36- MOVD 48(R0), R5 // a637+ MOVD syscall9Args_a6(R0), R5 // a6
37- MOVD 56(R0), R6 // a738+ MOVD syscall9Args_a7(R0), R6 // a7
38- MOVD 64(R0), R7 // a839+ MOVD syscall9Args_a8(R0), R7 // a8
39- MOVD 72(R0), R8 // a940+ MOVD syscall9Args_a9(R0), R8 // a9
40- MOVD 8(R0), R0 // a141+ MOVD syscall9Args_a1(R0), R0 // a1
41 42
42 // these may be float arguments43 // these may be float arguments
43 // so we put them also where C expects floats44 // 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 pointer58+ MOVD 8(RSP), R2 // pop structure pointer
58 ADD $16, RSP59 ADD $16, RSP
59- MOVD R0, 80(R2) // save r160+ MOVD R0, syscall9Args_r1(R2) // save r1
60- MOVD R1, 88(R2) // save r261+ 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 RET62 RET
M syscall.go +4 -1
@@ -21,8 +21,11 @@ const maxArgs = 9
2121 //go:nosplit
2222 //go:uintptrescapes
2323 func SyscallN(fn uintptr, args ...uintptr) (r1, r2, err uintptr) {
24+ if fn == 0 {
25+ panic("purego: fn is nil")
26+ }
2427 if len(args) > maxArgs {
25- panic("too many arguments to SyscallN")
28+ panic("purego: too many arguments to SyscallN")
2629 }
2730 // add padding so there is no out-of-bounds slicing
2831 var tmp [maxArgs]uintptr
@@ -21,8 +21,11 @@ const maxArgs = 9
21 //go:nosplit21 //go:nosplit
22 //go:uintptrescapes22 //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 slicing30 // add padding so there is no out-of-bounds slicing
28 var tmp [maxArgs]uintptr31 var tmp [maxArgs]uintptr
M syscall_darwin.go +3 -4
@@ -4,18 +4,17 @@ import "unsafe"
44
55 func callc(fn uintptr, args unsafe.Pointer) {
66 runtime_entersyscall()
7- runtime_libcCall(unsafe.Pointer(fn), args)
7+ runtime_libcCall(fn, args)
88 runtime_exitsyscall()
99 }
1010
1111 var syscall9XABI0 uintptr
1212
13-func syscall9X() // implemented in assembly
13+type syscall9Args struct{ fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, r1, r2, err uintptr }
1414
1515 //go:nosplit
1616 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}
1918 callc(syscall9XABI0, unsafe.Pointer(&args))
2019 return args.r1, args.r2, args.err
2120 }
@@ -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 uintptr11 var syscall9XABI0 uintptr
12 12
13-func syscall9X() // implemented in assembly13+type syscall9Args struct{ fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, r1, r2, err uintptr }
14 14
15 //go:nosplit15 //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.err19 return args.r1, args.r2, args.err
21 }20 }

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