mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 14:28:12 +00:00
wasm: Add a help command to the shell mode and start it on --shell
This commit is contained in:
parent
2b789adc16
commit
ccc79149d4
1 changed files with 56 additions and 15 deletions
|
@ -91,6 +91,30 @@ static bool pre_interpret_hook(Wasm::Configuration& config, Wasm::InstructionPoi
|
||||||
if (args.is_empty())
|
if (args.is_empty())
|
||||||
continue;
|
continue;
|
||||||
auto& cmd = args[0];
|
auto& cmd = args[0];
|
||||||
|
if (cmd.is_one_of("h", "help")) {
|
||||||
|
warnln("Wasm shell commands");
|
||||||
|
warnln("Toplevel:");
|
||||||
|
warnln("- [s]tep Run one instruction");
|
||||||
|
warnln("- next Alias for step");
|
||||||
|
warnln("- [c]ontinue Execute until a trap or the program exit point");
|
||||||
|
warnln("- [p]rint <args...> Print various things (see section on print)");
|
||||||
|
warnln("- call <fn> <args...> Call the function <fn> with the given arguments");
|
||||||
|
warnln("- set <args...> Set shell option (see section on settings)");
|
||||||
|
warnln("- unset <args...> Unset shell option (see section on settings)");
|
||||||
|
warnln("- [h]elp Print this help");
|
||||||
|
warnln();
|
||||||
|
warnln("Print:");
|
||||||
|
warnln("- print [s]tack Print the contents of the stack, including frames and labels");
|
||||||
|
warnln("- print [[m]em]ory <index> Print the contents of the memory identified by <index>");
|
||||||
|
warnln("- print [[i]nstr]uction Print the current instruction");
|
||||||
|
warnln("- print [[f]unc]tion <index> Print the function identified by <index>");
|
||||||
|
warnln();
|
||||||
|
warnln("Settings:");
|
||||||
|
warnln("- set print stack Make the shell print the stack on every instruction executed");
|
||||||
|
warnln("- set print [instr]uction Make the shell print the instruction that will be executed next");
|
||||||
|
warnln();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (cmd.is_one_of("s", "step", "next")) {
|
if (cmd.is_one_of("s", "step", "next")) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -266,6 +290,7 @@ int main(int argc, char* argv[])
|
||||||
bool attempt_instantiate = false;
|
bool attempt_instantiate = false;
|
||||||
bool debug = false;
|
bool debug = false;
|
||||||
bool export_all_imports = false;
|
bool export_all_imports = false;
|
||||||
|
bool shell_mode = false;
|
||||||
String exported_function_to_execute;
|
String exported_function_to_execute;
|
||||||
Vector<u64> values_to_push;
|
Vector<u64> values_to_push;
|
||||||
Vector<String> modules_to_link_in;
|
Vector<String> modules_to_link_in;
|
||||||
|
@ -277,6 +302,7 @@ int main(int argc, char* argv[])
|
||||||
parser.add_option(attempt_instantiate, "Attempt to instantiate the module", "instantiate", 'i');
|
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(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(export_all_imports, "Export noop functions corresponding to imports", "export-noop", 0);
|
||||||
|
parser.add_option(shell_mode, "Launch a REPL in the module's context (implies -i)", "shell", 's');
|
||||||
parser.add_option(Core::ArgsParser::Option {
|
parser.add_option(Core::ArgsParser::Option {
|
||||||
.requires_argument = true,
|
.requires_argument = true,
|
||||||
.help_string = "Extra modules to link with, use to resolve imports",
|
.help_string = "Extra modules to link with, use to resolve imports",
|
||||||
|
@ -307,12 +333,17 @@ int main(int argc, char* argv[])
|
||||||
});
|
});
|
||||||
parser.parse(argc, argv);
|
parser.parse(argc, argv);
|
||||||
|
|
||||||
if (debug && exported_function_to_execute.is_empty()) {
|
if (shell_mode) {
|
||||||
|
debug = true;
|
||||||
|
attempt_instantiate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!shell_mode && debug && exported_function_to_execute.is_empty()) {
|
||||||
warnln("Debug what? (pass -e fn)");
|
warnln("Debug what? (pass -e fn)");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (debug) {
|
if (debug || shell_mode) {
|
||||||
old_signal = signal(SIGINT, sigint_handler);
|
old_signal = signal(SIGINT, sigint_handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -337,6 +368,7 @@ int main(int argc, char* argv[])
|
||||||
g_interpreter.pre_interpret_hook = pre_interpret_hook;
|
g_interpreter.pre_interpret_hook = pre_interpret_hook;
|
||||||
g_interpreter.post_interpret_hook = post_interpret_hook;
|
g_interpreter.post_interpret_hook = post_interpret_hook;
|
||||||
}
|
}
|
||||||
|
|
||||||
// First, resolve the linked modules
|
// First, resolve the linked modules
|
||||||
NonnullOwnPtrVector<Wasm::ModuleInstance> linked_instances;
|
NonnullOwnPtrVector<Wasm::ModuleInstance> linked_instances;
|
||||||
Vector<Wasm::Module> linked_modules;
|
Vector<Wasm::Module> linked_modules;
|
||||||
|
@ -414,6 +446,21 @@ int main(int argc, char* argv[])
|
||||||
}
|
}
|
||||||
auto module_instance = result.release_value();
|
auto module_instance = result.release_value();
|
||||||
|
|
||||||
|
auto launch_repl = [&] {
|
||||||
|
Wasm::Configuration config { machine.store() };
|
||||||
|
Wasm::Expression expression { {} };
|
||||||
|
config.set_frame(Wasm::Frame {
|
||||||
|
*module_instance,
|
||||||
|
Vector<Wasm::Value> {},
|
||||||
|
expression,
|
||||||
|
0,
|
||||||
|
});
|
||||||
|
Wasm::Instruction instr { Wasm::Instructions::nop };
|
||||||
|
Wasm::InstructionPointer ip { 0 };
|
||||||
|
g_continue = false;
|
||||||
|
pre_interpret_hook(config, ip, instr);
|
||||||
|
};
|
||||||
|
|
||||||
auto stream = Core::OutputFileStream::standard_output();
|
auto stream = Core::OutputFileStream::standard_output();
|
||||||
auto print_func = [&](auto const& address) {
|
auto print_func = [&](auto const& address) {
|
||||||
Wasm::FunctionInstance* fn = machine.store().get(address);
|
Wasm::FunctionInstance* fn = machine.store().get(address);
|
||||||
|
@ -438,6 +485,11 @@ int main(int argc, char* argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (shell_mode) {
|
||||||
|
launch_repl();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!exported_function_to_execute.is_empty()) {
|
if (!exported_function_to_execute.is_empty()) {
|
||||||
Optional<Wasm::FunctionAddress> run_address;
|
Optional<Wasm::FunctionAddress> run_address;
|
||||||
Vector<Wasm::Value> values;
|
Vector<Wasm::Value> values;
|
||||||
|
@ -475,19 +527,8 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
auto result = machine.invoke(g_interpreter, run_address.value(), move(values));
|
auto result = machine.invoke(g_interpreter, run_address.value(), move(values));
|
||||||
|
|
||||||
if (debug) {
|
if (debug)
|
||||||
Wasm::Configuration config { machine.store() };
|
launch_repl();
|
||||||
config.set_frame(Wasm::Frame {
|
|
||||||
*module_instance,
|
|
||||||
Vector<Wasm::Value> {},
|
|
||||||
instance->get<Wasm::WasmFunction>().code().body(),
|
|
||||||
1,
|
|
||||||
});
|
|
||||||
Wasm::Instruction instr { Wasm::Instructions::nop };
|
|
||||||
Wasm::InstructionPointer ip { 0 };
|
|
||||||
g_continue = false;
|
|
||||||
pre_interpret_hook(config, ip, instr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result.is_trap())
|
if (result.is_trap())
|
||||||
warnln("Execution trapped!");
|
warnln("Execution trapped!");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue