Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a generate_interface program #197

Merged
merged 6 commits into from
Jul 9, 2023
Merged

Conversation

malcolmstill
Copy link
Owner

@malcolmstill malcolmstill commented Jul 9, 2023

Description

To help write host functions for known wasm binaries, adds a generate_interface binary that given a .wasm binary will generate host function stubs and a initHostFunctions function.

E.g. if I take the .wasm from https://silentspacemarine.com/ the binary generates:

const std = @import("std");
const zware = @import("zware");

pub fn initHostFunctions(module: []const u8, store: *zware.Store) !void {
	try store.addHostFunction(module, "exit", exit, [_]ValType{.I32, }, [_]ValType{});
	try store.addHostFunction(module, "emscripten_cancel_main_loop", emscripten_cancel_main_loop, [_]ValType{}, [_]ValType{});
	try store.addHostFunction(module, "emscripten_force_exit", emscripten_force_exit, [_]ValType{.I32, }, [_]ValType{});
	try store.addHostFunction(module, "time", time, [_]ValType{.I32, }, [_]ValType{.I32, });
	try store.addHostFunction(module, "__assert_fail", __assert_fail, [_]ValType{.I32, .I32, .I32, .I32, }, [_]ValType{});
	try store.addHostFunction(module, "emscripten_sleep", emscripten_sleep, [_]ValType{.I32, }, [_]ValType{});

        [deletia...]
}

pub fn exit(vm: *VirtualMachine) WasmError!void {
	const param0 = vm.popOperand(i32);
	std.debug.print("Unimplemented: exit({}, )", .{param0, });
	@panic("Unimplemented: exit");
}

pub fn emscripten_cancel_main_loop(vm: *VirtualMachine) WasmError!void {
	std.debug.print("Unimplemented: emscripten_cancel_main_loop()", .{});
	@panic("Unimplemented: emscripten_cancel_main_loop");
}

pub fn emscripten_force_exit(vm: *VirtualMachine) WasmError!void {
	const param0 = vm.popOperand(i32);
	std.debug.print("Unimplemented: emscripten_force_exit({}, )", .{param0, });
	@panic("Unimplemented: emscripten_force_exit");
}

pub fn time(vm: *VirtualMachine) WasmError!void {
	const param0 = vm.popOperand(i32);
	std.debug.print("Unimplemented: time({}, )", .{param0, });
	@panic("Unimplemented: time");
}

pub fn __assert_fail(vm: *VirtualMachine) WasmError!void {
	const param0 = vm.popOperand(i32);
	const param1 = vm.popOperand(i32);
	const param2 = vm.popOperand(i32);
	const param3 = vm.popOperand(i32);
	std.debug.print("Unimplemented: __assert_fail({}, {}, {}, {}, )", .{param0, param1, param2, param3, });
	@panic("Unimplemented: __assert_fail");
}

pub fn emscripten_sleep(vm: *VirtualMachine) WasmError!void {
	const param0 = vm.popOperand(i32);
	std.debug.print("Unimplemented: emscripten_sleep({}, )", .{param0, });
	@panic("Unimplemented: emscripten_sleep");
}

[deletia...]

The invocation for the above is just running from a command line generate_interface doom.wasm

Follow up

  • TODO: just merge with interface

@malcolmstill malcolmstill changed the title Add a generate_interface program (TODO: just merge with interface) Add a generate_interface program Jul 9, 2023
@malcolmstill malcolmstill merged commit 1714fe3 into master Jul 9, 2023
@malcolmstill malcolmstill deleted the malcolm/generate-interface branch July 9, 2023 15:20
malcolmstill added a commit that referenced this pull request Jul 9, 2023
…rror (#198)

# Description

#197 wasn't quite right...add
a bunch of fixes.
malcolmstill added a commit that referenced this pull request Jul 9, 2023
# Description

#197 generated stubs for host
functions and provided a function for loading those functions into the
runtime. What this PR is wraps calls to `instance.invoke` for all the
functions _exported_ by the `.wasm` binary.

For example, the https://silentspacemarine.com/ `.wasm` gives:

```zig
pub fn __wasm_call_ctors(instance: *zware.Instance) !void {
	var in = [_]u64{};
	var out = [_]u64{};
	try instance.invoke("__wasm_call_ctors", in[0..], out[0..], .{});
}

pub fn main(instance: *zware.Instance, param0: i32, param1: i32) !i32 {
	var in = [_]u64{@bitcast(@as(i64, param0)), @bitcast(@as(i64, param1))};
	var out = [_]u64{0};
	try instance.invoke("main", in[0..], out[0..], .{});
	return @bitcast(@as(u32, @truncate(out[0])));
}

pub fn malloc(instance: *zware.Instance, param0: i32) !i32 {
	var in = [_]u64{@bitcast(@as(i64, param0))};
	var out = [_]u64{0};
	try instance.invoke("malloc", in[0..], out[0..], .{});
	return @bitcast(@as(u32, @truncate(out[0])));
}

[deletia...]
```

## Follow ups

- This hasn't been tested on functions that return more than one value.
The extern ref, func refs and v128 cases are probably wrong too.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant