refactor(furvm): use new instructions in executor
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
#define FURVM_MODULE_HPP
|
#define FURVM_MODULE_HPP
|
||||||
|
|
||||||
#include "furlang/utility/hash.hpp"
|
#include "furlang/utility/hash.hpp"
|
||||||
|
#include "furlang/view.hpp"
|
||||||
#include "furvm/function.hpp"
|
#include "furvm/function.hpp"
|
||||||
#include "furvm/fwd.hpp"
|
#include "furvm/fwd.hpp"
|
||||||
#include "furvm/handle.hpp"
|
#include "furvm/handle.hpp"
|
||||||
@@ -195,7 +196,7 @@ public:
|
|||||||
*
|
*
|
||||||
* @return A constant reference to the bytecode.
|
* @return A constant reference to the bytecode.
|
||||||
*/
|
*/
|
||||||
constexpr const bytecode_t& bytecode() const { return m_bytecode; }
|
furlang::view<std::uint8_t> bytecode_view() const { return { m_bytecode.data(), m_bytecode.size() }; }
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Emplaces a function in the module's function container.
|
* @brief Emplaces a function in the module's function container.
|
||||||
@@ -284,6 +285,10 @@ public:
|
|||||||
m_functionMap.erase(it);
|
m_functionMap.erase(it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handle_container<function_h>& functions() const { return m_functions; }
|
||||||
|
|
||||||
|
const auto& function_map() const { return m_functionMap; }
|
||||||
public:
|
public:
|
||||||
template <typename NameFwd, typename Func>
|
template <typename NameFwd, typename Func>
|
||||||
void set_native_function(NameFwd&& name, Func&& func) {
|
void set_native_function(NameFwd&& name, Func&& func) {
|
||||||
@@ -341,6 +346,8 @@ public:
|
|||||||
void erase_type(Args&&... args) {
|
void erase_type(Args&&... args) {
|
||||||
m_types.erase(std::forward<Args>(args)...);
|
m_types.erase(std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handle_container<mod_type_h>& types() const { return m_types; }
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Prints the module in a bytecode form to an output stream.
|
* @brief Prints the module in a bytecode form to an output stream.
|
||||||
|
|||||||
+16
-36
@@ -1,5 +1,6 @@
|
|||||||
#include "furvm/executor.hpp"
|
#include "furvm/executor.hpp"
|
||||||
|
|
||||||
|
#include "furlang/view.hpp"
|
||||||
#include "furvm/context.hpp" // IWYU pragma: keep
|
#include "furvm/context.hpp" // IWYU pragma: keep
|
||||||
#include "furvm/exceptions.hpp"
|
#include "furvm/exceptions.hpp"
|
||||||
#include "furvm/function.hpp" // IWYU pragma: keep
|
#include "furvm/function.hpp" // IWYU pragma: keep
|
||||||
@@ -131,45 +132,36 @@ void executor::step() {
|
|||||||
|
|
||||||
struct frame& frame = m_frames.top();
|
struct frame& frame = m_frames.top();
|
||||||
|
|
||||||
instruction_t instr = static_cast<instruction_t>((*frame.mod).byte_at(frame.position++));
|
instruction instr{};
|
||||||
switch (instr) {
|
frame.position += instr.read(frame.mod->bytecode_view().subview(frame.position));
|
||||||
|
switch (instr.type) {
|
||||||
case instruction_t::NoOperation: break;
|
case instruction_t::NoOperation: break;
|
||||||
case instruction_t::PushS8: {
|
case instruction_t::PushS8: {
|
||||||
push_thing({ (struct thing_type){ thing_type::S8 }, m_context->thing_alloc() })->get<thing_type::s8>() =
|
push_thing({ (struct thing_type){ thing_type::S8 }, m_context->thing_alloc() })->get<thing_type::s8>() =
|
||||||
static_cast<thing_type::s8>(frame.mod->byte_at(frame.position++));
|
instr.arg.s8;
|
||||||
} break;
|
} break;
|
||||||
case instruction_t::PushU8: {
|
case instruction_t::PushU8: {
|
||||||
push_thing({ (struct thing_type){ thing_type::U8 }, m_context->thing_alloc() })->get<thing_type::u8>() =
|
push_thing({ (struct thing_type){ thing_type::U8 }, m_context->thing_alloc() })->get<thing_type::u8>() =
|
||||||
static_cast<thing_type::u8>(frame.mod->byte_at(frame.position++));
|
instr.arg.u8;
|
||||||
} break;
|
} break;
|
||||||
case instruction_t::PushS16: {
|
case instruction_t::PushS16: {
|
||||||
thing_type::u16 value = frame.mod->byte_at(frame.position++);
|
|
||||||
value |= static_cast<thing_type::u16>(frame.mod->byte_at(frame.position++) << 8);
|
|
||||||
push_thing({ (struct thing_type){ thing_type::S16 }, m_context->thing_alloc() })->get<thing_type::s16>() =
|
push_thing({ (struct thing_type){ thing_type::S16 }, m_context->thing_alloc() })->get<thing_type::s16>() =
|
||||||
static_cast<thing_type::s16>(value);
|
instr.arg.s16;
|
||||||
} break;
|
} break;
|
||||||
case instruction_t::PushU16: {
|
case instruction_t::PushU16: {
|
||||||
thing_type::u16 value = frame.mod->byte_at(frame.position++);
|
|
||||||
value |= static_cast<thing_type::u16>(frame.mod->byte_at(frame.position++) << 8);
|
|
||||||
push_thing({ (struct thing_type){ thing_type::U16 }, m_context->thing_alloc() })->get<thing_type::u16>() =
|
push_thing({ (struct thing_type){ thing_type::U16 }, m_context->thing_alloc() })->get<thing_type::u16>() =
|
||||||
value;
|
instr.arg.u16;
|
||||||
} break;
|
} break;
|
||||||
case instruction_t::PushS32: {
|
case instruction_t::PushS32: {
|
||||||
push_thing({ (struct thing_type){ thing_type::S32 }, m_context->thing_alloc() })->get<thing_type::s32>() =
|
push_thing({ (struct thing_type){ thing_type::S32 }, m_context->thing_alloc() })->get<thing_type::s32>() =
|
||||||
static_cast<thing_type::s32>(frame.mod->byte_at(frame.position++));
|
instr.arg.s8; // NOLINT
|
||||||
} break;
|
} break;
|
||||||
case instruction_t::PushU32: {
|
case instruction_t::PushU32: {
|
||||||
push_thing({ (struct thing_type){ thing_type::U32 }, m_context->thing_alloc() })->get<thing_type::u32>() =
|
push_thing({ (struct thing_type){ thing_type::U32 }, m_context->thing_alloc() })->get<thing_type::u32>() =
|
||||||
static_cast<thing_type::u32>(frame.mod->byte_at(frame.position++));
|
static_cast<thing_type::u32>(instr.arg.u8);
|
||||||
} break;
|
} break;
|
||||||
case instruction_t::Array: {
|
case instruction_t::Array: {
|
||||||
mod_type_id typeId = static_cast<mod_type_id>(frame.mod->byte_at(frame.position)) |
|
const auto& type = *mod_to_thing_type(frame.mod, *frame.mod->type_at(instr.arg.u32));
|
||||||
(static_cast<mod_type_id>(frame.mod->byte_at(frame.position + 1)) << 8) |
|
|
||||||
(static_cast<mod_type_id>(frame.mod->byte_at(frame.position + 2)) << 16) |
|
|
||||||
(static_cast<mod_type_id>(frame.mod->byte_at(frame.position + 3)) << 24);
|
|
||||||
frame.position += 4;
|
|
||||||
|
|
||||||
const auto& type = *mod_to_thing_type(frame.mod, *frame.mod->type_at(typeId));
|
|
||||||
if (type.type != thing_type::Array || type.value.array.type == nullptr || type.value.array.type == &type)
|
if (type.type != thing_type::Array || type.value.array.type == nullptr || type.value.array.type == &type)
|
||||||
throw std::runtime_error("invalid array type");
|
throw std::runtime_error("invalid array type");
|
||||||
|
|
||||||
@@ -304,31 +296,19 @@ void executor::step() {
|
|||||||
length->get<thing_type::u64>() = thing->length();
|
length->get<thing_type::u64>() = thing->length();
|
||||||
} break;
|
} break;
|
||||||
case instruction_t::Load: {
|
case instruction_t::Load: {
|
||||||
variable_t variable = static_cast<std::uint16_t>(frame.mod->byte_at(frame.position)) |
|
push_thing(load_thing(instr.arg.u16));
|
||||||
(static_cast<std::uint16_t>(frame.mod->byte_at(frame.position + 1)) << 8);
|
|
||||||
frame.position += 2;
|
|
||||||
push_thing(load_thing(variable));
|
|
||||||
} break;
|
} break;
|
||||||
case instruction_t::Store: {
|
case instruction_t::Store: {
|
||||||
variable_t variable = static_cast<std::uint16_t>(frame.mod->byte_at(frame.position)) |
|
store_thing(instr.arg.u16, std::move(pop_thing()));
|
||||||
(static_cast<std::uint16_t>(frame.mod->byte_at(frame.position + 1)) << 8);
|
|
||||||
frame.position += 2;
|
|
||||||
store_thing(variable, std::move(pop_thing()));
|
|
||||||
} break;
|
} break;
|
||||||
case instruction_t::Call: {
|
case instruction_t::Call: {
|
||||||
function_id funcId = static_cast<std::uint16_t>(frame.mod->byte_at(frame.position)) |
|
push_frame(frame.mod, *frame.mod->function_at(instr.arg.u16));
|
||||||
(static_cast<std::uint16_t>(frame.mod->byte_at(frame.position + 1)) << 8);
|
|
||||||
frame.position += 2;
|
|
||||||
push_frame(frame.mod, *frame.mod->function_at(funcId));
|
|
||||||
} break;
|
} break;
|
||||||
case instruction_t::Jump: {
|
case instruction_t::Jump: {
|
||||||
std::int8_t offset = static_cast<std::int8_t>(frame.mod->byte_at(frame.position++));
|
frame.position += instr.arg.s8;
|
||||||
frame.position += offset;
|
|
||||||
} break;
|
} break;
|
||||||
case instruction_t::JumpNotZero: {
|
case instruction_t::JumpNotZero: {
|
||||||
byte offset = frame.mod->byte_at(frame.position++);
|
if (pop_thing()->integer() != 0) frame.position += instr.arg.s8;
|
||||||
auto cond = pop_thing();
|
|
||||||
if (cond->integer() != 0) frame.position += (std::int8_t)offset;
|
|
||||||
} break;
|
} break;
|
||||||
case instruction_t::Return: {
|
case instruction_t::Return: {
|
||||||
pop_frame();
|
pop_frame();
|
||||||
|
|||||||
Reference in New Issue
Block a user