mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-06 20:13:40 +00:00
support WASI target (#1373)
* initial commit for WASI support
* merge "time" package with wasi build tag
* override syscall package with wasi build tag
* create runtime_wasm_{js,wasi}.go files
* create syscall_wasi.go file
* create time/zoneinfo_wasi.go file as the replacement of zoneinfo_js.go
* add targets/wasi.json target
* set visbility hidden for runtime extern variables
Accodring to the WASI docs (https://github.com/WebAssembly/WASI/blob/master/design/application-abi.md#current-unstable-abi),
none of exports of WASI executable(Command) should no be accessed.
v0.19.0 of bytecodealliance/wasmetime, which is often refered to as the reference implementation of WASI,
does not accept any exports except functions and the only limited variables like "table", "memory".
* merge syscall_{baremetal,wasi}.go
* fix js target build
* mv wasi functions to syscall/wasi && implement sleepTicks
* WASI: set visibility hidden for globals variables
* mv back syscall/wasi/* to runtime package
* WASI: add test
* unexport wasi types
* WASI test: fix wasmtime path
* stop changing visibility of runtime.alloc
* use GOOS=linux, GOARCH=arm for wasi target
Signed-off-by: mathetake <takeshi@tetrate.io>
* WASI: fix build tags for os/runtime packages
Signed-off-by: mathetake <takeshi@tetrate.io>
* run WASI test only on Linux
Signed-off-by: mathetake <takeshi@tetrate.io>
* set InternalLinkage instead of changing visibility
Signed-off-by: mathetake <takeshi@tetrate.io>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
// +build arm,!baremetal arm,arm7tdmi
|
||||
// +build arm,!baremetal,!wasm arm,arm7tdmi
|
||||
|
||||
package runtime
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// +build darwin linux,!baremetal freebsd,!baremetal
|
||||
// +build darwin linux,!baremetal,!wasi freebsd,!baremetal
|
||||
// +build !nintendoswitch
|
||||
|
||||
package runtime
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// +build darwin linux,!baremetal freebsd,!baremetal
|
||||
// +build darwin linux,!baremetal,!wasi freebsd,!baremetal
|
||||
// +build !nintendoswitch
|
||||
|
||||
// +build gc.conservative gc.leaking
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// +build darwin linux,!baremetal freebsd,!baremetal
|
||||
// +build darwin linux,!baremetal,!wasi freebsd,!baremetal
|
||||
|
||||
// +build !nintendoswitch
|
||||
|
||||
|
||||
@@ -2,35 +2,26 @@
|
||||
|
||||
package runtime
|
||||
|
||||
import "unsafe"
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type timeUnit float64 // time in milliseconds, just like Date.now() in JavaScript
|
||||
|
||||
// Implements __wasi_ciovec_t and __wasi_iovec_t.
|
||||
type wasiIOVec struct {
|
||||
// Implements __wasi_iovec_t.
|
||||
type __wasi_iovec_t struct {
|
||||
buf unsafe.Pointer
|
||||
bufLen uint
|
||||
}
|
||||
|
||||
//go:wasm-module wasi_unstable
|
||||
//export fd_write
|
||||
func fd_write(id uint32, iovs *wasiIOVec, iovs_len uint, nwritten *uint) (errno uint)
|
||||
func fd_write(id uint32, iovs *__wasi_iovec_t, iovs_len uint, nwritten *uint) (errno uint)
|
||||
|
||||
func postinit() {}
|
||||
|
||||
//export _start
|
||||
func _start() {
|
||||
// These need to be initialized early so that the heap can be initialized.
|
||||
heapStart = uintptr(unsafe.Pointer(&heapStartSymbol))
|
||||
heapEnd = uintptr(wasm_memory_size(0) * wasmPageSize)
|
||||
|
||||
run()
|
||||
}
|
||||
|
||||
// Using global variables to avoid heap allocation.
|
||||
var (
|
||||
putcharBuf = byte(0)
|
||||
putcharIOVec = wasiIOVec{
|
||||
putcharIOVec = __wasi_iovec_t{
|
||||
buf: unsafe.Pointer(&putcharBuf),
|
||||
bufLen: 1,
|
||||
}
|
||||
@@ -44,49 +35,6 @@ func putchar(c byte) {
|
||||
fd_write(stdout, &putcharIOVec, 1, &nwritten)
|
||||
}
|
||||
|
||||
var handleEvent func()
|
||||
|
||||
//go:linkname setEventHandler syscall/js.setEventHandler
|
||||
func setEventHandler(fn func()) {
|
||||
handleEvent = fn
|
||||
}
|
||||
|
||||
//export resume
|
||||
func resume() {
|
||||
go func() {
|
||||
handleEvent()
|
||||
}()
|
||||
scheduler()
|
||||
}
|
||||
|
||||
//export go_scheduler
|
||||
func go_scheduler() {
|
||||
scheduler()
|
||||
}
|
||||
|
||||
const asyncScheduler = true
|
||||
|
||||
func ticksToNanoseconds(ticks timeUnit) int64 {
|
||||
// The JavaScript API works in float64 milliseconds, so convert to
|
||||
// nanoseconds first before converting to a timeUnit (which is a float64),
|
||||
// to avoid precision loss.
|
||||
return int64(ticks * 1e6)
|
||||
}
|
||||
|
||||
func nanosecondsToTicks(ns int64) timeUnit {
|
||||
// The JavaScript API works in float64 milliseconds, so convert to timeUnit
|
||||
// (which is a float64) first before dividing, to avoid precision loss.
|
||||
return timeUnit(ns) / 1e6
|
||||
}
|
||||
|
||||
// This function is called by the scheduler.
|
||||
// Schedule a call to runtime.scheduler, do not actually sleep.
|
||||
//export runtime.sleepTicks
|
||||
func sleepTicks(d timeUnit)
|
||||
|
||||
//export runtime.ticks
|
||||
func ticks() timeUnit
|
||||
|
||||
// Abort executes the wasm 'unreachable' instruction.
|
||||
func abort() {
|
||||
trap()
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
// +build wasm,!wasi
|
||||
|
||||
package runtime
|
||||
|
||||
import "unsafe"
|
||||
|
||||
type timeUnit float64 // time in milliseconds, just like Date.now() in JavaScript
|
||||
|
||||
//export _start
|
||||
func _start() {
|
||||
// These need to be initialized early so that the heap can be initialized.
|
||||
heapStart = uintptr(unsafe.Pointer(&heapStartSymbol))
|
||||
heapEnd = uintptr(wasm_memory_size(0) * wasmPageSize)
|
||||
|
||||
run()
|
||||
}
|
||||
|
||||
var handleEvent func()
|
||||
|
||||
//go:linkname setEventHandler syscall/js.setEventHandler
|
||||
func setEventHandler(fn func()) {
|
||||
handleEvent = fn
|
||||
}
|
||||
|
||||
//export resume
|
||||
func resume() {
|
||||
go func() {
|
||||
handleEvent()
|
||||
}()
|
||||
scheduler()
|
||||
}
|
||||
|
||||
//export go_scheduler
|
||||
func go_scheduler() {
|
||||
scheduler()
|
||||
}
|
||||
|
||||
const asyncScheduler = true
|
||||
|
||||
func ticksToNanoseconds(ticks timeUnit) int64 {
|
||||
// The JavaScript API works in float64 milliseconds, so convert to
|
||||
// nanoseconds first before converting to a timeUnit (which is a float64),
|
||||
// to avoid precision loss.
|
||||
return int64(ticks * 1e6)
|
||||
}
|
||||
|
||||
func nanosecondsToTicks(ns int64) timeUnit {
|
||||
// The JavaScript API works in float64 milliseconds, so convert to timeUnit
|
||||
// (which is a float64) first before dividing, to avoid precision loss.
|
||||
return timeUnit(ns) / 1e6
|
||||
}
|
||||
|
||||
// This function is called by the scheduler.
|
||||
// Schedule a call to runtime.scheduler, do not actually sleep.
|
||||
//export runtime.sleepTicks
|
||||
func sleepTicks(d timeUnit)
|
||||
|
||||
//export runtime.ticks
|
||||
func ticks() timeUnit
|
||||
@@ -0,0 +1,117 @@
|
||||
// +build wasm,wasi
|
||||
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type timeUnit int64
|
||||
|
||||
//export _start
|
||||
func _start() {
|
||||
// These need to be initialized early so that the heap can be initialized.
|
||||
heapStart = uintptr(unsafe.Pointer(&heapStartSymbol))
|
||||
heapEnd = uintptr(wasm_memory_size(0) * wasmPageSize)
|
||||
run()
|
||||
}
|
||||
|
||||
func ticksToNanoseconds(ticks timeUnit) int64 {
|
||||
return int64(ticks)
|
||||
}
|
||||
|
||||
func nanosecondsToTicks(ns int64) timeUnit {
|
||||
return timeUnit(ns)
|
||||
}
|
||||
|
||||
const (
|
||||
asyncScheduler = false
|
||||
timePrecisionNanoseconds = 1000 // TODO: how can we determine the appropriate `precision`?
|
||||
)
|
||||
|
||||
var (
|
||||
sleepTicksSubscription = __wasi_subscription_t{
|
||||
userData: 0,
|
||||
u: __wasi_subscription_u_t{
|
||||
tag: __wasi_eventtype_t_clock,
|
||||
u: __wasi_subscription_clock_t{
|
||||
userData: 0,
|
||||
id: 0,
|
||||
timeout: 0,
|
||||
precision: timePrecisionNanoseconds,
|
||||
flags: 0,
|
||||
},
|
||||
},
|
||||
}
|
||||
sleepTicksResult = __wasi_event_t{}
|
||||
sleepTicksNEvents uint32
|
||||
)
|
||||
|
||||
func sleepTicks(d timeUnit) {
|
||||
sleepTicksSubscription.u.u.timeout = int64(d)
|
||||
poll_oneoff(&sleepTicksSubscription, &sleepTicksResult, 1, &sleepTicksNEvents)
|
||||
}
|
||||
|
||||
func ticks() timeUnit {
|
||||
var nano int64
|
||||
clock_time_get(0, timePrecisionNanoseconds, &nano)
|
||||
return timeUnit(nano)
|
||||
}
|
||||
|
||||
// Implementations of wasi_unstable APIs
|
||||
|
||||
//go:wasm-module wasi_unstable
|
||||
//export clock_time_get
|
||||
func clock_time_get(clockid uint32, precision uint64, time *int64) (errno uint16)
|
||||
|
||||
//go:wasm-module wasi_unstable
|
||||
//export poll_oneoff
|
||||
func poll_oneoff(in *__wasi_subscription_t, out *__wasi_event_t, nsubscriptions uint32, nevents *uint32) (errno uint16)
|
||||
|
||||
type __wasi_eventtype_t = uint8
|
||||
|
||||
const (
|
||||
__wasi_eventtype_t_clock __wasi_eventtype_t = 0
|
||||
// TODO: __wasi_eventtype_t_fd_read __wasi_eventtype_t = 1
|
||||
// TODO: __wasi_eventtype_t_fd_write __wasi_eventtype_t = 2
|
||||
)
|
||||
|
||||
type (
|
||||
// https://github.com/wasmerio/wasmer/blob/1.0.0-alpha3/lib/wasi/src/syscalls/types.rs#L584-L588
|
||||
__wasi_subscription_t struct {
|
||||
userData uint64
|
||||
u __wasi_subscription_u_t
|
||||
}
|
||||
|
||||
__wasi_subscription_u_t struct {
|
||||
tag __wasi_eventtype_t
|
||||
|
||||
// TODO: support fd_read/fd_write event
|
||||
u __wasi_subscription_clock_t
|
||||
}
|
||||
|
||||
// https://github.com/wasmerio/wasmer/blob/1.0.0-alpha3/lib/wasi/src/syscalls/types.rs#L711-L718
|
||||
__wasi_subscription_clock_t struct {
|
||||
userData uint64
|
||||
id uint32
|
||||
timeout int64
|
||||
precision int64
|
||||
flags uint16
|
||||
}
|
||||
)
|
||||
|
||||
type (
|
||||
// https://github.com/wasmerio/wasmer/blob/1.0.0-alpha3/lib/wasi/src/syscalls/types.rs#L191-L198
|
||||
__wasi_event_t struct {
|
||||
userData uint64
|
||||
errno uint16
|
||||
eventType __wasi_eventtype_t
|
||||
|
||||
// only used for fd_read or fd_write events
|
||||
// TODO: support fd_read/fd_write event
|
||||
_ struct {
|
||||
nBytes uint64
|
||||
flags uint16
|
||||
}
|
||||
}
|
||||
)
|
||||
Reference in New Issue
Block a user