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 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;
} }