mirror of
https://git.sfja.dk/Mikkel/slige.git
synced 2025-01-18 18:36:31 +00:00
136 lines
2.8 KiB
C++
136 lines
2.8 KiB
C++
#pragma once
|
|
|
|
#include "arch.hpp"
|
|
#include "value.hpp"
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <format>
|
|
#include <iostream>
|
|
#include <vector>
|
|
|
|
namespace sliger {
|
|
|
|
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;
|
|
};
|
|
|
|
class VM {
|
|
public:
|
|
VM(const std::vector<uint32_t>& program, VMOpts opts)
|
|
: opts(opts)
|
|
, program(program.data())
|
|
, program_size(program.size())
|
|
{
|
|
}
|
|
void run();
|
|
|
|
inline void step() { this->pc += 1; }
|
|
|
|
inline auto eat_op() -> Op
|
|
{
|
|
auto value = curr_as_op();
|
|
step();
|
|
return value;
|
|
}
|
|
inline auto curr_as_op() const -> Op
|
|
{
|
|
return static_cast<Op>(this->program[this->pc]);
|
|
}
|
|
|
|
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];
|
|
}
|
|
|
|
inline auto done() const -> bool { return this->pc >= this->program_size; }
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
private:
|
|
VMOpts opts;
|
|
uint32_t pc = 0;
|
|
uint32_t bp = 0;
|
|
const uint32_t* program;
|
|
size_t program_size;
|
|
std::vector<Value> stack;
|
|
std::vector<Value> pool_heap;
|
|
SourcePos current_pos = { 0, 1, 1 };
|
|
};
|
|
|
|
}
|