bytecode-improvements #3

Merged
andre merged 3 commits from bytecode-improvements into master 2026-04-29 11:40:46 -05:00
7 changed files with 86 additions and 60 deletions
Showing only changes of commit 766032e839 - Show all commits

View File

@@ -8,7 +8,11 @@
- Add/retrive all types of data - Add/retrive all types of data
- Keeps no memory except for caching - Keeps no memory except for caching
- [x] Refactor bytecode code - [x] Refactor bytecode code
- [ ] Output bytecode format
Improvements:
- [ ] Fixed int type (based on opcode)
- [ ] Constant type (only floats and strings for now)
- [ ] Debug output bytecode format
After some additional development: After some additional development:
- [ ] Bytecode debugging info - [ ] Bytecode debugging info

View File

@@ -1,17 +1,23 @@
Operations Operations
---------- ----------
Operations take either 0 or 1 parameter. The ones that take a parameter, it can be either a int8, int16 or int32.
The binary of the opcode is: XXYY.YYYY, where XX defines the parameter type, and YY.YYYY is the instruction. For the XX values:
00 - no parameter
01 - int8
10 - int16
11 - int32
Stack operations: (0x00~0x1f) Stack operations: (0x00~0x1f)
pushn [int] Push int pushn [int] Push int
pushr [float] Push float (real) pushc [index] Push constant
pshcn [index] Push int from constant list
pshcr [index] Push float from constant list
pshcs [index] Push string from constant list
pushf [function] Push function id pushf [function] Push function id
pushz Push zero (or false) pushz Push zero (or false)
pusht Push true pusht Push true
newa [array] Push (create) empty array newa Push (create) empty array
newt [table] Push (create) empty table newt Push (create) empty table
pop pop
dup dup

View File

