diff --git a/Makefile b/Makefile index d31e2bc..5205cb3 100644 --- a/Makefile +++ b/Makefile @@ -58,7 +58,7 @@ check: tyche-test ./tyche-test clean: - rm -f tyche libtyche.a libtyche.so* tyche-test **/*.o **/*.d compiler/compiler.h + rm -f tyche libtyche.a libtyche.so* tyche-test **/*.o **/*.d lib/compiler/compiler.h install: tyche libtyche.a libtyche.so.${VERSION} lib/tyche.h install -m 644 libtyche.a libtyche.so.${VERSION} ${PREFIX}/lib @@ -76,7 +76,7 @@ uninstall: # TODO - temporary, using Lua for compilation for now # LDFLAGS+=-llua -lm -lib/compiler/compiler.lua.h: +lib/compiler/compiler.lua.h: lib/compiler/compiler.lua luac -o lib/compiler/compiler.out lib/compiler/compiler.lua xxd -i lib/compiler/compiler.out > lib/compiler/compiler.lua.h rm lib/compiler/compiler.out diff --git a/lib/code.c b/lib/code.c index 0c2e9cd..df963c1 100644 --- a/lib/code.c +++ b/lib/code.c @@ -1,11 +1,20 @@ #include "priv.h" #include +#include + +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +# error Sorry, big endian architectures are not supported at this time. +#endif + +#define MAGIC 0xa7d6e9b1 struct Code { + uint8_t* bytecode; + size_t bytecode_sz; }; -Code* code_new(uint8_t* bytecode, size_t bytecode_sz) +Code* code_new() { Code* code = xcalloc(1, sizeof(Code)); return code; @@ -16,6 +25,23 @@ void code_destroy(Code* code) free(code); } +TYC_RESULT code_load_bytecode(Code* code, uint8_t* bytecode, size_t bytecode_sz) +{ + // TODO - linking + + if (bytecode_sz < 24) + return T_ERR_BYTECODE_TOO_SMALL; + + uint32_t magic = *(uint32_t*) &bytecode[0]; + if (magic != MAGIC) + return T_ERR_BYTECODE_INVALID_MAGIC; + + code->bytecode = bytecode; + code->bytecode_sz = bytecode_sz; + + return T_OK; +} + size_t code_n_consts(Code const* code) { return 0; // TODO diff --git a/lib/compiler.c b/lib/compiler.c index cd86aea..a8fe31b 100644 --- a/lib/compiler.c +++ b/lib/compiler.c @@ -33,15 +33,11 @@ TYC_RESULT code_assemble(const char* code, uint8_t** bytecode, size_t* bytecode_ return T_ERR_ASSEMBLER_SYNTAX_ERROR; } - if (!lua_istable(L, -1)) + if (!lua_isstring(L, -1)) abort(); *bytecode_sz = luaL_len(L, -1); *bytecode = malloc(*bytecode_sz); - for (size_t i = 0; i < *bytecode_sz; ++i) { - lua_geti(L, -1, i + 1); - (*bytecode)[i] = (uint8_t) lua_tointeger(L, -1); - lua_pop(L, 1); - } + memcpy(*bytecode, lua_tostring(L, -1), *bytecode_sz); lua_close(L); return T_OK; diff --git a/lib/compiler/compiler.lua b/lib/compiler/compiler.lua index 34085d7..664c816 100644 --- a/lib/compiler/compiler.lua +++ b/lib/compiler/compiler.lua @@ -4,7 +4,7 @@ -- -- ---------------------- -local function assemble(source) +local function parse_assembly(source) local proto = { constants = {}, functions = {}, @@ -15,8 +15,8 @@ local function assemble(source) local next_label = nil for line in source:gmatch("([^\n]+)") do - local line = line:gsub("%s*;.*$", "") -- remove comments - line = line:match("^%s*(.-)%s*$") -- trim + local line = line:gsub("%s*;.*$", "") -- remove comments + line = line:match("^%s*(.-)%s*$") -- trim if #line == 0 then goto continue end @@ -37,23 +37,23 @@ local function assemble(source) end elseif section == 'function' then local regexes = { - "^%s*(%a+)%s+(%d+)%s*$", -- instruction + parameter - "^%s*(%a+)%s+(@[%a_][%a%d_]*)%s*$", -- instruction + label - "^%s*(%a+)%s*$", -- instruction only - "^(@[%a_][%a%d_]*):%s*$", -- label + "^%s*(%a+)%s+(%d+)%s*$", -- instruction + parameter + "^%s*(%a+)%s+(@[%a_][%a%d_]*)%s*$", -- instruction + label + "^%s*(%a+)%s*$", -- instruction only + "^(@[%a_][%a%d_]*):%s*$", -- label } local match = false - for i,regex in ipairs(regexes) do + for i, regex in ipairs(regexes) do local inst, par = line:match(regex) if inst then match = true - if i == 1 then -- instruction + parameter + if i == 1 then -- instruction + parameter table.insert(proto.functions[current_f_id], { inst, tonumber(par), labels = next_label }) - elseif i == 2 then -- instruction + label + elseif i == 2 then -- instruction + label table.insert(proto.functions[current_f_id], { inst, par, labels = next_label }) - elseif i == 3 then -- instruction only + elseif i == 3 then -- instruction only table.insert(proto.functions[current_f_id], { inst, labels = next_label }) - elseif i == 4 then -- label + elseif i == 4 then -- label if not next_label then next_label = { inst } else @@ -74,6 +74,48 @@ local function assemble(source) return proto end +---------------------- +-- -- +-- BINARY -- +-- -- +---------------------- + +local MAGIC = 0xa7d6e9b1 +local VERSION = 1 + +local function assemble(proto) + local bin = {} + + local push16 = function(data) + table.insert(bin, data & 0xff) + table.insert(bin, (data >> 8) & 0xff) + return #bin - 2 + end + + local push32 = function(data) + table.insert(bin, data & 0xff) + table.insert(bin, (data >> 8) & 0xff) + table.insert(bin, (data >> 16) & 0xff) + table.insert(bin, (data >> 24) & 0xff) + return #bin - 4 + end + + -- header + push32(MAGIC) + push16(VERSION) + push16(0) + + -- constants + local code_addr_pos = push32(0) -- code address, to be replaced + push32(0) -- number of constants + + -- code + push32(0) -- debug address (TODO) + push32(0) -- number of functions + + return string.char(table.unpack(bin)) +end + ---------------------- -- -- -- GENERIC -- @@ -81,6 +123,5 @@ end ---------------------- return function(source) - print('test') - return { 0, 1, 2, 3, 4 } + return assemble(parse_assembly(source)) end \ No newline at end of file diff --git a/lib/priv.h b/lib/priv.h index ab112d4..adb3d90 100644 --- a/lib/priv.h +++ b/lib/priv.h @@ -126,9 +126,11 @@ void heap_gc(Heap* h, VALUE const* roots, size_t n_roots); TYC_RESULT code_assemble(const char* code, uint8_t** bytecode, size_t* bytecode_sz); -Code* code_new(uint8_t* bytecode, size_t bytecode_sz); +Code* code_new(); void code_destroy(Code* code); +TYC_RESULT code_load_bytecode(Code* code, uint8_t* bytecode, size_t bytecode_sz); + size_t code_n_consts(Code const* code); TYC_CONST_TYPE code_const_type(Code const* code, size_t n); diff --git a/lib/tyche.h b/lib/tyche.h index 1598c86..6ff15d5 100644 --- a/lib/tyche.h +++ b/lib/tyche.h @@ -11,6 +11,7 @@ typedef enum { T_ERR_HEAP_KEY_NOT_FOUND = -10, T_ERR_TABLE_KEY_NOT_FOUND = -20, T_ERR_ASSEMBLER_SYNTAX_ERROR = -30, + T_ERR_BYTECODE_TOO_SMALL = -40, T_ERR_BYTECODE_INVALID_MAGIC = -41, } TYC_RESULT; #define T_REAL float diff --git a/test/tests.c b/test/tests.c index f0d6d6a..59f85c5 100644 --- a/test/tests.c +++ b/test/tests.c @@ -233,7 +233,9 @@ int main() uint8_t* bytecode; size_t bytecode_sz; assert(code_assemble(assembly_code, &bytecode, &bytecode_sz) == T_OK); - Code* code = code_new(bytecode, bytecode_sz); + Code* code = code_new(); + + assert(code_load_bytecode(code, bytecode, bytecode_sz) == T_OK); assert(code_n_consts(code) == 2); assert(code_const_type(code, 0) == TC_REAL);