From e456304eb329169298e2cc35e9bf23f80e4f132f Mon Sep 17 00:00:00 2001 From: ProgramSnail Date: Thu, 14 Nov 2024 00:50:43 +0300 Subject: [PATCH] runtime fixes, byterun fixes --- byterun/Sort.bc | Bin 0 -> 839 bytes byterun/include/parser.h | 2 +- byterun/include/stack.h | 55 +++-- byterun/include/types.h | 77 ++++++- byterun/include/utils.h | 41 ++-- byterun/src/cli.c | 6 +- byterun/src/interpreter.c | 300 +++++++++++++------------- byterun/src/parser.c | 431 +++++++++++++++++++------------------- byterun/src/types.c | 6 +- runtime/gc.c | 2 +- runtime/runtime.c | 4 +- 11 files changed, 513 insertions(+), 411 deletions(-) create mode 100644 byterun/Sort.bc diff --git a/byterun/Sort.bc b/byterun/Sort.bc new file mode 100644 index 0000000000000000000000000000000000000000..29990be1a288b6db181dcfd2173f2c63cdae66c8 GIT binary patch literal 839 zcmZuw!A-+J5IhWo#0V(_&RWYL-424zk>@i&-OJ<|mSVp#PB<_2yP|nh%@g7ujc__z6%{_1iKP{n6O-^B z#T~_@s1Udiwpy~hB;5=ES+8~d`Wjd_>C!0iVq~WMyiNQve(5d0q?7H#((SUGX{(JZ ze*r7@6LD?4I30hraiD68iIn7gDglobal_area_size; + return (void **)__gc_stack_bottom - s.bf->global_area_size; } static inline bool s_is_empty() { - if (s.sp == s_top() || (s.fp != NULL && s.sp == f_locals(s.fp))) { + if ((void **)__gc_stack_top == s_top() || + (s.fp != NULL && (void **)__gc_stack_top == f_locals(s.fp))) { return true; } return false; @@ -26,39 +27,38 @@ static inline void **s_nth(aint n) { if (n < 0) { s_failure(&s, "can't access stack by negative index"); } - if (s.sp + n >= s_top()) { + if ((void **)__gc_stack_top + n >= s_top()) { s_failure(&s, "not enough elements in stack"); } - if (s.fp != NULL && s.sp + n >= f_locals(s.fp)) { + if (s.fp != NULL && (void **)__gc_stack_top + n >= f_locals(s.fp)) { s_failure(&s, "not enough elements in function stack"); } - return s.sp + n; + return (void **)__gc_stack_top + n; } static inline void **s_peek() { - if (s.sp == s_top()) { + if ((void **)__gc_stack_top == s_top()) { s_failure(&s, "empty stack"); } - if (s.fp != NULL && s.sp == f_locals(s.fp)) { + if (s.fp != NULL && (void **)__gc_stack_top == f_locals(s.fp)) { s_failure(&s, "empty function stack"); } - return s.sp; + return (void **)__gc_stack_top; } static inline aint *s_peek_i() { return (aint *)s_peek(); } static inline void s_push(void *val) { - if (s.sp == s.stack) { + if ((void **)__gc_stack_top == s.stack) { s_failure(&s, "stack overflow"); } #ifdef DEBUG_VERSION printf("--> push\n"); #endif - --s.sp; - *s.sp = val; - __gc_stack_top = (size_t)(s.sp) - (size_t)(s.sp) & 0xF; + __gc_stack_top -= sizeof(void *); + *(void **)__gc_stack_top = val; } static inline void s_push_i(aint val) { s_push((void *)val); } @@ -72,19 +72,18 @@ static inline void s_pushn_nil(size_t n) { } static inline void *s_pop() { - if (s.sp == s_top()) { + if ((void **)__gc_stack_top == s_top()) { s_failure(&s, "empty stack"); } - if (s.fp != NULL && s.sp == f_locals(s.fp)) { + if (s.fp != NULL && (void **)__gc_stack_top == f_locals(s.fp)) { s_failure(&s, "empty function stack"); } #ifdef DEBUG_VERSION printf("--> pop\n"); #endif - void *value = *s.sp; - *s.sp = NULL; - ++s.sp; - __gc_stack_top = (size_t)(s.sp) - (size_t)(s.sp) & 0xF; + void *value = *(void **)__gc_stack_top; + // *(void **)__gc_stack_top = NULL; + __gc_stack_top += sizeof(void *); return value; } @@ -112,11 +111,13 @@ static inline void s_enter_f(char *rp, bool is_closure_call, auint args_sz, #endif // check that params count is valid - if (s.sp + (aint)args_sz - (is_closure_call ? 0 : 1) >= s_top()) { + if ((void **)__gc_stack_top + (aint)args_sz - (is_closure_call ? 0 : 1) >= + s_top()) { s_failure(&s, "not enough parameters in stack"); } if (s.fp != NULL && - s.sp + (aint)args_sz - (is_closure_call ? 0 : 1) >= f_locals(s.fp)) { + (void **)__gc_stack_top + (aint)args_sz - (is_closure_call ? 0 : 1) >= + f_locals(s.fp)) { s_failure(&s, "not enough parameters in function stack"); } @@ -136,7 +137,7 @@ static inline void s_enter_f(char *rp, bool is_closure_call, auint args_sz, }; // put frame on stack - s.fp = (struct Frame *)s.sp; + s.fp = (struct Frame *)__gc_stack_top; (*s.fp) = frame; s_pushn_nil(locals_sz); @@ -148,10 +149,9 @@ static inline void s_exit_f() { } struct Frame frame = *s.fp; - push_extra_root((void **)&frame.ret); // drop stack entities, locals, frame - size_t to_pop = f_args(s.fp) - s.sp; + size_t to_pop = f_args(s.fp) - (void **)__gc_stack_top; s.fp = (struct Frame *)f_prev_fp(&frame); #ifdef DEBUG_VERSION printf("-> %zu to pop\n", to_pop); @@ -170,13 +170,11 @@ static inline void s_exit_f() { } s.ip = frame.rp; - - pop_extra_root((void **)&frame.ret); } static inline void print_stack() { - printf("stack (%i) is\n[", s.stack + STACK_SIZE - s.sp); - for (void **x = s.stack + STACK_SIZE - 1; x >= s.sp; --x) { + printf("stack (%i) is\n[", s.stack + STACK_SIZE - (void **)__gc_stack_top); + for (void **x = s.stack + STACK_SIZE - 1; x >= (void **)__gc_stack_top; --x) { printf("%li ", (long)UNBOX(*x)); } printf("]\n"); @@ -207,7 +205,8 @@ static inline void **var_by_category(enum VarCategory category, int id) { // f_locals_sz(s.fp)); } // printf("id is %i, local is %i, %i\n", id, - // UNBOX((auint)*((void**)f_locals(s.fp) + id)), f_locals(s.fp) - s.sp); + // UNBOX((auint)*((void**)f_locals(s.fp) + id)), f_locals(s.fp) - (void + // **)__gc_stack_top); var = f_locals(s.fp) + (f_locals_sz(s.fp) - id - 1); break; case VAR_ARGUMENT: diff --git a/byterun/include/types.h b/byterun/include/types.h index 9d033cba1..e4d4a928f 100644 --- a/byterun/include/types.h +++ b/byterun/include/types.h @@ -53,7 +53,7 @@ static inline void **f_args(struct Frame *fp) { struct State { void **stack; - void **sp; // stack pointer + // void **sp; // stack pointer struct Frame *fp; // function frame pointer bytefile *bf; int current_line; @@ -90,3 +90,78 @@ static inline enum VarCategory to_var_category(uint8_t category) { } return (enum VarCategory)category; } + +enum CMD { + CMD_BINOP = 0, + CMD_BASIC, + CMD_LD, + CMD_LDA, + CMD_ST, + CMD_CTRL, + CMD_PATT, + CMD_BUILTIN, + CMD_EXIT = 15, +}; + +enum CMD_BINOPS { + CMD_BINOP_ADD = 1, // + + CMD_BINOP_SUB, // - + CMD_BINOP_MULT, // * + CMD_BINOP_DIV, // / + CMD_BINOP_MOD, // % + CMD_BINOP_LEQ, // < + CMD_BINOP_LT, // <= + CMD_BINOP_GT, // > + CMD_BINOP_GEQ, // >= + CMD_BINOP_EQ, // == + CMD_BINOP_NEQ, // != + CMD_BINOP_AND, // && + CMD_BINOP_OR, // !! +}; + +enum CMD_BASICS { + CMD_BASIC_CONST = 0, + CMD_BASIC_STRING, + CMD_BASIC_SEXP, + CMD_BASIC_STI, + CMD_BASIC_STA, + CMD_BASIC_JMP, + CMD_BASIC_END, + CMD_BASIC_RET, + CMD_BASIC_DROP, + CMD_BASIC_DUP, + CMD_BASIC_SWAP, + CMD_BASIC_ELEM, +}; + +enum CMD_CTRLS { + CMD_CTRL_CJMPz = 0, + CMD_CTRL_CJMPnz, + CMD_CTRL_BEGIN, + CMD_CTRL_CBEGIN, + CMD_CTRL_CLOSURE, + CMD_CTRL_CALLC, + CMD_CTRL_CALL, + CMD_CTRL_TAG, + CMD_CTRL_ARRAY, + CMD_CTRL_FAIL, + CMD_CTRL_LINE, +}; + +enum CMD_PATTS { + CMD_PATT_STR = 0, + CMD_PATT_STR_TAG, + CMD_PATT_ARRAY_TAG, + CMD_PATT_SEXP_TAG, + CMD_PATT_REF_TAG, + CMD_PATT_VAL_TAG, + CMD_PATT_FUN_TAG, +}; + +enum CMD_BUILTINS { + CMD_BUILTIN_Lread = 0, + CMD_BUILTIN_Lwrite, + CMD_BUILTIN_Llength, + CMD_BUILTIN_Lstring, + CMD_BUILTIN_Barray, +}; diff --git a/byterun/include/utils.h b/byterun/include/utils.h index 1c3b11f39..f3986781e 100644 --- a/byterun/include/utils.h +++ b/byterun/include/utils.h @@ -20,25 +20,34 @@ typedef struct { char buffer[0]; } bytefile; -/* Gets a string from a string table by an index */ -static inline char *get_string(bytefile *f, size_t pos) { - return &f->string_ptr[pos]; -} - -/* Gets a name for a public symbol */ -static inline char *get_public_name(bytefile *f, size_t i) { - return get_string(f, f->public_ptr[i * 2]); -} - -/* Gets an offset for a publie symbol */ -static inline size_t get_public_offset(bytefile *f, size_t i) { - return f->public_ptr[i * 2 + 1]; -} - 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); } -// --- +/* Gets a string from a string table by an index */ +static inline const char *get_string(const bytefile *f, size_t pos) { + if (pos >= f->stringtab_size) { + failure("strinpg pos is out of range: %zu >= %i\n", pos, f->stringtab_size); + } + return &f->string_ptr[pos]; +} + +/* Gets a name for a public symbol */ +static inline const char *get_public_name(const bytefile *f, size_t i) { + if (i * 2 >= f->public_symbols_number) { + failure("public number is out of range: %zu >= %i\n", i * 2, + f->public_symbols_number); + } + return get_string(f, f->public_ptr[i * 2]); +} + +/* Gets an offset for a publie symbol */ +static inline size_t get_public_offset(const bytefile *f, size_t i) { + if (i * 2 + 1 >= f->public_symbols_number) { + failure("public number is out of range: %zu >= %i\n", i * 2 + 1, + f->public_symbols_number); + } + return f->public_ptr[i * 2 + 1]; +} diff --git a/byterun/src/cli.c b/byterun/src/cli.c index dca7f954f..c0d0a2dc3 100644 --- a/byterun/src/cli.c +++ b/byterun/src/cli.c @@ -10,9 +10,9 @@ int main(int argc, char** argv) { // printf("size of aint is %i\n", sizeof(aint)); bytefile *f = read_file(argv[1]); -#ifdef DEBUG_VERSION - dump_file (stdout, f); -#endif +// #ifdef DEBUG_VERSION +// dump_file (stdout, f); +// #endif run(f, argc - 1, argv + 1); free(f->global_ptr); diff --git a/byterun/src/interpreter.c b/byterun/src/interpreter.c index 15bc22ebb..b215a50c1 100644 --- a/byterun/src/interpreter.c +++ b/byterun/src/interpreter.c @@ -11,14 +11,22 @@ struct State s; static inline int ip_read_int(char **ip) { + if (*ip + sizeof(int) > s.bf->code_ptr + s.bf->code_size) { + failure("last command is invalid, int parameter can not be read\n"); + } *ip += sizeof(int); return *(int *)((*ip) - sizeof(int)); } -static inline char ip_read_byte(char **ip) { return *(*ip)++; } +static inline uint8_t ip_read_byte(char **ip) { + if (*ip + sizeof(char) > s.bf->code_ptr + s.bf->code_size) { + failure("last command is invalid, byte parameter can not be read\n"); + } + return *(*ip)++; +} -static inline char *ip_read_string(char **ip, bytefile *bf) { - return get_string(bf, ip_read_int(ip)); +static inline const char *ip_read_string(char **ip) { + return get_string(s.bf, ip_read_int(ip)); } const size_t BUFFER_SIZE = 1000; @@ -26,44 +34,43 @@ const size_t BUFFER_SIZE = 1000; void run(bytefile *bf, int argc, char **argv) { size_t stack[STACK_SIZE]; void *buffer[BUFFER_SIZE]; - construct_state(bf, &s, (void**)stack); + construct_state(bf, &s, (void **)stack); #ifdef DEBUG_VERSION printf("--- interpreter run ---\n"); #endif - const size_t OPS_SIZE = 13; - const char *ops[] = { - "+", "-", "*", "/", "%", "<", "<=", ">", ">=", "==", "!=", "&&", "!!"}; - aint (*ops_func[])(void *, void *) = { - &Ls__Infix_43, // + - &Ls__Infix_45, // - - &Ls__Infix_42, // * - &Ls__Infix_47, // / - &Ls__Infix_37, // % - &Ls__Infix_60, // < - &Ls__Infix_6061, // <= - &Ls__Infix_62, // > - &Ls__Infix_6261, // >= - &Ls__Infix_6161, // == - &Ls__Infix_3361, // != - &Ls__Infix_3838, // && - &Ls__Infix_3333, // !! - }; + // const char *ops[] = { + // "+", "-", "*", "/", "%", "<", "<=", ">", ">=", "==", "!=", "&&", "!!"}; + // aint (*ops_func[])(void *, void *) = { + // &Ls__Infix_43, // + + // &Ls__Infix_45, // - + // &Ls__Infix_42, // * + // &Ls__Infix_47, // / + // &Ls__Infix_37, // % + // &Ls__Infix_60, // < + // &Ls__Infix_6061, // <= + // &Ls__Infix_62, // > + // &Ls__Infix_6261, // >= + // &Ls__Infix_6161, // == + // &Ls__Infix_3361, // != + // &Ls__Infix_3838, // && + // &Ls__Infix_3333, // !! + // }; - const size_t PATS_SIZE = 7; - const char *pats[] = {"=str", "#string", "#array", "#sexp", - "#ref", "#val", "#fun"}; + // const char *pats[] = {"=str", "#string", "#array", "#sexp", + // "#ref", "#val", "#fun"}; // argc, argv { s_push_i(BOX(argc)); - void **argv_strs = calloc(argc, sizeof(void *)); for (size_t i = 0; i < argc; ++i) { - argv_strs[i] = Bstring((aint *)&argv[i]); + s_push(Bstring((aint *)&argv[argc - i - 1])); } - s_push(Barray((aint *)&argv_strs, argc)); - free(argv_strs); + s_push(Barray((aint *)s_peek(), argc)); + void *argv_elem = s_pop(); + s_popn(argc); + s_push(argv_elem); } #ifdef DEBUG_VERSION @@ -83,55 +90,93 @@ void run(bytefile *bf, int argc, char **argv) { } s.instr_ip = s.ip; - char x = ip_read_byte(&s.ip), h = (x & 0xF0) >> 4, l = x & 0x0F; + uint8_t x = ip_read_byte(&s.ip), h = (x & 0xF0) >> 4, l = x & 0x0F; #ifdef DEBUG_VERSION printf("0x%.8x\n", s.ip - bf->code_ptr - 1); #endif switch (h) { - case 15: + case CMD_EXIT: goto stop; /* BINOP */ - case 0: // BINOP ops[l-1] - if (l > OPS_SIZE) { - s_failure(&s, "undefined binop type index"); - } - if (l < 1) { - s_failure(&s, "negative binop type index"); - } + case CMD_BINOP: { // BINOP ops[l-1] void *left = s_pop(); void *right = s_pop(); - s_push((void *)ops_func[l - 1](right, left)); + switch ((int)l) { + case CMD_BINOP_ADD: // + + s_push_i(Ls__Infix_43(right, left)); + break; + case CMD_BINOP_SUB: // - + s_push_i(Ls__Infix_45(right, left)); + break; + case CMD_BINOP_MULT: // * + s_push_i(Ls__Infix_42(right, left)); + break; + case CMD_BINOP_DIV: // / + s_push_i(Ls__Infix_47(right, left)); + break; + case CMD_BINOP_MOD: // % + s_push_i(Ls__Infix_37(right, left)); + break; + case CMD_BINOP_LEQ: // < + s_push_i(Ls__Infix_60(right, left)); + break; + case CMD_BINOP_LT: // <= + s_push_i(Ls__Infix_6061(right, left)); + break; + case CMD_BINOP_GT: // > + s_push_i(Ls__Infix_62(right, left)); + break; + case CMD_BINOP_GEQ: // >= + s_push_i(Ls__Infix_6261(right, left)); + break; + case CMD_BINOP_EQ: // == + s_push_i(Ls__Infix_6161(right, left)); + break; + case CMD_BINOP_NEQ: // != + s_push_i(Ls__Infix_3361(right, left)); + break; + case CMD_BINOP_AND: // && + s_push_i(Ls__Infix_3838(right, left)); + break; + case CMD_BINOP_OR: // !! + s_push_i(Ls__Infix_3333(right, left)); + break; + default: + s_failure(&s, "invalid opcode"); // %d-%d\n", h, l); + break; + } break; + } - case 1: + case CMD_BASIC: switch (l) { - case 0: // CONST %d + case CMD_BASIC_CONST: // CONST %d s_push_i(BOX(ip_read_int(&s.ip))); break; - case 1: { // STRING %s - void *str = ip_read_string(&s.ip, bf); + case CMD_BASIC_STRING: { // STRING %s + void *str = (void *)ip_read_string(&s.ip); s_push(Bstring((aint *)&str)); break; } - case 2: { // SEXP %s %d // create sexpr with tag=%s and %d elements from - // stack + case CMD_BASIC_SEXP: { // SEXP %s %d // create sexpr with tag=%s and %d + // elements from + // stack // params read from stack - const char *name = ip_read_string(&s.ip, bf); - aint args_count = ip_read_int(&s.ip); + const char *name = ip_read_string(&s.ip); + size_t args_count = ip_read_int(&s.ip); #ifdef DEBUG_VERSION printf("tag hash is %i, n is %i\n", UNBOX(LtagHash((char *)name)), args_count); #endif - if (args_count < 0) { - s_failure(&s, "args count should be >= 0"); - } - void **opr_buffer = args_count >= BUFFER_SIZE ? calloc(args_count + 1, sizeof(void *)) : buffer; + void **opr_buffer = args_count >= BUFFER_SIZE + ? alloc((args_count + 1) * sizeof(void *)) + : buffer; for (size_t i = 1; i <= args_count; ++i) { opr_buffer[args_count - i] = s_pop(); @@ -140,17 +185,11 @@ void run(bytefile *bf, int argc, char **argv) { void *sexp = Bsexp((aint *)opr_buffer, BOX(args_count + 1)); - push_extra_root(sexp); s_push(sexp); - pop_extra_root(sexp); - - if (args_count >= BUFFER_SIZE) { - free(opr_buffer); - } break; } - case 3: { // STI - write by ref (?) + case CMD_BASIC_STI: { // STI - write by ref (?) // NOTE: example not found, no checks done void *elem = s_pop(); void **addr = (void **)s_pop(); @@ -159,7 +198,7 @@ void run(bytefile *bf, int argc, char **argv) { break; } - case 4: { // STA - write to array elem + case CMD_BASIC_STA: { // STA - write to array elem void *elem = s_pop(); aint index = s_pop_i(); void *data = s_pop(); @@ -167,17 +206,17 @@ void run(bytefile *bf, int argc, char **argv) { break; } - case 5: { // JMP 0x%.8x - int jmp_p = ip_read_int(&s.ip); + case CMD_BASIC_JMP: { // JMP 0x%.8x + uint jmp_p = ip_read_int(&s.ip); - if (jmp_p < 0) { - s_failure(&s, "negative file offset jumps are not allowed"); + if (jmp_p >= bf->code_size) { + s_failure(&s, "jump out of file"); } s.ip = bf->code_ptr + jmp_p; break; } - case 6: // END + case CMD_BASIC_END: // END if (!s_is_empty() && s.fp->prev_fp != 0) { s.fp->ret = *s_peek(); s_pop(); @@ -185,7 +224,7 @@ void run(bytefile *bf, int argc, char **argv) { s_exit_f(); break; - case 7: // RET + case CMD_BASIC_RET: // RET if (!s_is_empty() && s.fp->prev_fp != 0) { s.fp->ret = *s_peek(); s_pop(); @@ -193,35 +232,25 @@ void run(bytefile *bf, int argc, char **argv) { s_exit_f(); break; - case 8: // DROP + case CMD_BASIC_DROP: // DROP s_pop(); break; - case 9: // DUP + case CMD_BASIC_DUP: // DUP { s_push(*s_peek()); break; } - case 10: // SWAP + case CMD_BASIC_SWAP: // SWAP { - void* x = s_pop(); - void* y = s_pop(); + void *x = s_pop(); + void *y = s_pop(); s_push(y); s_push(x); - - // if (s.sp + 1 >= s.stack + STACK_SIZE || - // (s.fp != NULL && s.sp + 1 >= f_locals(s.fp))) { - // s_failure(&s, "can't SWAP: < 2 values on stack"); - // } - // void *v = *s.sp; - // push_extra_root(v); - // *s.sp = *(s.sp + 1); - // *(s.sp + 1) = v; - // pop_extra_root(v); } break; - case 11: // ELEM + case CMD_BASIC_ELEM: // ELEM { aint index = s_pop_i(); void *data = s_pop(); @@ -233,33 +262,30 @@ void run(bytefile *bf, int argc, char **argv) { } break; - case 2: { // LD %d - void **var_ptr = - var_by_category(to_var_category(l), ip_read_int(&s.ip)); + case CMD_LD: { // LD %d + void **var_ptr = var_by_category(to_var_category(l), ip_read_int(&s.ip)); s_push(*var_ptr); break; } - case 3: { // LDA %d - void **var_ptr = - var_by_category(to_var_category(l), ip_read_int(&s.ip)); + case CMD_LDA: { // LDA %d + void **var_ptr = var_by_category(to_var_category(l), ip_read_int(&s.ip)); s_push(*var_ptr); break; } - case 4: { // ST %d - void **var_ptr = - var_by_category(to_var_category(l), ip_read_int(&s.ip)); + case CMD_ST: { // ST %d + void **var_ptr = var_by_category(to_var_category(l), ip_read_int(&s.ip)); *var_ptr = *s_peek(); break; } - case 5: + case CMD_CTRL: switch (l) { - case 0: { // CJMPz 0x%.8x - int jmp_p = ip_read_int(&s.ip); + case CMD_CTRL_CJMPz: { // CJMPz 0x%.8x + uint jmp_p = ip_read_int(&s.ip); - if (jmp_p < 0) { - s_failure(&s, "negative file offset jumps are not allowed"); + if (jmp_p >= bf->code_size) { + s_failure(&s, "jump out of file"); } if (UNBOX(s_pop_i()) == 0) { s.ip = bf->code_ptr + jmp_p; @@ -267,11 +293,11 @@ void run(bytefile *bf, int argc, char **argv) { break; } - case 1: { // CJMPnz 0x%.8x - int jmp_p = ip_read_int(&s.ip); + case CMD_CTRL_CJMPnz: { // CJMPnz 0x%.8x + uint jmp_p = ip_read_int(&s.ip); - if (jmp_p < 0) { - s_failure(&s, "negative file offset jumps are not allowed"); + if (jmp_p >= bf->code_size) { + s_failure(&s, "jump out of file"); } if (UNBOX(s_pop_i()) != 0) { s.ip = bf->code_ptr + jmp_p; @@ -279,7 +305,7 @@ void run(bytefile *bf, int argc, char **argv) { break; } - case 2: { // BEGIN %d %d // function begin + case CMD_CTRL_BEGIN: { // BEGIN %d %d // function begin int args_sz = ip_read_int(&s.ip); int locals_sz = ip_read_int(&s.ip); if (s.fp != NULL && s.call_ip == NULL) { @@ -290,7 +316,7 @@ void run(bytefile *bf, int argc, char **argv) { break; } - case 3: { // CBEGIN %d %d + case CMD_CTRL_CBEGIN: { // CBEGIN %d %d // NOTE: example not found, no checks done int args_sz = ip_read_int(&s.ip); int locals_sz = ip_read_int(&s.ip); @@ -302,7 +328,7 @@ void run(bytefile *bf, int argc, char **argv) { break; } - case 4: // CLOSURE 0x%.8x + case CMD_CTRL_CLOSURE: // CLOSURE 0x%.8x { aint call_offset = ip_read_int(&s.ip); aint args_count = ip_read_int(&s.ip); @@ -316,16 +342,14 @@ void run(bytefile *bf, int argc, char **argv) { } s_push(bf->code_ptr + call_offset); - void *closure = Bclosure((aint *)s.sp, args_count); + void *closure = Bclosure((aint *)__gc_stack_top, args_count); - push_extra_root(closure); s_popn(args_count + 1); s_push(closure); - pop_extra_root(closure); break; } - case 5: { // CALLC %d // call clojure + case CMD_CTRL_CALLC: { // CALLC %d // call clojure aint args_count = ip_read_int(&s.ip); // args count call_happened = true; @@ -336,23 +360,23 @@ void run(bytefile *bf, int argc, char **argv) { break; } - case 6: { // CALL 0x%.8x %d // call function - int call_p = ip_read_int(&s.ip); + case CMD_CTRL_CALL: { // CALL 0x%.8x %d // call function + uint call_p = ip_read_int(&s.ip); ip_read_int(&s.ip); // args count call_happened = true; s.is_closure_call = false; s.call_ip = s.ip; - if (call_p < 0) { - s_failure(&s, "negative file offset jumps are not allowed"); + if (call_p >= bf->code_size) { + s_failure(&s, "jump out of file"); } s.ip = bf->code_ptr + call_p; break; } - case 7: { // TAG %s %d - const char *name = ip_read_string(&s.ip, bf); + case CMD_CTRL_TAG: { // TAG %s %d + const char *name = ip_read_string(&s.ip); aint args_count = ip_read_int(&s.ip); #ifdef DEBUG_VERSION @@ -364,18 +388,18 @@ void run(bytefile *bf, int argc, char **argv) { break; } - case 8: // ARRAY %d + case CMD_CTRL_ARRAY: // ARRAY %d s_push_i(Barray_patt(s_pop(), BOX(ip_read_int(&s.ip)))); break; - case 9: { // FAIL %d %d - int line = ip_read_int(&s.ip); // ?? - int col = ip_read_int(&s.ip); // ?? + case CMD_CTRL_FAIL: { // FAIL %d %d + int line = ip_read_int(&s.ip); + int col = ip_read_int(&s.ip); Bmatch_failure(s_pop(), argv[0], BOX(line), BOX(col)); break; } - case 10: // LINE %d + case CMD_CTRL_LINE: // LINE %d s.current_line = ip_read_int(&s.ip); // maybe some metainfo should be collected break; @@ -385,28 +409,28 @@ void run(bytefile *bf, int argc, char **argv) { } break; - case 6: // PATT pats[l] + case CMD_PATT: // PATT pats[l] // {"=str", "#string", "#array", "#sexp", "#ref", "#val", "#fun"} switch (l) { - case 0: // =str + case CMD_PATT_STR: // =str s_push_i(Bstring_patt(s_pop(), s_pop())); break; - case 1: // #string + case CMD_PATT_STR_TAG: // #string s_push_i(Bstring_tag_patt(s_pop())); break; - case 2: // #array + case CMD_PATT_ARRAY_TAG: // #array s_push_i(Barray_tag_patt(s_pop())); break; - case 3: // #sexp + case CMD_PATT_SEXP_TAG: // #sexp s_push_i(Bsexp_tag_patt(s_pop())); break; - case 4: // #ref + case CMD_PATT_REF_TAG: // #ref s_push_i(Bunboxed_patt(s_pop())); break; - case 5: // #val + case CMD_PATT_VAL_TAG: // #val s_push_i(Bboxed_patt(s_pop())); break; - case 6: // #fun + case CMD_PATT_FUN_TAG: // #fun s_push_i(Bclosure_tag_patt(s_pop())); break; default: @@ -414,45 +438,41 @@ void run(bytefile *bf, int argc, char **argv) { } break; - case 7: { + case CMD_BUILTIN: { switch (l) { - case 0: // CALL Lread + case CMD_BUILTIN_Lread: // CALL Lread s_push_i(Lread()); break; - case 1: // CALL Lwrite + case CMD_BUILTIN_Lwrite: // CALL Lwrite Lwrite(*s_peek_i()); break; - case 2: // CALL Llength + case CMD_BUILTIN_Llength: // CALL Llength s_push_i(Llength(s_pop())); break; - case 3: { // CALL Lstring + case CMD_BUILTIN_Lstring: { // CALL Lstring void *val = s_pop(); void *str = Lstring((aint *)&val); s_push(str); break; } - case 4: { // CALL Barray %d + case CMD_BUILTIN_Barray: { // CALL Barray %d size_t elem_count = ip_read_int(&s.ip); - if (elem_count < 0) { - s_failure(&s, "elements count should be >= 0"); - } - void **opr_buffer = elem_count > BUFFER_SIZE ? calloc(elem_count, sizeof(void *)) : buffer; + void **opr_buffer = elem_count > BUFFER_SIZE + ? alloc(elem_count * sizeof(void *)) + : buffer; for (size_t i = 0; i < elem_count; ++i) { opr_buffer[elem_count - i - 1] = s_pop(); } void *array = - Barray((aint *)opr_buffer, BOX(elem_count)); // NOTE: not shure if elems should be added + Barray((aint *)opr_buffer, + BOX(elem_count)); // NOTE: not shure if elems should be added s_push(array); - - if (elem_count > BUFFER_SIZE) { - free(opr_buffer); - } break; } diff --git a/byterun/src/parser.c b/byterun/src/parser.c index c070275e0..c06604c46 100644 --- a/byterun/src/parser.c +++ b/byterun/src/parser.c @@ -6,6 +6,7 @@ #include "../../runtime/runtime.h" +#include "types.h" #include "utils.h" #include "parser.h" @@ -66,90 +67,90 @@ bytefile* read_file (char *fname) { } const char *read_cmd(char *ip) { - char x = (*ip++), h = (x & 0xF0) >> 4, l = x & 0x0F; + uint8_t x = (*ip++), h = (x & 0xF0) >> 4, l = x & 0x0F; switch (h) { - case 15: + case CMD_EXIT: return "END"; - case 0: + case CMD_BINOP: return "BINOP"; - case 1: + case CMD_BASIC: switch (l) { - case 0: + case CMD_BASIC_CONST: return "CONST"; - case 1: + case CMD_BASIC_STRING: return "STRING"; - case 2: + case CMD_BASIC_SEXP: return "SEXP "; - case 3: + case CMD_BASIC_STI: return "STI"; - case 4: + case CMD_BASIC_STA: return "STA"; - case 5: + case CMD_BASIC_JMP: return "JMP"; - case 6: + case CMD_BASIC_END: return "END"; - case 7: + case CMD_BASIC_RET: return "RET"; - case 8: + case CMD_BASIC_DROP: return "DROP"; - case 9: + case CMD_BASIC_DUP: return "DUP"; - case 10: + case CMD_BASIC_SWAP: return "SWAP"; - case 11: + case CMD_BASIC_ELEM: return "ELEM"; default: return "_UNDEF_CMD1_"; } break; - case 2: + case CMD_LD: return "LD"; - case 3: + case CMD_LDA: return "LDA"; - case 4: + case CMD_ST: return "ST"; - case 5: + case CMD_CTRL: switch (l) { - case 0: + case CMD_CTRL_CJMPz: return "CJMPz"; - case 1: + case CMD_CTRL_CJMPnz: return "CJMPnz"; - case 2: + case CMD_CTRL_BEGIN: return "BEGIN"; - case 3: + case CMD_CTRL_CBEGIN: return "CBEGIN"; - case 4: + case CMD_CTRL_CLOSURE: return "CLOSURE"; - case 5: + case CMD_CTRL_CALLC: return "CALLC"; - case 6: + case CMD_CTRL_CALL: return "CALL"; - case 7: + case CMD_CTRL_TAG: return "TAG"; - case 8: + case CMD_CTRL_ARRAY: return "ARRAY"; - case 9: + case CMD_CTRL_FAIL: return "FAIL"; - case 10: + case CMD_CTRL_LINE: return "LINE"; default: return "_UNDEF_CMD5_"; } - case 6: + case CMD_PATT: return "PATT"; - case 7: { + case CMD_BUILTIN: { switch (l) { - case 0: + case CMD_BUILTIN_Lread: return "CALL\tLread"; - case 1: + case CMD_BUILTIN_Lwrite: return "CALL\tLwrite"; - case 2: + case CMD_BUILTIN_Llength: return "CALL\tLlength"; - case 3: + case CMD_BUILTIN_Lstring: return "CALL\tLstring"; - case 4: + case CMD_BUILTIN_Barray: return "CALL\tBarray\t%d"; default: return "_UNDEF_CALL_"; @@ -160,225 +161,225 @@ const char *read_cmd(char *ip) { } } -/* Disassembles the bytecode pool */ -void disassemble (FILE *f, bytefile *bf) { +// /* Disassembles the bytecode pool */ +// void disassemble (FILE *f, bytefile *bf) { -# define INT (ip += sizeof (int), *(int*)(ip - sizeof (int))) -# define BYTE *ip++ -# define STRING get_string (bf, INT) -# define FAIL failure ("ERROR: invalid opcode %d-%d\n", h, l) +// # define INT (ip += sizeof (int), *(int*)(ip - sizeof (int))) +// # define BYTE *ip++ +// # define STRING get_string (bf, INT) +// # define FAIL failure ("ERROR: invalid opcode %d-%d\n", h, l) - char *ip = bf->code_ptr; - char *ops [] = {"+", "-", "*", "/", "%", "<", "<=", ">", ">=", "==", "!=", "&&", "!!"}; - char *pats[] = {"=str", "#string", "#array", "#sexp", "#ref", "#val", "#fun"}; - char *lds [] = {"LD", "LDA", "ST"}; - do { - char x = BYTE, - h = (x & 0xF0) >> 4, - l = x & 0x0F; +// char *ip = bf->code_ptr; +// char *ops [] = {"+", "-", "*", "/", "%", "<", "<=", ">", ">=", "==", "!=", "&&", "!!"}; +// char *pats[] = {"=str", "#string", "#array", "#sexp", "#ref", "#val", "#fun"}; +// char *lds [] = {"LD", "LDA", "ST"}; +// do { +// uint8_t x = BYTE, +// h = (x & 0xF0) >> 4, +// l = x & 0x0F; - fprintf (f, "0x%.8x:\t", ip-bf->code_ptr-1); +// fprintf (f, "0x%.8x:\t", ip-bf->code_ptr-1); - switch (h) { - case 15: - goto stop; +// switch (h) { +// case 15: +// goto stop; - /* BINOP */ - case 0: - fprintf (f, "BINOP\t%s", ops[l-1]); - break; +// /* BINOP */ +// case 0: +// fprintf (f, "BINOP\t%s", ops[l-1]); +// break; - case 1: - switch (l) { - case 0: - fprintf (f, "CONST\t%d", INT); - break; +// case 1: +// switch (l) { +// case 0: +// fprintf (f, "CONST\t%d", INT); +// break; - case 1: - fprintf (f, "STRING\t%s", STRING); - break; +// case 1: +// fprintf (f, "STRING\t%s", STRING); +// break; - case 2: - fprintf (f, "SEXP\t%s ", STRING); - fprintf (f, "%d", INT); - break; +// case 2: +// fprintf (f, "SEXP\t%s ", STRING); +// fprintf (f, "%d", INT); +// break; - case 3: - fprintf (f, "STI"); - break; +// case 3: +// fprintf (f, "STI"); +// break; - case 4: - fprintf (f, "STA"); - break; +// case 4: +// fprintf (f, "STA"); +// break; - case 5: - fprintf (f, "JMP\t0x%.8x", INT); - break; +// case 5: +// fprintf (f, "JMP\t0x%.8x", INT); +// break; - case 6: - fprintf (f, "END"); - break; +// case 6: +// fprintf (f, "END"); +// break; - case 7: - fprintf (f, "RET"); - break; +// case 7: +// fprintf (f, "RET"); +// break; - case 8: - fprintf (f, "DROP"); - break; +// case 8: +// fprintf (f, "DROP"); +// break; - case 9: - fprintf (f, "DUP"); - break; +// case 9: +// fprintf (f, "DUP"); +// break; - case 10: - fprintf (f, "SWAP"); - break; +// case 10: +// fprintf (f, "SWAP"); +// break; - case 11: - fprintf (f, "ELEM"); - break; +// case 11: +// fprintf (f, "ELEM"); +// break; - default: - FAIL; - } - break; +// default: +// FAIL; +// } +// break; - case 2: - case 3: - case 4: - fprintf (f, "%s\t", lds[h-2]); - switch (l) { - case 0: fprintf (f, "G(%d)", INT); break; - case 1: fprintf (f, "L(%d)", INT); break; - case 2: fprintf (f, "A(%d)", INT); break; - case 3: fprintf (f, "C(%d)", INT); break; - default: FAIL; - } - break; +// case 2: +// case 3: +// case 4: +// fprintf (f, "%s\t", lds[h-2]); +// switch (l) { +// case 0: fprintf (f, "G(%d)", INT); break; +// case 1: fprintf (f, "L(%d)", INT); break; +// case 2: fprintf (f, "A(%d)", INT); break; +// case 3: fprintf (f, "C(%d)", INT); break; +// default: FAIL; +// } +// break; - case 5: - switch (l) { - case 0: - fprintf (f, "CJMPz\t0x%.8x", INT); - break; +// case 5: +// switch (l) { +// case 0: +// fprintf (f, "CJMPz\t0x%.8x", INT); +// break; - case 1: - fprintf (f, "CJMPnz\t0x%.8x", INT); - break; +// case 1: +// fprintf (f, "CJMPnz\t0x%.8x", INT); +// break; - case 2: - fprintf (f, "BEGIN\t%d ", INT); - fprintf (f, "%d", INT); - break; +// case 2: +// fprintf (f, "BEGIN\t%d ", INT); +// fprintf (f, "%d", INT); +// break; - case 3: - fprintf (f, "CBEGIN\t%d ", INT); - fprintf (f, "%d", INT); - break; +// case 3: +// fprintf (f, "CBEGIN\t%d ", INT); +// fprintf (f, "%d", INT); +// break; - case 4: - fprintf (f, "CLOSURE\t0x%.8x", INT); - {int n = INT; - for (int i = 0; i\n"); -} +// fprintf (f, "\n"); +// } +// while (1); +// stop: fprintf (f, "\n"); +// } -/* Dumps the contents of the file */ -void dump_file (FILE *f, bytefile *bf) { - size_t i; +// /* Dumps the contents of the file */ +// void dump_file (FILE *f, bytefile *bf) { +// size_t i; - fprintf (f, "String table size : %d\n", bf->stringtab_size); - fprintf (f, "Global area size : %d\n", bf->global_area_size); - fprintf (f, "Number of public symbols: %d\n", bf->public_symbols_number); - fprintf (f, "Public symbols :\n"); +// fprintf (f, "String table size : %d\n", bf->stringtab_size); +// fprintf (f, "Global area size : %d\n", bf->global_area_size); +// fprintf (f, "Number of public symbols: %d\n", bf->public_symbols_number); +// fprintf (f, "Public symbols :\n"); - for (i=0; i < bf->public_symbols_number; i++) - fprintf (f, " 0x%.8x: %s\n", get_public_offset (bf, i), get_public_name (bf, i)); +// for (i=0; i < bf->public_symbols_number; i++) +// fprintf (f, " 0x%.8x: %s\n", get_public_offset (bf, i), get_public_name (bf, i)); - fprintf (f, "Code:\n"); - disassemble (f, bf); -} +// fprintf (f, "Code:\n"); +// disassemble (f, bf); +// } diff --git a/byterun/src/types.c b/byterun/src/types.c index 78f72bb2f..b6772142c 100644 --- a/byterun/src/types.c +++ b/byterun/src/types.c @@ -26,14 +26,14 @@ static void init_state(bytefile *bf, struct State* s, void** stack) { // printf("%p:%zu - %zu", s->stack, (size_t)s->stack, (size_t)s->stack & 0xF); - s->sp = s->stack + STACK_SIZE; // [top -> bottom] stack + // s->sp = s->stack + STACK_SIZE; // [top -> bottom] stack s->fp = NULL; } void construct_state(bytefile *bf, struct State* s, void** stack) { __init(); init_state(bf, s, stack); - __gc_stack_bottom = (size_t)s->sp; + __gc_stack_bottom = (size_t)(s->stack + STACK_SIZE); __gc_stack_top = __gc_stack_bottom; s_pushn_nil(bf->global_area_size); @@ -47,7 +47,7 @@ void construct_state(bytefile *bf, struct State* s, void** stack) { static void destruct_state(struct State* state) { // free(state->stack); - state->sp = NULL; + // state->sp = NULL; state->fp = NULL; state->ip = NULL; state->call_ip = NULL; diff --git a/runtime/gc.c b/runtime/gc.c index a9d4d1775..15159bd3c 100644 --- a/runtime/gc.c +++ b/runtime/gc.c @@ -63,7 +63,7 @@ void *alloc (size_t size) { size = BYTES_TO_WORDS(size); size_t padding = size * sizeof(size_t) - obj_size; #if defined(DEBUG_VERSION) && defined(DEBUG_PRINT) - fprintf(stderr, "allocation of size %zu words (%zu bytes): ", size, bytes_sz); + fprintf(stderr, "allocation of size %zu words (%zu bytes): ", size, padding); #endif void *p = gc_alloc_on_existing_heap(size); if (!p) { diff --git a/runtime/runtime.c b/runtime/runtime.c index e8930de06..02994d790 100644 --- a/runtime/runtime.c +++ b/runtime/runtime.c @@ -15,11 +15,9 @@ extern size_t __gc_stack_top, __gc_stack_bottom; flag = __gc_stack_top == 0; \ if (flag) { __gc_stack_top = (size_t)__builtin_frame_address(0); } \ assert(__gc_stack_top != 0); \ - assert((__gc_stack_top & 0xF) == 0); \ - assert(__builtin_frame_address(0) <= (void *)__gc_stack_top); + assert((__gc_stack_top & 0x7) == 0); #define POST_GC() \ - assert(__builtin_frame_address(0) <= (void *)__gc_stack_top); \ if (flag) { __gc_stack_top = 0; } _Noreturn static void vfailure (char *s, va_list args) {