global vars implementation, todo gc problems

This commit is contained in:
ProgramSnail 2025-05-11 11:02:07 +03:00
parent 474b0a8ed2
commit aff30ad7c1
12 changed files with 76 additions and 52 deletions

View file

@ -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%.*}"

View file

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

View file

@ -1,2 +1,3 @@
I,Std;
V,x;
F,f;

View file

@ -1 +1,3 @@
public x = 1;
public fun f(a, b) { a + b }

View file

@ -1,3 +1,4 @@
I,Std;
V,x;
F,f;
F,g;

View file

View file

@ -0,0 +1,3 @@
import Dep;
f(x, 1)

View file

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

View file

@ -1,3 +1,4 @@
#include <cstring>
#include <iostream>
extern "C" {
#include "interpreter.h"
@ -16,6 +17,9 @@ extern "C" {
#include <unordered_map>
#include <vector>
static const constexpr char *GLOBAL_VAR_TAG = "global_";
static const size_t GLOBAL_VAR_TAG_LEN = std::strlen(GLOBAL_VAR_TAG);
template <size_t N, bool return_value, typename... Args>
requires(N == 0)
void call_func(void (*f)(), size_t n, Args... args) {
@ -35,7 +39,6 @@ template <size_t N, bool return_value, typename... Args>
void call_func(void (*f)(), size_t n, Args... args) {
void *arg = s_pop();
call_func<N - 1, return_value, Args..., void *>(f, n, arg, args...);
// TODO: check that arg is added on the right position
}
template <size_t N, bool return_value, bool do_check = true>
@ -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<Bytefile *> &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<Bytefile *> &&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<Bytefile *> &&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<Bytefile *> &&bytefiles) {
// TODO: add publics + updat name offsets too ?())
std::unordered_map<std::string, size_t> publics;
std::vector<size_t> 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<Bytefile *> &&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<Bytefile *> &&bytefiles) {
}
}
code_offset += bytefiles[i]->code_size;
globals_offset += bytefiles[i]->global_area_size;
}
}
@ -332,9 +346,9 @@ MergeResult merge_files(std::vector<Bytefile *> &&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<Bytefile *> &&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;