diff --git a/byterun/dep_check.sh b/byterun/dep_check.sh index 305f500d9..64c0fcbe6 100755 --- a/byterun/dep_check.sh +++ b/byterun/dep_check.sh @@ -17,7 +17,7 @@ $compiler -b ../stdlib/List.lama $compiler -b ../stdlib/Ref.lama $compiler -b ../stdlib/Fun.lama -for test in regression/dep_test*.lama; do +for test in regression/dep_test*.lama; do echo $test $compiler -b $test -I regression/ test_path="${test%.*}" diff --git a/byterun/include/runtime_externs.h b/byterun/include/runtime_externs.h index 9a9bfb3b2..6adc7553c 100644 --- a/byterun/include/runtime_externs.h +++ b/byterun/include/runtime_externs.h @@ -105,9 +105,7 @@ void *Lstring(aint *p); void *Bclosure(aint *args, aint bn); void *Barray(aint *args, aint bn); -void *Barray_rev(aint *args, aint bn); void *Bsexp(aint *args, aint bn); -void *Bsexp_rev(aint *args, aint bn); aint Btag(void *d, aint t, aint n); aint get_tag(data *d); diff --git a/byterun/regression/Dep.i b/byterun/regression/Dep.i index e0493b13d..8c170ca46 100644 --- a/byterun/regression/Dep.i +++ b/byterun/regression/Dep.i @@ -1,2 +1,3 @@ I,Std; +V,x; F,f; diff --git a/byterun/regression/Dep.lama b/byterun/regression/Dep.lama index 22e955ccd..c5eb5a7c5 100644 --- a/byterun/regression/Dep.lama +++ b/byterun/regression/Dep.lama @@ -1 +1,3 @@ +public x = 1; + public fun f(a, b) { a + b } diff --git a/byterun/regression/Dep2.i b/byterun/regression/Dep2.i index 445dc0b22..9145dcb75 100644 --- a/byterun/regression/Dep2.i +++ b/byterun/regression/Dep2.i @@ -1,3 +1,4 @@ I,Std; +V,x; F,f; F,g; diff --git a/byterun/regression/dep_test004.input b/byterun/regression/dep_test004.input new file mode 100644 index 000000000..e69de29bb diff --git a/byterun/regression/dep_test004.lama b/byterun/regression/dep_test004.lama new file mode 100644 index 000000000..15365581e --- /dev/null +++ b/byterun/regression/dep_test004.lama @@ -0,0 +1,3 @@ +import Dep; + +f(x, 1) diff --git a/byterun/src/interpreter.c b/byterun/src/interpreter.c index 2a9a72cca..b2ce3d7cb 100644 --- a/byterun/src/interpreter.c +++ b/byterun/src/interpreter.c @@ -397,7 +397,6 @@ void run_main(Bytefile* bf, int argc, char **argv) { } #endif s_rotate_n(args_count); - // NOTE: call_offset < 0 => deal with closure of builtin function s_push_i(BOX(call_offset)); void *closure = Bclosure((aint *)__gc_stack_top, BOX(args_count)); @@ -472,12 +471,10 @@ void run_main(Bytefile* bf, int argc, char **argv) { call_builtin(builtin_id, args_count); if (s.is_closure_call) { // NOTE: all functions have returned value, some values undefined - // if (is_builtin_with_ret(builtin_id)) { - s_swap_tops(); - // } + s_swap_tops(); s_pop(); } - s.ip = s.call_ip; // TODO: check + s.ip = s.call_ip; break; } default: diff --git a/byterun/src/module_manager.cpp b/byterun/src/module_manager.cpp index 2816876f0..834569c2f 100644 --- a/byterun/src/module_manager.cpp +++ b/byterun/src/module_manager.cpp @@ -1,3 +1,4 @@ +#include #include extern "C" { #include "interpreter.h" @@ -16,6 +17,9 @@ extern "C" { #include #include +static const constexpr char *GLOBAL_VAR_TAG = "global_"; +static const size_t GLOBAL_VAR_TAG_LEN = std::strlen(GLOBAL_VAR_TAG); + template requires(N == 0) void call_func(void (*f)(), size_t n, Args... args) { @@ -35,7 +39,6 @@ template void call_func(void (*f)(), size_t n, Args... args) { void *arg = s_pop(); call_func(f, n, arg, args...); - // TODO: check that arg is added on the right position } template @@ -96,10 +99,10 @@ void rewrite_code_with_offsets(Bytefile *bytefile, const Offsets &offsets) { 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); - aint value = ip_read_int_unsafe(&read_ip); + aint id = ip_read_int_unsafe(&read_ip); if (to_var_category(arg_type) == VAR_GLOBAL) { write_ip = read_ip; - ip_write_int_unsafe(write_ip, value + offsets.globals); + ip_write_int_unsafe(write_ip, id + offsets.globals); } } break; @@ -109,12 +112,7 @@ void rewrite_code_with_offsets(Bytefile *bytefile, const Offsets &offsets) { case Cmd::ST: if (to_var_category(l) == VAR_GLOBAL) { aint id = ip_read_int_unsafe(&read_ip); - if (id > 0) { // NOTE: do not rewrite sysargs usages - ip_write_int_unsafe( - write_ip, - id - 1 + offsets.globals); // rewrite with exclusion of local - // module sysargs reference - } + ip_write_int_unsafe(write_ip, id + offsets.globals); } break; default: @@ -227,25 +225,26 @@ void subst_in_code(Bytefile *bytefile, *(uint32_t *)(bytefile->code_ptr + offset + sizeof(uint32_t)); *val_ptr = builtins.at({.id = builtin_id, .args_count = args_count}); - continue; - } + } else { + // NOTE: works with globals too + const auto it = publics.find(name); + if (it == publics.end()) { + failure("public name for substitution is not found: <%s>\n", name); + } - 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; } - - *(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}; + Offsets sizes{.strings = 0, + .globals = 1, // NOTE: V,sysargs from, Std + .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 - - 1; // NOTE: exclude default variable sysargs + sizes.globals += bytefiles[i]->global_area_size; sizes.code += bytefiles[i]->code_size; // sizes.publics_num += bytefiles[i]->public_symbols_number; } @@ -261,6 +260,13 @@ MergeResult merge_files(std::vector &&bytefiles) { Offsets sizes = calc_merge_sizes(bytefiles); size_t public_symbols_size = calc_publics_size(sizes.publics_num); +#ifdef DEBUG_VERSION + std::cout << "- inputs:\n"; + for (const auto &bf : bytefiles) { + print_file(*bf, std::cout); + } +#endif + // find all builtin variations ad extract them BuiltinSubstMap builtins_map; { @@ -274,9 +280,6 @@ MergeResult merge_files(std::vector &&bytefiles) { gen_builtins(sizes.code, builtins_map); sizes.code += builtins_code_size; - // V,sysparams fro, Std - ++sizes.globals; - Bytefile *result = (Bytefile *)malloc(sizeof(Bytefile) + sizes.strings + sizes.code + public_symbols_size); // globals are on the stack @@ -285,8 +288,13 @@ MergeResult merge_files(std::vector &&bytefiles) { // TODO: add publics + updat name offsets too ?()) std::unordered_map publics; std::vector main_offsets; + + // NOTE: V,sysargs from, Std + publics.insert({"global_sysargs", 0}); + { size_t code_offset = 0; + size_t globals_offset = 1; // NOTE: V,sysargs from, Std for (size_t i = 0; i < bytefiles.size(); ++i) { #ifdef DEBUG_VERSION printf("bytefile <%zu>\n", i); @@ -297,11 +305,16 @@ MergeResult merge_files(std::vector &&bytefiles) { 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; + + size_t offset = + get_public_offset_unsafe(bytefiles[i], j) + + (std::memcmp(name, GLOBAL_VAR_TAG, GLOBAL_VAR_TAG_LEN) == 0 + ? globals_offset // NOTE: is global id + : code_offset); // NOTE: is function offset in code #ifdef DEBUG_VERSION - printf("symbol %s : %zu (code offset %zu)\n", name, offset, - code_offset); + printf("symbol %s : %zu (code offset %zu, globals offset %zu)\n", name, + offset, code_offset, globals_offset); #endif if (strcmp(name, "main") == 0) { main_offsets.push_back(offset); @@ -310,6 +323,7 @@ MergeResult merge_files(std::vector &&bytefiles) { } } code_offset += bytefiles[i]->code_size; + globals_offset += bytefiles[i]->global_area_size; } } @@ -332,9 +346,9 @@ MergeResult merge_files(std::vector &&bytefiles) { // update & merge code segments Offsets offsets{.strings = 0, - .globals = 1, + .globals = 1, // NOTE: V,sysargs from, Std .code = 0, - .publics_num = 0}; // NOTE: one global: sysargs + .publics_num = 0}; // REMOVE printf("merge bytefiles\n"); for (size_t i = 0; i < bytefiles.size(); ++i) { // REMOVE printf("rewrite offsets %zu\n", i); @@ -358,8 +372,7 @@ MergeResult merge_files(std::vector &&bytefiles) { // update offsets offsets.strings += bytefiles[i]->stringtab_size; - offsets.globals += - bytefiles[i]->global_area_size - 1; // NOTE: exclude sysargs + offsets.globals += bytefiles[i]->global_area_size; offsets.code += bytefiles[i]->code_size; // offsets.publics_num += bytefiles[i]->public_symbols_number; @@ -584,10 +597,10 @@ BUILTIN id_by_builtin(const char *name) { // } /* NOTE: from src/X86_64.ml: */ -/* For vararg functions where we pass them in the stdlib function using va_list, - we have to unbox values to print them correctly. - For this we have special assemply functions in `printf.S`. - We additionally pass them amount of arguments to unbox using register r11. */ +/* For vararg functions where we pass them in the stdlib function using + va_list, we have to unbox values to print them correctly. For this we have + special assemply functions in `printf.S`. We additionally pass them amount + of arguments to unbox using register r11. */ void run_stdlib_func(BUILTIN id, size_t args_count) { // std::cout << "RUN BUILTIN: " << id << '\n'; // TODO: TMP void *ret = NULL; diff --git a/runtime/Makefile b/runtime/Makefile index f71efd909..1175157cd 100644 --- a/runtime/Makefile +++ b/runtime/Makefile @@ -9,7 +9,7 @@ endif DISABLE_WARNINGS=-Wno-shift-negative-value COMMON_FLAGS=$(DISABLE_WARNINGS) -g -fstack-protector-all $(ARCH) --std=c11 -PROD_FLAGS=$(COMMON_FLAGS) -DLAMA_ENV +PROD_FLAGS=$(COMMON_FLAGS) TEST_FLAGS=$(COMMON_FLAGS) -DDEBUG_VERSION UNIT_TESTS_FLAGS=$(TEST_FLAGS) INVARIANTS_CHECK_FLAGS=$(TEST_FLAGS) -DFULL_INVARIANT_CHECKS diff --git a/runtime/gc.h b/runtime/gc.h index 2cf7131d6..932a91609 100644 --- a/runtime/gc.h +++ b/runtime/gc.h @@ -37,7 +37,7 @@ #define SET_FORWARD_ADDRESS(x, addr) (x = ((x & 3) | ((ptrt)(addr)))) // if heap is full after gc shows in how many times it has to be extended #define EXTRA_ROOM_HEAP_COEFFICIENT 2 -#define MINIMUM_HEAP_CAPACITY (64) +#define MINIMUM_HEAP_CAPACITY (640000) #include #include diff --git a/src/SM.ml b/src/SM.ml index a0bb36363..5828ca8a8 100644 --- a/src/SM.ml +++ b/src/SM.ml @@ -176,16 +176,21 @@ module ByteCode = struct let externs = Stdlib.ref S.empty in let pubs = Stdlib.ref S.empty in let imports = Stdlib.ref S.empty in - let globals = Stdlib.ref @@ M.add "sysargs" 0 @@ M.empty in (* sysargs is a vaiable from Std *) - let glob_count = Stdlib.ref 1 in (* sysargs *) + let globals = Stdlib.ref @@ M.empty in + let glob_count = Stdlib.ref 1 in (* 0 is the placeholder for globals externs *) let fixups = Stdlib.ref [] in let func_fixups = Stdlib.ref [] in + let vars_substs = Stdlib.ref [] in let add_lab l = lmap := M.add l (Buffer.length code) !lmap in - let add_extern l = externs := S.add l !externs in + let add_extern l = + if String.starts_with ~prefix:"global_" l + then globals := M.add l 0 !globals (* 0 is the placeholder for globals externs *) + else externs := S.add l !externs in let add_public l = pubs := S.add l !pubs in let add_import l = imports := S.add l !imports in let add_fixup l = fixups := (Buffer.length code, l) :: !fixups in let add_func_fixup l = func_fixups := (Buffer.length code, l) :: !func_fixups in + let add_var_subst l = vars_substs := (Buffer.length code, l) :: !vars_substs in let add_bytes = List.iter (fun x -> Buffer.add_char code @@ Char.chr x) in let add_ints = List.iter (fun x -> Buffer.add_int32_ne code @@ Int32.of_int x) @@ -198,16 +203,17 @@ module ByteCode = struct let b x = match n with None -> x | Some b -> (b * 16) + x in List.iter (function | Value.Global s -> + let s' = "global_" ^ s in let i = - try M.find s !globals + try M.find s' !globals with Not_found -> let i = !glob_count in incr glob_count; - globals := M.add s i !globals; + globals := M.add s' i !globals; i in add_bytes [ b 0 ]; - add_ints [ i ] + if i == 0 then (add_var_subst s'; add_ints [ 0 ]) else add_ints [ i - 1 ] | Value.Local n -> add_bytes [ b 1 ]; add_ints [ n ] @@ -341,6 +347,7 @@ module ByteCode = struct let substs = Stdlib.ref [] in let add_subst c l = substs := (c, l) :: !substs in List.iter insn_code insns; + substs := !vars_substs; add_bytes [ 255 ]; let code = Buffer.to_bytes code in List.iter @@ -371,7 +378,9 @@ module ByteCode = struct ( Int32.of_int @@ StringTab.add st l, Int32.of_int @@ - try M.find l !lmap + let is_global = String.starts_with ~prefix:"global_" l in + (* 0 was reserved for extern globals *) + try (if is_global then Int.max (M.find l !globals - 1) 0 else M.find l !lmap) with Not_found -> failwith (Printf.sprintf "ERROR: undefined label of public '%s'" l) )) @@ S.elements !pubs @@ -386,7 +395,7 @@ module ByteCode = struct Buffer.add_char subst_table (Char.chr 0)) !substs; Buffer.add_int32_ne file (Int32.of_int @@ Bytes.length str_table); - Buffer.add_int32_ne file (Int32.of_int @@ !glob_count); + Buffer.add_int32_ne file (Int32.of_int @@ !glob_count - 1); (* 0 was reserved for extern globals *) Buffer.add_int32_ne file (Int32.of_int @@ Buffer.length subst_table); Buffer.add_int32_ne file (Int32.of_int @@ List.length imports); Buffer.add_int32_ne file (Int32.of_int @@ List.length pubs);