detached 09060e5

Simplify assembly (#47)

using go:linkname and a generalized call5 trampoline function
it is possible to remove a lot of assembly and make the code more portable.
commit
09060e5358a96b293d8cd3787bac82a86a5a30b9
author
TotallyGamerJet · · 2022-09-28 12:56 UTC
committer
GitHub · · 2022-09-28 12:56 UTC
parent
aa1b0f6
signature
GPG Unverified4AEE18F83AFDEB23 The key is unknown
6 files · +191 -199
M dlfcn.go +19 -4
@@ -84,7 +84,22 @@ func Dlclose(handle uintptr) bool {
8484 }
8585
8686 // these functions exist in dlfcn_stubs.s and are calling C functions linked to in dlfcn_GOOS.go
87-var dlopenABI0 uintptr
88-var dlsymABI0 uintptr
89-var dlcloseABI0 uintptr
90-var dlerrorABI0 uintptr
87+// the indirection is necessary because a function is actually a pointer to the pointer to the code.
88+// sadly, I do not know of anyway to remove the assembly stubs entirely because //go:linkname doesn't
89+// appear to work if you link directly to the C function on darwin arm64.
90+
91+//go:linkname dlopen dlopen
92+var dlopen uintptr
93+var dlopenABI0 = uintptr(unsafe.Pointer(&dlopen))
94+
95+//go:linkname dlsym dlsym
96+var dlsym uintptr
97+var dlsymABI0 = uintptr(unsafe.Pointer(&dlsym))
98+
99+//go:linkname dlclose dlclose
100+var dlclose uintptr
101+var dlcloseABI0 = uintptr(unsafe.Pointer(&dlclose))
102+
103+//go:linkname dlerror dlerror
104+var dlerror uintptr
105+var dlerrorABI0 = uintptr(unsafe.Pointer(&dlerror))
@@ -84,7 +84,22 @@ func Dlclose(handle uintptr) bool {
84 }84 }
85 85
86 // these functions exist in dlfcn_stubs.s and are calling C functions linked to in dlfcn_GOOS.go86 // these functions exist in dlfcn_stubs.s and are calling C functions linked to in dlfcn_GOOS.go
87-var dlopenABI0 uintptr87+// the indirection is necessary because a function is actually a pointer to the pointer to the code.
88-var dlsymABI0 uintptr88+// sadly, I do not know of anyway to remove the assembly stubs entirely because //go:linkname doesn't
89-var dlcloseABI0 uintptr89+// appear to work if you link directly to the C function on darwin arm64.
90-var dlerrorABI0 uintptr90+
91+//go:linkname dlopen dlopen
92+var dlopen uintptr
93+var dlopenABI0 = uintptr(unsafe.Pointer(&dlopen))
94+
95+//go:linkname dlsym dlsym
96+var dlsym uintptr
97+var dlsymABI0 = uintptr(unsafe.Pointer(&dlsym))
98+
99+//go:linkname dlclose dlclose
100+var dlclose uintptr
101+var dlcloseABI0 = uintptr(unsafe.Pointer(&dlclose))
102+
103+//go:linkname dlerror dlerror
104+var dlerror uintptr
105+var dlerrorABI0 = uintptr(unsafe.Pointer(&dlerror))
M dlfcn_stubs.s +0 -8
@@ -7,29 +7,21 @@
77 #include "textflag.h"
88
99 // func dlopen(path *byte, mode int) (ret uintptr)
10-GLOBL ·dlopenABI0(SB), NOPTR|RODATA, $8
11-DATA ·dlopenABI0(SB)/8, $dlopen(SB)
1210 TEXT dlopen(SB), NOSPLIT, $0-0
1311 JMP _dlopen(SB)
1412 RET
1513
1614 // func dlsym(handle uintptr, symbol *byte) (ret uintptr)
17-GLOBL ·dlsymABI0(SB), NOPTR|RODATA, $8
18-DATA ·dlsymABI0(SB)/8, $dlsym(SB)
1915 TEXT dlsym(SB), NOSPLIT, $0-0
2016 JMP _dlsym(SB)
2117 RET
2218
2319 // func dlerror() (ret *byte)
24-GLOBL ·dlerrorABI0(SB), NOPTR|RODATA, $8
25-DATA ·dlerrorABI0(SB)/8, $dlerror(SB)
2620 TEXT dlerror(SB), NOSPLIT, $0-0
2721 JMP _dlerror(SB)
2822 RET
2923
3024 // func dlclose(handle uintptr) (ret int)
31-GLOBL ·dlcloseABI0(SB), NOPTR|RODATA, $8
32-DATA ·dlcloseABI0(SB)/8, $dlclose(SB)
3325 TEXT dlclose(SB), NOSPLIT, $0-0
3426 JMP _dlclose(SB)
3527 RET
@@ -7,29 +7,21 @@
7 #include "textflag.h"7 #include "textflag.h"
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
11-DATA ·dlopenABI0(SB)/8, $dlopen(SB)
12 TEXT dlopen(SB), NOSPLIT, $0-010 TEXT dlopen(SB), NOSPLIT, $0-0
13 JMP _dlopen(SB)11 JMP _dlopen(SB)
14 RET12 RET
15 13
16 // func dlsym(handle uintptr, symbol *byte) (ret uintptr)14 // func dlsym(handle uintptr, symbol *byte) (ret uintptr)
17-GLOBL ·dlsymABI0(SB), NOPTR|RODATA, $8
18-DATA ·dlsymABI0(SB)/8, $dlsym(SB)
19 TEXT dlsym(SB), NOSPLIT, $0-015 TEXT dlsym(SB), NOSPLIT, $0-0
20 JMP _dlsym(SB)16 JMP _dlsym(SB)
21 RET17 RET
22 18
23 // func dlerror() (ret *byte)19 // func dlerror() (ret *byte)
24-GLOBL ·dlerrorABI0(SB), NOPTR|RODATA, $8
25-DATA ·dlerrorABI0(SB)/8, $dlerror(SB)
26 TEXT dlerror(SB), NOSPLIT, $0-020 TEXT dlerror(SB), NOSPLIT, $0-0
27 JMP _dlerror(SB)21 JMP _dlerror(SB)
28 RET22 RET
29 23
30 // func dlclose(handle uintptr) (ret int)24 // func dlclose(handle uintptr) (ret int)
31-GLOBL ·dlcloseABI0(SB), NOPTR|RODATA, $8
32-DATA ·dlcloseABI0(SB)/8, $dlclose(SB)
33 TEXT dlclose(SB), NOSPLIT, $0-025 TEXT dlclose(SB), NOSPLIT, $0-0
34 JMP _dlclose(SB)26 JMP _dlclose(SB)
35 RET27 RET
M internal/fakecgo/symbols.go +96 -23
@@ -8,44 +8,117 @@ package fakecgo
88
99 import "unsafe"
1010
11+// setg_trampoline calls setg with the G provided
1112 func setg_trampoline(setg uintptr, G uintptr)
1213
1314 //go:linkname memmove runtime.memmove
1415 func memmove(to, from unsafe.Pointer, n uintptr)
1516
16-func malloc(size uintptr) unsafe.Pointer
17+// call5 takes fn the C function and 5 arguments and calls the function with those arguments
18+func call5(fn, a1, a2, a3, a4, a5 uintptr) uintptr
1719
18-func free(ptr unsafe.Pointer)
20+func malloc(size uintptr) unsafe.Pointer {
21+ ret := call5(mallocABI0, size, 0, 0, 0, 0)
22+ // this indirection is to avoid go vet complaining about possible misuse of unsafe.Pointer
23+ return *(*unsafe.Pointer)(unsafe.Pointer(&ret))
24+}
1925
20-func setenv(name *byte, value *byte, overwrite int32) int32
26+func free(ptr unsafe.Pointer) {
27+ call5(freeABI0, uintptr(ptr), 0, 0, 0, 0)
28+}
2129
22-func unsetenv(name *byte) int32
30+func setenv(name *byte, value *byte, overwrite int32) int32 {
31+ return int32(call5(setenvABI0, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(value)), uintptr(overwrite), 0, 0))
32+}
2333
24-// the no escape comments are needed inorder to ensure Go doesn't try
25-// and create a new object in the runtime when the runtime isn't available.
26-// After all, we are pretending to be C code.
34+func unsetenv(name *byte) int32 {
35+ return int32(call5(unsetenvABI0, uintptr(unsafe.Pointer(name)), 0, 0, 0, 0))
36+}
2737
28-//go:noescape
29-func pthread_attr_init(attr *pthread_attr_t) int32
38+func pthread_attr_init(attr *pthread_attr_t) int32 {
39+ return int32(call5(pthread_attr_initABI0, uintptr(unsafe.Pointer(attr)), 0, 0, 0, 0))
40+}
3041
31-//go:noescape
32-func pthread_create(thread *pthread_t, attr *pthread_attr_t, start, arg unsafe.Pointer) int32
42+func pthread_create(thread *pthread_t, attr *pthread_attr_t, start, arg unsafe.Pointer) int32 {
43+ return int32(call5(pthread_createABI0, uintptr(unsafe.Pointer(thread)), uintptr(unsafe.Pointer(attr)), uintptr(start), uintptr(arg), 0))
44+}
3345
34-func pthread_detach(thread pthread_t) int32
46+func pthread_detach(thread pthread_t) int32 {
47+ return int32(call5(pthread_detachABI0, uintptr(thread), 0, 0, 0, 0))
48+}
3549
36-//go:noescape
37-func pthread_sigmask(how sighow, ign *sigset_t, oset *sigset_t) int32
50+func pthread_sigmask(how sighow, ign *sigset_t, oset *sigset_t) int32 {
51+ return int32(call5(pthread_sigmaskABI0, uintptr(how), uintptr(unsafe.Pointer(ign)), uintptr(unsafe.Pointer(oset)), 0, 0))
52+}
3853
39-//go:noescape
40-func pthread_attr_getstacksize(attr *pthread_attr_t, stacksize *size_t) int32
54+func pthread_attr_getstacksize(attr *pthread_attr_t, stacksize *size_t) int32 {
55+ return int32(call5(pthread_attr_getstacksizeABI0, uintptr(unsafe.Pointer(attr)), uintptr(unsafe.Pointer(stacksize)), 0, 0, 0))
56+}
4157
42-//go:noescape
43-func pthread_attr_destroy(attr *pthread_attr_t) int32
58+func pthread_attr_destroy(attr *pthread_attr_t) int32 {
59+ return int32(call5(pthread_attr_destroyABI0, uintptr(unsafe.Pointer(attr)), 0, 0, 0, 0))
60+}
4461
45-func abort()
62+func sigfillset(set *sigset_t) int32 {
63+ return int32(call5(sigfillsetABI0, uintptr(unsafe.Pointer(set)), 0, 0, 0, 0))
64+}
4665
47-//go:noescape
48-func sigfillset(set *sigset_t) int32
66+func nanosleep(ts *timespec, rem *timespec) int32 {
67+ return int32(call5(nanosleepABI0, uintptr(unsafe.Pointer(ts)), uintptr(unsafe.Pointer(rem)), 0, 0, 0))
68+}
4969
50-//go:noescape
51-func nanosleep(ts *timespec, rem *timespec) int32
70+func abort() {
71+ call5(abortABI0, 0, 0, 0, 0, 0)
72+}
73+
74+//go:linkname _malloc _malloc
75+var _malloc uintptr
76+var mallocABI0 = uintptr(unsafe.Pointer(&_malloc))
77+
78+//go:linkname _free _free
79+var _free uintptr
80+var freeABI0 = uintptr(unsafe.Pointer(&_free))
81+
82+//go:linkname _setenv _setenv
83+var _setenv uintptr
84+var setenvABI0 = uintptr(unsafe.Pointer(&_setenv))
85+
86+//go:linkname _unsetenv _unsetenv
87+var _unsetenv uintptr
88+var unsetenvABI0 = uintptr(unsafe.Pointer(&_unsetenv))
89+
90+//go:linkname _pthread_attr_init _pthread_attr_init
91+var _pthread_attr_init uintptr
92+var pthread_attr_initABI0 = uintptr(unsafe.Pointer(&_pthread_attr_init))
93+
94+//go:linkname _pthread_create _pthread_create
95+var _pthread_create uintptr
96+var pthread_createABI0 = uintptr(unsafe.Pointer(&_pthread_create))
97+
98+//go:linkname _pthread_detach _pthread_detach
99+var _pthread_detach uintptr
100+var pthread_detachABI0 = uintptr(unsafe.Pointer(&_pthread_detach))
101+
102+//go:linkname _pthread_sigmask _pthread_sigmask
103+var _pthread_sigmask uintptr
104+var pthread_sigmaskABI0 = uintptr(unsafe.Pointer(&_pthread_sigmask))
105+
106+//go:linkname _pthread_attr_getstacksize _pthread_attr_getstacksize
107+var _pthread_attr_getstacksize uintptr
108+var pthread_attr_getstacksizeABI0 = uintptr(unsafe.Pointer(&_pthread_attr_getstacksize))
109+
110+//go:linkname _pthread_attr_destroy _pthread_attr_destroy
111+var _pthread_attr_destroy uintptr
112+var pthread_attr_destroyABI0 = uintptr(unsafe.Pointer(&_pthread_attr_destroy))
113+
114+//go:linkname _sigfillset _sigfillset
115+var _sigfillset uintptr
116+var sigfillsetABI0 = uintptr(unsafe.Pointer(&_sigfillset))
117+
118+//go:linkname _nanosleep _nanosleep
119+var _nanosleep uintptr
120+var nanosleepABI0 = uintptr(unsafe.Pointer(&_nanosleep))
121+
122+//go:linkname _abort _abort
123+var _abort uintptr
124+var abortABI0 = uintptr(unsafe.Pointer(&_abort))
@@ -8,44 +8,117 @@ package fakecgo
8 8
9 import "unsafe"9 import "unsafe"
10 10
11+// setg_trampoline calls setg with the G provided
11 func setg_trampoline(setg uintptr, G uintptr)12 func setg_trampoline(setg uintptr, G uintptr)
12 13
13 //go:linkname memmove runtime.memmove14 //go:linkname memmove runtime.memmove
14 func memmove(to, from unsafe.Pointer, n uintptr)15 func memmove(to, from unsafe.Pointer, n uintptr)
15 16
16-func malloc(size uintptr) unsafe.Pointer17+// call5 takes fn the C function and 5 arguments and calls the function with those arguments
18+func call5(fn, a1, a2, a3, a4, a5 uintptr) uintptr
17 19
18-func free(ptr unsafe.Pointer)20+func malloc(size uintptr) unsafe.Pointer {
21+ ret := call5(mallocABI0, size, 0, 0, 0, 0)
22+ // this indirection is to avoid go vet complaining about possible misuse of unsafe.Pointer
23+ return *(*unsafe.Pointer)(unsafe.Pointer(&ret))
24+}
19 25
20-func setenv(name *byte, value *byte, overwrite int32) int3226+func free(ptr unsafe.Pointer) {
27+ call5(freeABI0, uintptr(ptr), 0, 0, 0, 0)
28+}
21 29
22-func unsetenv(name *byte) int3230+func setenv(name *byte, value *byte, overwrite int32) int32 {
31+ return int32(call5(setenvABI0, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(value)), uintptr(overwrite), 0, 0))
32+}
23 33
24-// the no escape comments are needed inorder to ensure Go doesn't try34+func unsetenv(name *byte) int32 {
25-// and create a new object in the runtime when the runtime isn't available.35+ return int32(call5(unsetenvABI0, uintptr(unsafe.Pointer(name)), 0, 0, 0, 0))
26-// After all, we are pretending to be C code.36+}
27 37
28-//go:noescape38+func pthread_attr_init(attr *pthread_attr_t) int32 {
29-func pthread_attr_init(attr *pthread_attr_t) int3239+ return int32(call5(pthread_attr_initABI0, uintptr(unsafe.Pointer(attr)), 0, 0, 0, 0))
40+}
30 41
31-//go:noescape42+func pthread_create(thread *pthread_t, attr *pthread_attr_t, start, arg unsafe.Pointer) int32 {
32-func pthread_create(thread *pthread_t, attr *pthread_attr_t, start, arg unsafe.Pointer) int3243+ return int32(call5(pthread_createABI0, uintptr(unsafe.Pointer(thread)), uintptr(unsafe.Pointer(attr)), uintptr(start), uintptr(arg), 0))
44+}
33 45
34-func pthread_detach(thread pthread_t) int3246+func pthread_detach(thread pthread_t) int32 {
47+ return int32(call5(pthread_detachABI0, uintptr(thread), 0, 0, 0, 0))
48+}
35 49
36-//go:noescape50+func pthread_sigmask(how sighow, ign *sigset_t, oset *sigset_t) int32 {
37-func pthread_sigmask(how sighow, ign *sigset_t, oset *sigset_t) int3251+ return int32(call5(pthread_sigmaskABI0, uintptr(how), uintptr(unsafe.Pointer(ign)), uintptr(unsafe.Pointer(oset)), 0, 0))
52+}
38 53
39-//go:noescape54+func pthread_attr_getstacksize(attr *pthread_attr_t, stacksize *size_t) int32 {
40-func pthread_attr_getstacksize(attr *pthread_attr_t, stacksize *size_t) int3255+ return int32(call5(pthread_attr_getstacksizeABI0, uintptr(unsafe.Pointer(attr)), uintptr(unsafe.Pointer(stacksize)), 0, 0, 0))
56+}
41 57
42-//go:noescape58+func pthread_attr_destroy(attr *pthread_attr_t) int32 {
43-func pthread_attr_destroy(attr *pthread_attr_t) int3259+ return int32(call5(pthread_attr_destroyABI0, uintptr(unsafe.Pointer(attr)), 0, 0, 0, 0))
60+}
44 61
45-func abort()62+func sigfillset(set *sigset_t) int32 {
63+ return int32(call5(sigfillsetABI0, uintptr(unsafe.Pointer(set)), 0, 0, 0, 0))
64+}
46 65
47-//go:noescape66+func nanosleep(ts *timespec, rem *timespec) int32 {
48-func sigfillset(set *sigset_t) int3267+ return int32(call5(nanosleepABI0, uintptr(unsafe.Pointer(ts)), uintptr(unsafe.Pointer(rem)), 0, 0, 0))
68+}
49 69
50-//go:noescape70+func abort() {
51-func nanosleep(ts *timespec, rem *timespec) int3271+ call5(abortABI0, 0, 0, 0, 0, 0)
72+}
73+
74+//go:linkname _malloc _malloc
75+var _malloc uintptr
76+var mallocABI0 = uintptr(unsafe.Pointer(&_malloc))
77+
78+//go:linkname _free _free
79+var _free uintptr
80+var freeABI0 = uintptr(unsafe.Pointer(&_free))
81+
82+//go:linkname _setenv _setenv
83+var _setenv uintptr
84+var setenvABI0 = uintptr(unsafe.Pointer(&_setenv))
85+
86+//go:linkname _unsetenv _unsetenv
87+var _unsetenv uintptr
88+var unsetenvABI0 = uintptr(unsafe.Pointer(&_unsetenv))
89+
90+//go:linkname _pthread_attr_init _pthread_attr_init
91+var _pthread_attr_init uintptr
92+var pthread_attr_initABI0 = uintptr(unsafe.Pointer(&_pthread_attr_init))
93+
94+//go:linkname _pthread_create _pthread_create
95+var _pthread_create uintptr
96+var pthread_createABI0 = uintptr(unsafe.Pointer(&_pthread_create))
97+
98+//go:linkname _pthread_detach _pthread_detach
99+var _pthread_detach uintptr
100+var pthread_detachABI0 = uintptr(unsafe.Pointer(&_pthread_detach))
101+
102+//go:linkname _pthread_sigmask _pthread_sigmask
103+var _pthread_sigmask uintptr
104+var pthread_sigmaskABI0 = uintptr(unsafe.Pointer(&_pthread_sigmask))
105+
106+//go:linkname _pthread_attr_getstacksize _pthread_attr_getstacksize
107+var _pthread_attr_getstacksize uintptr
108+var pthread_attr_getstacksizeABI0 = uintptr(unsafe.Pointer(&_pthread_attr_getstacksize))
109+
110+//go:linkname _pthread_attr_destroy _pthread_attr_destroy
111+var _pthread_attr_destroy uintptr
112+var pthread_attr_destroyABI0 = uintptr(unsafe.Pointer(&_pthread_attr_destroy))
113+
114+//go:linkname _sigfillset _sigfillset
115+var _sigfillset uintptr
116+var sigfillsetABI0 = uintptr(unsafe.Pointer(&_sigfillset))
117+
118+//go:linkname _nanosleep _nanosleep
119+var _nanosleep uintptr
120+var nanosleepABI0 = uintptr(unsafe.Pointer(&_nanosleep))
121+
122+//go:linkname _abort _abort
123+var _abort uintptr
124+var abortABI0 = uintptr(unsafe.Pointer(&_abort))
M internal/fakecgo/trampolines_amd64.s +9 -82
@@ -68,86 +68,13 @@ TEXT threadentry_trampoline(SB), NOSPLIT, $16
6868 MOVQ 8(SP), AX
6969 RET
7070
71-TEXT ·setenv(SB), NOSPLIT, $0-0
72- MOVQ name+0(FP), DI
73- MOVQ value+8(FP), SI
74- MOVL overwrite+16(FP), DX
75- CALL libc_setenv(SB)
76- MOVL AX, ret+24(FP)
77- RET
78-
79-TEXT ·unsetenv(SB), NOSPLIT, $0-0
80- MOVQ name+0(FP), DI
81- CALL libc_unsetenv(SB)
82- MOVL AX, ret+8(FP)
83- RET
84-
85-TEXT ·malloc(SB), NOSPLIT, $0-0
86- MOVQ size+0(FP), DI
87- CALL libc_malloc(SB)
88- MOVQ AX, ret+8(FP)
89- RET
90-
91-TEXT ·free(SB), NOSPLIT, $0-0
92- MOVQ ptr+0(FP), DI
93- CALL libc_free(SB)
94- RET
95-
96-TEXT ·pthread_attr_init(SB), NOSPLIT, $0-12
97- MOVQ attr+0(FP), DI
98- CALL libc_pthread_attr_init(SB)
99- MOVL AX, ret+8(FP)
100- RET
101-
102-TEXT ·pthread_detach(SB), NOSPLIT, $0-12
103- MOVQ thread+0(FP), DI
104- CALL libc_pthread_detach(SB)
105- MOVL AX, ret+8(FP)
106- RET
107-
108-TEXT ·pthread_create(SB), NOSPLIT, $0-36
109- MOVQ thread+0(FP), DI
110- MOVQ attr+8(FP), SI
111- MOVQ start+16(FP), DX
112- MOVQ arg+24(FP), CX
113- CALL libc_pthread_create(SB)
114- MOVL AX, ret+32(FP)
115- RET
116-
117-TEXT ·pthread_attr_destroy(SB), NOSPLIT, $0-0
118- MOVQ attr+0(FP), DI
119- CALL libc_pthread_attr_destroy(SB)
120- MOVL AX, ret+8(FP)
121- RET
122-
123-TEXT ·pthread_attr_getstacksize(SB), NOSPLIT, $0-0
124- MOVQ attr+0(FP), DI
125- MOVQ stacksize+8(FP), SI
126- CALL libc_pthread_attr_getstacksize(SB)
127- MOVL AX, ret+16(FP)
128- RET
129-
130-TEXT ·pthread_sigmask(SB), NOSPLIT, $0-0
131- MOVL how+0(FP), DI
132- MOVQ ign+8(FP), SI
133- MOVQ oset+16(FP), DX
134- CALL libc_pthread_sigmask(SB)
135- MOVL AX, ret+24(FP)
136- RET
137-
138-TEXT ·abort(SB), NOSPLIT, $0-0
139- CALL libc_abort(SB)
140- RET
141-
142-TEXT ·sigfillset(SB), NOSPLIT, $0-12
143- MOVQ set+0(FP), DI
144- CALL libc_sigfillset(SB)
145- MOVL AX, ret+8(FP)
146- RET
147-
148-TEXT ·nanosleep(SB), NOSPLIT, $0-20
149- MOVQ ts+0(FP), DI
150- MOVQ rem+8(FP), SI
151- CALL libc_nanosleep(SB)
152- MOVL AX, ret+16(FP)
71+TEXT ·call5(SB), NOSPLIT, $0-0
72+ MOVQ fn+0(FP), AX
73+ MOVQ a1+8(FP), DI
74+ MOVQ a2+16(FP), SI
75+ MOVQ a3+24(FP), DX
76+ MOVQ a4+32(FP), CX
77+ MOVQ a5+40(FP), R8
78+ CALL AX
79+ MOVQ AX, ret+48(FP)
15380 RET
@@ -68,86 +68,13 @@ TEXT threadentry_trampoline(SB), NOSPLIT, $16
68 MOVQ 8(SP), AX68 MOVQ 8(SP), AX
69 RET69 RET
70 70
71-TEXT ·setenv(SB), NOSPLIT, $0-071+TEXT ·call5(SB), NOSPLIT, $0-0
72- MOVQ name+0(FP), DI72+ MOVQ fn+0(FP), AX
73- MOVQ value+8(FP), SI73+ MOVQ a1+8(FP), DI
74- MOVL overwrite+16(FP), DX74+ MOVQ a2+16(FP), SI
75- CALL libc_setenv(SB)75+ MOVQ a3+24(FP), DX
76- MOVL AX, ret+24(FP)76+ MOVQ a4+32(FP), CX
77- RET77+ MOVQ a5+40(FP), R8
78-78+ CALL AX
79-TEXT ·unsetenv(SB), NOSPLIT, $0-079+ MOVQ AX, ret+48(FP)
80- MOVQ name+0(FP), DI
81- CALL libc_unsetenv(SB)
82- MOVL AX, ret+8(FP)
83- RET
84-
85-TEXT ·malloc(SB), NOSPLIT, $0-0
86- MOVQ size+0(FP), DI
87- CALL libc_malloc(SB)
88- MOVQ AX, ret+8(FP)
89- RET
90-
91-TEXT ·free(SB), NOSPLIT, $0-0
92- MOVQ ptr+0(FP), DI
93- CALL libc_free(SB)
94- RET
95-
96-TEXT ·pthread_attr_init(SB), NOSPLIT, $0-12
97- MOVQ attr+0(FP), DI
98- CALL libc_pthread_attr_init(SB)
99- MOVL AX, ret+8(FP)
100- RET
101-
102-TEXT ·pthread_detach(SB), NOSPLIT, $0-12
103- MOVQ thread+0(FP), DI
104- CALL libc_pthread_detach(SB)
105- MOVL AX, ret+8(FP)
106- RET
107-
108-TEXT ·pthread_create(SB), NOSPLIT, $0-36
109- MOVQ thread+0(FP), DI
110- MOVQ attr+8(FP), SI
111- MOVQ start+16(FP), DX
112- MOVQ arg+24(FP), CX
113- CALL libc_pthread_create(SB)
114- MOVL AX, ret+32(FP)
115- RET
116-
117-TEXT ·pthread_attr_destroy(SB), NOSPLIT, $0-0
118- MOVQ attr+0(FP), DI
119- CALL libc_pthread_attr_destroy(SB)
120- MOVL AX, ret+8(FP)
121- RET
122-
123-TEXT ·pthread_attr_getstacksize(SB), NOSPLIT, $0-0
124- MOVQ attr+0(FP), DI
125- MOVQ stacksize+8(FP), SI
126- CALL libc_pthread_attr_getstacksize(SB)
127- MOVL AX, ret+16(FP)
128- RET
129-
130-TEXT ·pthread_sigmask(SB), NOSPLIT, $0-0
131- MOVL how+0(FP), DI
132- MOVQ ign+8(FP), SI
133- MOVQ oset+16(FP), DX
134- CALL libc_pthread_sigmask(SB)
135- MOVL AX, ret+24(FP)
136- RET
137-
138-TEXT ·abort(SB), NOSPLIT, $0-0
139- CALL libc_abort(SB)
140- RET
141-
142-TEXT ·sigfillset(SB), NOSPLIT, $0-12
143- MOVQ set+0(FP), DI
144- CALL libc_sigfillset(SB)
145- MOVL AX, ret+8(FP)
146- RET
147-
148-TEXT ·nanosleep(SB), NOSPLIT, $0-20
149- MOVQ ts+0(FP), DI
150- MOVQ rem+8(FP), SI
151- CALL libc_nanosleep(SB)
152- MOVL AX, ret+16(FP)
153 RET80 RET
M internal/fakecgo/trampolines_arm64.s +9 -82
@@ -48,86 +48,13 @@ TEXT threadentry_trampoline(SB), NOSPLIT, $0-0
4848 MOVD $0, R0 // TODO: get the return value from threadentry
4949 RET
5050
51-TEXT ·setenv(SB), NOSPLIT, $0-0
52- MOVD name+0(FP), R0
53- MOVD value+8(FP), R1
54- MOVD overwrite+16(FP), R2
55- CALL libc_setenv(SB)
56- MOVD R0, ret+24(FP)
57- RET
58-
59-TEXT ·unsetenv(SB), NOSPLIT, $0-0
60- MOVD name+0(FP), R0
61- CALL libc_unsetenv(SB)
62- MOVD R0, ret+8(FP)
63- RET
64-
65-TEXT ·malloc(SB), NOSPLIT, $0-0
66- MOVD size+0(FP), R0
67- CALL libc_malloc(SB)
68- MOVD R0, ret+8(FP)
69- RET
70-
71-TEXT ·free(SB), NOSPLIT, $0-0
72- MOVD ptr+0(FP), R0
73- CALL libc_free(SB)
74- RET
75-
76-TEXT ·pthread_attr_init(SB), NOSPLIT, $0-12
77- MOVD attr+0(FP), R0
78- CALL libc_pthread_attr_init(SB)
79- MOVD R0, ret+8(FP)
80- RET
81-
82-TEXT ·pthread_detach(SB), NOSPLIT, $0-12
83- MOVD thread+0(FP), R0
84- CALL libc_pthread_detach(SB)
85- MOVD R0, ret+8(FP)
86- RET
87-
88-TEXT ·pthread_create(SB), NOSPLIT, $0-36
89- MOVD thread+0(FP), R0
90- MOVD attr+8(FP), R1
91- MOVD start+16(FP), R2
92- MOVD arg+24(FP), R3
93- CALL libc_pthread_create(SB)
94- MOVD R0, ret+32(FP)
95- RET
96-
97-TEXT ·pthread_attr_destroy(SB), NOSPLIT, $0-0
98- MOVD attr+0(FP), R0
99- CALL libc_pthread_attr_destroy(SB)
100- MOVD R0, ret+8(FP)
101- RET
102-
103-TEXT ·pthread_attr_getstacksize(SB), NOSPLIT, $0-0
104- MOVD attr+0(FP), R0
105- MOVD stacksize+8(FP), R1
106- CALL libc_pthread_attr_getstacksize(SB)
107- MOVD R0, ret+16(FP)
108- RET
109-
110-TEXT ·pthread_sigmask(SB), NOSPLIT, $0-0
111- MOVD how+0(FP), R0
112- MOVD ign+8(FP), R1
113- MOVD oset+16(FP), R2
114- CALL libc_pthread_sigmask(SB)
115- MOVD R0, ret+24(FP)
116- RET
117-
118-TEXT ·abort(SB), NOSPLIT, $0-0
119- CALL libc_abort(SB)
120- RET
121-
122-TEXT ·sigfillset(SB), NOSPLIT, $0-12
123- MOVD set+0(FP), R0
124- CALL libc_sigfillset(SB)
125- MOVD R0, ret+8(FP)
126- RET
127-
128-TEXT ·nanosleep(SB), NOSPLIT, $0-20
129- MOVD ts+0(FP), R0
130- MOVD rem+8(FP), R1
131- CALL libc_nanosleep(SB)
132- MOVD R0, ret+16(FP)
51+TEXT ·call5(SB), NOSPLIT, $0-0
52+ MOVD fn+0(FP), R6
53+ MOVD a1+8(FP), R0
54+ MOVD a2+16(FP), R1
55+ MOVD a3+24(FP), R2
56+ MOVD a4+32(FP), R3
57+ MOVD a5+40(FP), R4
58+ CALL R6
59+ MOVD R0, ret+48(FP)
13360 RET
@@ -48,86 +48,13 @@ TEXT threadentry_trampoline(SB), NOSPLIT, $0-0
48 MOVD $0, R0 // TODO: get the return value from threadentry48 MOVD $0, R0 // TODO: get the return value from threadentry
49 RET49 RET
50 50
51-TEXT ·setenv(SB), NOSPLIT, $0-051+TEXT ·call5(SB), NOSPLIT, $0-0
52- MOVD name+0(FP), R052+ MOVD fn+0(FP), R6
53- MOVD value+8(FP), R153+ MOVD a1+8(FP), R0
54- MOVD overwrite+16(FP), R254+ MOVD a2+16(FP), R1
55- CALL libc_setenv(SB)55+ MOVD a3+24(FP), R2
56- MOVD R0, ret+24(FP)56+ MOVD a4+32(FP), R3
57- RET57+ MOVD a5+40(FP), R4
58-58+ CALL R6
59-TEXT ·unsetenv(SB), NOSPLIT, $0-059+ MOVD R0, ret+48(FP)
60- MOVD name+0(FP), R0
61- CALL libc_unsetenv(SB)
62- MOVD R0, ret+8(FP)
63- RET
64-
65-TEXT ·malloc(SB), NOSPLIT, $0-0
66- MOVD size+0(FP), R0
67- CALL libc_malloc(SB)
68- MOVD R0, ret+8(FP)
69- RET
70-
71-TEXT ·free(SB), NOSPLIT, $0-0
72- MOVD ptr+0(FP), R0
73- CALL libc_free(SB)
74- RET
75-
76-TEXT ·pthread_attr_init(SB), NOSPLIT, $0-12
77- MOVD attr+0(FP), R0
78- CALL libc_pthread_attr_init(SB)
79- MOVD R0, ret+8(FP)
80- RET
81-
82-TEXT ·pthread_detach(SB), NOSPLIT, $0-12
83- MOVD thread+0(FP), R0
84- CALL libc_pthread_detach(SB)
85- MOVD R0, ret+8(FP)
86- RET
87-
88-TEXT ·pthread_create(SB), NOSPLIT, $0-36
89- MOVD thread+0(FP), R0
90- MOVD attr+8(FP), R1
91- MOVD start+16(FP), R2
92- MOVD arg+24(FP), R3
93- CALL libc_pthread_create(SB)
94- MOVD R0, ret+32(FP)
95- RET
96-
97-TEXT ·pthread_attr_destroy(SB), NOSPLIT, $0-0
98- MOVD attr+0(FP), R0
99- CALL libc_pthread_attr_destroy(SB)
100- MOVD R0, ret+8(FP)
101- RET
102-
103-TEXT ·pthread_attr_getstacksize(SB), NOSPLIT, $0-0
104- MOVD attr+0(FP), R0
105- MOVD stacksize+8(FP), R1
106- CALL libc_pthread_attr_getstacksize(SB)
107- MOVD R0, ret+16(FP)
108- RET
109-
110-TEXT ·pthread_sigmask(SB), NOSPLIT, $0-0
111- MOVD how+0(FP), R0
112- MOVD ign+8(FP), R1
113- MOVD oset+16(FP), R2
114- CALL libc_pthread_sigmask(SB)
115- MOVD R0, ret+24(FP)
116- RET
117-
118-TEXT ·abort(SB), NOSPLIT, $0-0
119- CALL libc_abort(SB)
120- RET
121-
122-TEXT ·sigfillset(SB), NOSPLIT, $0-12
123- MOVD set+0(FP), R0
124- CALL libc_sigfillset(SB)
125- MOVD R0, ret+8(FP)
126- RET
127-
128-TEXT ·nanosleep(SB), NOSPLIT, $0-20
129- MOVD ts+0(FP), R0
130- MOVD rem+8(FP), R1
131- CALL libc_nanosleep(SB)
132- MOVD R0, ret+16(FP)
133 RET60 RET
A internal/fakecgo/trampolines_stubs_darwin.s +58 -0
@@ -0,0 +1,58 @@
1+// SPDX-License-Identifier: Apache-2.0
2+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3+
4+#include "textflag.h"
5+
6+// these stubs are here because it is not possible to go:linkname directly the C functions on darwin arm64
7+
8+TEXT _malloc(SB), NOSPLIT, $0-0
9+ JMP libc_malloc(SB)
10+ RET
11+
12+TEXT _free(SB), NOSPLIT, $0-0
13+ JMP libc_free(SB)
14+ RET
15+
16+TEXT _setenv(SB), NOSPLIT, $0-0
17+ JMP libc_setenv(SB)
18+ RET
19+
20+TEXT _unsetenv(SB), NOSPLIT, $0-0
21+ JMP libc_unsetenv(SB)
22+ RET
23+
24+TEXT _pthread_attr_init(SB), NOSPLIT, $0-0
25+ JMP libc_pthread_attr_init(SB)
26+ RET
27+
28+TEXT _pthread_create(SB), NOSPLIT, $0-0
29+ JMP libc_pthread_create(SB)
30+ RET
31+
32+TEXT _pthread_detach(SB), NOSPLIT, $0-12
33+ JMP libc_pthread_detach(SB)
34+ RET
35+
36+TEXT _pthread_sigmask(SB), NOSPLIT, $0-0
37+ JMP libc_pthread_sigmask(SB)
38+ RET
39+
40+TEXT _pthread_attr_getstacksize(SB), NOSPLIT, $0-0
41+ JMP libc_pthread_attr_getstacksize(SB)
42+ RET
43+
44+TEXT _pthread_attr_destroy(SB), NOSPLIT, $0-0
45+ JMP libc_pthread_attr_destroy(SB)
46+ RET
47+
48+TEXT _abort(SB), NOSPLIT, $0-0
49+ JMP libc_abort(SB)
50+ RET
51+
52+TEXT _nanosleep(SB), NOSPLIT, $0-0
53+ JMP libc_nanosleep(SB)
54+ RET
55+
56+TEXT _sigfillset(SB), NOSPLIT, $0-12
57+ CALL libc_sigfillset(SB)
58+ RET
@@ -0,0 +1,58 @@
1+// SPDX-License-Identifier: Apache-2.0
2+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3+
4+#include "textflag.h"
5+
6+// these stubs are here because it is not possible to go:linkname directly the C functions on darwin arm64
7+
8+TEXT _malloc(SB), NOSPLIT, $0-0
9+ JMP libc_malloc(SB)
10+ RET
11+
12+TEXT _free(SB), NOSPLIT, $0-0
13+ JMP libc_free(SB)
14+ RET
15+
16+TEXT _setenv(SB), NOSPLIT, $0-0
17+ JMP libc_setenv(SB)
18+ RET
19+
20+TEXT _unsetenv(SB), NOSPLIT, $0-0
21+ JMP libc_unsetenv(SB)
22+ RET
23+
24+TEXT _pthread_attr_init(SB), NOSPLIT, $0-0
25+ JMP libc_pthread_attr_init(SB)
26+ RET
27+
28+TEXT _pthread_create(SB), NOSPLIT, $0-0
29+ JMP libc_pthread_create(SB)
30+ RET
31+
32+TEXT _pthread_detach(SB), NOSPLIT, $0-12
33+ JMP libc_pthread_detach(SB)
34+ RET
35+
36+TEXT _pthread_sigmask(SB), NOSPLIT, $0-0
37+ JMP libc_pthread_sigmask(SB)
38+ RET
39+
40+TEXT _pthread_attr_getstacksize(SB), NOSPLIT, $0-0
41+ JMP libc_pthread_attr_getstacksize(SB)
42+ RET
43+
44+TEXT _pthread_attr_destroy(SB), NOSPLIT, $0-0
45+ JMP libc_pthread_attr_destroy(SB)
46+ RET
47+
48+TEXT _abort(SB), NOSPLIT, $0-0
49+ JMP libc_abort(SB)
50+ RET
51+
52+TEXT _nanosleep(SB), NOSPLIT, $0-0
53+ JMP libc_nanosleep(SB)
54+ RET
55+
56+TEXT _sigfillset(SB), NOSPLIT, $0-12
57+ CALL libc_sigfillset(SB)
58+ 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