modules: 'rebase' from byterun_with_modules, initial impl, without verification

This commit is contained in:
ProgramSnail 2025-01-08 23:52:39 +03:00
parent 73d3fbc388
commit eb1ddfa447
14 changed files with 420 additions and 115 deletions

View file

@ -5,26 +5,13 @@
(:main src/cli.cpp)
(:parser src/parser.cpp)
(:analyzer src/analyzer.cpp)
(:module_manager module_manager.o)
(:obj types.o interpreter.o)
(:runtime ../runtime/runtime.a))
(mode
(promote (until-clean)))
(action
(run g++ -std=c++20 -DWITH_CHECK -Iinclude/ %{main} %{parser} %{analyzer} %{runtime} %{obj} -o %{target})))
(rule
(target old_byterun.exe)
(deps
(:include (source_tree include))
(:main src/cli.cpp)
(:parser src/parser.cpp)
(:analyzer src/analyzer.cpp)
(:obj old_types.o old_interpreter.o)
(:runtime ../runtime/runtime.a))
(mode
(promote (until-clean)))
(action
(run g++ -std=c++20 -Iinclude/ %{main} %{parser} %{analyzer} %{runtime} %{obj} -o %{target})))
(run g++ -std=c++20 -DWITH_CHECK -Iinclude/ %{main} %{parser} %{analyzer} %{module_manager} %{runtime} %{obj} -o %{target})))
(rule
(target types.o)
@ -49,23 +36,12 @@
(run gcc -Iinclude/ -DWITH_CHECK -c %{src} -o %{target})))
(rule
(target old_types.o)
(target module_manager.o)
(deps
(:include (source_tree include))
(:src src/types.c)
(:src src/module_manager.cpp)
(:runtime ../runtime/runtime.a))
(mode
(promote (until-clean)))
(action
(run gcc -Iinclude/ -c %{src} -o %{target})))
(rule
(target old_interpreter.o)
(deps
(:include (source_tree include))
(:src src/interpreter.c)
(:runtime ../runtime/runtime.a))
(mode
(promote (until-clean)))
(action
(run gcc -Iinclude/ -c %{src} -o %{target})))
(run g++ -Iinclude/ -c %{src} -o %{target})))

View file

@ -2,4 +2,14 @@
#include "utils.h"
void run(Bytefile *bf, int argc, char **argv);
// void run(Bytefile *bf, int argc, char **argv);
void run_init(size_t *stack);
void run_mod_rec(uint mod_id, int argc, char **argv);
void run_prepare_exec(int argc, char **argv);
void run_mod(uint mod_id, int argc, char **argv);
void run_cleanup();

View file

@ -0,0 +1,23 @@
#pragma once
#include <stdint.h>
#include "utils.h"
struct ModSearchResult {
size_t symbol_offset;
uint32_t mod_id;
Bytefile *mod_file; // = NULL => not found
};
void mod_add_search_path(const char *path);
Bytefile *mod_get(uint32_t id);
int32_t find_mod_loaded(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);

View file

@ -35,6 +35,7 @@ enum class Cmd : int8_t {
ARRAY,
FAIL,
LINE,
CALLF,
PATT,
Lread,
Lwrite,

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"
@ -148,14 +149,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);
@ -186,6 +187,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),
};
@ -226,6 +228,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

