/src/serenity/Userland/Libraries/LibWasm/AbstractMachine/BytecodeInterpreter.h
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 | | #pragma once |
8 | | |
9 | | #include <AK/StackInfo.h> |
10 | | #include <LibWasm/AbstractMachine/Configuration.h> |
11 | | #include <LibWasm/AbstractMachine/Interpreter.h> |
12 | | |
13 | | namespace Wasm { |
14 | | |
15 | | struct BytecodeInterpreter : public Interpreter { |
16 | | explicit BytecodeInterpreter(StackInfo const& stack_info) |
17 | 0 | : m_stack_info(stack_info) |
18 | 0 | { |
19 | 0 | } |
20 | | |
21 | | virtual void interpret(Configuration&) final; |
22 | | |
23 | 0 | virtual ~BytecodeInterpreter() override = default; |
24 | 0 | virtual bool did_trap() const final { return !m_trap.has<Empty>(); } |
25 | | virtual ByteString trap_reason() const final |
26 | 0 | { |
27 | 0 | return m_trap.visit( |
28 | 0 | [](Empty) -> ByteString { VERIFY_NOT_REACHED(); }, |
29 | 0 | [](Trap const& trap) { return trap.reason; }, |
30 | 0 | [](JS::Completion const& completion) { return completion.value()->to_string_without_side_effects().to_byte_string(); }); |
31 | 0 | } |
32 | 0 | virtual void clear_trap() final { m_trap = Empty {}; } |
33 | | |
34 | | struct CallFrameHandle { |
35 | | explicit CallFrameHandle(BytecodeInterpreter& interpreter, Configuration& configuration) |
36 | 0 | : m_configuration_handle(configuration) |
37 | 0 | , m_interpreter(interpreter) |
38 | 0 | { |
39 | 0 | } |
40 | | |
41 | 0 | ~CallFrameHandle() = default; |
42 | | |
43 | | Configuration::CallFrameHandle m_configuration_handle; |
44 | | BytecodeInterpreter& m_interpreter; |
45 | | }; |
46 | | |
47 | | protected: |
48 | | void interpret_instruction(Configuration&, InstructionPointer&, Instruction const&); |
49 | | void branch_to_label(Configuration&, LabelIndex); |
50 | | template<typename ReadT, typename PushT> |
51 | | void load_and_push(Configuration&, Instruction const&); |
52 | | template<typename PopT, typename StoreT> |
53 | | void pop_and_store(Configuration&, Instruction const&); |
54 | | template<size_t N> |
55 | | void pop_and_store_lane_n(Configuration&, Instruction const&); |
56 | | template<size_t M, size_t N, template<typename> typename SetSign> |
57 | | void load_and_push_mxn(Configuration&, Instruction const&); |
58 | | template<size_t N> |
59 | | void load_and_push_lane_n(Configuration&, Instruction const&); |
60 | | template<size_t N> |
61 | | void load_and_push_zero_n(Configuration&, Instruction const&); |
62 | | template<size_t M> |
63 | | void load_and_push_m_splat(Configuration&, Instruction const&); |
64 | | template<size_t M, template<size_t> typename NativeType> |
65 | | void set_top_m_splat(Configuration&, NativeType<M>); |
66 | | template<size_t M, template<size_t> typename NativeType> |
67 | | void pop_and_push_m_splat(Configuration&, Instruction const&); |
68 | | template<typename M, template<typename> typename SetSign, typename VectorType = Native128ByteVectorOf<M, SetSign>> |
69 | | VectorType pop_vector(Configuration&); |
70 | | void store_to_memory(Configuration&, Instruction::MemoryArgument const&, ReadonlyBytes data, u32 base); |
71 | | void call_address(Configuration&, FunctionAddress); |
72 | | |
73 | | template<typename PopTypeLHS, typename PushType, typename Operator, typename PopTypeRHS = PopTypeLHS, typename... Args> |
74 | | void binary_numeric_operation(Configuration&, Args&&...); |
75 | | |
76 | | template<typename PopType, typename PushType, typename Operator, typename... Args> |
77 | | void unary_operation(Configuration&, Args&&...); |
78 | | |
79 | | template<typename T> |
80 | | T read_value(ReadonlyBytes data); |
81 | | |
82 | | ALWAYS_INLINE bool trap_if_not(bool value, StringView reason) |
83 | 0 | { |
84 | 0 | if (!value) |
85 | 0 | m_trap = Trap { reason }; |
86 | 0 | return !m_trap.has<Empty>(); |
87 | 0 | } |
88 | | |
89 | | Variant<Trap, JS::Completion, Empty> m_trap; |
90 | | StackInfo const& m_stack_info; |
91 | | }; |
92 | | |
93 | | struct DebuggerBytecodeInterpreter : public BytecodeInterpreter { |
94 | | DebuggerBytecodeInterpreter(StackInfo const& stack_info) |
95 | | : BytecodeInterpreter(stack_info) |
96 | 0 | { |
97 | 0 | } |
98 | | virtual ~DebuggerBytecodeInterpreter() override = default; |
99 | | |
100 | | Function<bool(Configuration&, InstructionPointer&, Instruction const&)> pre_interpret_hook; |
101 | | Function<bool(Configuration&, InstructionPointer&, Instruction const&, Interpreter const&)> post_interpret_hook; |
102 | | |
103 | | private: |
104 | | void interpret_instruction(Configuration&, InstructionPointer&, Instruction const&); |
105 | | }; |
106 | | |
107 | | } |