.
This commit is contained in:
4
Makefile
4
Makefile
@@ -58,7 +58,7 @@ check: tyche-test
|
|||||||
./tyche-test
|
./tyche-test
|
||||||
|
|
||||||
clean:
|
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: tyche libtyche.a libtyche.so.${VERSION} lib/tyche.h
|
||||||
install -m 644 libtyche.a libtyche.so.${VERSION} ${PREFIX}/lib
|
install -m 644 libtyche.a libtyche.so.${VERSION} ${PREFIX}/lib
|
||||||
@@ -76,7 +76,7 @@ uninstall:
|
|||||||
# TODO - temporary, using Lua for compilation for now
|
# TODO - temporary, using Lua for compilation for now
|
||||||
#
|
#
|
||||||
LDFLAGS+=-llua -lm
|
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
|
luac -o lib/compiler/compiler.out lib/compiler/compiler.lua
|
||||||
xxd -i lib/compiler/compiler.out > lib/compiler/compiler.lua.h
|
xxd -i lib/compiler/compiler.out > lib/compiler/compiler.lua.h
|
||||||
rm lib/compiler/compiler.out
|
rm lib/compiler/compiler.out
|
||||||
|
|||||||
28
lib/code.c
28
lib/code.c
@@ -1,11 +1,20 @@
|
|||||||
#include "priv.h"
|
#include "priv.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||||
|
# error Sorry, big endian architectures are not supported at this time.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MAGIC 0xa7d6e9b1
|
||||||
|
|
||||||
struct Code {
|
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));
|
Code* code = xcalloc(1, sizeof(Code));
|
||||||
return code;
|
return code;
|
||||||
@@ -16,6 +25,23 @@ void code_destroy(Code* code)
|
|||||||
free(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)
|
size_t code_n_consts(Code const* code)
|
||||||
{
|
{
|
||||||
return 0; // TODO
|
return 0; // TODO
|
||||||
|
|||||||
@@ -33,15 +33,11 @@ TYC_RESULT code_assemble(const char* code, uint8_t** bytecode, size_t* bytecode_
|
|||||||
return T_ERR_ASSEMBLER_SYNTAX_ERROR;
|
return T_ERR_ASSEMBLER_SYNTAX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!lua_istable(L, -1))
|
if (!lua_isstring(L, -1))
|
||||||
abort();
|
abort();
|
||||||
*bytecode_sz = luaL_len(L, -1);
|
*bytecode_sz = luaL_len(L, -1);
|
||||||
*bytecode = malloc(*bytecode_sz);
|
*bytecode = malloc(*bytecode_sz);
|
||||||
for (size_t i = 0; i < *bytecode_sz; ++i) {
|
memcpy(*bytecode, lua_tostring(L, -1), *bytecode_sz);
|
||||||
lua_geti(L, -1, i + 1);
|
|
||||||
(*bytecode)[i] = (uint8_t) lua_tointeger(L, -1);
|
|
||||||
lua_pop(L, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
lua_close(L);
|
lua_close(L);
|
||||||
return T_OK;
|
return T_OK;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
-- --
|
-- --
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
local function assemble(source)
|
local function parse_assembly(source)
|
||||||
local proto = {
|
local proto = {
|
||||||
constants = {},
|
constants = {},
|
||||||
functions = {},
|
functions = {},
|
||||||
@@ -15,8 +15,8 @@ local function assemble(source)
|
|||||||
|
|
||||||
local next_label = nil
|
local next_label = nil
|
||||||
for line in source:gmatch("([^\n]+)") do
|
for line in source:gmatch("([^\n]+)") do
|
||||||
local line = line:gsub("%s*;.*$", "") -- remove comments
|
local line = line:gsub("%s*;.*$", "") -- remove comments
|
||||||
line = line:match("^%s*(.-)%s*$") -- trim
|
line = line:match("^%s*(.-)%s*$") -- trim
|
||||||
|
|
||||||
if #line == 0 then goto continue end
|
if #line == 0 then goto continue end
|
||||||
|
|
||||||
@@ -37,23 +37,23 @@ local function assemble(source)
|
|||||||
end
|
end
|
||||||
elseif section == 'function' then
|
elseif section == 'function' then
|
||||||
local regexes = {
|
local regexes = {
|
||||||
"^%s*(%a+)%s+(%d+)%s*$", -- instruction + parameter
|
"^%s*(%a+)%s+(%d+)%s*$", -- instruction + parameter
|
||||||
"^%s*(%a+)%s+(@[%a_][%a%d_]*)%s*$", -- instruction + label
|
"^%s*(%a+)%s+(@[%a_][%a%d_]*)%s*$", -- instruction + label
|
||||||
"^%s*(%a+)%s*$", -- instruction only
|
"^%s*(%a+)%s*$", -- instruction only
|
||||||
"^(@[%a_][%a%d_]*):%s*$", -- label
|
"^(@[%a_][%a%d_]*):%s*$", -- label
|
||||||
}
|
}
|
||||||
local match = false
|
local match = false
|
||||||
for i,regex in ipairs(regexes) do
|
for i, regex in ipairs(regexes) do
|
||||||
local inst, par = line:match(regex)
|
local inst, par = line:match(regex)
|
||||||
if inst then
|
if inst then
|
||||||
match = true
|
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 })
|
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 })
|
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 })
|
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
|
if not next_label then
|
||||||
next_label = { inst }
|
next_label = { inst }
|
||||||
else
|
else
|
||||||
@@ -74,6 +74,48 @@ local function assemble(source)
|
|||||||
return proto
|
return proto
|
||||||
end
|
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 --
|
-- GENERIC --
|
||||||
@@ -81,6 +123,5 @@ end
|
|||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
return function(source)
|
return function(source)
|
||||||
print('test')
|
return assemble(parse_assembly(source))
|
||||||
return { 0, 1, 2, 3, 4 }
|
|
||||||
end
|
end
|
||||||
@@ -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);
|
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);
|
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);
|
size_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);
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ typedef enum {
|
|||||||
T_ERR_HEAP_KEY_NOT_FOUND = -10,
|
T_ERR_HEAP_KEY_NOT_FOUND = -10,
|
||||||
T_ERR_TABLE_KEY_NOT_FOUND = -20,
|
T_ERR_TABLE_KEY_NOT_FOUND = -20,
|
||||||
T_ERR_ASSEMBLER_SYNTAX_ERROR = -30,
|
T_ERR_ASSEMBLER_SYNTAX_ERROR = -30,
|
||||||
|
T_ERR_BYTECODE_TOO_SMALL = -40, T_ERR_BYTECODE_INVALID_MAGIC = -41,
|
||||||
} TYC_RESULT;
|
} TYC_RESULT;
|
||||||
|
|
||||||
#define T_REAL float
|
#define T_REAL float
|
||||||
|
|||||||
@@ -233,7 +233,9 @@ int main()
|
|||||||
uint8_t* bytecode; size_t bytecode_sz;
|
uint8_t* bytecode; size_t bytecode_sz;
|
||||||
assert(code_assemble(assembly_code, &bytecode, &bytecode_sz) == T_OK);
|
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_n_consts(code) == 2);
|
||||||
assert(code_const_type(code, 0) == TC_REAL);
|
assert(code_const_type(code, 0) == TC_REAL);
|
||||||
|
|||||||
Reference in New Issue
Block a user