142 lines
3.6 KiB
C++
142 lines
3.6 KiB
C++
#include "bytecode.hh"
|
|
#include "../common/overloaded.hh"
|
|
|
|
namespace tyche {
|
|
|
|
Bytecode::Bytecode(ByteArray ba)
|
|
: byte_array_(std::move(ba))
|
|
{
|
|
// check file size
|
|
if (byte_array_.size() < (HEADER_SZ + INDEX_SZ))
|
|
throw BytecodeParsingError("Invalid bytecode format (file too short)");
|
|
|
|
// check magic number and version
|
|
if (byte_array_.get_uint32(0) != MAGIC)
|
|
throw BytecodeParsingError("Invalid bytecode format (magic number not matching)");
|
|
if (byte_array_.get_uint32(4) != VERSION)
|
|
throw BytecodeParsingError("Unexpected bytecode format version");
|
|
|
|
// load cache
|
|
cache_.constants_addr = byte_array_.get_uint32(HEADER_SZ);
|
|
cache_.n_constants = byte_array_.get_uint16(HEADER_SZ + 4);
|
|
cache_.functions_addr = byte_array_.get_uint32(HEADER_SZ + 6);
|
|
cache_.n_functions = byte_array_.get_uint16(HEADER_SZ + 10);
|
|
}
|
|
|
|
uint32_t Bytecode::n_constants() const
|
|
{
|
|
return cache_.n_constants;
|
|
}
|
|
|
|
uint32_t Bytecode::n_functions() const
|
|
{
|
|
return cache_.n_functions;
|
|
}
|
|
|
|
int32_t Bytecode::get_constant_int(uint32_t idx) const
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
float Bytecode::get_constant_float(uint32_t idx) const
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
std::string Bytecode::get_constant_string(uint32_t idx) const
|
|
{
|
|
return std::string();
|
|
}
|
|
|
|
Bytecode::FunctionDef Bytecode::get_function_def(uint32_t function_id) const
|
|
{
|
|
return Bytecode::FunctionDef();
|
|
}
|
|
|
|
uint8_t Bytecode::get_code_byte(uint32_t function_id, uint32_t idx) const
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int32_t Bytecode::get_code_int(uint32_t function_id, uint32_t idx) const
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
float Bytecode::get_code_float(uint32_t function_id, uint32_t idx) const
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
ByteArray Bytecode::generate(BytecodePrototype const& bp)
|
|
{
|
|
ByteArray ba;
|
|
|
|
// constants
|
|
std::vector<uint32_t> constant_table;
|
|
ByteArray constant_array;
|
|
uint32_t idx = 0;
|
|
for (auto const& constant: bp.constants) {
|
|
constant_table.emplace_back(idx);
|
|
std::visit(overloaded {
|
|
[&](int32_t i) { constant_array.append_int(i); },
|
|
[&](float f) { constant_array.append_float(f); },
|
|
[&](std::string const& s) { constant_array.append_string(s); },
|
|
}, constant);
|
|
idx = constant_array.size();
|
|
}
|
|
|
|
// function table
|
|
std::vector<std::pair<FunctionDef, uint32_t>> functions;
|
|
ByteArray code;
|
|
for (auto const& f: bp.functions) {
|
|
code.append_bytearray(f.code);
|
|
functions.emplace_back(std::make_pair(FunctionDef { f.n_pars, f.n_locals }, code.size()));
|
|
}
|
|
|
|
//
|
|
// build binary
|
|
//
|
|
|
|
// header
|
|
ba.set_uint32(0, MAGIC);
|
|
ba.set_byte(4, VERSION);
|
|
|
|
// constants
|
|
idx = HEADER_SZ + INDEX_SZ;
|
|
for (auto const& const_idx: constant_table) {
|
|
ba.set_uint32(idx, const_idx);
|
|
idx += 4;
|
|
}
|
|
ba.append_bytearray(constant_array);
|
|
|
|
// constant index
|
|
if (!constant_table.empty()) {
|
|
ba.set_uint32(HEADER_SZ, HEADER_SZ + INDEX_SZ);
|
|
ba.set_uint16(HEADER_SZ + 4, constant_table.size());
|
|
}
|
|
|
|
// functions
|
|
size_t functions_start = idx + (constant_table.size() * 4);
|
|
idx = functions_start;
|
|
uint32_t code_idx = 0;
|
|
for (auto const& f: functions) {
|
|
ba.set_uint32(idx, code_idx);
|
|
ba.set_uint16(idx + 4, f.first.n_params);
|
|
ba.set_uint16(idx + 6, f.first.locals);
|
|
idx += 8;
|
|
code_idx += f.second;
|
|
}
|
|
for (auto const& f: bp.functions)
|
|
ba.append_bytearray(f.code);
|
|
|
|
// function index
|
|
if (!functions.empty()) {
|
|
ba.set_uint32(HEADER_SZ + 6, functions_start);
|
|
ba.set_uint16(HEADER_SZ + 6 + 4, functions.size());
|
|
}
|
|
|
|
return ba;
|
|
}
|
|
|
|
} |