types fix, frame fix to work with runtime

This commit is contained in:
ProgramSnail 2024-11-01 20:54:48 +03:00
parent 26a42d4c81
commit 39715334c7
5 changed files with 92 additions and 176 deletions

View file

@ -30,5 +30,4 @@ void s_enter_f(struct State *s, char *func_ip, size_t params_sz,
void s_exit_f(struct State *s); void s_exit_f(struct State *s);
union VarT **var_by_category(struct State *s, enum VarCategory category, void **var_by_category(struct State *s, enum VarCategory category, int id);
int id);

View file

@ -1,131 +1,50 @@
#pragma once #pragma once
#include "../../runtime/runtime.h" #include "../../runtime/runtime.h"
#include "../../runtime/runtime_common.h"
#include "parser.h" #include "parser.h"
#include <stdint.h> #include <stdint.h>
// ------ Var ------ // ------ General ------
enum Type { enum Type {
NIL_T = 0x00000000, STR_T = STRING_TAG,
INT_T = 0x00000001, ARRAY_T = ARRAY_TAG,
BOX_T = 0x00000002, SEXP_T = SEXP_TAG,
STR_T = 0x00000003, CLOJURE_T = CLOSURE_TAG,
CLOJURE_T = 0x00000004,
ARRAY_T = 0x00000005,
SEXP_T = 0x00000006,
FUN_T = 0x00000007
}; };
struct NilT { // AnyVarT too
uint32_t data_header;
};
struct IntT {
uint32_t data_header;
int32_t value;
};
struct BoxT {
uint32_t data_header;
struct NilT **value;
};
struct StrT {
uint32_t data_header; // param - is not const (0 for const, 1 for not const)
const char *value;
};
struct ClojureT { // TODO
uint32_t data_header;
char *fun_ip;
struct ArrayT *vars;
};
// struct ListT {
// uint32_t data_header;
// struct NilT *value;
// struct NilT *next;
// };
struct ArrayT {
uint32_t data_header;
struct NilT **values;
};
static const size_t MAX_ARRAY_SIZE = 0x11111110; static const size_t MAX_ARRAY_SIZE = 0x11111110;
struct SExpT {
uint32_t data_header;
const char *tag;
struct NilT **values;
};
struct FunT {
uint32_t data_header;
char *fun_ip;
};
union VarT {
struct NilT nil;
struct IntT int_t;
struct BoxT box;
struct StrT str;
struct ClojureT clojure;
// struct ListT list;
struct ArrayT array;
struct SExpT sexp;
struct FunT fun;
};
// same to TAG in runtime
static inline enum Type dh_type(int data_header) {
return (enum Type)(data_header & 0x00000007);
}
// same to LEN in runtime
static inline int dh_param(int data_header) {
return (data_header & 0xFFFFFFF8) >> 3;
}
static inline union VarT *to_var(struct NilT *var) { return (union VarT *)var; } static inline union VarT *to_var(struct NilT *var) { return (union VarT *)var; }
// ------ Frame ------ // ------ Frame ------
// TODO: store boxed offsets instead
struct Frame { struct Frame {
struct NilT *ret; // store returned value void *ret; // store returned value [gc pointer]
char *rp; // ret instruction pointer char *rp; // ret instruction pointer [not gc pointer]
struct Frame *prev_fp; // ret function frame pointer size_t to_prev_fp_box; // ret function frame pointer [boxed value, not gc
void **params; // store arguments // pointer]
void **locals; // store locals size_t args_sz_box; // store arguments [boxed value, not gc pointer]
void **end; // store locals size_t locals_sz_box; // store locals [boxed value, not gc pointer]
}; };
static inline uint64_t frame_locals_sz(struct Frame *frame) { size_t frame_sz();
return frame->locals - frame->params; void **f_prev_fp(struct Frame *fp);
} uint64_t f_locals_sz(struct Frame *fp);
static inline uint64_t frame_params_sz(struct Frame *frame) { uint64_t f_args_sz(struct Frame *fp);
return frame->end - frame->locals; void **f_locals(struct Frame *fp);
} void **f_args(struct Frame *fp);
// ------ State ------ // ------ State ------
union StackValue {
union VarT *var;
union VarT **var_ptr;
struct Frame frame; // ??
char *addr;
};
// static inline StackValue *to_sv(void *var) { return (StackValue *)var; }
struct State { struct State {
void **stack; // vaid** void **stack; // vaid**
void **vp; // stack pointer void **sp; // stack pointer
struct Frame *fp; // function frame pointer struct Frame *fp; // function frame pointer
char *ip; // instruction pointer char *ip; // instruction pointer
char *prev_ip; // prev instruction pointer char *prev_ip; // prev instruction pointer (to remember jmp locations)
}; };
struct State init_state(bytefile *bf); struct State init_state(bytefile *bf);
@ -137,12 +56,7 @@ enum VarCategory {
VAR_GLOBAL = 0, VAR_GLOBAL = 0,
VAR_LOCAL = 1, VAR_LOCAL = 1,
VAR_ARGUMENT = 2, VAR_ARGUMENT = 2,
VAR_C = 3 // TODO: constant ?? VAR_C = 3 // TODO: constants ??
}; };
static inline enum VarCategory to_var_category(uint8_t category) { enum VarCategory to_var_category(uint8_t category);
if (category > 3) {
failure("unexpected variable category");
}
return (enum VarCategory)category;
}

