internal/fakecgo: circumvent Go 1.20's race code (#73)
Go 1.20 rewrote the race detector on darwin to be entirely Go. This means that fakecgo had race functions placed inside of it which made it break. This PR circumvents the race functions by adding //go:norace and using closures to call the ABIInternal ABIWrapper which does not have the race instrumentation. Closes #71
- commit
- fcdb0240d06c471170813a06ef8f9c00df24e108
- author
- TotallyGamerJet · · 2022-12-02 03:15 UTC
- committer
- Hajime Hoshi · · 2022-12-02 15:58 UTC
- parent
- 7ec80ca
- signature
- unsigned
9 files · +73 -19
M example/main.go +11 -1
| @@ -6,9 +6,19 @@ | |||
| 6 | 6 | package main | |
| 7 | 7 | ||
| 8 | 8 | import ( | |
| 9 | + | "os" | |
| 10 | + | ||
| 9 | 11 | _ "github.com/ebitengine/purego" | |
| 10 | 12 | ) | |
| 11 | 13 | ||
| 12 | 14 | func main() { | |
| 13 | - | // TODO: Add an implementation. This example exists only for testing so far. | |
| 15 | + | // set and unset an environment variable since this calls into fakecgo. | |
| 16 | + | err := os.Setenv("TESTING", "SOMETHING") | |
| 17 | + | if err != nil { | |
| 18 | + | panic(err) | |
| 19 | + | } | |
| 20 | + | err = os.Unsetenv("TESTING") | |
| 21 | + | if err != nil { | |
| 22 | + | panic(err) | |
| 23 | + | } | |
| 14 | 24 | } | |
| @@ -6,9 +6,19 @@ | |||||
| 6 | package main | 6 | package main | ||
| 7 | 7 | ||||
| 8 | import ( | 8 | import ( | ||
| 9 | + | "os" | |||
| 10 | + | ||||
| 9 | _ "github.com/ebitengine/purego" | 11 | _ "github.com/ebitengine/purego" | ||
| 10 | ) | 12 | ) | ||
| 11 | 13 | ||||
| 12 | func main() { | 14 | func main() { | ||
| 13 | - | // TODO: Add an implementation. This example exists only for testing so far. | 15 | + | // set and unset an environment variable since this calls into fakecgo. |
| 16 | + | err := os.Setenv("TESTING", "SOMETHING") | |||
| 17 | + | if err != nil { | |||
| 18 | + | panic(err) | |||
| 19 | + | } | |||
| 20 | + | err = os.Unsetenv("TESTING") | |||
| 21 | + | if err != nil { | |||
| 22 | + | panic(err) | |||
| 23 | + | } | |||
| 14 | } | 24 | } | ||
M internal/fakecgo/callbacks.go +15 -0
| @@ -41,3 +41,18 @@ var _cgo_notify_runtime_init_done = &x_cgo_notify_runtime_init_done_trampoline | |||
| 41 | 41 | ||
| 42 | 42 | // TODO: decide if we need x_cgo_set_context_function | |
| 43 | 43 | // TODO: decide if we need _cgo_yield | |
| 44 | + | ||
| 45 | + | var ( | |
| 46 | + | // In Go 1.20 the race detector was rewritten to pure Go | |
| 47 | + | // on darwin. This means that when CGO_ENABLED=0 is set | |
| 48 | + | // fakecgo is built with race detector code. This is not | |
| 49 | + | // good since this code is pretending to be C. The | |
| 50 | + | // go:norace comments are not enough since the ABI wrappers | |
| 51 | + | // still have race code. These variables will circumvent | |
| 52 | + | // that issue by calling the function directly. | |
| 53 | + | threadentry_call = threadentry | |
| 54 | + | x_cgo_init_call = x_cgo_init | |
| 55 | + | x_cgo_setenv_call = x_cgo_setenv | |
| 56 | + | x_cgo_unsetenv_call = x_cgo_unsetenv | |
| 57 | + | x_cgo_thread_start_call = x_cgo_thread_start | |
| 58 | + | ) | |
| @@ -41,3 +41,18 @@ var _cgo_notify_runtime_init_done = &x_cgo_notify_runtime_init_done_trampoline | |||||
| 41 | 41 | ||||
| 42 | // TODO: decide if we need x_cgo_set_context_function | 42 | // TODO: decide if we need x_cgo_set_context_function | ||
| 43 | // TODO: decide if we need _cgo_yield | 43 | // TODO: decide if we need _cgo_yield | ||
| 44 | + | ||||
| 45 | + | var ( | |||
| 46 | + | // In Go 1.20 the race detector was rewritten to pure Go | |||
| 47 | + | // on darwin. This means that when CGO_ENABLED=0 is set | |||
| 48 | + | // fakecgo is built with race detector code. This is not | |||
| 49 | + | // good since this code is pretending to be C. The | |||
| 50 | + | // go:norace comments are not enough since the ABI wrappers | |||
| 51 | + | // still have race code. These variables will circumvent | |||
| 52 | + | // that issue by calling the function directly. | |||
| 53 | + | threadentry_call = threadentry | |||
| 54 | + | x_cgo_init_call = x_cgo_init | |||
| 55 | + | x_cgo_setenv_call = x_cgo_setenv | |||
| 56 | + | x_cgo_unsetenv_call = x_cgo_unsetenv | |||
| 57 | + | x_cgo_thread_start_call = x_cgo_thread_start | |||
| 58 | + | ) | |||
M internal/fakecgo/go_darwin_amd64.go +3 -0
| @@ -7,6 +7,7 @@ package fakecgo | |||
| 7 | 7 | import "unsafe" | |
| 8 | 8 | ||
| 9 | 9 | //go:nosplit | |
| 10 | + | //go:norace | |
| 10 | 11 | func _cgo_sys_thread_start(ts *ThreadStart) { | |
| 11 | 12 | var attr pthread_attr_t | |
| 12 | 13 | var ign, oset sigset_t | |
| @@ -41,6 +42,7 @@ var x_threadentry_trampoline byte | |||
| 41 | 42 | var threadentry_trampolineABI0 = &x_threadentry_trampoline | |
| 42 | 43 | ||
| 43 | 44 | //go:nosplit | |
| 45 | + | //go:norace | |
| 44 | 46 | func threadentry(v unsafe.Pointer) unsafe.Pointer { | |
| 45 | 47 | ts := *(*ThreadStart)(v) | |
| 46 | 48 | free(v) | |
| @@ -58,6 +60,7 @@ func threadentry(v unsafe.Pointer) unsafe.Pointer { | |||
| 58 | 60 | var setg_func uintptr | |
| 59 | 61 | ||
| 60 | 62 | //go:nosplit | |
| 63 | + | //go:norace | |
| 61 | 64 | func x_cgo_init(g *G, setg uintptr) { | |
| 62 | 65 | var size size_t | |
| 63 | 66 | var attr pthread_attr_t | |
| @@ -7,6 +7,7 @@ package fakecgo | |||||
| 7 | import "unsafe" | 7 | import "unsafe" | ||
| 8 | 8 | ||||
| 9 | //go:nosplit | 9 | //go:nosplit | ||
| 10 | + | //go:norace | |||
| 10 | func _cgo_sys_thread_start(ts *ThreadStart) { | 11 | func _cgo_sys_thread_start(ts *ThreadStart) { | ||
| 11 | var attr pthread_attr_t | 12 | var attr pthread_attr_t | ||
| 12 | var ign, oset sigset_t | 13 | var ign, oset sigset_t | ||
| @@ -41,6 +42,7 @@ var x_threadentry_trampoline byte | |||||
| 41 | var threadentry_trampolineABI0 = &x_threadentry_trampoline | 42 | var threadentry_trampolineABI0 = &x_threadentry_trampoline | ||
| 42 | 43 | ||||
| 43 | //go:nosplit | 44 | //go:nosplit | ||
| 45 | + | //go:norace | |||
| 44 | func threadentry(v unsafe.Pointer) unsafe.Pointer { | 46 | func threadentry(v unsafe.Pointer) unsafe.Pointer { | ||
| 45 | ts := *(*ThreadStart)(v) | 47 | ts := *(*ThreadStart)(v) | ||
| 46 | free(v) | 48 | free(v) | ||
| @@ -58,6 +60,7 @@ func threadentry(v unsafe.Pointer) unsafe.Pointer { | |||||
| 58 | var setg_func uintptr | 60 | var setg_func uintptr | ||
| 59 | 61 | ||||
| 60 | //go:nosplit | 62 | //go:nosplit | ||
| 63 | + | //go:norace | |||
| 61 | func x_cgo_init(g *G, setg uintptr) { | 64 | func x_cgo_init(g *G, setg uintptr) { | ||
| 62 | var size size_t | 65 | var size size_t | ||
| 63 | var attr pthread_attr_t | 66 | var attr pthread_attr_t | ||
M internal/fakecgo/go_darwin_arm64.go +3 -0
| @@ -7,6 +7,7 @@ package fakecgo | |||
| 7 | 7 | import "unsafe" | |
| 8 | 8 | ||
| 9 | 9 | //go:nosplit | |
| 10 | + | //go:norace | |
| 10 | 11 | func _cgo_sys_thread_start(ts *ThreadStart) { | |
| 11 | 12 | var attr pthread_attr_t | |
| 12 | 13 | var ign, oset sigset_t | |
| @@ -41,6 +42,7 @@ var x_threadentry_trampoline byte | |||
| 41 | 42 | var threadentry_trampolineABI0 = &x_threadentry_trampoline | |
| 42 | 43 | ||
| 43 | 44 | //go:nosplit | |
| 45 | + | //go:norace | |
| 44 | 46 | func threadentry(v unsafe.Pointer) unsafe.Pointer { | |
| 45 | 47 | ts := *(*ThreadStart)(v) | |
| 46 | 48 | free(v) | |
| @@ -67,6 +69,7 @@ var setg_func uintptr | |||
| 67 | 69 | // This function can't be go:systemstack since go is not in a state where the systemcheck would work. | |
| 68 | 70 | // | |
| 69 | 71 | //go:nosplit | |
| 72 | + | //go:norace | |
| 70 | 73 | func x_cgo_init(g *G, setg uintptr) { | |
| 71 | 74 | var size size_t | |
| 72 | 75 | var attr pthread_attr_t | |
| @@ -7,6 +7,7 @@ package fakecgo | |||||
| 7 | import "unsafe" | 7 | import "unsafe" | ||
| 8 | 8 | ||||
| 9 | //go:nosplit | 9 | //go:nosplit | ||
| 10 | + | //go:norace | |||
| 10 | func _cgo_sys_thread_start(ts *ThreadStart) { | 11 | func _cgo_sys_thread_start(ts *ThreadStart) { | ||
| 11 | var attr pthread_attr_t | 12 | var attr pthread_attr_t | ||
| 12 | var ign, oset sigset_t | 13 | var ign, oset sigset_t | ||
| @@ -41,6 +42,7 @@ var x_threadentry_trampoline byte | |||||
| 41 | var threadentry_trampolineABI0 = &x_threadentry_trampoline | 42 | var threadentry_trampolineABI0 = &x_threadentry_trampoline | ||
| 42 | 43 | ||||
| 43 | //go:nosplit | 44 | //go:nosplit | ||
| 45 | + | //go:norace | |||
| 44 | func threadentry(v unsafe.Pointer) unsafe.Pointer { | 46 | func threadentry(v unsafe.Pointer) unsafe.Pointer { | ||
| 45 | ts := *(*ThreadStart)(v) | 47 | ts := *(*ThreadStart)(v) | ||
| 46 | free(v) | 48 | free(v) | ||
| @@ -67,6 +69,7 @@ var setg_func uintptr | |||||
| 67 | // This function can't be go:systemstack since go is not in a state where the systemcheck would work. | 69 | // This function can't be go:systemstack since go is not in a state where the systemcheck would work. | ||
| 68 | // | 70 | // | ||
| 69 | //go:nosplit | 71 | //go:nosplit | ||
| 72 | + | //go:norace | |||
| 70 | func x_cgo_init(g *G, setg uintptr) { | 73 | func x_cgo_init(g *G, setg uintptr) { | ||
| 71 | var size size_t | 74 | var size size_t | ||
| 72 | var attr pthread_attr_t | 75 | var attr pthread_attr_t | ||
M internal/fakecgo/go_libinit.go +1 -0
| @@ -19,6 +19,7 @@ func x_cgo_notify_runtime_init_done() { | |||
| 19 | 19 | // EAGAIN. | |
| 20 | 20 | // | |
| 21 | 21 | //go:nosplit | |
| 22 | + | //go:norace | |
| 22 | 23 | func _cgo_try_pthread_create(thread *pthread_t, attr *pthread_attr_t, pfn unsafe.Pointer, arg *ThreadStart) int { | |
| 23 | 24 | var ts syscall.Timespec | |
| 24 | 25 | // tries needs to be the same type as syscall.Timespec.Nsec | |
| @@ -19,6 +19,7 @@ func x_cgo_notify_runtime_init_done() { | |||||
| 19 | // EAGAIN. | 19 | // EAGAIN. | ||
| 20 | // | 20 | // | ||
| 21 | //go:nosplit | 21 | //go:nosplit | ||
| 22 | + | //go:norace | |||
| 22 | func _cgo_try_pthread_create(thread *pthread_t, attr *pthread_attr_t, pfn unsafe.Pointer, arg *ThreadStart) int { | 23 | func _cgo_try_pthread_create(thread *pthread_t, attr *pthread_attr_t, pfn unsafe.Pointer, arg *ThreadStart) int { | ||
| 23 | var ts syscall.Timespec | 24 | var ts syscall.Timespec | ||
| 24 | // tries needs to be the same type as syscall.Timespec.Nsec | 25 | // tries needs to be the same type as syscall.Timespec.Nsec | ||
M internal/fakecgo/go_setenv.go +2 -0
| @@ -6,11 +6,13 @@ | |||
| 6 | 6 | package fakecgo | |
| 7 | 7 | ||
| 8 | 8 | //go:nosplit | |
| 9 | + | //go:norace | |
| 9 | 10 | func x_cgo_setenv(arg *[2]*byte) { | |
| 10 | 11 | setenv(arg[0], arg[1], 1) | |
| 11 | 12 | } | |
| 12 | 13 | ||
| 13 | 14 | //go:nosplit | |
| 15 | + | //go:norace | |
| 14 | 16 | func x_cgo_unsetenv(arg *[1]*byte) { | |
| 15 | 17 | unsetenv(arg[0]) | |
| 16 | 18 | } | |
| @@ -6,11 +6,13 @@ | |||||
| 6 | package fakecgo | 6 | package fakecgo | ||
| 7 | 7 | ||||
| 8 | //go:nosplit | 8 | //go:nosplit | ||
| 9 | + | //go:norace | |||
| 9 | func x_cgo_setenv(arg *[2]*byte) { | 10 | func x_cgo_setenv(arg *[2]*byte) { | ||
| 10 | setenv(arg[0], arg[1], 1) | 11 | setenv(arg[0], arg[1], 1) | ||
| 11 | } | 12 | } | ||
| 12 | 13 | ||||
| 13 | //go:nosplit | 14 | //go:nosplit | ||
| 15 | + | //go:norace | |||
| 14 | func x_cgo_unsetenv(arg *[1]*byte) { | 16 | func x_cgo_unsetenv(arg *[1]*byte) { | ||
| 15 | unsetenv(arg[0]) | 17 | unsetenv(arg[0]) | ||
| 16 | } | 18 | } | ||
M internal/fakecgo/go_util.go +1 -0
| @@ -16,6 +16,7 @@ import "unsafe" | |||
| 16 | 16 | // This function should be go:systemstack instead of go:nosplit (but that requires runtime) | |
| 17 | 17 | // | |
| 18 | 18 | //go:nosplit | |
| 19 | + | //go:norace | |
| 19 | 20 | func x_cgo_thread_start(arg *ThreadStart) { | |
| 20 | 21 | var ts *ThreadStart | |
| 21 | 22 | // Make our own copy that can persist after we return. | |
| @@ -16,6 +16,7 @@ import "unsafe" | |||||
| 16 | // This function should be go:systemstack instead of go:nosplit (but that requires runtime) | 16 | // This function should be go:systemstack instead of go:nosplit (but that requires runtime) | ||
| 17 | // | 17 | // | ||
| 18 | //go:nosplit | 18 | //go:nosplit | ||
| 19 | + | //go:norace | |||
| 19 | func x_cgo_thread_start(arg *ThreadStart) { | 20 | func x_cgo_thread_start(arg *ThreadStart) { | ||
| 20 | var ts *ThreadStart | 21 | var ts *ThreadStart | ||
| 21 | // Make our own copy that can persist after we return. | 22 | // Make our own copy that can persist after we return. | ||
M internal/fakecgo/trampolines_amd64.s +21 -12
| @@ -29,24 +29,32 @@ return value will be in AX | |||
| 29 | 29 | // these trampolines map the gcc ABI to Go ABI and then calls into the Go equivalent functions. | |
| 30 | 30 | ||
| 31 | 31 | TEXT x_cgo_init_trampoline(SB), NOSPLIT, $16 | |
| 32 | - | MOVQ DI, 0(SP) | |
| 33 | - | MOVQ SI, 8(SP) | |
| 34 | - | CALL ·x_cgo_init(SB) | |
| 32 | + | MOVQ DI, AX | |
| 33 | + | MOVQ SI, BX | |
| 34 | + | MOVQ ·x_cgo_init_call(SB), DX | |
| 35 | + | MOVQ (DX), CX | |
| 36 | + | CALL CX | |
| 35 | 37 | RET | |
| 36 | 38 | ||
| 37 | 39 | TEXT x_cgo_thread_start_trampoline(SB), NOSPLIT, $8 | |
| 38 | - | MOVQ DI, 0(SP) | |
| 39 | - | CALL ·x_cgo_thread_start(SB) | |
| 40 | + | MOVQ DI, AX | |
| 41 | + | MOVQ ·x_cgo_thread_start_call(SB), DX | |
| 42 | + | MOVQ (DX), CX | |
| 43 | + | CALL CX | |
| 40 | 44 | RET | |
| 41 | 45 | ||
| 42 | 46 | TEXT x_cgo_setenv_trampoline(SB), NOSPLIT, $8 | |
| 43 | - | MOVQ DI, 0(SP) | |
| 44 | - | CALL ·x_cgo_setenv(SB) | |
| 47 | + | MOVQ DI, AX | |
| 48 | + | MOVQ ·x_cgo_setenv_call(SB), DX | |
| 49 | + | MOVQ (DX), CX | |
| 50 | + | CALL CX | |
| 45 | 51 | RET | |
| 46 | 52 | ||
| 47 | 53 | TEXT x_cgo_unsetenv_trampoline(SB), NOSPLIT, $8 | |
| 48 | - | MOVQ DI, 0(SP) | |
| 49 | - | CALL ·x_cgo_unsetenv(SB) | |
| 54 | + | MOVQ DI, AX | |
| 55 | + | MOVQ ·x_cgo_unsetenv_call(SB), DX | |
| 56 | + | MOVQ (DX), CX | |
| 57 | + | CALL CX | |
| 50 | 58 | RET | |
| 51 | 59 | ||
| 52 | 60 | TEXT x_cgo_notify_runtime_init_done_trampoline(SB), NOSPLIT, $0 | |
| @@ -61,9 +69,10 @@ TEXT ·setg_trampoline(SB), NOSPLIT, $0-16 | |||
| 61 | 69 | RET | |
| 62 | 70 | ||
| 63 | 71 | TEXT threadentry_trampoline(SB), NOSPLIT, $16 | |
| 64 | - | MOVQ DI, 0(SP) | |
| 65 | - | CALL ·threadentry(SB) | |
| 66 | - | MOVQ 8(SP), AX | |
| 72 | + | MOVQ DI, AX | |
| 73 | + | MOVQ ·threadentry_call(SB), DX | |
| 74 | + | MOVQ (DX), CX | |
| 75 | + | CALL CX | |
| 67 | 76 | RET | |
| 68 | 77 | ||
| 69 | 78 | TEXT ·call5(SB), NOSPLIT, $0-0 | |
| @@ -29,24 +29,32 @@ return value will be in AX | |||||
| 29 | // these trampolines map the gcc ABI to Go ABI and then calls into the Go equivalent functions. | 29 | // these trampolines map the gcc ABI to Go ABI and then calls into the Go equivalent functions. | ||
| 30 | 30 | ||||
| 31 | TEXT x_cgo_init_trampoline(SB), NOSPLIT, $16 | 31 | TEXT x_cgo_init_trampoline(SB), NOSPLIT, $16 | ||
| 32 | - | MOVQ DI, 0(SP) | 32 | + | MOVQ DI, AX |
| 33 | - | MOVQ SI, 8(SP) | 33 | + | MOVQ SI, BX |
| 34 | - | CALL ·x_cgo_init(SB) | 34 | + | MOVQ ·x_cgo_init_call(SB), DX |
| 35 | + | MOVQ (DX), CX | |||
| 36 | + | CALL CX | |||
| 35 | RET | 37 | RET | ||
| 36 | 38 | ||||
| 37 | TEXT x_cgo_thread_start_trampoline(SB), NOSPLIT, $8 | 39 | TEXT x_cgo_thread_start_trampoline(SB), NOSPLIT, $8 | ||
| 38 | - | MOVQ DI, 0(SP) | 40 | + | MOVQ DI, AX |
| 39 | - | CALL ·x_cgo_thread_start(SB) | 41 | + | MOVQ ·x_cgo_thread_start_call(SB), DX |
| 42 | + | MOVQ (DX), CX | |||
| 43 | + | CALL CX | |||
| 40 | RET | 44 | RET | ||
| 41 | 45 | ||||
| 42 | TEXT x_cgo_setenv_trampoline(SB), NOSPLIT, $8 | 46 | TEXT x_cgo_setenv_trampoline(SB), NOSPLIT, $8 | ||
| 43 | - | MOVQ DI, 0(SP) | 47 | + | MOVQ DI, AX |
| 44 | - | CALL ·x_cgo_setenv(SB) | 48 | + | MOVQ ·x_cgo_setenv_call(SB), DX |
| 49 | + | MOVQ (DX), CX | |||
| 50 | + | CALL CX | |||
| 45 | RET | 51 | RET | ||
| 46 | 52 | ||||
| 47 | TEXT x_cgo_unsetenv_trampoline(SB), NOSPLIT, $8 | 53 | TEXT x_cgo_unsetenv_trampoline(SB), NOSPLIT, $8 | ||
| 48 | - | MOVQ DI, 0(SP) | 54 | + | MOVQ DI, AX |
| 49 | - | CALL ·x_cgo_unsetenv(SB) | 55 | + | MOVQ ·x_cgo_unsetenv_call(SB), DX |
| 56 | + | MOVQ (DX), CX | |||
| 57 | + | CALL CX | |||
| 50 | RET | 58 | RET | ||
| 51 | 59 | ||||
| 52 | TEXT x_cgo_notify_runtime_init_done_trampoline(SB), NOSPLIT, $0 | 60 | TEXT x_cgo_notify_runtime_init_done_trampoline(SB), NOSPLIT, $0 | ||
| @@ -61,9 +69,10 @@ TEXT ·setg_trampoline(SB), NOSPLIT, $0-16 | |||||
| 61 | RET | 69 | RET | ||
| 62 | 70 | ||||
| 63 | TEXT threadentry_trampoline(SB), NOSPLIT, $16 | 71 | TEXT threadentry_trampoline(SB), NOSPLIT, $16 | ||
| 64 | - | MOVQ DI, 0(SP) | 72 | + | MOVQ DI, AX |
| 65 | - | CALL ·threadentry(SB) | 73 | + | MOVQ ·threadentry_call(SB), DX |
| 66 | - | MOVQ 8(SP), AX | 74 | + | MOVQ (DX), CX |
| 75 | + | CALL CX | |||
| 67 | RET | 76 | RET | ||
| 68 | 77 | ||||
| 69 | TEXT ·call5(SB), NOSPLIT, $0-0 | 78 | TEXT ·call5(SB), NOSPLIT, $0-0 | ||
M internal/fakecgo/trampolines_arm64.s +16 -6
| @@ -11,22 +11,30 @@ | |||
| 11 | 11 | TEXT x_cgo_init_trampoline(SB), NOSPLIT, $0-0 | |
| 12 | 12 | MOVD R0, 8(RSP) | |
| 13 | 13 | MOVD R1, 16(RSP) | |
| 14 | - | CALL ·x_cgo_init(SB) | |
| 14 | + | MOVD ·x_cgo_init_call(SB), R26 | |
| 15 | + | MOVD (R26), R2 | |
| 16 | + | CALL (R2) | |
| 15 | 17 | RET | |
| 16 | 18 | ||
| 17 | 19 | TEXT x_cgo_thread_start_trampoline(SB), NOSPLIT, $0-0 | |
| 18 | 20 | MOVD R0, 8(RSP) | |
| 19 | - | CALL ·x_cgo_thread_start(SB) | |
| 21 | + | MOVD ·x_cgo_thread_start_call(SB), R26 | |
| 22 | + | MOVD (R26), R2 | |
| 23 | + | CALL (R2) | |
| 20 | 24 | RET | |
| 21 | 25 | ||
| 22 | 26 | TEXT x_cgo_setenv_trampoline(SB), NOSPLIT, $0-0 | |
| 23 | 27 | MOVD R0, 8(RSP) | |
| 24 | - | CALL ·x_cgo_setenv(SB) | |
| 28 | + | MOVD ·x_cgo_setenv_call(SB), R26 | |
| 29 | + | MOVD (R26), R2 | |
| 30 | + | CALL (R2) | |
| 25 | 31 | RET | |
| 26 | 32 | ||
| 27 | 33 | TEXT x_cgo_unsetenv_trampoline(SB), NOSPLIT, $0-0 | |
| 28 | 34 | MOVD R0, 8(RSP) | |
| 29 | - | CALL ·x_cgo_unsetenv(SB) | |
| 35 | + | MOVD ·x_cgo_unsetenv_call(SB), R26 | |
| 36 | + | MOVD (R26), R2 | |
| 37 | + | CALL (R2) | |
| 30 | 38 | RET | |
| 31 | 39 | ||
| 32 | 40 | TEXT x_cgo_notify_runtime_init_done_trampoline(SB), NOSPLIT, $0-0 | |
| @@ -42,8 +50,10 @@ TEXT ·setg_trampoline(SB), NOSPLIT, $0-16 | |||
| 42 | 50 | ||
| 43 | 51 | TEXT threadentry_trampoline(SB), NOSPLIT, $0-0 | |
| 44 | 52 | MOVD R0, 8(RSP) | |
| 45 | - | CALL ·threadentry(SB) | |
| 46 | - | MOVD $0, R0 // TODO: get the return value from threadentry | |
| 53 | + | MOVD ·threadentry_call(SB), R26 | |
| 54 | + | MOVD (R26), R2 | |
| 55 | + | CALL (R2) | |
| 56 | + | MOVD $0, R0 // TODO: get the return value from threadentry | |
| 47 | 57 | RET | |
| 48 | 58 | ||
| 49 | 59 | TEXT ·call5(SB), NOSPLIT, $0-0 | |
| @@ -11,22 +11,30 @@ | |||||
| 11 | TEXT x_cgo_init_trampoline(SB), NOSPLIT, $0-0 | 11 | TEXT x_cgo_init_trampoline(SB), NOSPLIT, $0-0 | ||
| 12 | MOVD R0, 8(RSP) | 12 | MOVD R0, 8(RSP) | ||
| 13 | MOVD R1, 16(RSP) | 13 | MOVD R1, 16(RSP) | ||
| 14 | - | CALL ·x_cgo_init(SB) | 14 | + | MOVD ·x_cgo_init_call(SB), R26 |
| 15 | + | MOVD (R26), R2 | |||
| 16 | + | CALL (R2) | |||
| 15 | RET | 17 | RET | ||
| 16 | 18 | ||||
| 17 | TEXT x_cgo_thread_start_trampoline(SB), NOSPLIT, $0-0 | 19 | TEXT x_cgo_thread_start_trampoline(SB), NOSPLIT, $0-0 | ||
| 18 | MOVD R0, 8(RSP) | 20 | MOVD R0, 8(RSP) | ||
| 19 | - | CALL ·x_cgo_thread_start(SB) | 21 | + | MOVD ·x_cgo_thread_start_call(SB), R26 |
| 22 | + | MOVD (R26), R2 | |||
| 23 | + | CALL (R2) | |||
| 20 | RET | 24 | RET | ||
| 21 | 25 | ||||
| 22 | TEXT x_cgo_setenv_trampoline(SB), NOSPLIT, $0-0 | 26 | TEXT x_cgo_setenv_trampoline(SB), NOSPLIT, $0-0 | ||
| 23 | MOVD R0, 8(RSP) | 27 | MOVD R0, 8(RSP) | ||
| 24 | - | CALL ·x_cgo_setenv(SB) | 28 | + | MOVD ·x_cgo_setenv_call(SB), R26 |
| 29 | + | MOVD (R26), R2 | |||
| 30 | + | CALL (R2) | |||
| 25 | RET | 31 | RET | ||
| 26 | 32 | ||||
| 27 | TEXT x_cgo_unsetenv_trampoline(SB), NOSPLIT, $0-0 | 33 | TEXT x_cgo_unsetenv_trampoline(SB), NOSPLIT, $0-0 | ||
| 28 | MOVD R0, 8(RSP) | 34 | MOVD R0, 8(RSP) | ||
| 29 | - | CALL ·x_cgo_unsetenv(SB) | 35 | + | MOVD ·x_cgo_unsetenv_call(SB), R26 |
| 36 | + | MOVD (R26), R2 | |||
| 37 | + | CALL (R2) | |||
| 30 | RET | 38 | RET | ||
| 31 | 39 | ||||
| 32 | TEXT x_cgo_notify_runtime_init_done_trampoline(SB), NOSPLIT, $0-0 | 40 | TEXT x_cgo_notify_runtime_init_done_trampoline(SB), NOSPLIT, $0-0 | ||
| @@ -42,8 +50,10 @@ TEXT ·setg_trampoline(SB), NOSPLIT, $0-16 | |||||
| 42 | 50 | ||||
| 43 | TEXT threadentry_trampoline(SB), NOSPLIT, $0-0 | 51 | TEXT threadentry_trampoline(SB), NOSPLIT, $0-0 | ||
| 44 | MOVD R0, 8(RSP) | 52 | MOVD R0, 8(RSP) | ||
| 45 | - | CALL ·threadentry(SB) | 53 | + | MOVD ·threadentry_call(SB), R26 |
| 46 | - | MOVD $0, R0 // TODO: get the return value from threadentry | 54 | + | MOVD (R26), R2 |
| 55 | + | CALL (R2) | |||
| 56 | + | MOVD $0, R0 // TODO: get the return value from threadentry | |||
| 47 | RET | 57 | RET | ||
| 48 | 58 | ||||
| 49 | TEXT ·call5(SB), NOSPLIT, $0-0 | 59 | TEXT ·call5(SB), NOSPLIT, $0-0 | ||