detached 05c1074

purego: add Linux support amd64 & arm64 (#66)

This commit adds Linux support for arm64 and amd64 with a Cgo fallback for other architectures.
commit
05c1074240f7a8180257bbb8a1d487937744da5b
author
TotallyGamerJet · · 2022-11-24 19:29 UTC
committer
GitHub · · 2022-11-24 19:29 UTC
parent
c9e35fa
signature
GPG Unverified4AEE18F83AFDEB23 The key is unknown
33 files · +554 -23
M .github/workflows/test.yml +4 -0
@@ -50,6 +50,10 @@ jobs:
5050 # Check cross-compiling macOS binaries.
5151 env GOOS=darwin GOARCH=amd64 go build -v ./...
5252 env GOOS=darwin GOARCH=arm64 go build -v ./...
53+
54+ # Check cross-compiling Linux binaries.
55+ env GOOS=linux GOARCH=amd64 go build -v ./...
56+ env GOOS=linux GOARCH=arm64 go build -v ./...
5357
5458 - name: go mod vendor
5559 if: ${{ !startsWith(matrix.os, 'ubuntu-') }}
@@ -50,6 +50,10 @@ jobs:
50 # Check cross-compiling macOS binaries.50 # Check cross-compiling macOS binaries.
51 env GOOS=darwin GOARCH=amd64 go build -v ./...51 env GOOS=darwin GOARCH=amd64 go build -v ./...
52 env GOOS=darwin GOARCH=arm64 go build -v ./... 52 env GOOS=darwin GOARCH=arm64 go build -v ./...
53+
54+ # Check cross-compiling Linux binaries.
55+ env GOOS=linux GOARCH=amd64 go build -v ./...
56+ env GOOS=linux GOARCH=arm64 go build -v ./...
53 57
54 - name: go mod vendor58 - name: go mod vendor
55 if: ${{ !startsWith(matrix.os, 'ubuntu-') }}59 if: ${{ !startsWith(matrix.os, 'ubuntu-') }}
M README.md +1 -0
@@ -12,5 +12,6 @@ This is a list of the copied files:
1212 * `zcallback_darwin_*.s` from package `runtime`
1313 * `internal/abi/abi_*.h` from package `runtime/cgo`
1414 * `internal/fakecgo/callbacks.go` from package `runtime/cgo`
15+* `internal/fakecgo/go_GOOS_GOARCH.go` from package `runtime/cgo`
1516 * `internal/fakecgo/iscgo.go` from package `runtime/cgo`
1617 * `internal/fakecgo/setenv.go` from package `runtime/cgo`⏎̸
@@ -12,5 +12,6 @@ This is a list of the copied files:
12 * `zcallback_darwin_*.s` from package `runtime`12 * `zcallback_darwin_*.s` from package `runtime`
13 * `internal/abi/abi_*.h` from package `runtime/cgo`13 * `internal/abi/abi_*.h` from package `runtime/cgo`
14 * `internal/fakecgo/callbacks.go` from package `runtime/cgo`14 * `internal/fakecgo/callbacks.go` from package `runtime/cgo`
15+* `internal/fakecgo/go_GOOS_GOARCH.go` from package `runtime/cgo`
15 * `internal/fakecgo/iscgo.go` from package `runtime/cgo`16 * `internal/fakecgo/iscgo.go` from package `runtime/cgo`
16 * `internal/fakecgo/setenv.go` from package `runtime/cgo`⏎̸17 * `internal/fakecgo/setenv.go` from package `runtime/cgo`⏎̸
R cgo_darwin.go → cgo.go +1 -1 renamed, 94% similar
@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4-//go:build cgo
4+//go:build cgo && (darwin || linux)
55
66 package purego
77
@@ -1,7 +1,7 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4-//go:build cgo4+//go:build cgo && (darwin || linux)
5 5
6 package purego6 package purego
7 7
M dlfcn.go +3 -1
@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4-//go:build darwin
4+//go:build darwin || linux
55
66 package purego
77
@@ -9,6 +9,8 @@ import (
99 "unsafe"
1010 )
1111
12+// Unix Specification for dlfcn.h: https://pubs.opengroup.org/onlinepubs/7908799/xsh/dlfcn.h.html
13+
1214 var (
1315 fnDlopen func(path string, mode int) uintptr
1416 fnDlsym func(handle uintptr, name string) uintptr
@@ -1,7 +1,7 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4-//go:build darwin4+//go:build darwin || linux
5 5
6 package purego6 package purego
7 7
@@ -9,6 +9,8 @@ import (
9 "unsafe"9 "unsafe"
10 )10 )
11 11
12+// Unix Specification for dlfcn.h: https://pubs.opengroup.org/onlinepubs/7908799/xsh/dlfcn.h.html
13+
12 var (14 var (
13 fnDlopen func(path string, mode int) uintptr15 fnDlopen func(path string, mode int) uintptr
14 fnDlsym func(handle uintptr, name string) uintptr16 fnDlsym func(handle uintptr, name string) uintptr
A dlfcn_linux.go +13 -0
@@ -0,0 +1,13 @@
1+// SPDX-License-Identifier: Apache-2.0
2+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3+
4+package purego
5+
6+// Source for constants: https://codebrowser.dev/glibc/glibc/bits/dlfcn.h.html
7+
8+const (
9+ RTLD_LAZY = 0x00001 // Relocations are performed at an implementation-dependent time.
10+ RTLD_NOW = 0x00002 // Relocations are performed when the object is loaded.
11+ RTLD_LOCAL = 0x00000 // All symbols are not made available for relocation processing by other modules.
12+ RTLD_GLOBAL = 0x00100 // All symbols are available for relocation processing of other modules.
13+)
@@ -0,0 +1,13 @@
1+// SPDX-License-Identifier: Apache-2.0
2+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3+
4+package purego
5+
6+// Source for constants: https://codebrowser.dev/glibc/glibc/bits/dlfcn.h.html
7+
8+const (
9+ RTLD_LAZY = 0x00001 // Relocations are performed at an implementation-dependent time.
10+ RTLD_NOW = 0x00002 // Relocations are performed when the object is loaded.
11+ RTLD_LOCAL = 0x00000 // All symbols are not made available for relocation processing by other modules.
12+ RTLD_GLOBAL = 0x00100 // All symbols are available for relocation processing of other modules.
13+)
A dlfcn_nocgo_linux.go +19 -0
@@ -0,0 +1,19 @@
1+// SPDX-License-Identifier: Apache-2.0
2+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3+
4+//go:build !cgo
5+
6+package purego
7+
8+// if there is no Cgo we must link to each of the functions from dlfcn.h
9+// then the functions are called inside dlfcn_stubs.s
10+
11+//go:cgo_import_dynamic purego_dlopen dlopen "libdl.so.2"
12+//go:cgo_import_dynamic purego_dlsym dlsym "libdl.so.2"
13+//go:cgo_import_dynamic purego_dlerror dlerror "libdl.so.2"
14+//go:cgo_import_dynamic purego_dlclose dlclose "libdl.so.2"
15+
16+// on amd64 we don't need the following line - on 386 we do...
17+// anyway - with those lines the output is better (but doesn't matter) - without it on amd64 we get multiple DT_NEEDED with "libc.so.6" etc
18+
19+//go:cgo_import_dynamic _ _ "libdl.so.2"
@@ -0,0 +1,19 @@
1+// SPDX-License-Identifier: Apache-2.0
2+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3+
4+//go:build !cgo
5+
6+package purego
7+
8+// if there is no Cgo we must link to each of the functions from dlfcn.h
9+// then the functions are called inside dlfcn_stubs.s
10+
11+//go:cgo_import_dynamic purego_dlopen dlopen "libdl.so.2"
12+//go:cgo_import_dynamic purego_dlsym dlsym "libdl.so.2"
13+//go:cgo_import_dynamic purego_dlerror dlerror "libdl.so.2"
14+//go:cgo_import_dynamic purego_dlclose dlclose "libdl.so.2"
15+
16+// on amd64 we don't need the following line - on 386 we do...
17+// anyway - with those lines the output is better (but doesn't matter) - without it on amd64 we get multiple DT_NEEDED with "libc.so.6" etc
18+
19+//go:cgo_import_dynamic _ _ "libdl.so.2"
M dlfcn_stubs.s +1 -1
@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4-//go:build darwin
4+//go:build darwin || (linux && !cgo)
55
66 #include "textflag.h"
77
@@ -1,7 +1,7 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4-//go:build darwin4+//go:build darwin || (linux && !cgo)
5 5
6 #include "textflag.h"6 #include "textflag.h"
7 7
M example/main.go +1 -1
@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4-//go:build darwin || windows
4+//go:build darwin || linux || windows
55
66 package main
77
@@ -1,7 +1,7 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4-//go:build darwin || windows4+//go:build darwin || linux || windows
5 5
6 package main6 package main
7 7
R func_darwin.go → func.go +10 -0 renamed, 94% similar
@@ -1,6 +1,8 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4+//go:build darwin || linux
5+
46 package purego
57
68 import (
@@ -14,6 +16,8 @@ import (
1416
1517 // RegisterLibFunc is a wrapper around RegisterFunc that uses the C function returned from Dlsym(handle, name).
1618 // It panics if Dlsym fails.
19+//
20+// Windows does not support this function.
1721 func RegisterLibFunc(fptr interface{}, handle uintptr, name string) {
1822 sym := Dlsym(handle, name)
1923 if sym == 0 {
@@ -59,6 +63,12 @@ func RegisterLibFunc(fptr interface{}, handle uintptr, name string) {
5963 // it will be expanded into a call to the C function as if it had the arguments in that slice.
6064 // This means that using arg ...interface{} is like a cast to the function with the arguments inside arg.
6165 // This is not the same as C variadic.
66+//
67+// There are some limitations when using RegisterFunc on Linux. First, there is no support for function arguments.
68+// Second, float32 and float64 arguments and return values do not work when CGO_ENABLED=1. Otherwise, Linux
69+// has the same feature parity as Darwin.
70+//
71+// Windows does not support this function.
6272 func RegisterFunc(fptr interface{}, cfn uintptr) {
6373 fn := reflect.ValueOf(fptr).Elem()
6474 ty := fn.Type()
@@ -1,6 +1,8 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4+//go:build darwin || linux
5+
4 package purego6 package purego
5 7
6 import (8 import (
@@ -14,6 +16,8 @@ import (
14 16
15 // RegisterLibFunc is a wrapper around RegisterFunc that uses the C function returned from Dlsym(handle, name).17 // RegisterLibFunc is a wrapper around RegisterFunc that uses the C function returned from Dlsym(handle, name).
16 // It panics if Dlsym fails.18 // It panics if Dlsym fails.
19+//
20+// Windows does not support this function.
17 func RegisterLibFunc(fptr interface{}, handle uintptr, name string) {21 func RegisterLibFunc(fptr interface{}, handle uintptr, name string) {
18 sym := Dlsym(handle, name)22 sym := Dlsym(handle, name)
19 if sym == 0 {23 if sym == 0 {
@@ -59,6 +63,12 @@ func RegisterLibFunc(fptr interface{}, handle uintptr, name string) {
59 // it will be expanded into a call to the C function as if it had the arguments in that slice.63 // it will be expanded into a call to the C function as if it had the arguments in that slice.
60 // This means that using arg ...interface{} is like a cast to the function with the arguments inside arg.64 // This means that using arg ...interface{} is like a cast to the function with the arguments inside arg.
61 // This is not the same as C variadic.65 // This is not the same as C variadic.
66+//
67+// There are some limitations when using RegisterFunc on Linux. First, there is no support for function arguments.
68+// Second, float32 and float64 arguments and return values do not work when CGO_ENABLED=1. Otherwise, Linux
69+// has the same feature parity as Darwin.
70+//
71+// Windows does not support this function.
62 func RegisterFunc(fptr interface{}, cfn uintptr) {72 func RegisterFunc(fptr interface{}, cfn uintptr) {
63 fn := reflect.ValueOf(fptr).Elem()73 fn := reflect.ValueOf(fptr).Elem()
64 ty := fn.Type()74 ty := fn.Type()
M go_runtime.go +1 -1
@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4-//go:build darwin
4+//go:build darwin || linux
55
66 package purego
77
@@ -1,7 +1,7 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4-//go:build darwin4+//go:build darwin || linux
5 5
6 package purego6 package purego
7 7
A internal/cgo/syscall_cgo_linux.go +58 -0
@@ -0,0 +1,58 @@
1+// SPDX-License-Identifier: Apache-2.0
2+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3+
4+package cgo
5+
6+// this file is placed inside internal/cgo and not package purego
7+// because Cgo and assembly files can't be in the same package.
8+
9+/*
10+ #cgo LDFLAGS: -ldl
11+
12+#include <stdint.h>
13+#include <dlfcn.h>
14+#include <errno.h>
15+#include <assert.h>
16+
17+typedef struct syscall9Args {
18+ uintptr_t fn;
19+ uintptr_t a1, a2, a3, a4, a5, a6, a7, a8, a9;
20+ uintptr_t f1, f2, f3, f4, f5, f6, f7, f8;
21+ uintptr_t r1, r2, err;
22+} syscall9Args;
23+
24+void syscall9(struct syscall9Args *args) {
25+ assert((args->f1|args->f2|args->f3|args->f4|args->f5|args->f6|args->f7|args->f8) == 0);
26+ uintptr_t (*func_name)(uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9);
27+ *(void**)(&func_name) = (void*)(args->fn);
28+ uintptr_t r1 = func_name(args->a1,args->a2,args->a3,args->a4,args->a5,args->a6,args->a7,args->a8,args->a9);
29+ args->r1 = r1;
30+ args->err = errno;
31+}
32+
33+*/
34+import "C"
35+import "unsafe"
36+
37+// assign purego.syscall9XABI0 to the C version of this function.
38+//
39+//go:linkname internal_syscall9XABI0 purego.syscall9XABI0
40+var internal_syscall9XABI0 = unsafe.Pointer(C.syscall9)
41+
42+// all that is needed is to assign each dl function because then its
43+// symbol will then be made available to the linker and linked to inside dlfcn.go
44+var (
45+ _ = C.dlopen
46+ _ = C.dlsym
47+ _ = C.dlerror
48+ _ = C.dlclose
49+)
50+
51+//go:nosplit
52+func Syscall9X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) {
53+ args := C.syscall9Args{C.uintptr_t(fn), C.uintptr_t(a1), C.uintptr_t(a2), C.uintptr_t(a3),
54+ C.uintptr_t(a4), C.uintptr_t(a5), C.uintptr_t(a6),
55+ C.uintptr_t(a7), C.uintptr_t(a8), C.uintptr_t(a9), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
56+ C.syscall9(&args)
57+ return uintptr(args.r1), uintptr(args.r2), uintptr(args.err)
58+}
@@ -0,0 +1,58 @@
1+// SPDX-License-Identifier: Apache-2.0
2+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3+
4+package cgo
5+
6+// this file is placed inside internal/cgo and not package purego
7+// because Cgo and assembly files can't be in the same package.
8+
9+/*
10+ #cgo LDFLAGS: -ldl
11+
12+#include <stdint.h>
13+#include <dlfcn.h>
14+#include <errno.h>
15+#include <assert.h>
16+
17+typedef struct syscall9Args {
18+ uintptr_t fn;
19+ uintptr_t a1, a2, a3, a4, a5, a6, a7, a8, a9;
20+ uintptr_t f1, f2, f3, f4, f5, f6, f7, f8;
21+ uintptr_t r1, r2, err;
22+} syscall9Args;
23+
24+void syscall9(struct syscall9Args *args) {
25+ assert((args->f1|args->f2|args->f3|args->f4|args->f5|args->f6|args->f7|args->f8) == 0);
26+ uintptr_t (*func_name)(uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9);
27+ *(void**)(&func_name) = (void*)(args->fn);
28+ uintptr_t r1 = func_name(args->a1,args->a2,args->a3,args->a4,args->a5,args->a6,args->a7,args->a8,args->a9);
29+ args->r1 = r1;
30+ args->err = errno;
31+}
32+
33+*/
34+import "C"
35+import "unsafe"
36+
37+// assign purego.syscall9XABI0 to the C version of this function.
38+//
39+//go:linkname internal_syscall9XABI0 purego.syscall9XABI0
40+var internal_syscall9XABI0 = unsafe.Pointer(C.syscall9)
41+
42+// all that is needed is to assign each dl function because then its
43+// symbol will then be made available to the linker and linked to inside dlfcn.go
44+var (
45+ _ = C.dlopen
46+ _ = C.dlsym
47+ _ = C.dlerror
48+ _ = C.dlclose
49+)
50+
51+//go:nosplit
52+func Syscall9X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) {
53+ args := C.syscall9Args{C.uintptr_t(fn), C.uintptr_t(a1), C.uintptr_t(a2), C.uintptr_t(a3),
54+ C.uintptr_t(a4), C.uintptr_t(a5), C.uintptr_t(a6),
55+ C.uintptr_t(a7), C.uintptr_t(a8), C.uintptr_t(a9), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
56+ C.syscall9(&args)
57+ return uintptr(args.r1), uintptr(args.r2), uintptr(args.err)
58+}
M internal/fakecgo/callbacks.go +1 -1
@@ -2,7 +2,7 @@
22 // Use of this source code is governed by a BSD-style
33 // license that can be found in the LICENSE file.
44
5-//go:build darwin
5+//go:build darwin || linux
66
77 package fakecgo
88
@@ -2,7 +2,7 @@
2 // Use of this source code is governed by a BSD-style2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.3 // license that can be found in the LICENSE file.
4 4
5-//go:build darwin5+//go:build darwin || linux
6 6
7 package fakecgo7 package fakecgo
8 8
M internal/fakecgo/go_darwin_amd64.go +3 -2
@@ -1,5 +1,6 @@
1-// SPDX-License-Identifier: Apache-2.0
2-// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
1+// Copyright 2011 The Go Authors. All rights reserved.
2+// Use of this source code is governed by a BSD-style
3+// license that can be found in the LICENSE file.
34
45 package fakecgo
56
@@ -1,5 +1,6 @@
1-// SPDX-License-Identifier: Apache-2.01+// Copyright 2011 The Go Authors. All rights reserved.
2-// SPDX-FileCopyrightText: 2022 The Ebitengine Authors2+// Use of this source code is governed by a BSD-style
3+// license that can be found in the LICENSE file.
3 4
4 package fakecgo5 package fakecgo
5 6
M internal/fakecgo/go_darwin_arm64.go +3 -2
@@ -1,5 +1,6 @@
1-// SPDX-License-Identifier: Apache-2.0
2-// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
1+// Copyright 2011 The Go Authors. All rights reserved.
2+// Use of this source code is governed by a BSD-style
3+// license that can be found in the LICENSE file.
34
45 package fakecgo
56
@@ -1,5 +1,6 @@
1-// SPDX-License-Identifier: Apache-2.01+// Copyright 2011 The Go Authors. All rights reserved.
2-// SPDX-FileCopyrightText: 2022 The Ebitengine Authors2+// Use of this source code is governed by a BSD-style
3+// license that can be found in the LICENSE file.
3 4
4 package fakecgo5 package fakecgo
5 6
M internal/fakecgo/go_libinit.go +1 -1
@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4-//go:build darwin
4+//go:build darwin || linux
55
66 package fakecgo
77
@@ -1,7 +1,7 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4-//go:build darwin4+//go:build darwin || linux
5 5
6 package fakecgo6 package fakecgo
7 7
A internal/fakecgo/go_linux_amd64.go +93 -0
@@ -0,0 +1,93 @@
1+// Copyright 2011 The Go Authors. All rights reserved.
2+// Use of this source code is governed by a BSD-style
3+// license that can be found in the LICENSE file.
4+
5+package fakecgo
6+
7+import "unsafe"
8+
9+//go:nosplit
10+func _cgo_sys_thread_start(ts *ThreadStart) {
11+ var attr pthread_attr_t
12+ var ign, oset sigset_t
13+ var p pthread_t
14+ var size size_t
15+ var err int
16+
17+ //fprintf(stderr, "runtime/cgo: _cgo_sys_thread_start: fn=%p, g=%p\n", ts->fn, ts->g); // debug
18+ sigfillset(&ign)
19+ pthread_sigmask(SIG_SETMASK, &ign, &oset)
20+
21+ pthread_attr_init(&attr)
22+ pthread_attr_getstacksize(&attr, &size)
23+ // Leave stacklo=0 and set stackhi=size; mstart will do the rest.
24+ ts.g.stackhi = uintptr(size)
25+
26+ err = _cgo_try_pthread_create(&p, &attr, unsafe.Pointer(threadentry_trampolineABI0), ts)
27+
28+ pthread_sigmask(SIG_SETMASK, &oset, nil)
29+
30+ if err != 0 {
31+ print("fakecgo: pthread_create failed: ")
32+ println(err)
33+ abort()
34+ }
35+}
36+
37+// threadentry_trampolineABI0 maps the C ABI to Go ABI then calls the Go function
38+//
39+//go:linkname x_threadentry_trampoline threadentry_trampoline
40+var x_threadentry_trampoline byte
41+var threadentry_trampolineABI0 = &x_threadentry_trampoline
42+
43+//go:nosplit
44+func threadentry(v unsafe.Pointer) unsafe.Pointer {
45+ ts := *(*ThreadStart)(v)
46+ free(v)
47+
48+ setg_trampoline(setg_func, uintptr(unsafe.Pointer(ts.g)))
49+
50+ // faking funcs in go is a bit a... involved - but the following works :)
51+ fn := uintptr(unsafe.Pointer(&ts.fn))
52+ (*(*func())(unsafe.Pointer(&fn)))()
53+
54+ return nil
55+}
56+
57+// here we will store a pointer to the provided setg func
58+var setg_func uintptr
59+
60+//go:nosplit
61+func x_cgo_init(g *G, setg uintptr) {
62+ var size size_t
63+ var attr *pthread_attr_t
64+
65+ /* The memory sanitizer distributed with versions of clang
66+ before 3.8 has a bug: if you call mmap before malloc, mmap
67+ may return an address that is later overwritten by the msan
68+ library. Avoid this problem by forcing a call to malloc
69+ here, before we ever call malloc.
70+
71+ This is only required for the memory sanitizer, so it's
72+ unfortunate that we always run it. It should be possible
73+ to remove this when we no longer care about versions of
74+ clang before 3.8. The test for this is
75+ misc/cgo/testsanitizers.
76+
77+ GCC works hard to eliminate a seemingly unnecessary call to
78+ malloc, so we actually use the memory we allocate. */
79+
80+ setg_func = setg
81+ attr = (*pthread_attr_t)(malloc(unsafe.Sizeof(*attr)))
82+ if attr == nil {
83+ println("fakecgo: malloc failed")
84+ abort()
85+ }
86+ pthread_attr_init(attr)
87+ pthread_attr_getstacksize(attr, &size)
88+ // runtime/cgo uses __builtin_frame_address(0) instead of `uintptr(unsafe.Pointer(&size))`
89+ // but this should be OK since we are taking the address of the first variable in this function.
90+ g.stacklo = uintptr(unsafe.Pointer(&size)) - uintptr(size) + 4096
91+ pthread_attr_destroy(attr)
92+ free(unsafe.Pointer(attr))
93+}
@@ -0,0 +1,93 @@
1+// Copyright 2011 The Go Authors. All rights reserved.
2+// Use of this source code is governed by a BSD-style
3+// license that can be found in the LICENSE file.
4+
5+package fakecgo
6+
7+import "unsafe"
8+
9+//go:nosplit
10+func _cgo_sys_thread_start(ts *ThreadStart) {
11+ var attr pthread_attr_t
12+ var ign, oset sigset_t
13+ var p pthread_t
14+ var size size_t
15+ var err int
16+
17+ //fprintf(stderr, "runtime/cgo: _cgo_sys_thread_start: fn=%p, g=%p\n", ts->fn, ts->g); // debug
18+ sigfillset(&ign)
19+ pthread_sigmask(SIG_SETMASK, &ign, &oset)
20+
21+ pthread_attr_init(&attr)
22+ pthread_attr_getstacksize(&attr, &size)
23+ // Leave stacklo=0 and set stackhi=size; mstart will do the rest.
24+ ts.g.stackhi = uintptr(size)
25+
26+ err = _cgo_try_pthread_create(&p, &attr, unsafe.Pointer(threadentry_trampolineABI0), ts)
27+
28+ pthread_sigmask(SIG_SETMASK, &oset, nil)
29+
30+ if err != 0 {
31+ print("fakecgo: pthread_create failed: ")
32+ println(err)
33+ abort()
34+ }
35+}
36+
37+// threadentry_trampolineABI0 maps the C ABI to Go ABI then calls the Go function
38+//
39+//go:linkname x_threadentry_trampoline threadentry_trampoline
40+var x_threadentry_trampoline byte
41+var threadentry_trampolineABI0 = &x_threadentry_trampoline
42+
43+//go:nosplit
44+func threadentry(v unsafe.Pointer) unsafe.Pointer {
45+ ts := *(*ThreadStart)(v)
46+ free(v)
47+
48+ setg_trampoline(setg_func, uintptr(unsafe.Pointer(ts.g)))
49+
50+ // faking funcs in go is a bit a... involved - but the following works :)
51+ fn := uintptr(unsafe.Pointer(&ts.fn))
52+ (*(*func())(unsafe.Pointer(&fn)))()
53+
54+ return nil
55+}
56+
57+// here we will store a pointer to the provided setg func
58+var setg_func uintptr
59+
60+//go:nosplit
61+func x_cgo_init(g *G, setg uintptr) {
62+ var size size_t
63+ var attr *pthread_attr_t
64+
65+ /* The memory sanitizer distributed with versions of clang
66+ before 3.8 has a bug: if you call mmap before malloc, mmap
67+ may return an address that is later overwritten by the msan
68+ library. Avoid this problem by forcing a call to malloc
69+ here, before we ever call malloc.
70+
71+ This is only required for the memory sanitizer, so it's
72+ unfortunate that we always run it. It should be possible
73+ to remove this when we no longer care about versions of
74+ clang before 3.8. The test for this is
75+ misc/cgo/testsanitizers.
76+
77+ GCC works hard to eliminate a seemingly unnecessary call to
78+ malloc, so we actually use the memory we allocate. */
79+
80+ setg_func = setg
81+ attr = (*pthread_attr_t)(malloc(unsafe.Sizeof(*attr)))
82+ if attr == nil {
83+ println("fakecgo: malloc failed")
84+ abort()
85+ }
86+ pthread_attr_init(attr)
87+ pthread_attr_getstacksize(attr, &size)
88+ // runtime/cgo uses __builtin_frame_address(0) instead of `uintptr(unsafe.Pointer(&size))`
89+ // but this should be OK since we are taking the address of the first variable in this function.
90+ g.stacklo = uintptr(unsafe.Pointer(&size)) - uintptr(size) + 4096
91+ pthread_attr_destroy(attr)
92+ free(unsafe.Pointer(attr))
93+}
A internal/fakecgo/go_linux_arm64.go +96 -0
@@ -0,0 +1,96 @@
1+// Copyright 2011 The Go Authors. All rights reserved.
2+// Use of this source code is governed by a BSD-style
3+// license that can be found in the LICENSE file.
4+
5+package fakecgo
6+
7+import "unsafe"
8+
9+//go:nosplit
10+func _cgo_sys_thread_start(ts *ThreadStart) {
11+ var attr pthread_attr_t
12+ var ign, oset sigset_t
13+ var p pthread_t
14+ var size size_t
15+ var err int
16+
17+ //fprintf(stderr, "runtime/cgo: _cgo_sys_thread_start: fn=%p, g=%p\n", ts->fn, ts->g); // debug
18+ sigfillset(&ign)
19+ pthread_sigmask(SIG_SETMASK, &ign, &oset)
20+
21+ pthread_attr_init(&attr)
22+ pthread_attr_getstacksize(&attr, &size)
23+ // Leave stacklo=0 and set stackhi=size; mstart will do the rest.
24+ ts.g.stackhi = uintptr(size)
25+
26+ err = _cgo_try_pthread_create(&p, &attr, unsafe.Pointer(threadentry_trampolineABI0), ts)
27+
28+ pthread_sigmask(SIG_SETMASK, &oset, nil)
29+
30+ if err != 0 {
31+ print("fakecgo: pthread_create failed: ")
32+ println(err)
33+ abort()
34+ }
35+}
36+
37+// threadentry_trampolineABI0 maps the C ABI to Go ABI then calls the Go function
38+//
39+//go:linkname x_threadentry_trampoline threadentry_trampoline
40+var x_threadentry_trampoline byte
41+var threadentry_trampolineABI0 = &x_threadentry_trampoline
42+
43+//go:nosplit
44+func threadentry(v unsafe.Pointer) unsafe.Pointer {
45+ ts := *(*ThreadStart)(v)
46+ free(v)
47+
48+ setg_trampoline(setg_func, uintptr(unsafe.Pointer(ts.g)))
49+
50+ // faking funcs in go is a bit a... involved - but the following works :)
51+ fn := uintptr(unsafe.Pointer(&ts.fn))
52+ (*(*func())(unsafe.Pointer(&fn)))()
53+
54+ return nil
55+}
56+
57+// here we will store a pointer to the provided setg func
58+var setg_func uintptr
59+
60+// x_cgo_init(G *g, void (*setg)(void*)) (runtime/cgo/gcc_linux_amd64.c)
61+// This get's called during startup, adjusts stacklo, and provides a pointer to setg_gcc for us
62+// Additionally, if we set _cgo_init to non-null, go won't do it's own TLS setup
63+// This function can't be go:systemstack since go is not in a state where the systemcheck would work.
64+//
65+//go:nosplit
66+func x_cgo_init(g *G, setg uintptr) {
67+ var size size_t
68+ var attr *pthread_attr_t
69+
70+ /* The memory sanitizer distributed with versions of clang
71+ before 3.8 has a bug: if you call mmap before malloc, mmap
72+ may return an address that is later overwritten by the msan
73+ library. Avoid this problem by forcing a call to malloc
74+ here, before we ever call malloc.
75+
76+ This is only required for the memory sanitizer, so it's
77+ unfortunate that we always run it. It should be possible
78+ to remove this when we no longer care about versions of
79+ clang before 3.8. The test for this is
80+ misc/cgo/testsanitizers.
81+
82+ GCC works hard to eliminate a seemingly unnecessary call to
83+ malloc, so we actually use the memory we allocate. */
84+
85+ setg_func = setg
86+ attr = (*pthread_attr_t)(malloc(unsafe.Sizeof(*attr)))
87+ if attr == nil {
88+ println("fakecgo: malloc failed")
89+ abort()
90+ }
91+ pthread_attr_init(attr)
92+ pthread_attr_getstacksize(attr, &size)
93+ g.stacklo = uintptr(unsafe.Pointer(&size)) - uintptr(size) + 4096
94+ pthread_attr_destroy(attr)
95+ free(unsafe.Pointer(attr))
96+}
@@ -0,0 +1,96 @@
1+// Copyright 2011 The Go Authors. All rights reserved.
2+// Use of this source code is governed by a BSD-style
3+// license that can be found in the LICENSE file.
4+
5+package fakecgo
6+
7+import "unsafe"
8+
9+//go:nosplit
10+func _cgo_sys_thread_start(ts *ThreadStart) {
11+ var attr pthread_attr_t
12+ var ign, oset sigset_t
13+ var p pthread_t
14+ var size size_t
15+ var err int
16+
17+ //fprintf(stderr, "runtime/cgo: _cgo_sys_thread_start: fn=%p, g=%p\n", ts->fn, ts->g); // debug
18+ sigfillset(&ign)
19+ pthread_sigmask(SIG_SETMASK, &ign, &oset)
20+
21+ pthread_attr_init(&attr)
22+ pthread_attr_getstacksize(&attr, &size)
23+ // Leave stacklo=0 and set stackhi=size; mstart will do the rest.
24+ ts.g.stackhi = uintptr(size)
25+
26+ err = _cgo_try_pthread_create(&p, &attr, unsafe.Pointer(threadentry_trampolineABI0), ts)
27+
28+ pthread_sigmask(SIG_SETMASK, &oset, nil)
29+
30+ if err != 0 {
31+ print("fakecgo: pthread_create failed: ")
32+ println(err)
33+ abort()
34+ }
35+}
36+
37+// threadentry_trampolineABI0 maps the C ABI to Go ABI then calls the Go function
38+//
39+//go:linkname x_threadentry_trampoline threadentry_trampoline
40+var x_threadentry_trampoline byte
41+var threadentry_trampolineABI0 = &x_threadentry_trampoline
42+
43+//go:nosplit
44+func threadentry(v unsafe.Pointer) unsafe.Pointer {
45+ ts := *(*ThreadStart)(v)
46+ free(v)
47+
48+ setg_trampoline(setg_func, uintptr(unsafe.Pointer(ts.g)))
49+
50+ // faking funcs in go is a bit a... involved - but the following works :)
51+ fn := uintptr(unsafe.Pointer(&ts.fn))
52+ (*(*func())(unsafe.Pointer(&fn)))()
53+
54+ return nil
55+}
56+
57+// here we will store a pointer to the provided setg func
58+var setg_func uintptr
59+
60+// x_cgo_init(G *g, void (*setg)(void*)) (runtime/cgo/gcc_linux_amd64.c)
61+// This get's called during startup, adjusts stacklo, and provides a pointer to setg_gcc for us
62+// Additionally, if we set _cgo_init to non-null, go won't do it's own TLS setup
63+// This function can't be go:systemstack since go is not in a state where the systemcheck would work.
64+//
65+//go:nosplit
66+func x_cgo_init(g *G, setg uintptr) {
67+ var size size_t
68+ var attr *pthread_attr_t
69+
70+ /* The memory sanitizer distributed with versions of clang
71+ before 3.8 has a bug: if you call mmap before malloc, mmap
72+ may return an address that is later overwritten by the msan
73+ library. Avoid this problem by forcing a call to malloc
74+ here, before we ever call malloc.
75+
76+ This is only required for the memory sanitizer, so it's
77+ unfortunate that we always run it. It should be possible
78+ to remove this when we no longer care about versions of
79+ clang before 3.8. The test for this is
80+ misc/cgo/testsanitizers.
81+
82+ GCC works hard to eliminate a seemingly unnecessary call to
83+ malloc, so we actually use the memory we allocate. */
84+
85+ setg_func = setg
86+ attr = (*pthread_attr_t)(malloc(unsafe.Sizeof(*attr)))
87+ if attr == nil {
88+ println("fakecgo: malloc failed")
89+ abort()
90+ }
91+ pthread_attr_init(attr)
92+ pthread_attr_getstacksize(attr, &size)
93+ g.stacklo = uintptr(unsafe.Pointer(&size)) - uintptr(size) + 4096
94+ pthread_attr_destroy(attr)
95+ free(unsafe.Pointer(attr))
96+}
M internal/fakecgo/go_setenv.go +1 -1
@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4-//go:build darwin
4+//go:build darwin || linux
55
66 package fakecgo
77
@@ -1,7 +1,7 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4-//go:build darwin4+//go:build darwin || linux
5 5
6 package fakecgo6 package fakecgo
7 7
M internal/fakecgo/go_util.go +1 -1
@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4-//go:build darwin
4+//go:build darwin || linux
55
66 package fakecgo
77
@@ -1,7 +1,7 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4-//go:build darwin4+//go:build darwin || linux
5 5
6 package fakecgo6 package fakecgo
7 7
M internal/fakecgo/iscgo.go +1 -1
@@ -2,7 +2,7 @@
22 // Use of this source code is governed by a BSD-style
33 // license that can be found in the LICENSE file.
44
5-//go:build darwin
5+//go:build darwin || linux
66
77 // The runtime package contains an uninitialized definition
88 // for runtime·iscgo. Override it to tell the runtime we're here.
@@ -2,7 +2,7 @@
2 // Use of this source code is governed by a BSD-style2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.3 // license that can be found in the LICENSE file.
4 4
5-//go:build darwin5+//go:build darwin || linux
6 6
7 // The runtime package contains an uninitialized definition7 // The runtime package contains an uninitialized definition
8 // for runtime·iscgo. Override it to tell the runtime we're here.8 // for runtime·iscgo. Override it to tell the runtime we're here.
M internal/fakecgo/libcgo.go +3 -3
@@ -1,13 +1,13 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4-//go:build darwin
4+//go:build darwin || linux
55
66 package fakecgo
77
88 type size_t uintptr
9-type sigset_t [128]byte // TODO: figure out how big this should be
10-type pthread_attr_t [56]byte // TODO: figure out how big this should be
9+type sigset_t [128]byte
10+type pthread_attr_t [64]byte
1111 type pthread_t int
1212
1313 // for pthread_sigmask:
@@ -1,13 +1,13 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4-//go:build darwin4+//go:build darwin || linux
5 5
6 package fakecgo6 package fakecgo
7 7
8 type size_t uintptr8 type size_t uintptr
9-type sigset_t [128]byte // TODO: figure out how big this should be9+type sigset_t [128]byte
10-type pthread_attr_t [56]byte // TODO: figure out how big this should be10+type pthread_attr_t [64]byte
11 type pthread_t int11 type pthread_t int
12 12
13 // for pthread_sigmask:13 // for pthread_sigmask:
M internal/fakecgo/setenv.go +1 -1
@@ -2,7 +2,7 @@
22 // Use of this source code is governed by a BSD-style
33 // license that can be found in the LICENSE file.
44
5-//go:build darwin
5+//go:build darwin || linux
66
77 package fakecgo
88
@@ -2,7 +2,7 @@
2 // Use of this source code is governed by a BSD-style2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.3 // license that can be found in the LICENSE file.
4 4
5-//go:build darwin5+//go:build darwin || linux
6 6
7 package fakecgo7 package fakecgo
8 8
M internal/fakecgo/symbols.go +1 -1
@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4-//go:build darwin
4+//go:build darwin || linux
55
66 package fakecgo
77
@@ -1,7 +1,7 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4-//go:build darwin4+//go:build darwin || linux
5 5
6 package fakecgo6 package fakecgo
7 7
A internal/fakecgo/symbols_linux.go +27 -0
@@ -0,0 +1,27 @@
1+// SPDX-License-Identifier: Apache-2.0
2+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3+
4+package fakecgo
5+
6+// pthread_attr_init will get us the wrong version on glibc - but this doesn't matter, since the memory we
7+// provide is zeroed - which will lead the correct result again
8+
9+//go:cgo_import_dynamic purego_pthread_attr_init pthread_attr_init "libpthread.so.0"
10+//go:cgo_import_dynamic purego_pthread_attr_getstacksize pthread_attr_getstacksize "libpthread.so.0"
11+//go:cgo_import_dynamic purego_pthread_attr_destroy pthread_attr_destroy "libpthread.so.0"
12+//go:cgo_import_dynamic purego_pthread_sigmask pthread_sigmask "libpthread.so.0"
13+//go:cgo_import_dynamic purego_pthread_create pthread_create "libpthread.so.0"
14+//go:cgo_import_dynamic purego_pthread_detach pthread_detach "libpthread.so.0"
15+//go:cgo_import_dynamic purego_setenv setenv "libc.so.6"
16+//go:cgo_import_dynamic purego_unsetenv unsetenv "libc.so.6"
17+//go:cgo_import_dynamic purego_malloc malloc "libc.so.6"
18+//go:cgo_import_dynamic purego_free free "libc.so.6"
19+//go:cgo_import_dynamic purego_nanosleep nanosleep "libc.so.6"
20+//go:cgo_import_dynamic purego_sigfillset sigfillset "libc.so.6"
21+//go:cgo_import_dynamic purego_abort abort "libc.so.6"
22+
23+// on amd64 we don't need the following lines - on 386 we do...
24+// anyway - with those lines the output is better (but doesn't matter) - without it on amd64 we get multiple DT_NEEDED with "libc.so.6" etc
25+
26+//go:cgo_import_dynamic _ _ "libpthread.so.0"
27+//go:cgo_import_dynamic _ _ "libc.so.6"
@@ -0,0 +1,27 @@
1+// SPDX-License-Identifier: Apache-2.0
2+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3+
4+package fakecgo
5+
6+// pthread_attr_init will get us the wrong version on glibc - but this doesn't matter, since the memory we
7+// provide is zeroed - which will lead the correct result again
8+
9+//go:cgo_import_dynamic purego_pthread_attr_init pthread_attr_init "libpthread.so.0"
10+//go:cgo_import_dynamic purego_pthread_attr_getstacksize pthread_attr_getstacksize "libpthread.so.0"
11+//go:cgo_import_dynamic purego_pthread_attr_destroy pthread_attr_destroy "libpthread.so.0"
12+//go:cgo_import_dynamic purego_pthread_sigmask pthread_sigmask "libpthread.so.0"
13+//go:cgo_import_dynamic purego_pthread_create pthread_create "libpthread.so.0"
14+//go:cgo_import_dynamic purego_pthread_detach pthread_detach "libpthread.so.0"
15+//go:cgo_import_dynamic purego_setenv setenv "libc.so.6"
16+//go:cgo_import_dynamic purego_unsetenv unsetenv "libc.so.6"
17+//go:cgo_import_dynamic purego_malloc malloc "libc.so.6"
18+//go:cgo_import_dynamic purego_free free "libc.so.6"
19+//go:cgo_import_dynamic purego_nanosleep nanosleep "libc.so.6"
20+//go:cgo_import_dynamic purego_sigfillset sigfillset "libc.so.6"
21+//go:cgo_import_dynamic purego_abort abort "libc.so.6"
22+
23+// on amd64 we don't need the following lines - on 386 we do...
24+// anyway - with those lines the output is better (but doesn't matter) - without it on amd64 we get multiple DT_NEEDED with "libc.so.6" etc
25+
26+//go:cgo_import_dynamic _ _ "libpthread.so.0"
27+//go:cgo_import_dynamic _ _ "libc.so.6"
M internal/fakecgo/trampolines_amd64.s +1 -1
@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4-//go:build darwin
4+//go:build darwin || linux
55
66 /*
77 trampoline for emulating required C functions for cgo in go (see cgo.go)
@@ -1,7 +1,7 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4-//go:build darwin4+//go:build darwin || linux
5 5
6 /*6 /*
7 trampoline for emulating required C functions for cgo in go (see cgo.go)7 trampoline for emulating required C functions for cgo in go (see cgo.go)
M internal/fakecgo/trampolines_arm64.s +1 -1
@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4-//go:build darwin
4+//go:build darwin || linux
55
66 #include "textflag.h"
77 #include "go_asm.h"
@@ -1,7 +1,7 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4-//go:build darwin4+//go:build darwin || linux
5 5
6 #include "textflag.h"6 #include "textflag.h"
7 #include "go_asm.h"7 #include "go_asm.h"
R internal/fakecgo/trampolines_stubs_darwin.s → internal/fakecgo/trampolines_stubs.s +2 -0 renamed, 97% similar
@@ -1,6 +1,8 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4+//go:build darwin || linux
5+
46 #include "textflag.h"
57
68 // these stubs are here because it is not possible to go:linkname directly the C functions on darwin arm64
@@ -1,6 +1,8 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4+//go:build darwin || linux
5+
4 #include "textflag.h"6 #include "textflag.h"
5 7
6 // these stubs are here because it is not possible to go:linkname directly the C functions on darwin arm648 // these stubs are here because it is not possible to go:linkname directly the C functions on darwin arm64
R nocgo_darwin.go → nocgo.go +1 -1 renamed, 97% similar
@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4-//go:build !cgo
4+//go:build !cgo && (darwin || linux)
55
66 package purego
77
@@ -1,7 +1,7 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4-//go:build !cgo4+//go:build !cgo && (darwin || linux)
5 5
6 package purego6 package purego
7 7
A sys_linux_amd64.s +70 -0
@@ -0,0 +1,70 @@
1+// SPDX-License-Identifier: Apache-2.0
2+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3+
4+#include "textflag.h"
5+#include "go_asm.h"
6+
7+// syscall9X calls a function in libc on behalf of the syscall package.
8+// syscall9X takes a pointer to a struct like:
9+// struct {
10+// fn uintptr
11+// a1 uintptr
12+// a2 uintptr
13+// a3 uintptr
14+// a4 uintptr
15+// a5 uintptr
16+// a6 uintptr
17+// a7 uintptr
18+// a8 uintptr
19+// a9 uintptr
20+// r1 uintptr
21+// r2 uintptr
22+// err uintptr
23+// }
24+// syscall9X must be called on the g0 stack with the
25+// C calling convention (use libcCall).
26+GLOBL ·syscall9XABI0(SB), NOPTR|RODATA, $8
27+DATA ·syscall9XABI0(SB)/8, $syscall9X(SB)
28+TEXT syscall9X(SB), NOSPLIT, $0
29+ PUSHQ BP
30+ MOVQ SP, BP
31+ SUBQ $32, SP
32+ MOVQ DI, 24(BP) // save the pointer
33+
34+ MOVQ syscall9Args_f1(DI), X0 // f1
35+ MOVQ syscall9Args_f2(DI), X1 // f2
36+ MOVQ syscall9Args_f3(DI), X2 // f3
37+ MOVQ syscall9Args_f4(DI), X3 // f4
38+ MOVQ syscall9Args_f5(DI), X4 // f5
39+ MOVQ syscall9Args_f6(DI), X5 // f6
40+ MOVQ syscall9Args_f7(DI), X6 // f7
41+ MOVQ syscall9Args_f8(DI), X7 // f8
42+
43+ MOVQ syscall9Args_fn(DI), R10 // fn
44+ MOVQ syscall9Args_a2(DI), SI // a2
45+ MOVQ syscall9Args_a3(DI), DX // a3
46+ MOVQ syscall9Args_a4(DI), CX // a4
47+ MOVQ syscall9Args_a5(DI), R8 // a5
48+ MOVQ syscall9Args_a6(DI), R9 // a6
49+ MOVQ syscall9Args_a7(DI), R11 // a7
50+ MOVQ syscall9Args_a8(DI), R12 // a8
51+ MOVQ syscall9Args_a9(DI), R13 // a9
52+ MOVQ syscall9Args_a1(DI), DI // a1
53+
54+ // push the remaining paramters onto the stack
55+ MOVQ R11, 0(SP) // push a7
56+ MOVQ R12, 8(SP) // push a8
57+ MOVQ R13, 16(SP) // push a9
58+ XORL AX, AX // vararg: say "no float args"
59+
60+ CALL R10
61+
62+ MOVQ 24(BP), DI // get the pointer back
63+ MOVQ AX, syscall9Args_r1(DI) // r1
64+ MOVQ DX, syscall9Args_r2(DI) // r2
65+
66+ XORL AX, AX // no error (it's ignored anyway)
67+ ADDQ $32, SP
68+ MOVQ BP, SP
69+ POPQ BP
70+ RET
@@ -0,0 +1,70 @@
1+// SPDX-License-Identifier: Apache-2.0
2+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3+
4+#include "textflag.h"
5+#include "go_asm.h"
6+
7+// syscall9X calls a function in libc on behalf of the syscall package.
8+// syscall9X takes a pointer to a struct like:
9+// struct {
10+// fn uintptr
11+// a1 uintptr
12+// a2 uintptr
13+// a3 uintptr
14+// a4 uintptr
15+// a5 uintptr
16+// a6 uintptr
17+// a7 uintptr
18+// a8 uintptr
19+// a9 uintptr
20+// r1 uintptr
21+// r2 uintptr
22+// err uintptr
23+// }
24+// syscall9X must be called on the g0 stack with the
25+// C calling convention (use libcCall).
26+GLOBL ·syscall9XABI0(SB), NOPTR|RODATA, $8
27+DATA ·syscall9XABI0(SB)/8, $syscall9X(SB)
28+TEXT syscall9X(SB), NOSPLIT, $0
29+ PUSHQ BP
30+ MOVQ SP, BP
31+ SUBQ $32, SP
32+ MOVQ DI, 24(BP) // save the pointer
33+
34+ MOVQ syscall9Args_f1(DI), X0 // f1
35+ MOVQ syscall9Args_f2(DI), X1 // f2
36+ MOVQ syscall9Args_f3(DI), X2 // f3
37+ MOVQ syscall9Args_f4(DI), X3 // f4
38+ MOVQ syscall9Args_f5(DI), X4 // f5
39+ MOVQ syscall9Args_f6(DI), X5 // f6
40+ MOVQ syscall9Args_f7(DI), X6 // f7
41+ MOVQ syscall9Args_f8(DI), X7 // f8
42+
43+ MOVQ syscall9Args_fn(DI), R10 // fn
44+ MOVQ syscall9Args_a2(DI), SI // a2
45+ MOVQ syscall9Args_a3(DI), DX // a3
46+ MOVQ syscall9Args_a4(DI), CX // a4
47+ MOVQ syscall9Args_a5(DI), R8 // a5
48+ MOVQ syscall9Args_a6(DI), R9 // a6
49+ MOVQ syscall9Args_a7(DI), R11 // a7
50+ MOVQ syscall9Args_a8(DI), R12 // a8
51+ MOVQ syscall9Args_a9(DI), R13 // a9
52+ MOVQ syscall9Args_a1(DI), DI // a1
53+
54+ // push the remaining paramters onto the stack
55+ MOVQ R11, 0(SP) // push a7
56+ MOVQ R12, 8(SP) // push a8
57+ MOVQ R13, 16(SP) // push a9
58+ XORL AX, AX // vararg: say "no float args"
59+
60+ CALL R10
61+
62+ MOVQ 24(BP), DI // get the pointer back
63+ MOVQ AX, syscall9Args_r1(DI) // r1
64+ MOVQ DX, syscall9Args_r2(DI) // r2
65+
66+ XORL AX, AX // no error (it's ignored anyway)
67+ ADDQ $32, SP
68+ MOVQ BP, SP
69+ POPQ BP
70+ RET
A sys_linux_arm64.s +71 -0
@@ -0,0 +1,71 @@
1+// SPDX-License-Identifier: Apache-2.0
2+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3+
4+#include "textflag.h"
5+#include "go_asm.h"
6+
7+// syscall9X calls a function in libc on behalf of the syscall package.
8+// syscall9X takes a pointer to a struct like:
9+// struct {
10+// fn uintptr
11+// a1 uintptr
12+// a2 uintptr
13+// a3 uintptr
14+// a4 uintptr
15+// a5 uintptr
16+// a6 uintptr
17+// a7 uintptr
18+// a8 uintptr
19+// a9 uintptr
20+// r1 uintptr
21+// r2 uintptr
22+// err uintptr
23+// }
24+// syscall9X must be called on the g0 stack with the
25+// C calling convention (use libcCall).
26+GLOBL ·syscall9XABI0(SB), NOPTR|RODATA, $8
27+DATA ·syscall9XABI0(SB)/8, $syscall9X(SB)
28+TEXT syscall9X(SB), NOSPLIT, $0
29+ SUB $16, RSP // push structure pointer
30+ MOVD R0, 8(RSP)
31+
32+ FMOVD syscall9Args_f1(R0), F0 // f1
33+ FMOVD syscall9Args_f2(R0), F1 // f2
34+ FMOVD syscall9Args_f3(R0), F2 // f3
35+ FMOVD syscall9Args_f4(R0), F3 // f4
36+ FMOVD syscall9Args_f5(R0), F4 // f5
37+ FMOVD syscall9Args_f6(R0), F5 // f6
38+ FMOVD syscall9Args_f7(R0), F6 // f7
39+ FMOVD syscall9Args_f8(R0), F7 // f8
40+
41+ MOVD syscall9Args_fn(R0), R12 // fn
42+ MOVD syscall9Args_a2(R0), R1 // a2
43+ MOVD syscall9Args_a3(R0), R2 // a3
44+ MOVD syscall9Args_a4(R0), R3 // a4
45+ MOVD syscall9Args_a5(R0), R4 // a5
46+ MOVD syscall9Args_a6(R0), R5 // a6
47+ MOVD syscall9Args_a7(R0), R6 // a7
48+ MOVD syscall9Args_a8(R0), R7 // a8
49+ MOVD syscall9Args_a9(R0), R8 // a9
50+ MOVD syscall9Args_a1(R0), R0 // a1
51+
52+ // these may be float arguments
53+ // so we put them also where C expects floats
54+ FMOVD R0, F0 // a1
55+ FMOVD R1, F1 // a2
56+ FMOVD R2, F2 // a3
57+ FMOVD R3, F3 // a4
58+ FMOVD R4, F4 // a5
59+ FMOVD R5, F5 // a6
60+ FMOVD R6, F6 // a7
61+ FMOVD R7, F7 // a8
62+
63+ MOVD R8, (RSP) // push a9 onto stack
64+
65+ BL (R12)
66+
67+ MOVD 8(RSP), R2 // pop structure pointer
68+ ADD $16, RSP
69+ MOVD R0, syscall9Args_r1(R2) // save r1
70+ MOVD R1, syscall9Args_r2(R2) // save r2
71+ RET
@@ -0,0 +1,71 @@
1+// SPDX-License-Identifier: Apache-2.0
2+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3+
4+#include "textflag.h"
5+#include "go_asm.h"
6+
7+// syscall9X calls a function in libc on behalf of the syscall package.
8+// syscall9X takes a pointer to a struct like:
9+// struct {
10+// fn uintptr
11+// a1 uintptr
12+// a2 uintptr
13+// a3 uintptr
14+// a4 uintptr
15+// a5 uintptr
16+// a6 uintptr
17+// a7 uintptr
18+// a8 uintptr
19+// a9 uintptr
20+// r1 uintptr
21+// r2 uintptr
22+// err uintptr
23+// }
24+// syscall9X must be called on the g0 stack with the
25+// C calling convention (use libcCall).
26+GLOBL ·syscall9XABI0(SB), NOPTR|RODATA, $8
27+DATA ·syscall9XABI0(SB)/8, $syscall9X(SB)
28+TEXT syscall9X(SB), NOSPLIT, $0
29+ SUB $16, RSP // push structure pointer
30+ MOVD R0, 8(RSP)
31+
32+ FMOVD syscall9Args_f1(R0), F0 // f1
33+ FMOVD syscall9Args_f2(R0), F1 // f2
34+ FMOVD syscall9Args_f3(R0), F2 // f3
35+ FMOVD syscall9Args_f4(R0), F3 // f4
36+ FMOVD syscall9Args_f5(R0), F4 // f5
37+ FMOVD syscall9Args_f6(R0), F5 // f6
38+ FMOVD syscall9Args_f7(R0), F6 // f7
39+ FMOVD syscall9Args_f8(R0), F7 // f8
40+
41+ MOVD syscall9Args_fn(R0), R12 // fn
42+ MOVD syscall9Args_a2(R0), R1 // a2
43+ MOVD syscall9Args_a3(R0), R2 // a3
44+ MOVD syscall9Args_a4(R0), R3 // a4
45+ MOVD syscall9Args_a5(R0), R4 // a5
46+ MOVD syscall9Args_a6(R0), R5 // a6
47+ MOVD syscall9Args_a7(R0), R6 // a7
48+ MOVD syscall9Args_a8(R0), R7 // a8
49+ MOVD syscall9Args_a9(R0), R8 // a9
50+ MOVD syscall9Args_a1(R0), R0 // a1
51+
52+ // these may be float arguments
53+ // so we put them also where C expects floats
54+ FMOVD R0, F0 // a1
55+ FMOVD R1, F1 // a2
56+ FMOVD R2, F2 // a3
57+ FMOVD R3, F3 // a4
58+ FMOVD R4, F4 // a5
59+ FMOVD R5, F5 // a6
60+ FMOVD R6, F6 // a7
61+ FMOVD R7, F7 // a8
62+
63+ MOVD R8, (RSP) // push a9 onto stack
64+
65+ BL (R12)
66+
67+ MOVD 8(RSP), R2 // pop structure pointer
68+ ADD $16, RSP
69+ MOVD R0, syscall9Args_r1(R2) // save r1
70+ MOVD R1, syscall9Args_r2(R2) // save r2
71+ RET
M syscall.go +1 -1
@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4-//go:build darwin || windows
4+//go:build darwin || windows || linux
55
66 package purego
77
@@ -1,7 +1,7 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4-//go:build darwin || windows4+//go:build darwin || windows || linux
5 5
6 package purego6 package purego
7 7
A syscall_cgo_linux.go +29 -0
@@ -0,0 +1,29 @@
1+// SPDX-License-Identifier: Apache-2.0
2+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3+
4+//go:build cgo
5+
6+package purego
7+
8+import (
9+ "github.com/ebitengine/purego/internal/cgo"
10+)
11+
12+// this is linked to a C function from internal/cgo
13+var syscall9XABI0 uintptr
14+
15+// this is only here to make the assembly files happy :)
16+type syscall9Args struct {
17+ fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr
18+ f1, f2, f3, f4, f5, f6, f7, f8 float64
19+ r1, r2, err uintptr
20+}
21+
22+//go:nosplit
23+func syscall_syscall9X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) {
24+ return cgo.Syscall9X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9)
25+}
26+
27+func NewCallback(_ interface{}) uintptr {
28+ panic("purego: NewCallback not supported")
29+}
@@ -0,0 +1,29 @@
1+// SPDX-License-Identifier: Apache-2.0
2+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3+
4+//go:build cgo
5+
6+package purego
7+
8+import (
9+ "github.com/ebitengine/purego/internal/cgo"
10+)
11+
12+// this is linked to a C function from internal/cgo
13+var syscall9XABI0 uintptr
14+
15+// this is only here to make the assembly files happy :)
16+type syscall9Args struct {
17+ fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr
18+ f1, f2, f3, f4, f5, f6, f7, f8 float64
19+ r1, r2, err uintptr
20+}
21+
22+//go:nosplit
23+func syscall_syscall9X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) {
24+ return cgo.Syscall9X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9)
25+}
26+
27+func NewCallback(_ interface{}) uintptr {
28+ panic("purego: NewCallback not supported")
29+}
A syscall_nocgo_linux.go +34 -0
@@ -0,0 +1,34 @@
1+// SPDX-License-Identifier: Apache-2.0
2+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3+
4+//go:build !cgo && (amd64 || arm64)
5+
6+package purego
7+
8+import (
9+ "math"
10+ "unsafe"
11+)
12+
13+var syscall9XABI0 uintptr
14+
15+type syscall9Args struct {
16+ fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr
17+ f1, f2, f3, f4, f5, f6, f7, f8 float64
18+ r1, r2, err uintptr
19+}
20+
21+//go:nosplit
22+func syscall_syscall9X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) {
23+ args := syscall9Args{fn, a1, a2, a3, a4, a5, a6, a7, a8, a9,
24+ math.Float64frombits(uint64(a1)), math.Float64frombits(uint64(a2)), math.Float64frombits(uint64(a3)),
25+ math.Float64frombits(uint64(a4)), math.Float64frombits(uint64(a5)), math.Float64frombits(uint64(a6)),
26+ math.Float64frombits(uint64(a7)), math.Float64frombits(uint64(a8)),
27+ r1, r2, err}
28+ runtime_cgocall(syscall9XABI0, unsafe.Pointer(&args))
29+ return args.r1, args.r2, args.err
30+}
31+
32+func NewCallback(_ interface{}) uintptr {
33+ panic("purego: NewCallback not supported")
34+}
@@ -0,0 +1,34 @@
1+// SPDX-License-Identifier: Apache-2.0
2+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3+
4+//go:build !cgo && (amd64 || arm64)
5+
6+package purego
7+
8+import (
9+ "math"
10+ "unsafe"
11+)
12+
13+var syscall9XABI0 uintptr
14+
15+type syscall9Args struct {
16+ fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr
17+ f1, f2, f3, f4, f5, f6, f7, f8 float64
18+ r1, r2, err uintptr
19+}
20+
21+//go:nosplit
22+func syscall_syscall9X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) {
23+ args := syscall9Args{fn, a1, a2, a3, a4, a5, a6, a7, a8, a9,
24+ math.Float64frombits(uint64(a1)), math.Float64frombits(uint64(a2)), math.Float64frombits(uint64(a3)),
25+ math.Float64frombits(uint64(a4)), math.Float64frombits(uint64(a5)), math.Float64frombits(uint64(a6)),
26+ math.Float64frombits(uint64(a7)), math.Float64frombits(uint64(a8)),
27+ r1, r2, err}
28+ runtime_cgocall(syscall9XABI0, unsafe.Pointer(&args))
29+ return args.r1, args.r2, args.err
30+}
31+
32+func NewCallback(_ interface{}) uintptr {
33+ panic("purego: NewCallback not supported")
34+}

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