diff --git a/furvm/include/furvm/instruction.hpp b/furvm/include/furvm/instruction.hpp index 31f887b..7d0a9ed 100644 --- a/furvm/include/furvm/instruction.hpp +++ b/furvm/include/furvm/instruction.hpp @@ -21,6 +21,7 @@ struct instruction_argument { Constant, Type, Variable, + GlobalVariable, Function, Offset, @@ -78,6 +79,8 @@ struct instruction { Lengthof, Load, Store, + LoadGlobal, + StoreGlobal, Call, Jump, JumpNotZero, diff --git a/furvm/include/furvm/module.hpp b/furvm/include/furvm/module.hpp index 532e81d..1b95081 100644 --- a/furvm/include/furvm/module.hpp +++ b/furvm/include/furvm/module.hpp @@ -6,10 +6,14 @@ #include "furvm/function.hpp" #include "furvm/fwd.hpp" #include "furvm/handle.hpp" +#include "furvm/thing.hpp" #include #include +#include +#include #include +#include #include #include #include @@ -348,6 +352,33 @@ public: } const handle_container& types() const { return m_types; } +public: + void set_global_variable_count(std::uint16_t count) { + m_globalVariables.resize(count); + m_globalVariables.shrink_to_fit(); + } + + std::uint16_t get_global_variable_count() const { return static_cast(m_globalVariables.size()); } + + void store_global_variable(std::uint16_t var, thing<>&& thing) { + if (var >= m_globalVariables.size()) throw std::runtime_error("invalid slot"); + m_globalVariables.emplace(m_globalVariables.cbegin() + var, std::move(thing)); + } + + void store_global_variable(std::uint16_t var, const thing<>& thing) { + if (var >= m_globalVariables.size()) throw std::runtime_error("invalid slot"); + m_globalVariables.emplace(m_globalVariables.cbegin() + var, thing); + } + + thing<>& load_global_variable(std::uint16_t var) { + if (var >= m_globalVariables.size()) throw std::runtime_error("invalid slot"); + return m_globalVariables[var]; + } + + const thing<>& load_global_variable(std::uint16_t var) const { + if (var >= m_globalVariables.size()) throw std::runtime_error("invalid slot"); + return m_globalVariables[var]; + } public: /** * @brief Prints the module in a bytecode form to an output stream. @@ -376,6 +407,8 @@ private: handle_container m_types; + std::vector> m_globalVariables; + std::unordered_map m_nativeFunctions; }; diff --git a/furvm/src/executor.cpp b/furvm/src/executor.cpp index 00fd1a1..f18e434 100644 --- a/furvm/src/executor.cpp +++ b/furvm/src/executor.cpp @@ -326,6 +326,12 @@ void executor::step() { case instruction_t::Store: { store_thing(instr.arg.u16, std::move(pop_thing())); } break; + case instruction_t::LoadGlobal: { + push_thing(make_reference(frame.mod->load_global_variable(instr.arg.u16))); + } break; + case instruction_t::StoreGlobal: { + frame.mod->store_global_variable(instr.arg.u16, std::move(pop_thing())); + } break; case instruction_t::Call: { push_frame(frame.mod, *frame.mod->function_at(instr.arg.u16)); } break; diff --git a/furvm/src/instruction.cpp b/furvm/src/instruction.cpp index f929196..e4e2e31 100644 --- a/furvm/src/instruction.cpp +++ b/furvm/src/instruction.cpp @@ -27,6 +27,8 @@ const std::size_t instruction_argument::s_sizes[instruction_argument::Count] = { 4, // Variable: 2, + // GlobalVariable: + 2, // Function: 4, // Offset: @@ -54,6 +56,8 @@ const bool instruction_argument::s_signedness[instruction_argument::Count] = { false, // Variable: false, + // GlobalVariable: + false, // Function: false, // Offset: @@ -125,6 +129,10 @@ const instruction_argument_t instruction::s_arguments[instruction::Count] = { instruction_argument::Variable, // Store: instruction_argument::Variable, + // LoadGlobal: + instruction_argument::GlobalVariable, + // StoreGlobal: + instruction_argument::GlobalVariable, // Call: instruction_argument::Function, // Jump: diff --git a/furvm/src/module.cpp b/furvm/src/module.cpp index 196b63f..ef90be5 100644 --- a/furvm/src/module.cpp +++ b/furvm/src/module.cpp @@ -88,6 +88,8 @@ std::ostream& mod::serialize(std::ostream& os) const { } } + detail::serialize(os, static_cast(m_globalVariables.size())); + detail::serialize(os, std::uint64_t(m_bytecode.size())); return os.write(reinterpret_cast(m_bytecode.data()), static_cast(m_bytecode.size())); } @@ -197,6 +199,10 @@ mod mod::load(std::istream& is) { } } + std::uint16_t globalVariables = 0; + detail::load(is, globalVariables); + mod.set_global_variable_count(globalVariables); + std::uint64_t bytecodeLength = 0; detail::load(is, bytecodeLength); mod.bytecode().resize(bytecodeLength);