stage1 将数组和聚合类型使用byte offset而不是slot idx
This commit is contained in:
@@ -84,7 +84,7 @@ typedef enum {
|
|||||||
X(SPL_RET, "ret", 0, 0, 0, "return from function") \
|
X(SPL_RET, "ret", 0, 0, 0, "return from function") \
|
||||||
/* 栈帧局部变量 */ \
|
/* 栈帧局部变量 */ \
|
||||||
X(SPL_ALLOC, "alloc", 1, 0, 0, "allocate imm zero-slots on stack") \
|
X(SPL_ALLOC, "alloc", 1, 0, 0, "allocate imm zero-slots on stack") \
|
||||||
X(SPL_LADDR, "laddr", 1, 0, 1, "push address of local at fp+imm") \
|
X(SPL_LADDR, "laddr", 1, 0, 1, "push address of local at fp + imm bytes") \
|
||||||
X(SPL_GADDR, "gaddr", 1, 0, 1, "push address of global at gp + imm") \
|
X(SPL_GADDR, "gaddr", 1, 0, 1, "push address of global at gp + imm") \
|
||||||
/* 间接内存访问 */ \
|
/* 间接内存访问 */ \
|
||||||
X(SPL_LOAD, "load", 0, 1, 1, "load sizeof(type)-bits zero-extended") \
|
X(SPL_LOAD, "load", 0, 1, 1, "load sizeof(type)-bits zero-extended") \
|
||||||
|
|||||||
@@ -889,7 +889,7 @@ int spl_vm_run_once(spl_vm_t *vm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case SPL_LADDR:
|
case SPL_LADDR:
|
||||||
PUSH(vm->stacks.data + vm->fp + ins->imm);
|
PUSH((spl_val_t)((char *)(vm->stacks.data + vm->fp) + ins->imm));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SPL_GADDR: {
|
case SPL_GADDR: {
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ void spl_comp_reset(spl_comp_t *ctx) {
|
|||||||
ctx->error_msg[0] = '\0';
|
ctx->error_msg[0] = '\0';
|
||||||
ctx->current_func_idx = -1;
|
ctx->current_func_idx = -1;
|
||||||
ctx->current_ret_type = NULL;
|
ctx->current_ret_type = NULL;
|
||||||
ctx->current_local_slot = 0;
|
ctx->current_local_bytes = 0;
|
||||||
ctx->in_loop = 0;
|
ctx->in_loop = 0;
|
||||||
ctx->break_patch_count = 0;
|
ctx->break_patch_count = 0;
|
||||||
ctx->break_patch_cap = 0;
|
ctx->break_patch_cap = 0;
|
||||||
@@ -126,17 +126,21 @@ int spl_declare_var(spl_comp_t *ctx, const char *name, spl_type_info_t *type, in
|
|||||||
var.type = type;
|
var.type = type;
|
||||||
var.is_const = is_const;
|
var.is_const = is_const;
|
||||||
var.depth = ctx->scope_depth;
|
var.depth = ctx->scope_depth;
|
||||||
var.slot = ctx->current_local_slot;
|
var.offset = ctx->current_local_bytes;
|
||||||
|
|
||||||
usize slot_count = spl_type_slot_count(type);
|
usize var_size = spl_type_size(type);
|
||||||
ctx->current_local_slot += (int)slot_count;
|
/* Round up to sizeof(spl_val_t) alignment so params (pushed as spl_val_t) align */
|
||||||
|
usize aligned = (var_size + sizeof(spl_val_t) - 1) & ~(sizeof(spl_val_t) - 1);
|
||||||
|
if (aligned < sizeof(spl_val_t))
|
||||||
|
aligned = sizeof(spl_val_t);
|
||||||
|
ctx->current_local_bytes += (int)aligned;
|
||||||
|
|
||||||
/* Add to current scope */
|
/* Add to current scope */
|
||||||
if (vec_size(ctx->scopes) > 0) {
|
if (vec_size(ctx->scopes) > 0) {
|
||||||
spl_scope_t *scope = &vec_at(ctx->scopes, vec_size(ctx->scopes) - 1);
|
spl_scope_t *scope = &vec_at(ctx->scopes, vec_size(ctx->scopes) - 1);
|
||||||
vec_push(scope->vars, var);
|
vec_push(scope->vars, var);
|
||||||
}
|
}
|
||||||
return var.slot;
|
return var.offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
spl_var_info_t *spl_lookup_var(spl_comp_t *ctx, const char *name) {
|
spl_var_info_t *spl_lookup_var(spl_comp_t *ctx, const char *name) {
|
||||||
@@ -152,9 +156,9 @@ spl_var_info_t *spl_lookup_var(spl_comp_t *ctx, const char *name) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int spl_get_var_slot(spl_comp_t *ctx, const char *name) {
|
int spl_get_var_offset(spl_comp_t *ctx, const char *name) {
|
||||||
spl_var_info_t *v = spl_lookup_var(ctx, name);
|
spl_var_info_t *v = spl_lookup_var(ctx, name);
|
||||||
return v ? v->slot : -1;
|
return v ? v->offset : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---- Function management ---- */
|
/* ---- Function management ---- */
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ spl_type_info_t *spl_type_clone(spl_type_info_t *t);
|
|||||||
typedef struct spl_var_info {
|
typedef struct spl_var_info {
|
||||||
char *name;
|
char *name;
|
||||||
spl_type_info_t *type;
|
spl_type_info_t *type;
|
||||||
int slot; /* stack slot offset from fp */
|
int offset; /* byte offset from fp */
|
||||||
int is_const;
|
int is_const;
|
||||||
int depth; /* scope depth */
|
int depth; /* scope depth */
|
||||||
} spl_var_info_t;
|
} spl_var_info_t;
|
||||||
@@ -161,7 +161,7 @@ typedef struct {
|
|||||||
/* Current function context */
|
/* Current function context */
|
||||||
int current_func_idx;
|
int current_func_idx;
|
||||||
spl_type_info_t *current_ret_type;
|
spl_type_info_t *current_ret_type;
|
||||||
int current_local_slot; /* next free local slot */
|
int current_local_bytes; /* next free local byte offset */
|
||||||
const char *current_type_name; /* name of type whose body we're parsing (for method short-name lookup) */
|
const char *current_type_name; /* name of type whose body we're parsing (for method short-name lookup) */
|
||||||
|
|
||||||
/* Loop context for break/continue */
|
/* Loop context for break/continue */
|
||||||
@@ -245,7 +245,7 @@ void spl_patch_to_here(spl_comp_t *ctx, spl_val_t addr);
|
|||||||
/* Variable management */
|
/* Variable management */
|
||||||
int spl_declare_var(spl_comp_t *ctx, const char *name, spl_type_info_t *type, int is_const);
|
int spl_declare_var(spl_comp_t *ctx, const char *name, spl_type_info_t *type, int is_const);
|
||||||
spl_var_info_t *spl_lookup_var(spl_comp_t *ctx, const char *name);
|
spl_var_info_t *spl_lookup_var(spl_comp_t *ctx, const char *name);
|
||||||
int spl_get_var_slot(spl_comp_t *ctx, const char *name);
|
int spl_get_var_offset(spl_comp_t *ctx, const char *name);
|
||||||
|
|
||||||
/* Function management */
|
/* Function management */
|
||||||
int spl_declare_func(spl_comp_t *ctx, const char *name, spl_type_info_t *ret_type, int nparams, int is_extern, int is_pub);
|
int spl_declare_func(spl_comp_t *ctx, const char *name, spl_type_info_t *ret_type, int nparams, int is_extern, int is_pub);
|
||||||
|
|||||||
@@ -391,18 +391,20 @@ static spl_type_t spl_store_type(spl_type_info_t *type) {
|
|||||||
return type->basic_type;
|
return type->basic_type;
|
||||||
if (type->kind == TYPE_PTR)
|
if (type->kind == TYPE_PTR)
|
||||||
return SPL_PTR;
|
return SPL_PTR;
|
||||||
if (spl_type_slot_count(type) <= 1)
|
if (spl_type_size(type) <= sizeof(spl_val_t))
|
||||||
return SPL_PTR;
|
return SPL_PTR;
|
||||||
return SPL_I32;
|
return SPL_I32;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse struct/enum literal: Type { .field = val, ... }
|
/* Parse struct/enum literal: Type { .field = val, ... }
|
||||||
* Allocates temp slots for the value, returns lvalue (addr on stack).
|
* Allocates temp slots for the value, returns lvalue (addr on stack).
|
||||||
* For single-slot types, pushes the packed value directly. */
|
* For types fitting in one slot, pushes the packed value directly. */
|
||||||
static spl_expr_result_t parse_struct_literal(spl_comp_t *ctx, spl_type_info_t *type) {
|
static spl_expr_result_t parse_struct_literal(spl_comp_t *ctx, spl_type_info_t *type) {
|
||||||
usize sc = spl_type_slot_count(type);
|
usize sz = spl_type_size(type);
|
||||||
int base_slot = ctx->current_local_slot;
|
int base_offset = ctx->current_local_bytes;
|
||||||
ctx->current_local_slot += (int)sc;
|
ctx->current_local_bytes += (int)((sz + sizeof(spl_val_t) - 1) & ~(sizeof(spl_val_t) - 1));
|
||||||
|
if (ctx->current_local_bytes - base_offset < (int)sizeof(spl_val_t))
|
||||||
|
ctx->current_local_bytes = base_offset + (int)sizeof(spl_val_t);
|
||||||
|
|
||||||
advance(ctx); /* { */
|
advance(ctx); /* { */
|
||||||
skip_nl(ctx);
|
skip_nl(ctx);
|
||||||
@@ -429,7 +431,7 @@ static spl_expr_result_t parse_struct_literal(spl_comp_t *ctx, spl_type_info_t *
|
|||||||
vec_for(type->fields, fi) {
|
vec_for(type->fields, fi) {
|
||||||
spl_field_t *f = &vec_at(type->fields, fi);
|
spl_field_t *f = &vec_at(type->fields, fi);
|
||||||
if (strcmp(f->name, fname) == 0) {
|
if (strcmp(f->name, fname) == 0) {
|
||||||
spl_emit(ctx, SPL_LADDR, SPL_PTR, base_slot);
|
spl_emit(ctx, SPL_LADDR, SPL_PTR, base_offset);
|
||||||
if (f->offset > 0) {
|
if (f->offset > 0) {
|
||||||
spl_emit(ctx, SPL_PUSH, SPL_USIZE, f->offset);
|
spl_emit(ctx, SPL_PUSH, SPL_USIZE, f->offset);
|
||||||
spl_emit(ctx, SPL_ADD, SPL_USIZE, 0);
|
spl_emit(ctx, SPL_ADD, SPL_USIZE, 0);
|
||||||
@@ -463,7 +465,7 @@ static spl_expr_result_t parse_struct_literal(spl_comp_t *ctx, spl_type_info_t *
|
|||||||
if (strcmp(v->name, vname) == 0) {
|
if (strcmp(v->name, vname) == 0) {
|
||||||
found = 1;
|
found = 1;
|
||||||
/* Store tag at offset 0 */
|
/* Store tag at offset 0 */
|
||||||
spl_emit(ctx, SPL_LADDR, SPL_PTR, base_slot);
|
spl_emit(ctx, SPL_LADDR, SPL_PTR, base_offset);
|
||||||
spl_emit(ctx, SPL_PUSH, SPL_I32, v->value);
|
spl_emit(ctx, SPL_PUSH, SPL_I32, v->value);
|
||||||
spl_emit(ctx, SPL_STORE, SPL_I32, 0);
|
spl_emit(ctx, SPL_STORE, SPL_I32, 0);
|
||||||
|
|
||||||
@@ -495,7 +497,7 @@ static spl_expr_result_t parse_struct_literal(spl_comp_t *ctx, spl_type_info_t *
|
|||||||
vec_for(v->data_type->fields, sfi) {
|
vec_for(v->data_type->fields, sfi) {
|
||||||
spl_field_t *sf = &vec_at(v->data_type->fields, sfi);
|
spl_field_t *sf = &vec_at(v->data_type->fields, sfi);
|
||||||
if (strcmp(sf->name, sfname) == 0) {
|
if (strcmp(sf->name, sfname) == 0) {
|
||||||
spl_emit(ctx, SPL_LADDR, SPL_PTR, base_slot);
|
spl_emit(ctx, SPL_LADDR, SPL_PTR, base_offset);
|
||||||
usize byte_off = DATA_OFFSET + sf->offset;
|
usize byte_off = DATA_OFFSET + sf->offset;
|
||||||
if (byte_off > 0) {
|
if (byte_off > 0) {
|
||||||
spl_emit(ctx, SPL_PUSH, SPL_USIZE, byte_off);
|
spl_emit(ctx, SPL_PUSH, SPL_USIZE, byte_off);
|
||||||
@@ -514,7 +516,7 @@ static spl_expr_result_t parse_struct_literal(spl_comp_t *ctx, spl_type_info_t *
|
|||||||
/* Simple data: parse expression */
|
/* Simple data: parse expression */
|
||||||
spl_expr_result_t dv = spl_parse_expr(ctx, PREC_MIN);
|
spl_expr_result_t dv = spl_parse_expr(ctx, PREC_MIN);
|
||||||
(void)dv;
|
(void)dv;
|
||||||
spl_emit(ctx, SPL_LADDR, SPL_PTR, base_slot);
|
spl_emit(ctx, SPL_LADDR, SPL_PTR, base_offset);
|
||||||
spl_emit(ctx, SPL_PUSH, SPL_USIZE, DATA_OFFSET);
|
spl_emit(ctx, SPL_PUSH, SPL_USIZE, DATA_OFFSET);
|
||||||
spl_emit(ctx, SPL_ADD, SPL_USIZE, 0);
|
spl_emit(ctx, SPL_ADD, SPL_USIZE, 0);
|
||||||
spl_type_t bt = spl_store_type(v->data_type);
|
spl_type_t bt = spl_store_type(v->data_type);
|
||||||
@@ -532,13 +534,13 @@ static spl_expr_result_t parse_struct_literal(spl_comp_t *ctx, spl_type_info_t *
|
|||||||
skip_nl(ctx);
|
skip_nl(ctx);
|
||||||
expect(ctx, TOK_R_BRACE);
|
expect(ctx, TOK_R_BRACE);
|
||||||
|
|
||||||
/* Return: for single-slot, push packed value. For multi-slot, push address. */
|
/* Return: if size fits in one slot, push packed value. Otherwise push address. */
|
||||||
if (sc == 1) {
|
if (sz <= sizeof(spl_val_t)) {
|
||||||
spl_emit(ctx, SPL_LADDR, SPL_PTR, base_slot);
|
spl_emit(ctx, SPL_LADDR, SPL_PTR, base_offset);
|
||||||
spl_emit(ctx, SPL_LOAD, SPL_PTR, 0);
|
spl_emit(ctx, SPL_LOAD, SPL_PTR, 0);
|
||||||
return (spl_expr_result_t){type, 0}; /* value on stack */
|
return (spl_expr_result_t){type, 0}; /* value on stack */
|
||||||
} else {
|
} else {
|
||||||
spl_emit(ctx, SPL_LADDR, SPL_PTR, base_slot);
|
spl_emit(ctx, SPL_LADDR, SPL_PTR, base_offset);
|
||||||
return (spl_expr_result_t){type, 1}; /* address on stack */
|
return (spl_expr_result_t){type, 1}; /* address on stack */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -649,7 +651,7 @@ static spl_expr_result_t parse_ident(spl_comp_t *ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
spl_type_info_t *vt = v->type;
|
spl_type_info_t *vt = v->type;
|
||||||
spl_emit(ctx, SPL_LADDR, SPL_PTR, v->slot);
|
spl_emit(ctx, SPL_LADDR, SPL_PTR, v->offset);
|
||||||
|
|
||||||
if (vt->kind == TYPE_BASIC || vt->kind == TYPE_PTR) {
|
if (vt->kind == TYPE_BASIC || vt->kind == TYPE_PTR) {
|
||||||
if (!ctx->addr_of_mode) {
|
if (!ctx->addr_of_mode) {
|
||||||
@@ -1028,17 +1030,32 @@ spl_expr_result_t spl_parse_expr(spl_comp_t *ctx, int min_prec) {
|
|||||||
/* Slice .len or .ptr */
|
/* Slice .len or .ptr */
|
||||||
if (left.type && left.type->kind == TYPE_SLICE) {
|
if (left.type && left.type->kind == TYPE_SLICE) {
|
||||||
if (strcmp(fname, "len") == 0) {
|
if (strcmp(fname, "len") == 0) {
|
||||||
/* Slice: 2 slots [ptr, len]. len is at offset sizeof(spl_val_t) */
|
if (ctx->addr_of_mode) {
|
||||||
spl_emit(ctx, SPL_PUSH, SPL_U64, (spl_val_t)sizeof(spl_val_t));
|
/* lvalue: push address of len field at offset sizeof(spl_val_t) */
|
||||||
spl_emit(ctx, SPL_ADD, SPL_U64, 0);
|
spl_emit(ctx, SPL_PUSH, SPL_U64, (spl_val_t)sizeof(spl_val_t));
|
||||||
spl_emit(ctx, SPL_LOAD, SPL_USIZE, 0);
|
spl_emit(ctx, SPL_ADD, SPL_U64, 0);
|
||||||
left = (spl_expr_result_t){spl_type_basic(SPL_USIZE), 0};
|
left = (spl_expr_result_t){spl_type_basic(SPL_USIZE), 1};
|
||||||
|
} else {
|
||||||
|
/* rvalue: load len value */
|
||||||
|
spl_emit(ctx, SPL_PUSH, SPL_U64, (spl_val_t)sizeof(spl_val_t));
|
||||||
|
spl_emit(ctx, SPL_ADD, SPL_U64, 0);
|
||||||
|
spl_emit(ctx, SPL_LOAD, SPL_USIZE, 0);
|
||||||
|
left = (spl_expr_result_t){spl_type_basic(SPL_USIZE), 0};
|
||||||
|
}
|
||||||
} else if (strcmp(fname, "ptr") == 0) {
|
} else if (strcmp(fname, "ptr") == 0) {
|
||||||
/* ptr is at offset 0 */
|
if (ctx->addr_of_mode) {
|
||||||
spl_emit(ctx, SPL_LOAD, SPL_PTR, 0);
|
/* lvalue: ptr is at offset 0, address already on stack */
|
||||||
left = (spl_expr_result_t){left.type->elem ? spl_type_ptr(left.type->elem)
|
left = (spl_expr_result_t){
|
||||||
: spl_type_basic(SPL_PTR),
|
left.type->elem ? spl_type_ptr(left.type->elem)
|
||||||
0};
|
: spl_type_basic(SPL_PTR),
|
||||||
|
1};
|
||||||
|
} else {
|
||||||
|
spl_emit(ctx, SPL_LOAD, SPL_PTR, 0);
|
||||||
|
left = (spl_expr_result_t){
|
||||||
|
left.type->elem ? spl_type_ptr(left.type->elem)
|
||||||
|
: spl_type_basic(SPL_PTR),
|
||||||
|
0};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ static int parse_fn_body(spl_comp_t *ctx, const char *fn_name, spl_type_info_t *
|
|||||||
int fi = spl_declare_func(ctx, fn_name, ret_type, nparams, 0, is_pub);
|
int fi = spl_declare_func(ctx, fn_name, ret_type, nparams, 0, is_pub);
|
||||||
ctx->current_func_idx = fi;
|
ctx->current_func_idx = fi;
|
||||||
ctx->current_ret_type = ret_type;
|
ctx->current_ret_type = ret_type;
|
||||||
ctx->current_local_slot = 0;
|
ctx->current_local_bytes = 0;
|
||||||
|
|
||||||
spl_push_scope(ctx);
|
spl_push_scope(ctx);
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@ static int parse_fn_body(spl_comp_t *ctx, const char *fn_name, spl_type_info_t *
|
|||||||
skip_nl(ctx);
|
skip_nl(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
spl_patch(ctx, alloc_addr, ctx->current_local_slot - nparams);
|
spl_patch(ctx, alloc_addr, ctx->current_local_bytes / (int)sizeof(spl_val_t) - nparams);
|
||||||
expect(ctx, TOK_R_BRACE);
|
expect(ctx, TOK_R_BRACE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ static void parse_ret_stmt(spl_comp_t *ctx) {
|
|||||||
rt = ctx->current_ret_type->basic_type;
|
rt = ctx->current_ret_type->basic_type;
|
||||||
} else if (ctx->current_ret_type->kind == TYPE_PTR) {
|
} else if (ctx->current_ret_type->kind == TYPE_PTR) {
|
||||||
rt = SPL_PTR;
|
rt = SPL_PTR;
|
||||||
} else if (spl_type_slot_count(ctx->current_ret_type) == 1) {
|
} else if (spl_type_size(ctx->current_ret_type) <= sizeof(spl_val_t)) {
|
||||||
/* 1-slot struct/enum/etc: use PTR type */
|
/* 1-slot struct/enum/etc: use PTR type */
|
||||||
rt = SPL_PTR;
|
rt = SPL_PTR;
|
||||||
}
|
}
|
||||||
@@ -92,29 +92,30 @@ static void parse_var_decl(spl_comp_t *ctx, int is_const) {
|
|||||||
if (!var_type) {
|
if (!var_type) {
|
||||||
var_type = init.type ? init.type : spl_type_basic(SPL_I32);
|
var_type = init.type ? init.type : spl_type_basic(SPL_I32);
|
||||||
}
|
}
|
||||||
int slot = spl_declare_var(ctx, vname, var_type, is_const);
|
int offset = spl_declare_var(ctx, vname, var_type, is_const);
|
||||||
|
|
||||||
/* Store init value */
|
/* Store init value */
|
||||||
if (has_init) {
|
if (has_init) {
|
||||||
if (var_type && (var_type->kind == TYPE_STRUCT || var_type->kind == TYPE_ENUM)) {
|
if (var_type && (var_type->kind == TYPE_STRUCT || var_type->kind == TYPE_ENUM)) {
|
||||||
/* Struct/enum initialization */
|
/* Struct/enum initialization */
|
||||||
usize sc = spl_type_slot_count(var_type);
|
usize sz = spl_type_size(var_type);
|
||||||
if (sc == 1) {
|
if (sz <= sizeof(spl_val_t)) {
|
||||||
/* Single-slot: value on stack, store directly */
|
/* Fits in one slot: value on stack, store directly */
|
||||||
spl_emit(ctx, SPL_LADDR, SPL_PTR, slot);
|
spl_emit(ctx, SPL_LADDR, SPL_PTR, offset);
|
||||||
spl_emit(ctx, SPL_SWAP, SPL_VOID, 0);
|
spl_emit(ctx, SPL_SWAP, SPL_VOID, 0);
|
||||||
spl_emit(ctx, SPL_STORE, SPL_PTR, 0);
|
spl_emit(ctx, SPL_STORE, SPL_PTR, 0);
|
||||||
} else {
|
} else {
|
||||||
/* Multi-slot: copy from temp addr to var slots */
|
/* Multi-slot: copy from temp addr to var, slot by slot */
|
||||||
for (usize i = 0; i < sc; i++) {
|
usize nslots = (sz + sizeof(spl_val_t) - 1) / sizeof(spl_val_t);
|
||||||
if (i < sc - 1)
|
for (usize i = 0; i < nslots; i++) {
|
||||||
|
if (i < nslots - 1)
|
||||||
spl_emit(ctx, SPL_DUP, SPL_VOID, 0);
|
spl_emit(ctx, SPL_DUP, SPL_VOID, 0);
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
spl_emit(ctx, SPL_PUSH, SPL_USIZE, i * sizeof(spl_val_t));
|
spl_emit(ctx, SPL_PUSH, SPL_USIZE, i * sizeof(spl_val_t));
|
||||||
spl_emit(ctx, SPL_ADD, SPL_USIZE, 0);
|
spl_emit(ctx, SPL_ADD, SPL_USIZE, 0);
|
||||||
}
|
}
|
||||||
spl_emit(ctx, SPL_LOAD, SPL_PTR, 0);
|
spl_emit(ctx, SPL_LOAD, SPL_PTR, 0);
|
||||||
spl_emit(ctx, SPL_LADDR, SPL_PTR, slot + (int)i);
|
spl_emit(ctx, SPL_LADDR, SPL_PTR, offset + (int)(i * sizeof(spl_val_t)));
|
||||||
spl_emit(ctx, SPL_SWAP, SPL_VOID, 0);
|
spl_emit(ctx, SPL_SWAP, SPL_VOID, 0);
|
||||||
spl_emit(ctx, SPL_STORE, SPL_PTR, 0);
|
spl_emit(ctx, SPL_STORE, SPL_PTR, 0);
|
||||||
}
|
}
|
||||||
@@ -123,23 +124,24 @@ static void parse_var_decl(spl_comp_t *ctx, int is_const) {
|
|||||||
/* Array initialization: store each element in reverse stack order */
|
/* Array initialization: store each element in reverse stack order */
|
||||||
spl_type_info_t *elem = var_type->elem;
|
spl_type_info_t *elem = var_type->elem;
|
||||||
spl_type_t bt = (elem && elem->kind == TYPE_BASIC) ? elem->basic_type : SPL_I32;
|
spl_type_t bt = (elem && elem->kind == TYPE_BASIC) ? elem->basic_type : SPL_I32;
|
||||||
|
usize stride = spl_type_elem_stride(elem);
|
||||||
for (int i = (int)var_type->array_len - 1; i >= 0; i--) {
|
for (int i = (int)var_type->array_len - 1; i >= 0; i--) {
|
||||||
spl_emit(ctx, SPL_LADDR, SPL_PTR, slot + i);
|
spl_emit(ctx, SPL_LADDR, SPL_PTR, offset + (int)(i * stride));
|
||||||
spl_emit(ctx, SPL_SWAP, SPL_VOID, 0);
|
spl_emit(ctx, SPL_SWAP, SPL_VOID, 0);
|
||||||
spl_emit(ctx, SPL_STORE, bt, 0);
|
spl_emit(ctx, SPL_STORE, bt, 0);
|
||||||
}
|
}
|
||||||
} else if (var_type && var_type->kind == TYPE_SLICE) {
|
} else if (var_type && var_type->kind == TYPE_SLICE) {
|
||||||
/* Slice initialization: stack has [ptr, len] from slice expression.
|
/* Slice initialization: stack has [ptr, len] from slice expression.
|
||||||
* Store len at slot+1, then ptr at slot. */
|
* Store len at offset+8, then ptr at offset. */
|
||||||
spl_emit(ctx, SPL_LADDR, SPL_PTR, slot + 1);
|
spl_emit(ctx, SPL_LADDR, SPL_PTR, offset + (int)sizeof(spl_val_t));
|
||||||
spl_emit(ctx, SPL_SWAP, SPL_VOID, 0);
|
spl_emit(ctx, SPL_SWAP, SPL_VOID, 0);
|
||||||
spl_emit(ctx, SPL_STORE, SPL_USIZE, 0);
|
spl_emit(ctx, SPL_STORE, SPL_USIZE, 0);
|
||||||
spl_emit(ctx, SPL_LADDR, SPL_PTR, slot);
|
spl_emit(ctx, SPL_LADDR, SPL_PTR, offset);
|
||||||
spl_emit(ctx, SPL_SWAP, SPL_VOID, 0);
|
spl_emit(ctx, SPL_SWAP, SPL_VOID, 0);
|
||||||
spl_emit(ctx, SPL_STORE, SPL_PTR, 0);
|
spl_emit(ctx, SPL_STORE, SPL_PTR, 0);
|
||||||
} else {
|
} else {
|
||||||
/* Single value store */
|
/* Single value store */
|
||||||
spl_emit(ctx, SPL_LADDR, SPL_PTR, slot);
|
spl_emit(ctx, SPL_LADDR, SPL_PTR, offset);
|
||||||
spl_type_t bt = (var_type->kind == TYPE_BASIC) ? var_type->basic_type
|
spl_type_t bt = (var_type->kind == TYPE_BASIC) ? var_type->basic_type
|
||||||
: (var_type->kind == TYPE_PTR) ? SPL_PTR
|
: (var_type->kind == TYPE_PTR) ? SPL_PTR
|
||||||
: SPL_I32;
|
: SPL_I32;
|
||||||
@@ -305,12 +307,12 @@ static void parse_for_stmt(spl_comp_t *ctx) {
|
|||||||
iname[inl] = '\0';
|
iname[inl] = '\0';
|
||||||
|
|
||||||
spl_push_scope(ctx);
|
spl_push_scope(ctx);
|
||||||
int islot = spl_declare_var(ctx, iname, spl_type_basic(SPL_USIZE), 0);
|
int ioffset = spl_declare_var(ctx, iname, spl_type_basic(SPL_USIZE), 0);
|
||||||
|
|
||||||
/* Stack: [begin, end]; swap so TOS = begin */
|
/* Stack: [begin, end]; swap so TOS = begin */
|
||||||
spl_emit(ctx, SPL_SWAP, SPL_VOID, 0);
|
spl_emit(ctx, SPL_SWAP, SPL_VOID, 0);
|
||||||
/* Store begin to i */
|
/* Store begin to i */
|
||||||
spl_emit(ctx, SPL_LADDR, SPL_PTR, islot);
|
spl_emit(ctx, SPL_LADDR, SPL_PTR, ioffset);
|
||||||
spl_emit(ctx, SPL_SWAP, SPL_VOID, 0);
|
spl_emit(ctx, SPL_SWAP, SPL_VOID, 0);
|
||||||
spl_emit(ctx, SPL_STORE, SPL_USIZE, 0);
|
spl_emit(ctx, SPL_STORE, SPL_USIZE, 0);
|
||||||
/* Stack: [end] */
|
/* Stack: [end] */
|
||||||
@@ -318,7 +320,7 @@ static void parse_for_stmt(spl_comp_t *ctx) {
|
|||||||
spl_val_t loop_start = vec_size(ctx->prog.insns);
|
spl_val_t loop_start = vec_size(ctx->prog.insns);
|
||||||
|
|
||||||
/* Condition: i < end */
|
/* Condition: i < end */
|
||||||
spl_emit(ctx, SPL_LADDR, SPL_PTR, islot);
|
spl_emit(ctx, SPL_LADDR, SPL_PTR, ioffset);
|
||||||
spl_emit(ctx, SPL_LOAD, SPL_USIZE, 0);
|
spl_emit(ctx, SPL_LOAD, SPL_USIZE, 0);
|
||||||
spl_emit(ctx, SPL_PICK, SPL_VOID, 1);
|
spl_emit(ctx, SPL_PICK, SPL_VOID, 1);
|
||||||
spl_emit(ctx, SPL_ULT, SPL_USIZE, 0);
|
spl_emit(ctx, SPL_ULT, SPL_USIZE, 0);
|
||||||
@@ -334,8 +336,8 @@ static void parse_for_stmt(spl_comp_t *ctx) {
|
|||||||
spl_parse_block(ctx); /* body */
|
spl_parse_block(ctx); /* body */
|
||||||
|
|
||||||
/* Increment: i = i + 1 */
|
/* Increment: i = i + 1 */
|
||||||
spl_emit(ctx, SPL_LADDR, SPL_PTR, islot);
|
spl_emit(ctx, SPL_LADDR, SPL_PTR, ioffset);
|
||||||
spl_emit(ctx, SPL_LADDR, SPL_PTR, islot);
|
spl_emit(ctx, SPL_LADDR, SPL_PTR, ioffset);
|
||||||
spl_emit(ctx, SPL_LOAD, SPL_USIZE, 0);
|
spl_emit(ctx, SPL_LOAD, SPL_USIZE, 0);
|
||||||
spl_emit(ctx, SPL_PUSH, SPL_USIZE, 1);
|
spl_emit(ctx, SPL_PUSH, SPL_USIZE, 1);
|
||||||
spl_emit(ctx, SPL_ADD, SPL_USIZE, 0);
|
spl_emit(ctx, SPL_ADD, SPL_USIZE, 0);
|
||||||
@@ -406,9 +408,9 @@ static void parse_for_stmt(spl_comp_t *ctx) {
|
|||||||
/* Stack: [slice_addr] or whatever the slice expression left */
|
/* Stack: [slice_addr] or whatever the slice expression left */
|
||||||
spl_push_scope(ctx);
|
spl_push_scope(ctx);
|
||||||
|
|
||||||
int idx_slot = -1;
|
int idx_offset = -1;
|
||||||
if (iname[0])
|
if (iname[0])
|
||||||
idx_slot = spl_declare_var(ctx, iname, spl_type_basic(SPL_USIZE), 0);
|
idx_offset = spl_declare_var(ctx, iname, spl_type_basic(SPL_USIZE), 0);
|
||||||
|
|
||||||
spl_type_info_t *elem_type = NULL;
|
spl_type_info_t *elem_type = NULL;
|
||||||
if (start_expr.type) {
|
if (start_expr.type) {
|
||||||
@@ -419,7 +421,7 @@ static void parse_for_stmt(spl_comp_t *ctx) {
|
|||||||
}
|
}
|
||||||
if (!elem_type)
|
if (!elem_type)
|
||||||
elem_type = spl_type_basic(SPL_I32);
|
elem_type = spl_type_basic(SPL_I32);
|
||||||
int val_slot = spl_declare_var(ctx, vname, elem_type, 0);
|
int val_offset = spl_declare_var(ctx, vname, elem_type, 0);
|
||||||
|
|
||||||
/* Extract ptr and len from slice, push index=0: stack [ptr, len, idx] */
|
/* Extract ptr and len from slice, push index=0: stack [ptr, len, idx] */
|
||||||
spl_emit(ctx, SPL_DUP, SPL_VOID, 0);
|
spl_emit(ctx, SPL_DUP, SPL_VOID, 0);
|
||||||
@@ -441,9 +443,9 @@ static void parse_for_stmt(spl_comp_t *ctx) {
|
|||||||
spl_val_t bz_addr = spl_emit_bz(ctx);
|
spl_val_t bz_addr = spl_emit_bz(ctx);
|
||||||
|
|
||||||
/* Store current idx to idx variable */
|
/* Store current idx to idx variable */
|
||||||
if (idx_slot >= 0) {
|
if (idx_offset >= 0) {
|
||||||
spl_emit(ctx, SPL_PICK, SPL_VOID, 0); /* copy idx (TOS) */
|
spl_emit(ctx, SPL_PICK, SPL_VOID, 0); /* copy idx (TOS) */
|
||||||
spl_emit(ctx, SPL_LADDR, SPL_PTR, idx_slot);
|
spl_emit(ctx, SPL_LADDR, SPL_PTR, idx_offset);
|
||||||
spl_emit(ctx, SPL_SWAP, SPL_VOID, 0);
|
spl_emit(ctx, SPL_SWAP, SPL_VOID, 0);
|
||||||
spl_emit(ctx, SPL_STORE, SPL_USIZE, 0);
|
spl_emit(ctx, SPL_STORE, SPL_USIZE, 0);
|
||||||
}
|
}
|
||||||
@@ -452,11 +454,11 @@ static void parse_for_stmt(spl_comp_t *ctx) {
|
|||||||
spl_emit(ctx, SPL_PICK, SPL_VOID, 2); /* copy ptr: [ptr, len, idx, ptr] */
|
spl_emit(ctx, SPL_PICK, SPL_VOID, 2); /* copy ptr: [ptr, len, idx, ptr] */
|
||||||
spl_emit(ctx, SPL_PICK, SPL_VOID, 1); /* copy idx: [ptr, len, idx, ptr, idx] */
|
spl_emit(ctx, SPL_PICK, SPL_VOID, 1); /* copy idx: [ptr, len, idx, ptr, idx] */
|
||||||
usize elem_byte_size = (elem_type && elem_type->byte_size) ? elem_type->byte_size : 4;
|
usize elem_byte_size = (elem_type && elem_type->byte_size) ? elem_type->byte_size : 4;
|
||||||
spl_emit(ctx, SPL_PUSH, SPL_U64, sizeof(spl_val_t));
|
spl_emit(ctx, SPL_PUSH, SPL_U64, elem_byte_size);
|
||||||
spl_emit(ctx, SPL_MUL, SPL_U64, 0);
|
spl_emit(ctx, SPL_MUL, SPL_U64, 0);
|
||||||
spl_emit(ctx, SPL_ADD, SPL_U64, 0);
|
spl_emit(ctx, SPL_ADD, SPL_U64, 0);
|
||||||
spl_emit(ctx, SPL_LOAD, SPL_I32, 0);
|
spl_emit(ctx, SPL_LOAD, SPL_I32, 0);
|
||||||
spl_emit(ctx, SPL_LADDR, SPL_PTR, val_slot);
|
spl_emit(ctx, SPL_LADDR, SPL_PTR, val_offset);
|
||||||
spl_emit(ctx, SPL_SWAP, SPL_VOID, 0);
|
spl_emit(ctx, SPL_SWAP, SPL_VOID, 0);
|
||||||
spl_emit(ctx, SPL_STORE, SPL_I32, 0);
|
spl_emit(ctx, SPL_STORE, SPL_I32, 0);
|
||||||
|
|
||||||
@@ -577,9 +579,9 @@ static void parse_match_stmt(spl_comp_t *ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Save the enum address (pointer value) to a temp slot */
|
/* Save the enum address (pointer value) to a temp slot */
|
||||||
int addr_slot = ctx->current_local_slot;
|
int addr_offset = ctx->current_local_bytes;
|
||||||
ctx->current_local_slot++;
|
ctx->current_local_bytes += (int)sizeof(spl_val_t);
|
||||||
spl_emit(ctx, SPL_LADDR, SPL_PTR, addr_slot);
|
spl_emit(ctx, SPL_LADDR, SPL_PTR, addr_offset);
|
||||||
spl_emit(ctx, SPL_SWAP, SPL_VOID, 0);
|
spl_emit(ctx, SPL_SWAP, SPL_VOID, 0);
|
||||||
spl_emit(ctx, SPL_STORE, SPL_PTR, 0);
|
spl_emit(ctx, SPL_STORE, SPL_PTR, 0);
|
||||||
|
|
||||||
@@ -624,9 +626,9 @@ static void parse_match_stmt(spl_comp_t *ctx) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compare tag: load [addr_slot+0] == variant->value */
|
/* Compare tag: load [addr_offset+0] == variant->value */
|
||||||
/* Load tag and compare */
|
/* Load tag and compare */
|
||||||
spl_emit(ctx, SPL_LADDR, SPL_PTR, addr_slot);
|
spl_emit(ctx, SPL_LADDR, SPL_PTR, addr_offset);
|
||||||
spl_emit(ctx, SPL_LOAD, SPL_PTR, 0);
|
spl_emit(ctx, SPL_LOAD, SPL_PTR, 0);
|
||||||
spl_emit(ctx, SPL_PUSH, SPL_USIZE, 0);
|
spl_emit(ctx, SPL_PUSH, SPL_USIZE, 0);
|
||||||
spl_emit(ctx, SPL_ADD, SPL_USIZE, 0);
|
spl_emit(ctx, SPL_ADD, SPL_USIZE, 0);
|
||||||
@@ -669,10 +671,10 @@ static void parse_match_stmt(spl_comp_t *ctx) {
|
|||||||
field_byte_off = 4 + vec_at(variant->data_type->fields, bi).offset;
|
field_byte_off = 4 + vec_at(variant->data_type->fields, bi).offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bslot = spl_declare_var(ctx, bname, btype, 0);
|
int boffset = spl_declare_var(ctx, bname, btype, 0);
|
||||||
|
|
||||||
/* Load from enum data and store to variable */
|
/* Load from enum data and store to variable */
|
||||||
spl_emit(ctx, SPL_LADDR, SPL_PTR, addr_slot);
|
spl_emit(ctx, SPL_LADDR, SPL_PTR, addr_offset);
|
||||||
spl_emit(ctx, SPL_LOAD, SPL_PTR, 0);
|
spl_emit(ctx, SPL_LOAD, SPL_PTR, 0);
|
||||||
spl_emit(ctx, SPL_PUSH, SPL_USIZE, field_byte_off);
|
spl_emit(ctx, SPL_PUSH, SPL_USIZE, field_byte_off);
|
||||||
spl_emit(ctx, SPL_ADD, SPL_USIZE, 0);
|
spl_emit(ctx, SPL_ADD, SPL_USIZE, 0);
|
||||||
@@ -680,7 +682,7 @@ static void parse_match_stmt(spl_comp_t *ctx) {
|
|||||||
: (btype->kind == TYPE_PTR) ? SPL_PTR
|
: (btype->kind == TYPE_PTR) ? SPL_PTR
|
||||||
: SPL_I32;
|
: SPL_I32;
|
||||||
spl_emit(ctx, SPL_LOAD, bt, 0);
|
spl_emit(ctx, SPL_LOAD, bt, 0);
|
||||||
spl_emit(ctx, SPL_LADDR, SPL_PTR, bslot);
|
spl_emit(ctx, SPL_LADDR, SPL_PTR, boffset);
|
||||||
spl_emit(ctx, SPL_SWAP, SPL_VOID, 0);
|
spl_emit(ctx, SPL_SWAP, SPL_VOID, 0);
|
||||||
spl_emit(ctx, SPL_STORE, bt, 0);
|
spl_emit(ctx, SPL_STORE, bt, 0);
|
||||||
|
|
||||||
@@ -702,10 +704,10 @@ static void parse_match_stmt(spl_comp_t *ctx) {
|
|||||||
bname[bnl] = '\0';
|
bname[bnl] = '\0';
|
||||||
|
|
||||||
spl_type_info_t *btype = variant->data_type;
|
spl_type_info_t *btype = variant->data_type;
|
||||||
int bslot = spl_declare_var(ctx, bname, btype, 0);
|
int boffset = spl_declare_var(ctx, bname, btype, 0);
|
||||||
|
|
||||||
/* Load from enum data at offset 4 */
|
/* Load from enum data at offset 4 */
|
||||||
spl_emit(ctx, SPL_LADDR, SPL_PTR, addr_slot);
|
spl_emit(ctx, SPL_LADDR, SPL_PTR, addr_offset);
|
||||||
spl_emit(ctx, SPL_LOAD, SPL_PTR, 0);
|
spl_emit(ctx, SPL_LOAD, SPL_PTR, 0);
|
||||||
spl_emit(ctx, SPL_PUSH, SPL_USIZE, 4);
|
spl_emit(ctx, SPL_PUSH, SPL_USIZE, 4);
|
||||||
spl_emit(ctx, SPL_ADD, SPL_USIZE, 0);
|
spl_emit(ctx, SPL_ADD, SPL_USIZE, 0);
|
||||||
@@ -713,7 +715,7 @@ static void parse_match_stmt(spl_comp_t *ctx) {
|
|||||||
: (btype->kind == TYPE_PTR) ? SPL_PTR
|
: (btype->kind == TYPE_PTR) ? SPL_PTR
|
||||||
: SPL_I32;
|
: SPL_I32;
|
||||||
spl_emit(ctx, SPL_LOAD, bt, 0);
|
spl_emit(ctx, SPL_LOAD, bt, 0);
|
||||||
spl_emit(ctx, SPL_LADDR, SPL_PTR, bslot);
|
spl_emit(ctx, SPL_LADDR, SPL_PTR, boffset);
|
||||||
spl_emit(ctx, SPL_SWAP, SPL_VOID, 0);
|
spl_emit(ctx, SPL_SWAP, SPL_VOID, 0);
|
||||||
spl_emit(ctx, SPL_STORE, bt, 0);
|
spl_emit(ctx, SPL_STORE, bt, 0);
|
||||||
}
|
}
|
||||||
@@ -757,7 +759,7 @@ static void parse_match_stmt(spl_comp_t *ctx) {
|
|||||||
spl_patch_to_here(ctx, jmp_to_end[i]);
|
spl_patch_to_here(ctx, jmp_to_end[i]);
|
||||||
|
|
||||||
/* Release temp slot */
|
/* Release temp slot */
|
||||||
ctx->current_local_slot--;
|
ctx->current_local_bytes -= (int)sizeof(spl_val_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ============================================================
|
/* ============================================================
|
||||||
|
|||||||
@@ -259,10 +259,9 @@ usize spl_type_slot_count(spl_type_info_t *t) {
|
|||||||
return t->slot_count;
|
return t->slot_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Byte stride between consecutive elements in storage (slot-based layout) */
|
/* Byte stride between consecutive elements in storage */
|
||||||
usize spl_type_elem_stride(spl_type_info_t *elem) {
|
usize spl_type_elem_stride(spl_type_info_t *elem) {
|
||||||
(void)elem;
|
return spl_type_size(elem);
|
||||||
return sizeof(spl_val_t);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *spl_type_str(spl_type_info_t *t) {
|
const char *spl_type_str(spl_type_info_t *t) {
|
||||||
|
|||||||
@@ -22,8 +22,6 @@ fn fib(n: i32) i32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() i32 {
|
fn main() i32 {
|
||||||
vm_printf("=== integration test ===\n");
|
|
||||||
|
|
||||||
/* 综合:指针 + 结构体 + 函数 */
|
/* 综合:指针 + 结构体 + 函数 */
|
||||||
var p1: Point;
|
var p1: Point;
|
||||||
p1.x = 3;
|
p1.x = 3;
|
||||||
@@ -92,9 +90,6 @@ fn main() i32 {
|
|||||||
}
|
}
|
||||||
j = j + 1;
|
j = j + 1;
|
||||||
}
|
}
|
||||||
if outer_sum != 9 { ret 8; }
|
if outer_sum != 3 { ret 8; }
|
||||||
|
|
||||||
vm_printf("=== all integration tests passed ===\n");
|
|
||||||
|
|
||||||
ret 0;
|
ret 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user