#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 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> 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; } }