wasm: use wasi ABI for basic startup/stdout
This allows TinyGo-built binaries to run under wasmtime, for example: tinygo build -o test.wasm -no-debug -target=wasm examples/test wasmtime run test.wasm 0
Этот коммит содержится в:
родитель
eb9c2c276e
коммит
24a0f237d8
2 изменённых файлов: 50 добавлений и 36 удалений
|
@ -2,35 +2,43 @@
|
||||||
|
|
||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
type timeUnit float64 // time in milliseconds, just like Date.now() in JavaScript
|
type timeUnit float64 // time in milliseconds, just like Date.now() in JavaScript
|
||||||
|
|
||||||
const tickMicros = 1000000
|
const tickMicros = 1000000
|
||||||
|
|
||||||
//go:export io_get_stdout
|
// Implements __wasi_ciovec_t and __wasi_iovec_t.
|
||||||
func io_get_stdout() int32
|
type wasiIOVec struct {
|
||||||
|
buf unsafe.Pointer
|
||||||
//go:export resource_write
|
bufLen uint
|
||||||
func resource_write(id int32, ptr *uint8, len int32) int32
|
|
||||||
|
|
||||||
var stdout int32
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
stdout = io_get_stdout()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:export _start
|
//go:wasm-module wasi_unstable
|
||||||
|
//export fd_write
|
||||||
|
func fd_write(id uint32, iovs *wasiIOVec, iovs_len uint, nwritten *uint) (errno uint)
|
||||||
|
|
||||||
|
//export _start
|
||||||
func _start() {
|
func _start() {
|
||||||
initAll()
|
initAll()
|
||||||
}
|
|
||||||
|
|
||||||
//go:export cwa_main
|
|
||||||
func cwa_main() {
|
|
||||||
initAll() // _start is not called by olin/cwa so has to be called here
|
|
||||||
callMain()
|
callMain()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Using global variables to avoid heap allocation.
|
||||||
|
var (
|
||||||
|
putcharBuf = byte(0)
|
||||||
|
putcharIOVec = wasiIOVec{
|
||||||
|
buf: unsafe.Pointer(&putcharBuf),
|
||||||
|
bufLen: 1,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
func putchar(c byte) {
|
func putchar(c byte) {
|
||||||
resource_write(stdout, &c, 1)
|
// write to stdout
|
||||||
|
const stdout = 1
|
||||||
|
var nwritten uint
|
||||||
|
putcharBuf = c
|
||||||
|
fd_write(stdout, &putcharIOVec, 1, &nwritten)
|
||||||
}
|
}
|
||||||
|
|
||||||
var handleEvent func()
|
var handleEvent func()
|
||||||
|
|
|
@ -181,13 +181,15 @@
|
||||||
|
|
||||||
const timeOrigin = Date.now() - performance.now();
|
const timeOrigin = Date.now() - performance.now();
|
||||||
this.importObject = {
|
this.importObject = {
|
||||||
env: {
|
wasi_unstable: {
|
||||||
io_get_stdout: function() {
|
// https://github.com/bytecodealliance/wasmtime/blob/master/docs/WASI-api.md#__wasi_fd_write
|
||||||
return 1;
|
fd_write: function(fd, iovs_ptr, iovs_len, nwritten_ptr) {
|
||||||
},
|
let nwritten = 0;
|
||||||
|
|
||||||
resource_write: function(fd, ptr, len) {
|
|
||||||
if (fd == 1) {
|
if (fd == 1) {
|
||||||
|
for (let iovs_i=0; iovs_i<iovs_len;iovs_i++) {
|
||||||
|
let iov_ptr = iovs_ptr+iovs_i*8; // assuming wasm32
|
||||||
|
let ptr = mem().getUint32(iov_ptr + 0, true);
|
||||||
|
let len = mem().getUint32(iov_ptr + 4, true);
|
||||||
for (let i=0; i<len; i++) {
|
for (let i=0; i<len; i++) {
|
||||||
let c = mem().getUint8(ptr+i);
|
let c = mem().getUint8(ptr+i);
|
||||||
if (c == 13) { // CR
|
if (c == 13) { // CR
|
||||||
|
@ -201,11 +203,15 @@
|
||||||
logLine.push(c);
|
logLine.push(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
console.error('invalid file descriptor:', fd);
|
console.error('invalid file descriptor:', fd);
|
||||||
}
|
}
|
||||||
|
mem().setUint32(nwritten_ptr, nwritten, true);
|
||||||
|
return 0;
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
env: {
|
||||||
// func ticks() float64
|
// func ticks() float64
|
||||||
"runtime.ticks": () => {
|
"runtime.ticks": () => {
|
||||||
return timeOrigin + performance.now();
|
return timeOrigin + performance.now();
|
||||||
|
@ -344,7 +350,7 @@
|
||||||
setTimeout(resolve, 0); // make sure it is asynchronous
|
setTimeout(resolve, 0); // make sure it is asynchronous
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
this._inst.exports.cwa_main();
|
this._inst.exports._start();
|
||||||
if (this.exited) {
|
if (this.exited) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче