.
This commit is contained in:
@@ -14,8 +14,7 @@ The bytecode file is composed of the following sections:
|
|||||||
Each constant:
|
Each constant:
|
||||||
[0]: Type (0 = string, 1 = real)
|
[0]: Type (0 = string, 1 = real)
|
||||||
if string:
|
if string:
|
||||||
[1..4]: string size
|
[...]: string (NULL terminated)
|
||||||
[...]: string
|
|
||||||
if real
|
if real
|
||||||
[1..4]: real
|
[1..4]: real
|
||||||
|
|
||||||
|
|||||||
68
lib/code.c
68
lib/code.c
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||||
# error Sorry, big endian architectures are not supported at this time.
|
# error Sorry, big endian architectures are not supported at this time.
|
||||||
@@ -15,13 +16,14 @@
|
|||||||
#define CONST_START 0x10
|
#define CONST_START 0x10
|
||||||
|
|
||||||
struct Code {
|
struct Code {
|
||||||
uint8_t* bytecode;
|
uint8_t const* bytecode;
|
||||||
size_t bytecode_sz;
|
size_t bytecode_sz;
|
||||||
uint32_t* const_addr;
|
uint32_t* const_addr;
|
||||||
uint32_t* fn_addr;
|
uint32_t fn_count;
|
||||||
|
uint32_t* fn_addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
Code* code_new()
|
Code* code_new(void)
|
||||||
{
|
{
|
||||||
Code* code = xcalloc(1, sizeof(Code));
|
Code* code = xcalloc(1, sizeof(Code));
|
||||||
return code;
|
return code;
|
||||||
@@ -29,6 +31,8 @@ Code* code_new()
|
|||||||
|
|
||||||
void code_destroy(Code* code)
|
void code_destroy(Code* code)
|
||||||
{
|
{
|
||||||
|
free(code->const_addr);
|
||||||
|
free(code->fn_addr);
|
||||||
free(code);
|
free(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,6 +50,7 @@ TYC_RESULT code_load_bytecode(Code* code, uint8_t* bytecode, size_t bytecode_sz)
|
|||||||
code->bytecode = bytecode;
|
code->bytecode = bytecode;
|
||||||
code->bytecode_sz = bytecode_sz;
|
code->bytecode_sz = bytecode_sz;
|
||||||
|
|
||||||
|
/*
|
||||||
for (size_t i = 0; i < bytecode_sz; ++i) {
|
for (size_t i = 0; i < bytecode_sz; ++i) {
|
||||||
if (i % 16 == 0)
|
if (i % 16 == 0)
|
||||||
printf("%04X: ", i);
|
printf("%04X: ", i);
|
||||||
@@ -53,32 +58,71 @@ TYC_RESULT code_load_bytecode(Code* code, uint8_t* bytecode, size_t bytecode_sz)
|
|||||||
if (i % 16 == 15)
|
if (i % 16 == 15)
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
printf("\n");
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint32_t n_consts = code_n_consts(code);
|
||||||
|
code->const_addr = calloc(n_consts, sizeof(uint32_t));
|
||||||
|
uint32_t addr = CONST_START;
|
||||||
|
for (size_t i = 0; i < n_consts; ++i) {
|
||||||
|
code->const_addr[i] = addr;
|
||||||
|
switch (code_const_type(code, i)) {
|
||||||
|
case TC_STRING: {
|
||||||
|
uint32_t sz = (uint32_t) strlen((const char*) &bytecode[code->const_addr[i] + 1]);
|
||||||
|
addr += sz + 2; // 2 = constant type + NULL terminator
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TC_REAL:
|
||||||
|
addr += 5; // 5 = constant type + float
|
||||||
|
break;
|
||||||
|
case TC_INVALID_TYPE:
|
||||||
|
default:
|
||||||
|
__builtin_unreachable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addr += 4; // skip debug start address
|
||||||
|
memcpy(&code->fn_count, &bytecode[addr], sizeof(uint32_t)); // number of functions
|
||||||
|
addr += 4;
|
||||||
|
|
||||||
|
code->fn_addr = calloc(code->fn_count, sizeof(uint32_t));
|
||||||
|
code->fn_addr[0] = addr;
|
||||||
|
for (size_t i = 1; i < code->fn_count; ++i) {
|
||||||
|
uint32_t addr_next;
|
||||||
|
memcpy(&addr_next, &bytecode[addr], sizeof(uint32_t));
|
||||||
|
addr = code->fn_addr[i] = addr_next;
|
||||||
|
}
|
||||||
|
|
||||||
return T_OK;
|
return T_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t code_n_consts(Code const* code)
|
uint32_t code_n_consts(Code const* code)
|
||||||
{
|
{
|
||||||
uint32_t n_consts = *(uint32_t*) &code->bytecode[N_CONST_ADDR];
|
uint32_t n_consts; memcpy(&n_consts, &code->bytecode[N_CONST_ADDR], sizeof(uint32_t));
|
||||||
return n_consts;
|
return n_consts;
|
||||||
}
|
}
|
||||||
|
|
||||||
TYC_CONST_TYPE code_const_type(Code const* code, size_t n)
|
TYC_CONST_TYPE code_const_type(Code const* code, size_t n)
|
||||||
{
|
{
|
||||||
return TC_REAL; // TODO
|
uint8_t t = code->bytecode[code->const_addr[n]];
|
||||||
|
if (t >= TC_INVALID_TYPE)
|
||||||
|
return TC_INVALID_TYPE;
|
||||||
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
T_REAL code_const_real(Code const* code, size_t n)
|
T_REAL code_const_real(Code const* code, size_t n)
|
||||||
{
|
{
|
||||||
return 0.f; // TODO
|
float f;
|
||||||
|
memcpy(&f, &code->bytecode[code->const_addr[n] + 1], sizeof(float));
|
||||||
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* code_const_string(Code const* code, size_t n)
|
const char* code_const_string(Code const* code, size_t n)
|
||||||
{
|
{
|
||||||
return ""; // TODO
|
return (const char*) &code->bytecode[code->const_addr[n] + 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t code_n_functions(Code const* code)
|
uint32_t code_n_functions(Code const* code)
|
||||||
{
|
{
|
||||||
return 0; // TODO
|
return code->fn_count;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ TYC_RESULT code_assemble(const char* code, uint8_t** bytecode, size_t* bytecode_
|
|||||||
|
|
||||||
if (!lua_isstring(L, -1))
|
if (!lua_isstring(L, -1))
|
||||||
abort();
|
abort();
|
||||||
*bytecode_sz = luaL_len(L, -1);
|
*bytecode_sz = (size_t) luaL_len(L, -1);
|
||||||
*bytecode = malloc(*bytecode_sz);
|
*bytecode = malloc(*bytecode_sz);
|
||||||
memcpy(*bytecode, lua_tostring(L, -1), *bytecode_sz);
|
memcpy(*bytecode, lua_tostring(L, -1), *bytecode_sz);
|
||||||
|
|
||||||
|
|||||||
@@ -107,13 +107,9 @@ local function assemble(proto)
|
|||||||
bin[pos + 3] = (data >> 24) & 0xff
|
bin[pos + 3] = (data >> 24) & 0xff
|
||||||
end
|
end
|
||||||
|
|
||||||
local float_to_le_bytes = function(f)
|
local function float_to_bits(f)
|
||||||
local bytes = {}
|
local bytes = string.pack("<f", f)
|
||||||
local packed = string.pack("<f", f)
|
return string.unpack("<I4", bytes)
|
||||||
for i = 1, 4 do
|
|
||||||
bytes[i] = packed:byte(i)
|
|
||||||
end
|
|
||||||
return bytes
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- header
|
-- header
|
||||||
@@ -123,34 +119,35 @@ local function assemble(proto)
|
|||||||
|
|
||||||
-- constants
|
-- constants
|
||||||
local code_addr_pos = push32(0) -- code address, to be replaced
|
local code_addr_pos = push32(0) -- code address, to be replaced
|
||||||
print(code_addr_pos)
|
push32(#proto.constants + 1) -- number of constants
|
||||||
push32(#proto.constants) -- number of constants
|
for i=0,#proto.constants do
|
||||||
for i, const in ipairs(proto.constants) do
|
local const = proto.constants[i]
|
||||||
if type(const) == 'string' then
|
if type(const) == 'string' then
|
||||||
table.insert(bin, 0) -- string type
|
table.insert(bin, 0) -- string type
|
||||||
push32(#const)
|
|
||||||
for c in const:gmatch('.') do
|
for c in const:gmatch('.') do
|
||||||
table.insert(bin, c:byte())
|
table.insert(bin, c:byte())
|
||||||
end
|
end
|
||||||
|
table.insert(bin, 0) -- string terminator
|
||||||
elseif type(const) == 'number' then
|
elseif type(const) == 'number' then
|
||||||
table.insert(bin, 0) -- float type
|
table.insert(bin, 1) -- float type
|
||||||
push32(float_to_le_bytes(const))
|
push32(float_to_bits(const))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
replace32(code_addr_pos, #bin)
|
replace32(code_addr_pos, #bin)
|
||||||
|
|
||||||
-- code
|
-- code
|
||||||
push32(0) -- debug address (TODO)
|
push32(0) -- debug address (TODO)
|
||||||
push32(#proto.functions) -- number of functions
|
push32(#proto.functions + 1) -- number of functions
|
||||||
for _,func in ipairs(proto.functions) do
|
for i=0,#proto.functions do
|
||||||
local next_function_pos = #bin
|
local func = proto.functions[i]
|
||||||
|
local next_function_pos = #bin + 1
|
||||||
push32(0) -- to be replaced with next function address
|
push32(0) -- to be replaced with next function address
|
||||||
-- TODO - add code
|
-- TODO - add code
|
||||||
replace32(next_function_pos, #bin)
|
replace32(next_function_pos, #bin)
|
||||||
end
|
end
|
||||||
|
|
||||||
return string.char(table.unpack(bin))
|
return string.char(table.unpack(bin))
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
----------------------
|
----------------------
|
||||||
|
|||||||
12
lib/priv.h
12
lib/priv.h
@@ -30,7 +30,7 @@ typedef uint32_t HEAP_KEY;
|
|||||||
typedef uint64_t TABLE_HASH;
|
typedef uint64_t TABLE_HASH;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
TC_STRING, TC_REAL,
|
TC_STRING, TC_REAL, TC_INVALID_TYPE
|
||||||
} TYC_CONST_TYPE;
|
} TYC_CONST_TYPE;
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -124,19 +124,19 @@ void heap_gc(Heap* h, VALUE const* roots, size_t n_roots);
|
|||||||
// CODE
|
// CODE
|
||||||
//
|
//
|
||||||
|
|
||||||
TYC_RESULT code_assemble(const char* code, uint8_t** bytecode, size_t* bytecode_sz);
|
TYC_RESULT code_assemble(const char* code, uint8_t** bytecode, size_t* bytecode_sz);
|
||||||
|
|
||||||
Code* code_new();
|
Code* code_new(void);
|
||||||
void code_destroy(Code* code);
|
void code_destroy(Code* code);
|
||||||
|
|
||||||
TYC_RESULT code_load_bytecode(Code* code, uint8_t* bytecode, size_t bytecode_sz);
|
TYC_RESULT code_load_bytecode(Code* code, uint8_t* bytecode, size_t bytecode_sz);
|
||||||
|
|
||||||
size_t code_n_consts(Code const* code);
|
uint32_t code_n_consts(Code const* code);
|
||||||
TYC_CONST_TYPE code_const_type(Code const* code, size_t n);
|
TYC_CONST_TYPE code_const_type(Code const* code, size_t n);
|
||||||
|
|
||||||
T_REAL code_const_real(Code const* code, size_t n);
|
T_REAL code_const_real(Code const* code, size_t n);
|
||||||
const char* code_const_string(Code const* code, size_t n);
|
const char* code_const_string(Code const* code, size_t n);
|
||||||
|
|
||||||
size_t code_n_functions(Code const* code);
|
uint32_t code_n_functions(Code const* code);
|
||||||
|
|
||||||
#endif //TYCHE_PRIV_H
|
#endif //TYCHE_PRIV_H
|
||||||
|
|||||||
@@ -241,9 +241,10 @@ int main()
|
|||||||
assert(code_const_type(code, 0) == TC_REAL);
|
assert(code_const_type(code, 0) == TC_REAL);
|
||||||
assert(code_const_type(code, 1) == TC_STRING);
|
assert(code_const_type(code, 1) == TC_STRING);
|
||||||
assert(code_const_real(code, 0) >= 3.13 && code_const_real(code, 0) <= 3.15);
|
assert(code_const_real(code, 0) >= 3.13 && code_const_real(code, 0) <= 3.15);
|
||||||
assert(strcmp(code_const_string(code, 1), "Hello world\n") == 0);
|
assert(strcmp(code_const_string(code, 1), "Hello world") == 0);
|
||||||
assert(code_n_functions(code) == 2);
|
assert(code_n_functions(code) == 2);
|
||||||
|
|
||||||
|
code_destroy(code);
|
||||||
free(bytecode);
|
free(bytecode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user