@@ -14,14 +14,23 @@ void ByteArray::set_byte(uint32_t addr, uint8_t byte)
} }
} }
void ByteArray::set_int(uint32_t addr, int32_t value) void ByteArray::set_int8(uint32_t addr, int8_t value)
{ {
uint32_t zz = ((uint32_t)(value << 1)) ^ ((uint32_t)(value >> 31)); set_byte(addr, (uint8_t) value);
while (zz > 0x7F) { }
set_byte(addr++, (zz & 0x7F) | 0x80);
zz >>= 7; void ByteArray::set_int16(uint32_t addr, int16_t value)
} {
set_byte(addr, zz & 0x7F); 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) void ByteArray::set_uint16(uint32_t addr, uint16_t value)
@@ -80,20 +89,23 @@ uint32_t ByteArray::get_uint32(uint32_t addr) const
| (uint32_t) get_byte(addr+3) << 24; | (uint32_t) get_byte(addr+3) << 24;
} }
std::pair<int32_t, size_t> ByteArray::get_int(uint32_t addr) const int8_t ByteArray::get_int8(uint32_t addr) const
{ {
uint32_t zz = 0; return std::bit_cast<int8_t>(get_byte(addr));
int shift = 0; }
for (size_t i = 0; shift < 35; i++) {
uint8_t byte = get_byte(addr++); int16_t ByteArray::get_int16(uint32_t addr) const
zz |= (uint32_t)(byte & 0x7F) << shift; {
if (!(byte & 0x80)) { return (uint16_t) get_byte(addr)
int32_t value = (int32_t)((zz >> 1) ^ -(zz & 1)); | (uint16_t) get_byte(addr+1) << 8;
return std::make_pair(value, (int)(i + 1)); }
}
shift += 7; int32_t ByteArray::get_int32(uint32_t addr) const
} {
throw BytecodeParsingError("Error parsing int32 at position " + std::to_string(addr)); 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 float ByteArray::get_float(uint32_t addr) const

View File

@@ -16,23 +16,29 @@ public:
void set_byte(uint32_t addr, uint8_t byte); void set_byte(uint32_t addr, uint8_t byte);
void set_uint16(uint32_t addr, uint16_t value); void set_uint16(uint32_t addr, uint16_t value);
void set_uint32(uint32_t addr, uint32_t value); void set_uint32(uint32_t addr, uint32_t value);
void set_int(uint32_t addr, int32_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_float(uint32_t addr, float value);
void set_string(uint32_t addr, std::string const& str); void set_string(uint32_t addr, std::string const& str);
void set_bytearray(uint32_t addr, ByteArray const& bytearray); void set_bytearray(uint32_t addr, ByteArray const& bytearray);
void append_byte(uint8_t byte) { set_byte(data_.size(), byte); } void append_byte(uint8_t byte) { set_byte(data_.size(), byte); }
void append_uint16(uint16_t value) { set_uint16(data_.size(), value); } void append_uint16(uint16_t value) { set_uint16(data_.size(), value); }
void append_uint32(uint32_t value) { set_uint32(data_.size(), value); } void append_uint32(uint32_t value) { set_uint32(data_.size(), value); }
void append_int(int32_t value) { set_int(data_.size(), value); } void append_int8(int8_t value) { set_int8(data_.size(), value); }
void append_float(float value) { set_float(data_.size(), value); } void append_int16(int16_t value) { set_int16(data_.size(), value); }
void append_string(std::string const& str) { set_string(data_.size(), str); } 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); 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]] uint16_t get_uint16(uint32_t addr) const; [[nodiscard]] uint16_t get_uint16(uint32_t addr) const;
[[nodiscard]] uint32_t get_uint32(uint32_t addr) const; [[nodiscard]] uint32_t get_uint32(uint32_t addr) const;
[[nodiscard]] std::pair<int32_t, size_t> get_int(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]] float get_float(uint32_t addr) const;
[[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;

View File

@@ -39,12 +39,6 @@ uint32_t Bytecode::n_functions() const
return cache_.n_functions; return cache_.n_functions;
} }
int32_t Bytecode::get_constant_int(uint32_t idx) const
{
uint32_t constant_idx = byte_array_.get_uint32(cache_.constants_idx_addr + (idx * CONST_RECORD_SZ));
return byte_array_.get_int(cache_.constants_start_addr + constant_idx).first;
}
float Bytecode::get_constant_float(uint32_t idx) const float Bytecode::get_constant_float(uint32_t idx) const
{ {
uint32_t constant_idx = byte_array_.get_uint32(cache_.constants_idx_addr + (idx * CONST_RECORD_SZ)); uint32_t constant_idx = byte_array_.get_uint32(cache_.constants_idx_addr + (idx * CONST_RECORD_SZ));
@@ -76,14 +70,19 @@ 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);
} }
std::pair<int32_t, size_t> Bytecode::get_code_int(uint32_t function_id, uint32_t idx) const int8_t Bytecode::get_code_int8(uint32_t function_id, uint32_t idx) const
{ {
return byte_array_.get_int(cache_.function_addr.at(function_id) + idx); return byte_array_.get_int8(cache_.function_addr.at(function_id) + idx);
} }
float Bytecode::get_code_float(uint32_t function_id, uint32_t idx) const int16_t Bytecode::get_code_int16(uint32_t function_id, uint32_t idx) const
{ {
return byte_array_.get_float(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);
} }
ByteArray Bytecode::generate(BytecodePrototype const& bp) ByteArray Bytecode::generate(BytecodePrototype const& bp)
@@ -101,7 +100,7 @@ ByteArray Bytecode::generate(BytecodePrototype const& bp)
for (auto const& constant: bp.constants) { for (auto const& constant: bp.constants) {
constant_indexes.append_uint32(idx); constant_indexes.append_uint32(idx);
std::visit(overloaded { std::visit(overloaded {
[&](int32_t i) { raw_constants.append_int(i); }, [&](int32_t i) { raw_constants.append_int32(i); },
[&](float f) { raw_constants.append_float(f); }, [&](float f) { raw_constants.append_float(f); },
[&](std::string const& s) { raw_constants.append_string(s); }, [&](std::string const& s) { raw_constants.append_string(s); },
}, constant); }, constant);

View File

@@ -13,7 +13,6 @@ public:
[[nodiscard]] uint32_t n_constants() const; [[nodiscard]] uint32_t n_constants() const;
[[nodiscard]] uint32_t n_functions() const; [[nodiscard]] uint32_t n_functions() const;
[[nodiscard]] int32_t get_constant_int(uint32_t idx) const;
[[nodiscard]] float get_constant_float(uint32_t idx) const; [[nodiscard]] float get_constant_float(uint32_t idx) const;
[[nodiscard]] std::string get_constant_string(uint32_t idx) const; [[nodiscard]] std::string get_constant_string(uint32_t idx) const;
@@ -21,9 +20,10 @@ public:
[[nodiscard]] FunctionDef get_function_def(uint32_t function_id) const; [[nodiscard]] FunctionDef get_function_def(uint32_t function_id) const;
[[nodiscard]] uint32_t get_function_sz(uint32_t function_id) const; [[nodiscard]] uint32_t get_function_sz(uint32_t function_id) const;
[[nodiscard]] uint8_t get_code_byte(uint32_t function_id, uint32_t idx) const; [[nodiscard]] uint8_t get_code_byte(uint32_t function_id, uint32_t idx) const;
[[nodiscard]] std::pair<int32_t, size_t> get_code_int(uint32_t function_id, uint32_t idx) const; [[nodiscard]] int8_t get_code_int8(uint32_t function_id, uint32_t idx) const;
[[nodiscard]] float get_code_float(uint32_t function_id, uint32_t idx) const; [[nodiscard]] int16_t get_code_int16(uint32_t function_id, uint32_t idx) const;
[[nodiscard]] int32_t get_code_int32(uint32_t function_id, uint32_t idx) const;
// TODO - debugging info // TODO - debugging info

View File

@@ -26,11 +26,11 @@ TEST(ByteArray, ByteArray)
ByteArray ba; ByteArray ba;
ba.set_byte(1, 0xab); ASSERT_EQ(ba.get_byte(1), 0xab); ba.set_byte(1, 0xab); ASSERT_EQ(ba.get_byte(1), 0xab);
ba.set_int(1, 12); ASSERT_EQ(ba.get_int(1), std::make_pair(12, 1)); ba.set_int8(1, 12); ASSERT_EQ(ba.get_int8(1), 12);
ba.set_int(1, -12); ASSERT_EQ(ba.get_int(1), std::make_pair(-12, 1)); ba.set_int8(1, -12); ASSERT_EQ(ba.get_int8(1), -12);
ba.set_int(1, 5000); ASSERT_EQ(ba.get_int(1), std::make_pair(5000, 2)); ba.set_int16(1, 5000); ASSERT_EQ(ba.get_int16(1), 5000);
ba.set_int(1, 5000300); ASSERT_EQ(ba.get_int(1), std::make_pair(5000300, 4)); ba.set_int32(1, 5000300); ASSERT_EQ(ba.get_int32(1), 5000300);
ba.set_int(1, -5000300); ASSERT_EQ(ba.get_int(1), std::make_pair(-5000300, 4)); ba.set_int32(1, -5000300); ASSERT_EQ(ba.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, -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);
@@ -82,7 +82,7 @@ TEST(Bytecode, Code)
BytecodePrototype bp; BytecodePrototype bp;
auto& f = bp.functions.emplace_back(0, 0); auto& f = bp.functions.emplace_back(0, 0);
f.code.append_byte(0x68); f.code.append_byte(0x68);
f.code.append_int(42); f.code.append_int32(42);
auto& f2 = bp.functions.emplace_back(2, 1); auto& f2 = bp.functions.emplace_back(2, 1);
f2.code.append_byte(0x42); f2.code.append_byte(0x42);
@@ -128,7 +128,7 @@ TEST(Bytecode, Parsing)
auto& f = bp.functions.emplace_back(0, 0); auto& f = bp.functions.emplace_back(0, 0);
f.code.append_byte(0x68); f.code.append_byte(0x68);
f.code.append_int(42); f.code.append_int8(42);
auto& ff = bp.functions.emplace_back(2, 1); auto& ff = bp.functions.emplace_back(2, 1);
ff.code.append_byte(0x42); ff.code.append_byte(0x42);
@@ -140,10 +140,9 @@ TEST(Bytecode, Parsing)
Bytecode bc(std::move(ba)); Bytecode bc(std::move(ba));
ASSERT_EQ(bc.n_constants(), 3); ASSERT_EQ(bc.n_constants(), 2);
ASSERT_EQ(bc.n_functions(), 2); ASSERT_EQ(bc.n_functions(), 2);
ASSERT_EQ(bc.get_constant_int(0), 42);
ASSERT_FLOAT_EQ(bc.get_constant_float(1), 3.14f); ASSERT_FLOAT_EQ(bc.get_constant_float(1), 3.14f);
ASSERT_EQ(bc.get_constant_string(2), "HELLO"); ASSERT_EQ(bc.get_constant_string(2), "HELLO");
@@ -156,7 +155,7 @@ TEST(Bytecode, Parsing)
ASSERT_EQ(f2.locals, 1); ASSERT_EQ(f2.locals, 1);
ASSERT_EQ(bc.get_code_byte(0, 0), 0x68); ASSERT_EQ(bc.get_code_byte(0, 0), 0x68);
ASSERT_EQ(bc.get_code_int(0, 1), std::make_pair(42, 1)); ASSERT_EQ(bc.get_code_int8(0, 1), 42);
ASSERT_EQ(bc.get_code_byte(1, 0), 0x42); ASSERT_EQ(bc.get_code_byte(1, 0), 0x42);
} }