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"
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"
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);

View file

@ -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 &params &locals &end
// |> param_0 ... param_n | frame[ ret rp prev_fp ... &params &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() {

View file

@ -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);

View file

@ -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;

View file

@ -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) {

View file

@ -1,3 +1,4 @@
#include <optional>
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<const char *> 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),
};

View file

@ -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;

View file

@ -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);