stage1 重构到 USIZE, 使得 vm 支持 usize, isize
This commit is contained in:
@@ -97,7 +97,7 @@ static void emit_slice_create(spl_comp_t *ctx, usize stride) {
|
||||
/* --- Compute len = end - begin --- */
|
||||
spl_emit(ctx, SPL_PICK, SPL_VOID, 1); /* [base, begin, end, ptr, end] */
|
||||
spl_emit(ctx, SPL_PICK, SPL_VOID, 3); /* [base, begin, end, ptr, end, begin] */
|
||||
spl_emit(ctx, SPL_SUB, SPL_I32, 0); /* [base, begin, end, ptr, len] */
|
||||
spl_emit(ctx, SPL_SUB, SPL_USIZE, 0); /* [base, begin, end, ptr, len] */
|
||||
|
||||
/* --- Cleanup: drop [base, begin, end], keep [ptr, len] --- */
|
||||
spl_emit(ctx, SPL_ROT, SPL_VOID, 0); /* [base, begin, ptr, len, end] */
|
||||
@@ -442,10 +442,25 @@ static spl_expr_result_t parse_prefix_op(spl_comp_t *ctx) {
|
||||
}
|
||||
break;
|
||||
case TOK_MUL:
|
||||
/* *expr — dereference: push the pointer value, then load */
|
||||
/* right should evaluate to the pointer */
|
||||
/* *expr — dereference */
|
||||
if (right.type && right.type->kind == TYPE_PTR && right.type->elem) {
|
||||
spl_emit(ctx, SPL_LOAD, right.type->elem->basic_type, 0);
|
||||
/* If right is still an lvalue, load the pointer value for the target */
|
||||
if (right.is_lvalue) {
|
||||
spl_emit(ctx, SPL_LOAD, SPL_PTR, 0);
|
||||
}
|
||||
spl_type_info_t *elem = right.type->elem;
|
||||
if (elem->kind == TYPE_BASIC || elem->kind == TYPE_PTR) {
|
||||
if (!ctx->addr_of_mode) {
|
||||
spl_type_t bt = (elem->kind == TYPE_BASIC) ? elem->basic_type : SPL_PTR;
|
||||
spl_emit(ctx, SPL_LOAD, bt, 0);
|
||||
right = (spl_expr_result_t){ elem, 0 };
|
||||
} else {
|
||||
right = (spl_expr_result_t){ elem, 1 };
|
||||
}
|
||||
} else {
|
||||
/* Struct/array/slice: keep address on stack */
|
||||
right = (spl_expr_result_t){ elem, 1 };
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -544,15 +559,19 @@ spl_expr_result_t spl_parse_expr(spl_comp_t *ctx, int min_prec) {
|
||||
if (strcmp(vec_at(left.type->fields, fi).name, fname) == 0) {
|
||||
spl_field_t *f = &vec_at(left.type->fields, fi);
|
||||
if (f->offset > 0) {
|
||||
spl_emit(ctx, SPL_PUSH, SPL_I32, f->offset);
|
||||
spl_emit(ctx, SPL_ADD, SPL_I32, 0);
|
||||
spl_emit(ctx, SPL_PUSH, SPL_USIZE, f->offset);
|
||||
spl_emit(ctx, SPL_ADD, SPL_USIZE, 0);
|
||||
}
|
||||
/* Load value if basic type */
|
||||
spl_type_info_t *ft = f->type;
|
||||
if (ft->kind == TYPE_BASIC || ft->kind == TYPE_PTR) {
|
||||
spl_type_t bt = (ft->kind == TYPE_BASIC) ? ft->basic_type : SPL_PTR;
|
||||
spl_emit(ctx, SPL_LOAD, bt, 0);
|
||||
left = (spl_expr_result_t){ ft, 0 };
|
||||
if (!ctx->addr_of_mode) {
|
||||
spl_type_t bt = (ft->kind == TYPE_BASIC) ? ft->basic_type : SPL_PTR;
|
||||
spl_emit(ctx, SPL_LOAD, bt, 0);
|
||||
left = (spl_expr_result_t){ ft, 0 };
|
||||
} else {
|
||||
left = (spl_expr_result_t){ ft, 1 };
|
||||
}
|
||||
} else {
|
||||
left = (spl_expr_result_t){ ft, 1 };
|
||||
}
|
||||
@@ -566,21 +585,27 @@ spl_expr_result_t spl_parse_expr(spl_comp_t *ctx, int min_prec) {
|
||||
if (left.type && left.type->kind == TYPE_PTR && left.type->elem &&
|
||||
left.type->elem->kind == TYPE_STRUCT) {
|
||||
spl_type_info_t *st = left.type->elem;
|
||||
/* Left has the pointer value on stack. Load it to get the struct address. */
|
||||
spl_emit(ctx, SPL_LOAD, SPL_PTR, 0);
|
||||
/* Load pointer value to get struct address if left is still lvalue */
|
||||
if (left.is_lvalue) {
|
||||
spl_emit(ctx, SPL_LOAD, SPL_PTR, 0);
|
||||
}
|
||||
/* Now search field */
|
||||
vec_for(st->fields, fi) {
|
||||
if (strcmp(vec_at(st->fields, fi).name, fname) == 0) {
|
||||
spl_field_t *f = &vec_at(st->fields, fi);
|
||||
if (f->offset > 0) {
|
||||
spl_emit(ctx, SPL_PUSH, SPL_I32, f->offset);
|
||||
spl_emit(ctx, SPL_ADD, SPL_I32, 0);
|
||||
spl_emit(ctx, SPL_PUSH, SPL_USIZE, f->offset);
|
||||
spl_emit(ctx, SPL_ADD, SPL_USIZE, 0);
|
||||
}
|
||||
spl_type_info_t *ft = f->type;
|
||||
if (ft->kind == TYPE_BASIC || ft->kind == TYPE_PTR) {
|
||||
spl_type_t bt = (ft->kind == TYPE_BASIC) ? ft->basic_type : SPL_PTR;
|
||||
spl_emit(ctx, SPL_LOAD, bt, 0);
|
||||
left = (spl_expr_result_t){ ft, 0 };
|
||||
if (!ctx->addr_of_mode) {
|
||||
spl_type_t bt = (ft->kind == TYPE_BASIC) ? ft->basic_type : SPL_PTR;
|
||||
spl_emit(ctx, SPL_LOAD, bt, 0);
|
||||
left = (spl_expr_result_t){ ft, 0 };
|
||||
} else {
|
||||
left = (spl_expr_result_t){ ft, 1 };
|
||||
}
|
||||
} else {
|
||||
left = (spl_expr_result_t){ ft, 1 };
|
||||
}
|
||||
@@ -596,8 +621,8 @@ spl_expr_result_t spl_parse_expr(spl_comp_t *ctx, int min_prec) {
|
||||
/* 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_I32, 0);
|
||||
left = (spl_expr_result_t){ spl_type_basic(SPL_I32), 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);
|
||||
@@ -606,22 +631,30 @@ spl_expr_result_t spl_parse_expr(spl_comp_t *ctx, int min_prec) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Postfix dereference: expr.* */
|
||||
if (strcmp(fname, "*") == 0 && left.type && left.type->kind == TYPE_PTR && left.type->elem) {
|
||||
if (left.is_lvalue) {
|
||||
spl_emit(ctx, SPL_LOAD, SPL_PTR, 0);
|
||||
}
|
||||
spl_type_info_t *elem = left.type->elem;
|
||||
if (elem->kind == TYPE_BASIC || elem->kind == TYPE_PTR) {
|
||||
if (!ctx->addr_of_mode) {
|
||||
spl_type_t bt = (elem->kind == TYPE_BASIC) ? elem->basic_type : SPL_PTR;
|
||||
spl_emit(ctx, SPL_LOAD, bt, 0);
|
||||
left = (spl_expr_result_t){ elem, 0 };
|
||||
} else {
|
||||
left = (spl_expr_result_t){ elem, 1 };
|
||||
}
|
||||
} else {
|
||||
left = (spl_expr_result_t){ elem, 1 };
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
spl_comp_error(ctx, "unknown field '%s'", fname);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Postfix deref: expr.* */
|
||||
if (opt == TOK_MUL && ctx->tok_idx + 1 < vec_size(ctx->toks) &&
|
||||
peek(ctx)->type == TOK_MUL && vec_at(ctx->toks, ctx->tok_idx + 1).type == TOK_MUL) {
|
||||
/* Handle .* — actually just * (multiplication) */
|
||||
/* The spec defines .* as postfix deref, but in token stream,
|
||||
* the lexer tokenizes .* as TOK_DOT + TOK_MUL */
|
||||
/* Actually, .* is not a multi-char token. Let's check the lexer. */
|
||||
/* If we see . then *, it's field access then multiplication? No. */
|
||||
/* In .*, we see TOK_DOT then TOK_MUL. But after TOK_DOT we already consumed
|
||||
* the next token as a field name. So .* doesn't work with the current approach. */
|
||||
}
|
||||
|
||||
/* Array/slice indexing: expr[expr] or expr[begin..end] */
|
||||
if (opt == TOK_L_BRACKET) {
|
||||
advance(ctx); /* skip [ */
|
||||
@@ -654,7 +687,7 @@ spl_expr_result_t spl_parse_expr(spl_comp_t *ctx, int min_prec) {
|
||||
spl_emit(ctx, SPL_PICK, SPL_VOID, 1);
|
||||
spl_emit(ctx, SPL_PUSH, SPL_U64, sizeof(spl_val_t));
|
||||
spl_emit(ctx, SPL_ADD, SPL_U64, 0);
|
||||
spl_emit(ctx, SPL_LOAD, SPL_I32, 0);
|
||||
spl_emit(ctx, SPL_LOAD, SPL_USIZE, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -695,9 +728,13 @@ spl_expr_result_t spl_parse_expr(spl_comp_t *ctx, int min_prec) {
|
||||
spl_emit(ctx, SPL_ADD, SPL_U64, 0);
|
||||
}
|
||||
if (elem && (elem->kind == TYPE_BASIC || elem->kind == TYPE_PTR)) {
|
||||
spl_type_t bt = (elem->kind == TYPE_BASIC) ? elem->basic_type : SPL_PTR;
|
||||
spl_emit(ctx, SPL_LOAD, bt, 0);
|
||||
left = (spl_expr_result_t){ elem, 0 };
|
||||
if (!ctx->addr_of_mode) {
|
||||
spl_type_t bt = (elem->kind == TYPE_BASIC) ? elem->basic_type : SPL_PTR;
|
||||
spl_emit(ctx, SPL_LOAD, bt, 0);
|
||||
left = (spl_expr_result_t){ elem, 0 };
|
||||
} else {
|
||||
left = (spl_expr_result_t){ elem, 1 };
|
||||
}
|
||||
} else {
|
||||
left = (spl_expr_result_t){ elem, 1 };
|
||||
}
|
||||
@@ -752,7 +789,9 @@ static spl_expr_result_t parse_infix(spl_comp_t *ctx, spl_expr_result_t left, sp
|
||||
ctx->addr_of_mode = saved_addr_of_mode;
|
||||
|
||||
if (left.is_lvalue) {
|
||||
spl_type_t bt = left.type && left.type->kind == TYPE_BASIC ? left.type->basic_type : SPL_I32;
|
||||
spl_type_t bt = left.type ?
|
||||
(left.type->kind == TYPE_BASIC ? left.type->basic_type :
|
||||
left.type->kind == TYPE_PTR ? SPL_PTR : SPL_I32) : SPL_I32;
|
||||
if (op == TOK_ASSIGN) {
|
||||
/* Simple assignment: stack is [addr, rhs] */
|
||||
/* STORE pops TOS=value, TOS-1=address — already correct order */
|
||||
|
||||
Reference in New Issue
Block a user