diff --git a/CMakeLists.txt b/CMakeLists.txt index ac29828..158f32b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -72,7 +72,8 @@ target_compile_options(lib${PROJECT_NAME} PRIVATE ${warnings}) # tests # -add_executable(${PROJECT_NAME}-bytecode-test src/bytecode/tests.cc) +add_executable(${PROJECT_NAME}-bytecode-test src/bytecode/tests.cc + common/overloaded.hh) target_link_libraries(${PROJECT_NAME}-bytecode-test lib${PROJECT_NAME} gtest_main) add_test(NAME tyche_bytecode_test COMMAND ${PROJECT_NAME}-bytecode-test) diff --git a/doc/OPCODES b/doc/OPCODES index a84051c..4edbf82 100644 --- a/doc/OPCODES +++ b/doc/OPCODES @@ -83,9 +83,9 @@ The bytecode file is composed of the following sections: [0:3]: Magic [4]: VM format * [0x1] Index: pointers to each one of the sections, up to 8 - Each pointer: 4 bits + Each pointer: 4 bytes * [0x2] Constants: all constants (such as strings) used in the code - * Table of 4-bit constant indexes with pointer to constant + * Table of 4-byte constant indexes with pointer to constant * Raw constant data * [0x3] Functions: Pointer to functions within the code [0:3]: function pointer diff --git a/src/bytecode/bytearray.cc b/src/bytecode/bytearray.cc index e8fbbd9..6b06f1e 100644 --- a/src/bytecode/bytearray.cc +++ b/src/bytecode/bytearray.cc @@ -4,7 +4,7 @@ namespace tyche { -void ByteArray::add_byte(uint32_t addr, uint8_t byte) +void ByteArray::set_byte(uint32_t addr, uint8_t byte) { try { data_.at(addr) = byte; @@ -14,39 +14,39 @@ void ByteArray::add_byte(uint32_t addr, uint8_t byte) } } -void ByteArray::add_int(uint32_t addr, int32_t value) +void ByteArray::set_int(uint32_t addr, int32_t value) { uint32_t zz = ((uint32_t)(value << 1)) ^ ((uint32_t)(value >> 31)); while (zz > 0x7F) { - add_byte(addr++, (zz & 0x7F) | 0x80); + set_byte(addr++, (zz & 0x7F) | 0x80); zz >>= 7; } - add_byte(addr, zz & 0x7F); + set_byte(addr, zz & 0x7F); } -void ByteArray::add_uint32(uint32_t addr, uint32_t value) +void ByteArray::set_uint32(uint32_t addr, uint32_t value) { - add_byte(addr, (uint8_t)(value)); - add_byte(addr+1, (uint8_t)(value >> 8)); - add_byte(addr+2, (uint8_t)(value >> 16)); - add_byte(addr+3, (uint8_t)(value >> 24)); + set_byte(addr, (uint8_t) (value)); + set_byte(addr+1, (uint8_t) (value >> 8)); + set_byte(addr+2, (uint8_t) (value >> 16)); + set_byte(addr+3, (uint8_t) (value >> 24)); } -void ByteArray::add_float(uint32_t addr, float value) +void ByteArray::set_float(uint32_t addr, float value) { uint32_t bits; std::memcpy(&bits, &value, 4); - add_byte(addr, (uint8_t)(bits)); - add_byte(addr+1, (uint8_t)(bits >> 8)); - add_byte(addr+2, (uint8_t)(bits >> 16)); - add_byte(addr+3, (uint8_t)(bits >> 24)); + set_byte(addr, (uint8_t) (bits)); + set_byte(addr+1, (uint8_t) (bits >> 8)); + set_byte(addr+2, (uint8_t) (bits >> 16)); + set_byte(addr+3, (uint8_t) (bits >> 24)); } -void ByteArray::add_string(uint32_t addr, std::string const& str) +void ByteArray::set_string(uint32_t addr, std::string const& str) { for (uint8_t c: str) - add_byte(addr++, c); - add_byte(addr, 0); + set_byte(addr++, c); + set_byte(addr, 0); } uint8_t ByteArray::get_byte(uint32_t addr) const @@ -97,4 +97,9 @@ std::pair ByteArray::get_string(uint32_t addr) const return { data, data.size() + 1 }; } +void ByteArray::append_bytearray(ByteArray const& bytearray) +{ + data_.insert(data_.end(), bytearray.data().begin(), bytearray.data().end()); +} + } \ No newline at end of file diff --git a/src/bytecode/bytearray.hh b/src/bytecode/bytearray.hh index c189ba6..c0f97da 100644 --- a/src/bytecode/bytearray.hh +++ b/src/bytecode/bytearray.hh @@ -13,17 +13,18 @@ public: ByteArray() = default; explicit ByteArray(std::vector data) : data_(std::move(data)) {} - void add_byte(uint32_t addr, uint8_t byte); - void add_uint32(uint32_t addr, uint32_t value); - void add_int(uint32_t addr, int32_t value); - void add_float(uint32_t addr, float value); - void add_string(uint32_t addr, std::string const& str); + void set_byte(uint32_t addr, uint8_t byte); + void set_uint32(uint32_t addr, uint32_t value); + void set_int(uint32_t addr, int32_t value); + void set_float(uint32_t addr, float value); + void set_string(uint32_t addr, std::string const& str); - void append_byte(uint32_t addr, uint8_t byte) { add_byte(data_.size(), byte); } - void append_uint32(uint32_t addr, uint32_t value) { add_uint32(data_.size(), value); } - void append_int(uint32_t addr, int32_t value) { add_int(data_.size(), value); } - void append_float(uint32_t addr, float value) { add_float(data_.size(), value); } - void append_string(uint32_t addr, std::string const& str) { add_string(data_.size(), str); } + void append_byte(uint8_t byte) { set_byte(data_.size(), byte); } + void append_uint32(uint32_t value) { set_uint32(data_.size(), value); } + void append_int(int32_t value) { set_int(data_.size(), value); } + void append_float(float value) { set_float(data_.size(), value); } + void append_string(std::string const& str) { set_string(data_.size(), str); } + void append_bytearray(ByteArray const& bytearray); [[nodiscard]] uint8_t get_byte(uint32_t addr) const; [[nodiscard]] uint32_t get_uint32(uint32_t addr) const; @@ -32,6 +33,7 @@ public: [[nodiscard]] std::pair get_string(uint32_t addr) const; [[nodiscard]] std::vector const& data() const { return data_; } + [[nodiscard]] size_t size() const { return data_.size(); } private: std::vector data_; diff --git a/src/bytecode/bytecode.cc b/src/bytecode/bytecode.cc index 5069221..05548c5 100644 --- a/src/bytecode/bytecode.cc +++ b/src/bytecode/bytecode.cc @@ -1,23 +1,44 @@ #include "bytecode.hh" +#include "../common/overloaded.hh" namespace tyche { Bytecode::Bytecode(BytecodePrototype const& bp) { - // header - byte_array_.add_uint32(0, MAGIC); - byte_array_.add_byte(4, VERSION); - // constants - std::vector constant_indexes; - std::vector constant_array; + 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(); } - // constants table - // function table + + // + // build binary + // + + // header + byte_array_.set_uint32(0, MAGIC); + byte_array_.set_byte(4, VERSION); + + // index - other entries created later + byte_array_.set_uint32(HEADER_SZ, HEADER_SZ + INDEX_SZ); + + // constants + idx = HEADER_SZ + INDEX_SZ; + for (auto const& const_idx: constant_table) { + byte_array_.set_uint32(idx, const_idx); + idx += 4; + } + byte_array_.append_bytearray(constant_array); } uint32_t Bytecode::n_constants() const diff --git a/src/bytecode/bytecode.hh b/src/bytecode/bytecode.hh index 2095bba..4946946 100644 --- a/src/bytecode/bytecode.hh +++ b/src/bytecode/bytecode.hh @@ -31,6 +31,8 @@ private: ByteArray byte_array_; static constexpr uint8_t VERSION = 1; static constexpr uint32_t MAGIC = 0x74b3c138; + static constexpr uint32_t HEADER_SZ = 16, + INDEX_SZ = 8 * 4; }; } diff --git a/src/bytecode/tests.cc b/src/bytecode/tests.cc index 7d5ab87..60d1031 100644 --- a/src/bytecode/tests.cc +++ b/src/bytecode/tests.cc @@ -18,10 +18,10 @@ TEST(ByteArray, ByteArray) #define TESTX(a, ...) test([](ByteArray& ba) { a; }, std::vector({ __VA_ARGS__ })); - TESTX(ba.add_byte(1, 0xab), 0x00, 0xab) + TESTX(ba.set_byte(1, 0xab), 0x00, 0xab) ByteArray ba; - ba.add_byte(1, 0xab); ASSERT_EQ(ba.get_byte(1), 0xab); + ba.set_byte(1, 0xab); ASSERT_EQ(ba.get_byte(1), 0xab); ba.add_int(1, 12); ASSERT_EQ(ba.get_int(1), std::make_pair(12, 1)); ba.add_int(1, -12); ASSERT_EQ(ba.get_int(1), std::make_pair(-12, 1)); diff --git a/src/common/overloaded.hh b/src/common/overloaded.hh new file mode 100644 index 0000000..f0ad1a0 --- /dev/null +++ b/src/common/overloaded.hh @@ -0,0 +1,8 @@ +#ifndef TYCHE_OVERLOADED_HH +#define TYCHE_OVERLOADED_HH + +// used by std::visitor +template +struct overloaded : Ts... { using Ts::operator()...; }; + +#endif //TYCHE_OVERLOADED_HH