Skip to content

Commit

Permalink
wasi: implementations
Browse files Browse the repository at this point in the history
  • Loading branch information
malcolmstill committed Jul 21, 2023
1 parent a96a200 commit 894fba0
Show file tree
Hide file tree
Showing 5 changed files with 498 additions and 4 deletions.
51 changes: 51 additions & 0 deletions src/instance.zig
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
const std = @import("std");
const mem = std.mem;
const math = std.math;
const os = std.os;
const wasi = std.os.wasi;
const ArrayList = std.ArrayList;
const Module = @import("module.zig").Module;
const Store = @import("store.zig").ArrayListStore;
Expand Down Expand Up @@ -40,6 +42,22 @@ pub const Instance = struct {
elemaddrs: ArrayList(usize),
dataaddrs: ArrayList(usize),

// wasi-specific fields
//
// They are defined on an instance but only really on an
// initial instance that is invoked. When initialising a
// VirtualMachine this initial instance will pass its wasi
// data to the VirtualMachine (via pointers).
//
// The wasi implementations can (and must) then lookup this data via
// the VirtualMachine, it shouldn't call e.g. `vm.inst...` because
// a VirtualMachine swaps out its `inst` (instance) pointer as
// it executes; an arbitrary `inst` will not contain the correct
// data.
wasi_preopens: std.AutoHashMap(wasi.fd_t, WasiPreopen),
wasi_args: std.ArrayList([:0]u8),
wasi_env: std.StringHashMap([]const u8),

pub fn init(alloc: mem.Allocator, store: *Store, module: Module) Instance {
return Instance{
.module = module,
Expand All @@ -50,6 +68,10 @@ pub const Instance = struct {
.globaladdrs = ArrayList(usize).init(alloc),
.elemaddrs = ArrayList(usize).init(alloc),
.dataaddrs = ArrayList(usize).init(alloc),

.wasi_preopens = std.AutoHashMap(os.wasi.fd_t, WasiPreopen).init(alloc),
.wasi_args = ArrayList([:0]u8).init(alloc),
.wasi_env = std.StringHashMap([]const u8).init(alloc),
};
}

Expand All @@ -60,6 +82,10 @@ pub const Instance = struct {
self.globaladdrs.deinit();
self.elemaddrs.deinit();
self.dataaddrs.deinit();

self.wasi_preopens.deinit();
self.wasi_args.deinit();
self.wasi_env.deinit();
}

pub fn getFunc(self: *Instance, funcidx: usize) !Function {
Expand Down Expand Up @@ -411,4 +437,29 @@ pub const Instance = struct {
else => return vm.popOperand(Result),
}
}

pub fn addWasiPreopen(self: *Instance, wasi_fd: os.wasi.fd_t, name: []const u8, host_fd: os.fd_t) !void {
return self.wasi_preopens.put(wasi_fd, .{
.wasi_fd = wasi_fd,
.name = name,
.host_fd = host_fd,
});
}

// Caller must call std.process.argsFree on returned args
pub fn forwardArgs(self: *Instance, alloc: mem.Allocator) ![][:0]u8 {
const args = try std.process.argsAlloc(alloc);

for (args) |arg| {
try self.wasi_args.append(arg);
}

return args;
}
};

pub const WasiPreopen = struct {
wasi_fd: wasi.fd_t,
name: []const u8,
host_fd: os.fd_t,
};
29 changes: 27 additions & 2 deletions src/instance/vm.zig
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
const std = @import("std");
const os = std.os;
const mem = std.mem;
const math = std.math;
const wasi = std.os.wasi;
const ArrayList = std.ArrayList;
const Module = @import("../module.zig").Module;
const ValType = @import("../module.zig").ValType;
const Instance = @import("../instance.zig").Instance;
const WasiPreopen = @import("../instance.zig").WasiPreopen;
const Rr = @import("../rr.zig").Rr;

// VirtualMachine:
Expand Down Expand Up @@ -32,6 +35,15 @@ pub const VirtualMachine = struct {
inst: *Instance = undefined,
ip: usize = 0,

// wasi support
//
// These fields match the types in Instance but are
// instead pointers. These will point to the Instance
// that initialises the VirtualMachine
wasi_preopens: *std.AutoHashMap(wasi.fd_t, WasiPreopen),
wasi_args: *std.ArrayList([:0]u8),
wasi_env: *std.StringHashMap([]const u8),

pub const Frame = struct {
locals: []u64 = undefined, // TODO: we're in trouble if we move our stacks in memory
return_arity: usize = 0,
Expand All @@ -55,9 +67,22 @@ pub const VirtualMachine = struct {
.frame_stack = frame_stack,
.label_stack = label_stack,
.inst = inst,
.wasi_preopens = &inst.wasi_preopens,
.wasi_args = &inst.wasi_args,
.wasi_env = &inst.wasi_env,
};
}

pub fn lookupWasiPreopen(self: *VirtualMachine, wasi_fd: os.wasi.fd_t) ?WasiPreopen {
return self.wasi_preopens.get(wasi_fd);
}

pub fn getHostFd(self: *VirtualMachine, wasi_fd: wasi.fd_t) os.fd_t {
const preopen = self.lookupWasiPreopen(wasi_fd) orelse return wasi_fd;

return preopen.host_fd;
}

pub fn invoke(self: *VirtualMachine, ip: usize) !void {
const instr = self.inst.module.parsed_code.items[ip];

Expand Down Expand Up @@ -2306,9 +2331,9 @@ pub const VirtualMachine = struct {
// FIXME: move initial bounds check into Memory implementation
const data = memory.memory();
if (dest <= src) {
memory.uncheckedCopy(dest, data[src..src+n]);
memory.uncheckedCopy(dest, data[src .. src + n]);
} else {
memory.uncheckedCopyBackwards(dest, data[src..src+n]);
memory.uncheckedCopyBackwards(dest, data[src .. src + n]);
}

return dispatch(self, ip + 1, code);
Expand Down
1 change: 1 addition & 0 deletions src/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub const Function = @import("store/function.zig").Function;
pub const Global = @import("store/global.zig").Global;
pub const Memory = @import("store/memory.zig").Memory;
pub const ValType = @import("valtype.zig").ValType;
pub const wasi = @import("wasi/wasi.zig");

test {
_ = @import("module/validator.zig");
Expand Down
Loading

0 comments on commit 894fba0

Please sign in to comment.