View file

@ -111,19 +111,19 @@ void run(bytefile *bf) {
case 9: // DUP case 9: // DUP
{ // guess { // guess
if (s.vp == s.stack || (s.fp != NULL && s.vp == s.fp->end)) { if (s.sp == s.stack || (s.fp != NULL && s.sp == s.fp->end)) {
failure("can't DUP: no value on stack"); failure("can't DUP: no value on stack");
} }
*s.vp = *(s.vp - 1); *s.sp = *(s.sp - 1);
++s.vp; ++s.sp;
break; break;
} }
case 10: // SWAP case 10: // SWAP
{ // guess { // guess
struct NilT* v = *s.vp; struct NilT* v = *s.sp;
*s.vp = *(s.vp - 1); *s.sp = *(s.sp - 1);
*(s.vp - 1) = v; *(s.sp - 1) = v;
} }
break; break;

View file

@ -4,12 +4,14 @@
extern size_t STACK_SIZE; extern size_t STACK_SIZE;
// ------ basic stack oprs ------
void s_push(struct State *s, void *val) { void s_push(struct State *s, void *val) {
if (s->vp == s->stack) { if (s->sp == s->stack) {
failure("stack overflow"); failure("stack overflow");
} }
--s->vp; --s->sp;
*s->vp = val; *s->sp = val;
} }
void s_push_nil(struct State *s) { void s_push_nil(struct State *s) {
@ -23,12 +25,12 @@ void s_pushn_nil(struct State *s, size_t n) {
} }
void* s_pop(struct State *s) { void* s_pop(struct State *s) {
if (s->vp == s->stack + STACK_SIZE || (s->fp != NULL && s->vp == s->fp->end)) { if (s->sp == s->stack + STACK_SIZE || (s->fp != NULL && s->sp == f_locals(s->fp))) {
failure("take: no var"); failure("take: no var");
} }
void* value = *s->vp; void* value = *s->sp;
*s->vp = NULL; *s->sp = NULL;
++s->vp; ++s->sp;
return value; return value;
} }
@ -41,70 +43,64 @@ void s_popn(struct State *s, size_t n) {
// ------ functions ------ // ------ functions ------
// TODO void s_enter_f(struct State *s, char *func_ip, size_t args_sz,
// |> param_0 ... param_n | frame[ ret rp prev_fp &params &locals &end ]
// |> local_0 ... local_m |> | ...
//
// where |> defines corresponding frame pointer, | is stack pointer location
// before / after new frame added
void s_enter_f(struct State *s, char *func_ip, size_t params_sz,
size_t locals_sz) { size_t locals_sz) {
if (params_sz > s->vp - s->stack || // check that params count is valid
(s->fp != NULL && params_sz > s->vp - s->fp->end)) { if (args_sz > s->sp + STACK_SIZE - s->stack ||
(s->fp != NULL && args_sz > s->sp + STACK_SIZE - f_locals(s->fp))) {
failure("not enough parameters in stack"); failure("not enough parameters in stack");
} }
size_t frame_sz_in_ptr = sizeof(struct Frame) / sizeof(void *);
// create frame
struct Frame frame = { struct Frame frame = {
.ret = NULL, // field in frame itself .ret = NULL, // field in frame itself
.rp = s->ip, .rp = s->ip,
.prev_fp = s->fp, .to_prev_fp_box = BOX((void**)s->fp - s->sp),
.params = s->vp - params_sz, .args_sz_box = BOX(args_sz),
.locals = s->vp + frame_sz_in_ptr, .locals_sz_box = BOX(locals_sz),
.end = s->vp + frame_sz_in_ptr + locals_sz,
}; };
// put frame on stack // put frame on stack
s->fp = (struct Frame *)s->vp; s_push_nil(s); // sp contains value
s->fp = (struct Frame *)s->sp;
s_pushn_nil(s, frame_sz() - 1);
(*s->fp) = frame; (*s->fp) = frame;
// update stack pointer s_pushn_nil(s, locals_sz);
s->vp = frame.end;
// go to function body // go to function body
s->ip = func_ip; s->ip = func_ip;
} }
// TODO
void s_exit_f(struct State *s) { void s_exit_f(struct State *s) {
if (s->fp == NULL) { if (s->fp == NULL) {
failure("exit: no func"); failure("exit: no func");
} }
// drop stack entities and locals struct Frame frame = *s->fp;
s_popn(s, f_locals_sz(s->fp)); push_extra_root((void **)&frame.ret);
// TODO: skip // drop stack entities, locals, frame
s_popn(s, (void**)s->fp - s->sp + 1); // TODO:check +1
// drop params // drop args
s->vp = (void **)s->fp; s_popn(s, f_args_sz(&frame));
s_popn(s, f_args_sz(s->fp));
// s->vp = s->fp->params; // done automatically // save returned value
s_push(s, frame.ret);
// save ret_val s->ip = frame.rp;
s_push(s, s->fp->ret); s->fp = (struct Frame*)f_prev_fp(&frame);
s->ip = s->fp->rp; pop_extra_root((void **)&frame.ret);
s->fp = s->fp->prev_fp;
} }
// TODO void **var_by_category(struct State *s, enum VarCategory category,
union VarT **var_by_category(struct State *s, enum VarCategory category,
int id) { int id) {
if (id < 0) { if (id < 0) {
failure("can't read variable: negative id %i", id); failure("can't read variable: negative id %i", id);
} }
union VarT **var = NULL; void **var = NULL;
switch (category) { switch (category) {
case VAR_GLOBAL: case VAR_GLOBAL:
// TODO: FIXME // TODO: FIXME
@ -113,11 +109,11 @@ union VarT **var_by_category(struct State *s, enum VarCategory category,
if (s->fp == NULL) { if (s->fp == NULL) {
failure("can't read local outside of function"); failure("can't read local outside of function");
} }
if (frame_args_sz(s->fp) <= id) { if (f_args_sz(s->fp) <= id) {
failure("can't read local: too big id, %i >= %ul", f_locals_sz(s->fp), failure("can't read local: too big id, %i >= %ul", f_locals_sz(s->fp),
id); id);
} }
var = (union VarT **)&f_locals_at(s->fp, id); var = &f_locals(s->fp)[id];
break; break;
case VAR_ARGUMENT: case VAR_ARGUMENT:
if (s->fp == NULL) { if (s->fp == NULL) {
@ -127,12 +123,14 @@ union VarT **var_by_category(struct State *s, enum VarCategory category,
failure("can't read arguments: too big id, %i >= %ul", f_args_sz(s->fp), failure("can't read arguments: too big id, %i >= %ul", f_args_sz(s->fp),
id); id);
} }
var = (union VarT **)&f_args_at(s->fp, id); var = &f_args(s->fp)[id]; // TODO: check if not reversed order
break; break;
case VAR_C: case VAR_C:
// TODO: ?? // TODO: ??
break; break;
} }
// TODO: push extra root ??
return var; return var;
} }

View file

@ -8,34 +8,31 @@ extern size_t __gc_stack_top, __gc_stack_bottom;
const size_t STACK_SIZE = 100000; const size_t STACK_SIZE = 100000;
// --- // --- Frame ---
void st_stack_push(struct State* state, void* value) { // NOTE: stack is [top -> bottom]
size_t frame_sz() {
return sizeof(struct Frame) / sizeof(void *);
} }
void **f_prev_fp(struct Frame *fp) {
void st_stack_pop(struct State* state) { return (void **)fp + UNBOX(fp->to_prev_fp_box);
if (state->vp == st->stack)
} }
uint64_t f_locals_sz(struct Frame *fp) { return UNBOX(fp->locals_sz_box); }
uint64_t f_args_sz(struct Frame *fp) { return UNBOX(fp->args_sz_box); }
void **f_locals(struct Frame *fp) { return (void **)fp - f_locals_sz(fp) - frame_sz(); }
void **f_args(struct Frame *fp) { return (void **)fp + f_args_sz(fp); }
size_t st_stack_size(struct State* state) {
return (state->stack + STACK_SIZE) - state->vp;
}
void** st_stack_top(struct State* state) { // --- State ---
return state->vp;
}
// ---
static struct State alloc_state(bytefile *bf) { static struct State alloc_state(bytefile *bf) {
struct State state = { struct State state = {
.stack = calloc(STACK_SIZE, sizeof(void*)), .stack = calloc(STACK_SIZE + 1, sizeof(void*)),
.ip = bf->code_ptr, .ip = bf->code_ptr,
.prev_ip = NULL, .prev_ip = NULL,
}; };
state.vp = *state.stack + STACK_SIZE; // [top -> bottom] stack state.sp = *state.stack + STACK_SIZE; // [top -> bottom] stack
state.fp = NULL; state.fp = NULL;
return state; return state;
} }
@ -43,14 +40,14 @@ static struct State alloc_state(bytefile *bf) {
struct State init_state(bytefile *bf) { struct State init_state(bytefile *bf) {
__init(); __init();
struct State state = alloc_state(bf); struct State state = alloc_state(bf);
__gc_stack_bottom = (size_t)state.vp; __gc_stack_bottom = (size_t)state.sp;
return state; return state;
} }
static void destruct_state(struct State* state) { static void destruct_state(struct State* state) {
free(state->stack); free(state->stack);
state->vp = NULL; state->sp = NULL;
state->fp = NULL; state->fp = NULL;
state->ip = NULL; state->ip = NULL;
state->prev_ip = NULL; state->prev_ip = NULL;
@ -61,3 +58,11 @@ void cleanup_state(struct State* state) {
__shutdown(); __shutdown();
} }
// --- VarCategory ---
enum VarCategory to_var_category(uint8_t category) {
if (category > 3) {
failure("unexpected variable category");
}
return (enum VarCategory)category;
}