Skip to content

Commit 4b554ed

Browse files
committed
Implement wasi_snapshot_preview1 fd_write
1 parent b2939ac commit 4b554ed

File tree

7 files changed

+130
-5
lines changed

7 files changed

+130
-5
lines changed

dub.sdl

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
name "tiny-wasm-runtime"
22
authors "Hiroki Noda"
33
copyright "Copyright © 2024, Hiroki Noda"
4+
dflags `-J./source/fixtures`

source/app.d

+13-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,14 @@
1-
import binary;
2-
import execution;
1+
import execution.wasi : WasiSnapshotPreview1;
2+
import execution.runtime : Runtime;
33

4-
void main() {}
4+
import std.stdio;
5+
6+
void main()
7+
{
8+
auto wasi = WasiSnapshotPreview1(
9+
fileTable: [stdin, stdout, stderr]
10+
);
11+
const(ubyte)[] wasm = cast(const(ubyte)[]) import("hello_world.wasm");
12+
auto runtime = Runtime.instantiate(wasm, wasi);
13+
runtime.call("_start", []);
14+
}

source/execution/package.d

+1
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ module execution;
33
import execution.value;
44
import execution.runtime;
55
import execution.store;
6+
import execution.wasi;

source/execution/runtime.d

+22-2
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ import binary.types;
66

77
import execution.store;
88
import execution.value;
9+
import execution.wasi : WasiSnapshotPreview1;
910

1011
import std.bitmanip : write;
1112
import std.exception : enforce;
1213
import std.range;
14+
import std.stdio;
1315
import std.sumtype;
1416
import std.system : Endian;
1517
import std.typecons;
@@ -35,6 +37,7 @@ private:
3537
Value[] stack;
3638
Frame*[] callStack;
3739
Import import_;
40+
Nullable!WasiSnapshotPreview1 wasi;
3841

3942
void execute()
4043
{
@@ -167,6 +170,13 @@ private:
167170
const bottom = this.stack.length - func.funcType.params.length;
168171
Value[] args = this.stack[bottom..$];
169172
this.stack = this.stack[0..bottom];
173+
if (func.moduleName == "wasi_snapshot_preview1")
174+
{
175+
if (!this.wasi.isNull)
176+
{
177+
return this.wasi.get.invoke(this.store, func.func, args);
178+
}
179+
}
170180
const mod = func.moduleName in this.import_;
171181
enforce(mod !is null, "not found module");
172182
const importFunc = func.func in *mod;
@@ -175,11 +185,21 @@ private:
175185
}
176186

177187
public:
178-
static Runtime instantiate(ref const(ubyte)[] wasm)
188+
static Runtime instantiate(const(ubyte)[] wasm)
189+
{
190+
auto mod = decodeModule(wasm);
191+
auto store = Store(mod);
192+
return Runtime(store: store);
193+
}
194+
195+
static Runtime instantiate(const(ubyte)[] wasm, ref WasiSnapshotPreview1 wasi)
179196
{
180197
auto mod = decodeModule(wasm);
181198
auto store = Store(mod);
182-
return Runtime(store);
199+
return Runtime(
200+
store: store,
201+
wasi: nullable(wasi)
202+
);
183203
}
184204

185205
void addImport(string moduleName, string funcName, ImportFunc func)

source/execution/wasi.d

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
module execution.wasi;
2+
3+
import execution.value;
4+
import execution.store;
5+
6+
import std.array : array;
7+
import std.bitmanip : peek, write;
8+
import std.stdio;
9+
import std.sumtype;
10+
import std.system : Endian;
11+
import std.typecons : Nullable, nullable;
12+
13+
struct WasiSnapshotPreview1
14+
{
15+
File[] fileTable;
16+
17+
this(File[] fileTable)
18+
{
19+
this.fileTable = fileTable;
20+
}
21+
22+
Nullable!Value invoke(ref Store store, string func, Value[] args)
23+
{
24+
switch (func)
25+
{
26+
case "fd_write":
27+
return fdWrite(store, args);
28+
default:
29+
assert(false, "not implemented yet");
30+
}
31+
assert(false);
32+
}
33+
34+
Nullable!Value fdWrite(ref Store store, Value[] args)
35+
{
36+
import std.algorithm : map;
37+
38+
int[] _args = args.map!((Value arg) {
39+
return arg.match!(
40+
(I32 i32) => i32.i,
41+
_ => assert(false)
42+
)();
43+
}).array;
44+
45+
int fd = _args[0];
46+
size_t iovs = _args[1];
47+
int iovsLen = _args[2];
48+
const size_t rp = _args[3];
49+
50+
auto file = fileTable[fd];
51+
auto memory = store.memories[0];
52+
53+
int nwritten = 0;
54+
55+
foreach (_; 0..iovsLen)
56+
{
57+
const start = memory.data.peek!(int, Endian.littleEndian)(&iovs);
58+
const len = memory.data.peek!(int, Endian.littleEndian)(&iovs);
59+
const end = start + len;
60+
file.rawWrite(memory.data[start..end]);
61+
nwritten += len;
62+
}
63+
memory.data.write!(int, Endian.littleEndian)(nwritten, rp);
64+
65+
return nullable(cast(Value) I32(0));
66+
}
67+
}
68+
69+

source/fixtures/hello_world.wasm

139 Bytes
Binary file not shown.

source/fixtures/hello_world.wat

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
(module
2+
(import "wasi_snapshot_preview1" "fd_write"
3+
(func $fd_write (param i32 i32 i32 i32) (result i32))
4+
)
5+
(memory 1)
6+
(data (i32.const 0) "Hello, World!\n")
7+
8+
(func $hello_world (result i32)
9+
(local $iovs i32)
10+
11+
(i32.store (i32.const 16) (i32.const 0))
12+
(i32.store (i32.const 20) (i32.const 14))
13+
14+
(local.set $iovs (i32.const 16))
15+
16+
(call $fd_write
17+
(i32.const 1)
18+
(local.get $iovs)
19+
(i32.const 1)
20+
(i32.const 24)
21+
)
22+
)
23+
(export "_start" (func $hello_world))
24+
)

0 commit comments

Comments
 (0)