/src/serenity/Userland/Libraries/LibWasm/AbstractMachine/Configuration.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2021, Ali Mohammad Pur <mpfard@serenityos.org> |
3 | | * |
4 | | * SPDX-License-Identifier: BSD-2-Clause |
5 | | */ |
6 | | |
7 | | #include <AK/MemoryStream.h> |
8 | | #include <LibWasm/AbstractMachine/Configuration.h> |
9 | | #include <LibWasm/AbstractMachine/Interpreter.h> |
10 | | #include <LibWasm/Printer/Printer.h> |
11 | | |
12 | | namespace Wasm { |
13 | | |
14 | | void Configuration::unwind(Badge<CallFrameHandle>, CallFrameHandle const& frame_handle) |
15 | 0 | { |
16 | 0 | auto frame = m_frame_stack.take_last(); |
17 | 0 | m_depth--; |
18 | 0 | m_ip = frame_handle.ip; |
19 | 0 | } |
20 | | |
21 | | Result Configuration::call(Interpreter& interpreter, FunctionAddress address, Vector<Value> arguments) |
22 | 0 | { |
23 | 0 | auto* function = m_store.get(address); |
24 | 0 | if (!function) |
25 | 0 | return Trap {}; |
26 | 0 | if (auto* wasm_function = function->get_pointer<WasmFunction>()) { |
27 | 0 | Vector<Value> locals = move(arguments); |
28 | 0 | locals.ensure_capacity(locals.size() + wasm_function->code().func().locals().size()); |
29 | 0 | for (auto& local : wasm_function->code().func().locals()) { |
30 | 0 | for (size_t i = 0; i < local.n(); ++i) |
31 | 0 | locals.append(Value()); |
32 | 0 | } |
33 | |
|
34 | 0 | set_frame(Frame { |
35 | 0 | wasm_function->module(), |
36 | 0 | move(locals), |
37 | 0 | wasm_function->code().func().body(), |
38 | 0 | wasm_function->type().results().size(), |
39 | 0 | }); |
40 | 0 | m_ip = 0; |
41 | 0 | return execute(interpreter); |
42 | 0 | } |
43 | | |
44 | | // It better be a host function, else something is really wrong. |
45 | 0 | auto& host_function = function->get<HostFunction>(); |
46 | 0 | return host_function.function()(*this, arguments); |
47 | 0 | } |
48 | | |
49 | | Result Configuration::execute(Interpreter& interpreter) |
50 | 0 | { |
51 | 0 | interpreter.interpret(*this); |
52 | 0 | if (interpreter.did_trap()) |
53 | 0 | return Trap { interpreter.trap_reason() }; |
54 | | |
55 | 0 | Vector<Value> results; |
56 | 0 | results.ensure_capacity(frame().arity()); |
57 | 0 | for (size_t i = 0; i < frame().arity(); ++i) |
58 | 0 | results.unchecked_append(value_stack().take_last()); |
59 | |
|
60 | 0 | label_stack().take_last(); |
61 | 0 | return Result { move(results) }; |
62 | 0 | } |
63 | | |
64 | | void Configuration::dump_stack() |
65 | 0 | { |
66 | 0 | auto print_value = []<typename... Ts>(CheckedFormatString<Ts...> format, Ts... vs) { |
67 | 0 | AllocatingMemoryStream memory_stream; |
68 | 0 | Printer { memory_stream }.print(vs...); |
69 | 0 | auto buffer = memory_stream.read_until_eof().release_value_but_fixme_should_propagate_errors(); |
70 | 0 | dbgln(format.view(), StringView(buffer).trim_whitespace()); |
71 | 0 | }; |
72 | 0 | for (auto const& value : value_stack()) { |
73 | 0 | print_value(" {}", value); |
74 | 0 | } |
75 | 0 | } |
76 | | |
77 | | } |