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
Этот коммит содержится в:
Ayke van Laethem 2020-01-25 23:22:27 +01:00 коммит произвёл Ron Evans
родитель eb9c2c276e
коммит 24a0f237d8
2 изменённых файлов: 50 добавлений и 36 удалений

Просмотреть файл

@ -2,35 +2,43 @@
package runtime
import "unsafe"
type timeUnit float64 // time in milliseconds, just like Date.now() in JavaScript
const tickMicros = 1000000
//go:export io_get_stdout
func io_get_stdout() int32
//go:export resource_write
func resource_write(id int32, ptr *uint8, len int32) int32
var stdout int32
func init() {
stdout = io_get_stdout()
// Implements __wasi_ciovec_t and __wasi_iovec_t.
type wasiIOVec struct {
buf unsafe.Pointer
bufLen uint
}
//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() {
initAll()
}
//go:export cwa_main
func cwa_main() {
initAll() // _start is not called by olin/cwa so has to be called here
callMain()
}
// Using global variables to avoid heap allocation.
var (
putcharBuf = byte(0)
putcharIOVec = wasiIOVec{
buf: unsafe.Pointer(&putcharBuf),
bufLen: 1,
}
)
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()

Просмотреть файл

@ -181,13 +181,15 @@
const timeOrigin = Date.now() - performance.now();
this.importObject = {
env: {
io_get_stdout: function() {
return 1;
},
resource_write: function(fd, ptr, len) {
wasi_unstable: {
// https://github.com/bytecodealliance/wasmtime/blob/master/docs/WASI-api.md#__wasi_fd_write
fd_write: function(fd, iovs_ptr, iovs_len, nwritten_ptr) {
let nwritten = 0;
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++) {
let c = mem().getUint8(ptr+i);
if (c == 13) { // CR
@ -201,11 +203,15 @@
logLine.push(c);
}
}
}
} else {
console.error('invalid file descriptor:', fd);
}
mem().setUint32(nwritten_ptr, nwritten, true);
return 0;
},
},
env: {
// func ticks() float64
"runtime.ticks": () => {
return timeOrigin + performance.now();
@ -344,7 +350,7 @@
setTimeout(resolve, 0); // make sure it is asynchronous
};
});
this._inst.exports.cwa_main();
this._inst.exports._start();
if (this.exited) {
break;
}