.
This commit is contained in:
7
.idea/ctestState.xml
generated
7
.idea/ctestState.xml
generated
@@ -2,9 +2,10 @@
|
||||
<project version="4">
|
||||
<component name="CidrCTestProjectState">
|
||||
<ctestState>
|
||||
<lineNumber testId="path:CMakeLists.txt test:tyche_as_test" value="108" />
|
||||
<lineNumber testId="path:CMakeLists.txt test:tyche_bytecode_test" value="100" />
|
||||
<lineNumber testId="path:CMakeLists.txt test:tyche_vm_test" value="104" />
|
||||
<lineNumber testId="path:CMakeLists.txt test:tyche_as_test" value="116" />
|
||||
<lineNumber testId="path:CMakeLists.txt test:tyche_bytearray_test" value="102" />
|
||||
<lineNumber testId="path:CMakeLists.txt test:tyche_bytecode_test" value="106" />
|
||||
<lineNumber testId="path:CMakeLists.txt test:tyche_vm_test" value="110" />
|
||||
</ctestState>
|
||||
</component>
|
||||
</project>
|
||||
@@ -60,32 +60,34 @@ FetchContent_MakeAvailable(googletest)
|
||||
|
||||
add_library(lib${PROJECT_NAME} SHARED
|
||||
src/common/overloaded.hh
|
||||
src/common/bytearray.hh
|
||||
src/common/bytearray.cc
|
||||
src/bytecode/bytecode.cc
|
||||
src/bytecode/bytecode.hh
|
||||
src/bytecode/bytecodeprototype.hh
|
||||
src/bytecode/constant.hh
|
||||
src/bytecode/bc_exceptions.hh
|
||||
src/assembler/lexer.cc
|
||||
src/assembler/lexer.hh
|
||||
src/assembler/assembler.cc
|
||||
src/assembler/assembler.hh
|
||||
src/assembler/as_exceptions.hh
|
||||
src/instructions/instruction.hh
|
||||
src/instructions/instruction.cc
|
||||
src/vm/code.cc
|
||||
src/vm/code.hh
|
||||
src/vm/value.cc
|
||||
src/vm/value.hh
|
||||
src/vm/stack.cc
|
||||
src/vm/stack.hh
|
||||
src/vm/vm_exceptions.hh
|
||||
src/vm/vm.cc
|
||||
src/vm/vm.hh
|
||||
src/vm/expr.cc
|
||||
src/vm/expr.hh
|
||||
src/vm/location.hh
|
||||
src/bytearray/bytearray.hh
|
||||
src/bytearray/bytearray.cc
|
||||
src/bytearray/bytearraybuilder.hh
|
||||
src/bytearray/bytearraybuilder.cc
|
||||
#src/bytecode/bytecode.cc
|
||||
#src/bytecode/bytecode.hh
|
||||
#src/bytecode/bytecodeprototype.hh
|
||||
#src/bytecode/constant.hh
|
||||
#src/bytecode/bc_exceptions.hh
|
||||
#src/assembler/lexer.cc
|
||||
#src/assembler/lexer.hh
|
||||
#src/assembler/assembler.cc
|
||||
#src/assembler/assembler.hh
|
||||
#src/assembler/as_exceptions.hh
|
||||
#src/instructions/instruction.hh
|
||||
#src/instructions/instruction.cc
|
||||
#src/vm/code.cc
|
||||
#src/vm/code.hh
|
||||
#src/vm/value.cc
|
||||
#src/vm/value.hh
|
||||
#src/vm/stack.cc
|
||||
#src/vm/stack.hh
|
||||
#src/vm/vm_exceptions.hh
|
||||
#src/vm/vm.cc
|
||||
#src/vm/vm.hh
|
||||
#src/vm/expr.cc
|
||||
#src/vm/expr.hh
|
||||
#src/vm/location.hh
|
||||
)
|
||||
|
||||
target_compile_options(lib${PROJECT_NAME} PRIVATE ${warnings})
|
||||
@@ -96,6 +98,10 @@ target_compile_options(lib${PROJECT_NAME} PRIVATE ${warnings})
|
||||
|
||||
enable_testing()
|
||||
|
||||
add_executable(${PROJECT_NAME}-bytearray-test src/bytearray/tests.cc)
|
||||
target_link_libraries(${PROJECT_NAME}-bytearray-test lib${PROJECT_NAME} gtest_main)
|
||||
add_test(NAME tyche_bytearray_test COMMAND ${PROJECT_NAME}-bytearray-test)
|
||||
|
||||
add_executable(${PROJECT_NAME}-bytecode-test src/bytecode/tests.cc)
|
||||
target_link_libraries(${PROJECT_NAME}-bytecode-test lib${PROJECT_NAME} gtest_main)
|
||||
add_test(NAME tyche_bytecode_test COMMAND ${PROJECT_NAME}-bytecode-test)
|
||||
@@ -104,7 +110,9 @@ add_executable(${PROJECT_NAME}-vm-test src/vm/tests.cc)
|
||||
target_link_libraries(${PROJECT_NAME}-vm-test lib${PROJECT_NAME} gtest_main)
|
||||
add_test(NAME tyche_vm_test COMMAND ${PROJECT_NAME}-vm-test)
|
||||
|
||||
add_executable(${PROJECT_NAME}-as-test src/assembler/tests.cc)
|
||||
add_executable(${PROJECT_NAME}-as-test src/assembler/tests.cc
|
||||
src/bytearray/bytearraybuilder.cc
|
||||
src/bytearray/bytearraybuilder.hh)
|
||||
target_link_libraries(${PROJECT_NAME}-as-test lib${PROJECT_NAME} gtest_main)
|
||||
add_test(NAME tyche_as_test COMMAND ${PROJECT_NAME}-as-test)
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ using namespace std::string_literals;
|
||||
|
||||
namespace tyche::as {
|
||||
|
||||
ByteArray Assembler::assemble()
|
||||
StaticByteArray Assembler::assemble()
|
||||
{
|
||||
bc::BytecodePrototype bp;
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include <string>
|
||||
|
||||
#include "lexer.hh"
|
||||
#include "../common/bytearray.hh"
|
||||
#include "../bytearray/bytearray.hh"
|
||||
#include "../bytecode/bytecodeprototype.hh"
|
||||
|
||||
namespace tyche::as {
|
||||
@@ -14,7 +14,7 @@ class Assembler {
|
||||
public:
|
||||
explicit Assembler(std::string source) : lexer_(std::move(source) + "\n") {}
|
||||
|
||||
[[nodiscard]] ByteArray assemble();
|
||||
[[nodiscard]] StaticByteArray assemble();
|
||||
|
||||
private:
|
||||
Lexer lexer_;
|
||||
|
||||
@@ -47,7 +47,7 @@ TEST(Assember, Assembler)
|
||||
bp.functions.at(1).code.append_byte((uint8_t) Instruction::PushInt16);
|
||||
bp.functions.at(1).code.append_int16(5000);
|
||||
bp.functions.at(1).code.append_byte((uint8_t) Instruction::Return);
|
||||
ByteArray expected = Bytecode::generate(bp);
|
||||
StaticByteArray expected = Bytecode::generate(bp);
|
||||
|
||||
std::string src = R"(
|
||||
.const
|
||||
@@ -64,7 +64,7 @@ TEST(Assember, Assembler)
|
||||
ret
|
||||
)";
|
||||
|
||||
ByteArray actual = Assembler(src).assemble();
|
||||
StaticByteArray actual = Assembler(src).assemble();
|
||||
ASSERT_EQ(expected, actual);
|
||||
}
|
||||
|
||||
|
||||
81
src/bytearray/bytearray.cc
Normal file
81
src/bytearray/bytearray.cc
Normal file
@@ -0,0 +1,81 @@
|
||||
#include "bytearray.hh"
|
||||
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
|
||||
namespace tyche {
|
||||
|
||||
uint8_t StaticByteArray::get_byte(uint32_t addr) const
|
||||
{
|
||||
return data_.at(addr);
|
||||
}
|
||||
|
||||
uint16_t StaticByteArray::get_uint16(uint32_t addr) const
|
||||
{
|
||||
return (uint32_t) get_byte(addr)
|
||||
| (uint32_t) get_byte(addr+1) << 8;
|
||||
}
|
||||
|
||||
uint32_t StaticByteArray::get_uint32(uint32_t addr) const
|
||||
{
|
||||
return (uint32_t) get_byte(addr)
|
||||
| (uint32_t) get_byte(addr+1) << 8
|
||||
| (uint32_t) get_byte(addr+2) << 16
|
||||
| (uint32_t) get_byte(addr+3) << 24;
|
||||
}
|
||||
|
||||
int8_t StaticByteArray::get_int8(uint32_t addr) const
|
||||
{
|
||||
return std::bit_cast<int8_t>(get_byte(addr));
|
||||
}
|
||||
|
||||
int16_t StaticByteArray::get_int16(uint32_t addr) const
|
||||
{
|
||||
return (uint16_t) get_byte(addr)
|
||||
| (uint16_t) get_byte(addr+1) << 8;
|
||||
}
|
||||
|
||||
int32_t StaticByteArray::get_int32(uint32_t addr) const
|
||||
{
|
||||
return std::bit_cast<int32_t>((uint32_t) get_byte(addr)
|
||||
| (uint32_t) get_byte(addr+1) << 8
|
||||
| (uint32_t) get_byte(addr+2) << 16
|
||||
| (uint32_t) get_byte(addr+3) << 24);
|
||||
}
|
||||
|
||||
float StaticByteArray::get_float(uint32_t addr) const
|
||||
{
|
||||
uint32_t bits = (uint32_t) get_byte(addr)
|
||||
| (uint32_t) get_byte(addr+1) << 8
|
||||
| (uint32_t) get_byte(addr+2) << 16
|
||||
| (uint32_t) get_byte(addr+3) << 24;
|
||||
float value;
|
||||
std::memcpy(&value, &bits, 4);
|
||||
return value;
|
||||
}
|
||||
|
||||
std::pair<const char*, size_t> StaticByteArray::get_string_ptr(uint32_t addr) const
|
||||
{
|
||||
return { (const char *) &data_.at(addr), strlen((const char *) &data_.at(addr)) + 1 };
|
||||
}
|
||||
|
||||
std::string StaticByteArray::hexdump() const
|
||||
{
|
||||
auto to_hex = [](uint32_t value, size_t n_chars) -> std::string {
|
||||
char buf[15];
|
||||
snprintf(buf, sizeof buf, "%0*X", (int) n_chars, value);
|
||||
return { buf };
|
||||
};
|
||||
|
||||
std::string out;
|
||||
for (size_t i = 0; i < data_.size(); ++i) {
|
||||
if (i % 16 == 0)
|
||||
out += to_hex(i, 4) + " | ";
|
||||
out += to_hex(data_.at(i), 2) + " ";
|
||||
if (i % 16 == 15)
|
||||
out += "\n";
|
||||
}
|
||||
return out + "\n";
|
||||
}
|
||||
|
||||
}
|
||||
44
src/bytearray/bytearray.hh
Normal file
44
src/bytearray/bytearray.hh
Normal file
@@ -0,0 +1,44 @@
|
||||
#ifndef TYCHE_BYTEARRAY_HH
|
||||
#define TYCHE_BYTEARRAY_HH
|
||||
|
||||
#include <cstdint>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace tyche {
|
||||
|
||||
class StaticByteArray {
|
||||
public:
|
||||
explicit StaticByteArray(std::vector<uint8_t> const& data) : data_(data) {}
|
||||
|
||||
explicit StaticByteArray(StaticByteArray const& ba) : data_(ba.data()) {}
|
||||
|
||||
// not assignable or moveable
|
||||
StaticByteArray(StaticByteArray&&) = delete;
|
||||
StaticByteArray& operator=(StaticByteArray const&) = delete;
|
||||
StaticByteArray& operator=(StaticByteArray&&) = delete;
|
||||
|
||||
[[nodiscard]] uint8_t get_byte(uint32_t addr) const;
|
||||
[[nodiscard]] uint16_t get_uint16(uint32_t addr) const;
|
||||
[[nodiscard]] uint32_t get_uint32(uint32_t addr) const;
|
||||
[[nodiscard]] int8_t get_int8(uint32_t addr) const;
|
||||
[[nodiscard]] int16_t get_int16(uint32_t addr) const;
|
||||
[[nodiscard]] int32_t get_int32(uint32_t addr) const;
|
||||
[[nodiscard]] float get_float(uint32_t addr) const;
|
||||
[[nodiscard]] std::pair<const char*, size_t> get_string_ptr(uint32_t addr) const;
|
||||
|
||||
[[nodiscard]] std::vector<uint8_t> const& data() const { return data_; }
|
||||
[[nodiscard]] size_t size() const { return data_.size(); }
|
||||
|
||||
[[nodiscard]] std::string hexdump() const;
|
||||
|
||||
friend bool operator==(StaticByteArray const& lhs, StaticByteArray const& rhs) { return lhs.data_ == rhs.data_; }
|
||||
|
||||
private:
|
||||
const std::vector<uint8_t> data_ {};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //TYCHE_BYTEARRAY_HH
|
||||
88
src/bytearray/bytearraybuilder.cc
Normal file
88
src/bytearray/bytearraybuilder.cc
Normal file
@@ -0,0 +1,88 @@
|
||||
#include "bytearraybuilder.hh"
|
||||
|
||||
namespace tyche {
|
||||
|
||||
ByteArrayBuilder& ByteArrayBuilder::set_byte(uint32_t addr, uint8_t byte)
|
||||
{
|
||||
if (data_.size() < (addr + 1))
|
||||
data_.resize(addr + 1, 0);
|
||||
data_.at(addr) = byte;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ByteArrayBuilder& ByteArrayBuilder::set_int8(uint32_t addr, int8_t value)
|
||||
{
|
||||
set_byte(addr, (uint8_t) value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ByteArrayBuilder& ByteArrayBuilder::set_int16(uint32_t addr, int16_t value)
|
||||
{
|
||||
set_byte(addr, (uint8_t) (value));
|
||||
set_byte(addr+1, (uint8_t) (value >> 8));
|
||||
return *this;
|
||||
}
|
||||
|
||||
ByteArrayBuilder& ByteArrayBuilder::set_int32(uint32_t addr, int32_t value)
|
||||
{
|
||||
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));
|
||||
return *this;
|
||||
}
|
||||
|
||||
ByteArrayBuilder& ByteArrayBuilder::set_uint16(uint32_t addr, uint16_t value)
|
||||
{
|
||||
set_byte(addr, (uint8_t) (value));
|
||||
set_byte(addr+1, (uint8_t) (value >> 8));
|
||||
return *this;
|
||||
}
|
||||
|
||||
ByteArrayBuilder& ByteArrayBuilder::set_uint32(uint32_t addr, uint32_t value)
|
||||
{
|
||||
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));
|
||||
return *this;
|
||||
}
|
||||
|
||||
ByteArrayBuilder& ByteArrayBuilder::set_float(uint32_t addr, float value)
|
||||
{
|
||||
uint32_t bits;
|
||||
std::memcpy(&bits, &value, 4);
|
||||
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));
|
||||
return *this;
|
||||
}
|
||||
|
||||
ByteArrayBuilder& ByteArrayBuilder::set_string(uint32_t addr, std::string const& str)
|
||||
{
|
||||
for (uint8_t c: str)
|
||||
set_byte(addr++, c);
|
||||
set_byte(addr, 0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ByteArrayBuilder& ByteArrayBuilder::set_bytearray(uint32_t addr, ByteArrayBuilder const& bytearray)
|
||||
{
|
||||
for (uint8_t byte: bytearray.data_)
|
||||
set_byte(addr++, byte);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ByteArrayBuilder& ByteArrayBuilder::append_bytearray(ByteArrayBuilder const& bytearray)
|
||||
{
|
||||
data_.insert(data_.end(), bytearray.data_.begin(), bytearray.data_.end());
|
||||
return *this;
|
||||
}
|
||||
|
||||
StaticByteArray ByteArrayBuilder::build() const
|
||||
{
|
||||
return StaticByteArray(data_);
|
||||
}
|
||||
|
||||
}
|
||||
45
src/bytearray/bytearraybuilder.hh
Normal file
45
src/bytearray/bytearraybuilder.hh
Normal file
@@ -0,0 +1,45 @@
|
||||
#ifndef TYCHE_BYTEARRAYBUILDER_HH
|
||||
#define TYCHE_BYTEARRAYBUILDER_HH
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "bytearray.hh"
|
||||
|
||||
namespace tyche {
|
||||
|
||||
class ByteArrayBuilder {
|
||||
public:
|
||||
ByteArrayBuilder& set_byte(uint32_t addr, uint8_t byte);
|
||||
ByteArrayBuilder& set_uint16(uint32_t addr, uint16_t value);
|
||||
ByteArrayBuilder& set_uint32(uint32_t addr, uint32_t value);
|
||||
ByteArrayBuilder& set_int8(uint32_t addr, int8_t value);
|
||||
ByteArrayBuilder& set_int16(uint32_t addr, int16_t value);
|
||||
ByteArrayBuilder& set_int32(uint32_t addr, int32_t value);
|
||||
ByteArrayBuilder& set_float(uint32_t addr, float value);
|
||||
ByteArrayBuilder& set_string(uint32_t addr, std::string const& str);
|
||||
ByteArrayBuilder& set_bytearray(uint32_t addr, ByteArrayBuilder const& bytearray);
|
||||
|
||||
ByteArrayBuilder& append_byte(uint8_t byte) { set_byte(data_.size(), byte); return *this; }
|
||||
ByteArrayBuilder& append_uint16(uint16_t value) { set_uint16(data_.size(), value); return *this; }
|
||||
ByteArrayBuilder& append_uint32(uint32_t value) { set_uint32(data_.size(), value); return *this; }
|
||||
ByteArrayBuilder& append_int8(int8_t value) { set_int8(data_.size(), value); return *this; }
|
||||
ByteArrayBuilder& append_int16(int16_t value) { set_int16(data_.size(), value); return *this; }
|
||||
ByteArrayBuilder& append_int32(int32_t value) { set_int32(data_.size(), value); return *this; }
|
||||
ByteArrayBuilder& append_float(float value) { set_float(data_.size(), value); return *this; }
|
||||
ByteArrayBuilder& append_string(std::string const& str) { set_string(data_.size(), str); return *this; }
|
||||
ByteArrayBuilder& append_bytearray(ByteArrayBuilder const& bytearray);
|
||||
|
||||
[[nodiscard]] std::vector<uint8_t> const& data() const { return data_; }
|
||||
[[nodiscard]] size_t size() const { return data_.size(); }
|
||||
|
||||
[[nodiscard]] StaticByteArray build() const;
|
||||
|
||||
private:
|
||||
std::vector<uint8_t> data_ {};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //TYCHE_BYTEARRAYBUILDER_HH
|
||||
51
src/bytearray/tests.cc
Normal file
51
src/bytearray/tests.cc
Normal file
@@ -0,0 +1,51 @@
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
|
||||
#include "bytearray.hh"
|
||||
#include "bytearraybuilder.hh"
|
||||
|
||||
using namespace tyche;
|
||||
|
||||
TEST(StaticByteArray, StaticByteArray)
|
||||
{
|
||||
auto test = [](std::function<void(ByteArrayBuilder&)> const& f, std::vector<uint8_t> const& expected) {
|
||||
ByteArrayBuilder ba;
|
||||
f(ba);
|
||||
ASSERT_EQ(ba.data().size(), expected.size());
|
||||
ASSERT_EQ(std::memcmp(ba.data().data(), expected.data(), ba.data().size()), 0);
|
||||
};
|
||||
|
||||
#define TESTX(a, ...) test([](ByteArrayBuilder& ba) { a; }, std::vector<uint8_t>({ __VA_ARGS__ }));
|
||||
|
||||
TESTX(ba.set_byte(1, 0xab), 0x00, 0xab)
|
||||
|
||||
ByteArrayBuilder ba;
|
||||
{ auto b = ba.set_byte(1, 0xab).build(); ASSERT_EQ(b.get_byte(1), 0xab); }
|
||||
|
||||
{ auto b = ba.set_int8(1, 12).build(); ASSERT_EQ(b.get_int8(1), 12); }
|
||||
{ auto b = ba.set_int8(1, -12).build(); ASSERT_EQ(b.get_int8(1), -12); }
|
||||
{ auto b = ba.set_int16(1, 5000).build(); ASSERT_EQ(b.get_int16(1), 5000); }
|
||||
{ auto b = ba.set_int32(1, 5000300).build(); ASSERT_EQ(b.get_int32(1), 5000300); }
|
||||
{ auto b = ba.set_int32(1, -5000300).build(); ASSERT_EQ(b.get_int32(1), -5000300); }
|
||||
|
||||
{ auto b = ba.set_float(1, 3.14).build(); ASSERT_FLOAT_EQ(b.get_float(1), 3.14); }
|
||||
{ auto b = ba.set_float(1, -3.14).build(); ASSERT_FLOAT_EQ(b.get_float(1), -3.14); }
|
||||
{ auto b = ba.set_float(1, -5000300.1324).build(); ASSERT_FLOAT_EQ(b.get_float(1), -5000300.1324); }
|
||||
|
||||
{
|
||||
auto b = ba.set_string(1, "Hello world!").build();
|
||||
auto str = b.get_string_ptr(1);
|
||||
EXPECT_STREQ(str.first, "Hello world!");
|
||||
ASSERT_EQ(str.second, 13);
|
||||
}
|
||||
|
||||
#undef TESTX
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
@@ -5,29 +5,29 @@
|
||||
|
||||
namespace tyche::bc {
|
||||
|
||||
Bytecode::Bytecode(ByteArray ba)
|
||||
: byte_array_(std::move(ba))
|
||||
Bytecode::Bytecode(StaticByteArray const* ba)
|
||||
: byte_array_(ba)
|
||||
{
|
||||
// check file size
|
||||
if (byte_array_.size() < (TOC_START + TOC_SZ))
|
||||
if (byte_array_->size() < (TOC_START + TOC_SZ))
|
||||
throw BytecodeParsingError("Invalid bytecode format (file too short)");
|
||||
|
||||
// check magic number and version
|
||||
if (byte_array_.get_uint32(0) != MAGIC_NUMBER)
|
||||
if (byte_array_->get_uint32(0) != MAGIC_NUMBER)
|
||||
throw BytecodeParsingError("Invalid bytecode format (magic number not matching)");
|
||||
if (byte_array_.get_uint32(4) != BYTECODE_VERSION)
|
||||
if (byte_array_->get_uint32(4) != BYTECODE_VERSION)
|
||||
throw BytecodeParsingError("Unexpected bytecode format version");
|
||||
|
||||
// load cache
|
||||
cache_.constants_idx_addr = byte_array_.get_uint32(TOC_START);
|
||||
cache_.n_constants = byte_array_.get_uint16(TOC_START + 4);
|
||||
cache_.functions_idx_addr = byte_array_.get_uint32(TOC_START + (1 * TOC_RECORD_SZ));
|
||||
cache_.n_functions = byte_array_.get_uint16(TOC_START + (1 * TOC_RECORD_SZ) + 4);
|
||||
cache_.constants_start_addr = byte_array_.get_uint32(TOC_START + (2 * TOC_RECORD_SZ));
|
||||
uint32_t code_start = byte_array_.get_uint32(TOC_START + (3 * TOC_RECORD_SZ));
|
||||
cache_.constants_idx_addr = byte_array_->get_uint32(TOC_START);
|
||||
cache_.n_constants = byte_array_->get_uint16(TOC_START + 4);
|
||||
cache_.functions_idx_addr = byte_array_->get_uint32(TOC_START + (1 * TOC_RECORD_SZ));
|
||||
cache_.n_functions = byte_array_->get_uint16(TOC_START + (1 * TOC_RECORD_SZ) + 4);
|
||||
cache_.constants_start_addr = byte_array_->get_uint32(TOC_START + (2 * TOC_RECORD_SZ));
|
||||
uint32_t code_start = byte_array_->get_uint32(TOC_START + (3 * TOC_RECORD_SZ));
|
||||
for (uint32_t i = 0; i < cache_.n_functions; ++i) {
|
||||
cache_.function_addr.emplace_back(code_start + byte_array_.get_uint32(cache_.functions_idx_addr + (i * FUNCTION_RECORD_SZ)));
|
||||
cache_.function_sz.emplace_back(byte_array_.get_uint32(cache_.functions_idx_addr + (i * FUNCTION_RECORD_SZ) + 8));
|
||||
cache_.function_addr.emplace_back(code_start + byte_array_->get_uint32(cache_.functions_idx_addr + (i * FUNCTION_RECORD_SZ)));
|
||||
cache_.function_sz.emplace_back(byte_array_->get_uint32(cache_.functions_idx_addr + (i * FUNCTION_RECORD_SZ) + 8));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,12 +43,12 @@ uint32_t Bytecode::n_functions() const
|
||||
|
||||
ConstantValue Bytecode::get_constant(uint32_t idx) const
|
||||
{
|
||||
uint32_t constant_idx = byte_array_.get_uint32(cache_.constants_idx_addr + (idx * CONST_RECORD_SZ));
|
||||
switch ((ConstantType) byte_array_.get_byte(cache_.constants_start_addr + constant_idx)) {
|
||||
uint32_t constant_idx = byte_array_->get_uint32(cache_.constants_idx_addr + (idx * CONST_RECORD_SZ));
|
||||
switch ((ConstantType) byte_array_->get_byte(cache_.constants_start_addr + constant_idx)) {
|
||||
case CONST_TYPE_FLOAT:
|
||||
return byte_array_.get_float(cache_.constants_start_addr + constant_idx + 1);
|
||||
return byte_array_->get_float(cache_.constants_start_addr + constant_idx + 1);
|
||||
case CONST_TYPE_STRING:
|
||||
return byte_array_.get_string_ptr(cache_.constants_start_addr + constant_idx + 1).first;
|
||||
return byte_array_->get_string_ptr(cache_.constants_start_addr + constant_idx + 1).first;
|
||||
default:
|
||||
throw BytecodeParsingError("Invalid bytecode format (invalid constant type)");
|
||||
}
|
||||
@@ -58,8 +58,8 @@ Bytecode::FunctionDef Bytecode::get_function_def(uint32_t function_id) const
|
||||
{
|
||||
uint32_t idx = cache_.functions_idx_addr + (function_id * FUNCTION_RECORD_SZ);
|
||||
return {
|
||||
.n_params = byte_array_.get_uint16(idx + 4),
|
||||
.locals = byte_array_.get_uint16(idx + 6),
|
||||
.n_params = byte_array_->get_uint16(idx + 4),
|
||||
.locals = byte_array_->get_uint16(idx + 6),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -70,34 +70,34 @@ uint32_t Bytecode::get_function_sz(uint32_t function_id) const
|
||||
|
||||
uint8_t Bytecode::get_code_byte(uint32_t function_id, uint32_t idx) const
|
||||
{
|
||||
return byte_array_.get_byte(cache_.function_addr.at(function_id) + idx);
|
||||
return byte_array_->get_byte(cache_.function_addr.at(function_id) + idx);
|
||||
}
|
||||
|
||||
int8_t Bytecode::get_code_int8(uint32_t function_id, uint32_t idx) const
|
||||
{
|
||||
return byte_array_.get_int8(cache_.function_addr.at(function_id) + idx);
|
||||
return byte_array_->get_int8(cache_.function_addr.at(function_id) + idx);
|
||||
}
|
||||
|
||||
int16_t Bytecode::get_code_int16(uint32_t function_id, uint32_t idx) const
|
||||
{
|
||||
return byte_array_.get_int16(cache_.function_addr.at(function_id) + idx);
|
||||
return byte_array_->get_int16(cache_.function_addr.at(function_id) + idx);
|
||||
}
|
||||
|
||||
int32_t Bytecode::get_code_int32(uint32_t function_id, uint32_t idx) const
|
||||
{
|
||||
return byte_array_.get_int32(cache_.function_addr.at(function_id) + idx);
|
||||
return byte_array_->get_int32(cache_.function_addr.at(function_id) + idx);
|
||||
}
|
||||
|
||||
ByteArray Bytecode::generate(BytecodePrototype const& bp)
|
||||
StaticByteArray Bytecode::generate(BytecodePrototype const& bp)
|
||||
{
|
||||
// header section
|
||||
ByteArray header;
|
||||
ByteArrayBuilder header;
|
||||
header.set_uint32(0, MAGIC_NUMBER);
|
||||
header.set_byte(4, BYTECODE_VERSION);
|
||||
|
||||
// constants
|
||||
ByteArray constant_indexes;
|
||||
ByteArray raw_constants;
|
||||
ByteArrayBuilder constant_indexes;
|
||||
ByteArrayBuilder raw_constants;
|
||||
|
||||
uint32_t idx = 0;
|
||||
for (auto const& constant: bp.constants) {
|
||||
@@ -116,8 +116,8 @@ ByteArray Bytecode::generate(BytecodePrototype const& bp)
|
||||
}
|
||||
|
||||
// functions
|
||||
ByteArray functions_indexes;
|
||||
ByteArray raw_code;
|
||||
ByteArrayBuilder functions_indexes;
|
||||
ByteArrayBuilder raw_code;
|
||||
|
||||
uint32_t idx_idx = 0, code_idx = 0;
|
||||
for (auto const& f: bp.functions) {
|
||||
@@ -135,7 +135,7 @@ ByteArray Bytecode::generate(BytecodePrototype const& bp)
|
||||
uint32_t raw_constant_start = function_idx_start + functions_indexes.size();
|
||||
uint32_t raw_code_start = raw_constant_start + raw_constants.size();
|
||||
|
||||
ByteArray toc;
|
||||
ByteArrayBuilder toc;
|
||||
if (!bp.constants.empty()) {
|
||||
toc.set_uint32(SEC_CONST_IDX * TOC_RECORD_SZ, CONST_IDX_START);
|
||||
toc.set_uint32(SEC_CONST_IDX * TOC_RECORD_SZ + 4, constant_indexes.size() / CONST_RECORD_SZ);
|
||||
@@ -153,14 +153,14 @@ ByteArray Bytecode::generate(BytecodePrototype const& bp)
|
||||
// assemble bytecode
|
||||
//
|
||||
|
||||
ByteArray ba;
|
||||
ByteArrayBuilder ba;
|
||||
ba.set_bytearray(0, header);
|
||||
ba.set_bytearray(TOC_START, toc);
|
||||
ba.set_bytearray(CONST_IDX_START, constant_indexes);
|
||||
ba.set_bytearray(function_idx_start, functions_indexes);
|
||||
ba.set_bytearray(raw_constant_start, raw_constants);
|
||||
ba.set_bytearray(raw_code_start, raw_code);
|
||||
return ba;
|
||||
return ba.build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef TYCHE_BYTECODE_HH
|
||||
#define TYCHE_BYTECODE_HH
|
||||
|
||||
#include "../common/bytearray.hh"
|
||||
#include "../bytearray/bytearray.hh"
|
||||
#include "bytecodeprototype.hh"
|
||||
#include "constant.hh"
|
||||
|
||||
@@ -9,8 +9,7 @@ namespace tyche::bc {
|
||||
|
||||
class Bytecode {
|
||||
public:
|
||||
Bytecode() = default;
|
||||
explicit Bytecode(ByteArray ba);
|
||||
explicit Bytecode(StaticByteArray const* ba);
|
||||
|
||||
[[nodiscard]] uint32_t n_constants() const;
|
||||
[[nodiscard]] uint32_t n_functions() const;
|
||||
@@ -28,10 +27,10 @@ public:
|
||||
|
||||
// TODO - debugging info
|
||||
|
||||
[[nodiscard]] static ByteArray generate(BytecodePrototype const& bp);
|
||||
[[nodiscard]] static StaticByteArray generate(BytecodePrototype const& bp);
|
||||
|
||||
private:
|
||||
ByteArray byte_array_; // the actual data
|
||||
StaticByteArray const* byte_array_; // the actual data
|
||||
|
||||
static constexpr uint8_t BYTECODE_VERSION = 1;
|
||||
static constexpr uint32_t MAGIC_NUMBER = 0x74b3c138;
|
||||
|
||||
@@ -5,17 +5,17 @@
|
||||
#include <string>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
#include "../common/bytearray.hh"
|
||||
#include "../bytearray/bytearraybuilder.hh"
|
||||
|
||||
namespace tyche::bc {
|
||||
|
||||
struct BytecodePrototype {
|
||||
struct Function {
|
||||
uint16_t n_pars;
|
||||
uint16_t n_locals;
|
||||
ByteArray code {};
|
||||
uint16_t n_pars;
|
||||
uint16_t n_locals;
|
||||
ByteArrayBuilder code {};
|
||||
|
||||
Function(uint16_t n_pars_, uint16_t n_locals_) : n_pars(n_pars_), n_locals(n_locals_), code(ByteArray {}) {}
|
||||
Function(uint16_t n_pars_, uint16_t n_locals_) : n_pars(n_pars_), n_locals(n_locals_), code(ByteArrayBuilder {}) {}
|
||||
};
|
||||
|
||||
using ConstantValue = std::variant<float, std::string>;
|
||||
|
||||
@@ -3,43 +3,46 @@
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
|
||||
#include "../common/bytearray.hh"
|
||||
#include "../bytearray/bytearray.hh"
|
||||
#include "../bytearray/bytearraybuilder.hh"
|
||||
#include "bytecodeprototype.hh"
|
||||
#include "bytecode.hh"
|
||||
|
||||
using namespace tyche;
|
||||
using namespace tyche::bc;
|
||||
|
||||
TEST(ByteArray, ByteArray)
|
||||
TEST(StaticByteArray, StaticByteArray)
|
||||
{
|
||||
auto test = [](std::function<void(ByteArray&)> const& f, std::vector<uint8_t> const& expected) {
|
||||
ByteArray ba;
|
||||
auto test = [](std::function<void(ByteArrayBuilder&)> const& f, std::vector<uint8_t> const& expected) {
|
||||
ByteArrayBuilder ba;
|
||||
f(ba);
|
||||
ASSERT_EQ(ba.data().size(), expected.size());
|
||||
ASSERT_EQ(std::memcmp(ba.data().data(), expected.data(), ba.data().size()), 0);
|
||||
};
|
||||
|
||||
#define TESTX(a, ...) test([](ByteArray& ba) { a; }, std::vector<uint8_t>({ __VA_ARGS__ }));
|
||||
#define TESTX(a, ...) test([](ByteArrayBuilder& ba) { a; }, std::vector<uint8_t>({ __VA_ARGS__ }));
|
||||
|
||||
TESTX(ba.set_byte(1, 0xab), 0x00, 0xab)
|
||||
|
||||
ByteArray ba;
|
||||
ba.set_byte(1, 0xab); ASSERT_EQ(ba.get_byte(1), 0xab);
|
||||
ByteArrayBuilder ba;
|
||||
{ auto b = ba.set_byte(1, 0xab).build(); ASSERT_EQ(b.get_byte(1), 0xab); }
|
||||
|
||||
ba.set_int8(1, 12); ASSERT_EQ(ba.get_int8(1), 12);
|
||||
ba.set_int8(1, -12); ASSERT_EQ(ba.get_int8(1), -12);
|
||||
ba.set_int16(1, 5000); ASSERT_EQ(ba.get_int16(1), 5000);
|
||||
ba.set_int32(1, 5000300); ASSERT_EQ(ba.get_int32(1), 5000300);
|
||||
ba.set_int32(1, -5000300); ASSERT_EQ(ba.get_int32(1), -5000300);
|
||||
{ auto b = ba.set_int8(1, 12).build(); ASSERT_EQ(b.get_int8(1), 12); }
|
||||
{ auto b = ba.set_int8(1, -12).build(); ASSERT_EQ(b.get_int8(1), -12); }
|
||||
{ auto b = ba.set_int16(1, 5000).build(); ASSERT_EQ(b.get_int16(1), 5000); }
|
||||
{ auto b = ba.set_int32(1, 5000300).build(); ASSERT_EQ(b.get_int32(1), 5000300); }
|
||||
{ auto b = ba.set_int32(1, -5000300).build(); ASSERT_EQ(b.get_int32(1), -5000300); }
|
||||
|
||||
ba.set_float(1, 3.14); ASSERT_FLOAT_EQ(ba.get_float(1), 3.14);
|
||||
ba.set_float(1, -3.14); ASSERT_FLOAT_EQ(ba.get_float(1), -3.14);
|
||||
ba.set_float(1, -5000300.1324); ASSERT_FLOAT_EQ(ba.get_float(1), -5000300.1324);
|
||||
{ auto b = ba.set_float(1, 3.14).build(); ASSERT_FLOAT_EQ(b.get_float(1), 3.14); }
|
||||
{ auto b = ba.set_float(1, -3.14).build(); ASSERT_FLOAT_EQ(b.get_float(1), -3.14); }
|
||||
{ auto b = ba.set_float(1, -5000300.1324).build(); ASSERT_FLOAT_EQ(b.get_float(1), -5000300.1324); }
|
||||
|
||||
ba.set_string(1, "Hello world!");
|
||||
auto str = ba.get_string_ptr(1);
|
||||
EXPECT_STREQ(str.first, "Hello world!");
|
||||
ASSERT_EQ(str.second, 13);
|
||||
{
|
||||
auto b = ba.set_string(1, "Hello world!").build();
|
||||
auto str = b.get_string_ptr(1);
|
||||
EXPECT_STREQ(str.first, "Hello world!");
|
||||
ASSERT_EQ(str.second, 13);
|
||||
}
|
||||
|
||||
#undef TESTX
|
||||
}
|
||||
@@ -76,7 +79,7 @@ TEST(Bytecode, Constants)
|
||||
CONST_TYPE_STRING, 'H', 'E', 'L', 'L', 'O', 0x00
|
||||
};
|
||||
|
||||
ByteArray ba = Bytecode::generate(bp);
|
||||
StaticByteArray ba = Bytecode::generate(bp);
|
||||
ASSERT_EQ(ba.data(), expected);
|
||||
}
|
||||
|
||||
@@ -115,7 +118,7 @@ TEST(Bytecode, Code)
|
||||
0x68, 42, 0x42,
|
||||
};
|
||||
|
||||
ByteArray ba = Bytecode::generate(bp);
|
||||
StaticByteArray ba = Bytecode::generate(bp);
|
||||
ASSERT_EQ(ba.data(), expected);
|
||||
}
|
||||
|
||||
@@ -135,12 +138,12 @@ TEST(Bytecode, Parsing)
|
||||
auto& ff = bp.functions.emplace_back(2, 1);
|
||||
ff.code.append_byte(0x42);
|
||||
|
||||
ByteArray ba = Bytecode::generate(bp);
|
||||
StaticByteArray ba = Bytecode::generate(bp);
|
||||
// print(ba.data());
|
||||
|
||||
// read bytecode
|
||||
|
||||
Bytecode bc(std::move(ba));
|
||||
Bytecode bc(&ba);
|
||||
|
||||
ASSERT_EQ(bc.n_constants(), 2);
|
||||
ASSERT_EQ(bc.n_functions(), 2);
|
||||
|
||||
@@ -1,149 +0,0 @@
|
||||
#include "bytearray.hh"
|
||||
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
|
||||
namespace tyche {
|
||||
|
||||
void ByteArray::set_byte(uint32_t addr, uint8_t byte)
|
||||
{
|
||||
if (data_.size() < (addr + 1))
|
||||
data_.resize(addr + 1, 0);
|
||||
data_.at(addr) = byte;
|
||||
}
|
||||
|
||||
void ByteArray::set_int8(uint32_t addr, int8_t value)
|
||||
{
|
||||
set_byte(addr, (uint8_t) value);
|
||||
}
|
||||
|
||||
void ByteArray::set_int16(uint32_t addr, int16_t value)
|
||||
{
|
||||
set_byte(addr, (uint8_t) (value));
|
||||
set_byte(addr+1, (uint8_t) (value >> 8));
|
||||
}
|
||||
|
||||
void ByteArray::set_int32(uint32_t addr, int32_t value)
|
||||
{
|
||||
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::set_uint16(uint32_t addr, uint16_t value)
|
||||
{
|
||||
set_byte(addr, (uint8_t) (value));
|
||||
set_byte(addr+1, (uint8_t) (value >> 8));
|
||||
}
|
||||
|
||||
void ByteArray::set_uint32(uint32_t addr, uint32_t value)
|
||||
{
|
||||
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::set_float(uint32_t addr, float value)
|
||||
{
|
||||
uint32_t bits;
|
||||
std::memcpy(&bits, &value, 4);
|
||||
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::set_string(uint32_t addr, std::string const& str)
|
||||
{
|
||||
for (uint8_t c: str)
|
||||
set_byte(addr++, c);
|
||||
set_byte(addr, 0);
|
||||
}
|
||||
|
||||
void ByteArray::set_bytearray(uint32_t addr, ByteArray const& bytearray)
|
||||
{
|
||||
for (uint8_t byte: bytearray.data())
|
||||
set_byte(addr++, byte);
|
||||
}
|
||||
|
||||
uint8_t ByteArray::get_byte(uint32_t addr) const
|
||||
{
|
||||
return data_.at(addr);
|
||||
}
|
||||
|
||||
uint16_t ByteArray::get_uint16(uint32_t addr) const
|
||||
{
|
||||
return (uint32_t) get_byte(addr)
|
||||
| (uint32_t) get_byte(addr+1) << 8;
|
||||
}
|
||||
|
||||
uint32_t ByteArray::get_uint32(uint32_t addr) const
|
||||
{
|
||||
return (uint32_t) get_byte(addr)
|
||||
| (uint32_t) get_byte(addr+1) << 8
|
||||
| (uint32_t) get_byte(addr+2) << 16
|
||||
| (uint32_t) get_byte(addr+3) << 24;
|
||||
}
|
||||
|
||||
int8_t ByteArray::get_int8(uint32_t addr) const
|
||||
{
|
||||
return std::bit_cast<int8_t>(get_byte(addr));
|
||||
}
|
||||
|
||||
int16_t ByteArray::get_int16(uint32_t addr) const
|
||||
{
|
||||
return (uint16_t) get_byte(addr)
|
||||
| (uint16_t) get_byte(addr+1) << 8;
|
||||
}
|
||||
|
||||
int32_t ByteArray::get_int32(uint32_t addr) const
|
||||
{
|
||||
return std::bit_cast<int32_t>((uint32_t) get_byte(addr)
|
||||
| (uint32_t) get_byte(addr+1) << 8
|
||||
| (uint32_t) get_byte(addr+2) << 16
|
||||
| (uint32_t) get_byte(addr+3) << 24);
|
||||
}
|
||||
|
||||
float ByteArray::get_float(uint32_t addr) const
|
||||
{
|
||||
uint32_t bits = (uint32_t) get_byte(addr)
|
||||
| (uint32_t) get_byte(addr+1) << 8
|
||||
| (uint32_t) get_byte(addr+2) << 16
|
||||
| (uint32_t) get_byte(addr+3) << 24;
|
||||
float value;
|
||||
std::memcpy(&value, &bits, 4);
|
||||
return value;
|
||||
}
|
||||
|
||||
std::pair<const char*, size_t> ByteArray::get_string_ptr(uint32_t addr) const
|
||||
{
|
||||
return { (const char *) &data_.at(addr), strlen((const char *) &data_.at(addr)) + 1 };
|
||||
}
|
||||
|
||||
void ByteArray::append_bytearray(ByteArray const& bytearray)
|
||||
{
|
||||
data_.insert(data_.end(), bytearray.data().begin(), bytearray.data().end());
|
||||
}
|
||||
|
||||
std::string ByteArray::hexdump() const
|
||||
{
|
||||
auto to_hex = [](uint32_t value, size_t n_chars) -> std::string {
|
||||
char buf[15];
|
||||
snprintf(buf, sizeof buf, "%0*X", (int) n_chars, value);
|
||||
return { buf };
|
||||
};
|
||||
|
||||
std::string out;
|
||||
for (size_t i = 0; i < data_.size(); ++i) {
|
||||
if (i % 16 == 0)
|
||||
out += to_hex(i, 4) + " | ";
|
||||
out += to_hex(data_.at(i), 2) + " ";
|
||||
if (i % 16 == 15)
|
||||
out += "\n";
|
||||
}
|
||||
return out + "\n";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
#ifndef TYCHE_BYTEARRAY_HH
|
||||
#define TYCHE_BYTEARRAY_HH
|
||||
|
||||
#include <cstdint>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace tyche {
|
||||
|
||||
class ByteArray {
|
||||
public:
|
||||
ByteArray() = default;
|
||||
explicit ByteArray(std::vector<uint8_t> data) : data_(std::move(data)) {}
|
||||
|
||||
void set_byte(uint32_t addr, uint8_t byte);
|
||||
void set_uint16(uint32_t addr, uint16_t value);
|
||||
void set_uint32(uint32_t addr, uint32_t value);
|
||||
void set_int8(uint32_t addr, int8_t value);
|
||||
void set_int16(uint32_t addr, int16_t value);
|
||||
void set_int32(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 set_bytearray(uint32_t addr, ByteArray const& bytearray);
|
||||
|
||||
void append_byte(uint8_t byte) { set_byte(data_.size(), byte); }
|
||||
void append_uint16(uint16_t value) { set_uint16(data_.size(), value); }
|
||||
void append_uint32(uint32_t value) { set_uint32(data_.size(), value); }
|
||||
void append_int8(int8_t value) { set_int8(data_.size(), value); }
|
||||
void append_int16(int16_t value) { set_int16(data_.size(), value); }
|
||||
void append_int32(int32_t value) { set_int32(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]] uint16_t get_uint16(uint32_t addr) const;
|
||||
[[nodiscard]] uint32_t get_uint32(uint32_t addr) const;
|
||||
[[nodiscard]] int8_t get_int8(uint32_t addr) const;
|
||||
[[nodiscard]] int16_t get_int16(uint32_t addr) const;
|
||||
[[nodiscard]] int32_t get_int32(uint32_t addr) const;
|
||||
[[nodiscard]] float get_float(uint32_t addr) const;
|
||||
[[nodiscard]] std::pair<const char*, size_t> get_string_ptr(uint32_t addr) const;
|
||||
|
||||
[[nodiscard]] std::vector<uint8_t> const& data() const { return data_; }
|
||||
[[nodiscard]] size_t size() const { return data_.size(); }
|
||||
|
||||
[[nodiscard]] std::string hexdump() const;
|
||||
|
||||
friend bool operator==(ByteArray const& lhs, ByteArray const& rhs) { return lhs.data_ == rhs.data_; }
|
||||
|
||||
private:
|
||||
std::vector<uint8_t> data_ {};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //TYCHE_BYTEARRAY_HH
|
||||
@@ -4,9 +4,9 @@
|
||||
|
||||
namespace tyche::vm {
|
||||
|
||||
FunctionId Code::import_bytecode(ByteArray incoming)
|
||||
FunctionId Code::import_bytecode(StaticByteArray const* incoming)
|
||||
{
|
||||
bc::Bytecode bc(std::move(incoming));
|
||||
bc::Bytecode bc(incoming);
|
||||
// TODO - adjust function calls, constants
|
||||
|
||||
bytecode_ = std::move(bc);
|
||||
|
||||
@@ -17,7 +17,7 @@ struct Operation
|
||||
|
||||
class Code {
|
||||
public:
|
||||
FunctionId import_bytecode(ByteArray incoming);
|
||||
FunctionId import_bytecode(StaticByteArray const* incoming);
|
||||
|
||||
[[nodiscard]] std::string disassemble() const;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user