part of multimodule execution impl in interpreter: frame extension, state exstension, call and return

This commit is contained in:
ProgramSnail 2024-11-29 23:11:46 +03:00
parent 0a26953318
commit 59f3dfb43e
9 changed files with 108 additions and 59 deletions

View file

@ -2,4 +2,4 @@
#include "parser.h" #include "parser.h"
void run(bytefile *bf, int argc, char **argv); void run(uint mod_id, int argc, char **argv);

View file

@ -5,9 +5,9 @@
#include "utils.h" #include "utils.h"
struct ModSearchResult { struct ModSearchResult {
ssize_t symbol_offset; // < 0 => not found size_t symbol_offset;
uint32_t mod_id; uint32_t mod_id;
bytefile *mod_file; bytefile *mod_file; // = NULL => not found
}; };
void mod_add_search_path(const char *path); 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 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); struct ModSearchResult mod_search_pub_symbol(const char *name);

View file

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "../../runtime/gc.h" #include "../../runtime/gc.h"
#include "module_manager.h"
#include "runtime_externs.h" #include "runtime_externs.h"
#include "types.h" #include "types.h"
#include "utils.h" #include "utils.h"
@ -134,14 +135,14 @@ static inline void s_rotate_n(size_t n) {
// ------ functions ------ // ------ functions ------
// |> param_0 ... param_n | frame[ ret rp prev_fp &params &locals &end // |> param_0 ... param_n | frame[ ret rp prev_fp ... &params &locals &end
// ] // ]
// |> local_0 ... local_m |> | ... // |> local_0 ... local_m |> | ...
// //
// where |> defines corresponding frame pointer, | is stack pointer // where |> defines corresponding frame pointer, | is stack pointer
// location before / after new frame added // location before / after new frame added
static inline void s_enter_f(char *rp, bool is_closure_call, auint args_sz, static inline void s_enter_f(char *rp, aint ret_module_id, bool is_closure_call,
auint locals_sz) { auint args_sz, auint locals_sz) {
#ifdef DEBUG_VERSION #ifdef DEBUG_VERSION
printf("-> %i args sz\n", args_sz); printf("-> %i args sz\n", args_sz);
printf("-> %i locals sz\n", locals_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 .ret = NULL, // field in frame itself
.rp = rp, .rp = rp,
.prev_fp = (void **)s.fp, .prev_fp = (void **)s.fp,
.ret_module_box = BOX(ret_module_id),
.args_sz_box = BOX(args_sz), .args_sz_box = BOX(args_sz),
.locals_sz_box = BOX(locals_sz), .locals_sz_box = BOX(locals_sz),
}; };
@ -207,6 +209,10 @@ static inline void s_exit_f() {
} }
s.ip = frame.rp; 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() { static inline void print_stack() {

View file

@ -22,13 +22,14 @@ static const size_t MAX_ARRAY_SIZE = 0x11111110;
// ------ Frame ------ // ------ Frame ------
struct Frame { struct Frame {
void *closure; // where closure value stored if needed void *closure; // where closure value stored if needed
void *ret; // store returned value [gc pointer] void *ret; // store returned value [gc pointer]
char *rp; // ret instruction pointer [not gc pointer] char *rp; // ret instruction pointer [not gc pointer]
void **prev_fp; // ret function frame pointer [boxed value, not gc void **prev_fp; // ret function frame pointer [boxed value, not gc
// pointer] // pointer]
aint args_sz_box; // store arguments [boxed value, not gc pointer] aint ret_module_box; // module to return [boxed value, not gc pointer]
aint locals_sz_box; // store locals [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] // NOTE: stack is [top -> bottom]
@ -60,14 +61,18 @@ struct State {
bool is_closure_call; bool is_closure_call;
uint current_module_id;
uint call_module_id;
char *ip; // instruction pointer char *ip; // instruction pointer
char *instr_ip; // poiter to current instruction char *instr_ip; // poiter to current instruction
char *call_ip; // prev instruction pointer (to remember jmp locations) 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); void cleanup_state(struct State *state);
// TODO: print current mod id
static inline void s_failure(struct State *s, const char *msg) { static inline void s_failure(struct State *s, const char *msg) {
exec_failure(read_cmd(s->instr_ip), s->current_line, exec_failure(read_cmd(s->instr_ip), s->current_line,
s->instr_ip - s->bf->code_ptr, msg); s->instr_ip - s->bf->code_ptr, msg);

View file

@ -1,4 +1,5 @@
#include "interpreter.h" #include "interpreter.h"
#include "module_manager.h"
#include "parser.h" #include "parser.h"
#include "utils.h" #include "utils.h"
#include "../../runtime/runtime.h" #include "../../runtime/runtime.h"
@ -9,15 +10,15 @@ int main(int argc, char** argv) {
} }
bytefile *f = read_file(argv[2]); bytefile *f = read_file(argv[2]);
uint main_mod_id = mod_add(f);
if (strcmp(argv[1], "-i") == 0) { 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) { } else if (strcmp(argv[1], "-p") == 0) {
dump_file (stdout, f); dump_file (stdout, f);
} else { } else {
failure("undefined execution mode. Execution mode should be -i (interpret) or -p (print)\n"); failure("undefined execution mode. Execution mode should be -i (interpret) or -p (print)\n");
} }
free(f->global_ptr);
free(f); free(f);
return 0; return 0;

View file

@ -3,6 +3,7 @@
#include "../../runtime/gc.h" #include "../../runtime/gc.h"
#include "../../runtime/runtime.h" #include "../../runtime/runtime.h"
#include "module_manager.h"
#include "runtime_externs.h" #include "runtime_externs.h"
#include "stack.h" #include "stack.h"
#include "types.h" #include "types.h"
@ -37,10 +38,17 @@ static inline const char *ip_read_string(char **ip) {
const size_t BUFFER_SIZE = 1000; 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]; size_t stack[STACK_SIZE];
void *buffer[BUFFER_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 #ifdef DEBUG_VERSION
printf("--- interpreter run ---\n"); printf("--- interpreter run ---\n");
@ -65,11 +73,11 @@ void run(bytefile *bf, int argc, char **argv) {
do { do {
bool call_happened = false; 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)"); 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)"); 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 case CMD_BASIC_JMP: { // JMP 0x%.8x
uint jmp_p = ip_read_int(&s.ip); 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_failure(&s, "jump out of file");
} }
s.ip = bf->code_ptr + jmp_p; s.ip = s.bf->code_ptr + jmp_p;
break; break;
} }
@ -246,11 +254,11 @@ void run(bytefile *bf, int argc, char **argv) {
case CMD_CTRL_CJMPz: { // CJMPz 0x%.8x case CMD_CTRL_CJMPz: { // CJMPz 0x%.8x
uint jmp_p = ip_read_int(&s.ip); 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_failure(&s, "jump out of file");
} }
if (UNBOX(s_pop_i()) == 0) { if (UNBOX(s_pop_i()) == 0) {
s.ip = bf->code_ptr + jmp_p; s.ip = s.bf->code_ptr + jmp_p;
} }
break; break;
} }
@ -258,11 +266,11 @@ void run(bytefile *bf, int argc, char **argv) {
case CMD_CTRL_CJMPnz: { // CJMPnz 0x%.8x case CMD_CTRL_CJMPnz: { // CJMPnz 0x%.8x
uint jmp_p = ip_read_int(&s.ip); 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_failure(&s, "jump out of file");
} }
if (UNBOX(s_pop_i()) != 0) { if (UNBOX(s_pop_i()) != 0) {
s.ip = bf->code_ptr + jmp_p; s.ip = s.bf->code_ptr + jmp_p;
} }
break; break;
} }
@ -273,8 +281,8 @@ void run(bytefile *bf, int argc, char **argv) {
if (s.fp != NULL && s.call_ip == NULL) { if (s.fp != NULL && s.call_ip == NULL) {
s_failure(&s, "begin should only be called after call"); 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, s_enter_f(s.call_ip /*ip from call*/, s.call_module_id,
locals_sz); s.is_closure_call, args_sz, locals_sz);
break; break;
} }
@ -285,8 +293,8 @@ void run(bytefile *bf, int argc, char **argv) {
if (s.fp != NULL && s.call_ip == NULL) { if (s.fp != NULL && s.call_ip == NULL) {
s_failure(&s, "begin should only be called after call"); 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, s_enter_f(s.call_ip /*ip from call*/, s.call_module_id,
locals_sz); s.is_closure_call, args_sz, locals_sz);
break; 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)); var_by_category(to_var_category(l), ip_read_int(&s.ip));
s_push(*var_ptr); 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_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); void *closure = Bclosure((aint *)__gc_stack_top, args_count);
@ -320,6 +328,7 @@ void run(bytefile *bf, int argc, char **argv) {
call_happened = true; call_happened = true;
s.is_closure_call = true; s.is_closure_call = true;
s.call_ip = s.ip; 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 ?? s.ip = Belem(*s_nth(args_count), BOX(0)); // use offset instead ??
break; break;
@ -332,11 +341,12 @@ void run(bytefile *bf, int argc, char **argv) {
call_happened = true; call_happened = true;
s.is_closure_call = false; s.is_closure_call = false;
s.call_ip = s.ip; 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_failure(&s, "jump out of file");
} }
s.ip = bf->code_ptr + call_p; s.ip = s.bf->code_ptr + call_p;
break; break;
} }
@ -370,19 +380,27 @@ void run(bytefile *bf, int argc, char **argv) {
break; break;
case CMD_CTRL_CALLF: { // CALLF %s %d // call external function 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 ip_read_int(&s.ip); // args count
// TODO: jump to other module, save ret module // 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; call_happened = true;
// s.is_closure_call = false; s.is_closure_call = false;
// s.call_ip = s.ip; s.call_ip = s.ip;
s.call_module_id = s.current_module_id;
// if (call_p >= bf->code_size) { s.current_module_id = func.mod_id;
// s_failure(&s, "jump out of file"); s.bf = func.mod_file;
// }
// s.ip = bf->code_ptr + call_p; 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; break;
} }
@ -452,10 +470,9 @@ void run(bytefile *bf, int argc, char **argv) {
} }
// s_rotate_n(elem_count); // s_rotate_n(elem_count);
void *array = void *array = Barray((aint *)opr_buffer,
Barray((aint *)opr_buffer, BOX(elem_count)); // NOTE: not shure if elems
BOX(elem_count)); // NOTE: not shure if elems should be // should be added
// added
// void *array = Barray((aint *)s_peek(), BOX(elem_count)); // void *array = Barray((aint *)s_peek(), BOX(elem_count));
s_push(array); s_push(array);
@ -474,6 +491,7 @@ void run(bytefile *bf, int argc, char **argv) {
if (!call_happened) { if (!call_happened) {
s.is_closure_call = false; s.is_closure_call = false;
s.call_ip = NULL; s.call_ip = NULL;
s.call_module_id = 0;
} }
if (s.fp == NULL) { if (s.fp == NULL) {

View file

@ -1,3 +1,4 @@
#include <optional>
extern "C" { extern "C" {
#include "module_manager.h" #include "module_manager.h"
#include "parser.h" #include "parser.h"
@ -23,8 +24,8 @@ struct ModuleManager {
static ModuleManager manager; static ModuleManager manager;
uint32_t path_mod_load(const char *name, std::filesystem::path &&path) { uint32_t mod_add_impl(bytefile *module,
bytefile *module = read_file(path.c_str()); std::optional<const char *> name = std::nullopt) {
uint32_t id = manager.modules.size(); uint32_t id = manager.modules.size();
manager.modules.push_back(module); manager.modules.push_back(module);
for (size_t i = 0; i < module->public_symbols_number; ++i) { 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"); failure("public symbol loaded more then once\n");
} }
} }
manager.loaded_modules.insert({name, id}); if (name) {
manager.loaded_modules.insert({*name, id});
}
return 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" { extern "C" {
void mod_add_search_path(const char *path) { void mod_add_search_path(const char *path) {
@ -85,14 +93,16 @@ int32_t mod_load(const char *name) {
return -1; return -1;
} }
uint32_t mod_add(bytefile *module) { return mod_add_impl(module); }
ModSearchResult mod_search_pub_symbol(const char *name) { ModSearchResult mod_search_pub_symbol(const char *name) {
auto it = manager.public_symbols_mods.find(name); auto it = manager.public_symbols_mods.find(name);
if (it == manager.public_symbols_mods.end()) { 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 { return {
.symbol_offset = (int32_t)it->second.offset, .symbol_offset = it->second.offset,
.mod_id = it->second.mod_id, .mod_id = it->second.mod_id,
.mod_file = mod_get(it->second.mod_id), .mod_file = mod_get(it->second.mod_id),
}; };

View file

@ -65,7 +65,10 @@ bytefile* read_file (const char *fname) {
file->imports_ptr = (int*) file->buffer; file->imports_ptr = (int*) file->buffer;
file->public_ptr = (int*) (file->buffer + imports_size); file->public_ptr = (int*) (file->buffer + imports_size);
file->code_ptr = &file->string_ptr [file->stringtab_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; file->code_size = size - strings_buffer_offset - file->stringtab_size;

View file

@ -1,5 +1,6 @@
#include "types.h" #include "types.h"
#include "module_manager.h"
#include "stack.h" #include "stack.h"
#include "utils.h" #include "utils.h"
#include "parser.h" #include "parser.h"
@ -11,12 +12,14 @@ extern size_t __gc_stack_top, __gc_stack_bottom;
// --- State --- // --- 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->stack = stack;
s->bf = bf; s->bf = mod_get(mod_id);
s->is_closure_call = false; s->is_closure_call = false;
s->ip = bf->code_ptr; s->current_module_id = mod_id;
s->instr_ip = bf->code_ptr; s->call_module_id = 0; // TODO: ??
s->ip = s->bf->code_ptr;
s->instr_ip = s->bf->code_ptr;
s->call_ip = NULL; s->call_ip = NULL;
s->current_line = 0; s->current_line = 0;
@ -30,13 +33,14 @@ static void init_state(bytefile *bf, struct State* s, void** stack) {
s->fp = NULL; 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();
init_state(bf, s, stack); init_state(mod_id, s, stack);
__gc_stack_bottom = (size_t)(s->stack + STACK_SIZE); __gc_stack_bottom = (size_t)(s->stack + STACK_SIZE);
__gc_stack_top = __gc_stack_bottom; __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 #ifdef DEBUG_VERSION
print_stack(s); print_stack(s);