mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-06 20:13:40 +00:00
darwin: replace custom syscall package with Go native syscall package
This required a few compiler and runtime tricks to work, but I ran a bunch of tests and it seems fine. (CI will of course do more exhaustive testing). The main benefit here is that we don't need to maintain the darwin version of the syscall package, and reduce extra risks for bugs (because we reuse the well-tested syscall package). For example, Go 1.23 needed a bunch of new constants in the syscall package. That would have been avoided if we had used the native syscall package on MacOS.
This commit is contained in:
committed by
Ron Evans
parent
753f4b38b4
commit
105fe9b25d
+27
-2
@@ -1,7 +1,32 @@
|
||||
// Wrapper function because 'open' is a variadic function and variadic functions
|
||||
// use a different (incompatible) calling convention on darwin/arm64.
|
||||
//go:build none
|
||||
|
||||
// This file is included in the build, despite the //go:build line above.
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
// Wrapper function because 'open' is a variadic function and variadic functions
|
||||
// use a different (incompatible) calling convention on darwin/arm64.
|
||||
// This function is referenced from the compiler, when it sees a
|
||||
// syscall.libc_open_trampoline function.
|
||||
int syscall_libc_open(const char *pathname, int flags, mode_t mode) {
|
||||
return open(pathname, flags, mode);
|
||||
}
|
||||
|
||||
// The following functions are called by the runtime because Go can't call
|
||||
// function pointers directly.
|
||||
|
||||
int tinygo_syscall(int (*fn)(uintptr_t a1, uintptr_t a2, uintptr_t a3), uintptr_t a1, uintptr_t a2, uintptr_t a3) {
|
||||
return fn(a1, a2, a3);
|
||||
}
|
||||
|
||||
uintptr_t tinygo_syscallX(uintptr_t (*fn)(uintptr_t a1, uintptr_t a2, uintptr_t a3), uintptr_t a1, uintptr_t a2, uintptr_t a3) {
|
||||
return fn(a1, a2, a3);
|
||||
}
|
||||
|
||||
int tinygo_syscall6(int (*fn)(uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6), uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6) {
|
||||
return fn(a1, a2, a3, a4, a5, a6);
|
||||
}
|
||||
|
||||
uintptr_t tinygo_syscall6X(uintptr_t (*fn)(uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6), uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6) {
|
||||
return fn(a1, a2, a3, a4, a5, a6);
|
||||
}
|
||||
|
||||
+100
-2
@@ -4,8 +4,6 @@ package runtime
|
||||
|
||||
import "unsafe"
|
||||
|
||||
import "C" // dummy import so that os_darwin.c works
|
||||
|
||||
const GOOS = "darwin"
|
||||
|
||||
const (
|
||||
@@ -127,7 +125,107 @@ func hardwareRand() (n uint64, ok bool) {
|
||||
return n, true
|
||||
}
|
||||
|
||||
//go:linkname syscall_Getpagesize syscall.Getpagesize
|
||||
func syscall_Getpagesize() int {
|
||||
return int(libc_getpagesize())
|
||||
}
|
||||
|
||||
// Call "system calls" (actually: libc functions) in a special way.
|
||||
// - Most calls calls return a C int (which is 32-bits), and -1 on failure.
|
||||
// - syscallX* is for functions that return a 64-bit integer (and also return
|
||||
// -1 on failure).
|
||||
// - syscallPtr is for functions that return a pointer on success or NULL on
|
||||
// failure.
|
||||
// - rawSyscall seems to avoid some stack modifications, which isn't relevant
|
||||
// to TinyGo.
|
||||
|
||||
//go:linkname syscall_syscall syscall.syscall
|
||||
func syscall_syscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
|
||||
// For TinyGo we don't need to do anything special to call C functions.
|
||||
return syscall_rawSyscall(fn, a1, a2, a3)
|
||||
}
|
||||
|
||||
//go:linkname syscall_rawSyscall syscall.rawSyscall
|
||||
func syscall_rawSyscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
|
||||
result := call_syscall(fn, a1, a2, a3)
|
||||
r1 = uintptr(result)
|
||||
if result == -1 {
|
||||
// Syscall returns -1 on failure.
|
||||
err = uintptr(*libc___error())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//go:linkname syscall_syscallX syscall.syscallX
|
||||
func syscall_syscallX(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
|
||||
r1 = call_syscallX(fn, a1, a2, a3)
|
||||
if int64(r1) == -1 {
|
||||
// Syscall returns -1 on failure.
|
||||
err = uintptr(*libc___error())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//go:linkname syscall_syscallPtr syscall.syscallPtr
|
||||
func syscall_syscallPtr(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
|
||||
r1 = call_syscallX(fn, a1, a2, a3)
|
||||
if r1 == 0 {
|
||||
// Syscall returns a pointer on success, or NULL on failure.
|
||||
err = uintptr(*libc___error())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//go:linkname syscall_syscall6 syscall.syscall6
|
||||
func syscall_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
|
||||
result := call_syscall6(fn, a1, a2, a3, a4, a5, a6)
|
||||
r1 = uintptr(result)
|
||||
if result == -1 {
|
||||
// Syscall returns -1 on failure.
|
||||
err = uintptr(*libc___error())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//go:linkname syscall_syscall6X syscall.syscall6X
|
||||
func syscall_syscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
|
||||
r1 = call_syscall6X(fn, a1, a2, a3, a4, a5, a6)
|
||||
if int64(r1) == -1 {
|
||||
// Syscall returns -1 on failure.
|
||||
err = uintptr(*libc___error())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// uint32_t arc4random(void);
|
||||
//
|
||||
//export arc4random
|
||||
func libc_arc4random() uint32
|
||||
|
||||
// int getpagesize(void);
|
||||
//
|
||||
//export getpagesize
|
||||
func libc_getpagesize() int32
|
||||
|
||||
// This function returns the error location in the darwin ABI.
|
||||
// Discovered by compiling the following code using Clang:
|
||||
//
|
||||
// #include <errno.h>
|
||||
// int getErrno() {
|
||||
// return errno;
|
||||
// }
|
||||
//
|
||||
//export __error
|
||||
func libc___error() *int32
|
||||
|
||||
//export tinygo_syscall
|
||||
func call_syscall(fn, a1, a2, a3 uintptr) int32
|
||||
|
||||
//export tinygo_syscallX
|
||||
func call_syscallX(fn, a1, a2, a3 uintptr) uintptr
|
||||
|
||||
//export tinygo_syscall6
|
||||
func call_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) int32
|
||||
|
||||
//export tinygo_syscall6X
|
||||
func call_syscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) uintptr
|
||||
|
||||
Reference in New Issue
Block a user