diff options
-rw-r--r-- | Userland/Utilities/wasm.cpp | 116 |
1 files changed, 39 insertions, 77 deletions
diff --git a/Userland/Utilities/wasm.cpp b/Userland/Utilities/wasm.cpp index bea9796b4f..89dc21e404 100644 --- a/Userland/Utilities/wasm.cpp +++ b/Userland/Utilities/wasm.cpp @@ -265,10 +265,10 @@ int main(int argc, char* argv[]) bool print = false; bool attempt_instantiate = false; bool debug = false; + bool export_all_imports = false; String exported_function_to_execute; Vector<u64> values_to_push; Vector<String> modules_to_link_in; - HashMap<Wasm::Linker::Name, Wasm::HostFunction> exported_host_functions; Core::ArgsParser parser; parser.add_positional_argument(filename, "File name to parse", "file"); @@ -276,6 +276,7 @@ int main(int argc, char* argv[]) 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(exported_function_to_execute, "Attempt to execute the named exported function from the module (implies -i)", "execute", 'e', "name"); + parser.add_option(export_all_imports, "Export noop functions corresponding to imports", "export-noop", 0); parser.add_option(Core::ArgsParser::Option { .requires_argument = true, .help_string = "Extra modules to link with, use to resolve imports", @@ -304,71 +305,6 @@ int main(int argc, char* argv[]) return false; }, }); - parser.add_option(Core::ArgsParser::Option { - .requires_argument = true, - .help_string = "Export a noop function that returns default-initialised values (module!name::t,t,t...:t,t,t...)", - .long_name = "export-noop", - .short_name = 0, - .value_name = "module!name:atypes:rtypes", - .accept_value = [&](const char* str) -> bool { - GenericLexer lexer { str }; - auto name = lexer.consume_until("::"); - auto parts = name.split_view('!'); - if (parts.size() != 2) { - warnln("Expected a two-part name module!name, got '{}'", name); - return false; - } - auto module_name = parts[0]; - auto export_name = parts[1]; - - auto arg_types = lexer.consume_until(":").split_view(','); - auto ret_types = lexer.consume_all().split_view(','); - Vector<Wasm::ValueType> argument_types, return_types; - for (auto& name : arg_types) { - if (name == "i32") { - argument_types.empend(Wasm::ValueType::Kind::I32); - } else if (name == "i64") { - argument_types.empend(Wasm::ValueType::Kind::I64); - } else if (name == "f32") { - argument_types.empend(Wasm::ValueType::Kind::F32); - } else if (name == "f64") { - argument_types.empend(Wasm::ValueType::Kind::F64); - } else { - warnln("Unknown type '{}'", name); - return false; - } - } - for (auto& name : ret_types) { - if (name == "i32") { - return_types.empend(Wasm::ValueType::Kind::I32); - } else if (name == "i64") { - return_types.empend(Wasm::ValueType::Kind::I64); - } else if (name == "f32") { - return_types.empend(Wasm::ValueType::Kind::F32); - } else if (name == "f64") { - return_types.empend(Wasm::ValueType::Kind::F64); - } else { - warnln("Unknown type '{}'", name); - return false; - } - } - - Wasm::FunctionType function_type { argument_types, return_types }; - exported_host_functions.set( - Wasm::Linker::Name { module_name, export_name, function_type }, - Wasm::HostFunction { - [&](auto&, auto&) -> Wasm::Result { - Vector<Wasm::Value> values; - values.ensure_capacity(return_types.size()); - for (auto& type : return_types) - values.empend(type, 0ull); - return Wasm::Result { move(values) }; - }, - function_type }); - - return true; - }, - }); parser.parse(argc, argv); if (debug && exported_function_to_execute.is_empty()) { @@ -384,6 +320,9 @@ int main(int argc, char* argv[]) attempt_instantiate = true; auto parse_result = parse(filename); + if (!parse_result.has_value()) + return 1; + if (print && !attempt_instantiate) { auto out_stream = Core::OutputFileStream::standard_output(); Wasm::Printer printer(out_stream); @@ -425,20 +364,43 @@ int main(int argc, char* argv[]) linked_instances.append(instantiation_result.release_value()); } - HashMap<Wasm::Linker::Name, Wasm::ExternValue> exports; - for (auto& entry : exported_host_functions) { - auto address = machine.store().allocate(move(entry.value)); - if (!address.has_value()) { - warnln("Could not export {}/{}", entry.key.module, entry.key.name); - return 1; - } - exports.set(entry.key, *address); - } - Wasm::Linker linker { parse_result.value() }; for (auto& instance : linked_instances) linker.link(instance); - linker.link(exports); + + if (export_all_imports) { + HashMap<Wasm::Linker::Name, Wasm::ExternValue> exports; + for (auto& entry : linker.unresolved_imports()) { + if (!entry.type.has<Wasm::TypeIndex>()) + continue; + auto type = parse_result.value().type(entry.type.get<Wasm::TypeIndex>()); + auto address = machine.store().allocate(Wasm::HostFunction( + [name = entry.name, type = type](auto&, auto& arguments) -> Wasm::Result { + StringBuilder argument_builder; + bool first = true; + for (auto& argument : arguments) { + DuplexMemoryStream stream; + Wasm::Printer { stream }.print(argument); + if (first) + first = false; + else + argument_builder.append(", "sv); + argument_builder.append(StringView(stream.copy_into_contiguous_buffer()).trim_whitespace()); + } + dbgln("[wasm runtime] Stub function {} was called with the following arguments: {}", name, argument_builder.to_string()); + Vector<Wasm::Value> result; + result.ensure_capacity(type.results().size()); + for (auto& result_type : type.results()) + result.append(Wasm::Value { result_type, 0ull }); + return Wasm::Result { move(result) }; + }, + type)); + exports.set(entry, *address); + } + + linker.link(exports); + } + auto link_result = linker.finish(); if (link_result.is_error()) { warnln("Linking main module failed"); |