slige/runtime/vm.hpp

136 lines
2.8 KiB
C++
Raw Normal View History

2024-11-08 11:22:42 +00:00
#pragma once
#include "arch.hpp"
#include "value.hpp"
#include <cstddef>
#include <cstdint>
2024-11-11 14:31:54 +00:00
#include <format>
#include <iostream>
2024-11-08 11:22:42 +00:00
#include <vector>
namespace sliger {
2024-11-18 14:01:24 +00:00
struct SourcePos {
int index;
int line;
int col;
};
struct FGNode {
uint32_t fn;
int64_t acc;
int64_t ic_start;
size_t parent;
std::vector<size_t> children;
};
class FlameGraphBuilder {
public:
inline auto report_call(size_t fn, int64_t ic_start) { }
inline auto report_return(int64_t ic_end) { }
private:
std::vector<FGNode> nodes;
};
struct VMOpts {
bool flameGraph;
bool codeCoverage;
};
2024-11-08 11:22:42 +00:00
class VM {
public:
2024-11-18 14:01:24 +00:00
VM(const std::vector<uint32_t>& program, VMOpts opts)
: opts(opts)
, program(program.data())
2024-11-08 11:22:42 +00:00
, program_size(program.size())
{
}
void run();
inline void step() { this->pc += 1; }
2024-11-11 14:31:54 +00:00
inline auto eat_op() -> Op
2024-11-08 11:22:42 +00:00
{
auto value = curr_as_op();
step();
return value;
}
inline auto curr_as_op() const -> Op
{
return static_cast<Op>(this->program[this->pc]);
}
2024-11-11 14:31:54 +00:00
inline auto eat_int32() -> int32_t
{
auto value = curr_as_int32();
step();
return value;
}
inline auto curr_as_int32() const -> int32_t
{
return static_cast<int32_t>(this->program[this->pc]);
}
inline auto eat_uint32() -> uint32_t
{
auto value = curr_as_uint32();
step();
return value;
}
inline auto curr_as_uint32() const -> uint32_t
{
return this->program[this->pc];
}
2024-11-08 11:22:42 +00:00
inline auto done() const -> bool { return this->pc >= this->program_size; }
2024-11-11 14:31:54 +00:00
inline auto fn_stack_at(size_t idx) -> Value&
{
return this->stack.at(this->bp + idx);
}
inline void assert_fn_stack_has(size_t count)
{
if (this->stack.size() - this->bp < count) {
std::cerr << std::format("stack underflow");
std::exit(1);
}
}
inline void assert_stack_has(size_t count)
{
if (this->stack.size() < count) {
std::cerr << std::format("stack underflow");
std::exit(1);
}
}
inline void stack_push(Value&& value) { this->stack.push_back(value); }
inline void stack_push(Value& value) { this->stack.push_back(value); }
inline auto stack_pop() -> Value
{
auto value = this->stack.at(this->stack.size() - 1);
this->stack.pop_back();
return value;
}
inline auto assert_program_has(size_t count)
{
if (this->pc + count >= program_size) {
std::cerr << std::format("stack underflow");
std::exit(1);
}
}
2024-11-08 11:22:42 +00:00
private:
2024-11-18 14:01:24 +00:00
VMOpts opts;
2024-11-08 11:22:42 +00:00
uint32_t pc = 0;
2024-11-11 14:31:54 +00:00
uint32_t bp = 0;
const uint32_t* program;
2024-11-08 11:22:42 +00:00
size_t program_size;
std::vector<Value> stack;
std::vector<Value> pool_heap;
2024-11-18 14:01:24 +00:00
SourcePos current_pos = { 0, 1, 1 };
2024-11-08 11:22:42 +00:00
};
2024-11-18 14:01:24 +00:00
2024-11-08 11:22:42 +00:00
}