stage1 将数组和聚合类型使用byte offset而不是slot idx
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user