From 056be42c0be2a4ac43fd50ab3c34c269f24244c9 Mon Sep 17 00:00:00 2001 From: Ali Mohammad Pur Date: Sat, 1 May 2021 03:19:01 +0430 Subject: [PATCH] LibWasm: Start implementing a naive bytecode interpreter As the parser now flattens out the instructions and inserts synthetic nesting/structured instructions where needed, we can treat the whole thing as a simple parsed bytecode stream. This currently knows how to execute the following instructions: - unreachable - nop - local.get - local.set - {i,f}{32,64}.const - block - loop - if/else - branch / branch_if - i32_add - i32_and/or/xor - i32_ne This also extends the 'wasm' utility to optionally execute the first function in the module with optionally user-supplied arguments. --- AK/Debug.h.in | 3 + Meta/CMake/all_the_debug_macros.cmake | 1 + .../LibWasm/AbstractMachine/AbstractMachine.h | 37 +- .../LibWasm/AbstractMachine/Configuration.cpp | 29 ++ .../LibWasm/AbstractMachine/Configuration.h | 6 +- .../LibWasm/AbstractMachine/Interpreter.cpp | 393 +++++++++++++++++- .../LibWasm/AbstractMachine/Interpreter.h | 5 + .../Libraries/LibWasm/Printer/Printer.cpp | 2 +- Userland/Libraries/LibWasm/Printer/Printer.h | 2 + Userland/Utilities/wasm.cpp | 65 ++- 10 files changed, 513 insertions(+), 30 deletions(-) diff --git a/AK/Debug.h.in b/AK/Debug.h.in index cdbbb622dbe..a037bbdf9bc 100644 --- a/AK/Debug.h.in +++ b/AK/Debug.h.in @@ -422,3 +422,6 @@ #cmakedefine01 WSSCREEN_DEBUG #endif +#ifndef WASM_TRACE_DEBUG +#cmakedefine01 WASM_TRACE_DEBUG +#endif diff --git a/Meta/CMake/all_the_debug_macros.cmake b/Meta/CMake/all_the_debug_macros.cmake index cb8297a1931..e89e4d19620 100644 --- a/Meta/CMake/all_the_debug_macros.cmake +++ b/Meta/CMake/all_the_debug_macros.cmake @@ -179,6 +179,7 @@ set(LINE_EDITOR_DEBUG ON) set(LANGUAGE_SERVER_DEBUG ON) set(GL_DEBUG ON) set(WASM_BINPARSER_DEBUG ON) +set(WASM_TRACE_DEBUG ON) set(PDF_DEBUG ON) set(SOLITAIRE_DEBUG ON) diff --git a/Userland/Libraries/LibWasm/AbstractMachine/AbstractMachine.h b/Userland/Libraries/LibWasm/AbstractMachine/AbstractMachine.h index f97b747a1f5..badd3422892 100644 --- a/Userland/Libraries/LibWasm/AbstractMachine/AbstractMachine.h +++ b/Userland/Libraries/LibWasm/AbstractMachine/AbstractMachine.h @@ -49,7 +49,7 @@ public: } template - requires(sizeof(T) <= sizeof(u64)) explicit Value(ValueType type, T raw_value) + requires(sizeof(T) == sizeof(u64)) explicit Value(ValueType type, T raw_value) : m_value(0) , m_type(type) { @@ -89,6 +89,33 @@ public: { } + Value& operator=(Value&& value) + { + m_value = move(value.m_value); + m_type = move(value.m_type); + return *this; + } + + template + Optional to() + { + Optional result; + m_value.visit( + [&](auto value) { + if constexpr (!IsSame && !IsSame) + result = value; + }, + [&](const FunctionAddress& address) { + if constexpr (IsSame) + result = address; + }, + [&](const ExternAddress& address) { + if constexpr (IsSame) + result = address; + }); + return result; + } + auto& type() const { return m_type; } auto& value() const { return m_value; } @@ -317,14 +344,17 @@ private: class Label { public: - explicit Label(InstructionPointer continuation) - : m_continuation(continuation) + explicit Label(size_t arity, InstructionPointer continuation) + : m_arity(arity) + , m_continuation(continuation) { } auto continuation() const { return m_continuation; } + auto arity() const { return m_arity; } private: + size_t m_arity { 0 }; InstructionPointer m_continuation; }; @@ -342,6 +372,7 @@ public: auto& module() const { return m_module; } auto& locals() const { return m_locals; } + auto& locals() { return m_locals; } auto& expression() const { return m_expression; } auto arity() const { return m_arity; } diff --git a/Userland/Libraries/LibWasm/AbstractMachine/Configuration.cpp b/Userland/Libraries/LibWasm/AbstractMachine/Configuration.cpp index 6666f8598ff..2da24f00227 100644 --- a/Userland/Libraries/LibWasm/AbstractMachine/Configuration.cpp +++ b/Userland/Libraries/LibWasm/AbstractMachine/Configuration.cpp @@ -74,4 +74,33 @@ Result Configuration::execute() return Result { move(results_moved) }; } +void Configuration::dump_stack() +{ + for (const auto& entry : stack().entries()) { + entry.visit( + [](const NonnullOwnPtr& v) { + v->value().visit([](const T& v) { + if constexpr (IsIntegral || IsFloatingPoint) + dbgln(" {}", v); + else + dbgln(" *{}", v.value()); + }); + }, + [](const NonnullOwnPtr& f) { + dbgln(" frame({})", f->arity()); + for (auto& local : f->locals()) { + local.value().visit([](const T& v) { + if constexpr (IsIntegral || IsFloatingPoint) + dbgln(" {}", v); + else + dbgln(" *{}", v.value()); + }); + } + }, + [](const NonnullOwnPtr