summaryrefslogtreecommitdiff
path: root/vendor/github.com/ebitengine/purego/internal
diff options
context:
space:
mode:
authormo khan <mo@mokhan.ca>2025-05-11 21:12:57 -0600
committermo khan <mo@mokhan.ca>2025-05-11 21:12:57 -0600
commit60440f90dca28e99a31dd328c5f6d5dc0f9b6a2e (patch)
tree2f54adf55086516f162f0a55a5347e6b25f7f176 /vendor/github.com/ebitengine/purego/internal
parent05ca9b8d3a9c7203a3a3b590beaa400900bd9007 (diff)
chore: vendor go dependencies
Diffstat (limited to 'vendor/github.com/ebitengine/purego/internal')
-rw-r--r--vendor/github.com/ebitengine/purego/internal/cgo/dlfcn_cgo_unix.go56
-rw-r--r--vendor/github.com/ebitengine/purego/internal/cgo/empty.go6
-rw-r--r--vendor/github.com/ebitengine/purego/internal/cgo/syscall_cgo_unix.go55
-rw-r--r--vendor/github.com/ebitengine/purego/internal/fakecgo/abi_amd64.h99
-rw-r--r--vendor/github.com/ebitengine/purego/internal/fakecgo/abi_arm64.h39
-rw-r--r--vendor/github.com/ebitengine/purego/internal/fakecgo/asm_amd64.s39
-rw-r--r--vendor/github.com/ebitengine/purego/internal/fakecgo/asm_arm64.s36
-rw-r--r--vendor/github.com/ebitengine/purego/internal/fakecgo/callbacks.go93
-rw-r--r--vendor/github.com/ebitengine/purego/internal/fakecgo/doc.go32
-rw-r--r--vendor/github.com/ebitengine/purego/internal/fakecgo/freebsd.go27
-rw-r--r--vendor/github.com/ebitengine/purego/internal/fakecgo/go_darwin_amd64.go73
-rw-r--r--vendor/github.com/ebitengine/purego/internal/fakecgo/go_darwin_arm64.go88
-rw-r--r--vendor/github.com/ebitengine/purego/internal/fakecgo/go_freebsd_amd64.go95
-rw-r--r--vendor/github.com/ebitengine/purego/internal/fakecgo/go_freebsd_arm64.go98
-rw-r--r--vendor/github.com/ebitengine/purego/internal/fakecgo/go_libinit.go69
-rw-r--r--vendor/github.com/ebitengine/purego/internal/fakecgo/go_linux_amd64.go95
-rw-r--r--vendor/github.com/ebitengine/purego/internal/fakecgo/go_linux_arm64.go98
-rw-r--r--vendor/github.com/ebitengine/purego/internal/fakecgo/go_setenv.go18
-rw-r--r--vendor/github.com/ebitengine/purego/internal/fakecgo/go_util.go37
-rw-r--r--vendor/github.com/ebitengine/purego/internal/fakecgo/iscgo.go19
-rw-r--r--vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo.go39
-rw-r--r--vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_darwin.go22
-rw-r--r--vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_freebsd.go16
-rw-r--r--vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_linux.go16
-rw-r--r--vendor/github.com/ebitengine/purego/internal/fakecgo/setenv.go19
-rw-r--r--vendor/github.com/ebitengine/purego/internal/fakecgo/symbols.go201
-rw-r--r--vendor/github.com/ebitengine/purego/internal/fakecgo/symbols_darwin.go29
-rw-r--r--vendor/github.com/ebitengine/purego/internal/fakecgo/symbols_freebsd.go29
-rw-r--r--vendor/github.com/ebitengine/purego/internal/fakecgo/symbols_linux.go29
-rw-r--r--vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_amd64.s104
-rw-r--r--vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_arm64.s72
-rw-r--r--vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_stubs.s90
-rw-r--r--vendor/github.com/ebitengine/purego/internal/strings/strings.go40
33 files changed, 1878 insertions, 0 deletions
diff --git a/vendor/github.com/ebitengine/purego/internal/cgo/dlfcn_cgo_unix.go b/vendor/github.com/ebitengine/purego/internal/cgo/dlfcn_cgo_unix.go
new file mode 100644
index 0000000..b09ecac
--- /dev/null
+++ b/vendor/github.com/ebitengine/purego/internal/cgo/dlfcn_cgo_unix.go
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2024 The Ebitengine Authors
+
+//go:build freebsd || linux
+
+package cgo
+
+/*
+ #cgo LDFLAGS: -ldl
+
+#include <dlfcn.h>
+#include <stdlib.h>
+*/
+import "C"
+
+import (
+ "errors"
+ "unsafe"
+)
+
+func Dlopen(filename string, flag int) (uintptr, error) {
+ cfilename := C.CString(filename)
+ defer C.free(unsafe.Pointer(cfilename))
+ handle := C.dlopen(cfilename, C.int(flag))
+ if handle == nil {
+ return 0, errors.New(C.GoString(C.dlerror()))
+ }
+ return uintptr(handle), nil
+}
+
+func Dlsym(handle uintptr, symbol string) (uintptr, error) {
+ csymbol := C.CString(symbol)
+ defer C.free(unsafe.Pointer(csymbol))
+ symbolAddr := C.dlsym(*(*unsafe.Pointer)(unsafe.Pointer(&handle)), csymbol)
+ if symbolAddr == nil {
+ return 0, errors.New(C.GoString(C.dlerror()))
+ }
+ return uintptr(symbolAddr), nil
+}
+
+func Dlclose(handle uintptr) error {
+ result := C.dlclose(*(*unsafe.Pointer)(unsafe.Pointer(&handle)))
+ if result != 0 {
+ return errors.New(C.GoString(C.dlerror()))
+ }
+ return nil
+}
+
+// all that is needed is to assign each dl function because then its
+// symbol will then be made available to the linker and linked to inside dlfcn.go
+var (
+ _ = C.dlopen
+ _ = C.dlsym
+ _ = C.dlerror
+ _ = C.dlclose
+)
diff --git a/vendor/github.com/ebitengine/purego/internal/cgo/empty.go b/vendor/github.com/ebitengine/purego/internal/cgo/empty.go
new file mode 100644
index 0000000..1d7cffe
--- /dev/null
+++ b/vendor/github.com/ebitengine/purego/internal/cgo/empty.go
@@ -0,0 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2024 The Ebitengine Authors
+
+package cgo
+
+// Empty so that importing this package doesn't cause issue for certain platforms.
diff --git a/vendor/github.com/ebitengine/purego/internal/cgo/syscall_cgo_unix.go b/vendor/github.com/ebitengine/purego/internal/cgo/syscall_cgo_unix.go
new file mode 100644
index 0000000..37ff24d
--- /dev/null
+++ b/vendor/github.com/ebitengine/purego/internal/cgo/syscall_cgo_unix.go
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build freebsd || (linux && !(arm64 || amd64))
+
+package cgo
+
+// this file is placed inside internal/cgo and not package purego
+// because Cgo and assembly files can't be in the same package.
+
+/*
+ #cgo LDFLAGS: -ldl
+
+#include <stdint.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <assert.h>
+
+typedef struct syscall15Args {
+ uintptr_t fn;
+ uintptr_t a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15;
+ uintptr_t f1, f2, f3, f4, f5, f6, f7, f8;
+ uintptr_t err;
+} syscall15Args;
+
+void syscall15(struct syscall15Args *args) {
+ assert((args->f1|args->f2|args->f3|args->f4|args->f5|args->f6|args->f7|args->f8) == 0);
+ 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, uintptr_t a10, uintptr_t a11, uintptr_t a12,
+ uintptr_t a13, uintptr_t a14, uintptr_t a15);
+ *(void**)(&func_name) = (void*)(args->fn);
+ uintptr_t r1 = func_name(args->a1,args->a2,args->a3,args->a4,args->a5,args->a6,args->a7,args->a8,args->a9,
+ args->a10,args->a11,args->a12,args->a13,args->a14,args->a15);
+ args->a1 = r1;
+ args->err = errno;
+}
+
+*/
+import "C"
+import "unsafe"
+
+// assign purego.syscall15XABI0 to the C version of this function.
+var Syscall15XABI0 = unsafe.Pointer(C.syscall15)
+
+//go:nosplit
+func Syscall15X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr) (r1, r2, err uintptr) {
+ args := C.syscall15Args{
+ C.uintptr_t(fn), C.uintptr_t(a1), C.uintptr_t(a2), C.uintptr_t(a3),
+ C.uintptr_t(a4), C.uintptr_t(a5), C.uintptr_t(a6),
+ C.uintptr_t(a7), C.uintptr_t(a8), C.uintptr_t(a9), C.uintptr_t(a10), C.uintptr_t(a11), C.uintptr_t(a12),
+ C.uintptr_t(a13), C.uintptr_t(a14), C.uintptr_t(a15), 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }
+ C.syscall15(&args)
+ return uintptr(args.a1), 0, uintptr(args.err)
+}
diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/abi_amd64.h b/vendor/github.com/ebitengine/purego/internal/fakecgo/abi_amd64.h
new file mode 100644
index 0000000..9949435
--- /dev/null
+++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/abi_amd64.h
@@ -0,0 +1,99 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Macros for transitioning from the host ABI to Go ABI0.
+//
+// These save the frame pointer, so in general, functions that use
+// these should have zero frame size to suppress the automatic frame
+// pointer, though it's harmless to not do this.
+
+#ifdef GOOS_windows
+
+// REGS_HOST_TO_ABI0_STACK is the stack bytes used by
+// PUSH_REGS_HOST_TO_ABI0.
+#define REGS_HOST_TO_ABI0_STACK (28*8 + 8)
+
+// PUSH_REGS_HOST_TO_ABI0 prepares for transitioning from
+// the host ABI to Go ABI0 code. It saves all registers that are
+// callee-save in the host ABI and caller-save in Go ABI0 and prepares
+// for entry to Go.
+//
+// Save DI SI BP BX R12 R13 R14 R15 X6-X15 registers and the DF flag.
+// Clear the DF flag for the Go ABI.
+// MXCSR matches the Go ABI, so we don't have to set that,
+// and Go doesn't modify it, so we don't have to save it.
+#define PUSH_REGS_HOST_TO_ABI0() \
+ PUSHFQ \
+ CLD \
+ ADJSP $(REGS_HOST_TO_ABI0_STACK - 8) \
+ MOVQ DI, (0*0)(SP) \
+ MOVQ SI, (1*8)(SP) \
+ MOVQ BP, (2*8)(SP) \
+ MOVQ BX, (3*8)(SP) \
+ MOVQ R12, (4*8)(SP) \
+ MOVQ R13, (5*8)(SP) \
+ MOVQ R14, (6*8)(SP) \
+ MOVQ R15, (7*8)(SP) \
+ MOVUPS X6, (8*8)(SP) \
+ MOVUPS X7, (10*8)(SP) \
+ MOVUPS X8, (12*8)(SP) \
+ MOVUPS X9, (14*8)(SP) \
+ MOVUPS X10, (16*8)(SP) \
+ MOVUPS X11, (18*8)(SP) \
+ MOVUPS X12, (20*8)(SP) \
+ MOVUPS X13, (22*8)(SP) \
+ MOVUPS X14, (24*8)(SP) \
+ MOVUPS X15, (26*8)(SP)
+
+#define POP_REGS_HOST_TO_ABI0() \
+ MOVQ (0*0)(SP), DI \
+ MOVQ (1*8)(SP), SI \
+ MOVQ (2*8)(SP), BP \
+ MOVQ (3*8)(SP), BX \
+ MOVQ (4*8)(SP), R12 \
+ MOVQ (5*8)(SP), R13 \
+ MOVQ (6*8)(SP), R14 \
+ MOVQ (7*8)(SP), R15 \
+ MOVUPS (8*8)(SP), X6 \
+ MOVUPS (10*8)(SP), X7 \
+ MOVUPS (12*8)(SP), X8 \
+ MOVUPS (14*8)(SP), X9 \
+ MOVUPS (16*8)(SP), X10 \
+ MOVUPS (18*8)(SP), X11 \
+ MOVUPS (20*8)(SP), X12 \
+ MOVUPS (22*8)(SP), X13 \
+ MOVUPS (24*8)(SP), X14 \
+ MOVUPS (26*8)(SP), X15 \
+ ADJSP $-(REGS_HOST_TO_ABI0_STACK - 8) \
+ POPFQ
+
+#else
+// SysV ABI
+
+#define REGS_HOST_TO_ABI0_STACK (6*8)
+
+// SysV MXCSR matches the Go ABI, so we don't have to set that,
+// and Go doesn't modify it, so we don't have to save it.
+// Both SysV and Go require DF to be cleared, so that's already clear.
+// The SysV and Go frame pointer conventions are compatible.
+#define PUSH_REGS_HOST_TO_ABI0() \
+ ADJSP $(REGS_HOST_TO_ABI0_STACK) \
+ MOVQ BP, (5*8)(SP) \
+ LEAQ (5*8)(SP), BP \
+ MOVQ BX, (0*8)(SP) \
+ MOVQ R12, (1*8)(SP) \
+ MOVQ R13, (2*8)(SP) \
+ MOVQ R14, (3*8)(SP) \
+ MOVQ R15, (4*8)(SP)
+
+#define POP_REGS_HOST_TO_ABI0() \
+ MOVQ (0*8)(SP), BX \
+ MOVQ (1*8)(SP), R12 \
+ MOVQ (2*8)(SP), R13 \
+ MOVQ (3*8)(SP), R14 \
+ MOVQ (4*8)(SP), R15 \
+ MOVQ (5*8)(SP), BP \
+ ADJSP $-(REGS_HOST_TO_ABI0_STACK)
+
+#endif
diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/abi_arm64.h b/vendor/github.com/ebitengine/purego/internal/fakecgo/abi_arm64.h
new file mode 100644
index 0000000..5d5061e
--- /dev/null
+++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/abi_arm64.h
@@ -0,0 +1,39 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Macros for transitioning from the host ABI to Go ABI0.
+//
+// These macros save and restore the callee-saved registers
+// from the stack, but they don't adjust stack pointer, so
+// the user should prepare stack space in advance.
+// SAVE_R19_TO_R28(offset) saves R19 ~ R28 to the stack space
+// of ((offset)+0*8)(RSP) ~ ((offset)+9*8)(RSP).
+//
+// SAVE_F8_TO_F15(offset) saves F8 ~ F15 to the stack space
+// of ((offset)+0*8)(RSP) ~ ((offset)+7*8)(RSP).
+//
+// R29 is not saved because Go will save and restore it.
+
+#define SAVE_R19_TO_R28(offset) \
+ STP (R19, R20), ((offset)+0*8)(RSP) \
+ STP (R21, R22), ((offset)+2*8)(RSP) \
+ STP (R23, R24), ((offset)+4*8)(RSP) \
+ STP (R25, R26), ((offset)+6*8)(RSP) \
+ STP (R27, g), ((offset)+8*8)(RSP)
+#define RESTORE_R19_TO_R28(offset) \
+ LDP ((offset)+0*8)(RSP), (R19, R20) \
+ LDP ((offset)+2*8)(RSP), (R21, R22) \
+ LDP ((offset)+4*8)(RSP), (R23, R24) \
+ LDP ((offset)+6*8)(RSP), (R25, R26) \
+ LDP ((offset)+8*8)(RSP), (R27, g) /* R28 */
+#define SAVE_F8_TO_F15(offset) \
+ FSTPD (F8, F9), ((offset)+0*8)(RSP) \
+ FSTPD (F10, F11), ((offset)+2*8)(RSP) \
+ FSTPD (F12, F13), ((offset)+4*8)(RSP) \
+ FSTPD (F14, F15), ((offset)+6*8)(RSP)
+#define RESTORE_F8_TO_F15(offset) \
+ FLDPD ((offset)+0*8)(RSP), (F8, F9) \
+ FLDPD ((offset)+2*8)(RSP), (F10, F11) \
+ FLDPD ((offset)+4*8)(RSP), (F12, F13) \
+ FLDPD ((offset)+6*8)(RSP), (F14, F15)
diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/asm_amd64.s b/vendor/github.com/ebitengine/purego/internal/fakecgo/asm_amd64.s
new file mode 100644
index 0000000..2b7eb57
--- /dev/null
+++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/asm_amd64.s
@@ -0,0 +1,39 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "textflag.h"
+#include "abi_amd64.h"
+
+// Called by C code generated by cmd/cgo.
+// func crosscall2(fn, a unsafe.Pointer, n int32, ctxt uintptr)
+// Saves C callee-saved registers and calls cgocallback with three arguments.
+// fn is the PC of a func(a unsafe.Pointer) function.
+// This signature is known to SWIG, so we can't change it.
+TEXT crosscall2(SB), NOSPLIT, $0-0
+ PUSH_REGS_HOST_TO_ABI0()
+
+ // Make room for arguments to cgocallback.
+ ADJSP $0x18
+
+#ifndef GOOS_windows
+ MOVQ DI, 0x0(SP) // fn
+ MOVQ SI, 0x8(SP) // arg
+
+ // Skip n in DX.
+ MOVQ CX, 0x10(SP) // ctxt
+
+#else
+ MOVQ CX, 0x0(SP) // fn
+ MOVQ DX, 0x8(SP) // arg
+
+ // Skip n in R8.
+ MOVQ R9, 0x10(SP) // ctxt
+
+#endif
+
+ CALL runtime·cgocallback(SB)
+
+ ADJSP $-0x18
+ POP_REGS_HOST_TO_ABI0()
+ RET
diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/asm_arm64.s b/vendor/github.com/ebitengine/purego/internal/fakecgo/asm_arm64.s
new file mode 100644
index 0000000..50e5261
--- /dev/null
+++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/asm_arm64.s
@@ -0,0 +1,36 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "textflag.h"
+#include "abi_arm64.h"
+
+// Called by C code generated by cmd/cgo.
+// func crosscall2(fn, a unsafe.Pointer, n int32, ctxt uintptr)
+// Saves C callee-saved registers and calls cgocallback with three arguments.
+// fn is the PC of a func(a unsafe.Pointer) function.
+TEXT crosscall2(SB), NOSPLIT|NOFRAME, $0
+/*
+ * We still need to save all callee save register as before, and then
+ * push 3 args for fn (R0, R1, R3), skipping R2.
+ * Also note that at procedure entry in gc world, 8(RSP) will be the
+ * first arg.
+ */
+ SUB $(8*24), RSP
+ STP (R0, R1), (8*1)(RSP)
+ MOVD R3, (8*3)(RSP)
+
+ SAVE_R19_TO_R28(8*4)
+ SAVE_F8_TO_F15(8*14)
+ STP (R29, R30), (8*22)(RSP)
+
+ // Initialize Go ABI environment
+ BL runtime·load_g(SB)
+ BL runtime·cgocallback(SB)
+
+ RESTORE_R19_TO_R28(8*4)
+ RESTORE_F8_TO_F15(8*14)
+ LDP (8*22)(RSP), (R29, R30)
+
+ ADD $(8*24), RSP
+ RET
diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/callbacks.go b/vendor/github.com/ebitengine/purego/internal/fakecgo/callbacks.go
new file mode 100644
index 0000000..f29e690
--- /dev/null
+++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/callbacks.go
@@ -0,0 +1,93 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build !cgo && (darwin || freebsd || linux)
+
+package fakecgo
+
+import (
+ _ "unsafe"
+)
+
+// TODO: decide if we need _runtime_cgo_panic_internal
+
+//go:linkname x_cgo_init_trampoline x_cgo_init_trampoline
+//go:linkname _cgo_init _cgo_init
+var x_cgo_init_trampoline byte
+var _cgo_init = &x_cgo_init_trampoline
+
+// Creates a new system thread without updating any Go state.
+//
+// This method is invoked during shared library loading to create a new OS
+// thread to perform the runtime initialization. This method is similar to
+// _cgo_sys_thread_start except that it doesn't update any Go state.
+
+//go:linkname x_cgo_thread_start_trampoline x_cgo_thread_start_trampoline
+//go:linkname _cgo_thread_start _cgo_thread_start
+var x_cgo_thread_start_trampoline byte
+var _cgo_thread_start = &x_cgo_thread_start_trampoline
+
+// Notifies that the runtime has been initialized.
+//
+// We currently block at every CGO entry point (via _cgo_wait_runtime_init_done)
+// to ensure that the runtime has been initialized before the CGO call is
+// executed. This is necessary for shared libraries where we kickoff runtime
+// initialization in a separate thread and return without waiting for this
+// thread to complete the init.
+
+//go:linkname x_cgo_notify_runtime_init_done_trampoline x_cgo_notify_runtime_init_done_trampoline
+//go:linkname _cgo_notify_runtime_init_done _cgo_notify_runtime_init_done
+var x_cgo_notify_runtime_init_done_trampoline byte
+var _cgo_notify_runtime_init_done = &x_cgo_notify_runtime_init_done_trampoline
+
+// Indicates whether a dummy thread key has been created or not.
+//
+// When calling go exported function from C, we register a destructor
+// callback, for a dummy thread key, by using pthread_key_create.
+
+//go:linkname _cgo_pthread_key_created _cgo_pthread_key_created
+var x_cgo_pthread_key_created uintptr
+var _cgo_pthread_key_created = &x_cgo_pthread_key_created
+
+// Set the x_crosscall2_ptr C function pointer variable point to crosscall2.
+// It's for the runtime package to call at init time.
+func set_crosscall2() {
+ // nothing needs to be done here for fakecgo
+ // because it's possible to just call cgocallback directly
+}
+
+//go:linkname _set_crosscall2 runtime.set_crosscall2
+var _set_crosscall2 = set_crosscall2
+
+// Store the g into the thread-specific value.
+// So that pthread_key_destructor will dropm when the thread is exiting.
+
+//go:linkname x_cgo_bindm_trampoline x_cgo_bindm_trampoline
+//go:linkname _cgo_bindm _cgo_bindm
+var x_cgo_bindm_trampoline byte
+var _cgo_bindm = &x_cgo_bindm_trampoline
+
+// TODO: decide if we need x_cgo_set_context_function
+// TODO: decide if we need _cgo_yield
+
+var (
+ // In Go 1.20 the race detector was rewritten to pure Go
+ // on darwin. This means that when CGO_ENABLED=0 is set
+ // fakecgo is built with race detector code. This is not
+ // good since this code is pretending to be C. The go:norace
+ // pragma is not enough, since it only applies to the native
+ // ABIInternal function. The ABIO wrapper (which is necessary,
+ // since all references to text symbols from assembly will use it)
+ // does not inherit the go:norace pragma, so it will still be
+ // instrumented by the race detector.
+ //
+ // To circumvent this issue, using closure calls in the
+ // assembly, which forces the compiler to use the ABIInternal
+ // native implementation (which has go:norace) instead.
+ threadentry_call = threadentry
+ x_cgo_init_call = x_cgo_init
+ x_cgo_setenv_call = x_cgo_setenv
+ x_cgo_unsetenv_call = x_cgo_unsetenv
+ x_cgo_thread_start_call = x_cgo_thread_start
+)
diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/doc.go b/vendor/github.com/ebitengine/purego/internal/fakecgo/doc.go
new file mode 100644
index 0000000..be82f7d
--- /dev/null
+++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/doc.go
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build !cgo && (darwin || freebsd || linux)
+
+// Package fakecgo implements the Cgo runtime (runtime/cgo) entirely in Go.
+// This allows code that calls into C to function properly when CGO_ENABLED=0.
+//
+// # Goals
+//
+// fakecgo attempts to replicate the same naming structure as in the runtime.
+// For example, functions that have the prefix "gcc_*" are named "go_*".
+// This makes it easier to port other GOOSs and GOARCHs as well as to keep
+// it in sync with runtime/cgo.
+//
+// # Support
+//
+// Currently, fakecgo only supports macOS on amd64 & arm64. It also cannot
+// be used with -buildmode=c-archive because that requires special initialization
+// that fakecgo does not implement at the moment.
+//
+// # Usage
+//
+// Using fakecgo is easy just import _ "github.com/ebitengine/purego" and then
+// set the environment variable CGO_ENABLED=0.
+// The recommended usage for fakecgo is to prefer using runtime/cgo if possible
+// but if cross-compiling or fast build times are important fakecgo is available.
+// Purego will pick which ever Cgo runtime is available and prefer the one that
+// comes with Go (runtime/cgo).
+package fakecgo
+
+//go:generate go run gen.go
diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/freebsd.go b/vendor/github.com/ebitengine/purego/internal/fakecgo/freebsd.go
new file mode 100644
index 0000000..bb73a70
--- /dev/null
+++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/freebsd.go
@@ -0,0 +1,27 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build freebsd && !cgo
+
+package fakecgo
+
+import _ "unsafe" // for go:linkname
+
+// Supply environ and __progname, because we don't
+// link against the standard FreeBSD crt0.o and the
+// libc dynamic library needs them.
+
+// Note: when building with cross-compiling or CGO_ENABLED=0, add
+// the following argument to `go` so that these symbols are defined by
+// making fakecgo the Cgo.
+// -gcflags="github.com/ebitengine/purego/internal/fakecgo=-std"
+
+//go:linkname _environ environ
+//go:linkname _progname __progname
+
+//go:cgo_export_dynamic environ
+//go:cgo_export_dynamic __progname
+
+var _environ uintptr
+var _progname uintptr
diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/go_darwin_amd64.go b/vendor/github.com/ebitengine/purego/internal/fakecgo/go_darwin_amd64.go
new file mode 100644
index 0000000..39f5ff1
--- /dev/null
+++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/go_darwin_amd64.go
@@ -0,0 +1,73 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build !cgo
+
+package fakecgo
+
+import "unsafe"
+
+//go:nosplit
+//go:norace
+func _cgo_sys_thread_start(ts *ThreadStart) {
+ var attr pthread_attr_t
+ var ign, oset sigset_t
+ var p pthread_t
+ var size size_t
+ var err int
+
+ sigfillset(&ign)
+ pthread_sigmask(SIG_SETMASK, &ign, &oset)
+
+ size = pthread_get_stacksize_np(pthread_self())
+ pthread_attr_init(&attr)
+ pthread_attr_setstacksize(&attr, size)
+ // Leave stacklo=0 and set stackhi=size; mstart will do the rest.
+ ts.g.stackhi = uintptr(size)
+
+ err = _cgo_try_pthread_create(&p, &attr, unsafe.Pointer(threadentry_trampolineABI0), ts)
+
+ pthread_sigmask(SIG_SETMASK, &oset, nil)
+
+ if err != 0 {
+ print("fakecgo: pthread_create failed: ")
+ println(err)
+ abort()
+ }
+}
+
+// threadentry_trampolineABI0 maps the C ABI to Go ABI then calls the Go function
+//
+//go:linkname x_threadentry_trampoline threadentry_trampoline
+var x_threadentry_trampoline byte
+var threadentry_trampolineABI0 = &x_threadentry_trampoline
+
+//go:nosplit
+//go:norace
+func threadentry(v unsafe.Pointer) unsafe.Pointer {
+ ts := *(*ThreadStart)(v)
+ free(v)
+
+ setg_trampoline(setg_func, uintptr(unsafe.Pointer(ts.g)))
+
+ // faking funcs in go is a bit a... involved - but the following works :)
+ fn := uintptr(unsafe.Pointer(&ts.fn))
+ (*(*func())(unsafe.Pointer(&fn)))()
+
+ return nil
+}
+
+// here we will store a pointer to the provided setg func
+var setg_func uintptr
+
+//go:nosplit
+//go:norace
+func x_cgo_init(g *G, setg uintptr) {
+ var size size_t
+
+ setg_func = setg
+
+ size = pthread_get_stacksize_np(pthread_self())
+ g.stacklo = uintptr(unsafe.Add(unsafe.Pointer(&size), -size+4096))
+}
diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/go_darwin_arm64.go b/vendor/github.com/ebitengine/purego/internal/fakecgo/go_darwin_arm64.go
new file mode 100644
index 0000000..d0868f0
--- /dev/null
+++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/go_darwin_arm64.go
@@ -0,0 +1,88 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build !cgo
+
+package fakecgo
+
+import "unsafe"
+
+//go:nosplit
+//go:norace
+func _cgo_sys_thread_start(ts *ThreadStart) {
+ var attr pthread_attr_t
+ var ign, oset sigset_t
+ var p pthread_t
+ var size size_t
+ var err int
+
+ sigfillset(&ign)
+ pthread_sigmask(SIG_SETMASK, &ign, &oset)
+
+ size = pthread_get_stacksize_np(pthread_self())
+ pthread_attr_init(&attr)
+ pthread_attr_setstacksize(&attr, size)
+ // Leave stacklo=0 and set stackhi=size; mstart will do the rest.
+ ts.g.stackhi = uintptr(size)
+
+ err = _cgo_try_pthread_create(&p, &attr, unsafe.Pointer(threadentry_trampolineABI0), ts)
+
+ pthread_sigmask(SIG_SETMASK, &oset, nil)
+
+ if err != 0 {
+ print("fakecgo: pthread_create failed: ")
+ println(err)
+ abort()
+ }
+}
+
+// threadentry_trampolineABI0 maps the C ABI to Go ABI then calls the Go function
+//
+//go:linkname x_threadentry_trampoline threadentry_trampoline
+var x_threadentry_trampoline byte
+var threadentry_trampolineABI0 = &x_threadentry_trampoline
+
+//go:nosplit
+//go:norace
+func threadentry(v unsafe.Pointer) unsafe.Pointer {
+ ts := *(*ThreadStart)(v)
+ free(v)
+
+ // TODO: support ios
+ //#if TARGET_OS_IPHONE
+ // darwin_arm_init_thread_exception_port();
+ //#endif
+ setg_trampoline(setg_func, uintptr(unsafe.Pointer(ts.g)))
+
+ // faking funcs in go is a bit a... involved - but the following works :)
+ fn := uintptr(unsafe.Pointer(&ts.fn))
+ (*(*func())(unsafe.Pointer(&fn)))()
+
+ return nil
+}
+
+// here we will store a pointer to the provided setg func
+var setg_func uintptr
+
+// x_cgo_init(G *g, void (*setg)(void*)) (runtime/cgo/gcc_linux_amd64.c)
+// This get's called during startup, adjusts stacklo, and provides a pointer to setg_gcc for us
+// Additionally, if we set _cgo_init to non-null, go won't do it's own TLS setup
+// This function can't be go:systemstack since go is not in a state where the systemcheck would work.
+//
+//go:nosplit
+//go:norace
+func x_cgo_init(g *G, setg uintptr) {
+ var size size_t
+
+ setg_func = setg
+ size = pthread_get_stacksize_np(pthread_self())
+ g.stacklo = uintptr(unsafe.Add(unsafe.Pointer(&size), -size+4096))
+
+ //TODO: support ios
+ //#if TARGET_OS_IPHONE
+ // darwin_arm_init_mach_exception_handler();
+ // darwin_arm_init_thread_exception_port();
+ // init_working_dir();
+ //#endif
+}
diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/go_freebsd_amd64.go b/vendor/github.com/ebitengine/purego/internal/fakecgo/go_freebsd_amd64.go
new file mode 100644
index 0000000..c9ff715
--- /dev/null
+++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/go_freebsd_amd64.go
@@ -0,0 +1,95 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build !cgo
+
+package fakecgo
+
+import "unsafe"
+
+//go:nosplit
+func _cgo_sys_thread_start(ts *ThreadStart) {
+ var attr pthread_attr_t
+ var ign, oset sigset_t
+ var p pthread_t
+ var size size_t
+ var err int
+
+ //fprintf(stderr, "runtime/cgo: _cgo_sys_thread_start: fn=%p, g=%p\n", ts->fn, ts->g); // debug
+ sigfillset(&ign)
+ pthread_sigmask(SIG_SETMASK, &ign, &oset)
+
+ pthread_attr_init(&attr)
+ pthread_attr_getstacksize(&attr, &size)
+ // Leave stacklo=0 and set stackhi=size; mstart will do the rest.
+ ts.g.stackhi = uintptr(size)
+
+ err = _cgo_try_pthread_create(&p, &attr, unsafe.Pointer(threadentry_trampolineABI0), ts)
+
+ pthread_sigmask(SIG_SETMASK, &oset, nil)
+
+ if err != 0 {
+ print("fakecgo: pthread_create failed: ")
+ println(err)
+ abort()
+ }
+}
+
+// threadentry_trampolineABI0 maps the C ABI to Go ABI then calls the Go function
+//
+//go:linkname x_threadentry_trampoline threadentry_trampoline
+var x_threadentry_trampoline byte
+var threadentry_trampolineABI0 = &x_threadentry_trampoline
+
+//go:nosplit
+func threadentry(v unsafe.Pointer) unsafe.Pointer {
+ ts := *(*ThreadStart)(v)
+ free(v)
+
+ setg_trampoline(setg_func, uintptr(unsafe.Pointer(ts.g)))
+
+ // faking funcs in go is a bit a... involved - but the following works :)
+ fn := uintptr(unsafe.Pointer(&ts.fn))
+ (*(*func())(unsafe.Pointer(&fn)))()
+
+ return nil
+}
+
+// here we will store a pointer to the provided setg func
+var setg_func uintptr
+
+//go:nosplit
+func x_cgo_init(g *G, setg uintptr) {
+ var size size_t
+ var attr *pthread_attr_t
+
+ /* The memory sanitizer distributed with versions of clang
+ before 3.8 has a bug: if you call mmap before malloc, mmap
+ may return an address that is later overwritten by the msan
+ library. Avoid this problem by forcing a call to malloc
+ here, before we ever call malloc.
+
+ This is only required for the memory sanitizer, so it's
+ unfortunate that we always run it. It should be possible
+ to remove this when we no longer care about versions of
+ clang before 3.8. The test for this is
+ misc/cgo/testsanitizers.
+
+ GCC works hard to eliminate a seemingly unnecessary call to
+ malloc, so we actually use the memory we allocate. */
+
+ setg_func = setg
+ attr = (*pthread_attr_t)(malloc(unsafe.Sizeof(*attr)))
+ if attr == nil {
+ println("fakecgo: malloc failed")
+ abort()
+ }
+ pthread_attr_init(attr)
+ pthread_attr_getstacksize(attr, &size)
+ // runtime/cgo uses __builtin_frame_address(0) instead of `uintptr(unsafe.Pointer(&size))`
+ // but this should be OK since we are taking the address of the first variable in this function.
+ g.stacklo = uintptr(unsafe.Pointer(&size)) - uintptr(size) + 4096
+ pthread_attr_destroy(attr)
+ free(unsafe.Pointer(attr))
+}
diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/go_freebsd_arm64.go b/vendor/github.com/ebitengine/purego/internal/fakecgo/go_freebsd_arm64.go
new file mode 100644
index 0000000..e3a060b
--- /dev/null
+++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/go_freebsd_arm64.go
@@ -0,0 +1,98 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build !cgo
+
+package fakecgo
+
+import "unsafe"
+
+//go:nosplit
+func _cgo_sys_thread_start(ts *ThreadStart) {
+ var attr pthread_attr_t
+ var ign, oset sigset_t
+ var p pthread_t
+ var size size_t
+ var err int
+
+ // fprintf(stderr, "runtime/cgo: _cgo_sys_thread_start: fn=%p, g=%p\n", ts->fn, ts->g); // debug
+ sigfillset(&ign)
+ pthread_sigmask(SIG_SETMASK, &ign, &oset)
+
+ pthread_attr_init(&attr)
+ pthread_attr_getstacksize(&attr, &size)
+ // Leave stacklo=0 and set stackhi=size; mstart will do the rest.
+ ts.g.stackhi = uintptr(size)
+
+ err = _cgo_try_pthread_create(&p, &attr, unsafe.Pointer(threadentry_trampolineABI0), ts)
+
+ pthread_sigmask(SIG_SETMASK, &oset, nil)
+
+ if err != 0 {
+ print("fakecgo: pthread_create failed: ")
+ println(err)
+ abort()
+ }
+}
+
+// threadentry_trampolineABI0 maps the C ABI to Go ABI then calls the Go function
+//
+//go:linkname x_threadentry_trampoline threadentry_trampoline
+var x_threadentry_trampoline byte
+var threadentry_trampolineABI0 = &x_threadentry_trampoline
+
+//go:nosplit
+func threadentry(v unsafe.Pointer) unsafe.Pointer {
+ ts := *(*ThreadStart)(v)
+ free(v)
+
+ setg_trampoline(setg_func, uintptr(unsafe.Pointer(ts.g)))
+
+ // faking funcs in go is a bit a... involved - but the following works :)
+ fn := uintptr(unsafe.Pointer(&ts.fn))
+ (*(*func())(unsafe.Pointer(&fn)))()
+
+ return nil
+}
+
+// here we will store a pointer to the provided setg func
+var setg_func uintptr
+
+// x_cgo_init(G *g, void (*setg)(void*)) (runtime/cgo/gcc_linux_amd64.c)
+// This get's called during startup, adjusts stacklo, and provides a pointer to setg_gcc for us
+// Additionally, if we set _cgo_init to non-null, go won't do it's own TLS setup
+// This function can't be go:systemstack since go is not in a state where the systemcheck would work.
+//
+//go:nosplit
+func x_cgo_init(g *G, setg uintptr) {
+ var size size_t
+ var attr *pthread_attr_t
+
+ /* The memory sanitizer distributed with versions of clang
+ before 3.8 has a bug: if you call mmap before malloc, mmap
+ may return an address that is later overwritten by the msan
+ library. Avoid this problem by forcing a call to malloc
+ here, before we ever call malloc.
+
+ This is only required for the memory sanitizer, so it's
+ unfortunate that we always run it. It should be possible
+ to remove this when we no longer care about versions of
+ clang before 3.8. The test for this is
+ misc/cgo/testsanitizers.
+
+ GCC works hard to eliminate a seemingly unnecessary call to
+ malloc, so we actually use the memory we allocate. */
+
+ setg_func = setg
+ attr = (*pthread_attr_t)(malloc(unsafe.Sizeof(*attr)))
+ if attr == nil {
+ println("fakecgo: malloc failed")
+ abort()
+ }
+ pthread_attr_init(attr)
+ pthread_attr_getstacksize(attr, &size)
+ g.stacklo = uintptr(unsafe.Pointer(&size)) - uintptr(size) + 4096
+ pthread_attr_destroy(attr)
+ free(unsafe.Pointer(attr))
+}
diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/go_libinit.go b/vendor/github.com/ebitengine/purego/internal/fakecgo/go_libinit.go
new file mode 100644
index 0000000..d229d84
--- /dev/null
+++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/go_libinit.go
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build !cgo && (darwin || freebsd || linux)
+
+package fakecgo
+
+import (
+ "syscall"
+ "unsafe"
+)
+
+var (
+ pthread_g pthread_key_t
+
+ runtime_init_cond = PTHREAD_COND_INITIALIZER
+ runtime_init_mu = PTHREAD_MUTEX_INITIALIZER
+ runtime_init_done int
+)
+
+//go:nosplit
+func x_cgo_notify_runtime_init_done() {
+ pthread_mutex_lock(&runtime_init_mu)
+ runtime_init_done = 1
+ pthread_cond_broadcast(&runtime_init_cond)
+ pthread_mutex_unlock(&runtime_init_mu)
+}
+
+// Store the g into a thread-specific value associated with the pthread key pthread_g.
+// And pthread_key_destructor will dropm when the thread is exiting.
+func x_cgo_bindm(g unsafe.Pointer) {
+ // We assume this will always succeed, otherwise, there might be extra M leaking,
+ // when a C thread exits after a cgo call.
+ // We only invoke this function once per thread in runtime.needAndBindM,
+ // and the next calls just reuse the bound m.
+ pthread_setspecific(pthread_g, g)
+}
+
+// _cgo_try_pthread_create retries pthread_create if it fails with
+// EAGAIN.
+//
+//go:nosplit
+//go:norace
+func _cgo_try_pthread_create(thread *pthread_t, attr *pthread_attr_t, pfn unsafe.Pointer, arg *ThreadStart) int {
+ var ts syscall.Timespec
+ // tries needs to be the same type as syscall.Timespec.Nsec
+ // but the fields are int32 on 32bit and int64 on 64bit.
+ // tries is assigned to syscall.Timespec.Nsec in order to match its type.
+ tries := ts.Nsec
+ var err int
+
+ for tries = 0; tries < 20; tries++ {
+ // inlined this call because it ran out of stack when inlining was disabled
+ err = int(call5(pthread_createABI0, uintptr(unsafe.Pointer(thread)), uintptr(unsafe.Pointer(attr)), uintptr(pfn), uintptr(unsafe.Pointer(arg)), 0))
+ if err == 0 {
+ // inlined this call because it ran out of stack when inlining was disabled
+ call5(pthread_detachABI0, uintptr(*thread), 0, 0, 0, 0)
+ return 0
+ }
+ if err != int(syscall.EAGAIN) {
+ return err
+ }
+ ts.Sec = 0
+ ts.Nsec = (tries + 1) * 1000 * 1000 // Milliseconds.
+ // inlined this call because it ran out of stack when inlining was disabled
+ call5(nanosleepABI0, uintptr(unsafe.Pointer(&ts)), 0, 0, 0, 0)
+ }
+ return int(syscall.EAGAIN)
+}
diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/go_linux_amd64.go b/vendor/github.com/ebitengine/purego/internal/fakecgo/go_linux_amd64.go
new file mode 100644
index 0000000..c9ff715
--- /dev/null
+++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/go_linux_amd64.go
@@ -0,0 +1,95 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build !cgo
+
+package fakecgo
+
+import "unsafe"
+
+//go:nosplit
+func _cgo_sys_thread_start(ts *ThreadStart) {
+ var attr pthread_attr_t
+ var ign, oset sigset_t
+ var p pthread_t
+ var size size_t
+ var err int
+
+ //fprintf(stderr, "runtime/cgo: _cgo_sys_thread_start: fn=%p, g=%p\n", ts->fn, ts->g); // debug
+ sigfillset(&ign)
+ pthread_sigmask(SIG_SETMASK, &ign, &oset)
+
+ pthread_attr_init(&attr)
+ pthread_attr_getstacksize(&attr, &size)
+ // Leave stacklo=0 and set stackhi=size; mstart will do the rest.
+ ts.g.stackhi = uintptr(size)
+
+ err = _cgo_try_pthread_create(&p, &attr, unsafe.Pointer(threadentry_trampolineABI0), ts)
+
+ pthread_sigmask(SIG_SETMASK, &oset, nil)
+
+ if err != 0 {
+ print("fakecgo: pthread_create failed: ")
+ println(err)
+ abort()
+ }
+}
+
+// threadentry_trampolineABI0 maps the C ABI to Go ABI then calls the Go function
+//
+//go:linkname x_threadentry_trampoline threadentry_trampoline
+var x_threadentry_trampoline byte
+var threadentry_trampolineABI0 = &x_threadentry_trampoline
+
+//go:nosplit
+func threadentry(v unsafe.Pointer) unsafe.Pointer {
+ ts := *(*ThreadStart)(v)
+ free(v)
+
+ setg_trampoline(setg_func, uintptr(unsafe.Pointer(ts.g)))
+
+ // faking funcs in go is a bit a... involved - but the following works :)
+ fn := uintptr(unsafe.Pointer(&ts.fn))
+ (*(*func())(unsafe.Pointer(&fn)))()
+
+ return nil
+}
+
+// here we will store a pointer to the provided setg func
+var setg_func uintptr
+
+//go:nosplit
+func x_cgo_init(g *G, setg uintptr) {
+ var size size_t
+ var attr *pthread_attr_t
+
+ /* The memory sanitizer distributed with versions of clang
+ before 3.8 has a bug: if you call mmap before malloc, mmap
+ may return an address that is later overwritten by the msan
+ library. Avoid this problem by forcing a call to malloc
+ here, before we ever call malloc.
+
+ This is only required for the memory sanitizer, so it's
+ unfortunate that we always run it. It should be possible
+ to remove this when we no longer care about versions of
+ clang before 3.8. The test for this is
+ misc/cgo/testsanitizers.
+
+ GCC works hard to eliminate a seemingly unnecessary call to
+ malloc, so we actually use the memory we allocate. */
+
+ setg_func = setg
+ attr = (*pthread_attr_t)(malloc(unsafe.Sizeof(*attr)))
+ if attr == nil {
+ println("fakecgo: malloc failed")
+ abort()
+ }
+ pthread_attr_init(attr)
+ pthread_attr_getstacksize(attr, &size)
+ // runtime/cgo uses __builtin_frame_address(0) instead of `uintptr(unsafe.Pointer(&size))`
+ // but this should be OK since we are taking the address of the first variable in this function.
+ g.stacklo = uintptr(unsafe.Pointer(&size)) - uintptr(size) + 4096
+ pthread_attr_destroy(attr)
+ free(unsafe.Pointer(attr))
+}
diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/go_linux_arm64.go b/vendor/github.com/ebitengine/purego/internal/fakecgo/go_linux_arm64.go
new file mode 100644
index 0000000..a3b1cca
--- /dev/null
+++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/go_linux_arm64.go
@@ -0,0 +1,98 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build !cgo
+
+package fakecgo
+
+import "unsafe"
+
+//go:nosplit
+func _cgo_sys_thread_start(ts *ThreadStart) {
+ var attr pthread_attr_t
+ var ign, oset sigset_t
+ var p pthread_t
+ var size size_t
+ var err int
+
+ //fprintf(stderr, "runtime/cgo: _cgo_sys_thread_start: fn=%p, g=%p\n", ts->fn, ts->g); // debug
+ sigfillset(&ign)
+ pthread_sigmask(SIG_SETMASK, &ign, &oset)
+
+ pthread_attr_init(&attr)
+ pthread_attr_getstacksize(&attr, &size)
+ // Leave stacklo=0 and set stackhi=size; mstart will do the rest.
+ ts.g.stackhi = uintptr(size)
+
+ err = _cgo_try_pthread_create(&p, &attr, unsafe.Pointer(threadentry_trampolineABI0), ts)
+
+ pthread_sigmask(SIG_SETMASK, &oset, nil)
+
+ if err != 0 {
+ print("fakecgo: pthread_create failed: ")
+ println(err)
+ abort()
+ }
+}
+
+// threadentry_trampolineABI0 maps the C ABI to Go ABI then calls the Go function
+//
+//go:linkname x_threadentry_trampoline threadentry_trampoline
+var x_threadentry_trampoline byte
+var threadentry_trampolineABI0 = &x_threadentry_trampoline
+
+//go:nosplit
+func threadentry(v unsafe.Pointer) unsafe.Pointer {
+ ts := *(*ThreadStart)(v)
+ free(v)
+
+ setg_trampoline(setg_func, uintptr(unsafe.Pointer(ts.g)))
+
+ // faking funcs in go is a bit a... involved - but the following works :)
+ fn := uintptr(unsafe.Pointer(&ts.fn))
+ (*(*func())(unsafe.Pointer(&fn)))()
+
+ return nil
+}
+
+// here we will store a pointer to the provided setg func
+var setg_func uintptr
+
+// x_cgo_init(G *g, void (*setg)(void*)) (runtime/cgo/gcc_linux_amd64.c)
+// This get's called during startup, adjusts stacklo, and provides a pointer to setg_gcc for us
+// Additionally, if we set _cgo_init to non-null, go won't do it's own TLS setup
+// This function can't be go:systemstack since go is not in a state where the systemcheck would work.
+//
+//go:nosplit
+func x_cgo_init(g *G, setg uintptr) {
+ var size size_t
+ var attr *pthread_attr_t
+
+ /* The memory sanitizer distributed with versions of clang
+ before 3.8 has a bug: if you call mmap before malloc, mmap
+ may return an address that is later overwritten by the msan
+ library. Avoid this problem by forcing a call to malloc
+ here, before we ever call malloc.
+
+ This is only required for the memory sanitizer, so it's
+ unfortunate that we always run it. It should be possible
+ to remove this when we no longer care about versions of
+ clang before 3.8. The test for this is
+ misc/cgo/testsanitizers.
+
+ GCC works hard to eliminate a seemingly unnecessary call to
+ malloc, so we actually use the memory we allocate. */
+
+ setg_func = setg
+ attr = (*pthread_attr_t)(malloc(unsafe.Sizeof(*attr)))
+ if attr == nil {
+ println("fakecgo: malloc failed")
+ abort()
+ }
+ pthread_attr_init(attr)
+ pthread_attr_getstacksize(attr, &size)
+ g.stacklo = uintptr(unsafe.Pointer(&size)) - uintptr(size) + 4096
+ pthread_attr_destroy(attr)
+ free(unsafe.Pointer(attr))
+}
diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/go_setenv.go b/vendor/github.com/ebitengine/purego/internal/fakecgo/go_setenv.go
new file mode 100644
index 0000000..e42d84f
--- /dev/null
+++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/go_setenv.go
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build !cgo && (darwin || freebsd || linux)
+
+package fakecgo
+
+//go:nosplit
+//go:norace
+func x_cgo_setenv(arg *[2]*byte) {
+ setenv(arg[0], arg[1], 1)
+}
+
+//go:nosplit
+//go:norace
+func x_cgo_unsetenv(arg *[1]*byte) {
+ unsetenv(arg[0])
+}
diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/go_util.go b/vendor/github.com/ebitengine/purego/internal/fakecgo/go_util.go
new file mode 100644
index 0000000..0ac10d1
--- /dev/null
+++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/go_util.go
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build !cgo && (darwin || freebsd || linux)
+
+package fakecgo
+
+import "unsafe"
+
+// _cgo_thread_start is split into three parts in cgo since only one part is system dependent (keep it here for easier handling)
+
+// _cgo_thread_start(ThreadStart *arg) (runtime/cgo/gcc_util.c)
+// This get's called instead of the go code for creating new threads
+// -> pthread_* stuff is used, so threads are setup correctly for C
+// If this is missing, TLS is only setup correctly on thread 1!
+// This function should be go:systemstack instead of go:nosplit (but that requires runtime)
+//
+//go:nosplit
+//go:norace
+func x_cgo_thread_start(arg *ThreadStart) {
+ var ts *ThreadStart
+ // Make our own copy that can persist after we return.
+ // _cgo_tsan_acquire();
+ ts = (*ThreadStart)(malloc(unsafe.Sizeof(*ts)))
+ // _cgo_tsan_release();
+ if ts == nil {
+ println("fakecgo: out of memory in thread_start")
+ abort()
+ }
+ // *ts = *arg would cause a writebarrier so copy using slices
+ s1 := unsafe.Slice((*uintptr)(unsafe.Pointer(ts)), unsafe.Sizeof(*ts)/8)
+ s2 := unsafe.Slice((*uintptr)(unsafe.Pointer(arg)), unsafe.Sizeof(*arg)/8)
+ for i := range s2 {
+ s1[i] = s2[i]
+ }
+ _cgo_sys_thread_start(ts) // OS-dependent half
+}
diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/iscgo.go b/vendor/github.com/ebitengine/purego/internal/fakecgo/iscgo.go
new file mode 100644
index 0000000..28af41c
--- /dev/null
+++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/iscgo.go
@@ -0,0 +1,19 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build !cgo && (darwin || freebsd || linux)
+
+// The runtime package contains an uninitialized definition
+// for runtime·iscgo. Override it to tell the runtime we're here.
+// There are various function pointers that should be set too,
+// but those depend on dynamic linker magic to get initialized
+// correctly, and sometimes they break. This variable is a
+// backup: it depends only on old C style static linking rules.
+
+package fakecgo
+
+import _ "unsafe" // for go:linkname
+
+//go:linkname _iscgo runtime.iscgo
+var _iscgo bool = true
diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo.go b/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo.go
new file mode 100644
index 0000000..38f9441
--- /dev/null
+++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo.go
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build !cgo && (darwin || freebsd || linux)
+
+package fakecgo
+
+type (
+ size_t uintptr
+ // Sources:
+ // Darwin (32 bytes) - https://github.com/apple/darwin-xnu/blob/2ff845c2e033bd0ff64b5b6aa6063a1f8f65aa32/bsd/sys/_types.h#L74
+ // FreeBSD (32 bytes) - https://github.com/DoctorWkt/xv6-freebsd/blob/d2a294c2a984baed27676068b15ed9a29b06ab6f/include/signal.h#L98C9-L98C21
+ // Linux (128 bytes) - https://github.com/torvalds/linux/blob/ab75170520d4964f3acf8bb1f91d34cbc650688e/arch/x86/include/asm/signal.h#L25
+ sigset_t [128]byte
+ pthread_attr_t [64]byte
+ pthread_t int
+ pthread_key_t uint64
+)
+
+// for pthread_sigmask:
+
+type sighow int32
+
+const (
+ SIG_BLOCK sighow = 0
+ SIG_UNBLOCK sighow = 1
+ SIG_SETMASK sighow = 2
+)
+
+type G struct {
+ stacklo uintptr
+ stackhi uintptr
+}
+
+type ThreadStart struct {
+ g *G
+ tls *uintptr
+ fn uintptr
+}
diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_darwin.go b/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_darwin.go
new file mode 100644
index 0000000..af14833
--- /dev/null
+++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_darwin.go
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build !cgo
+
+package fakecgo
+
+type (
+ pthread_mutex_t struct {
+ sig int64
+ opaque [56]byte
+ }
+ pthread_cond_t struct {
+ sig int64
+ opaque [40]byte
+ }
+)
+
+var (
+ PTHREAD_COND_INITIALIZER = pthread_cond_t{sig: 0x3CB0B1BB}
+ PTHREAD_MUTEX_INITIALIZER = pthread_mutex_t{sig: 0x32AAABA7}
+)
diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_freebsd.go b/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_freebsd.go
new file mode 100644
index 0000000..ca1f722
--- /dev/null
+++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_freebsd.go
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build !cgo
+
+package fakecgo
+
+type (
+ pthread_cond_t uintptr
+ pthread_mutex_t uintptr
+)
+
+var (
+ PTHREAD_COND_INITIALIZER = pthread_cond_t(0)
+ PTHREAD_MUTEX_INITIALIZER = pthread_mutex_t(0)
+)
diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_linux.go b/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_linux.go
new file mode 100644
index 0000000..c4b6e9e
--- /dev/null
+++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_linux.go
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build !cgo
+
+package fakecgo
+
+type (
+ pthread_cond_t [48]byte
+ pthread_mutex_t [48]byte
+)
+
+var (
+ PTHREAD_COND_INITIALIZER = pthread_cond_t{}
+ PTHREAD_MUTEX_INITIALIZER = pthread_mutex_t{}
+)
diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/setenv.go b/vendor/github.com/ebitengine/purego/internal/fakecgo/setenv.go
new file mode 100644
index 0000000..f30af0e
--- /dev/null
+++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/setenv.go
@@ -0,0 +1,19 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build !cgo && (darwin || freebsd || linux)
+
+package fakecgo
+
+import _ "unsafe" // for go:linkname
+
+//go:linkname x_cgo_setenv_trampoline x_cgo_setenv_trampoline
+//go:linkname _cgo_setenv runtime._cgo_setenv
+var x_cgo_setenv_trampoline byte
+var _cgo_setenv = &x_cgo_setenv_trampoline
+
+//go:linkname x_cgo_unsetenv_trampoline x_cgo_unsetenv_trampoline
+//go:linkname _cgo_unsetenv runtime._cgo_unsetenv
+var x_cgo_unsetenv_trampoline byte
+var _cgo_unsetenv = &x_cgo_unsetenv_trampoline
diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/symbols.go b/vendor/github.com/ebitengine/purego/internal/fakecgo/symbols.go
new file mode 100644
index 0000000..7a3a1bb
--- /dev/null
+++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/symbols.go
@@ -0,0 +1,201 @@
+// Code generated by 'go generate' with gen.go. DO NOT EDIT.
+
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build !cgo && (darwin || freebsd || linux)
+
+package fakecgo
+
+import (
+ "syscall"
+ "unsafe"
+)
+
+// setg_trampoline calls setg with the G provided
+func setg_trampoline(setg uintptr, G uintptr)
+
+// call5 takes fn the C function and 5 arguments and calls the function with those arguments
+func call5(fn, a1, a2, a3, a4, a5 uintptr) uintptr
+
+//go:nosplit
+func malloc(size uintptr) unsafe.Pointer {
+ ret := call5(mallocABI0, uintptr(size), 0, 0, 0, 0)
+ // this indirection is to avoid go vet complaining about possible misuse of unsafe.Pointer
+ return *(*unsafe.Pointer)(unsafe.Pointer(&ret))
+}
+
+//go:nosplit
+func free(ptr unsafe.Pointer) {
+ call5(freeABI0, uintptr(ptr), 0, 0, 0, 0)
+}
+
+//go:nosplit
+func setenv(name *byte, value *byte, overwrite int32) int32 {
+ return int32(call5(setenvABI0, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(value)), uintptr(overwrite), 0, 0))
+}
+
+//go:nosplit
+func unsetenv(name *byte) int32 {
+ return int32(call5(unsetenvABI0, uintptr(unsafe.Pointer(name)), 0, 0, 0, 0))
+}
+
+//go:nosplit
+func sigfillset(set *sigset_t) int32 {
+ return int32(call5(sigfillsetABI0, uintptr(unsafe.Pointer(set)), 0, 0, 0, 0))
+}
+
+//go:nosplit
+func nanosleep(ts *syscall.Timespec, rem *syscall.Timespec) int32 {
+ return int32(call5(nanosleepABI0, uintptr(unsafe.Pointer(ts)), uintptr(unsafe.Pointer(rem)), 0, 0, 0))
+}
+
+//go:nosplit
+func abort() {
+ call5(abortABI0, 0, 0, 0, 0, 0)
+}
+
+//go:nosplit
+func pthread_attr_init(attr *pthread_attr_t) int32 {
+ return int32(call5(pthread_attr_initABI0, uintptr(unsafe.Pointer(attr)), 0, 0, 0, 0))
+}
+
+//go:nosplit
+func pthread_create(thread *pthread_t, attr *pthread_attr_t, start unsafe.Pointer, arg unsafe.Pointer) int32 {
+ return int32(call5(pthread_createABI0, uintptr(unsafe.Pointer(thread)), uintptr(unsafe.Pointer(attr)), uintptr(start), uintptr(arg), 0))
+}
+
+//go:nosplit
+func pthread_detach(thread pthread_t) int32 {
+ return int32(call5(pthread_detachABI0, uintptr(thread), 0, 0, 0, 0))
+}
+
+//go:nosplit
+func pthread_sigmask(how sighow, ign *sigset_t, oset *sigset_t) int32 {
+ return int32(call5(pthread_sigmaskABI0, uintptr(how), uintptr(unsafe.Pointer(ign)), uintptr(unsafe.Pointer(oset)), 0, 0))
+}
+
+//go:nosplit
+func pthread_self() pthread_t {
+ return pthread_t(call5(pthread_selfABI0, 0, 0, 0, 0, 0))
+}
+
+//go:nosplit
+func pthread_get_stacksize_np(thread pthread_t) size_t {
+ return size_t(call5(pthread_get_stacksize_npABI0, uintptr(thread), 0, 0, 0, 0))
+}
+
+//go:nosplit
+func pthread_attr_getstacksize(attr *pthread_attr_t, stacksize *size_t) int32 {
+ return int32(call5(pthread_attr_getstacksizeABI0, uintptr(unsafe.Pointer(attr)), uintptr(unsafe.Pointer(stacksize)), 0, 0, 0))
+}
+
+//go:nosplit
+func pthread_attr_setstacksize(attr *pthread_attr_t, size size_t) int32 {
+ return int32(call5(pthread_attr_setstacksizeABI0, uintptr(unsafe.Pointer(attr)), uintptr(size), 0, 0, 0))
+}
+
+//go:nosplit
+func pthread_attr_destroy(attr *pthread_attr_t) int32 {
+ return int32(call5(pthread_attr_destroyABI0, uintptr(unsafe.Pointer(attr)), 0, 0, 0, 0))
+}
+
+//go:nosplit
+func pthread_mutex_lock(mutex *pthread_mutex_t) int32 {
+ return int32(call5(pthread_mutex_lockABI0, uintptr(unsafe.Pointer(mutex)), 0, 0, 0, 0))
+}
+
+//go:nosplit
+func pthread_mutex_unlock(mutex *pthread_mutex_t) int32 {
+ return int32(call5(pthread_mutex_unlockABI0, uintptr(unsafe.Pointer(mutex)), 0, 0, 0, 0))
+}
+
+//go:nosplit
+func pthread_cond_broadcast(cond *pthread_cond_t) int32 {
+ return int32(call5(pthread_cond_broadcastABI0, uintptr(unsafe.Pointer(cond)), 0, 0, 0, 0))
+}
+
+//go:nosplit
+func pthread_setspecific(key pthread_key_t, value unsafe.Pointer) int32 {
+ return int32(call5(pthread_setspecificABI0, uintptr(key), uintptr(value), 0, 0, 0))
+}
+
+//go:linkname _malloc _malloc
+var _malloc uintptr
+var mallocABI0 = uintptr(unsafe.Pointer(&_malloc))
+
+//go:linkname _free _free
+var _free uintptr
+var freeABI0 = uintptr(unsafe.Pointer(&_free))
+
+//go:linkname _setenv _setenv
+var _setenv uintptr
+var setenvABI0 = uintptr(unsafe.Pointer(&_setenv))
+
+//go:linkname _unsetenv _unsetenv
+var _unsetenv uintptr
+var unsetenvABI0 = uintptr(unsafe.Pointer(&_unsetenv))
+
+//go:linkname _sigfillset _sigfillset
+var _sigfillset uintptr
+var sigfillsetABI0 = uintptr(unsafe.Pointer(&_sigfillset))
+
+//go:linkname _nanosleep _nanosleep
+var _nanosleep uintptr
+var nanosleepABI0 = uintptr(unsafe.Pointer(&_nanosleep))
+
+//go:linkname _abort _abort
+var _abort uintptr
+var abortABI0 = uintptr(unsafe.Pointer(&_abort))
+
+//go:linkname _pthread_attr_init _pthread_attr_init
+var _pthread_attr_init uintptr
+var pthread_attr_initABI0 = uintptr(unsafe.Pointer(&_pthread_attr_init))
+
+//go:linkname _pthread_create _pthread_create
+var _pthread_create uintptr
+var pthread_createABI0 = uintptr(unsafe.Pointer(&_pthread_create))
+
+//go:linkname _pthread_detach _pthread_detach
+var _pthread_detach uintptr
+var pthread_detachABI0 = uintptr(unsafe.Pointer(&_pthread_detach))
+
+//go:linkname _pthread_sigmask _pthread_sigmask
+var _pthread_sigmask uintptr
+var pthread_sigmaskABI0 = uintptr(unsafe.Pointer(&_pthread_sigmask))
+
+//go:linkname _pthread_self _pthread_self
+var _pthread_self uintptr
+var pthread_selfABI0 = uintptr(unsafe.Pointer(&_pthread_self))
+
+//go:linkname _pthread_get_stacksize_np _pthread_get_stacksize_np
+var _pthread_get_stacksize_np uintptr
+var pthread_get_stacksize_npABI0 = uintptr(unsafe.Pointer(&_pthread_get_stacksize_np))
+
+//go:linkname _pthread_attr_getstacksize _pthread_attr_getstacksize
+var _pthread_attr_getstacksize uintptr
+var pthread_attr_getstacksizeABI0 = uintptr(unsafe.Pointer(&_pthread_attr_getstacksize))
+
+//go:linkname _pthread_attr_setstacksize _pthread_attr_setstacksize
+var _pthread_attr_setstacksize uintptr
+var pthread_attr_setstacksizeABI0 = uintptr(unsafe.Pointer(&_pthread_attr_setstacksize))
+
+//go:linkname _pthread_attr_destroy _pthread_attr_destroy
+var _pthread_attr_destroy uintptr
+var pthread_attr_destroyABI0 = uintptr(unsafe.Pointer(&_pthread_attr_destroy))
+
+//go:linkname _pthread_mutex_lock _pthread_mutex_lock
+var _pthread_mutex_lock uintptr
+var pthread_mutex_lockABI0 = uintptr(unsafe.Pointer(&_pthread_mutex_lock))
+
+//go:linkname _pthread_mutex_unlock _pthread_mutex_unlock
+var _pthread_mutex_unlock uintptr
+var pthread_mutex_unlockABI0 = uintptr(unsafe.Pointer(&_pthread_mutex_unlock))
+
+//go:linkname _pthread_cond_broadcast _pthread_cond_broadcast
+var _pthread_cond_broadcast uintptr
+var pthread_cond_broadcastABI0 = uintptr(unsafe.Pointer(&_pthread_cond_broadcast))
+
+//go:linkname _pthread_setspecific _pthread_setspecific
+var _pthread_setspecific uintptr
+var pthread_setspecificABI0 = uintptr(unsafe.Pointer(&_pthread_setspecific))
diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/symbols_darwin.go b/vendor/github.com/ebitengine/purego/internal/fakecgo/symbols_darwin.go
new file mode 100644
index 0000000..54aaa46
--- /dev/null
+++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/symbols_darwin.go
@@ -0,0 +1,29 @@
+// Code generated by 'go generate' with gen.go. DO NOT EDIT.
+
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build !cgo
+
+package fakecgo
+
+//go:cgo_import_dynamic purego_malloc malloc "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic purego_free free "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic purego_setenv setenv "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic purego_unsetenv unsetenv "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic purego_sigfillset sigfillset "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic purego_nanosleep nanosleep "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic purego_abort abort "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic purego_pthread_attr_init pthread_attr_init "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic purego_pthread_create pthread_create "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic purego_pthread_detach pthread_detach "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic purego_pthread_sigmask pthread_sigmask "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic purego_pthread_self pthread_self "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic purego_pthread_get_stacksize_np pthread_get_stacksize_np "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic purego_pthread_attr_getstacksize pthread_attr_getstacksize "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic purego_pthread_attr_setstacksize pthread_attr_setstacksize "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic purego_pthread_attr_destroy pthread_attr_destroy "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic purego_pthread_mutex_lock pthread_mutex_lock "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic purego_pthread_mutex_unlock pthread_mutex_unlock "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic purego_pthread_cond_broadcast pthread_cond_broadcast "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic purego_pthread_setspecific pthread_setspecific "/usr/lib/libSystem.B.dylib"
diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/symbols_freebsd.go b/vendor/github.com/ebitengine/purego/internal/fakecgo/symbols_freebsd.go
new file mode 100644
index 0000000..8153811
--- /dev/null
+++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/symbols_freebsd.go
@@ -0,0 +1,29 @@
+// Code generated by 'go generate' with gen.go. DO NOT EDIT.
+
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build !cgo
+
+package fakecgo
+
+//go:cgo_import_dynamic purego_malloc malloc "libc.so.7"
+//go:cgo_import_dynamic purego_free free "libc.so.7"
+//go:cgo_import_dynamic purego_setenv setenv "libc.so.7"
+//go:cgo_import_dynamic purego_unsetenv unsetenv "libc.so.7"
+//go:cgo_import_dynamic purego_sigfillset sigfillset "libc.so.7"
+//go:cgo_import_dynamic purego_nanosleep nanosleep "libc.so.7"
+//go:cgo_import_dynamic purego_abort abort "libc.so.7"
+//go:cgo_import_dynamic purego_pthread_attr_init pthread_attr_init "libpthread.so"
+//go:cgo_import_dynamic purego_pthread_create pthread_create "libpthread.so"
+//go:cgo_import_dynamic purego_pthread_detach pthread_detach "libpthread.so"
+//go:cgo_import_dynamic purego_pthread_sigmask pthread_sigmask "libpthread.so"
+//go:cgo_import_dynamic purego_pthread_self pthread_self "libpthread.so"
+//go:cgo_import_dynamic purego_pthread_get_stacksize_np pthread_get_stacksize_np "libpthread.so"
+//go:cgo_import_dynamic purego_pthread_attr_getstacksize pthread_attr_getstacksize "libpthread.so"
+//go:cgo_import_dynamic purego_pthread_attr_setstacksize pthread_attr_setstacksize "libpthread.so"
+//go:cgo_import_dynamic purego_pthread_attr_destroy pthread_attr_destroy "libpthread.so"
+//go:cgo_import_dynamic purego_pthread_mutex_lock pthread_mutex_lock "libpthread.so"
+//go:cgo_import_dynamic purego_pthread_mutex_unlock pthread_mutex_unlock "libpthread.so"
+//go:cgo_import_dynamic purego_pthread_cond_broadcast pthread_cond_broadcast "libpthread.so"
+//go:cgo_import_dynamic purego_pthread_setspecific pthread_setspecific "libpthread.so"
diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/symbols_linux.go b/vendor/github.com/ebitengine/purego/internal/fakecgo/symbols_linux.go
new file mode 100644
index 0000000..180057d
--- /dev/null
+++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/symbols_linux.go
@@ -0,0 +1,29 @@
+// Code generated by 'go generate' with gen.go. DO NOT EDIT.
+
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build !cgo
+
+package fakecgo
+
+//go:cgo_import_dynamic purego_malloc malloc "libc.so.6"
+//go:cgo_import_dynamic purego_free free "libc.so.6"
+//go:cgo_import_dynamic purego_setenv setenv "libc.so.6"
+//go:cgo_import_dynamic purego_unsetenv unsetenv "libc.so.6"
+//go:cgo_import_dynamic purego_sigfillset sigfillset "libc.so.6"
+//go:cgo_import_dynamic purego_nanosleep nanosleep "libc.so.6"
+//go:cgo_import_dynamic purego_abort abort "libc.so.6"
+//go:cgo_import_dynamic purego_pthread_attr_init pthread_attr_init "libpthread.so.0"
+//go:cgo_import_dynamic purego_pthread_create pthread_create "libpthread.so.0"
+//go:cgo_import_dynamic purego_pthread_detach pthread_detach "libpthread.so.0"
+//go:cgo_import_dynamic purego_pthread_sigmask pthread_sigmask "libpthread.so.0"
+//go:cgo_import_dynamic purego_pthread_self pthread_self "libpthread.so.0"
+//go:cgo_import_dynamic purego_pthread_get_stacksize_np pthread_get_stacksize_np "libpthread.so.0"
+//go:cgo_import_dynamic purego_pthread_attr_getstacksize pthread_attr_getstacksize "libpthread.so.0"
+//go:cgo_import_dynamic purego_pthread_attr_setstacksize pthread_attr_setstacksize "libpthread.so.0"
+//go:cgo_import_dynamic purego_pthread_attr_destroy pthread_attr_destroy "libpthread.so.0"
+//go:cgo_import_dynamic purego_pthread_mutex_lock pthread_mutex_lock "libpthread.so.0"
+//go:cgo_import_dynamic purego_pthread_mutex_unlock pthread_mutex_unlock "libpthread.so.0"
+//go:cgo_import_dynamic purego_pthread_cond_broadcast pthread_cond_broadcast "libpthread.so.0"
+//go:cgo_import_dynamic purego_pthread_setspecific pthread_setspecific "libpthread.so.0"
diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_amd64.s b/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_amd64.s
new file mode 100644
index 0000000..c9a3cc0
--- /dev/null
+++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_amd64.s
@@ -0,0 +1,104 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build !cgo && (darwin || linux || freebsd)
+
+/*
+trampoline for emulating required C functions for cgo in go (see cgo.go)
+(we convert cdecl calling convention to go and vice-versa)
+
+Since we're called from go and call into C we can cheat a bit with the calling conventions:
+ - in go all the registers are caller saved
+ - in C we have a couple of callee saved registers
+
+=> we can use BX, R12, R13, R14, R15 instead of the stack
+
+C Calling convention cdecl used here (we only need integer args):
+1. arg: DI
+2. arg: SI
+3. arg: DX
+4. arg: CX
+5. arg: R8
+6. arg: R9
+We don't need floats with these functions -> AX=0
+return value will be in AX
+*/
+#include "textflag.h"
+#include "go_asm.h"
+
+// these trampolines map the gcc ABI to Go ABI and then calls into the Go equivalent functions.
+
+TEXT x_cgo_init_trampoline(SB), NOSPLIT, $16
+ MOVQ DI, AX
+ MOVQ SI, BX
+ MOVQ ·x_cgo_init_call(SB), DX
+ MOVQ (DX), CX
+ CALL CX
+ RET
+
+TEXT x_cgo_thread_start_trampoline(SB), NOSPLIT, $8
+ MOVQ DI, AX
+ MOVQ ·x_cgo_thread_start_call(SB), DX
+ MOVQ (DX), CX
+ CALL CX
+ RET
+
+TEXT x_cgo_setenv_trampoline(SB), NOSPLIT, $8
+ MOVQ DI, AX
+ MOVQ ·x_cgo_setenv_call(SB), DX
+ MOVQ (DX), CX
+ CALL CX
+ RET
+
+TEXT x_cgo_unsetenv_trampoline(SB), NOSPLIT, $8
+ MOVQ DI, AX
+ MOVQ ·x_cgo_unsetenv_call(SB), DX
+ MOVQ (DX), CX
+ CALL CX
+ RET
+
+TEXT x_cgo_notify_runtime_init_done_trampoline(SB), NOSPLIT, $0
+ CALL ·x_cgo_notify_runtime_init_done(SB)
+ RET
+
+TEXT x_cgo_bindm_trampoline(SB), NOSPLIT, $0
+ CALL ·x_cgo_bindm(SB)
+ RET
+
+// func setg_trampoline(setg uintptr, g uintptr)
+TEXT ·setg_trampoline(SB), NOSPLIT, $0-16
+ MOVQ G+8(FP), DI
+ MOVQ setg+0(FP), BX
+ XORL AX, AX
+ CALL BX
+ RET
+
+TEXT threadentry_trampoline(SB), NOSPLIT, $16
+ MOVQ DI, AX
+ MOVQ ·threadentry_call(SB), DX
+ MOVQ (DX), CX
+ CALL CX
+ RET
+
+TEXT ·call5(SB), NOSPLIT, $0-56
+ MOVQ fn+0(FP), BX
+ MOVQ a1+8(FP), DI
+ MOVQ a2+16(FP), SI
+ MOVQ a3+24(FP), DX
+ MOVQ a4+32(FP), CX
+ MOVQ a5+40(FP), R8
+
+ XORL AX, AX // no floats
+
+ PUSHQ BP // save BP
+ MOVQ SP, BP // save SP inside BP bc BP is callee-saved
+ SUBQ $16, SP // allocate space for alignment
+ ANDQ $-16, SP // align on 16 bytes for SSE
+
+ CALL BX
+
+ MOVQ BP, SP // get SP back
+ POPQ BP // restore BP
+
+ MOVQ AX, ret+48(FP)
+ RET
diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_arm64.s b/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_arm64.s
new file mode 100644
index 0000000..9dbdbc0
--- /dev/null
+++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_arm64.s
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build !cgo && (darwin || freebsd || linux)
+
+#include "textflag.h"
+#include "go_asm.h"
+
+// these trampolines map the gcc ABI to Go ABI and then calls into the Go equivalent functions.
+
+TEXT x_cgo_init_trampoline(SB), NOSPLIT, $0-0
+ MOVD R0, 8(RSP)
+ MOVD R1, 16(RSP)
+ MOVD ·x_cgo_init_call(SB), R26
+ MOVD (R26), R2
+ CALL (R2)
+ RET
+
+TEXT x_cgo_thread_start_trampoline(SB), NOSPLIT, $0-0
+ MOVD R0, 8(RSP)
+ MOVD ·x_cgo_thread_start_call(SB), R26
+ MOVD (R26), R2
+ CALL (R2)
+ RET
+
+TEXT x_cgo_setenv_trampoline(SB), NOSPLIT, $0-0
+ MOVD R0, 8(RSP)
+ MOVD ·x_cgo_setenv_call(SB), R26
+ MOVD (R26), R2
+ CALL (R2)
+ RET
+
+TEXT x_cgo_unsetenv_trampoline(SB), NOSPLIT, $0-0
+ MOVD R0, 8(RSP)
+ MOVD ·x_cgo_unsetenv_call(SB), R26
+ MOVD (R26), R2
+ CALL (R2)
+ RET
+
+TEXT x_cgo_notify_runtime_init_done_trampoline(SB), NOSPLIT, $0-0
+ CALL ·x_cgo_notify_runtime_init_done(SB)
+ RET
+
+TEXT x_cgo_bindm_trampoline(SB), NOSPLIT, $0
+ CALL ·x_cgo_bindm(SB)
+ RET
+
+// func setg_trampoline(setg uintptr, g uintptr)
+TEXT ·setg_trampoline(SB), NOSPLIT, $0-16
+ MOVD G+8(FP), R0
+ MOVD setg+0(FP), R1
+ CALL R1
+ RET
+
+TEXT threadentry_trampoline(SB), NOSPLIT, $0-0
+ MOVD R0, 8(RSP)
+ MOVD ·threadentry_call(SB), R26
+ MOVD (R26), R2
+ CALL (R2)
+ MOVD $0, R0 // TODO: get the return value from threadentry
+ RET
+
+TEXT ·call5(SB), NOSPLIT, $0-0
+ MOVD fn+0(FP), R6
+ MOVD a1+8(FP), R0
+ MOVD a2+16(FP), R1
+ MOVD a3+24(FP), R2
+ MOVD a4+32(FP), R3
+ MOVD a5+40(FP), R4
+ CALL R6
+ MOVD R0, ret+48(FP)
+ RET
diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_stubs.s b/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_stubs.s
new file mode 100644
index 0000000..a65b201
--- /dev/null
+++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_stubs.s
@@ -0,0 +1,90 @@
+// Code generated by 'go generate' with gen.go. DO NOT EDIT.
+
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build !cgo && (darwin || freebsd || linux)
+
+#include "textflag.h"
+
+// these stubs are here because it is not possible to go:linkname directly the C functions on darwin arm64
+
+TEXT _malloc(SB), NOSPLIT|NOFRAME, $0-0
+ JMP purego_malloc(SB)
+ RET
+
+TEXT _free(SB), NOSPLIT|NOFRAME, $0-0
+ JMP purego_free(SB)
+ RET
+
+TEXT _setenv(SB), NOSPLIT|NOFRAME, $0-0
+ JMP purego_setenv(SB)
+ RET
+
+TEXT _unsetenv(SB), NOSPLIT|NOFRAME, $0-0
+ JMP purego_unsetenv(SB)
+ RET
+
+TEXT _sigfillset(SB), NOSPLIT|NOFRAME, $0-0
+ JMP purego_sigfillset(SB)
+ RET
+
+TEXT _nanosleep(SB), NOSPLIT|NOFRAME, $0-0
+ JMP purego_nanosleep(SB)
+ RET
+
+TEXT _abort(SB), NOSPLIT|NOFRAME, $0-0
+ JMP purego_abort(SB)
+ RET
+
+TEXT _pthread_attr_init(SB), NOSPLIT|NOFRAME, $0-0
+ JMP purego_pthread_attr_init(SB)
+ RET
+
+TEXT _pthread_create(SB), NOSPLIT|NOFRAME, $0-0
+ JMP purego_pthread_create(SB)
+ RET
+
+TEXT _pthread_detach(SB), NOSPLIT|NOFRAME, $0-0
+ JMP purego_pthread_detach(SB)
+ RET
+
+TEXT _pthread_sigmask(SB), NOSPLIT|NOFRAME, $0-0
+ JMP purego_pthread_sigmask(SB)
+ RET
+
+TEXT _pthread_self(SB), NOSPLIT|NOFRAME, $0-0
+ JMP purego_pthread_self(SB)
+ RET
+
+TEXT _pthread_get_stacksize_np(SB), NOSPLIT|NOFRAME, $0-0
+ JMP purego_pthread_get_stacksize_np(SB)
+ RET
+
+TEXT _pthread_attr_getstacksize(SB), NOSPLIT|NOFRAME, $0-0
+ JMP purego_pthread_attr_getstacksize(SB)
+ RET
+
+TEXT _pthread_attr_setstacksize(SB), NOSPLIT|NOFRAME, $0-0
+ JMP purego_pthread_attr_setstacksize(SB)
+ RET
+
+TEXT _pthread_attr_destroy(SB), NOSPLIT|NOFRAME, $0-0
+ JMP purego_pthread_attr_destroy(SB)
+ RET
+
+TEXT _pthread_mutex_lock(SB), NOSPLIT|NOFRAME, $0-0
+ JMP purego_pthread_mutex_lock(SB)
+ RET
+
+TEXT _pthread_mutex_unlock(SB), NOSPLIT|NOFRAME, $0-0
+ JMP purego_pthread_mutex_unlock(SB)
+ RET
+
+TEXT _pthread_cond_broadcast(SB), NOSPLIT|NOFRAME, $0-0
+ JMP purego_pthread_cond_broadcast(SB)
+ RET
+
+TEXT _pthread_setspecific(SB), NOSPLIT|NOFRAME, $0-0
+ JMP purego_pthread_setspecific(SB)
+ RET
diff --git a/vendor/github.com/ebitengine/purego/internal/strings/strings.go b/vendor/github.com/ebitengine/purego/internal/strings/strings.go
new file mode 100644
index 0000000..5b0d252
--- /dev/null
+++ b/vendor/github.com/ebitengine/purego/internal/strings/strings.go
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+package strings
+
+import (
+ "unsafe"
+)
+
+// hasSuffix tests whether the string s ends with suffix.
+func hasSuffix(s, suffix string) bool {
+ return len(s) >= len(suffix) && s[len(s)-len(suffix):] == suffix
+}
+
+// CString converts a go string to *byte that can be passed to C code.
+func CString(name string) *byte {
+ if hasSuffix(name, "\x00") {
+ return &(*(*[]byte)(unsafe.Pointer(&name)))[0]
+ }
+ b := make([]byte, len(name)+1)
+ copy(b, name)
+ return &b[0]
+}
+
+// GoString copies a null-terminated char* to a Go string.
+func GoString(c uintptr) string {
+ // We take the address and then dereference it to trick go vet from creating a possible misuse of unsafe.Pointer
+ ptr := *(*unsafe.Pointer)(unsafe.Pointer(&c))
+ if ptr == nil {
+ return ""
+ }
+ var length int
+ for {
+ if *(*byte)(unsafe.Add(ptr, uintptr(length))) == '\x00' {
+ break
+ }
+ length++
+ }
+ return string(unsafe.Slice((*byte)(ptr), length))
+}