diff --git a/byterun/include/interpreter.h b/byterun/include/interpreter.h index aae9ad99e..2a87ac2fe 100644 --- a/byterun/include/interpreter.h +++ b/byterun/include/interpreter.h @@ -2,4 +2,4 @@ #include "parser.h" -void run(bytefile *bf, int argc, char **argv); +void run(uint mod_id, int argc, char **argv); diff --git a/byterun/include/module_manager.h b/byterun/include/module_manager.h index f4dadd8d7..70d643bc4 100644 --- a/byterun/include/module_manager.h +++ b/byterun/include/module_manager.h @@ -5,9 +5,9 @@ #include "utils.h" struct ModSearchResult { - ssize_t symbol_offset; // < 0 => not found + size_t symbol_offset; uint32_t mod_id; - bytefile *mod_file; + bytefile *mod_file; // = NULL => not found }; void mod_add_search_path(const char *path); @@ -16,4 +16,6 @@ bytefile *mod_get(uint32_t id); int32_t mod_load(const char *name); // < 0 => not found +uint32_t mod_add(bytefile *module); + struct ModSearchResult mod_search_pub_symbol(const char *name); diff --git a/byterun/include/stack.h b/byterun/include/stack.h index b58de8ac5..8aa99b7fe 100644 --- a/byterun/include/stack.h +++ b/byterun/include/stack.h @@ -1,6 +1,7 @@ #pragma once #include "../../runtime/gc.h" +#include "module_manager.h" #include "runtime_externs.h" #include "types.h" #include "utils.h" @@ -134,14 +135,14 @@ static inline void s_rotate_n(size_t n) { // ------ functions ------ -// |> param_0 ... param_n | frame[ ret rp prev_fp ¶ms &locals &end +// |> param_0 ... param_n | frame[ ret rp prev_fp ... ¶ms &locals &end // ] // |> local_0 ... local_m |> | ... // // where |> defines corresponding frame pointer, | is stack pointer // location before / after new frame added -static inline void s_enter_f(char *rp, bool is_closure_call, auint args_sz, - auint locals_sz) { +static inline void s_enter_f(char *rp, aint ret_module_id, bool is_closure_call, + auint args_sz, auint locals_sz) { #ifdef DEBUG_VERSION printf("-> %i args sz\n", args_sz); printf("-> %i locals sz\n", locals_sz); @@ -169,6 +170,7 @@ static inline void s_enter_f(char *rp, bool is_closure_call, auint args_sz, .ret = NULL, // field in frame itself .rp = rp, .prev_fp = (void **)s.fp, + .ret_module_box = BOX(ret_module_id), .args_sz_box = BOX(args_sz), .locals_sz_box = BOX(locals_sz), }; @@ -207,6 +209,10 @@ static inline void s_exit_f() { } s.ip = frame.rp; + + s.current_module_id = UNBOX(frame.ret_module_box); + s.bf = mod_get(s.current_module_id); + // TODO: return to ret_module } static inline void print_stack() { diff --git a/byterun/include/types.h b/byterun/include/types.h index a3cba0592..c9067c048 100644 --- a/byterun/include/types.h +++ b/byterun/include/types.h @@ -22,13 +22,14 @@ static const size_t MAX_ARRAY_SIZE = 0x11111110; // ------ Frame ------ struct Frame { - void *closure; // where closure value stored if needed - void *ret; // store returned value [gc pointer] - char *rp; // ret instruction pointer [not gc pointer] - void **prev_fp; // ret function frame pointer [boxed value, not gc - // pointer] - aint args_sz_box; // store arguments [boxed value, not gc pointer] - aint locals_sz_box; // store locals [boxed value, not gc pointer] + void *closure; // where closure value stored if needed + void *ret; // store returned value [gc pointer] + char *rp; // ret instruction pointer [not gc pointer] + void **prev_fp; // ret function frame pointer [boxed value, not gc + // pointer] + aint ret_module_box; // module to return [boxed value, not gc pointer] + aint args_sz_box; // store arguments [boxed value, not gc pointer] + aint locals_sz_box; // store locals [boxed value, not gc pointer] }; // NOTE: stack is [top -> bottom] @@ -60,14 +61,18 @@ struct State { bool is_closure_call; + uint current_module_id; + uint call_module_id; + char *ip; // instruction pointer char *instr_ip; // poiter to current instruction char *call_ip; // prev instruction pointer (to remember jmp locations) }; -void construct_state(bytefile *bf, struct State *s, void **stack); +void construct_state(uint mod_id, struct State *s, void **stack); void cleanup_state(struct State *state); +// TODO: print current mod id static inline void s_failure(struct State *s, const char *msg) { exec_failure(read_cmd(s->instr_ip), s->current_line, s->instr_ip - s->bf->code_ptr, msg); diff --git a/byterun/src/cli.c b/byterun/src/cli.c index 3b22af2da..5ed2a26c5 100644 --- a/byterun/src/cli.c +++ b/byterun/src/cli.c @@ -1,4 +1,5 @@ #include "interpreter.h" +#include "module_manager.h" #include "parser.h" #include "utils.h" #include "../../runtime/runtime.h" @@ -9,15 +10,15 @@ int main(int argc, char** argv) { } bytefile *f = read_file(argv[2]); + uint main_mod_id = mod_add(f); if (strcmp(argv[1], "-i") == 0) { - run(f, argc - 1, argv + 1); + run(main_mod_id, argc - 1, argv + 1); // TODO: init all modules, execute all prev. modules } else if (strcmp(argv[1], "-p") == 0) { dump_file (stdout, f); } else { failure("undefined execution mode. Execution mode should be -i (interpret) or -p (print)\n"); } - free(f->global_ptr); free(f); return 0; diff --git a/byterun/src/interpreter.c b/byterun/src/interpreter.c index 4cde7f572..039695837 100644 --- a/byterun/src/interpreter.c +++ b/byterun/src/interpreter.c @@ -3,6 +3,7 @@ #include "../../runtime/gc.h" #include "../../runtime/runtime.h" +#include "module_manager.h" #include "runtime_externs.h" #include "stack.h" #include "types.h" @@ -37,10 +38,17 @@ static inline const char *ip_read_string(char **ip) { const size_t BUFFER_SIZE = 1000; -void run(bytefile *bf, int argc, char **argv) { +void init_stack(int argc, char **argv) {} // TODO + +void init_mod_rec(uint mod_id) {} // TODO + +void run(uint mod_id, int argc, char **argv) { // TODO: remove mod init and stack init size_t stack[STACK_SIZE]; void *buffer[BUFFER_SIZE]; - construct_state(bf, &s, (void **)stack); + construct_state( + mod_id, &s, + (void **) + stack); // TODO: separate on each module part and part for all run #ifdef DEBUG_VERSION printf("--- interpreter run ---\n"); @@ -65,11 +73,11 @@ void run(bytefile *bf, int argc, char **argv) { do { bool call_happened = false; - if (s.ip >= bf->code_ptr + bf->code_size) { + if (s.ip >= s.bf->code_ptr + s.bf->code_size) { s_failure(&s, "instruction pointer is out of range (>= size)"); } - if (s.ip < bf->code_ptr) { + if (s.ip < s.bf->code_ptr) { s_failure(&s, "instruction pointer is out of range (< 0)"); } @@ -171,10 +179,10 @@ void run(bytefile *bf, int argc, char **argv) { case CMD_BASIC_JMP: { // JMP 0x%.8x uint jmp_p = ip_read_int(&s.ip); - if (jmp_p >= bf->code_size) { + if (jmp_p >= s.bf->code_size) { s_failure(&s, "jump out of file"); } - s.ip = bf->code_ptr + jmp_p; + s.ip = s.bf->code_ptr + jmp_p; break; } @@ -246,11 +254,11 @@ void run(bytefile *bf, int argc, char **argv) { case CMD_CTRL_CJMPz: { // CJMPz 0x%.8x uint jmp_p = ip_read_int(&s.ip); - if (jmp_p >= bf->code_size) { + if (jmp_p >= s.bf->code_size) { s_failure(&s, "jump out of file"); } if (UNBOX(s_pop_i()) == 0) { - s.ip = bf->code_ptr + jmp_p; + s.ip = s.bf->code_ptr + jmp_p; } break; } @@ -258,11 +266,11 @@ void run(bytefile *bf, int argc, char **argv) { case CMD_CTRL_CJMPnz: { // CJMPnz 0x%.8x uint jmp_p = ip_read_int(&s.ip); - if (jmp_p >= bf->code_size) { + if (jmp_p >= s.bf->code_size) { s_failure(&s, "jump out of file"); } if (UNBOX(s_pop_i()) != 0) { - s.ip = bf->code_ptr + jmp_p; + s.ip = s.bf->code_ptr + jmp_p; } break; } @@ -273,8 +281,8 @@ void run(bytefile *bf, int argc, char **argv) { if (s.fp != NULL && s.call_ip == NULL) { s_failure(&s, "begin should only be called after call"); } - s_enter_f(s.call_ip /*ip from call*/, s.is_closure_call, args_sz, - locals_sz); + s_enter_f(s.call_ip /*ip from call*/, s.call_module_id, + s.is_closure_call, args_sz, locals_sz); break; } @@ -285,8 +293,8 @@ void run(bytefile *bf, int argc, char **argv) { if (s.fp != NULL && s.call_ip == NULL) { s_failure(&s, "begin should only be called after call"); } - s_enter_f(s.call_ip /*ip from call*/, s.is_closure_call, args_sz, - locals_sz); + s_enter_f(s.call_ip /*ip from call*/, s.call_module_id, + s.is_closure_call, args_sz, locals_sz); break; } @@ -302,10 +310,10 @@ void run(bytefile *bf, int argc, char **argv) { var_by_category(to_var_category(l), ip_read_int(&s.ip)); s_push(*var_ptr); } - if (call_offset >= bf->code_size) { + if (call_offset >= s.bf->code_size) { s_failure(&s, "jump out of file"); } - s_push(bf->code_ptr + call_offset); + s_push(s.bf->code_ptr + call_offset); void *closure = Bclosure((aint *)__gc_stack_top, args_count); @@ -320,6 +328,7 @@ void run(bytefile *bf, int argc, char **argv) { call_happened = true; s.is_closure_call = true; s.call_ip = s.ip; + s.call_module_id = s.current_module_id; s.ip = Belem(*s_nth(args_count), BOX(0)); // use offset instead ?? break; @@ -332,11 +341,12 @@ void run(bytefile *bf, int argc, char **argv) { call_happened = true; s.is_closure_call = false; s.call_ip = s.ip; + s.call_module_id = s.current_module_id; - if (call_p >= bf->code_size) { + if (call_p >= s.bf->code_size) { s_failure(&s, "jump out of file"); } - s.ip = bf->code_ptr + call_p; + s.ip = s.bf->code_ptr + call_p; break; } @@ -370,19 +380,27 @@ void run(bytefile *bf, int argc, char **argv) { break; case CMD_CTRL_CALLF: { // CALLF %s %d // call external function - const char* call_func = ip_read_string(&s.ip); + const char *call_func_name = ip_read_string(&s.ip); ip_read_int(&s.ip); // args count // TODO: jump to other module, save ret module + struct ModSearchResult func = mod_search_pub_symbol(call_func_name); + if (func.mod_file == NULL) { + s_failure(&s, "external function not found"); + } - // call_happened = true; - // s.is_closure_call = false; - // s.call_ip = s.ip; + call_happened = true; + s.is_closure_call = false; + s.call_ip = s.ip; + s.call_module_id = s.current_module_id; - // if (call_p >= bf->code_size) { - // s_failure(&s, "jump out of file"); - // } - // s.ip = bf->code_ptr + call_p; + s.current_module_id = func.mod_id; + s.bf = func.mod_file; + + if (func.symbol_offset >= s.bf->code_size) { + s_failure(&s, "jump out of file"); + } + s.ip = s.bf->code_ptr + func.symbol_offset; break; } @@ -452,10 +470,9 @@ void run(bytefile *bf, int argc, char **argv) { } // s_rotate_n(elem_count); - void *array = - Barray((aint *)opr_buffer, - BOX(elem_count)); // NOTE: not shure if elems should be - // added + void *array = Barray((aint *)opr_buffer, + BOX(elem_count)); // NOTE: not shure if elems + // should be added // void *array = Barray((aint *)s_peek(), BOX(elem_count)); s_push(array); @@ -474,6 +491,7 @@ void run(bytefile *bf, int argc, char **argv) { if (!call_happened) { s.is_closure_call = false; s.call_ip = NULL; + s.call_module_id = 0; } if (s.fp == NULL) { diff --git a/byterun/src/module_manager.cpp b/byterun/src/module_manager.cpp index fba0b624e..2044a2dc6 100644 --- a/byterun/src/module_manager.cpp +++ b/byterun/src/module_manager.cpp @@ -1,3 +1,4 @@ +#include extern "C" { #include "module_manager.h" #include "parser.h" @@ -23,8 +24,8 @@ struct ModuleManager { static ModuleManager manager; -uint32_t path_mod_load(const char *name, std::filesystem::path &&path) { - bytefile *module = read_file(path.c_str()); +uint32_t mod_add_impl(bytefile *module, + std::optional name = std::nullopt) { uint32_t id = manager.modules.size(); manager.modules.push_back(module); for (size_t i = 0; i < module->public_symbols_number; ++i) { @@ -37,9 +38,16 @@ uint32_t path_mod_load(const char *name, std::filesystem::path &&path) { failure("public symbol loaded more then once\n"); } } - manager.loaded_modules.insert({name, id}); + if (name) { + manager.loaded_modules.insert({*name, id}); + } return id; } + +uint32_t path_mod_load(const char *name, std::filesystem::path &&path) { + bytefile *module = read_file(path.c_str()); + return mod_add_impl(module, name); +} extern "C" { void mod_add_search_path(const char *path) { @@ -85,14 +93,16 @@ int32_t mod_load(const char *name) { return -1; } +uint32_t mod_add(bytefile *module) { return mod_add_impl(module); } + ModSearchResult mod_search_pub_symbol(const char *name) { auto it = manager.public_symbols_mods.find(name); if (it == manager.public_symbols_mods.end()) { - return {.symbol_offset = -1, .mod_id = 0, .mod_file = nullptr}; + return {.symbol_offset = 0, .mod_id = 0, .mod_file = NULL}; } return { - .symbol_offset = (int32_t)it->second.offset, + .symbol_offset = it->second.offset, .mod_id = it->second.mod_id, .mod_file = mod_get(it->second.mod_id), }; diff --git a/byterun/src/parser.c b/byterun/src/parser.c index 02c9ad4dc..658090f06 100644 --- a/byterun/src/parser.c +++ b/byterun/src/parser.c @@ -65,7 +65,10 @@ bytefile* read_file (const char *fname) { file->imports_ptr = (int*) file->buffer; file->public_ptr = (int*) (file->buffer + imports_size); file->code_ptr = &file->string_ptr [file->stringtab_size]; - file->global_ptr = (int*) calloc (file->global_area_size, sizeof (int)); + + // is allocated on module run on stack + file->global_ptr = NULL; + // file->global_ptr = (int*) calloc (file->global_area_size, sizeof (int)); file->code_size = size - strings_buffer_offset - file->stringtab_size; diff --git a/byterun/src/types.c b/byterun/src/types.c index b6772142c..b1c211ba4 100644 --- a/byterun/src/types.c +++ b/byterun/src/types.c @@ -1,5 +1,6 @@ #include "types.h" +#include "module_manager.h" #include "stack.h" #include "utils.h" #include "parser.h" @@ -11,12 +12,14 @@ extern size_t __gc_stack_top, __gc_stack_bottom; // --- State --- -static void init_state(bytefile *bf, struct State* s, void** stack) { +static void init_state(uint mod_id, struct State* s, void** stack) { s->stack = stack; - s->bf = bf; + s->bf = mod_get(mod_id); s->is_closure_call = false; - s->ip = bf->code_ptr; - s->instr_ip = bf->code_ptr; + s->current_module_id = mod_id; + s->call_module_id = 0; // TODO: ?? + s->ip = s->bf->code_ptr; + s->instr_ip = s->bf->code_ptr; s->call_ip = NULL; s->current_line = 0; @@ -30,13 +33,14 @@ static void init_state(bytefile *bf, struct State* s, void** stack) { s->fp = NULL; } -void construct_state(bytefile *bf, struct State* s, void** stack) { +void construct_state(uint mod_id, struct State* s, void** stack) { __init(); - init_state(bf, s, stack); + init_state(mod_id, s, stack); __gc_stack_bottom = (size_t)(s->stack + STACK_SIZE); __gc_stack_top = __gc_stack_bottom; - s_pushn_nil(bf->global_area_size); + s_pushn_nil(s->bf->global_area_size); // TODO: move to run, do for each module + s->bf->global_ptr = (void*)__gc_stack_top; #ifdef DEBUG_VERSION print_stack(s);