stage1 将数组和聚合类型使用byte offset而不是slot idx

This commit is contained in:
zzy
2026-07-07 11:38:31 +08:00
parent 3cf11f922e
commit 1df3e3bcb4
9 changed files with 103 additions and 86 deletions

View File

@@ -391,18 +391,20 @@ static spl_type_t spl_store_type(spl_type_info_t *type) {
return type->basic_type;
if (type->kind == TYPE_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_I32;
}
/* Parse struct/enum literal: Type { .field = val, ... }
* 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) {
usize sc = spl_type_slot_count(type);
int base_slot = ctx->current_local_slot;
ctx->current_local_slot += (int)sc;
usize sz = spl_type_size(type);
int base_offset = ctx->current_local_bytes;
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); /* { */
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) {
spl_field_t *f = &vec_at(type->fields, fi);
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) {
spl_emit(ctx, SPL_PUSH, SPL_USIZE, f->offset);
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) {
found = 1;
/* 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_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) {
spl_field_t *sf = &vec_at(v->data_type->fields, sfi);
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;
if (byte_off > 0) {
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 */
spl_expr_result_t dv = spl_parse_expr(ctx, PREC_MIN);
(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_ADD, SPL_USIZE, 0);
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);
expect(ctx, TOK_R_BRACE);
/* Return: for single-slot, push packed value. For multi-slot, push address. */
if (sc == 1) {
spl_emit(ctx, SPL_LADDR, SPL_PTR, base_slot);
/* Return: if size fits in one slot, push packed value. Otherwise push address. */
if (sz <= sizeof(spl_val_t)) {
spl_emit(ctx, SPL_LADDR, SPL_PTR, base_offset);
spl_emit(ctx, SPL_LOAD, SPL_PTR, 0);
return (spl_expr_result_t){type, 0}; /* value on stack */
} 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 */
}
}
@@ -649,7 +651,7 @@ static spl_expr_result_t parse_ident(spl_comp_t *ctx) {
}
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 (!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 */
if (left.type && left.type->kind == TYPE_SLICE) {
if (strcmp(fname, "len") == 0) {
/* Slice: 2 slots [ptr, len]. len is at offset sizeof(spl_val_t) */
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};
if (ctx->addr_of_mode) {
/* lvalue: push address of len field at offset sizeof(spl_val_t) */
spl_emit(ctx, SPL_PUSH, SPL_U64, (spl_val_t)sizeof(spl_val_t));
spl_emit(ctx, SPL_ADD, SPL_U64, 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) {
/* ptr is at offset 0 */
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};
if (ctx->addr_of_mode) {
/* lvalue: ptr is at offset 0, address already on stack */
left = (spl_expr_result_t){
left.type->elem ? spl_type_ptr(left.type->elem)
: 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;
}