From da9dae734c9425e090b04453e0a8dff89376b664 Mon Sep 17 00:00:00 2001 From: zzy <2450266535@qq.com> Date: Wed, 22 Jul 2026 18:04:35 +0800 Subject: [PATCH] =?UTF-8?q?stage1=20=E4=BF=AE=E5=A4=8D=E9=94=99=E8=AF=AF?= =?UTF-8?q?=20=E6=8F=90=E4=BE=9B=E7=B1=BB=E5=9E=8B=E6=A3=80=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- stage0/spl_syscall.c | 7 +++ stage1/spl_emit.c | 3 ++ stage1/spl_expr.c | 113 ++++++++++++++++++++++++++++++++++++++----- stage1/spl_parser.c | 10 +++- stage1/spl_type.c | 33 +++++++------ 5 files changed, 136 insertions(+), 30 deletions(-) diff --git a/stage0/spl_syscall.c b/stage0/spl_syscall.c index e540a95..4bf8e9b 100644 --- a/stage0/spl_syscall.c +++ b/stage0/spl_syscall.c @@ -194,6 +194,13 @@ static spl_val_t vm_printf(int nargs, spl_val_t *args) { continue; } switch (fmt[i]) { + case '.': { + Assert(i + 2 < fmt_len && arg_idx + 1 <= nargs && fmt[i + 1] == '*' && + fmt[i + 2] == 's'); + for (usize j = 0; j < args[arg_idx]; ++j) { + vec_push(buffer, ((const char *)args[arg_idx + 1])[j]); + } + } break; case 'd': snprintf(tmp_buf, sizeof(tmp_buf), "%zd", args[arg_idx]); for (usize j = 0; j < strlen(tmp_buf); ++j) { diff --git a/stage1/spl_emit.c b/stage1/spl_emit.c index 80b4f85..3b61646 100644 --- a/stage1/spl_emit.c +++ b/stage1/spl_emit.c @@ -185,6 +185,9 @@ void emit_patch_call_fixups(spl_emit_t *e, spl_prog_t *prog) { if (fe->func_idx >= 0 && fe->func_idx < (int)vec_size(prog->funcs)) { spl_val_t addr = vec_at(prog->funcs, fe->func_idx).address; vec_at(prog->insns, fe->insn_idx).imm = addr; + } else { + fprintf(stderr, "WARN: fixup func_idx=%d out of bounds [0,%zu), insn_idx=%zu\n", + fe->func_idx, vec_size(prog->funcs), fe->insn_idx); } } } diff --git a/stage1/spl_expr.c b/stage1/spl_expr.c index 725c5db..e25b021 100644 --- a/stage1/spl_expr.c +++ b/stage1/spl_expr.c @@ -609,24 +609,107 @@ static int parse_call_args(spl_comp_t *ctx) { return nargs; } +static int types_equal(spl_type_ctx_t *tctx, int a, int b) { + if (a < 0 || b < 0) + return 0; + a = spl_type_resolve_underlying(tctx, a); + b = spl_type_resolve_underlying(tctx, b); + if (a == b) + return 1; + + spl_type_kind_t ak = spl_type_kind(tctx, a); + spl_type_kind_t bk = spl_type_kind(tctx, b); + if (ak != bk) + return 0; + + switch (ak) { + case TYPE_VOID: + return 1; + case TYPE_BASIC: + return spl_type_basic_type(tctx, a) == spl_type_basic_type(tctx, b); + case TYPE_PTR: + return types_equal(tctx, spl_type_elem_type(tctx, a), spl_type_elem_type(tctx, b)); + case TYPE_ARRAY: + return spl_type_array_len(tctx, a) == spl_type_array_len(tctx, b) && + types_equal(tctx, spl_type_elem_type(tctx, a), spl_type_elem_type(tctx, b)); + case TYPE_SLICE: + return types_equal(tctx, spl_type_elem_type(tctx, a), spl_type_elem_type(tctx, b)); + case TYPE_STRUCT: + case TYPE_UNION: + case TYPE_ENUM: { + const char *an = spl_type_name(tctx, a); + const char *bn = spl_type_name(tctx, b); + return an && bn && strcmp(an, bn) == 0; + } + default: + return 0; + } +} + static void spl_check_arg_type(spl_comp_t *ctx, const char *fname, int arg_type_idx, int param_type_idx, int arg_idx) { if (arg_type_idx < 0 || param_type_idx < 0) return; - if (spl_type_kind(&ctx->tctx, param_type_idx) == TYPE_PTR && - spl_type_elem_type(&ctx->tctx, param_type_idx) >= 0 && - spl_type_kind(&ctx->tctx, arg_type_idx) != TYPE_PTR && - spl_type_name(&ctx->tctx, arg_type_idx) && - spl_type_name(&ctx->tctx, spl_type_elem_type(&ctx->tctx, param_type_idx)) && - strcmp(spl_type_name(&ctx->tctx, arg_type_idx), - spl_type_name(&ctx->tctx, spl_type_elem_type(&ctx->tctx, param_type_idx))) == 0) { - fprintf(stderr, - "%s: warning: argument %d of '%s' expects '%s*', " - "got '%s' (missing '&'?)\n", - ctx->fname, arg_idx + 1, fname, - spl_type_name(&ctx->tctx, spl_type_elem_type(&ctx->tctx, param_type_idx)), - spl_type_name(&ctx->tctx, arg_type_idx)); + + /* Level 1: structurally equal types */ + if (types_equal(&ctx->tctx, arg_type_idx, param_type_idx)) + return; + + int arg_u = spl_type_resolve_underlying(&ctx->tctx, arg_type_idx); + int param_u = spl_type_resolve_underlying(&ctx->tctx, param_type_idx); + + /* Level 1b: void pointer (*_) accepts any pointer */ + if (spl_type_kind(&ctx->tctx, param_u) == TYPE_PTR) { + int param_elem = spl_type_elem_type(&ctx->tctx, param_u); + int param_elem_u = spl_type_resolve_underlying(&ctx->tctx, param_elem); + if (param_elem_u >= 0 && spl_type_kind(&ctx->tctx, param_elem_u) == TYPE_BASIC && + spl_type_basic_type(&ctx->tctx, param_elem_u) == SPL_VOID && + spl_type_kind(&ctx->tctx, arg_u) == TYPE_PTR) { + return; + } } + + /* Level 2: pointer indirection mismatch with same inner type */ + if (spl_type_kind(&ctx->tctx, param_u) == TYPE_PTR) { + int param_elem = spl_type_elem_type(&ctx->tctx, param_u); + if (param_elem < 0) + goto type_mismatch; + + /* 2a: param = *T, arg = T (missing '&') */ + if (spl_type_kind(&ctx->tctx, arg_u) != TYPE_PTR) { + if (types_equal(&ctx->tctx, arg_type_idx, param_elem)) { + const char *is = spl_type_str(&ctx->tctx, param_elem); + fprintf(stderr, + "%s: warning: argument %d of '%s' expects '%s*', " + "got '%s' (missing '&'?)\n", + ctx->fname, arg_idx + 1, fname, is, is); + return; + } + } + + /* 2b: param = *T, arg = **T (extra '&') */ + if (spl_type_kind(&ctx->tctx, arg_u) == TYPE_PTR) { + int arg_elem = spl_type_elem_type(&ctx->tctx, arg_u); + int arg_elem_u = spl_type_resolve_underlying(&ctx->tctx, arg_elem); + if (spl_type_kind(&ctx->tctx, arg_elem_u) == TYPE_PTR) { + if (types_equal(&ctx->tctx, spl_type_elem_type(&ctx->tctx, arg_elem), param_elem)) { + const char *is = spl_type_str(&ctx->tctx, param_elem); + fprintf(stderr, + "%s: warning: argument %d of '%s' expects '%s*', " + "got '%s**' (extra '&'?)\n", + ctx->fname, arg_idx + 1, fname, is, is); + return; + } + } + } + } + + /* Level 3: general type mismatch → error */ +type_mismatch:; + const char *as = spl_type_str(&ctx->tctx, arg_type_idx); + const char *ps = spl_type_str(&ctx->tctx, param_type_idx); + spl_comp_error(ctx, "argument %d of '%s' type mismatch: expected '%s', got '%s'", arg_idx + 1, + fname, ps, as); } static int parse_call_args_checked(spl_comp_t *ctx, const char *fname, int *param_type_indices, @@ -975,6 +1058,10 @@ static spl_expr_result_t parse_postfix_expr(spl_comp_t *ctx, spl_expr_result_t l } expect(ctx, TOK_R_PAREN); + if (func->func_idx < 0) { + fprintf(stderr, "WARN: method call '%s.' with invalid func_idx=%d\n", + func->name, func->func_idx); + } emit_call_with_fixup(&ctx->emit, nargs, func->func_idx); left = (spl_expr_result_t){func->ret_type_idx, 0}; diff --git a/stage1/spl_parser.c b/stage1/spl_parser.c index b0b1bea..12332a3 100644 --- a/stage1/spl_parser.c +++ b/stage1/spl_parser.c @@ -90,8 +90,14 @@ static int parse_fn_body(spl_comp_t *ctx, const char *fn_name, int ret_type_idx, if ((usize)ctx->emit.frame.peak_bytes < min_bytes) ctx->emit.frame.peak_bytes = (int)min_bytes; } - emit_patch(&ctx->emit, alloc_addr, - ctx->emit.frame.peak_bytes / (int)sizeof(spl_val_t) - total_phys_slots); + int alloc_slots = ctx->emit.frame.peak_bytes / (int)sizeof(spl_val_t) - total_phys_slots; + if (alloc_slots < 0 || alloc_slots > 65536) { + fprintf( + stderr, + "WARN: parse_fn_body: suspicious alloc_slots=%d (peak_bytes=%d, phys_slots=%d)\n", + alloc_slots, ctx->emit.frame.peak_bytes, total_phys_slots); + } + emit_patch(&ctx->emit, alloc_addr, alloc_slots); expect(ctx, TOK_R_BRACE); } diff --git a/stage1/spl_type.c b/stage1/spl_type.c index 77b58e9..0bddece 100644 --- a/stage1/spl_type.c +++ b/stage1/spl_type.c @@ -575,7 +575,14 @@ spl_type_t spl_type_emit_type(spl_type_ctx_t *tctx, int type_idx) { return SPL_PTR; } +#define TYPE_STR_BUF_COUNT 8 +#define TYPE_STR_BUF_SIZE 64 + const char *spl_type_str(spl_type_ctx_t *tctx, int type_idx) { + static char b[TYPE_STR_BUF_COUNT][TYPE_STR_BUF_SIZE]; + static int bi = 0; + int my = (bi++) % TYPE_STR_BUF_COUNT; + if (type_idx < 0) return ""; spl_type_info_t *t = &vec_at(tctx->types, type_idx); @@ -616,22 +623,18 @@ const char *spl_type_str(spl_type_ctx_t *tctx, int type_idx) { return ""; } } - case TYPE_PTR: { - static char buf[64]; - snprintf(buf, sizeof(buf), "*%s", spl_type_str(tctx, spl_type_elem_type(tctx, type_idx))); - return buf; - } - case TYPE_ARRAY: { - static char buf[64]; - snprintf(buf, sizeof(buf), "[%zu]%s", spl_type_array_len(tctx, type_idx), + case TYPE_PTR: + snprintf(b[my], TYPE_STR_BUF_SIZE, "*%s", spl_type_str(tctx, spl_type_elem_type(tctx, type_idx))); - return buf; - } - case TYPE_SLICE: { - static char buf[64]; - snprintf(buf, sizeof(buf), "[]%s", spl_type_str(tctx, spl_type_elem_type(tctx, type_idx))); - return buf; - } + return b[my]; + case TYPE_ARRAY: + snprintf(b[my], TYPE_STR_BUF_SIZE, "[%zu]%s", spl_type_array_len(tctx, type_idx), + spl_type_str(tctx, spl_type_elem_type(tctx, type_idx))); + return b[my]; + case TYPE_SLICE: + snprintf(b[my], TYPE_STR_BUF_SIZE, "[]%s", + spl_type_str(tctx, spl_type_elem_type(tctx, type_idx))); + return b[my]; case TYPE_STRUCT: case TYPE_UNION: case TYPE_ENUM: