mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-09 21:43:40 +00:00
wasi preview 2 support (#4027)
* all: wasip2 support Co-authored-by: Randy Reddig <randy.reddig@fastly.com>
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
//go:build darwin || nintendoswitch || wasip1
|
||||
|
||||
package syscall
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func Environ() []string {
|
||||
|
||||
// This function combines all the environment into a single allocation.
|
||||
// While this optimizes for memory usage and garbage collector
|
||||
// overhead, it does run the risk of potentially pinning a "large"
|
||||
// allocation if a user holds onto a single environment variable or
|
||||
// value. Having each variable be its own allocation would make the
|
||||
// trade-off in the other direction.
|
||||
|
||||
// calculate total memory required
|
||||
var length uintptr
|
||||
var vars int
|
||||
for environ := libc_environ; *environ != nil; {
|
||||
length += libc_strlen(*environ)
|
||||
vars++
|
||||
environ = (*unsafe.Pointer)(unsafe.Add(unsafe.Pointer(environ), unsafe.Sizeof(environ)))
|
||||
}
|
||||
|
||||
// allocate our backing slice for the strings
|
||||
b := make([]byte, length)
|
||||
// and the slice we're going to return
|
||||
envs := make([]string, 0, vars)
|
||||
|
||||
// loop over the environment again, this time copying over the data to the backing slice
|
||||
for environ := libc_environ; *environ != nil; {
|
||||
length = libc_strlen(*environ)
|
||||
// construct a Go string pointing at the libc-allocated environment variable data
|
||||
var envVar string
|
||||
rawEnvVar := (*struct {
|
||||
ptr unsafe.Pointer
|
||||
length uintptr
|
||||
})(unsafe.Pointer(&envVar))
|
||||
rawEnvVar.ptr = *environ
|
||||
rawEnvVar.length = length
|
||||
// pull off the number of bytes we need for this environment variable
|
||||
var bs []byte
|
||||
bs, b = b[:length], b[length:]
|
||||
// copy over the bytes to the Go heap
|
||||
copy(bs, envVar)
|
||||
// convert trimmed slice to string
|
||||
s := *(*string)(unsafe.Pointer(&bs))
|
||||
// add s to our list of environment variables
|
||||
envs = append(envs, s)
|
||||
// environ++
|
||||
environ = (*unsafe.Pointer)(unsafe.Add(unsafe.Pointer(environ), unsafe.Sizeof(environ)))
|
||||
}
|
||||
return envs
|
||||
}
|
||||
|
||||
//go:extern environ
|
||||
var libc_environ *unsafe.Pointer
|
||||
@@ -0,0 +1,11 @@
|
||||
//go:build wasip2
|
||||
|
||||
package syscall
|
||||
|
||||
func Environ() []string {
|
||||
var env []string
|
||||
for k, v := range libc_envs {
|
||||
env = append(env, k+"="+v)
|
||||
}
|
||||
return env
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
//go:build !wasip1 && !darwin
|
||||
//go:build !wasip1 && !wasip2 && !darwin
|
||||
|
||||
package syscall
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
//go:build wasip1
|
||||
|
||||
package syscall
|
||||
|
||||
// Use a go:extern definition to access the errno from wasi-libc
|
||||
//
|
||||
//go:extern errno
|
||||
var libcErrno Errno
|
||||
@@ -0,0 +1,7 @@
|
||||
//go:build wasip2
|
||||
|
||||
package syscall
|
||||
|
||||
// The errno for libc_wasip2.go
|
||||
|
||||
var libcErrno Errno
|
||||
@@ -1,4 +1,4 @@
|
||||
//go:build baremetal || (wasm && !wasip1) || wasm_unknown
|
||||
//go:build baremetal || (wasm && !wasip1 && !wasip2) || wasm_unknown
|
||||
|
||||
// This file emulates some file-related functions that are only available
|
||||
// under a real operating system.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//go:build !(baremetal || (wasm && !wasip1) || wasm_unknown)
|
||||
//go:build !(baremetal || (wasm && !wasip1 && !wasip2) || wasm_unknown)
|
||||
|
||||
// This file assumes there is a libc available that runs on a real operating
|
||||
// system.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
//go:build darwin || nintendoswitch || wasi || wasip1
|
||||
//go:build darwin || nintendoswitch || wasip1 || wasip2
|
||||
|
||||
package syscall
|
||||
|
||||
@@ -260,55 +260,6 @@ func Mprotect(b []byte, prot int) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func Environ() []string {
|
||||
|
||||
// This function combines all the environment into a single allocation.
|
||||
// While this optimizes for memory usage and garbage collector
|
||||
// overhead, it does run the risk of potentially pinning a "large"
|
||||
// allocation if a user holds onto a single environment variable or
|
||||
// value. Having each variable be its own allocation would make the
|
||||
// trade-off in the other direction.
|
||||
|
||||
// calculate total memory required
|
||||
var length uintptr
|
||||
var vars int
|
||||
for environ := libc_environ; *environ != nil; {
|
||||
length += libc_strlen(*environ)
|
||||
vars++
|
||||
environ = (*unsafe.Pointer)(unsafe.Add(unsafe.Pointer(environ), unsafe.Sizeof(environ)))
|
||||
}
|
||||
|
||||
// allocate our backing slice for the strings
|
||||
b := make([]byte, length)
|
||||
// and the slice we're going to return
|
||||
envs := make([]string, 0, vars)
|
||||
|
||||
// loop over the environment again, this time copying over the data to the backing slice
|
||||
for environ := libc_environ; *environ != nil; {
|
||||
length = libc_strlen(*environ)
|
||||
// construct a Go string pointing at the libc-allocated environment variable data
|
||||
var envVar string
|
||||
rawEnvVar := (*struct {
|
||||
ptr unsafe.Pointer
|
||||
length uintptr
|
||||
})(unsafe.Pointer(&envVar))
|
||||
rawEnvVar.ptr = *environ
|
||||
rawEnvVar.length = length
|
||||
// pull off the number of bytes we need for this environment variable
|
||||
var bs []byte
|
||||
bs, b = b[:length], b[length:]
|
||||
// copy over the bytes to the Go heap
|
||||
copy(bs, envVar)
|
||||
// convert trimmed slice to string
|
||||
s := *(*string)(unsafe.Pointer(&bs))
|
||||
// add s to our list of environment variables
|
||||
envs = append(envs, s)
|
||||
// environ++
|
||||
environ = (*unsafe.Pointer)(unsafe.Add(unsafe.Pointer(environ), unsafe.Sizeof(environ)))
|
||||
}
|
||||
return envs
|
||||
}
|
||||
|
||||
// BytePtrFromString returns a pointer to a NUL-terminated array of
|
||||
// bytes containing the text of s. If s contains a NUL byte at any
|
||||
// location, it returns (nil, EINVAL).
|
||||
@@ -445,6 +396,3 @@ func libc_readlink(path *byte, buf *byte, count uint) int
|
||||
//
|
||||
//export unlink
|
||||
func libc_unlink(pathname *byte) int32
|
||||
|
||||
//go:extern environ
|
||||
var libc_environ *unsafe.Pointer
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//go:build wasip1
|
||||
//go:build wasip1 || wasip2
|
||||
|
||||
package syscall
|
||||
|
||||
@@ -70,9 +70,10 @@ const (
|
||||
__WASI_FILETYPE_SYMBOLIC_LINK = 7
|
||||
|
||||
// ../../lib/wasi-libc/libc-bottom-half/headers/public/__header_fcntl.h
|
||||
O_RDONLY = 0x04000000
|
||||
O_WRONLY = 0x10000000
|
||||
O_RDWR = O_RDONLY | O_WRONLY
|
||||
O_NOFOLLOW = 0x01000000
|
||||
O_RDONLY = 0x04000000
|
||||
O_WRONLY = 0x10000000
|
||||
O_RDWR = O_RDONLY | O_WRONLY
|
||||
|
||||
O_CREAT = __WASI_OFLAGS_CREAT << 12
|
||||
O_TRUNC = __WASI_OFLAGS_TRUNC << 12
|
||||
@@ -118,11 +119,9 @@ const (
|
||||
PATH_MAX = 4096
|
||||
)
|
||||
|
||||
//go:extern errno
|
||||
var libcErrno uintptr
|
||||
|
||||
func getErrno() error {
|
||||
return Errno(libcErrno)
|
||||
// libcErrno is the errno from wasi-libc for wasip1 and the errno for libc_wasip2 for wasip2
|
||||
return libcErrno
|
||||
}
|
||||
|
||||
func (e Errno) Is(target error) bool {
|
||||
@@ -195,6 +194,7 @@ const (
|
||||
ENOTCONN Errno = 53 /* Socket is not connected */
|
||||
ENOTDIR Errno = 54 /* Not a directory */
|
||||
ENOTEMPTY Errno = 55 /* Directory not empty */
|
||||
ENOTRECOVERABLE Errno = 56 /* State not recoverable */
|
||||
ENOTSOCK Errno = 57 /* Socket operation on non-socket */
|
||||
ESOCKTNOSUPPORT Errno = 58 /* Socket type not supported */
|
||||
EOPNOTSUPP Errno = 58 /* Operation not supported on transport endpoint */
|
||||
@@ -213,10 +213,15 @@ const (
|
||||
ESRCH Errno = 71 /* No such process */
|
||||
ESTALE Errno = 72
|
||||
ETIMEDOUT Errno = 73 /* Connection timed out */
|
||||
ETXTBSY Errno = 74 /* Text file busy */
|
||||
EXDEV Errno = 75 /* Cross-device link */
|
||||
ENOTCAPABLE Errno = 76 /* Extension: Capabilities insufficient. */
|
||||
|
||||
EWASIERROR Errno = 255 /* Unknown WASI error */
|
||||
)
|
||||
|
||||
// TODO(ydnar): remove Timespec for WASI Preview 2 (seconds is uint64).
|
||||
//
|
||||
// https://github.com/WebAssembly/wasi-libc/blob/main/libc-bottom-half/headers/public/__struct_timespec.h
|
||||
type Timespec struct {
|
||||
Sec int32
|
||||
@@ -411,6 +416,11 @@ type Utsname struct {
|
||||
Domainname [65]int8
|
||||
}
|
||||
|
||||
//go:linkname faccessat syscall.Faccessat
|
||||
func faccessat(dirfd int, path string, mode uint32, flags int) (err error) {
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
// Stub Utsname, needed because WASI pretends to be linux/arm.
|
||||
func Uname(buf *Utsname) (err error)
|
||||
|
||||
Reference in New Issue
Block a user