diff options
-rw-r--r-- | src/interp/interp.cc | 24 | ||||
-rw-r--r-- | src/interp/interp.h | 5 | ||||
-rw-r--r-- | src/tools/wasm-interp.cc | 26 | ||||
-rw-r--r-- | test/help/wasm-interp.txt | 1 | ||||
-rw-r--r-- | test/interp/call-dummy-import.txt | 20 |
5 files changed, 68 insertions, 8 deletions
diff --git a/src/interp/interp.cc b/src/interp/interp.cc index ca8ff59d..3d5ee30e 100644 --- a/src/interp/interp.cc +++ b/src/interp/interp.cc @@ -144,11 +144,27 @@ Module* Environment::FindModule(string_view name) { } Module* Environment::FindRegisteredModule(string_view name) { - auto iter = registered_module_bindings_.find(name.to_string()); - if (iter == registered_module_bindings_.end()) { - return nullptr; + bool retry = false; + while (true) { + auto iter = registered_module_bindings_.find(name.to_string()); + if (iter != registered_module_bindings_.end()) { + return modules_[iter->second.index].get(); + } + + if (retry) { + // If you return true from on_unknown_module, you must add the module + // using AppendHostModule(). + assert(false); + break; + } + + if (on_unknown_module && on_unknown_module(this, name)) { + retry = true; + continue; + } + break; } - return modules_[iter->second.index].get(); + return nullptr; } Thread::Options::Options(uint32_t value_stack_size, uint32_t call_stack_size) diff --git a/src/interp/interp.h b/src/interp/interp.h index 1a98ccfb..1230b927 100644 --- a/src/interp/interp.h +++ b/src/interp/interp.h @@ -537,6 +537,11 @@ class Environment { void Disassemble(Stream* stream, IstreamOffset from, IstreamOffset to); void DisassembleModule(Stream* stream, Module*); + // Called when a module name isn't found in registered_module_bindings_. If + // you want to provide a module with this name, call AppendHostModule() with + // this name and return true. + std::function<bool(Environment*, string_view name)> on_unknown_module; + private: friend class Thread; diff --git a/src/tools/wasm-interp.cc b/src/tools/wasm-interp.cc index cb5808d8..c08a4382 100644 --- a/src/tools/wasm-interp.cc +++ b/src/tools/wasm-interp.cc @@ -46,6 +46,7 @@ static Thread::Options s_thread_options; static Stream* s_trace_stream; static bool s_run_all_exports; static bool s_host_print; +static bool s_dummy_import_func; static Features s_features; static std::unique_ptr<FileStream> s_log_stream; @@ -106,6 +107,11 @@ static void ParseOptions(int argc, char** argv) { "Include an importable function named \"host.print\" for " "printing to stdout", []() { s_host_print = true; }); + parser.AddOption( + "dummy-import-func", + "Provide a dummy implementation of all imported functions. The function " + "will log the call and return an appropriate zero value.", + []() { s_dummy_import_func = true; }); parser.AddArgument("filename", OptionParser::ArgumentCount::One, [](const char* argument) { s_infile = argument; }); @@ -169,7 +175,7 @@ static interp::Result PrintCallback(const HostFunc* func, static void InitEnvironment(Environment* env) { if (s_host_print) { - HostModule* host_module = env->AppendHostModule("host"); + auto* host_module = env->AppendHostModule("host"); host_module->on_unknown_func_export = [](Environment* env, HostModule* host_module, string_view name, Index sig_index) -> Index { @@ -177,9 +183,21 @@ static void InitEnvironment(Environment* env) { return kInvalidIndex; } - std::pair<HostFunc*, Index> pair = - host_module->AppendFuncExport(name, sig_index, PrintCallback); - return pair.second; + return host_module->AppendFuncExport(name, sig_index, PrintCallback) + .second; + }; + } + + if (s_dummy_import_func) { + env->on_unknown_module = [](Environment* env, string_view name) { + auto* host_module = env->AppendHostModule(name); + host_module->on_unknown_func_export = + [](Environment* env, HostModule* host_module, string_view name, + Index sig_index) -> Index { + return host_module->AppendFuncExport(name, sig_index, PrintCallback) + .second; + }; + return true; }; } } diff --git a/test/help/wasm-interp.txt b/test/help/wasm-interp.txt index 05264173..9c84f15c 100644 --- a/test/help/wasm-interp.txt +++ b/test/help/wasm-interp.txt @@ -39,4 +39,5 @@ options: -t, --trace Trace execution --run-all-exports Run all the exported functions, in order. Useful for testing --host-print Include an importable function named "host.print" for printing to stdout + --dummy-import-func Provide a dummy implementation of all imported functions. The function will log the call and return an appropriate zero value. ;;; STDOUT ;;) diff --git a/test/interp/call-dummy-import.txt b/test/interp/call-dummy-import.txt new file mode 100644 index 00000000..0ec46162 --- /dev/null +++ b/test/interp/call-dummy-import.txt @@ -0,0 +1,20 @@ +;;; TOOL: run-interp +;;; ARGS: --dummy-import-func +(module + (import "foo" "bar" (func $bar (param i32 f32) (result i32))) + (import "baz" "quux" (func $quux (param f64) (result i64))) + + (func (export "f1") (result i32) + i32.const 1 + f32.const 2 + call $bar) + + (func (export "f2") (result i64) + f64.const 3 + call $quux)) +(;; STDOUT ;;; +called host foo.bar(i32:1, f32:2.000000) => i32:0 +f1() => i32:0 +called host baz.quux(f64:3.000000) => i64:0 +f2() => i64:0 +;;; STDOUT ;;) |