detached f2a39ff

internal/fakecgo: generate symbols.go and trampolines_stubs.s (#70)

These files are very repetitive so it is better to just generate them. It will make adding functions in the future easier.

This also standardizes all the assembly trampoline functions to have zero frame and zero arguments.
commit
f2a39ffe90f7baec85442ed5e1c3c7dfce5f4685
author
TotallyGamerJet · · 2022-11-28 12:54 UTC
committer
GitHub · · 2022-11-28 12:54 UTC
parent
05c1074
signature
GPG Unverified4AEE18F83AFDEB23 The key is unknown
4 files · +180 -10
M internal/fakecgo/doc.go +3 -0
@@ -28,3 +28,6 @@
2828 // Purego will pick which ever Cgo runtime is available and prefer the one that
2929 // comes with Go (runtime/cgo).
3030 package fakecgo
31+
32+//go:generate go run gen.go
33+//go:generate gofmt -s -w symbols.go
@@ -28,3 +28,6 @@
28 // Purego will pick which ever Cgo runtime is available and prefer the one that28 // Purego will pick which ever Cgo runtime is available and prefer the one that
29 // comes with Go (runtime/cgo).29 // comes with Go (runtime/cgo).
30 package fakecgo30 package fakecgo
31+
32+//go:generate go run gen.go
33+//go:generate gofmt -s -w symbols.go
A internal/fakecgo/gen.go +163 -0
@@ -0,0 +1,163 @@
1+// SPDX-License-Identifier: Apache-2.0
2+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3+
4+//go:build ignore
5+
6+package main
7+
8+import (
9+ "log"
10+ "os"
11+ "strings"
12+ "text/template"
13+)
14+
15+const templateSymbols = `// Code generated by 'go generate' with gen.go. DO NOT EDIT.
16+
17+// SPDX-License-Identifier: Apache-2.0
18+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
19+
20+//go:build darwin || linux
21+
22+package fakecgo
23+
24+import (
25+ "syscall"
26+ "unsafe"
27+)
28+
29+// setg_trampoline calls setg with the G provided
30+func setg_trampoline(setg uintptr, G uintptr)
31+
32+//go:linkname memmove runtime.memmove
33+func memmove(to, from unsafe.Pointer, n uintptr)
34+
35+// call5 takes fn the C function and 5 arguments and calls the function with those arguments
36+func call5(fn, a1, a2, a3, a4, a5 uintptr) uintptr
37+
38+{{ range . -}}
39+func {{.Name}}(
40+{{- range .Args -}}
41+ {{- if .Name -}}
42+ {{.Name}} {{.Type}},
43+ {{- end -}}
44+{{- end -}}) {{.Return}} {
45+ {{- if .Return -}}
46+ {{- if eq .Return "unsafe.Pointer" -}}
47+ ret :=
48+ {{- else -}}
49+ return {{.Return}}(
50+ {{- end -}}
51+ {{- end -}}
52+call5({{.Name}}ABI0,
53+{{- range .Args}}
54+ {{- if .Name -}}
55+ {{- if hasPrefix .Type "*" -}}
56+ uintptr(unsafe.Pointer({{.Name}})),
57+ {{- else -}}
58+ uintptr({{.Name}}),
59+ {{- end -}}
60+ {{- else -}}
61+ 0,
62+ {{- end -}}
63+{{- end -}}
64+ ) {{/* end of call5 */}}
65+{{- if .Return -}}
66+ {{- if eq .Return "unsafe.Pointer"}}
67+ // this indirection is to avoid go vet complaining about possible misuse of unsafe.Pointer
68+ return *(*unsafe.Pointer)(unsafe.Pointer(&ret))
69+ {{- else -}}
70+ ) {{/* end of cast */}}
71+ {{- end -}}
72+{{- end}}
73+}
74+
75+{{end}}
76+{{- range . }}
77+//go:linkname _{{.Name}} _{{.Name}}
78+var _{{.Name}} uintptr
79+var {{.Name}}ABI0 = uintptr(unsafe.Pointer(&_{{.Name}}))
80+{{ end }}
81+`
82+
83+const templateTrampolinesStubs = `// Code generated by 'go generate' with gen.go. DO NOT EDIT.
84+
85+// SPDX-License-Identifier: Apache-2.0
86+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
87+
88+//go:build darwin || linux
89+
90+#include "textflag.h"
91+
92+// these stubs are here because it is not possible to go:linkname directly the C functions on darwin arm64
93+{{ range . }}
94+TEXT _{{.Name}}(SB), NOSPLIT, $0-0
95+ JMP purego_{{.Name}}(SB)
96+ RET
97+{{ end -}}
98+`
99+
100+type Arg struct {
101+ Name string
102+ Type string
103+}
104+
105+type Symbol struct {
106+ Name string
107+ Args [5]Arg
108+ Return string
109+}
110+
111+var symbols = []Symbol{
112+ {"malloc", [5]Arg{{"size", "uintptr"}}, "unsafe.Pointer"},
113+ {"free", [5]Arg{{"ptr", "unsafe.Pointer"}}, ""},
114+ {"setenv", [5]Arg{{"name", "*byte"}, {"value", "*byte"}, {"overwrite", "int32"}}, "int32"},
115+ {"unsetenv", [5]Arg{{"name", "*byte"}}, "int32"},
116+ {"pthread_attr_init", [5]Arg{{"attr", "*pthread_attr_t"}}, "int32"},
117+ {"pthread_create", [5]Arg{{"thread", "*pthread_t"}, {"attr", "*pthread_attr_t"}, {"start", "unsafe.Pointer"}, {"arg", "unsafe.Pointer"}}, "int32"},
118+ {"pthread_detach", [5]Arg{{"thread", "pthread_t"}}, "int32"},
119+ {"pthread_sigmask", [5]Arg{{"how", "sighow"}, {"ign", "*sigset_t"}, {"oset", "*sigset_t"}}, "int32"},
120+ {"pthread_attr_getstacksize", [5]Arg{{"attr", "*pthread_attr_t"}, {"stacksize", "*size_t"}}, "int32"},
121+ {"pthread_attr_destroy", [5]Arg{{"attr", "*pthread_attr_t"}}, "int32"},
122+ {"sigfillset", [5]Arg{{"set", "*sigset_t"}}, "int32"},
123+ {"nanosleep", [5]Arg{{"ts", "*syscall.Timespec"}, {"rem", "*syscall.Timespec"}}, "int32"},
124+ {"abort", [5]Arg{}, ""},
125+}
126+
127+var funcs = map[string]any{
128+ "hasPrefix": strings.HasPrefix,
129+}
130+
131+func run() error {
132+ t, err := template.New("symbol.go").Funcs(funcs).Parse(templateSymbols)
133+ if err != nil {
134+ return err
135+ }
136+ f, err := os.Create("symbols.go")
137+ defer f.Close()
138+ if err != nil {
139+ return err
140+ }
141+ if err := t.Execute(f, symbols); err != nil {
142+ return err
143+ }
144+ t, err = template.New("trampolines_stubs.s").Funcs(funcs).Parse(templateTrampolinesStubs)
145+ if err != nil {
146+ return err
147+ }
148+ f, err = os.Create("trampolines_stubs.s")
149+ defer f.Close()
150+ if err != nil {
151+ return err
152+ }
153+ if err := t.Execute(f, symbols); err != nil {
154+ return err
155+ }
156+ return nil
157+}
158+
159+func main() {
160+ if err := run(); err != nil {
161+ log.Fatal(err)
162+ }
163+}
@@ -0,0 +1,163 @@
1+// SPDX-License-Identifier: Apache-2.0
2+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3+
4+//go:build ignore
5+
6+package main
7+
8+import (
9+ "log"
10+ "os"
11+ "strings"
12+ "text/template"
13+)
14+
15+const templateSymbols = `// Code generated by 'go generate' with gen.go. DO NOT EDIT.
16+
17+// SPDX-License-Identifier: Apache-2.0
18+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
19+
20+//go:build darwin || linux
21+
22+package fakecgo
23+
24+import (
25+ "syscall"
26+ "unsafe"
27+)
28+
29+// setg_trampoline calls setg with the G provided
30+func setg_trampoline(setg uintptr, G uintptr)
31+
32+//go:linkname memmove runtime.memmove
33+func memmove(to, from unsafe.Pointer, n uintptr)
34+
35+// call5 takes fn the C function and 5 arguments and calls the function with those arguments
36+func call5(fn, a1, a2, a3, a4, a5 uintptr) uintptr
37+
38+{{ range . -}}
39+func {{.Name}}(
40+{{- range .Args -}}
41+ {{- if .Name -}}
42+ {{.Name}} {{.Type}},
43+ {{- end -}}
44+{{- end -}}) {{.Return}} {
45+ {{- if .Return -}}
46+ {{- if eq .Return "unsafe.Pointer" -}}
47+ ret :=
48+ {{- else -}}
49+ return {{.Return}}(
50+ {{- end -}}
51+ {{- end -}}
52+call5({{.Name}}ABI0,
53+{{- range .Args}}
54+ {{- if .Name -}}
55+ {{- if hasPrefix .Type "*" -}}
56+ uintptr(unsafe.Pointer({{.Name}})),
57+ {{- else -}}
58+ uintptr({{.Name}}),
59+ {{- end -}}
60+ {{- else -}}
61+ 0,
62+ {{- end -}}
63+{{- end -}}
64+ ) {{/* end of call5 */}}
65+{{- if .Return -}}
66+ {{- if eq .Return "unsafe.Pointer"}}
67+ // this indirection is to avoid go vet complaining about possible misuse of unsafe.Pointer
68+ return *(*unsafe.Pointer)(unsafe.Pointer(&ret))
69+ {{- else -}}
70+ ) {{/* end of cast */}}
71+ {{- end -}}
72+{{- end}}
73+}
74+
75+{{end}}
76+{{- range . }}
77+//go:linkname _{{.Name}} _{{.Name}}
78+var _{{.Name}} uintptr
79+var {{.Name}}ABI0 = uintptr(unsafe.Pointer(&_{{.Name}}))
80+{{ end }}
81+`
82+
83+const templateTrampolinesStubs = `// Code generated by 'go generate' with gen.go. DO NOT EDIT.
84+
85+// SPDX-License-Identifier: Apache-2.0
86+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
87+
88+//go:build darwin || linux
89+
90+#include "textflag.h"
91+
92+// these stubs are here because it is not possible to go:linkname directly the C functions on darwin arm64
93+{{ range . }}
94+TEXT _{{.Name}}(SB), NOSPLIT, $0-0
95+ JMP purego_{{.Name}}(SB)
96+ RET
97+{{ end -}}
98+`
99+
100+type Arg struct {
101+ Name string
102+ Type string
103+}
104+
105+type Symbol struct {
106+ Name string
107+ Args [5]Arg
108+ Return string
109+}
110+
111+var symbols = []Symbol{
112+ {"malloc", [5]Arg{{"size", "uintptr"}}, "unsafe.Pointer"},
113+ {"free", [5]Arg{{"ptr", "unsafe.Pointer"}}, ""},
114+ {"setenv", [5]Arg{{"name", "*byte"}, {"value", "*byte"}, {"overwrite", "int32"}}, "int32"},
115+ {"unsetenv", [5]Arg{{"name", "*byte"}}, "int32"},
116+ {"pthread_attr_init", [5]Arg{{"attr", "*pthread_attr_t"}}, "int32"},
117+ {"pthread_create", [5]Arg{{"thread", "*pthread_t"}, {"attr", "*pthread_attr_t"}, {"start", "unsafe.Pointer"}, {"arg", "unsafe.Pointer"}}, "int32"},
118+ {"pthread_detach", [5]Arg{{"thread", "pthread_t"}}, "int32"},
119+ {"pthread_sigmask", [5]Arg{{"how", "sighow"}, {"ign", "*sigset_t"}, {"oset", "*sigset_t"}}, "int32"},
120+ {"pthread_attr_getstacksize", [5]Arg{{"attr", "*pthread_attr_t"}, {"stacksize", "*size_t"}}, "int32"},
121+ {"pthread_attr_destroy", [5]Arg{{"attr", "*pthread_attr_t"}}, "int32"},
122+ {"sigfillset", [5]Arg{{"set", "*sigset_t"}}, "int32"},
123+ {"nanosleep", [5]Arg{{"ts", "*syscall.Timespec"}, {"rem", "*syscall.Timespec"}}, "int32"},
124+ {"abort", [5]Arg{}, ""},
125+}
126+
127+var funcs = map[string]any{
128+ "hasPrefix": strings.HasPrefix,
129+}
130+
131+func run() error {
132+ t, err := template.New("symbol.go").Funcs(funcs).Parse(templateSymbols)
133+ if err != nil {
134+ return err
135+ }
136+ f, err := os.Create("symbols.go")
137+ defer f.Close()
138+ if err != nil {
139+ return err
140+ }
141+ if err := t.Execute(f, symbols); err != nil {
142+ return err
143+ }
144+ t, err = template.New("trampolines_stubs.s").Funcs(funcs).Parse(templateTrampolinesStubs)
145+ if err != nil {
146+ return err
147+ }
148+ f, err = os.Create("trampolines_stubs.s")
149+ defer f.Close()
150+ if err != nil {
151+ return err
152+ }
153+ if err := t.Execute(f, symbols); err != nil {
154+ return err
155+ }
156+ return nil
157+}
158+
159+func main() {
160+ if err := run(); err != nil {
161+ log.Fatal(err)
162+ }
163+}
M internal/fakecgo/symbols.go +7 -5
@@ -1,3 +1,5 @@
1+// Code generated by 'go generate' with gen.go. DO NOT EDIT.
2+
13 // SPDX-License-Identifier: Apache-2.0
24 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
35
@@ -20,7 +22,7 @@ func memmove(to, from unsafe.Pointer, n uintptr)
2022 func call5(fn, a1, a2, a3, a4, a5 uintptr) uintptr
2123
2224 func malloc(size uintptr) unsafe.Pointer {
23- ret := call5(mallocABI0, size, 0, 0, 0, 0)
25+ ret := call5(mallocABI0, uintptr(size), 0, 0, 0, 0)
2426 // this indirection is to avoid go vet complaining about possible misuse of unsafe.Pointer
2527 return *(*unsafe.Pointer)(unsafe.Pointer(&ret))
2628 }
@@ -29,7 +31,7 @@ func free(ptr unsafe.Pointer) {
2931 call5(freeABI0, uintptr(ptr), 0, 0, 0, 0)
3032 }
3133
32-func setenv(name, value *byte, overwrite int32) int32 {
34+func setenv(name *byte, value *byte, overwrite int32) int32 {
3335 return int32(call5(setenvABI0, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(value)), uintptr(overwrite), 0, 0))
3436 }
3537
@@ -41,7 +43,7 @@ func pthread_attr_init(attr *pthread_attr_t) int32 {
4143 return int32(call5(pthread_attr_initABI0, uintptr(unsafe.Pointer(attr)), 0, 0, 0, 0))
4244 }
4345
44-func pthread_create(thread *pthread_t, attr *pthread_attr_t, start, arg unsafe.Pointer) int32 {
46+func pthread_create(thread *pthread_t, attr *pthread_attr_t, start unsafe.Pointer, arg unsafe.Pointer) int32 {
4547 return int32(call5(pthread_createABI0, uintptr(unsafe.Pointer(thread)), uintptr(unsafe.Pointer(attr)), uintptr(start), uintptr(arg), 0))
4648 }
4749
@@ -49,7 +51,7 @@ func pthread_detach(thread pthread_t) int32 {
4951 return int32(call5(pthread_detachABI0, uintptr(thread), 0, 0, 0, 0))
5052 }
5153
52-func pthread_sigmask(how sighow, ign, oset *sigset_t) int32 {
54+func pthread_sigmask(how sighow, ign *sigset_t, oset *sigset_t) int32 {
5355 return int32(call5(pthread_sigmaskABI0, uintptr(how), uintptr(unsafe.Pointer(ign)), uintptr(unsafe.Pointer(oset)), 0, 0))
5456 }
5557
@@ -65,7 +67,7 @@ func sigfillset(set *sigset_t) int32 {
6567 return int32(call5(sigfillsetABI0, uintptr(unsafe.Pointer(set)), 0, 0, 0, 0))
6668 }
6769
68-func nanosleep(ts, rem *syscall.Timespec) int32 {
70+func nanosleep(ts *syscall.Timespec, rem *syscall.Timespec) int32 {
6971 return int32(call5(nanosleepABI0, uintptr(unsafe.Pointer(ts)), uintptr(unsafe.Pointer(rem)), 0, 0, 0))
7072 }
7173
@@ -1,3 +1,5 @@
1+// Code generated by 'go generate' with gen.go. DO NOT EDIT.
2+
1 // SPDX-License-Identifier: Apache-2.03 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors4 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 5
@@ -20,7 +22,7 @@ func memmove(to, from unsafe.Pointer, n uintptr)
20 func call5(fn, a1, a2, a3, a4, a5 uintptr) uintptr22 func call5(fn, a1, a2, a3, a4, a5 uintptr) uintptr
21 23
22 func malloc(size uintptr) unsafe.Pointer {24 func malloc(size uintptr) unsafe.Pointer {
23- ret := call5(mallocABI0, size, 0, 0, 0, 0)25+ ret := call5(mallocABI0, uintptr(size), 0, 0, 0, 0)
24 // this indirection is to avoid go vet complaining about possible misuse of unsafe.Pointer26 // this indirection is to avoid go vet complaining about possible misuse of unsafe.Pointer
25 return *(*unsafe.Pointer)(unsafe.Pointer(&ret))27 return *(*unsafe.Pointer)(unsafe.Pointer(&ret))
26 }28 }
@@ -29,7 +31,7 @@ func free(ptr unsafe.Pointer) {
29 call5(freeABI0, uintptr(ptr), 0, 0, 0, 0)31 call5(freeABI0, uintptr(ptr), 0, 0, 0, 0)
30 }32 }
31 33
32-func setenv(name, value *byte, overwrite int32) int32 {34+func setenv(name *byte, value *byte, overwrite int32) int32 {
33 return int32(call5(setenvABI0, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(value)), uintptr(overwrite), 0, 0))35 return int32(call5(setenvABI0, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(value)), uintptr(overwrite), 0, 0))
34 }36 }
35 37
@@ -41,7 +43,7 @@ func pthread_attr_init(attr *pthread_attr_t) int32 {
41 return int32(call5(pthread_attr_initABI0, uintptr(unsafe.Pointer(attr)), 0, 0, 0, 0))43 return int32(call5(pthread_attr_initABI0, uintptr(unsafe.Pointer(attr)), 0, 0, 0, 0))
42 }44 }
43 45
44-func pthread_create(thread *pthread_t, attr *pthread_attr_t, start, arg unsafe.Pointer) int32 {46+func pthread_create(thread *pthread_t, attr *pthread_attr_t, start unsafe.Pointer, arg unsafe.Pointer) int32 {
45 return int32(call5(pthread_createABI0, uintptr(unsafe.Pointer(thread)), uintptr(unsafe.Pointer(attr)), uintptr(start), uintptr(arg), 0))47 return int32(call5(pthread_createABI0, uintptr(unsafe.Pointer(thread)), uintptr(unsafe.Pointer(attr)), uintptr(start), uintptr(arg), 0))
46 }48 }
47 49
@@ -49,7 +51,7 @@ func pthread_detach(thread pthread_t) int32 {
49 return int32(call5(pthread_detachABI0, uintptr(thread), 0, 0, 0, 0))51 return int32(call5(pthread_detachABI0, uintptr(thread), 0, 0, 0, 0))
50 }52 }
51 53
52-func pthread_sigmask(how sighow, ign, oset *sigset_t) int32 {54+func pthread_sigmask(how sighow, ign *sigset_t, oset *sigset_t) int32 {
53 return int32(call5(pthread_sigmaskABI0, uintptr(how), uintptr(unsafe.Pointer(ign)), uintptr(unsafe.Pointer(oset)), 0, 0))55 return int32(call5(pthread_sigmaskABI0, uintptr(how), uintptr(unsafe.Pointer(ign)), uintptr(unsafe.Pointer(oset)), 0, 0))
54 }56 }
55 57
@@ -65,7 +67,7 @@ func sigfillset(set *sigset_t) int32 {
65 return int32(call5(sigfillsetABI0, uintptr(unsafe.Pointer(set)), 0, 0, 0, 0))67 return int32(call5(sigfillsetABI0, uintptr(unsafe.Pointer(set)), 0, 0, 0, 0))
66 }68 }
67 69
68-func nanosleep(ts, rem *syscall.Timespec) int32 {70+func nanosleep(ts *syscall.Timespec, rem *syscall.Timespec) int32 {
69 return int32(call5(nanosleepABI0, uintptr(unsafe.Pointer(ts)), uintptr(unsafe.Pointer(rem)), 0, 0, 0))71 return int32(call5(nanosleepABI0, uintptr(unsafe.Pointer(ts)), uintptr(unsafe.Pointer(rem)), 0, 0, 0))
70 }72 }
71 73
M internal/fakecgo/trampolines_stubs.s +7 -5
@@ -1,3 +1,5 @@
1+// Code generated by 'go generate' with gen.go. DO NOT EDIT.
2+
13 // SPDX-License-Identifier: Apache-2.0
24 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
35
@@ -31,7 +33,7 @@ TEXT _pthread_create(SB), NOSPLIT, $0-0
3133 JMP purego_pthread_create(SB)
3234 RET
3335
34-TEXT _pthread_detach(SB), NOSPLIT, $0-12
36+TEXT _pthread_detach(SB), NOSPLIT, $0-0
3537 JMP purego_pthread_detach(SB)
3638 RET
3739
@@ -47,14 +49,14 @@ TEXT _pthread_attr_destroy(SB), NOSPLIT, $0-0
4749 JMP purego_pthread_attr_destroy(SB)
4850 RET
4951
50-TEXT _abort(SB), NOSPLIT, $0-0
51- JMP purego_abort(SB)
52+TEXT _sigfillset(SB), NOSPLIT, $0-0
53+ JMP purego_sigfillset(SB)
5254 RET
5355
5456 TEXT _nanosleep(SB), NOSPLIT, $0-0
5557 JMP purego_nanosleep(SB)
5658 RET
5759
58-TEXT _sigfillset(SB), NOSPLIT, $0-12
59- CALL purego_sigfillset(SB)
60+TEXT _abort(SB), NOSPLIT, $0-0
61+ JMP purego_abort(SB)
6062 RET
@@ -1,3 +1,5 @@
1+// Code generated by 'go generate' with gen.go. DO NOT EDIT.
2+
1 // SPDX-License-Identifier: Apache-2.03 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors4 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 5
@@ -31,7 +33,7 @@ TEXT _pthread_create(SB), NOSPLIT, $0-0
31 JMP purego_pthread_create(SB)33 JMP purego_pthread_create(SB)
32 RET34 RET
33 35
34-TEXT _pthread_detach(SB), NOSPLIT, $0-1236+TEXT _pthread_detach(SB), NOSPLIT, $0-0
35 JMP purego_pthread_detach(SB)37 JMP purego_pthread_detach(SB)
36 RET38 RET
37 39
@@ -47,14 +49,14 @@ TEXT _pthread_attr_destroy(SB), NOSPLIT, $0-0
47 JMP purego_pthread_attr_destroy(SB)49 JMP purego_pthread_attr_destroy(SB)
48 RET50 RET
49 51
50-TEXT _abort(SB), NOSPLIT, $0-052+TEXT _sigfillset(SB), NOSPLIT, $0-0
51- JMP purego_abort(SB)53+ JMP purego_sigfillset(SB)
52 RET54 RET
53 55
54 TEXT _nanosleep(SB), NOSPLIT, $0-056 TEXT _nanosleep(SB), NOSPLIT, $0-0
55 JMP purego_nanosleep(SB)57 JMP purego_nanosleep(SB)
56 RET58 RET
57 59
58-TEXT _sigfillset(SB), NOSPLIT, $0-1260+TEXT _abort(SB), NOSPLIT, $0-0
59- CALL purego_sigfillset(SB)61+ JMP purego_abort(SB)
60 RET62 RET

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