From 58c9fd77c22004e411fbaf5f1dc02b49d56393ee Mon Sep 17 00:00:00 2001 From: ProgramSnail Date: Sun, 2 Mar 2025 15:05:09 +0300 Subject: [PATCH] fix interpreter and analyzer with new algorithm (with bugs) --- byterun/dune | 13 +- byterun/include/analyzer.hpp | 4 +- byterun/include/interpreter.h | 6 +- byterun/include/module_manager.h | 69 +- byterun/include/parser.hpp | 4 +- byterun/include/stack.h | 8 +- byterun/include/types.h | 39 +- byterun/include/utils.h | 19 +- byterun/regression_check.sh | 5 +- byterun/src/analyzer.cpp | 132 +- byterun/src/cli.cpp | 22 +- byterun/src/compiler.cpp | 6 +- byterun/src/interpreter.c | 109 +- byterun/src/module_manager.cpp | 553 +++++-- byterun/src/parser.cpp | 190 +-- byterun/src/types.c | 13 +- byterun/test046 | Bin 0 -> 102736 bytes byterun/test046.i | 1 + byterun/test046.s | 2351 ++++++++++++++++++++++++++++++ byterun/test046.sm | 490 +++++++ byterun/xmake.lua | 14 + 21 files changed, 3489 insertions(+), 559 deletions(-) create mode 100755 byterun/test046 create mode 100644 byterun/test046.i create mode 100644 byterun/test046.s create mode 100644 byterun/test046.sm create mode 100644 byterun/xmake.lua diff --git a/byterun/dune b/byterun/dune index 258b18920..cf8dcb382 100644 --- a/byterun/dune +++ b/byterun/dune @@ -5,7 +5,7 @@ (:main src/cli.cpp) (:parser src/parser.cpp) (:analyzer src/analyzer.cpp) - (:module_manager module_manager.o) + (:module_manager src/module_manager.cpp) (:obj types.o interpreter.o) (:runtime ../runtime/runtime.a)) (mode @@ -34,14 +34,3 @@ (promote (until-clean))) (action (run gcc -Wall -Wextra -Iinclude/ -DWITH_CHECK -c %{src} -o %{target}))) - -(rule -(target module_manager.o) -(deps - (:include (source_tree include)) - (:src src/module_manager.cpp) - (:runtime ../runtime/runtime.a)) - (mode - (promote (until-clean))) - (action - (run g++ -Wall -Wextra -std=c++20 -Iinclude/ -c %{src} -o %{target}))) diff --git a/byterun/include/analyzer.hpp b/byterun/include/analyzer.hpp index 9a2b533a5..a006c5ce7 100644 --- a/byterun/include/analyzer.hpp +++ b/byterun/include/analyzer.hpp @@ -4,4 +4,6 @@ extern "C" { #include "utils.h" } -void analyze(uint32_t mod_id); +#include + +void analyze(Bytefile *bf, std::vector &&add_publics = {}); diff --git a/byterun/include/interpreter.h b/byterun/include/interpreter.h index d270b9f72..cebbb3142 100644 --- a/byterun/include/interpreter.h +++ b/byterun/include/interpreter.h @@ -7,10 +7,8 @@ void run_init(size_t *stack); -void run_mod_rec(uint mod_id, int argc, char **argv, bool do_verification); +void set_argc_argv(int argc, char **argv); -void run_prepare_exec(int argc, char **argv); - -void run_mod(uint mod_id, int argc, char **argv); +void run_main(Bytefile *bf, int argc, char **argv); void run_cleanup(); diff --git a/byterun/include/module_manager.h b/byterun/include/module_manager.h index 22a7c732a..d6e31d036 100644 --- a/byterun/include/module_manager.h +++ b/byterun/include/module_manager.h @@ -5,26 +5,55 @@ #include "utils.h" -struct ModSearchResult { - size_t symbol_offset; - uint32_t mod_id; - Bytefile *mod_file; // = NULL => not found +Bytefile *run_with_imports(Bytefile *root, int argc, char **argv, + bool do_verification); + +// --- + +enum BUILTIN : uint { + BUILTIN_Luppercase, + BUILTIN_Llowercase, + BUILTIN_Lassert, + BUILTIN_Lstring, + BUILTIN_Llength, + BUILTIN_LstringInt, + BUILTIN_Lread, + BUILTIN_Lwrite, + BUILTIN_LmakeArray, + BUILTIN_LmakeString, + BUILTIN_Lstringcat, + BUILTIN_LmatchSubString, + BUILTIN_Lsprintf, + BUILTIN_Lsubstring, + BUILTIN_Li__Infix_4343, // ++ + BUILTIN_Lclone, + BUILTIN_Lhash, + BUILTIN_LtagHash, + BUILTIN_Lcompare, + BUILTIN_LflatCompare, + BUILTIN_Lfst, + BUILTIN_Lsnd, + BUILTIN_Lhd, + BUILTIN_Ltl, + BUILTIN_Lprintf, + BUILTIN_LreadLine, + BUILTIN_Lfopen, + BUILTIN_Lfclose, + BUILTIN_Lfread, + BUILTIN_Lfwrite, + BUILTIN_Lfexists, + BUILTIN_Lfprintf, + BUILTIN_Lregexp, + BUILTIN_LregexpMatch, + BUILTIN_Lfailure, + BUILTIN_Lsystem, + BUILTIN_LgetEnv, + BUILTIN_Lrandom, + BUILTIN_Ltime, + BUILTIN_Barray, // can't be run with run_stdlib_func + BUILTIN_NONE, }; -void mod_cleanup(); +enum BUILTIN id_by_builtin(const char *name); -void mod_add_search_path(const char *path); - -const char *mod_get_name(uint32_t id); - -Bytefile *mod_get(uint32_t id); - -int32_t find_mod_loaded(const char *name); // < 0 => not found - -int32_t mod_load(const char *name, bool do_verification); // < 0 => not found - -uint32_t mod_add(Bytefile *module, bool do_verification); - -struct ModSearchResult mod_search_pub_symbol(const char *name); - -bool run_stdlib_func(const char *name, size_t args_count); +void run_stdlib_func(enum BUILTIN id, size_t args_count); diff --git a/byterun/include/parser.hpp b/byterun/include/parser.hpp index 8bee8adbd..3f63a2ca9 100644 --- a/byterun/include/parser.hpp +++ b/byterun/include/parser.hpp @@ -36,7 +36,7 @@ enum class Cmd : int8_t { ARRAY, FAIL, LINE, - // CALLF, + BUILTIN, PATT, // NOTE: no longer used // Lread, @@ -50,8 +50,6 @@ enum class Cmd : int8_t { Bytefile *read_file(const char *fname); -Bytefile *merge_files(const std::vector &bytefiles); - std::pair parse_command(char **ip, const Bytefile *bf); std::pair parse_command(char **ip, const Bytefile *bf, std::ostream &out); diff --git a/byterun/include/stack.h b/byterun/include/stack.h index 04f1ff05f..005d821c9 100644 --- a/byterun/include/stack.h +++ b/byterun/include/stack.h @@ -155,8 +155,8 @@ static inline void s_rotate_n(size_t n) { // // where |> defines corresponding frame pointer, | is stack pointer // location before / after new frame added -static inline void s_enter_f(char *rp, aint ret_module_id, bool is_closure_call, - auint args_sz, auint locals_sz) { +static inline void s_enter_f(char *rp, 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,7 +186,6 @@ static inline void s_enter_f(char *rp, aint ret_module_id, bool is_closure_call, .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), }; @@ -227,9 +226,6 @@ 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); } static inline void print_stack(struct State *state) { diff --git a/byterun/include/types.h b/byterun/include/types.h index bb4cb3d0c..53315f8c5 100644 --- a/byterun/include/types.h +++ b/byterun/include/types.h @@ -23,14 +23,13 @@ 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 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] + 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] }; // NOTE: stack is [top -> bottom] @@ -62,33 +61,27 @@ 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 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 prepare_state(Bytefile *bf, struct State *s); +void push_globals(struct State *s); void cleanup_state(struct State *state); static inline void s_failure(struct State *s, const char *msg) { - exec_failure(read_cmd(s->instr_ip, s->bf), mod_get_name(s->current_module_id), - s->current_line, s->instr_ip - s->bf->code_ptr, msg); + exec_failure(read_cmd(s->instr_ip, s->bf), s->current_line, + s->instr_ip - s->bf->code_ptr, msg); } -static inline void ip_failure(char *ip, uint32_t mod_id, const char *msg) { - Bytefile *bf = mod_get(mod_id); - exec_failure(read_cmd(ip, bf), mod_get_name(mod_id), 0, ip - bf->code_ptr, - msg); +static inline void ip_failure(char *ip, Bytefile *bf, const char *msg) { + exec_failure(read_cmd(ip, bf), 0, ip - bf->code_ptr, msg); } -static inline void ip_safe_failure(char *ip, uint32_t mod_id, const char *msg) { - Bytefile *bf = mod_get(mod_id); - exec_failure("_UNDEF_", mod_get_name(mod_id), 0, ip - bf->code_ptr, msg); +static inline void ip_safe_failure(char *ip, Bytefile *bf, const char *msg) { + exec_failure("_UNDEF_", 0, ip - bf->code_ptr, msg); } // ------ VarCategory ------ @@ -164,7 +157,7 @@ enum CMD_CTRLS { CMD_CTRL_ARRAY, CMD_CTRL_FAIL, CMD_CTRL_LINE, - // CMD_CTRL_CALLF, + CMD_CTRL_BUILTIN, }; enum CMD_PATTS { diff --git a/byterun/include/utils.h b/byterun/include/utils.h index b201df3a9..4d26b8527 100644 --- a/byterun/include/utils.h +++ b/byterun/include/utils.h @@ -7,11 +7,6 @@ #include "../../runtime/runtime.h" #include "../../runtime/runtime_common.h" -typedef struct { - uint offset; - char label[0]; -} Subst; - /* The unpacked representation of bytecode file */ typedef struct { uint main_offset; /* offset of the function 'main' */ @@ -30,10 +25,10 @@ typedef struct { char buffer[0]; } Bytefile; -static inline void exec_failure(const char *cmd, const char *module_name, - int line, aint offset, const char *msg) { - failure("*** RUNTIME ERROR: %s:%i(0x%.8x):%s error: %s\n", module_name, line, - offset, cmd, msg); +static inline void exec_failure(const char *cmd, int line, aint offset, + const char *msg) { + failure("*** RUNTIME ERROR: %i(0x%.8x):%s error: %s\n", line, offset, cmd, + msg); } // --- unsafe versions @@ -166,3 +161,9 @@ static inline uint8_t ip_read_byte_safe(char **ip, const Bytefile *bf) { static inline const char *ip_read_string_safe(char **ip, const Bytefile *bf) { return get_string_safe(bf, ip_read_int_safe(ip, bf)); } + +// --- + +static inline size_t calc_publics_size(size_t publics_number) { + return publics_number * 2 * sizeof(int); +} diff --git a/byterun/regression_check.sh b/byterun/regression_check.sh index 2fc1c31bc..162a7d908 100755 --- a/byterun/regression_check.sh +++ b/byterun/regression_check.sh @@ -10,12 +10,13 @@ compiler=../_build/default/src/Driver.exe echo "Used compiler path:" echo $compiler -for test in ../regression/*.lama; do +for test in ../regression/*009.lama; do echo $test $compiler -b $test > /dev/null test_file="${test%.*}" echo $test_file - cat $test_file.input | ./byterun.exe -vi test*.bc > /dev/null + cat $test_file.input | ./byterun.exe -p test*.bc #> /dev/null + cat $test_file.input | ./byterun.exe -vi test*.bc #> /dev/null rm test*.bc echo "done" done diff --git a/byterun/src/analyzer.cpp b/byterun/src/analyzer.cpp index 24ec0feea..1a278658a 100644 --- a/byterun/src/analyzer.cpp +++ b/byterun/src/analyzer.cpp @@ -9,13 +9,11 @@ extern "C" { #include -void analyze(uint32_t mod_id) { - Bytefile *bf = mod_get(mod_id); - +void analyze(Bytefile *bf, std::vector &&add_publics) { static constexpr const int NOT_VISITED = -1; std::vector visited(bf->code_size, NOT_VISITED); // store stack depth - std::vector to_visit_func; + std::vector to_visit_func = std::move(add_publics); std::vector to_visit_jmp; int current_stack_depth = 0; @@ -30,57 +28,55 @@ void analyze(uint32_t mod_id) { char *current_ip = ip; char *saved_current_ip = current_ip; - auto const jmp_to_visit_push = [&saved_current_ip, mod_id, &visited, + auto const jmp_to_visit_push = [&saved_current_ip, bf, &visited, ¤t_stack_depth, &to_visit_jmp](size_t offset) { if (visited[offset] == NOT_VISITED) { visited[offset] = current_stack_depth; to_visit_jmp.push_back(offset); } else if (visited[offset] != current_stack_depth) { - ip_failure(saved_current_ip, mod_id, + ip_failure(saved_current_ip, bf, "different stack depth on same point is not allowed"); } }; - auto const func_to_visit_push = [&saved_current_ip, mod_id, &visited, + auto const func_to_visit_push = [&saved_current_ip, bf, &visited, &to_visit_func](size_t offset) { if (visited[offset] == NOT_VISITED) { visited[offset] = 0; to_visit_func.push_back(offset); } else if (visited[offset] != 0) { - ip_failure(saved_current_ip, mod_id, + ip_failure(saved_current_ip, bf, "different stack depth on same point is not allowed"); } }; - auto const check_correct_var = [&saved_current_ip, mod_id, &globals_count, + auto const check_correct_var = [&saved_current_ip, bf, &globals_count, ¤t_locals_count, ¤t_args_count, &is_in_closure](uint8_t l, uint id) { if (l > 3) { - ip_failure(saved_current_ip, mod_id, "unexpected variable category"); + ip_failure(saved_current_ip, bf, "unexpected variable category"); } VarCategory category = to_var_category(l); switch (category) { case VAR_GLOBAL: if (id >= globals_count) { - ip_failure(saved_current_ip, mod_id, - "global var index is out of range"); + ip_failure(saved_current_ip, bf, "global var index is out of range"); } break; case VAR_LOCAL: if (id >= current_locals_count) { - ip_failure(saved_current_ip, mod_id, "local var index is out of range"); + ip_failure(saved_current_ip, bf, "local var index is out of range"); } break; case VAR_ARGUMENT: if (id >= current_args_count) { - ip_failure(saved_current_ip, mod_id, - "argument var index is out of range"); + ip_failure(saved_current_ip, bf, "argument var index is out of range"); } break; case VAR_CLOSURE: if (!is_in_closure) { - ip_failure(saved_current_ip, mod_id, + ip_failure(saved_current_ip, bf, "can't access closure vars outside of closure"); } // NOTE: impossible to properly check bounds there @@ -89,13 +85,13 @@ void analyze(uint32_t mod_id) { }; // add publics - to_visit_func.reserve(bf->public_symbols_number); + to_visit_func.reserve(bf->public_symbols_number + to_visit_func.size()); for (size_t i = 0; i < bf->public_symbols_number; ++i) { func_to_visit_push(get_public_offset_safe(bf, i)); } if (to_visit_func.size() == 0) { - failure("no public symbols detected"); + failure("no public symbols detected\n"); } while (true) { @@ -112,7 +108,8 @@ void analyze(uint32_t mod_id) { if (to_visit_jmp.empty()) { current_begin_counter = nullptr; if (func_end_found != 1) { - failure("each function should have exactly one end"); + failure("each function should have exactly one end (%zu found)\n", + func_end_found); } continue; } @@ -121,12 +118,11 @@ void analyze(uint32_t mod_id) { } if (ip >= bf->code_ptr + bf->code_size) { - ip_safe_failure(ip, mod_id, - "instruction pointer is out of range (>= size)"); + ip_safe_failure(ip, bf, "instruction pointer is out of range (>= size)"); } if (ip < bf->code_ptr) { - ip_safe_failure(ip, mod_id, "instruction pointer is out of range (< 0)"); + ip_safe_failure(ip, bf, "instruction pointer is out of range (< 0)"); } current_ip = ip; @@ -134,18 +130,18 @@ void analyze(uint32_t mod_id) { #ifdef DEBUG_VERSION const auto [cmd, l] = parse_command(&ip, bf, std::cout); + std::cout << '\n'; #else const auto [cmd, l] = parse_command(&ip, bf); #endif if (current_begin_counter == nullptr && cmd != Cmd::BEGIN && cmd != Cmd::CBEGIN) { - ip_failure(saved_current_ip, mod_id, - "function does not start with begin"); + ip_failure(saved_current_ip, bf, "function does not start with begin"); } if (visited[current_ip - bf->code_ptr] == NOT_VISITED) { - ip_failure(saved_current_ip, mod_id, "not visited command"); + ip_failure(saved_current_ip, bf, "not visited command"); } current_stack_depth = visited[current_ip - bf->code_ptr]; @@ -161,7 +157,7 @@ void analyze(uint32_t mod_id) { case Cmd::BINOP: current_stack_depth -= 2; if (current_stack_depth < 0) { - ip_failure(saved_current_ip, mod_id, "not enough elements in stack"); + ip_failure(saved_current_ip, bf, "not enough elements in stack"); } ++current_stack_depth; break; @@ -175,21 +171,21 @@ void analyze(uint32_t mod_id) { ip_read_string_unsafe(¤t_ip, bf); current_stack_depth -= ip_read_int_unsafe(¤t_ip); if (current_stack_depth < 0) { - ip_failure(saved_current_ip, mod_id, "not enough elements in stack"); + ip_failure(saved_current_ip, bf, "not enough elements in stack"); } ++current_stack_depth; break; case Cmd::STI: current_stack_depth -= 2; if (current_stack_depth < 0) { - ip_failure(saved_current_ip, mod_id, "not enough elements in stack"); + ip_failure(saved_current_ip, bf, "not enough elements in stack"); } ++current_stack_depth; break; case Cmd::STA: current_stack_depth -= 3; if (current_stack_depth < 0) { - ip_failure(saved_current_ip, mod_id, "not enough elements in stack"); + ip_failure(saved_current_ip, bf, "not enough elements in stack"); } ++current_stack_depth; break; @@ -207,19 +203,19 @@ void analyze(uint32_t mod_id) { break; case Cmd::DUP: if (current_stack_depth < 1) { - ip_failure(saved_current_ip, mod_id, "not enough elements in stack"); + ip_failure(saved_current_ip, bf, "not enough elements in stack"); } ++current_stack_depth; break; case Cmd::SWAP: if (current_stack_depth < 2) { - ip_failure(saved_current_ip, mod_id, "not enough elements in stack"); + ip_failure(saved_current_ip, bf, "not enough elements in stack"); } break; case Cmd::ELEM: current_stack_depth -= 2; if (current_stack_depth < 0) { - ip_failure(saved_current_ip, mod_id, "not enough elements in stack"); + ip_failure(saved_current_ip, bf, "not enough elements in stack"); } ++current_stack_depth; break; @@ -234,7 +230,7 @@ void analyze(uint32_t mod_id) { case Cmd::ST: check_correct_var(l, ip_read_int_unsafe(¤t_ip)); if (current_stack_depth < 1) { - ip_failure(saved_current_ip, mod_id, "not enough elements in stack"); + ip_failure(saved_current_ip, bf, "not enough elements in stack"); } break; case Cmd::CJMPz: @@ -244,13 +240,14 @@ void analyze(uint32_t mod_id) { case Cmd::BEGIN: case Cmd::CBEGIN: if (current_begin_counter != nullptr) { - ip_failure(saved_current_ip, mod_id, "unexpected function beginning"); + ip_failure(saved_current_ip, bf, "unexpected function beginning"); } current_args_count = ip_read_int_unsafe(¤t_ip); current_begin_counter = (uint16_t *)(current_ip + sizeof(uint16_t)); current_locals_count = ip_read_int_unsafe(¤t_ip); if (current_locals_count >= std::numeric_limits::max()) { - ip_failure(saved_current_ip, mod_id, "too many locals in functions"); + std::cerr << current_locals_count << " locals" << '\n'; + ip_failure(saved_current_ip, bf, "too many locals in functions"); } (*(uint16_t *)(current_ip - sizeof(uint16_t))) = current_locals_count; *current_begin_counter = 0; @@ -269,12 +266,12 @@ void analyze(uint32_t mod_id) { ++current_stack_depth; // if (closure_offset >= bf->code_size) { - // ip_failure(saved_current_ip, mod_id, "jump/call out of file"); + // ip_failure(saved_current_ip, bf, "jump/call out of file"); // } // NOTE: is not always true // if (!is_command_name(bf->code_ptr + closure_offset, bf, Cmd::CBEGIN)) { - // ip_failure(saved_current_ip, mod_id, "closure should point to + // ip_failure(saved_current_ip, bf, "closure should point to // cbegin"); // } } break; @@ -282,7 +279,7 @@ void analyze(uint32_t mod_id) { uint args_count = ip_read_int_unsafe(¤t_ip); current_stack_depth -= args_count + 1; // + closure itself if (current_stack_depth < 0) { - ip_failure(saved_current_ip, mod_id, "not enough elements in stack"); + ip_failure(saved_current_ip, bf, "not enough elements in stack"); } ++current_stack_depth; // NOTE: can't check args == cbegin args @@ -292,29 +289,29 @@ void analyze(uint32_t mod_id) { uint args_count = ip_read_int_unsafe(¤t_ip); current_stack_depth -= args_count; if (current_stack_depth < 0) { - ip_failure(saved_current_ip, mod_id, "not enough elements in stack"); + ip_failure(saved_current_ip, bf, "not enough elements in stack"); } ++current_stack_depth; if ((int)call_offset >= bf->code_size) { - ip_failure(saved_current_ip, mod_id, "jump/call out of file"); + ip_failure(saved_current_ip, bf, "jump/call out of file"); } if (!is_command_name(bf->code_ptr + call_offset, bf, Cmd::BEGIN)) { - ip_failure(saved_current_ip, mod_id, "call should point to begin"); + ip_failure(saved_current_ip, bf, "call should point to begin"); } if (args_count != *(uint *)(bf->code_ptr + call_offset + 1)) { - ip_failure(saved_current_ip, mod_id, "wrong call argument count"); + ip_failure(saved_current_ip, bf, "wrong call argument count"); } } break; case Cmd::TAG: if (current_stack_depth < 1) { - ip_failure(saved_current_ip, mod_id, "not enough elements in stack"); + ip_failure(saved_current_ip, bf, "not enough elements in stack"); } break; case Cmd::ARRAY: if (current_stack_depth < 1) { - ip_failure(saved_current_ip, mod_id, "not enough elements in stack"); + ip_failure(saved_current_ip, bf, "not enough elements in stack"); } break; case Cmd::FAIL: @@ -322,25 +319,31 @@ void analyze(uint32_t mod_id) { break; case Cmd::LINE: break; - // case Cmd::CALLF: { - // // TODO: find link to real function and replace call (need to save all - // // modules in one space) <- optimization + case Cmd::BUILTIN: { + std::cout << "builtin\n"; + // TODO: find link to real function and replace call (need to save all + // modules in one space) <- optimization - // ip_read_int_unsafe(¤t_ip); // function name (str) - // uint args_count = ip_read_int_unsafe(¤t_ip); - // current_stack_depth -= args_count; - // if (current_stack_depth < 0) { - // ip_failure(saved_current_ip, mod_id, "not enough elements in stack"); - // } - // ++current_stack_depth; - // } break; + size_t id = ip_read_int_unsafe(¤t_ip); // builtin id + + if (id >= BUILTIN_NONE) { + ip_failure(saved_current_ip, bf, "undefined builtin id"); + } + + uint args_count = ip_read_int_unsafe(¤t_ip); + current_stack_depth -= args_count; + if (current_stack_depth < 0) { + ip_failure(saved_current_ip, bf, "not enough elements in stack"); + } + ++current_stack_depth; + } break; case Cmd::PATT: --current_stack_depth; if (l == CMD_PATT_STR) { --current_stack_depth; } if (current_stack_depth < 0) { - ip_failure(saved_current_ip, mod_id, "not enough elements in stack"); + ip_failure(saved_current_ip, bf, "not enough elements in stack"); } ++current_stack_depth; break; @@ -352,32 +355,31 @@ void analyze(uint32_t mod_id) { // case Cmd::Llength: // case Cmd::Lstring: // if (current_stack_depth < 1) { - // ip_failure(saved_current_ip, mod_id, "not enough elements in stack"); + // ip_failure(saved_current_ip, bf, "not enough elements in stack"); // } // break; // case Cmd::Barray: // current_stack_depth -= ip_read_int_unsafe(¤t_ip); // elem count // if (current_stack_depth < 0) { - // ip_failure(saved_current_ip, mod_id, "not enough elements in stack"); + // ip_failure(saved_current_ip, bf, "not enough elements in stack"); // } // ++current_stack_depth; // break; case Cmd::EXIT: - ip_failure(saved_current_ip, mod_id, + ip_failure(saved_current_ip, bf, "exit should be unreachable"); // NOTE: not sure break; case Cmd::_UNDEF_: - ip_failure(saved_current_ip, mod_id, "undefined command"); + ip_failure(saved_current_ip, bf, "undefined command"); break; } if (current_begin_counter == nullptr) { - ip_failure(saved_current_ip, mod_id, - "function does not start with begin"); + ip_failure(saved_current_ip, bf, "function does not start with begin"); } if (current_stack_depth < 0) { - ip_failure(saved_current_ip, mod_id, "not enough elements in stack"); + ip_failure(saved_current_ip, bf, "not enough elements in stack"); } *current_begin_counter = @@ -404,7 +406,7 @@ void analyze(uint32_t mod_id) { uint jmp_p = ip_read_int_unsafe(¤t_ip); if ((int)jmp_p >= bf->code_size) { // NOTE: maybe also should check that > begin (?) - ip_failure(saved_current_ip, mod_id, "jump/call out of file"); + ip_failure(saved_current_ip, bf, "jump/call out of file"); } if (is_call) { func_to_visit_push(jmp_p); @@ -415,7 +417,7 @@ void analyze(uint32_t mod_id) { } case Cmd::_UNDEF_: - ip_failure(saved_current_ip, mod_id, "undefined command"); + ip_failure(saved_current_ip, bf, "undefined command"); break; default: diff --git a/byterun/src/cli.cpp b/byterun/src/cli.cpp index fefeb7a30..0ae8fa980 100644 --- a/byterun/src/cli.cpp +++ b/byterun/src/cli.cpp @@ -42,42 +42,32 @@ int main(int argc, char **argv) { } #ifdef DEBUG_VERSION - std::cerr << "- read code file" << std::endl; + std::cout << "- read code file" << std::endl; #endif Bytefile *f = read_file(argv[2]); if (do_print) { #ifdef DEBUG_VERSION - std::cerr << "- print code file" << std::endl; + std::cout << "- print code file" << std::endl; #endif print_file(*f, std::cout); - free(f); } if (do_verification || do_interpretation) { #ifdef DEBUG_VERSION - std::cerr << "- init stack" << std::endl; + std::cout << "- init stack" << std::endl; #endif size_t stack[STACK_SIZE]; run_init(stack); #ifdef DEBUG_VERSION - std::cerr << "- add main module" << std::endl; + std::cout << "- run with imports" << std::endl; #endif - uint main_mod_id = mod_add(f, do_verification); - - if (do_interpretation) { -#ifdef DEBUG_VERSION - std::cerr << "- start interpretation" << std::endl; -#endif - - run_mod_rec(main_mod_id, argc - 2, argv + 2, do_verification); - } + f = run_with_imports(f, argc - 2, argv + 2, do_verification); } - mod_cleanup(); - + free(f); return 0; } diff --git a/byterun/src/compiler.cpp b/byterun/src/compiler.cpp index 35ae073e9..0387da2f7 100644 --- a/byterun/src/compiler.cpp +++ b/byterun/src/compiler.cpp @@ -328,7 +328,7 @@ struct ArgumentLocation { }; /* We need to know the word size to calculate offsets correctly */ -constexpr auto word_size = 8; +constexpr size_t word_size = 8; const Register::T &as_register(const Opnd &opnd) { return std::visit( @@ -1278,7 +1278,7 @@ std::vector compile_binop(Env &env, Opr op) { switch (op) { case Opr::DIV: return with_rdx([&x, &y](const auto &rdx) -> std::vector { - return {Mov{y, rax}, Sar1{rax}, Binop{"^", rdx, rdx}, + return {Mov{y, rax}, Sar1{rax}, Binop{Opr::XOR, rdx, rdx}, Cltd{}, Sar1{x}, IDiv{x}, Sal1{rax}, Or1{rax}, Mov{rax, y}}; }); @@ -1301,7 +1301,7 @@ std::vector compile_binop(Env &env, Opr op) { return { Binop{Opr::XOR, rax, rax}, Mov{x, extra}, - Binop{"cmp", extra, y}, + Binop{Opr::CMP, extra, y}, Set{suffix(op), Registers::rax}, Sal1{rax}, Or1{rax}, diff --git a/byterun/src/interpreter.c b/byterun/src/interpreter.c index 406db87b0..bc897a0e1 100644 --- a/byterun/src/interpreter.c +++ b/byterun/src/interpreter.c @@ -58,7 +58,7 @@ void run_init(size_t *stack) { init_state(&s, (void**)stack); } -void run_prepare_exec(int argc, char **argv) { +void set_argc_argv(int argc, char **argv) { s_push_i(BOX(argc)); #ifdef DEBUG_VERSION printf("- argc: %i\n", argc); @@ -80,38 +80,7 @@ void run_prepare_exec(int argc, char **argv) { #endif } -void run_mod_rec(uint mod_id, int argc, char **argv, bool do_verification) { - Bytefile* mod = mod_get(mod_id); -#ifdef DEBUG_VERSION - printf("- run mod rec, %i imports\n", mod->imports_number); -#endif - for (size_t i = 0; i < mod->imports_number; ++i) { - const char* import_str = get_import_safe(mod, i); - if (find_mod_loaded(import_str) < 0 && strcmp(import_str, "Std") != 0) { // not loaded -#ifdef DEBUG_VERSION - printf("- mod load <%s>\n", import_str); -#endif - int32_t import_mod = mod_load(import_str, do_verification); - if (import_mod < 0) { - failure("module <%s> not found\n", import_str); - } -#ifdef DEBUG_VERSION - printf("- mod run <%s>\n", import_str); -#endif - run_mod_rec(import_mod, argc, argv, do_verification); - } - } - - 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); - - cleanup_state(&s); -} - -static inline void call_Barray(size_t elem_count, char** ip, void** buffer) { +void call_Barray(size_t elem_count, char** ip, void** buffer) { // size_t elem_count = ip_read_int(ip); bool use_new_buffer = (elem_count > BUFFER_SIZE); @@ -149,17 +118,17 @@ static inline void call_Barray(size_t elem_count, char** ip, void** buffer) { } } -void run_mod(uint mod_id, int argc, char **argv) { +void run_main(Bytefile* bf, int argc, char **argv) { #ifdef DEBUG_VERSION - printf("--- module init state ---\n"); + printf("--- init state ---\n"); #endif - init_mod_state(mod_id, &s); + prepare_state(bf, &s); void *buffer[BUFFER_SIZE]; #ifdef DEBUG_VERSION - printf("--- module run begin ---\n"); + printf("--- run begin ---\n"); #endif do { @@ -178,9 +147,9 @@ void run_mod(uint mod_id, 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 +// #ifdef DEBUG_VERSION printf("0x%.8x: %s\n", s.ip - s.bf->code_ptr - 1, read_cmd(s.ip - 1, s.bf)); -#endif +// #endif switch (h) { case CMD_EXIT: @@ -207,7 +176,7 @@ void run_mod(uint mod_id, int argc, char **argv) { #undef BINOP_OPR default: - s_failure(&s, "invalid opcode"); // %d-%d\n", h, l); + s_failure(&s, "interpreter: invalid opcode"); // %d-%d\n", h, l); break; } } @@ -343,7 +312,7 @@ void run_mod(uint mod_id, int argc, char **argv) { } break; default: - s_failure(&s, "invalid opcode"); // %d-%d\n", h, l); + s_failure(&s, "interpreter: basic, invalid opcode"); // %d-%d\n", h, l); } break; @@ -407,7 +376,7 @@ void run_mod(uint mod_id, 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.call_module_id, + s_enter_f(s.call_ip /*ip from call*/, s.is_closure_call, args_sz, locals_sz); #ifndef WITH_CHECK if ((void **)__gc_stack_top + (aint)max_additional_stack_sz - 1 <= s.stack) { @@ -431,7 +400,7 @@ void run_mod(uint mod_id, 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.call_module_id, + s_enter_f(s.call_ip /*ip from call*/, s.is_closure_call, args_sz, locals_sz); #ifdef WITH_CHECK if ((void **)__gc_stack_top + (aint)max_additional_stack_sz - 1 <= s.stack) { @@ -474,7 +443,6 @@ void run_mod(uint mod_id, 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; @@ -487,7 +455,6 @@ void run_mod(uint mod_id, 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 >= s.bf->code_size) { @@ -527,42 +494,29 @@ void run_mod(uint mod_id, 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); - // size_t args_count = ip_read_int(&s.ip); // args count + case CMD_CTRL_BUILTIN: { // BUILTIN %d %d // call builtin + size_t builtin_id = ip_read_int(&s.ip); + size_t args_count = ip_read_int(&s.ip); // args count - // if (run_stdlib_func(call_func_name, args_count)) { - // // case of stdlib function - // break; - // } + printf("builtin id: %zu\n", builtin_id); +// #ifndef WITH_CHECK + if (builtin_id >= BUILTIN_NONE) { + s_failure(&s, "invalid builtin"); + } +// #endif - // if (strcmp(call_func_name, ".array") == 0) { - // call_Barray(args_count, &s.ip, buffer); - // break; - // } - - // struct ModSearchResult func = mod_search_pub_symbol(call_func_name); - // if (func.mod_file == NULL) { - // failure("RUNTIME ERROR: external function <%s> with <%zu> args not found\n", call_func_name, args_count); - // } - - // 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; - // } + if (builtin_id == BUILTIN_Barray) { + call_Barray(args_count, &s.ip, buffer); + } else { + run_stdlib_func(builtin_id, args_count); + } + printf("builtin end\n"); + fflush(stdout); + break; + } default: - s_failure(&s, "invalid opcode"); // %d-%d\n", h, l); + s_failure(&s, "interpreter: ctrl, invalid opcode"); // %d-%d\n", h, l); } break; @@ -650,7 +604,6 @@ void run_mod(uint mod_id, 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 188392728..419800f07 100644 --- a/byterun/src/module_manager.cpp +++ b/byterun/src/module_manager.cpp @@ -1,4 +1,6 @@ +#include extern "C" { +#include "interpreter.h" #include "module_manager.h" #include "runtime_externs.h" #include "stack.h" @@ -9,6 +11,7 @@ extern "C" { #include "parser.hpp" #include +#include #include #include #include @@ -42,146 +45,336 @@ void call_anyarg_func(void (*f)(), size_t n) { } } -struct ModSymbolPos { - uint32_t mod_id; - size_t offset; +// --- + +struct Offsets { + size_t strings; + size_t globals; + size_t code; + size_t publics_num; }; -struct Module { - std::string name; - Bytefile *bf; -}; +void rewrite_code_with_offsets(Bytefile *bytefile, const Offsets &offsets) { + // TODO: globals offsets -struct ModuleManager { - std::unordered_map loaded_modules; - std::unordered_map public_symbols_mods; - std::vector modules; - std::vector search_paths; -}; + char *ip = bytefile->code_ptr; + while (ip - bytefile->code_ptr < bytefile->code_size) { + char *instr_ip = ip; + const auto [cmd, l] = parse_command(&ip, bytefile); -static ModuleManager manager; - -uint32_t mod_add_impl(Bytefile *bf, bool do_verification, - std::optional name = std::nullopt) { -#ifdef DEBUG_VERSION - std::cerr << "- add module (impl) '" << std::string{name ? *name : ""} - << "'\n"; -#endif - uint32_t id = manager.modules.size(); - manager.modules.push_back({.name = name ? *name : "", .bf = bf}); - for (size_t i = 0; i < bf->public_symbols_number; ++i) { - const char *public_name = get_public_name_safe(bf, i); -#ifdef DEBUG_VERSION - std::cerr << "- load public " << public_name << "\n"; -#endif - size_t public_offset = get_public_offset_safe(bf, i); - if (strcmp(public_name, "main") == 0) { - bf->main_offset = public_offset; - } else if (!manager.public_symbols_mods - .insert( - {public_name, {.mod_id = id, .offset = public_offset}}) - .second) { - failure("public symbol '%s' loaded more then once\n", - get_public_name_safe(bf, i)); + char *read_ip = instr_ip + 1; + char *write_ip = instr_ip + 1; + switch (cmd) { + case Cmd::STRING: + ip_write_int_unsafe(write_ip, + ip_read_int_unsafe(&read_ip) + offsets.strings); + break; + case Cmd::JMP: + case Cmd::CJMPnz: + case Cmd::CJMPz: + case Cmd::CALL: + ip_write_int_unsafe(write_ip, + ip_read_int_unsafe(&read_ip) + offsets.code); + break; + case Cmd::CLOSURE: { + ip_write_int_unsafe(write_ip, + ip_read_int_unsafe(&read_ip) + offsets.code); + size_t args_count = ip_read_int_unsafe(&read_ip); + for (size_t i = 0; i < args_count; ++i) { + uint8_t arg_type = ip_read_byte_unsafe(&read_ip); + if (to_var_category(arg_type) == VAR_GLOBAL) { + write_ip = read_ip; + ip_write_int_unsafe(write_ip, + ip_read_int_unsafe(&read_ip) + offsets.globals); + } + } + break; + } + case Cmd::LD: + case Cmd::ST: + case Cmd::STA: + if (to_var_category(l) == VAR_GLOBAL) { + ip_write_int_unsafe(write_ip, + ip_read_int_unsafe(&read_ip) + offsets.globals); + } + break; + default: + break; } } - if (name) { - manager.loaded_modules.insert({*name, id}); - } - if (do_verification) { - analyze(id); - } - return id; } -uint32_t path_mod_load(const char *name, std::filesystem::path &&path, - bool do_verification) { +void subst_in_code(Bytefile *bytefile, + const std::unordered_map &publics) { + for (size_t i = 0; i < bytefile->substs_area_size; ++i) { + if (i + sizeof(uint32_t) >= bytefile->substs_area_size) { + failure("substitution %zu offset is out of area\n", i); + } + + uint32_t offset = *(uint32_t *)(bytefile->substs_ptr + i); + i += sizeof(uint32_t); + const char *name = bytefile->substs_ptr + i; + i += strlen(name); + #ifdef DEBUG_VERSION - std::cerr << "- module path load '" << name << "'\n"; + printf("subst: offset %u, name %s\n", offset, name); #endif - Bytefile *module = read_file(path.c_str()); - return mod_add_impl(module, do_verification, name); + + if (i > bytefile->substs_area_size) { + failure("substitution %zu name is out of area\n", i); + } + + BUILTIN builtin = id_by_builtin(name); + + // NOTE: address is first argument of the call + if (builtin != BUILTIN_NONE) { + uint8_t cmd = ((CMD_CTRL << 4) | CMD_CTRL_BUILTIN); +#ifdef DEBUG_VERSION + printf("set builtin %i, offset %i, cmd %u = (%u << 4) | %u, h = %u, l = " + "%u\n", + builtin, offset, cmd, CMD_CTRL, CMD_CTRL_BUILTIN, + (cmd & 0xF0) >> 4, cmd & 0x0F); +#endif + *(uint8_t *)(bytefile->code_ptr + offset - 1) = + cmd; // set BUILTIN command + *(uint32_t *)(bytefile->code_ptr + offset) = builtin; + continue; + } + + const auto it = publics.find(name); + if (it == publics.end()) { + failure("public name for substitution is not found: <%s>\n", name); + } + + *(uint32_t *)(bytefile->code_ptr + offset) = it->second; + // TODO: check: +4 to match ? + } } +Offsets calc_merge_sizes(const std::vector &bytefiles) { + Offsets sizes{.strings = 0, .globals = 0, .code = 0, .publics_num = 0}; + for (size_t i = 0; i < bytefiles.size(); ++i) { + sizes.strings += bytefiles[i]->stringtab_size; + sizes.globals += bytefiles[i]->global_area_size; + sizes.code += bytefiles[i]->code_size; + sizes.publics_num += bytefiles[i]->public_symbols_number; + } + return sizes; +} + +struct MergeResult { + Bytefile *bf; + std::vector main_offsets; +}; + +MergeResult merge_files(std::vector &&bytefiles) { + Offsets sizes = calc_merge_sizes(bytefiles); + size_t public_symbols_size = calc_publics_size(sizes.publics_num); + Bytefile *result = + (Bytefile *)malloc(sizeof(Bytefile) + sizes.strings + sizes.code + + public_symbols_size); // globals are on the stack + + // collect publics + // TODO: add publics + updat name offsets too ?()) + std::unordered_map publics; + std::vector main_offsets; + { + size_t code_offset = 0; + for (size_t i = 0; i < bytefiles.size(); ++i) { +#ifdef DEBUG_VERSION + printf("bytefile <%zu>\n", i); +#endif + for (size_t j = 0; j < bytefiles[i]->public_symbols_number; ++j) { +#ifdef DEBUG_VERSION + printf("symbol <%zu>:<%zu>\n", i, j); +#endif + const char *name = get_public_name_unsafe(bytefiles[i], j); + size_t offset = get_public_offset_unsafe(bytefiles[i], j) + code_offset; + +#ifdef DEBUG_VERSION + printf("symbol %s : %zu (code offset %zu)\n", name, offset, + code_offset); +#endif + if (strcmp(name, "main") == 0) { + main_offsets.push_back(offset); + } else if (!publics.insert({name, offset}).second) { + failure("public name found more then once: %s", name); + } + } + code_offset += bytefiles[i]->code_size; + } + } + + // init result + result->code_size = sizes.code; + result->stringtab_size = sizes.strings; + result->global_area_size = sizes.globals; + result->substs_area_size = 0; + result->imports_number = 0; + result->public_symbols_number = sizes.publics_num; + + result->main_offset = 0; // TODO: save al main offsets in some way (?) + result->public_ptr = (int *)result->buffer; + result->string_ptr = (char *)result->public_ptr + public_symbols_size; + result->code_ptr = result->string_ptr + result->stringtab_size; + result->imports_ptr = NULL; + result->global_ptr = NULL; + result->substs_ptr = NULL; + + // update & merge code segments + Offsets offsets{.strings = 0, .globals = 0, .code = 0, .publics_num = 0}; + // REMOVE printf("merge bytefiles\n"); + for (size_t i = 0; i < bytefiles.size(); ++i) { + // REMOVE printf("rewrite offsets %zu\n", i); + rewrite_code_with_offsets(bytefiles[i], offsets); + // REMOVE printf("subst in code %zu\n", i); + subst_in_code(bytefiles[i], publics); + + size_t publics_offset = calc_publics_size(offsets.publics_num); + + // copy data to merged file + memcpy(result->string_ptr + offsets.strings, bytefiles[i]->string_ptr, + bytefiles[i]->stringtab_size); + memcpy(result->code_ptr + offsets.code, bytefiles[i]->code_ptr, + bytefiles[i]->code_size); + memcpy((char *)result->public_ptr + publics_offset, + (char *)bytefiles[i]->public_ptr, + calc_publics_size( + bytefiles[i]->public_symbols_number)); // TODO: recalc publics: + // offsets, strings + + // update offsets + offsets.strings += bytefiles[i]->stringtab_size; + offsets.globals += bytefiles[i]->global_area_size; + offsets.code += bytefiles[i]->code_size; + offsets.publics_num += bytefiles[i]->public_symbols_number; + free(bytefiles[i]); + } + +#ifdef DEBUG_VERSION + std::cout << "- merged file:\n"; + print_file(*result, std::cout); +#endif + return {result, main_offsets}; +} + +// --- + +Bytefile *path_mod_load(const char *name, std::filesystem::path &&path) { +#ifdef DEBUG_VERSION + std::cout << "- module path load '" << name << "'\n"; +#endif + return read_file(path.c_str()); +} + +static std::vector search_paths; + extern "C" { -void mod_cleanup() { - for (auto &mod : manager.modules) { - free(mod.bf); - } -} +void mod_add_search_path(const char *path) { search_paths.emplace_back(path); } -void mod_add_search_path(const char *path) { - manager.search_paths.emplace_back(path); -} - -const char *mod_get_name(uint32_t id) { - if (id > manager.modules.size()) { - failure("module id is out of range\n"); - } - return manager.modules[id].name.c_str(); -} - -Bytefile *mod_get(uint32_t id) { - if (id > manager.modules.size()) { - failure("module id is out of range\n"); - } - return manager.modules[id].bf; -} - -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, bool do_verification) { +Bytefile *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, do_verification); + return path_mod_load(name, full_name); } - for (const auto &dir_path : manager.search_paths) { + for (const auto &dir_path : search_paths) { auto path = dir_path / full_name; if (std::filesystem::exists(path)) { - return path_mod_load(name, std::move(path), do_verification); + return path_mod_load(name, std::move(path)); } } - return -1; + return NULL; } -uint32_t mod_add(Bytefile *module, bool do_verification) { +} // extern "C" + +// uint32_t mod_add(Bytefile *module, bool do_verification) { +// #ifdef DEBUG_VERSION +// std::cout << "- add module, no name\n"; +// #endif +// return mod_add_impl(module, do_verification); +// } + +// 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), +// }; +// } + +void mod_load_rec(Bytefile *mod, + std::unordered_map &loaded, + std::vector &loaded_ord) { #ifdef DEBUG_VERSION - std::cerr << "- add module, no name\n"; + printf("- run mod rec, %i imports\n", mod->imports_number); #endif - return mod_add_impl(module, do_verification); + for (size_t i = 0; i < mod->imports_number; ++i) { + const char *import_str = get_import_safe(mod, i); + if (loaded.count(import_str) == 0 && + strcmp(import_str, "Std") != 0) { // not loaded +#ifdef DEBUG_VERSION + printf("- mod load <%s>\n", import_str); +#endif + Bytefile *import_mod = mod_load(import_str); // TODO + if (import_mod == NULL) { + failure("module <%s> not found\n", import_str); + } + loaded.insert({import_str, import_mod}); + mod_load_rec(import_mod, loaded, loaded_ord); + // loaded_ord.push_back(import_mod); + } + } + loaded_ord.push_back(mod); } -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}; +MergeResult load_with_imports(Bytefile *root, bool do_verification) { + std::unordered_map loaded; + std::vector loaded_ord; + mod_load_rec(root, loaded, loaded_ord); + + MergeResult result = merge_files(std::move(loaded_ord)); + + if (do_verification) { + // #ifdef DEBUG_VERSION + printf("main offsets count: %zu\n", result.main_offsets.size()); + // #endif + analyze(result.bf /*, std::move(result.main_offsets)*/); + } + return result; +} + +extern "C" { +Bytefile *run_with_imports(Bytefile *root, int argc, char **argv, + bool do_verification) { + + MergeResult result = load_with_imports(root, do_verification); + + Bytefile *bf = result.bf; + + bf->main_offset = 0; + prepare_state(bf, &s); // NOTE: for push_globals + push_globals(&s); + + for (size_t i = 0; i < result.main_offsets.size(); ++i) { + bf->main_offset = result.main_offsets[i]; + set_argc_argv(argc, argv); // args for module main + run_main(bf, argc, argv); } - return { - .symbol_offset = it->second.offset, - .mod_id = it->second.mod_id, - .mod_file = mod_get(it->second.mod_id), - }; + cleanup_state(&s); + + return bf; } +} // extern "C" struct StdFunc { void (*ptr)(); @@ -189,75 +382,128 @@ struct StdFunc { bool is_args = false; // one var for all args bool is_vararg = false; }; -bool run_stdlib_func(const char *name, size_t args_count) { - static const std::unordered_map std_func = { - {"Luppercase", {.ptr = (void (*)()) & Luppercase, .args_count = 1}}, - {"Llowercase", {.ptr = (void (*)()) & Llowercase, .args_count = 1}}, - {"Lassert", + +BUILTIN id_by_builtin(const char *name) { + static const std::unordered_map std_func = { + {"Luppercase", BUILTIN_Luppercase}, + {"Llowercase", BUILTIN_Llowercase}, + {"Lassert", BUILTIN_Lassert}, + {"Lstring", BUILTIN_Lstring}, + {"Llength", BUILTIN_Llength}, + {"LstringInt", BUILTIN_LstringInt}, + {"Lread", BUILTIN_Lread}, + {"Lwrite", BUILTIN_Lwrite}, + {"LmakeArray", BUILTIN_LmakeArray}, + {"LmakeString", BUILTIN_LmakeString}, + {"Lstringcat", BUILTIN_Lstringcat}, + {"LmatchSubString", BUILTIN_LmatchSubString}, + {"Lsprintf", BUILTIN_Lsprintf}, + {"Lsubstring", BUILTIN_Lsubstring}, + {"Li__Infix_4343", BUILTIN_Li__Infix_4343}, // ++ + {"Lclone", BUILTIN_Lclone}, + {"Lhash", BUILTIN_Lhash}, + {"LtagHash", BUILTIN_LtagHash}, + {"Lcompare", BUILTIN_Lcompare}, + {"LflatCompare", BUILTIN_LflatCompare}, + {"Lfst", BUILTIN_Lfst}, + {"Lsnd", BUILTIN_Lsnd}, + {"Lhd", BUILTIN_Lhd}, + {"Ltl", BUILTIN_Ltl}, + {"LreadLine", BUILTIN_LreadLine}, + {"Lprintf", BUILTIN_Lprintf}, + {"Lfopen", BUILTIN_Lfopen}, + {"Lfclose", BUILTIN_Lfclose}, + {"Lfread", BUILTIN_Lfread}, + {"Lfwrite", BUILTIN_Lfwrite}, + {"Lfexists", BUILTIN_Lfexists}, + {"Lfprintf", BUILTIN_Lfprintf}, + {"Lregexp", BUILTIN_Lregexp}, + {"LregexpMatch", BUILTIN_LregexpMatch}, + {"Lfailure", BUILTIN_Lfailure}, + {"Lsystem", BUILTIN_Lsystem}, + {"LgetEnv", BUILTIN_LgetEnv}, + {"Lrandom", BUILTIN_Lrandom}, + {"Ltime", BUILTIN_Ltime}, + {".array", BUILTIN_Barray}, + }; + + auto const it = std_func.find(name); + + return it == std_func.end() ? BUILTIN_NONE : it->second; +} + +void run_stdlib_func(BUILTIN id, size_t args_count) { + static const std::map std_func = { + {BUILTIN_Luppercase, {.ptr = (void (*)()) & Luppercase, .args_count = 1}}, + {BUILTIN_Llowercase, {.ptr = (void (*)()) & Llowercase, .args_count = 1}}, + {BUILTIN_Lassert, {.ptr = (void (*)()) & Lassert, .args_count = 2, .is_vararg = true}}, - {"Lstring", + {BUILTIN_Lstring, {.ptr = (void (*)()) & Lstring, .args_count = 1, .is_args = true}}, - {"Llength", {.ptr = (void (*)()) & Llength, .args_count = 1}}, - {"LstringInt", {.ptr = (void (*)()) & LstringInt, .args_count = 1}}, - {"Lread", {.ptr = (void (*)()) & Lread, .args_count = 0}}, - {"Lwrite", {.ptr = (void (*)()) & Lwrite, .args_count = 1}}, - {"LmakeArray", {.ptr = (void (*)()) & LmakeArray, .args_count = 1}}, - {"LmakeString", {.ptr = (void (*)()) & LmakeString, .args_count = 1}}, - {"Lstringcat", + {BUILTIN_Llength, {.ptr = (void (*)()) & Llength, .args_count = 1}}, + {BUILTIN_LstringInt, {.ptr = (void (*)()) & LstringInt, .args_count = 1}}, + {BUILTIN_Lread, {.ptr = (void (*)()) & Lread, .args_count = 0}}, + {BUILTIN_Lwrite, {.ptr = (void (*)()) & Lwrite, .args_count = 1}}, + {BUILTIN_LmakeArray, {.ptr = (void (*)()) & LmakeArray, .args_count = 1}}, + {BUILTIN_LmakeString, + {.ptr = (void (*)()) & LmakeString, .args_count = 1}}, + {BUILTIN_Lstringcat, {.ptr = (void (*)()) & Lstringcat, .args_count = 1, .is_args = true}}, - {"LmatchSubString", + {BUILTIN_LmatchSubString, {.ptr = (void (*)()) & LmatchSubString, .args_count = 3}}, - {"Lsprintf", + {BUILTIN_Lsprintf, {.ptr = (void (*)()) & Lsprintf, .args_count = 1, .is_vararg = true}}, - {"Lsubstring", + {BUILTIN_Lsubstring, {.ptr = (void (*)()) & Lsubstring, .args_count = 3, .is_args = true}}, - {"Li__Infix_4343", + {BUILTIN_Li__Infix_4343, {.ptr = (void (*)()) & Li__Infix_4343, .args_count = 2, .is_args = true}}, // ++ - {"Lclone", + {BUILTIN_Lclone, {.ptr = (void (*)()) & Lclone, .args_count = 1, .is_args = true}}, - {"Lhash", {.ptr = (void (*)()) & Lhash, .args_count = 1}}, - {"LtagHash", {.ptr = (void (*)()) & LtagHash, .args_count = 1}}, - {"Lcompare", {.ptr = (void (*)()) & Lcompare, .args_count = 2}}, - {"LflatCompare", {.ptr = (void (*)()) & LflatCompare, .args_count = 2}}, - {"Lfst", {.ptr = (void (*)()) & Lfst, .args_count = 1}}, - {"Lsnd", {.ptr = (void (*)()) & Lsnd, .args_count = 1}}, - {"Lhd", {.ptr = (void (*)()) & Lhd, .args_count = 1}}, - {"Ltl", {.ptr = (void (*)()) & Ltl, .args_count = 1}}, - {"LreadLine", {.ptr = (void (*)()) & LreadLine, .args_count = 0}}, - {"Lprintf", + {BUILTIN_Lhash, {.ptr = (void (*)()) & Lhash, .args_count = 1}}, + {BUILTIN_LtagHash, {.ptr = (void (*)()) & LtagHash, .args_count = 1}}, + {BUILTIN_Lcompare, {.ptr = (void (*)()) & Lcompare, .args_count = 2}}, + {BUILTIN_LflatCompare, + {.ptr = (void (*)()) & LflatCompare, .args_count = 2}}, + {BUILTIN_Lfst, {.ptr = (void (*)()) & Lfst, .args_count = 1}}, + {BUILTIN_Lsnd, {.ptr = (void (*)()) & Lsnd, .args_count = 1}}, + {BUILTIN_Lhd, {.ptr = (void (*)()) & Lhd, .args_count = 1}}, + {BUILTIN_Ltl, {.ptr = (void (*)()) & Ltl, .args_count = 1}}, + {BUILTIN_LreadLine, {.ptr = (void (*)()) & LreadLine, .args_count = 0}}, + {BUILTIN_Lprintf, {.ptr = (void (*)()) & Lprintf, .args_count = 1, .is_vararg = true}}, - {"Lfopen", {.ptr = (void (*)()) & Lfopen, .args_count = 2}}, - {"Lfclose", {.ptr = (void (*)()) & Lfclose, .args_count = 1}}, - {"Lfread", {.ptr = (void (*)()) & Lfread, .args_count = 1}}, - {"Lfwrite", {.ptr = (void (*)()) & Lfwrite, .args_count = 2}}, - {"Lfexists", {.ptr = (void (*)()) & Lfexists, .args_count = 1}}, - {"Lfprintf", + {BUILTIN_Lfopen, {.ptr = (void (*)()) & Lfopen, .args_count = 2}}, + {BUILTIN_Lfclose, {.ptr = (void (*)()) & Lfclose, .args_count = 1}}, + {BUILTIN_Lfread, {.ptr = (void (*)()) & Lfread, .args_count = 1}}, + {BUILTIN_Lfwrite, {.ptr = (void (*)()) & Lfwrite, .args_count = 2}}, + {BUILTIN_Lfexists, {.ptr = (void (*)()) & Lfexists, .args_count = 1}}, + {BUILTIN_Lfprintf, {.ptr = (void (*)()) & Lfprintf, .args_count = 2, .is_vararg = true}}, - {"Lregexp", {.ptr = (void (*)()) & Lregexp, .args_count = 1}}, - {"LregexpMatch", {.ptr = (void (*)()) & LregexpMatch, .args_count = 3}}, - {"Lfailure", + {BUILTIN_Lregexp, {.ptr = (void (*)()) & Lregexp, .args_count = 1}}, + {BUILTIN_LregexpMatch, + {.ptr = (void (*)()) & LregexpMatch, .args_count = 3}}, + {BUILTIN_Lfailure, {.ptr = (void (*)()) & Lfailure, .args_count = 1, .is_vararg = true}}, - {"Lsystem", {.ptr = (void (*)()) & Lsystem, .args_count = 1}}, - {"LgetEnv", {.ptr = (void (*)()) & LgetEnv, .args_count = 1}}, - {"Lrandom", {.ptr = (void (*)()) & Lrandom, .args_count = 1}}, - {"Ltime", {.ptr = (void (*)()) & Ltime, .args_count = 0}}, + {BUILTIN_Lsystem, {.ptr = (void (*)()) & Lsystem, .args_count = 1}}, + {BUILTIN_LgetEnv, {.ptr = (void (*)()) & LgetEnv, .args_count = 1}}, + {BUILTIN_Lrandom, {.ptr = (void (*)()) & Lrandom, .args_count = 1}}, + {BUILTIN_Ltime, {.ptr = (void (*)()) & Ltime, .args_count = 0}}, }; // some functions do use on args pointer - const auto it = std_func.find(name); + const auto it = std_func.find(id); if (it == std_func.end()) { - return false; + failure("RUNTIME ERROR: stdlib function <%u> not found\n", id); } // TODO: move to bytecode verifier if ((!it->second.is_vararg && it->second.args_count != args_count) || it->second.args_count > args_count) { - failure("RUNTIME ERROR: stdlib function <%s> argument count <%zu> is not " + failure("RUNTIME ERROR: stdlib function <%u> argument count <%zu> is not " "expected (expected is <%s%zu>)\n", - name, it->second.args_count, it->second.is_vararg ? ">=" : "=", + id, it->second.args_count, it->second.is_vararg ? ">=" : "=", args_count); } @@ -268,7 +514,4 @@ bool run_stdlib_func(const char *name, size_t args_count) { } else { call_anyarg_func<20>(it->second.ptr, args_count); } - return true; } - -} // extern "C" diff --git a/byterun/src/parser.cpp b/byterun/src/parser.cpp index fcbc05128..50ec7f3c2 100644 --- a/byterun/src/parser.cpp +++ b/byterun/src/parser.cpp @@ -72,6 +72,8 @@ Bytefile *read_file(const char *fname) { char *file_begin = (char *)file + additional_size; char *file_end = file_begin + size; + size_t buffer_size = size + additional_size - sizeof(Bytefile); + if (file == 0) { failure("unable to allocate memory to store file data\n"); } @@ -85,7 +87,7 @@ Bytefile *read_file(const char *fname) { fclose(f); size_t imports_size = file->imports_number * sizeof(int); - size_t public_symbols_size = file->public_symbols_number * 2 * sizeof(int); + size_t public_symbols_size = calc_publics_size(file->public_symbols_number); size_t strings_buffer_offset = public_symbols_size + imports_size; if (file->buffer + strings_buffer_offset >= file_end) { @@ -98,7 +100,7 @@ Bytefile *read_file(const char *fname) { size_t substs_buffer_offset = strings_buffer_offset + file->stringtab_size; file->substs_ptr = file->buffer + substs_buffer_offset; - if ((char *)file->substs_ptr + file->substs_area_size > file_end) { + if (file->substs_ptr + file->substs_area_size > file_end) { failure("substitutions table is out of the file size\n"); } @@ -106,7 +108,9 @@ Bytefile *read_file(const char *fname) { // file->string_ptr[file->stringtab_size - 1] != 0) { // failure("strings table is not zero-ended\n"); // } - file->code_size = size - substs_buffer_offset - file->substs_area_size; + file->code_ptr = file->substs_ptr + file->substs_area_size; + // file->code_size = size - substs_buffer_offset - file->substs_area_size; + file->code_size = buffer_size - (file->code_ptr - file->buffer); if (file->code_size < 0 || public_symbols_size < 0 || file->stringtab_size < 0) { @@ -116,144 +120,11 @@ Bytefile *read_file(const char *fname) { file->imports_ptr = (int *)file->buffer; file->public_ptr = (int *)(file->buffer + imports_size); file->global_ptr = NULL; // is allocated on module run on stack - file->code_ptr = file->string_ptr + file->stringtab_size; // file->global_ptr = (int*) calloc (file->global_area_size, sizeof (int)); return file; } -struct Offsets { - size_t strings; - size_t globals; - size_t code; -}; - -void rewrite_code_with_offsets(Bytefile *bytefile, const Offsets &offsets) { - char *ip = bytefile->code_ptr; - while (ip - bytefile->code_ptr < bytefile->code_size) { - const auto [cmd, l] = parse_command(&ip, bytefile); - - char *cmd_ip = ip; - - switch (cmd) { - case Cmd::STRING: - ip_write_int_unsafe(cmd_ip, ip_read_int_unsafe(&ip) + - offsets.strings); // TODO: check - break; - case Cmd::JMP: - case Cmd::CJMPnz: - case Cmd::CJMPz: - case Cmd::CLOSURE: - case Cmd::CALL: - ip_write_int_unsafe(cmd_ip, ip_read_int_unsafe(&ip) + - offsets.code); // TODO: check - break; - default: - break; - } - } -} - -void subst_in_code(Bytefile *bytefile, - const std::unordered_map &publics) { - for (size_t i = 0; i < bytefile->substs_area_size;) { - if (i + sizeof(uint32_t) >= bytefile->substs_area_size) { - failure("substitution %zu offset is out of area", i); - } - - uint32_t offset = *(uint32_t *)(bytefile->substs_ptr + i); - i += sizeof(uint32_t); - const char *name = bytefile->substs_ptr + i; - - i += strlen(name); - - if (i > bytefile->substs_area_size) { - failure("substitution %zu name is out of area", i); - } - - const auto it = publics.find(name); - if (it == publics.end()) { - failure("public name for substitution is not found: %s", name); - } - - *(uint32_t *)(bytefile->code_ptr + offset) = it->second; - // TODO: check: +4 to match ? - } -} - -Offsets calc_merge_sizes(const std::vector &bytefiles) { - Offsets sizes{.strings = 0, .globals = 0, .code = 0}; - for (size_t i = 0; i < bytefiles.size(); ++i) { - sizes.strings += bytefiles[i]->stringtab_size; - sizes.strings += bytefiles[i]->global_area_size; - sizes.strings += bytefiles[i]->code_size; - } - return sizes; -} - -Bytefile *merge_files(std::vector &&bytefiles) { - Offsets sizes = calc_merge_sizes(bytefiles); - Bytefile *result = (Bytefile *)malloc(sizeof(Bytefile) + sizes.strings + - sizes.code); // globals - on stack - - // collect publics - std::unordered_map publics; - std::vector main_offsets; - { - size_t code_offset = 0; - for (size_t i = 0; i < bytefiles.size(); ++i) { - for (size_t j = 0; j < bytefiles[i]->public_symbols_number; ++j) { - const char *name = get_public_name_unsafe(bytefiles[i], j); - size_t offset = - get_public_name_offset_unsafe(bytefiles[i], j) + code_offset; - - if (strcmp(name, "main") == 0) { - main_offsets.push_back(offset); - } else if (!publics.insert({name, offset}).second) { - failure("public name found more then once: %s", name); - } - } - code_offset += bytefiles[i]->code_size; - } - } - - // init result - result->code_size = sizes.code; - result->stringtab_size = sizes.strings; - result->global_area_size = sizes.globals; - result->substs_area_size = 0; - result->imports_number = 0; - result->public_symbols_number = 0; - - result->main_offset = 0; // TODO: save al main offsets in some way (?) - result->string_ptr = result->buffer; - result->imports_ptr = NULL; - result->public_ptr = NULL; - result->code_ptr = result->string_ptr + result->stringtab_size; - result->global_ptr = NULL; - result->substs_ptr = NULL; - - // update & merge code segments - Offsets offsets{.strings = 0, .globals = 0, .code = 0}; - for (size_t i = 0; i < bytefiles.size(); ++i) { - rewrite_code_with_offsets(bytefiles[i], offsets); - subst_in_code(bytefiles[i], publics); - - // copy data to merged file - memcpy(result->string_ptr + offsets.strings, bytefiles[i]->string_ptr, - bytefiles[i]->stringtab_size); - memcpy(result->code_ptr + offsets.code, bytefiles[i]->code_ptr, - bytefiles[i]->code_size); - - // update offsets - offsets.strings += bytefiles[i]->stringtab_size; - offsets.globals += bytefiles[i]->global_area_size; - offsets.code += bytefiles[i]->code_size; - free(bytefiles[i]); - } - return result; -} - const char *command_name(Cmd cmd, int8_t l) { static const char *const ops[] = { #define OP_TO_STR(id, op) "BINOP:" #op, @@ -349,6 +220,8 @@ const char *command_name(Cmd cmd, int8_t l) { return "CALLC"; case Cmd::CALL: return "CALL"; + case Cmd::BUILTIN: + return "BUILTIN"; case Cmd::TAG: return "TAG"; case Cmd::ARRAY: @@ -379,7 +252,7 @@ const char *command_name(Cmd cmd, int8_t l) { return "_UNDEF_"; } - exit(1); + failure("command_name: unexpected command %u", static_cast(cmd)); } // } // extern "C" @@ -569,14 +442,14 @@ std::pair parse_command_impl(char **ip, const Bytefile &bf, break; default: - failure("invalid opcode"); + failure("parser: basic, invalid opcode\n"); } break; case CMD_LD: // LD %d cmd = Cmd::LD; if (l > sizeof(ldts) / sizeof(char *)) { - failure("wrong ld argument type"); + failure("wrong ld argument type\n"); } read_print_cmd_seq_opt(cmd, l, ip, bf, out); @@ -584,7 +457,7 @@ std::pair parse_command_impl(char **ip, const Bytefile &bf, case CMD_LDA: // LDA %d cmd = Cmd::LDA; if (l > sizeof(ldts) / sizeof(char *)) { - failure("wrong lda argument type"); + failure("wrong lda argument type\n"); } read_print_cmd_seq_opt(cmd, l, ip, bf, out); @@ -592,7 +465,7 @@ std::pair parse_command_impl(char **ip, const Bytefile &bf, case CMD_ST: // ST %d cmd = Cmd::ST; if (l > sizeof(ldts) / sizeof(char *)) { - failure("wrong st argument type"); + failure("wrong st argument type\n"); } read_print_cmd_seq_opt(cmd, l, ip, bf, out); @@ -633,7 +506,7 @@ std::pair parse_command_impl(char **ip, const Bytefile &bf, for (size_t i = 0; i < args_count; i++) { uint8_t arg_type = ip_read_byte_safe(ip, &bf); if (arg_type > sizeof(ldts) / sizeof(char *)) { - failure("wrong closure argument type"); + failure("wrong closure argument type\n"); } print_space(out); print_val(out, ldts[arg_type]); @@ -677,22 +550,21 @@ std::pair parse_command_impl(char **ip, const Bytefile &bf, read_print_cmd_seq_opt(cmd, l, ip, bf, out); break; - // NOTE: is replaced - // case CMD_CTRL_CALLF: // CALLF %s %d - // cmd = Cmd::CALLF; - // read_print_cmd_seq_opt( - // cmd, l, ip, bf, out); - // break; + case CMD_CTRL_BUILTIN: // BUILTIN %d %d // call builtin + cmd = Cmd::BUILTIN; + read_print_cmd_seq_opt( + cmd, l, ip, bf, out); + break; default: - failure("invalid opcode"); + failure("parser: ctrl, invalid opcode\n"); } break; case CMD_PATT: // PATT pats[l] // {"=str", "#string", "#array", "#sexp", "#ref", "#val", "#fun"} if (l >= sizeof(pats) / sizeof(char *)) { - failure("invalid opcode"); + failure("parser: patt, invalid opcode\n"); } cmd = Cmd::PATT; read_print_cmd_seq_opt(cmd, l, ip, bf, out); @@ -726,12 +598,12 @@ std::pair parse_command_impl(char **ip, const Bytefile &bf, // break; // default: - // failure("invalid opcode"); + // failure("parser: bultin, invalid opcode\n"); // } // } break; default: - failure("invalid opcode"); + failure("parser: invalid opcode\n"); } #ifdef DEBUG_VERSION std::cout << command_name(cmd, l) << '\n'; @@ -757,6 +629,7 @@ bool is_command_name(char *ip, const Bytefile *bf, Cmd cmd) { } void print_file_info(const Bytefile &bf, std::ostream &out) { + out << "Code size : " << bf.code_size << '\n'; out << "String table size : " << bf.stringtab_size << '\n'; out << "Global area size : " << bf.global_area_size << '\n'; out << "Substitutions area size : " << bf.substs_area_size << '\n'; @@ -774,6 +647,16 @@ void print_file_info(const Bytefile &bf, std::ostream &out) { << get_public_offset_safe(&bf, i) << ": " << std::dec << get_public_name_safe(&bf, i) << '\n'; } + + out << "Substs :\n"; + for (size_t i = 0; i < bf.substs_area_size; i++) { + uint32_t offset = *(uint32_t *)(bf.substs_ptr + i); + i += sizeof(uint32_t); + const char *name = bf.substs_ptr + i; + out << " " << std::setfill('0') << std::setw(8) << std::hex << offset + << ": " << std::dec << name << '\n'; + i += strlen(name); + } } void print_file_code(const Bytefile &bf, std::ostream &out) { @@ -786,6 +669,7 @@ void print_file_code(const Bytefile &bf, std::ostream &out) { out << std::endl; if (cmd == Cmd::EXIT) { + std::cout << "> EXIT" << std::endl; break; } } @@ -796,7 +680,7 @@ void print_file(const Bytefile &bf, std::ostream &out) { out << "Code:\n"; print_file_code(bf, out); - out << "code end\n"; + out << "Code end\n"; } extern "C" { diff --git a/byterun/src/types.c b/byterun/src/types.c index e2df5881a..1a38e7f49 100644 --- a/byterun/src/types.c +++ b/byterun/src/types.c @@ -19,8 +19,6 @@ void init_state(struct State* s, void** stack) { s->bf = NULL; s->current_line = 0; s->is_closure_call = false; - s->current_module_id = 0; - s->call_module_id = 0; s->ip = NULL; //s->bf->code_ptr; s->instr_ip = NULL; //s->bf->code_ptr; s->call_ip = NULL; @@ -38,16 +36,13 @@ void init_state(struct State* s, void** stack) { #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; +void prepare_state(Bytefile* bf, struct State* s) { + // init data + s->bf = bf; // 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; @@ -62,7 +57,7 @@ void init_mod_state(uint mod_id, struct State* s) { #endif } -void init_mod_state_globals(struct State *s) { +void push_globals(struct State *s) { s_pushn_nil(s->bf->global_area_size); s->bf->global_ptr = (void*)__gc_stack_top; diff --git a/byterun/test046 b/byterun/test046 new file mode 100755 index 0000000000000000000000000000000000000000..2081b68b76569121d3fe2e069020720ce7186295 GIT binary patch literal 102736 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 HxwZZ;hBuuM literal 0 HcmV?d00001 diff --git a/byterun/test046.i b/byterun/test046.i new file mode 100644 index 000000000..517e120ae --- /dev/null +++ b/byterun/test046.i @@ -0,0 +1 @@ +I,Std; diff --git a/byterun/test046.s b/byterun/test046.s new file mode 100644 index 000000000..64204d021 --- /dev/null +++ b/byterun/test046.s @@ -0,0 +1,2351 @@ + .file "/home/dragon/Containers/LaMa/projects/Lama/byterun/../regression/test046.lama" + + .stabs "/home/dragon/Containers/LaMa/projects/Lama/byterun/../regression/test046.lama",100,0,0,.Ltext + + .globl main + + .data + +string_0: .string "../regression/test046.lama" + +init: .quad 0 + + .section custom_data,"aw",@progbits + +filler: .fill 5, 8, 1 + + .stabs "n:S1",40,0,0,global_n + +global_n: .quad 1 + + .text + +.Ltext: + + .stabs "data:t1=r1;0;4294967295;",128,0,0,0 + +# IMPORT ("Std") + +# PUBLIC ("main") + +# EXTERN ("Llowercase") + +# EXTERN ("Luppercase") + +# EXTERN ("LtagHash") + +# EXTERN ("LflatCompare") + +# EXTERN ("LcompareTags") + +# EXTERN ("LkindOf") + +# EXTERN ("Ltime") + +# EXTERN ("Lrandom") + +# EXTERN ("LdisableGC") + +# EXTERN ("LenableGC") + +# EXTERN ("Ls__Infix_37") + +# EXTERN ("Ls__Infix_47") + +# EXTERN ("Ls__Infix_42") + +# EXTERN ("Ls__Infix_45") + +# EXTERN ("Ls__Infix_43") + +# EXTERN ("Ls__Infix_62") + +# EXTERN ("Ls__Infix_6261") + +# EXTERN ("Ls__Infix_60") + +# EXTERN ("Ls__Infix_6061") + +# EXTERN ("Ls__Infix_3361") + +# EXTERN ("Ls__Infix_6161") + +# EXTERN ("Ls__Infix_3838") + +# EXTERN ("Ls__Infix_3333") + +# EXTERN ("Ls__Infix_58") + +# EXTERN ("Li__Infix_4343") + +# EXTERN ("Lcompare") + +# EXTERN ("Lwrite") + +# EXTERN ("Lread") + +# EXTERN ("Lfailure") + +# EXTERN ("Lfexists") + +# EXTERN ("Lfwrite") + +# EXTERN ("Lfread") + +# EXTERN ("Lfclose") + +# EXTERN ("Lfopen") + +# EXTERN ("Lfprintf") + +# EXTERN ("Lprintf") + +# EXTERN ("LmakeString") + +# EXTERN ("Lsprintf") + +# EXTERN ("LregexpMatch") + +# EXTERN ("Lregexp") + +# EXTERN ("Lsubstring") + +# EXTERN ("LmatchSubString") + +# EXTERN ("Lstringcat") + +# EXTERN ("LreadLine") + +# EXTERN ("Ltl") + +# EXTERN ("Lhd") + +# EXTERN ("Lsnd") + +# EXTERN ("Lfst") + +# EXTERN ("Lhash") + +# EXTERN ("Lclone") + +# EXTERN ("Llength") + +# EXTERN ("Lstring") + +# EXTERN ("LmakeArray") + +# EXTERN ("LstringInt") + +# EXTERN ("global_sysargs") + +# EXTERN ("Lsystem") + +# EXTERN ("LgetEnv") + +# EXTERN ("Lassert") + +# LABEL ("main") + +main: + +# BEGIN ("main", 2, 4, [], [], []) + + .type main, @function + + .cfi_startproc + + movq init(%rip), %rax + test %rax, %rax + jz continue + ret +_ERROR: + + call Lbinoperror + ret +_ERROR2: + + call Lbinoperror2 + ret +continue: + + movq $1, init(%rip) + pushq %rbp + .cfi_def_cfa_offset 8 + + .cfi_offset 5, -8 + + movq %rsp, %rbp + .cfi_def_cfa_register 5 + + subq $Lmain_SIZE, %rsp + movq %rdi, %r12 + movq %rsi, %r13 + movq %rcx, %r14 + movq %rsp, %rdi + leaq filler(%rip), %rsi + movq $LSmain_SIZE, %rcx + rep movsq + movq %r12, %rdi + movq %r13, %rsi + movq %r14, %rcx + movq $15, %rax + test %rsp, %rax + jz ALIGNED + pushq filler(%rip) +ALIGNED: + + pushq %rdi + pushq %rsi + call __gc_init + popq %rsi + popq %rdi + call set_args +# SLABEL ("L1") + +L1: + +# LINE (3) + + .stabn 68,0,3,.L0 + +.L0: + +# CALL ("Lread", 0, false) + + pushq %rdi + pushq %rsi + movq $0, %r11 + call Lread + popq %rsi + popq %rdi + movq %rax, %r10 +# LINE (1) + + .stabn 68,0,1,.L1 + +.L1: + +# ST (Global ("n")) + + movq %r10, global_n(%rip) +# DROP + +# CONST (3) + + movq $7, %r10 +# DUP + + movq %r10, %r11 +# SLABEL ("L11") + +L11: + +# DROP + +# DUP + + movq %r10, %r11 +# ST (Local (0)) + + movq %r11, -8(%rbp) +# DROP + +# DROP + +# SLABEL ("L13") + +L13: + +# LINE (6) + + .stabn 68,0,6,.L2 + +.L2: + +# LD (Local (0)) + + movq -8(%rbp), %r10 +# CALL ("Lwrite", 1, false) + + pushq %rdi + pushq %rsi + movq %r10, %rdi + movq $1, %r11 + call Lwrite + popq %rsi + popq %rdi + movq %rax, %r10 +# DROP + +# SLABEL ("L14") + +L14: + +# JMP ("L7") + + jmp L7 +# SLABEL ("L12") + +L12: + +# JMP ("L7") + +# LABEL ("L7") + +L7: + +# CONST (3) + + movq $7, %r10 +# DUP + + movq %r10, %r11 +# SLABEL ("L20") + +L20: + +# DROP + +# DUP + + movq %r10, %r11 +# ST (Local (0)) + + movq %r11, -8(%rbp) +# DROP + +# DROP + +# SLABEL ("L22") + +L22: + +# LINE (11) + + .stabn 68,0,11,.L3 + +.L3: + +# LD (Local (0)) + + movq -8(%rbp), %r10 +# CALL ("Lwrite", 1, false) + + pushq %rdi + pushq %rsi + movq %r10, %rdi + movq $1, %r11 + call Lwrite + popq %rsi + popq %rdi + movq %rax, %r10 +# DROP + +# SLABEL ("L23") + +L23: + +# SLABEL ("L21") + +L21: + +# JMP ("L17") + + jmp L17 +# LABEL ("L17") + +L17: + +# CONST (3) + + movq $7, %r10 +# DUP + + movq %r10, %r11 +# SLABEL ("L29") + +L29: + +# DROP + +# DUP + + movq %r10, %r11 +# ST (Local (0)) + + movq %r11, -8(%rbp) +# DROP + +# DROP + +# SLABEL ("L31") + +L31: + +# LINE (15) + + .stabn 68,0,15,.L4 + +.L4: + +# LD (Local (0)) + + movq -8(%rbp), %r10 +# CALL ("Lwrite", 1, false) + + pushq %rdi + pushq %rsi + movq %r10, %rdi + movq $1, %r11 + call Lwrite + popq %rsi + popq %rdi + movq %rax, %r10 +# DROP + +# SLABEL ("L32") + +L32: + +# SLABEL ("L30") + +L30: + +# JMP ("L26") + + jmp L26 +# LABEL ("L26") + +L26: + +# CONST (1) + + movq $3, %r10 +# CONST (2) + + movq $5, %r11 +# CONST (3) + + movq $7, %r12 +# SEXP ("A", 3) + + movq $55, %r13 + pushq %rdi + pushq %rsi + pushq %r13 + pushq %r12 + pushq %r11 + pushq %r10 + movq %rsp, %rdi + movq $9, %rsi + call Bsexp + addq $32, %rsp + popq %rsi + popq %rdi + movq %rax, %r10 +# DUP + + movq %r10, %r11 +# SLABEL ("L44") + +L44: + +# DUP + + movq %r11, %r12 +# TAG ("A", 0) + + movq $55, %r13 + movq $1, %r14 + pushq %rdi + pushq %rsi + pushq %r10 + pushq %r11 + movq %r14, %rdx + movq %r13, %rsi + movq %r12, %rdi + movq $3, %r11 + call Btag + popq %r11 + popq %r10 + popq %rsi + popq %rdi + movq %rax, %r12 +# CJMP ("nz", "L42") + + sarq %r12 + cmpq $0, %r12 + jnz L42 +# LABEL ("L43") + +L43: + +# DROP + +# JMP ("L41") + + jmp L41 +# LABEL ("L42") + +L42: + +# DROP + +# DROP + +# SLABEL ("L46") + +L46: + +# LINE (19) + + .stabn 68,0,19,.L5 + +.L5: + +# CONST (1) + + movq $3, %r10 +# CALL ("Lwrite", 1, false) + + pushq %rdi + pushq %rsi + movq %r10, %rdi + movq $1, %r11 + call Lwrite + popq %rsi + popq %rdi + movq %rax, %r10 +# DROP + +# SLABEL ("L47") + +L47: + +# JMP ("L35") + + jmp L35 +# SLABEL ("L45") + +L45: + +# SLABEL ("L52") + +L52: + +# LABEL ("L41") + +L41: + +# DUP + + movq %r10, %r11 +# DUP + + movq %r11, %r12 +# TAG ("A", 3) + + movq $55, %r13 + movq $7, %r14 + pushq %rdi + pushq %rsi + pushq %r10 + pushq %r11 + movq %r14, %rdx + movq %r13, %rsi + movq %r12, %rdi + movq $3, %r11 + call Btag + popq %r11 + popq %r10 + popq %rsi + popq %rdi + movq %rax, %r12 +# CJMP ("nz", "L50") + + sarq %r12 + cmpq $0, %r12 + jnz L50 +# LABEL ("L51") + +L51: + +# DROP + +# JMP ("L36") + + jmp L36 +# LABEL ("L50") + +L50: + +# DUP + + movq %r11, %r12 +# CONST (0) + + movq $1, %r13 +# ELEM + + pushq %rdi + pushq %rsi + pushq %r10 + pushq %r11 + movq %r13, %rsi + movq %r12, %rdi + movq $2, %r11 + call Belem + popq %r11 + popq %r10 + popq %rsi + popq %rdi + movq %rax, %r12 +# DROP + +# DUP + + movq %r11, %r12 +# CONST (1) + + movq $3, %r13 +# ELEM + + pushq %rdi + pushq %rsi + pushq %r10 + pushq %r11 + movq %r13, %rsi + movq %r12, %rdi + movq $2, %r11 + call Belem + popq %r11 + popq %r10 + popq %rsi + popq %rdi + movq %rax, %r12 +# DROP + +# DUP + + movq %r11, %r12 +# CONST (2) + + movq $5, %r13 +# ELEM + + pushq %rdi + pushq %rsi + pushq %r10 + pushq %r11 + movq %r13, %rsi + movq %r12, %rdi + movq $2, %r11 + call Belem + popq %r11 + popq %r10 + popq %rsi + popq %rdi + movq %rax, %r12 +# DROP + +# DROP + +# DUP + + movq %r10, %r11 +# ST (Local (0)) + + movq %r11, -8(%rbp) +# DROP + +# DROP + +# SLABEL ("L54") + +L54: + +# LINE (20) + + .stabn 68,0,20,.L6 + +.L6: + +# LD (Local (0)) + + movq -8(%rbp), %r10 +# DUP + + movq %r10, %r11 +# SLABEL ("L60") + +L60: + +# DUP + + movq %r11, %r12 +# TAG ("A", 3) + + movq $55, %r13 + movq $7, %r14 + pushq %rdi + pushq %rsi + pushq %r10 + pushq %r11 + movq %r14, %rdx + movq %r13, %rsi + movq %r12, %rdi + movq $3, %r11 + call Btag + popq %r11 + popq %r10 + popq %rsi + popq %rdi + movq %rax, %r12 +# CJMP ("nz", "L58") + + sarq %r12 + cmpq $0, %r12 + jnz L58 +# LABEL ("L59") + +L59: + +# DROP + +# JMP ("L56") + + jmp L56 +# LABEL ("L58") + +L58: + +# DUP + + movq %r11, %r12 +# CONST (0) + + movq $1, %r13 +# ELEM + + pushq %rdi + pushq %rsi + pushq %r10 + pushq %r11 + movq %r13, %rsi + movq %r12, %rdi + movq $2, %r11 + call Belem + popq %r11 + popq %r10 + popq %rsi + popq %rdi + movq %rax, %r12 +# DROP + +# DUP + + movq %r11, %r12 +# CONST (1) + + movq $3, %r13 +# ELEM + + pushq %rdi + pushq %rsi + pushq %r10 + pushq %r11 + movq %r13, %rsi + movq %r12, %rdi + movq $2, %r11 + call Belem + popq %r11 + popq %r10 + popq %rsi + popq %rdi + movq %rax, %r12 +# DROP + +# DUP + + movq %r11, %r12 +# CONST (2) + + movq $5, %r13 +# ELEM + + pushq %rdi + pushq %rsi + pushq %r10 + pushq %r11 + movq %r13, %rsi + movq %r12, %rdi + movq $2, %r11 + call Belem + popq %r11 + popq %r10 + popq %rsi + popq %rdi + movq %rax, %r12 +# DROP + +# DROP + +# DUP + + movq %r10, %r11 +# CONST (0) + + movq $1, %r12 +# ELEM + + pushq %rdi + pushq %rsi + pushq %r10 + pushq filler(%rip) + movq %r12, %rsi + movq %r11, %rdi + movq $2, %r11 + call Belem + addq $8, %rsp + popq %r10 + popq %rsi + popq %rdi + movq %rax, %r11 +# ST (Local (3)) + + movq %r11, -32(%rbp) +# DROP + +# DUP + + movq %r10, %r11 +# CONST (1) + + movq $3, %r12 +# ELEM + + pushq %rdi + pushq %rsi + pushq %r10 + pushq filler(%rip) + movq %r12, %rsi + movq %r11, %rdi + movq $2, %r11 + call Belem + addq $8, %rsp + popq %r10 + popq %rsi + popq %rdi + movq %rax, %r11 +# ST (Local (2)) + + movq %r11, -24(%rbp) +# DROP + +# DUP + + movq %r10, %r11 +# CONST (2) + + movq $5, %r12 +# ELEM + + pushq %rdi + pushq %rsi + pushq %r10 + pushq filler(%rip) + movq %r12, %rsi + movq %r11, %rdi + movq $2, %r11 + call Belem + addq $8, %rsp + popq %r10 + popq %rsi + popq %rdi + movq %rax, %r11 +# ST (Local (1)) + + movq %r11, -16(%rbp) +# DROP + +# DROP + +# SLABEL ("L62") + +L62: + +# LINE (21) + + .stabn 68,0,21,.L7 + +.L7: + +# LD (Local (3)) + + movq -32(%rbp), %r10 +# CALL ("Lwrite", 1, false) + + pushq %rdi + pushq %rsi + movq %r10, %rdi + movq $1, %r11 + call Lwrite + popq %rsi + popq %rdi + movq %rax, %r10 +# DROP + +# LD (Local (2)) + + movq -24(%rbp), %r10 +# CALL ("Lwrite", 1, false) + + pushq %rdi + pushq %rsi + movq %r10, %rdi + movq $1, %r11 + call Lwrite + popq %rsi + popq %rdi + movq %rax, %r10 +# DROP + +# LD (Local (1)) + + movq -16(%rbp), %r10 +# CALL ("Lwrite", 1, false) + + pushq %rdi + pushq %rsi + movq %r10, %rdi + movq $1, %r11 + call Lwrite + popq %rsi + popq %rdi + movq %rax, %r10 +# DROP + +# SLABEL ("L63") + +L63: + +# SLABEL ("L61") + +L61: + +# JMP ("L35") + + jmp L35 +# LABEL ("L56") + +L56: + +# FAIL ((20, 24), false) + + movq $24, %r13 + movq $20, %r12 + leaq string_0(%rip), %r11 + movq %r10, %r10 + pushq %rdi + pushq %rsi + movq %r13, %rcx + movq %r12, %rdx + movq %r11, %rsi + movq %r10, %rdi + movq $4, %r11 + call Bmatch_failure + popq %rsi + popq %rdi + movq %rax, %r10 +# JMP ("L35") + + jmp L35 +# SLABEL ("L55") + +L55: + +# SLABEL ("L53") + +L53: + +# JMP ("L35") + +# LABEL ("L36") + +L36: + +# FAIL ((18, 5), false) + + movq $5, %r13 + movq $18, %r12 + leaq string_0(%rip), %r11 + movq %r10, %r10 + pushq %rdi + pushq %rsi + movq %r13, %rcx + movq %r12, %rdx + movq %r11, %rsi + movq %r10, %rdi + movq $4, %r11 + call Bmatch_failure + popq %rsi + popq %rdi + movq %rax, %r10 +# JMP ("L35") + + jmp L35 +# LABEL ("L35") + +L35: + +# CONST (1) + + movq $3, %r10 +# CONST (2) + + movq $5, %r11 +# CONST (3) + + movq $7, %r12 +# CONST (4) + + movq $9, %r13 +# CONST (5) + + movq $11, %r14 +# SEXP ("A", 5) + + movq $55, -40(%rbp) + pushq %rdi + pushq %rsi + pushq -40(%rbp) + pushq %r14 + pushq %r13 + pushq %r12 + pushq %r11 + pushq %r10 + movq %rsp, %rdi + movq $13, %rsi + call Bsexp + addq $48, %rsp + popq %rsi + popq %rdi + movq %rax, %r10 +# DUP + + movq %r10, %r11 +# SLABEL ("L83") + +L83: + +# DUP + + movq %r11, %r12 +# TAG ("A", 0) + + movq $55, %r13 + movq $1, %r14 + pushq %rdi + pushq %rsi + pushq %r10 + pushq %r11 + movq %r14, %rdx + movq %r13, %rsi + movq %r12, %rdi + movq $3, %r11 + call Btag + popq %r11 + popq %r10 + popq %rsi + popq %rdi + movq %rax, %r12 +# CJMP ("nz", "L81") + + sarq %r12 + cmpq $0, %r12 + jnz L81 +# LABEL ("L82") + +L82: + +# DROP + +# JMP ("L80") + + jmp L80 +# LABEL ("L81") + +L81: + +# DROP + +# DROP + +# SLABEL ("L85") + +L85: + +# LINE (26) + + .stabn 68,0,26,.L8 + +.L8: + +# CONST (0) + + movq $1, %r10 +# CALL ("Lwrite", 1, false) + + pushq %rdi + pushq %rsi + movq %r10, %rdi + movq $1, %r11 + call Lwrite + popq %rsi + popq %rdi + movq %rax, %r10 +# DROP + +# SLABEL ("L86") + +L86: + +# JMP ("L72") + + jmp L72 +# SLABEL ("L84") + +L84: + +# SLABEL ("L92") + +L92: + +# LABEL ("L80") + +L80: + +# DUP + + movq %r10, %r11 +# DUP + + movq %r11, %r12 +# TAG ("A", 1) + + movq $55, %r13 + movq $3, %r14 + pushq %rdi + pushq %rsi + pushq %r10 + pushq %r11 + movq %r14, %rdx + movq %r13, %rsi + movq %r12, %rdi + movq $3, %r11 + call Btag + popq %r11 + popq %r10 + popq %rsi + popq %rdi + movq %rax, %r12 +# CJMP ("nz", "L90") + + sarq %r12 + cmpq $0, %r12 + jnz L90 +# LABEL ("L91") + +L91: + +# DROP + +# JMP ("L89") + + jmp L89 +# LABEL ("L90") + +L90: + +# DUP + + movq %r11, %r12 +# CONST (0) + + movq $1, %r13 +# ELEM + + pushq %rdi + pushq %rsi + pushq %r10 + pushq %r11 + movq %r13, %rsi + movq %r12, %rdi + movq $2, %r11 + call Belem + popq %r11 + popq %r10 + popq %rsi + popq %rdi + movq %rax, %r12 +# DROP + +# DROP + +# DROP + +# SLABEL ("L94") + +L94: + +# LINE (27) + + .stabn 68,0,27,.L9 + +.L9: + +# CONST (1) + + movq $3, %r10 +# CALL ("Lwrite", 1, false) + + pushq %rdi + pushq %rsi + movq %r10, %rdi + movq $1, %r11 + call Lwrite + popq %rsi + popq %rdi + movq %rax, %r10 +# DROP + +# SLABEL ("L95") + +L95: + +# JMP ("L72") + + jmp L72 +# SLABEL ("L93") + +L93: + +# SLABEL ("L101") + +L101: + +# LABEL ("L89") + +L89: + +# DUP + + movq %r10, %r11 +# DUP + + movq %r11, %r12 +# TAG ("A", 2) + + movq $55, %r13 + movq $5, %r14 + pushq %rdi + pushq %rsi + pushq %r10 + pushq %r11 + movq %r14, %rdx + movq %r13, %rsi + movq %r12, %rdi + movq $3, %r11 + call Btag + popq %r11 + popq %r10 + popq %rsi + popq %rdi + movq %rax, %r12 +# CJMP ("nz", "L99") + + sarq %r12 + cmpq $0, %r12 + jnz L99 +# LABEL ("L100") + +L100: + +# DROP + +# JMP ("L98") + + jmp L98 +# LABEL ("L99") + +L99: + +# DUP + + movq %r11, %r12 +# CONST (0) + + movq $1, %r13 +# ELEM + + pushq %rdi + pushq %rsi + pushq %r10 + pushq %r11 + movq %r13, %rsi + movq %r12, %rdi + movq $2, %r11 + call Belem + popq %r11 + popq %r10 + popq %rsi + popq %rdi + movq %rax, %r12 +# DROP + +# DUP + + movq %r11, %r12 +# CONST (1) + + movq $3, %r13 +# ELEM + + pushq %rdi + pushq %rsi + pushq %r10 + pushq %r11 + movq %r13, %rsi + movq %r12, %rdi + movq $2, %r11 + call Belem + popq %r11 + popq %r10 + popq %rsi + popq %rdi + movq %rax, %r12 +# DROP + +# DROP + +# DROP + +# SLABEL ("L103") + +L103: + +# LINE (28) + + .stabn 68,0,28,.L10 + +.L10: + +# CONST (2) + + movq $5, %r10 +# CALL ("Lwrite", 1, false) + + pushq %rdi + pushq %rsi + movq %r10, %rdi + movq $1, %r11 + call Lwrite + popq %rsi + popq %rdi + movq %rax, %r10 +# DROP + +# SLABEL ("L104") + +L104: + +# JMP ("L72") + + jmp L72 +# SLABEL ("L102") + +L102: + +# SLABEL ("L110") + +L110: + +# LABEL ("L98") + +L98: + +# DUP + + movq %r10, %r11 +# DUP + + movq %r11, %r12 +# TAG ("A", 3) + + movq $55, %r13 + movq $7, %r14 + pushq %rdi + pushq %rsi + pushq %r10 + pushq %r11 + movq %r14, %rdx + movq %r13, %rsi + movq %r12, %rdi + movq $3, %r11 + call Btag + popq %r11 + popq %r10 + popq %rsi + popq %rdi + movq %rax, %r12 +# CJMP ("nz", "L108") + + sarq %r12 + cmpq $0, %r12 + jnz L108 +# LABEL ("L109") + +L109: + +# DROP + +# JMP ("L107") + + jmp L107 +# LABEL ("L108") + +L108: + +# DUP + + movq %r11, %r12 +# CONST (0) + + movq $1, %r13 +# ELEM + + pushq %rdi + pushq %rsi + pushq %r10 + pushq %r11 + movq %r13, %rsi + movq %r12, %rdi + movq $2, %r11 + call Belem + popq %r11 + popq %r10 + popq %rsi + popq %rdi + movq %rax, %r12 +# DROP + +# DUP + + movq %r11, %r12 +# CONST (1) + + movq $3, %r13 +# ELEM + + pushq %rdi + pushq %rsi + pushq %r10 + pushq %r11 + movq %r13, %rsi + movq %r12, %rdi + movq $2, %r11 + call Belem + popq %r11 + popq %r10 + popq %rsi + popq %rdi + movq %rax, %r12 +# DROP + +# DUP + + movq %r11, %r12 +# CONST (2) + + movq $5, %r13 +# ELEM + + pushq %rdi + pushq %rsi + pushq %r10 + pushq %r11 + movq %r13, %rsi + movq %r12, %rdi + movq $2, %r11 + call Belem + popq %r11 + popq %r10 + popq %rsi + popq %rdi + movq %rax, %r12 +# DROP + +# DROP + +# DROP + +# SLABEL ("L112") + +L112: + +# LINE (29) + + .stabn 68,0,29,.L11 + +.L11: + +# CONST (3) + + movq $7, %r10 +# CALL ("Lwrite", 1, false) + + pushq %rdi + pushq %rsi + movq %r10, %rdi + movq $1, %r11 + call Lwrite + popq %rsi + popq %rdi + movq %rax, %r10 +# DROP + +# SLABEL ("L113") + +L113: + +# JMP ("L72") + + jmp L72 +# SLABEL ("L111") + +L111: + +# SLABEL ("L119") + +L119: + +# LABEL ("L107") + +L107: + +# DUP + + movq %r10, %r11 +# DUP + + movq %r11, %r12 +# TAG ("A", 4) + + movq $55, %r13 + movq $9, %r14 + pushq %rdi + pushq %rsi + pushq %r10 + pushq %r11 + movq %r14, %rdx + movq %r13, %rsi + movq %r12, %rdi + movq $3, %r11 + call Btag + popq %r11 + popq %r10 + popq %rsi + popq %rdi + movq %rax, %r12 +# CJMP ("nz", "L117") + + sarq %r12 + cmpq $0, %r12 + jnz L117 +# LABEL ("L118") + +L118: + +# DROP + +# JMP ("L116") + + jmp L116 +# LABEL ("L117") + +L117: + +# DUP + + movq %r11, %r12 +# CONST (0) + + movq $1, %r13 +# ELEM + + pushq %rdi + pushq %rsi + pushq %r10 + pushq %r11 + movq %r13, %rsi + movq %r12, %rdi + movq $2, %r11 + call Belem + popq %r11 + popq %r10 + popq %rsi + popq %rdi + movq %rax, %r12 +# DROP + +# DUP + + movq %r11, %r12 +# CONST (1) + + movq $3, %r13 +# ELEM + + pushq %rdi + pushq %rsi + pushq %r10 + pushq %r11 + movq %r13, %rsi + movq %r12, %rdi + movq $2, %r11 + call Belem + popq %r11 + popq %r10 + popq %rsi + popq %rdi + movq %rax, %r12 +# DROP + +# DUP + + movq %r11, %r12 +# CONST (2) + + movq $5, %r13 +# ELEM + + pushq %rdi + pushq %rsi + pushq %r10 + pushq %r11 + movq %r13, %rsi + movq %r12, %rdi + movq $2, %r11 + call Belem + popq %r11 + popq %r10 + popq %rsi + popq %rdi + movq %rax, %r12 +# DROP + +# DUP + + movq %r11, %r12 +# CONST (3) + + movq $7, %r13 +# ELEM + + pushq %rdi + pushq %rsi + pushq %r10 + pushq %r11 + movq %r13, %rsi + movq %r12, %rdi + movq $2, %r11 + call Belem + popq %r11 + popq %r10 + popq %rsi + popq %rdi + movq %rax, %r12 +# DROP + +# DROP + +# DROP + +# SLABEL ("L121") + +L121: + +# LINE (30) + + .stabn 68,0,30,.L12 + +.L12: + +# CONST (4) + + movq $9, %r10 +# CALL ("Lwrite", 1, false) + + pushq %rdi + pushq %rsi + movq %r10, %rdi + movq $1, %r11 + call Lwrite + popq %rsi + popq %rdi + movq %rax, %r10 +# DROP + +# SLABEL ("L122") + +L122: + +# JMP ("L72") + + jmp L72 +# SLABEL ("L120") + +L120: + +# SLABEL ("L127") + +L127: + +# LABEL ("L116") + +L116: + +# DUP + + movq %r10, %r11 +# DUP + + movq %r11, %r12 +# TAG ("A", 5) + + movq $55, %r13 + movq $11, %r14 + pushq %rdi + pushq %rsi + pushq %r10 + pushq %r11 + movq %r14, %rdx + movq %r13, %rsi + movq %r12, %rdi + movq $3, %r11 + call Btag + popq %r11 + popq %r10 + popq %rsi + popq %rdi + movq %rax, %r12 +# CJMP ("nz", "L125") + + sarq %r12 + cmpq $0, %r12 + jnz L125 +# LABEL ("L126") + +L126: + +# DROP + +# JMP ("L73") + + jmp L73 +# LABEL ("L125") + +L125: + +# DUP + + movq %r11, %r12 +# CONST (0) + + movq $1, %r13 +# ELEM + + pushq %rdi + pushq %rsi + pushq %r10 + pushq %r11 + movq %r13, %rsi + movq %r12, %rdi + movq $2, %r11 + call Belem + popq %r11 + popq %r10 + popq %rsi + popq %rdi + movq %rax, %r12 +# DROP + +# DUP + + movq %r11, %r12 +# CONST (1) + + movq $3, %r13 +# ELEM + + pushq %rdi + pushq %rsi + pushq %r10 + pushq %r11 + movq %r13, %rsi + movq %r12, %rdi + movq $2, %r11 + call Belem + popq %r11 + popq %r10 + popq %rsi + popq %rdi + movq %rax, %r12 +# DROP + +# DUP + + movq %r11, %r12 +# CONST (2) + + movq $5, %r13 +# ELEM + + pushq %rdi + pushq %rsi + pushq %r10 + pushq %r11 + movq %r13, %rsi + movq %r12, %rdi + movq $2, %r11 + call Belem + popq %r11 + popq %r10 + popq %rsi + popq %rdi + movq %rax, %r12 +# DROP + +# DUP + + movq %r11, %r12 +# CONST (3) + + movq $7, %r13 +# ELEM + + pushq %rdi + pushq %rsi + pushq %r10 + pushq %r11 + movq %r13, %rsi + movq %r12, %rdi + movq $2, %r11 + call Belem + popq %r11 + popq %r10 + popq %rsi + popq %rdi + movq %rax, %r12 +# DROP + +# DUP + + movq %r11, %r12 +# CONST (4) + + movq $9, %r13 +# ELEM + + pushq %rdi + pushq %rsi + pushq %r10 + pushq %r11 + movq %r13, %rsi + movq %r12, %rdi + movq $2, %r11 + call Belem + popq %r11 + popq %r10 + popq %rsi + popq %rdi + movq %rax, %r12 +# DROP + +# DROP + +# DROP + +# SLABEL ("L129") + +L129: + +# LINE (31) + + .stabn 68,0,31,.L13 + +.L13: + +# CONST (5) + + movq $11, %r10 +# CALL ("Lwrite", 1, false) + + pushq %rdi + pushq %rsi + movq %r10, %rdi + movq $1, %r11 + call Lwrite + popq %rsi + popq %rdi + movq %rax, %r10 +# DROP + +# SLABEL ("L130") + +L130: + +# SLABEL ("L128") + +L128: + +# JMP ("L72") + + jmp L72 +# LABEL ("L73") + +L73: + +# FAIL ((25, 5), false) + + movq $5, %r13 + movq $25, %r12 + leaq string_0(%rip), %r11 + movq %r10, %r10 + pushq %rdi + pushq %rsi + movq %r13, %rcx + movq %r12, %rdx + movq %r11, %rsi + movq %r10, %rdi + movq $4, %r11 + call Bmatch_failure + popq %rsi + popq %rdi + movq %rax, %r10 +# JMP ("L72") + + jmp L72 +# LABEL ("L72") + +L72: + +# LINE (32) + + .stabn 68,0,32,.L14 + +.L14: + +# CONST (1) + + movq $3, %r10 +# CONST (2) + + movq $5, %r11 +# CONST (3) + + movq $7, %r12 +# CONST (4) + + movq $9, %r13 +# CONST (5) + + movq $11, %r14 +# SEXP ("A", 5) + + movq $55, -40(%rbp) + pushq %rdi + pushq %rsi + pushq -40(%rbp) + pushq %r14 + pushq %r13 + pushq %r12 + pushq %r11 + pushq %r10 + movq %rsp, %rdi + movq $13, %rsi + call Bsexp + addq $48, %rsp + popq %rsi + popq %rdi + movq %rax, %r10 +# CALL ("Llength", 1, false) + + pushq %rdi + pushq %rsi + movq %r10, %rdi + movq $1, %r11 + call Llength + popq %rsi + popq %rdi + movq %rax, %r10 +# CALL ("Lwrite", 1, false) + + pushq %rdi + pushq %rsi + movq %r10, %rdi + movq $1, %r11 + call Lwrite + popq %rsi + popq %rdi + movq %rax, %r10 +# DROP + +# LINE (34) + + .stabn 68,0,34,.L15 + +.L15: + +# CONST (1) + + movq $3, %r10 +# CONST (2) + + movq $5, %r11 +# CONST (3) + + movq $7, %r12 +# CONST (4) + + movq $9, %r13 +# CONST (5) + + movq $11, %r14 +# SEXP ("A", 5) + + movq $55, -40(%rbp) + pushq %rdi + pushq %rsi + pushq -40(%rbp) + pushq %r14 + pushq %r13 + pushq %r12 + pushq %r11 + pushq %r10 + movq %rsp, %rdi + movq $13, %rsi + call Bsexp + addq $48, %rsp + popq %rsi + popq %rdi + movq %rax, %r10 +# CONST (0) + + movq $1, %r11 +# ELEM + + pushq %rdi + pushq %rsi + movq %r11, %rsi + movq %r10, %rdi + movq $2, %r11 + call Belem + popq %rsi + popq %rdi + movq %rax, %r10 +# CALL ("Lwrite", 1, false) + + pushq %rdi + pushq %rsi + movq %r10, %rdi + movq $1, %r11 + call Lwrite + popq %rsi + popq %rdi + movq %rax, %r10 +# DROP + +# LINE (36) + + .stabn 68,0,36,.L16 + +.L16: + +# CONST (1) + + movq $3, %r10 +# CONST (2) + + movq $5, %r11 +# CONST (3) + + movq $7, %r12 +# CONST (4) + + movq $9, %r13 +# CONST (5) + + movq $11, %r14 +# SEXP ("A", 5) + + movq $55, -40(%rbp) + pushq %rdi + pushq %rsi + pushq -40(%rbp) + pushq %r14 + pushq %r13 + pushq %r12 + pushq %r11 + pushq %r10 + movq %rsp, %rdi + movq $13, %rsi + call Bsexp + addq $48, %rsp + popq %rsi + popq %rdi + movq %rax, %r10 +# CONST (1) + + movq $3, %r11 +# ELEM + + pushq %rdi + pushq %rsi + movq %r11, %rsi + movq %r10, %rdi + movq $2, %r11 + call Belem + popq %rsi + popq %rdi + movq %rax, %r10 +# CALL ("Lwrite", 1, false) + + pushq %rdi + pushq %rsi + movq %r10, %rdi + movq $1, %r11 + call Lwrite + popq %rsi + popq %rdi + movq %rax, %r10 +# DROP + +# LINE (37) + + .stabn 68,0,37,.L17 + +.L17: + +# CONST (1) + + movq $3, %r10 +# CONST (2) + + movq $5, %r11 +# CONST (3) + + movq $7, %r12 +# CONST (4) + + movq $9, %r13 +# CONST (5) + + movq $11, %r14 +# SEXP ("A", 5) + + movq $55, -40(%rbp) + pushq %rdi + pushq %rsi + pushq -40(%rbp) + pushq %r14 + pushq %r13 + pushq %r12 + pushq %r11 + pushq %r10 + movq %rsp, %rdi + movq $13, %rsi + call Bsexp + addq $48, %rsp + popq %rsi + popq %rdi + movq %rax, %r10 +# CONST (2) + + movq $5, %r11 +# ELEM + + pushq %rdi + pushq %rsi + movq %r11, %rsi + movq %r10, %rdi + movq $2, %r11 + call Belem + popq %rsi + popq %rdi + movq %rax, %r10 +# CALL ("Lwrite", 1, false) + + pushq %rdi + pushq %rsi + movq %r10, %rdi + movq $1, %r11 + call Lwrite + popq %rsi + popq %rdi + movq %rax, %r10 +# DROP + +# LINE (38) + + .stabn 68,0,38,.L18 + +.L18: + +# CONST (1) + + movq $3, %r10 +# CONST (2) + + movq $5, %r11 +# CONST (3) + + movq $7, %r12 +# CONST (4) + + movq $9, %r13 +# CONST (5) + + movq $11, %r14 +# SEXP ("A", 5) + + movq $55, -40(%rbp) + pushq %rdi + pushq %rsi + pushq -40(%rbp) + pushq %r14 + pushq %r13 + pushq %r12 + pushq %r11 + pushq %r10 + movq %rsp, %rdi + movq $13, %rsi + call Bsexp + addq $48, %rsp + popq %rsi + popq %rdi + movq %rax, %r10 +# CONST (3) + + movq $7, %r11 +# ELEM + + pushq %rdi + pushq %rsi + movq %r11, %rsi + movq %r10, %rdi + movq $2, %r11 + call Belem + popq %rsi + popq %rdi + movq %rax, %r10 +# CALL ("Lwrite", 1, false) + + pushq %rdi + pushq %rsi + movq %r10, %rdi + movq $1, %r11 + call Lwrite + popq %rsi + popq %rdi + movq %rax, %r10 +# DROP + +# LINE (39) + + .stabn 68,0,39,.L19 + +.L19: + +# CONST (1) + + movq $3, %r10 +# CONST (2) + + movq $5, %r11 +# CONST (3) + + movq $7, %r12 +# CONST (4) + + movq $9, %r13 +# CONST (5) + + movq $11, %r14 +# SEXP ("A", 5) + + movq $55, -40(%rbp) + pushq %rdi + pushq %rsi + pushq -40(%rbp) + pushq %r14 + pushq %r13 + pushq %r12 + pushq %r11 + pushq %r10 + movq %rsp, %rdi + movq $13, %rsi + call Bsexp + addq $48, %rsp + popq %rsi + popq %rdi + movq %rax, %r10 +# CONST (4) + + movq $9, %r11 +# ELEM + + pushq %rdi + pushq %rsi + movq %r11, %rsi + movq %r10, %rdi + movq $2, %r11 + call Belem + popq %rsi + popq %rdi + movq %rax, %r10 +# CALL ("Lwrite", 1, false) + + pushq %rdi + pushq %rsi + movq %r10, %rdi + movq $1, %r11 + call Lwrite + popq %rsi + popq %rdi + movq %rax, %r10 +# SLABEL ("L2") + +L2: + +# END + + movq %r10, %rax +Lmain_epilogue: + + movq %rbp, %rsp + popq %rbp + xorq %rax, %rax + .cfi_restore 5 + + .cfi_def_cfa 4, 4 + + ret + .cfi_endproc + + .set Lmain_SIZE, 48 + + .set LSmain_SIZE, 5 + + .size main, .-main + diff --git a/byterun/test046.sm b/byterun/test046.sm new file mode 100644 index 000000000..72a74bc25 --- /dev/null +++ b/byterun/test046.sm @@ -0,0 +1,490 @@ +IMPORT ("Std") +PUBLIC ("main") +EXTERN ("Llowercase") +EXTERN ("Luppercase") +EXTERN ("LtagHash") +EXTERN ("LflatCompare") +EXTERN ("LcompareTags") +EXTERN ("LkindOf") +EXTERN ("Ltime") +EXTERN ("Lrandom") +EXTERN ("LdisableGC") +EXTERN ("LenableGC") +EXTERN ("Ls__Infix_37") +EXTERN ("Ls__Infix_47") +EXTERN ("Ls__Infix_42") +EXTERN ("Ls__Infix_45") +EXTERN ("Ls__Infix_43") +EXTERN ("Ls__Infix_62") +EXTERN ("Ls__Infix_6261") +EXTERN ("Ls__Infix_60") +EXTERN ("Ls__Infix_6061") +EXTERN ("Ls__Infix_3361") +EXTERN ("Ls__Infix_6161") +EXTERN ("Ls__Infix_3838") +EXTERN ("Ls__Infix_3333") +EXTERN ("Ls__Infix_58") +EXTERN ("Li__Infix_4343") +EXTERN ("Lcompare") +EXTERN ("Lwrite") +EXTERN ("Lread") +EXTERN ("Lfailure") +EXTERN ("Lfexists") +EXTERN ("Lfwrite") +EXTERN ("Lfread") +EXTERN ("Lfclose") +EXTERN ("Lfopen") +EXTERN ("Lfprintf") +EXTERN ("Lprintf") +EXTERN ("LmakeString") +EXTERN ("Lsprintf") +EXTERN ("LregexpMatch") +EXTERN ("Lregexp") +EXTERN ("Lsubstring") +EXTERN ("LmatchSubString") +EXTERN ("Lstringcat") +EXTERN ("LreadLine") +EXTERN ("Ltl") +EXTERN ("Lhd") +EXTERN ("Lsnd") +EXTERN ("Lfst") +EXTERN ("Lhash") +EXTERN ("Lclone") +EXTERN ("Llength") +EXTERN ("Lstring") +EXTERN ("LmakeArray") +EXTERN ("LstringInt") +EXTERN ("global_sysargs") +EXTERN ("Lsystem") +EXTERN ("LgetEnv") +EXTERN ("Lassert") +LABEL ("main") +BEGIN ("main", 2, 4, [], [], []) +SLABEL ("L1") +LINE (3) +CALL ("Lread", 0, false) +LINE (1) +ST (Global ("n")) +DROP +CONST (3) +DUP +SLABEL ("L11") +DROP +DUP +ST (Local (0)) +DROP +DROP +SLABEL ("L13") +LINE (6) +LD (Local (0)) +CALL ("Lwrite", 1, false) +DROP +SLABEL ("L14") +JMP ("L7") +SLABEL ("L12") +JMP ("L7") +LABEL ("L7") +CONST (3) +DUP +SLABEL ("L20") +DROP +DUP +ST (Local (0)) +DROP +DROP +SLABEL ("L22") +LINE (11) +LD (Local (0)) +CALL ("Lwrite", 1, false) +DROP +SLABEL ("L23") +SLABEL ("L21") +JMP ("L17") +LABEL ("L17") +CONST (3) +DUP +SLABEL ("L29") +DROP +DUP +ST (Local (0)) +DROP +DROP +SLABEL ("L31") +LINE (15) +LD (Local (0)) +CALL ("Lwrite", 1, false) +DROP +SLABEL ("L32") +SLABEL ("L30") +JMP ("L26") +LABEL ("L26") +CONST (1) +CONST (2) +CONST (3) +SEXP ("A", 3) +DUP +SLABEL ("L44") +DUP +TAG ("A", 0) +CJMP ("nz", "L42") +LABEL ("L43") +DROP +JMP ("L41") +LABEL ("L42") +DROP +DROP +SLABEL ("L46") +LINE (19) +CONST (1) +CALL ("Lwrite", 1, false) +DROP +SLABEL ("L47") +JMP ("L35") +SLABEL ("L45") +SLABEL ("L52") +LABEL ("L41") +DUP +DUP +TAG ("A", 3) +CJMP ("nz", "L50") +LABEL ("L51") +DROP +JMP ("L36") +LABEL ("L50") +DUP +CONST (0) +ELEM +DROP +DUP +CONST (1) +ELEM +DROP +DUP +CONST (2) +ELEM +DROP +DROP +DUP +ST (Local (0)) +DROP +DROP +SLABEL ("L54") +LINE (20) +LD (Local (0)) +DUP +SLABEL ("L60") +DUP +TAG ("A", 3) +CJMP ("nz", "L58") +LABEL ("L59") +DROP +JMP ("L56") +LABEL ("L58") +DUP +CONST (0) +ELEM +DROP +DUP +CONST (1) +ELEM +DROP +DUP +CONST (2) +ELEM +DROP +DROP +DUP +CONST (0) +ELEM +ST (Local (3)) +DROP +DUP +CONST (1) +ELEM +ST (Local (2)) +DROP +DUP +CONST (2) +ELEM +ST (Local (1)) +DROP +DROP +SLABEL ("L62") +LINE (21) +LD (Local (3)) +CALL ("Lwrite", 1, false) +DROP +LD (Local (2)) +CALL ("Lwrite", 1, false) +DROP +LD (Local (1)) +CALL ("Lwrite", 1, false) +DROP +SLABEL ("L63") +SLABEL ("L61") +JMP ("L35") +LABEL ("L56") +FAIL ((20, 24), false) +JMP ("L35") +SLABEL ("L55") +SLABEL ("L53") +JMP ("L35") +LABEL ("L36") +FAIL ((18, 5), false) +JMP ("L35") +LABEL ("L35") +CONST (1) +CONST (2) +CONST (3) +CONST (4) +CONST (5) +SEXP ("A", 5) +DUP +SLABEL ("L83") +DUP +TAG ("A", 0) +CJMP ("nz", "L81") +LABEL ("L82") +DROP +JMP ("L80") +LABEL ("L81") +DROP +DROP +SLABEL ("L85") +LINE (26) +CONST (0) +CALL ("Lwrite", 1, false) +DROP +SLABEL ("L86") +JMP ("L72") +SLABEL ("L84") +SLABEL ("L92") +LABEL ("L80") +DUP +DUP +TAG ("A", 1) +CJMP ("nz", "L90") +LABEL ("L91") +DROP +JMP ("L89") +LABEL ("L90") +DUP +CONST (0) +ELEM +DROP +DROP +DROP +SLABEL ("L94") +LINE (27) +CONST (1) +CALL ("Lwrite", 1, false) +DROP +SLABEL ("L95") +JMP ("L72") +SLABEL ("L93") +SLABEL ("L101") +LABEL ("L89") +DUP +DUP +TAG ("A", 2) +CJMP ("nz", "L99") +LABEL ("L100") +DROP +JMP ("L98") +LABEL ("L99") +DUP +CONST (0) +ELEM +DROP +DUP +CONST (1) +ELEM +DROP +DROP +DROP +SLABEL ("L103") +LINE (28) +CONST (2) +CALL ("Lwrite", 1, false) +DROP +SLABEL ("L104") +JMP ("L72") +SLABEL ("L102") +SLABEL ("L110") +LABEL ("L98") +DUP +DUP +TAG ("A", 3) +CJMP ("nz", "L108") +LABEL ("L109") +DROP +JMP ("L107") +LABEL ("L108") +DUP +CONST (0) +ELEM +DROP +DUP +CONST (1) +ELEM +DROP +DUP +CONST (2) +ELEM +DROP +DROP +DROP +SLABEL ("L112") +LINE (29) +CONST (3) +CALL ("Lwrite", 1, false) +DROP +SLABEL ("L113") +JMP ("L72") +SLABEL ("L111") +SLABEL ("L119") +LABEL ("L107") +DUP +DUP +TAG ("A", 4) +CJMP ("nz", "L117") +LABEL ("L118") +DROP +JMP ("L116") +LABEL ("L117") +DUP +CONST (0) +ELEM +DROP +DUP +CONST (1) +ELEM +DROP +DUP +CONST (2) +ELEM +DROP +DUP +CONST (3) +ELEM +DROP +DROP +DROP +SLABEL ("L121") +LINE (30) +CONST (4) +CALL ("Lwrite", 1, false) +DROP +SLABEL ("L122") +JMP ("L72") +SLABEL ("L120") +SLABEL ("L127") +LABEL ("L116") +DUP +DUP +TAG ("A", 5) +CJMP ("nz", "L125") +LABEL ("L126") +DROP +JMP ("L73") +LABEL ("L125") +DUP +CONST (0) +ELEM +DROP +DUP +CONST (1) +ELEM +DROP +DUP +CONST (2) +ELEM +DROP +DUP +CONST (3) +ELEM +DROP +DUP +CONST (4) +ELEM +DROP +DROP +DROP +SLABEL ("L129") +LINE (31) +CONST (5) +CALL ("Lwrite", 1, false) +DROP +SLABEL ("L130") +SLABEL ("L128") +JMP ("L72") +LABEL ("L73") +FAIL ((25, 5), false) +JMP ("L72") +LABEL ("L72") +LINE (32) +CONST (1) +CONST (2) +CONST (3) +CONST (4) +CONST (5) +SEXP ("A", 5) +CALL ("Llength", 1, false) +CALL ("Lwrite", 1, false) +DROP +LINE (34) +CONST (1) +CONST (2) +CONST (3) +CONST (4) +CONST (5) +SEXP ("A", 5) +CONST (0) +ELEM +CALL ("Lwrite", 1, false) +DROP +LINE (36) +CONST (1) +CONST (2) +CONST (3) +CONST (4) +CONST (5) +SEXP ("A", 5) +CONST (1) +ELEM +CALL ("Lwrite", 1, false) +DROP +LINE (37) +CONST (1) +CONST (2) +CONST (3) +CONST (4) +CONST (5) +SEXP ("A", 5) +CONST (2) +ELEM +CALL ("Lwrite", 1, false) +DROP +LINE (38) +CONST (1) +CONST (2) +CONST (3) +CONST (4) +CONST (5) +SEXP ("A", 5) +CONST (3) +ELEM +CALL ("Lwrite", 1, false) +DROP +LINE (39) +CONST (1) +CONST (2) +CONST (3) +CONST (4) +CONST (5) +SEXP ("A", 5) +CONST (4) +ELEM +CALL ("Lwrite", 1, false) +SLABEL ("L2") +END diff --git a/byterun/xmake.lua b/byterun/xmake.lua new file mode 100644 index 000000000..437b8814c --- /dev/null +++ b/byterun/xmake.lua @@ -0,0 +1,14 @@ +-- add_rules("mode.debug", "mode.release") +-- add_rules("c++.unity_build") + +set_languages("c++20", "c20") + +target("byterun") + set_kind("binary") + add_includedirs("include") + add_files("../runtime/runtime.a") + add_files("src/**.cpp", "src/**.c") + remove_files("src/compiler.cpp") + set_warnings("allextra") + set_rundir("$(projectdir)") +