bytecode2 #2
@@ -72,7 +72,8 @@ target_compile_options(lib${PROJECT_NAME} PRIVATE ${warnings})
|
|||||||
# tests
|
# 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)
|
target_link_libraries(${PROJECT_NAME}-bytecode-test lib${PROJECT_NAME} gtest_main)
|
||||||
add_test(NAME tyche_bytecode_test COMMAND ${PROJECT_NAME}-bytecode-test)
|
add_test(NAME tyche_bytecode_test COMMAND ${PROJECT_NAME}-bytecode-test)
|
||||||
|
|
||||||
|
|||||||
@@ -83,9 +83,9 @@ The bytecode file is composed of the following sections:
|
|||||||
[0:3]: Magic
|
[0:3]: Magic
|
||||||
[4]: VM format
|
[4]: VM format
|
||||||
* [0x1] Index: pointers to each one of the sections, up to 8
|
* [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
|
* [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
|
* Raw constant data
|
||||||
* [0x3] Functions: Pointer to functions within the code
|
* [0x3] Functions: Pointer to functions within the code
|
||||||
[0:3]: function pointer
|
[0:3]: function pointer
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
namespace tyche {
|
namespace tyche {
|
||||||
|
|
||||||
void ByteArray::add_byte(uint32_t addr, uint8_t byte)
|
void ByteArray::set_byte(uint32_t addr, uint8_t byte)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
data_.at(addr) = byte;
|
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));
|
uint32_t zz = ((uint32_t)(value << 1)) ^ ((uint32_t)(value >> 31));
|
||||||
while (zz > 0x7F) {
|
while (zz > 0x7F) {
|
||||||
add_byte(addr++, (zz & 0x7F) | 0x80);
|
set_byte(addr++, (zz & 0x7F) | 0x80);
|
||||||
zz >>= 7;
|
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));
|
set_byte(addr, (uint8_t) (value));
|
||||||
add_byte(addr+1, (uint8_t)(value >> 8));
|
set_byte(addr+1, (uint8_t) (value >> 8));
|
||||||
add_byte(addr+2, (uint8_t)(value >> 16));
|
set_byte(addr+2, (uint8_t) (value >> 16));
|
||||||
add_byte(addr+3, (uint8_t)(value >> 24));
|
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;
|
uint32_t bits;
|
||||||
std::memcpy(&bits, &value, 4);
|
std::memcpy(&bits, &value, 4);
|
||||||
add_byte(addr, (uint8_t)(bits));
|
set_byte(addr, (uint8_t) (bits));
|
||||||
add_byte(addr+1, (uint8_t)(bits >> 8));
|
set_byte(addr+1, (uint8_t) (bits >> 8));
|
||||||
add_byte(addr+2, (uint8_t)(bits >> 16));
|
set_byte(addr+2, (uint8_t) (bits >> 16));
|
||||||
add_byte(addr+3, (uint8_t)(bits >> 24));
|
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)
|
for (uint8_t c: str)
|
||||||
add_byte(addr++, c);
|
set_byte(addr++, c);
|
||||||
add_byte(addr, 0);
|
set_byte(addr, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t ByteArray::get_byte(uint32_t addr) const
|
uint8_t ByteArray::get_byte(uint32_t addr) const
|
||||||
@@ -97,4 +97,9 @@ std::pair<std::string, size_t> ByteArray::get_string(uint32_t addr) const
|
|||||||
return { data, data.size() + 1 };
|
return { data, data.size() + 1 };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ByteArray::append_bytearray(ByteArray const& bytearray)
|
||||||
|
{
|
||||||
|
data_.insert(data_.end(), bytearray.data().begin(), bytearray.data().end());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -13,17 +13,18 @@ public:
|
|||||||
ByteArray() = default;
|
ByteArray() = default;
|
||||||
explicit ByteArray(std::vector<uint8_t> data) : data_(std::move(data)) {}
|
explicit ByteArray(std::vector<uint8_t> data) : data_(std::move(data)) {}
|
||||||
|
|
||||||
void add_byte(uint32_t addr, uint8_t byte);
|
void set_byte(uint32_t addr, uint8_t byte);
|
||||||
void add_uint32(uint32_t addr, uint32_t value);
|
void set_uint32(uint32_t addr, uint32_t value);
|
||||||
void add_int(uint32_t addr, int32_t value);
|
void set_int(uint32_t addr, int32_t value);
|
||||||
void add_float(uint32_t addr, float value);
|
void set_float(uint32_t addr, float value);
|
||||||
void add_string(uint32_t addr, std::string const& str);
|
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_byte(uint8_t byte) { set_byte(data_.size(), byte); }
|
||||||
void append_uint32(uint32_t addr, uint32_t value) { add_uint32(data_.size(), value); }
|
void append_uint32(uint32_t value) { set_uint32(data_.size(), value); }
|
||||||
void append_int(uint32_t addr, int32_t value) { add_int(data_.size(), value); }
|
void append_int(int32_t value) { set_int(data_.size(), value); }
|
||||||
void append_float(uint32_t addr, float value) { add_float(data_.size(), value); }
|
void append_float(float value) { set_float(data_.size(), value); }
|
||||||
void append_string(uint32_t addr, std::string const& str) { add_string(data_.size(), str); }
|
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]] uint8_t get_byte(uint32_t addr) const;
|
||||||
[[nodiscard]] uint32_t get_uint32(uint32_t addr) const;
|
[[nodiscard]] uint32_t get_uint32(uint32_t addr) const;
|
||||||
@@ -32,6 +33,7 @@ public:
|
|||||||
[[nodiscard]] std::pair<std::string, size_t> get_string(uint32_t addr) const;
|
[[nodiscard]] std::pair<std::string, size_t> get_string(uint32_t addr) const;
|
||||||
|
|
||||||
[[nodiscard]] std::vector<uint8_t> const& data() const { return data_; }
|
[[nodiscard]] std::vector<uint8_t> const& data() const { return data_; }
|
||||||
|
[[nodiscard]] size_t size() const { return data_.size(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<uint8_t> data_;
|
std::vector<uint8_t> data_;
|
||||||
|
|||||||
@@ -1,23 +1,44 @@
|
|||||||
#include "bytecode.hh"
|
#include "bytecode.hh"
|
||||||
|
#include "../common/overloaded.hh"
|
||||||
|
|
||||||
namespace tyche {
|
namespace tyche {
|
||||||
|
|
||||||
Bytecode::Bytecode(BytecodePrototype const& bp)
|
Bytecode::Bytecode(BytecodePrototype const& bp)
|
||||||
{
|
{
|
||||||
// header
|
|
||||||
byte_array_.add_uint32(0, MAGIC);
|
|
||||||
byte_array_.add_byte(4, VERSION);
|
|
||||||
|
|
||||||
// constants
|
// constants
|
||||||
std::vector<uint32_t> constant_indexes;
|
std::vector<uint32_t> constant_table;
|
||||||
std::vector<uint8_t> constant_array;
|
ByteArray constant_array;
|
||||||
|
uint32_t idx = 0;
|
||||||
for (auto const& constant: bp.constants) {
|
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
|
// 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
|
uint32_t Bytecode::n_constants() const
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ private:
|
|||||||
ByteArray byte_array_;
|
ByteArray byte_array_;
|
||||||
static constexpr uint8_t VERSION = 1;
|
static constexpr uint8_t VERSION = 1;
|
||||||
static constexpr uint32_t MAGIC = 0x74b3c138;
|
static constexpr uint32_t MAGIC = 0x74b3c138;
|
||||||
|
static constexpr uint32_t HEADER_SZ = 16,
|
||||||
|
INDEX_SZ = 8 * 4;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,10 +18,10 @@ TEST(ByteArray, ByteArray)
|
|||||||
|
|
||||||
#define TESTX(a, ...) test([](ByteArray& ba) { a; }, std::vector<uint8_t>({ __VA_ARGS__ }));
|
#define TESTX(a, ...) test([](ByteArray& ba) { a; }, std::vector<uint8_t>({ __VA_ARGS__ }));
|
||||||
|
|
||||||
TESTX(ba.add_byte(1, 0xab), 0x00, 0xab)
|
TESTX(ba.set_byte(1, 0xab), 0x00, 0xab)
|
||||||
|
|
||||||
ByteArray ba;
|
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));
|
||||||
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));
|
||||||
|
|||||||
8
src/common/overloaded.hh
Normal file
8
src/common/overloaded.hh
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#ifndef TYCHE_OVERLOADED_HH
|
||||||
|
#define TYCHE_OVERLOADED_HH
|
||||||
|
|
||||||
|
// used by std::visitor
|
||||||
|
template<class... Ts>
|
||||||
|
struct overloaded : Ts... { using Ts::operator()...; };
|
||||||
|
|
||||||
|
#endif //TYCHE_OVERLOADED_HH
|
||||||
Reference in New Issue
Block a user