@ -27,6 +27,7 @@ struct Frame {
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]
};
@ -60,14 +61,20 @@ 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 init_state(struct State *s, void **stack);
void init_mod_state(uint mod_id, struct State *s);
void init_mod_state_globals(struct State *s);
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->bf), s->current_line,
s->instr_ip - s->bf->code_ptr, msg);
@ -154,6 +161,7 @@ enum CMD_CTRLS {
CMD_CTRL_ARRAY,
CMD_CTRL_FAIL,
CMD_CTRL_LINE,
CMD_CTRL_CALLF,
};
enum CMD_PATTS {

View file

@ -10,12 +10,14 @@
/* The unpacked representation of bytecode file */
typedef struct {
char *string_ptr; /* A pointer to the beginning of the string table */
int *imports_ptr; /* A pointer to the beginning of imports table */
int *public_ptr; /* A pointer to the beginning of publics table */
char *code_ptr; /* A pointer to the bytecode itself */
int *global_ptr; /* A pointer to the global area */
int code_size; /* The size (in bytes) of code */
uint stringtab_size; /* The size (in bytes) of the string table */
uint global_area_size; /* The size (in words) of global area */
uint imports_number; /* The number of imports */
uint public_symbols_number; /* The number of public symbols */
char buffer[0];
} Bytefile;
@ -35,6 +37,14 @@ static inline const char *get_string_unsafe(const Bytefile *bf, size_t pos) {
return &bf->string_ptr[pos];
}
/* Gets import */
static inline const char *get_import_unsafe(const Bytefile *f, size_t i) {
if (i >= f->imports_number) {
failure("import pos is out of range: %zu >= %i\n", i, f->imports_number);
}
return get_string_unsafe(f, f->imports_ptr[i]);
}
/* Gets a name offset for a public symbol */
static inline size_t get_public_name_offset_unsafe(const Bytefile *bf,
size_t i) {
@ -80,6 +90,14 @@ static inline const char *get_string_safe(const Bytefile *f, size_t pos) {
return get_string_unsafe(f, pos);
}
/* Gets import */
static inline const char *get_import_safe(const Bytefile *f, size_t i) {
if (i >= f->imports_number) {
failure("import pos is out of range: %zu >= %i\n", i, f->imports_number);
}
return get_string_safe(f, f->imports_ptr[i]);
}
/* Gets a name offset for a public symbol */
static inline size_t get_public_name_offset_safe(const Bytefile *f, size_t i) {
if (i >= f->public_symbols_number) {

View file

@ -315,6 +315,9 @@ void analyze(Bytefile *bf) {
break;
case Cmd::LINE:
break;
case Cmd::CALLF: // FIXME TODO
ip_failure(saved_current_ip, bf, "CALLF analysis is not implemented yet");
break;
case Cmd::PATT:
--current_stack_depth;
if (l == CMD_PATT_STR) {

View file

@ -6,7 +6,9 @@
extern "C" {
#include "../../runtime/runtime.h"
#include "interpreter.h"
#include "module_manager.h"
#include "parser.h"
#include "types.h"
#include "utils.h"
}
@ -40,9 +42,6 @@ int main(int argc, char **argv) {
}
Bytefile *f = read_file(argv[2]);
#ifdef DEBUG_VERSION
dump_file(stdout, f);
#endif
if (do_print) {
print_file(*f, std::cout);
}
@ -50,12 +49,19 @@ int main(int argc, char **argv) {
analyze(f);
}
if (do_interpretation) {
run(f, argc - 2, argv + 2);
// TODO FIXME: add all loaded modules verification
size_t stack[STACK_SIZE];
run_init(stack);
uint main_mod_id = mod_add(f);
run_mod_rec(main_mod_id, argc - 1, argv + 1);
}
// TODO: remove, before modules
// // NOTE: not used for now
// // free(f->global_ptr);
free(f);
// 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"
@ -53,17 +54,11 @@ static inline const char *ip_read_string(char **ip) {
const size_t BUFFER_SIZE = 1000;
void run(Bytefile *bf, int argc, char **argv) {
size_t stack[STACK_SIZE];
void *buffer[BUFFER_SIZE];
construct_state(bf, &s, (void **)stack);
void run_init(size_t *stack) {
init_state(&s, (void**)stack);
}
#ifdef DEBUG_VERSION
printf("--- interpreter run ---\n");
#endif
// argc, argv
{
void run_prepare_exec(int argc, char **argv) {
s_push_i(BOX(argc));
for (size_t i = 0; i < argc; ++i) {
s_push(Bstring((aint *)&argv[argc - i - 1]));
@ -74,19 +69,48 @@ void run(Bytefile *bf, int argc, char **argv) {
s_push(argv_elem);
}
// TODO: use unsafe, move checks to verifier (?)
void run_mod_rec(uint mod_id, int argc, char **argv) {
Bytefile* mod = mod_get(mod_id); // TODO: pass as param ??
for (size_t i = 0; i < mod->imports_number; ++i) {
if (find_mod_loaded(get_import_safe(mod, i)) < 0 && strcmp(get_import_safe(mod, i), "Std") != 0) { // not loaded
int32_t import_mod = mod_load(get_import_safe(mod, i));
if (import_mod < 0) {
failure("module %s not found\n", get_import_safe(mod, i));
}
run_mod_rec(mod_id, argc, argv);
}
}
init_mod_state(mod_id, &s);
init_mod_state_globals(&s);
run_prepare_exec(argc, argv); // args for module main
run_mod(mod_id, argc, argv);
}
void run_mod(uint mod_id, int argc, char **argv) {
#ifdef DEBUG_VERSION
printf("- loop start\n");
printf("--- module init state ---\n");
#endif
init_mod_state(mod_id, &s);
void *buffer[BUFFER_SIZE];
#ifdef DEBUG_VERSION
printf("--- module run begin ---\n");
#endif
do {
bool call_happened = false;
#ifndef WITH_CHECK
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)");
}
#endif
@ -94,9 +118,9 @@ void run(Bytefile *bf, int argc, char **argv) {
s.instr_ip = s.ip;
uint8_t x = ip_read_byte(&s.ip), h = (x & 0xF0) >> 4, l = x & 0x0F;
// #ifdef DEBUG_VERSION
printf("0x%.8x: %s\n", s.ip - bf->code_ptr - 1, read_cmd(s.ip - 1, s.bf));
// #endif
#ifdef DEBUG_VERSION
printf("0x%.8x: %s\n", s.ip - s.bf->code_ptr - 1, read_cmd(s.ip - 1, s.bf));
#endif
switch (h) {
case CMD_EXIT:
@ -193,11 +217,11 @@ void run(Bytefile *bf, int argc, char **argv) {
uint jmp_p = ip_read_int(&s.ip);
#ifndef WITH_CHECK
if (jmp_p >= bf->code_size) {
if (jmp_p >= s.bf->code_size) {
s_failure(&s, "jump out of file");
}
#endif
s.ip = bf->code_ptr + jmp_p;
s.ip = s.bf->code_ptr + jmp_p;
break;
}
@ -270,12 +294,12 @@ void run(Bytefile *bf, int argc, char **argv) {
uint jmp_p = ip_read_int(&s.ip);
#ifndef WITH_CHECK
if (jmp_p >= bf->code_size) {
if (jmp_p >= s.bf->code_size) {
s_failure(&s, "jump out of file");
}
#endif
if (UNBOX(s_pop_i()) == 0) {
s.ip = bf->code_ptr + jmp_p;
s.ip = s.bf->code_ptr + jmp_p;
}
break;
}
@ -284,12 +308,12 @@ void run(Bytefile *bf, int argc, char **argv) {
uint jmp_p = ip_read_int(&s.ip);
#ifndef WITH_CHECK
if (jmp_p >= bf->code_size) {
if (jmp_p >= s.bf->code_size) {
s_failure(&s, "jump out of file");
}
#endif
if (UNBOX(s_pop_i()) != 0) {
s.ip = bf->code_ptr + jmp_p;
s.ip = s.bf->code_ptr + jmp_p;
}
break;
}
@ -307,8 +331,8 @@ void run(Bytefile *bf, int argc, char **argv) {
s_failure(&s, "begin should only be called after call");
}
#endif
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);
#ifndef WITH_CHECK
if ((void **)__gc_stack_top + (aint)max_additional_stack_sz - 1 <= s.stack) {
s_failure(&s, "stack owerflow");
@ -331,8 +355,8 @@ void run(Bytefile *bf, int argc, char **argv) {
s_failure(&s, "begin should only be called after call");
}
#endif
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);
#ifdef WITH_CHECK
if ((void **)__gc_stack_top + (aint)max_additional_stack_sz - 1 <= s.stack) {
s_failure(&s, "stack owerflow");
@ -354,11 +378,11 @@ void run(Bytefile *bf, int argc, char **argv) {
s_push(*var_ptr);
}
#ifndef WITH_CHECK
if (call_offset >= bf->code_size) {
if (call_offset >= s.bf->code_size) {
s_failure(&s, "jump out of file");
}
#endif
s_push(bf->code_ptr + call_offset);
s_push(s.bf->code_ptr + call_offset);
void *closure = Bclosure((aint *)__gc_stack_top, BOX(args_count));
// printf("args is %li, count is %li\n", args_count, get_len(TO_DATA(closure)));
@ -374,6 +398,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 = (char*)Belem(*s_nth(args_count), BOX(0)); // use offset instead ??
break;
@ -386,13 +411,14 @@ 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;
#ifndef WITH_CHECK
if (call_p >= bf->code_size) {
if (call_p >= s.bf->code_size) {
s_failure(&s, "jump out of file");
}
#endif
s.ip = bf->code_ptr + call_p;
s.ip = s.bf->code_ptr + call_p;
break;
}
@ -425,6 +451,31 @@ void run(Bytefile *bf, int argc, char **argv) {
// maybe some metainfo should be collected
break;
case CMD_CTRL_CALLF: { // CALLF %s %d // call external function
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;
s.call_module_id = s.current_module_id;
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;
}
default:
s_failure(&s, "invalid opcode"); // %d-%d\n", h, l);
}
@ -493,7 +544,7 @@ 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
BOX(elem_count)); // NOTE: not sure if elems should be
// added
// void *array = Barray((aint *)s_peek(), BOX(elem_count));
@ -513,6 +564,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) {
@ -524,7 +576,8 @@ void run(Bytefile *bf, int argc, char **argv) {
} while (1);
stop:;
#ifdef DEBUG_VERSION
printf("--- run end ---\n");
printf("--- module run end ---\n");
#endif
cleanup_state(&s);
}
void run_cleanup() { cleanup_state(&s); }

View file

@ -0,0 +1,113 @@
extern "C" {
#include "module_manager.h"
#include "utils.h"
}
#include "parser.hpp"
#include <filesystem>
#include <optional>
#include <string>
#include <unordered_map>
#include <vector>
struct ModSymbolPos {
uint32_t mod_id;
size_t offset;
};
struct ModuleManager {
std::unordered_map<std::string, uint32_t> loaded_modules;
std::unordered_map<std::string, ModSymbolPos> public_symbols_mods;
std::vector<Bytefile *> modules;
std::vector<std::filesystem::path> search_paths;
};
static ModuleManager manager;
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) {
if (!manager.public_symbols_mods
.insert({
get_public_name_safe(module, i),
{.mod_id = id, .offset = get_public_offset_safe(module, i)},
})
.second) {
failure("public symbol loaded more then once\n");
}
}
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) {
manager.search_paths.emplace_back(path);
}
Bytefile *mod_get(uint32_t id) {
if (id > manager.modules.size()) {
failure("module id is out of range\n");
}
return manager.modules[id];
}
int32_t find_mod_loaded(const char *name) {
auto it = manager.loaded_modules.find(name);
// module already loaded
if (it != manager.loaded_modules.end()) {
return it->second;
}
return -1;
}
int32_t mod_load(const char *name) {
std::string full_name = std::string{name} + ".bc";
auto it = manager.loaded_modules.find(name);
// module already loaded
if (it != manager.loaded_modules.end()) {
return it->second;
}
if (std::filesystem::exists(full_name)) {
return path_mod_load(name, full_name);
}
for (const auto &dir_path : manager.search_paths) {
auto path = dir_path / full_name;
if (std::filesystem::exists(path)) {
return path_mod_load(name, std::move(path));
}
}
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 = 0, .mod_id = 0, .mod_file = NULL};
}
return {
.symbol_offset = it->second.offset,
.mod_id = it->second.mod_id,
.mod_file = mod_get(it->second.mod_id),
};
}
}

View file

@ -52,7 +52,7 @@ Bytefile *read_file(const char *fname) {
}
long size = ftell(f);
long additional_size = sizeof(void *) * 4 + sizeof(int);
long additional_size = sizeof(void *) * 5 + sizeof(int);
file = (Bytefile *)malloc(size +
additional_size); // file itself + additional data
@ -71,10 +71,14 @@ Bytefile *read_file(const char *fname) {
fclose(f);
long imports_size = file->imports_number * sizeof(int);
long public_symbols_size = file->public_symbols_number * 2 * sizeof(int);
if (file->buffer + public_symbols_size >= file_end) {
long strings_buffer_offset = public_symbols_size + imports_size;
if (file->buffer + strings_buffer_offset >= file_end) {
failure("public symbols are out of the file size\n");
}
file->string_ptr =
&file->buffer[strings_buffer_offset]; // TODO: check that should be there
if (file->string_ptr + file->stringtab_size > file_end) {
failure("strings table is out of the file size\n");
}
@ -87,14 +91,13 @@ Bytefile *read_file(const char *fname) {
failure("file zones sizes should be >= 0\n");
}
file->string_ptr = &file->buffer[public_symbols_size];
file->public_ptr = (int *)file->buffer;
file->code_ptr = &file->string_ptr[file->stringtab_size];
// NOTE: not used for now
file->imports_ptr = (int *)file->buffer;
file->public_ptr = (int *)(file->buffer + imports_size);
// is allocated on module run on stack
file->global_ptr = NULL;
// file->global_ptr = (int*) calloc (file->global_area_size, sizeof (int));
file->global_ptr = nullptr;
file->code_size = size - public_symbols_size - file->stringtab_size;
file->code_size = size - strings_buffer_offset - file->stringtab_size;
return file;
}
@ -202,6 +205,8 @@ const char *command_name(Cmd cmd, int8_t l) {
return "FAIL";
case Cmd::LINE:
return "LINE";
case Cmd::CALLF:
return "CALLF";
case Cmd::PATT:
if (l >= sizeof(pats) / sizeof(char *)) {
return "_UNDEF_PATT_";
@ -520,6 +525,11 @@ std::pair<Cmd, uint8_t> parse_command_impl(char **ip, const Bytefile &bf,
read_print_cmd_seq_opt<do_read_args, use_out, ArgT::INT>(cmd, l, ip, bf,
out);
break;
case CMD_CTRL_CALLF: // CALLF %s %d
cmd = Cmd::CALLF;
read_print_cmd_seq_opt<do_read_args, use_out, ArgT::STR, ArgT::INT>(
cmd, l, ip, bf, out);
break;
default:
failure("invalid opcode");
@ -591,12 +601,32 @@ bool is_command_name(char *ip, const Bytefile *bf, Cmd cmd) {
return parse_command_name(&ip, bf).first == cmd;
}
void print_file(const Bytefile &bf, std::ostream &out) {
void print_file_info(const Bytefile &bf, std::ostream &out) {
out << "String table size : " << bf.stringtab_size << '\n';
out << "Global area size : " << bf.global_area_size << '\n';
out << "Number of imports : " << bf.imports_number << '\n';
out << "Number of public symbols: " << bf.public_symbols_number << '\n';
out << "Imports :\n";
for (size_t i = 0; i < bf.imports_number; i++) {
out << " %s\n" << get_import_safe(&bf, i);
}
out << "Public symbols :\n";
for (size_t i = 0; i < bf.public_symbols_number; i++) {
out << " " << std::setfill('0') << std::setw(8) << std::hex
<< get_public_offset_safe(&bf, i) << ": " << std::dec
<< get_public_name_safe(&bf, i);
}
}
void print_file_code(const Bytefile &bf, std::ostream &out) {
char *ip = bf.code_ptr;
while (true) {
out << std::setfill('0') << std::setw(8) << std::hex << ip - bf.code_ptr
<< ": " << std::dec;
out << " " << std::setfill('0') << std::setw(8) << std::hex
<< ip - bf.code_ptr << ": " << std::dec;
const auto [cmd, l] = parse_command(&ip, &bf, out);
out << '\n';
@ -606,6 +636,14 @@ void print_file(const Bytefile &bf, std::ostream &out) {
}
}
void print_file(const Bytefile &bf, std::ostream &out) {
print_file_info(bf, out);
out << "Code:\n";
print_file_code(bf, out);
}
extern "C" {
const char *read_cmd(char *ip, const Bytefile *bf) {
const auto [cmd, l] = parse_command_impl<false, false>(&ip, *bf, std::clog);

View file

@ -11,12 +11,14 @@ extern size_t __gc_stack_top, __gc_stack_bottom;
// --- State ---
static void init_state(Bytefile *bf, struct State* s, void** stack) {
void init_state(struct State* s, void** stack) {
s->stack = stack;
s->bf = bf;
s->bf = NULL;
s->is_closure_call = false;
s->ip = bf->code_ptr;
s->instr_ip = bf->code_ptr;
s->current_module_id = 0;
s->call_module_id = 0;
s->ip = s->bf->code_ptr;
s->instr_ip = s->bf->code_ptr;
s->call_ip = NULL;
s->current_line = 0;
@ -24,26 +26,48 @@ static void init_state(Bytefile *bf, struct State* s, void** stack) {
s->stack[i] = NULL;
}
// printf("%p:%zu - %zu", s->stack, (size_t)s->stack, (size_t)s->stack & 0xF);
// s->sp = s->stack + STACK_SIZE; // [top -> bottom] stack
s->fp = NULL;
}
void construct_state(Bytefile *bf, struct State* s, void** stack) {
__init();
init_state(bf, s, stack);
__gc_stack_bottom = (size_t)(s->stack + STACK_SIZE);
__gc_stack_top = __gc_stack_bottom;
s_pushn_nil(bf->global_area_size);
#ifdef DEBUG_VERSION
print_stack(s);
printf("- state init done\n");
#endif
}
void init_mod_state(uint mod_id, struct State* s) {
// init module data
s->bf = mod_get(mod_id);
s->current_module_id = mod_id;
// clearup from previous executions
s->is_closure_call = false;
s->current_module_id = 0;
s->call_module_id = 0;
s->call_ip = NULL;
s->current_line = 0;
s->fp = NULL;
#ifdef DEBUG_VERSION
print_stack(s);
printf("- mod state init done\n");
#endif
}
void init_mod_state_globals(struct State *s) {
s_pushn_nil(s->bf->global_area_size);
s->bf->global_ptr = (void*)__gc_stack_top;
#ifdef DEBUG_VERSION
print_stack(s);
printf("- state globals init done\n");
#endif
}
static void destruct_state(struct State* state) {
// free(state->stack);

View file

@ -172,15 +172,19 @@ module ByteCode = struct
let code = Buffer.create 256 in
let st = StringTab.create () in
let lmap = Stdlib.ref M.empty in
let externs = Stdlib.ref S.empty in
let pubs = Stdlib.ref S.empty in
let imports = Stdlib.ref S.empty in
let globals = Stdlib.ref M.empty in
let glob_count = Stdlib.ref 0 in
let fixups = Stdlib.ref [] in
let func_fixups = Stdlib.ref [] in
let add_lab l = lmap := M.add l (Buffer.length code) !lmap in
let add_extern l = externs := S.add l !externs in
let add_public l = pubs := S.add l !pubs in
let add_import l = imports := S.add l !imports in
let add_fixup l = fixups := (Buffer.length code, l) :: !fixups in
let add_func_fixup c l = func_fixups := (c, Buffer.length code, l) :: !func_fixups in
let add_bytes = List.iter (fun x -> Buffer.add_char code @@ Char.chr x) in
let add_ints =
List.iter (fun x -> Buffer.add_int32_ne code @@ Int32.of_int x)
@ -302,9 +306,10 @@ module ByteCode = struct
add_ints [ n ]
(* 0x56 l:32 n:32 *)
| CALL (fn, n, _) ->
add_bytes [ (5 * 16) + 6 ];
add_fixup fn;
add_ints [ 0; n ]
(add_bytes [ (5 * 16) + 6 ];
(* TODO: 1 -> sizeof byte ?? *)
add_func_fixup (Buffer.length code - 1) fn;
add_ints [ 0; n ])
(* 0x57 s:32 n:32 *)
| TAG (s, n) ->
add_bytes [ (5 * 16) + 7 ];
@ -324,9 +329,11 @@ module ByteCode = struct
add_ints [ n ]
(* 0x6p *)
| PATT p -> add_bytes [ (6 * 16) + enum patt p ]
| EXTERN _ -> ()
| EXTERN s -> add_extern s
(* TODO: put externs in string table (?), or check that all external funtions are externs *)
| PUBLIC s -> add_public s
| IMPORT s -> add_import s
(* TODO: add imports table before publics *)
| _ ->
failwith
(Printf.sprintf "Unexpected pattern: %s: %d" __FILE__ __LINE__)
@ -334,6 +341,15 @@ module ByteCode = struct
List.iter insn_code insns;
add_bytes [ 255 ];
let code = Buffer.to_bytes code in
List.iter
(fun (cmd_ofs, addr_ofs, l) ->
Bytes.set_int32_ne code addr_ofs
(Int32.of_int
@@
try M.find l !lmap
with Not_found ->
Bytes.set_int8 code cmd_ofs ((5 * 16) + 11); StringTab.add st l))
!func_fixups;
List.iter
(fun (ofs, l) ->
Bytes.set_int32_ne code ofs
@ -343,6 +359,11 @@ module ByteCode = struct
with Not_found ->
failwith (Printf.sprintf "ERROR: undefined label '%s'" l)))
!fixups;
let imports = (* TODO: check *)
List.map (fun l ->
(Int32.of_int @@ StringTab.add st l))
@@ S.elements !imports
in
let pubs =
List.map (fun l ->
( Int32.of_int @@ StringTab.add st l,
@ -357,7 +378,12 @@ module ByteCode = struct
let file = Buffer.create 1024 in
Buffer.add_int32_ne file (Int32.of_int @@ Bytes.length st);
Buffer.add_int32_ne file (Int32.of_int @@ !glob_count);
Buffer.add_int32_ne file (Int32.of_int @@ List.length imports);
Buffer.add_int32_ne file (Int32.of_int @@ List.length pubs);
List.iter
(fun (n) ->
Buffer.add_int32_ne file n)
imports;
List.iter
(fun (n, o) ->
Buffer.add_int32_ne file n;