mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 07:07:45 +00:00
LibWasm: Add basic support for module instantiation and execution stubs
This adds very basic support for module instantiation/allocation, as well as a stub for an interpreter (and executions APIs). The 'wasm' utility is further expanded to instantiate, and attempt executing the first non-imported function in the module. Note that as the execution is a stub, the expected result is a zero. Regardless, this will allow future commits to implement the JS WebAssembly API. :^)
This commit is contained in:
parent
2b755f1fbf
commit
4d9246ac9d
8 changed files with 938 additions and 1 deletions
|
@ -7,6 +7,7 @@
|
|||
#include <LibCore/ArgsParser.h>
|
||||
#include <LibCore/File.h>
|
||||
#include <LibCore/FileStream.h>
|
||||
#include <LibWasm/AbstractMachine/AbstractMachine.h>
|
||||
#include <LibWasm/Printer/Printer.h>
|
||||
#include <LibWasm/Types.h>
|
||||
|
||||
|
@ -14,12 +15,19 @@ int main(int argc, char* argv[])
|
|||
{
|
||||
const char* filename = nullptr;
|
||||
bool print = false;
|
||||
bool attempt_instantiate = false;
|
||||
bool attemp_execute = false;
|
||||
|
||||
Core::ArgsParser parser;
|
||||
parser.add_positional_argument(filename, "File name to parse", "file");
|
||||
parser.add_option(print, "Print the parsed module", "print", 'p');
|
||||
parser.add_option(attempt_instantiate, "Attempt to instantiate the module", "instantiate", 'i');
|
||||
parser.add_option(attemp_execute, "Attempt to execute a function from the module (implies -i)", "execute", 'e');
|
||||
parser.parse(argc, argv);
|
||||
|
||||
if (attemp_execute)
|
||||
attempt_instantiate = true;
|
||||
|
||||
auto result = Core::File::open(filename, Core::OpenMode::ReadOnly);
|
||||
if (result.is_error()) {
|
||||
warnln("Failed to open {}: {}", filename, result.error());
|
||||
|
@ -34,11 +42,85 @@ int main(int argc, char* argv[])
|
|||
return 2;
|
||||
}
|
||||
|
||||
if (print) {
|
||||
if (print && !attempt_instantiate) {
|
||||
auto out_stream = Core::OutputFileStream::standard_output();
|
||||
Wasm::Printer printer(out_stream);
|
||||
printer.print(parse_result.value());
|
||||
}
|
||||
|
||||
if (attempt_instantiate) {
|
||||
Wasm::AbstractMachine machine;
|
||||
auto result = machine.instantiate(parse_result.value(), {});
|
||||
if (result.is_error()) {
|
||||
warnln("Module instantiation failed: {}", result.error().error);
|
||||
return 1;
|
||||
}
|
||||
|
||||
auto stream = Core::OutputFileStream::standard_output();
|
||||
auto print_func = [&](const auto& address) {
|
||||
Wasm::FunctionInstance* fn = machine.store().get(address);
|
||||
stream.write(String::formatted("- Function with address {}, ptr = {}\n", address.value(), fn).bytes());
|
||||
if (fn) {
|
||||
stream.write(String::formatted(" wasm function? {}\n", fn->has<Wasm::WasmFunction>()).bytes());
|
||||
fn->visit(
|
||||
[&](const Wasm::WasmFunction& func) {
|
||||
Wasm::Printer printer { stream, 3 };
|
||||
stream.write(" type:\n"sv.bytes());
|
||||
printer.print(func.type());
|
||||
stream.write(" code:\n"sv.bytes());
|
||||
printer.print(func.code());
|
||||
},
|
||||
[](const Wasm::HostFunction&) {});
|
||||
}
|
||||
};
|
||||
if (print) {
|
||||
// Now, let's dump the functions!
|
||||
for (auto& address : machine.module_instance().functions()) {
|
||||
print_func(address);
|
||||
}
|
||||
}
|
||||
|
||||
if (attemp_execute) {
|
||||
Optional<Wasm::FunctionAddress> run_address;
|
||||
Vector<Wasm::Value> values;
|
||||
// Pick a function that takes no args :P
|
||||
for (auto& address : machine.module_instance().functions()) {
|
||||
auto fn = machine.store().get(address);
|
||||
if (!fn)
|
||||
continue;
|
||||
if (auto ptr = fn->get_pointer<Wasm::WasmFunction>()) {
|
||||
const Wasm::FunctionType& ty = ptr->type();
|
||||
for (auto& param : ty.parameters()) {
|
||||
values.append(Wasm::Value { param, 0ull });
|
||||
}
|
||||
run_address = address;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!run_address.has_value()) {
|
||||
warnln("No nullary function, sorry :(");
|
||||
return 1;
|
||||
}
|
||||
outln("Executing ");
|
||||
print_func(*run_address);
|
||||
outln();
|
||||
|
||||
auto result = machine.invoke(run_address.value(), move(values));
|
||||
if (!result.values().is_empty())
|
||||
warnln("Returned:");
|
||||
for (auto& value : result.values()) {
|
||||
value.value().visit(
|
||||
[&](const auto& value) {
|
||||
if constexpr (requires { value.value(); })
|
||||
out(" -> addr{} ", value.value());
|
||||
else
|
||||
out(" -> {} ", value);
|
||||
});
|
||||
Wasm::Printer printer { stream };
|
||||
printer.print(value.type());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue