
wasmtime by default will assume the subcommand is "run" vs one of its others, but being explicit helps clarify the actual command invoked. For example, we pass similar looking args to wasmtime and also wasi. Signed-off-by: Adrian Cole <adrian@tetrate.io>
165 строки
3,9 КиБ
Go
165 строки
3,9 КиБ
Go
//go:build tinygo.wasm && wasi
|
|
|
|
package runtime
|
|
|
|
import (
|
|
"unsafe"
|
|
)
|
|
|
|
type timeUnit int64
|
|
|
|
// libc constructors
|
|
//
|
|
//export __wasm_call_ctors
|
|
func __wasm_call_ctors()
|
|
|
|
//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()
|
|
}
|
|
|
|
// Read the command line arguments from WASI.
|
|
// For example, they can be passed to a program with wasmtime like this:
|
|
//
|
|
// wasmtime run ./program.wasm arg1 arg2
|
|
func init() {
|
|
__wasm_call_ctors()
|
|
}
|
|
|
|
var args []string
|
|
|
|
//go:linkname os_runtime_args os.runtime_args
|
|
func os_runtime_args() []string {
|
|
if args == nil {
|
|
// Read the number of args (argc) and the buffer size required to store
|
|
// all these args (argv).
|
|
var argc, argv_buf_size uint32
|
|
args_sizes_get(&argc, &argv_buf_size)
|
|
if argc == 0 {
|
|
return nil
|
|
}
|
|
|
|
// Obtain the command line arguments
|
|
argsSlice := make([]unsafe.Pointer, argc)
|
|
buf := make([]byte, argv_buf_size)
|
|
args_get(&argsSlice[0], unsafe.Pointer(&buf[0]))
|
|
|
|
// Convert the array of C strings to an array of Go strings.
|
|
args = make([]string, argc)
|
|
for i, cstr := range argsSlice {
|
|
length := strlen(cstr)
|
|
argString := _string{
|
|
length: length,
|
|
ptr: (*byte)(cstr),
|
|
}
|
|
args[i] = *(*string)(unsafe.Pointer(&argString))
|
|
}
|
|
}
|
|
return args
|
|
}
|
|
|
|
func ticksToNanoseconds(ticks timeUnit) int64 {
|
|
return int64(ticks)
|
|
}
|
|
|
|
func nanosecondsToTicks(ns int64) timeUnit {
|
|
return timeUnit(ns)
|
|
}
|
|
|
|
const 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{
|
|
id: 0,
|
|
timeout: 0,
|
|
precision: timePrecisionNanoseconds,
|
|
flags: 0,
|
|
},
|
|
},
|
|
}
|
|
sleepTicksResult = __wasi_event_t{}
|
|
sleepTicksNEvents uint32
|
|
)
|
|
|
|
func sleepTicks(d timeUnit) {
|
|
sleepTicksSubscription.u.u.timeout = uint64(d)
|
|
poll_oneoff(&sleepTicksSubscription, &sleepTicksResult, 1, &sleepTicksNEvents)
|
|
}
|
|
|
|
func ticks() timeUnit {
|
|
var nano uint64
|
|
clock_time_get(0, timePrecisionNanoseconds, &nano)
|
|
return timeUnit(nano)
|
|
}
|
|
|
|
// Implementations of WASI APIs
|
|
|
|
//go:wasm-module wasi_snapshot_preview1
|
|
//export args_get
|
|
func args_get(argv *unsafe.Pointer, argv_buf unsafe.Pointer) (errno uint16)
|
|
|
|
//go:wasm-module wasi_snapshot_preview1
|
|
//export args_sizes_get
|
|
func args_sizes_get(argc *uint32, argv_buf_size *uint32) (errno uint16)
|
|
|
|
//go:wasm-module wasi_snapshot_preview1
|
|
//export clock_time_get
|
|
func clock_time_get(clockid uint32, precision uint64, time *uint64) (errno uint16)
|
|
|
|
//go:wasm-module wasi_snapshot_preview1
|
|
//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/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#-subscription-record
|
|
__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/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#-subscription_clock-record
|
|
__wasi_subscription_clock_t struct {
|
|
id uint32
|
|
timeout uint64
|
|
precision uint64
|
|
flags uint16
|
|
}
|
|
)
|
|
|
|
type (
|
|
// https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#-event-record
|
|
__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
|
|
}
|
|
}
|
|
)
|