From 34df303b56d2e7f62401d2afef06f69efd09812f Mon Sep 17 00:00:00 2001 From: zzy <2450266535@qq.com> Date: Fri, 28 Aug 2026 13:01:19 +0800 Subject: [PATCH] =?UTF-8?q?stage1=20=E5=AE=9E=E7=8E=B0=E9=83=A8=E5=88=86as?= =?UTF-8?q?t2ir=E5=86=85=E5=AE=B9=E5=B9=B6=E9=87=8D=E6=9E=84stage0=20?= =?UTF-8?q?=E5=BC=95=E5=85=A5=E5=B9=B6=E9=87=8D=E6=9E=84ir2vm=20=E6=9E=84?= =?UTF-8?q?=E5=BB=BA=E7=B3=BB=E7=BB=9F=E4=BF=AE=E6=94=B9=E9=83=A8=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nob.c | 49 +- stage0/spl_cli.c | 9 + stage0/spl_disasm.c | 76 --- stage0/spl_mcode.c | 55 ++ stage0/spl_mcode.h | 1 + stage1/spl_ast.c | 138 ++-- stage1/spl_ast.h | 29 +- stage1/spl_ast2ir.c | 424 +++++++++++-- stage1/spl_ast2ir.h | 2 + stage1/spl_ir.c | 11 +- stage1/spl_ir.h | 2 +- stage1/spl_ir2vm.c | 1461 ++----------------------------------------- stage1/spl_ir2vm.h | 85 +-- stage1/spl_sema.c | 34 +- stage1/spl_type.c | 4 +- stage1/spl_type.h | 4 +- stage1/splc0.c | 52 +- 17 files changed, 636 insertions(+), 1800 deletions(-) delete mode 100644 stage0/spl_disasm.c diff --git a/nob.c b/nob.c index b7b08c5..6214383 100644 --- a/nob.c +++ b/nob.c @@ -1,52 +1,28 @@ #undef UNICODE #define NOB_IMPLEMENTATION -// Redefine nob_cc_flags() to carry the project's debug flags. Keep in sync -// with CFLAGS_STR below. + #define SPL_CFLAGS "-Wall", "-Wextra", "-O0", "-g", "-D_CRT_SECURE_NO_WARNINGS" #define nob_cc_flags(cmd) nob_cmd_append(cmd, SPL_CFLAGS) #include "nob.h" #ifdef _WIN32 #include #endif - -// C-side bootstrap build script. Builds the stage0 VM tools and the splc0 -// compiler from their C sources. The SPL self-hosting chain (splc1, ...) is -// out of scope and is driven by a different mechanism. -// -// Usage: -// cc -o nob nob.c # bootstrap once -// ./nob # build all targets -// ./nob build # build specific targets -// ./nob run [..] # build and run -// ./nob test # build and run VM unit tests -// ./nob clean # remove build artifacts -// ./nob list # list all targets -// ./nob help # print this help - #define BUILD_FOLDER "build/" -#ifdef _WIN32 -#define EXE_SUFFIX ".exe" -#else -#define EXE_SUFFIX "" -#endif - // Content of the .cflags stamp file; must match SPL_CFLAGS above. #define CFLAGS_STR "-Wall -Wextra -O0 -g" // Stamp file whose mtime is refreshed whenever the flags change so that all // object files get rebuilt. static const char *CFLAGS_STAMP = BUILD_FOLDER ".cflags"; -// Target descriptions #define VM_SRCS "stage0/spl_mcode.c", "stage0/spl_syscall.c", "stage0/spl_vm.c" -#define SPLC0_PART_SRCS \ - "stage1/spl_ast.c", "stage1/spl_lexer.c", "stage1/spl_dumptree.c", "stage1/spl_type.c", \ - "stage1/spl_sema.c", "stage1/spl_ir.c", "stage1/spl_ast2ir.c" - static const char *spl_cli_srcs[] = {"stage0/spl_cli.c", VM_SRCS}; -static const char *splc0_srcs[] = {"stage1/splc0.c", VM_SRCS, SPLC0_PART_SRCS}; static const char *test_srcs[] = {"stage0/test_spl_vm.c", VM_SRCS}; -static const char *spl_disasm_srcs[] = {"stage0/spl_disasm.c", VM_SRCS}; +static const char *splc0_srcs[] = { + "stage1/splc0.c", "stage0/spl_mcode.c", "stage1/spl_ast.c", "stage1/spl_lexer.c", + "stage1/spl_dumptree.c", "stage1/spl_type.c", "stage1/spl_sema.c", "stage1/spl_ir.c", + "stage1/spl_ast2ir.c", "stage1/spl_ir2vm.c", +}; typedef struct { const char *name; @@ -56,9 +32,8 @@ typedef struct { static Exe_Target exe_targets[] = { {"spl_cli", spl_cli_srcs, NOB_ARRAY_LEN(spl_cli_srcs)}, - {"splc0", splc0_srcs, NOB_ARRAY_LEN(splc0_srcs)}, {"test", test_srcs, NOB_ARRAY_LEN(test_srcs)}, - {"spl_disasm", spl_disasm_srcs, NOB_ARRAY_LEN(spl_disasm_srcs)}, + {"splc0", splc0_srcs, NOB_ARRAY_LEN(splc0_srcs)}, }; static const Exe_Target *find_exe_target(const char *name) { @@ -84,10 +59,6 @@ static const char *obj_path(const char *src) { return out; } -static const char *exe_path(const char *name) { - return nob_temp_sprintf(BUILD_FOLDER "%s" EXE_SUFFIX, name); -} - static bool sync_cflags_stamp(void) { Nob_String_View cflags = nob_sv_from_cstr(CFLAGS_STR); Nob_String_Builder old = {0}; @@ -135,7 +106,7 @@ static bool build_object(const char *src) { } static bool link_exe(const Exe_Target *target) { - const char *exe = exe_path(target->name); + const char *exe = nob_temp_sprintf(BUILD_FOLDER "%s", target->name); const char **objs = (const char **)nob_temp_alloc(sizeof(const char *) * target->srcs_count); for (size_t i = 0; i < target->srcs_count; ++i) { objs[i] = obj_path(target->srcs[i]); @@ -246,7 +217,7 @@ int main(int argc, char **argv) { if (!build_target(target_name)) return 1; Nob_Cmd cmd = {0}; - nob_cmd_append(&cmd, exe_path(target_name)); + nob_cmd_append(&cmd, nob_temp_sprintf(BUILD_FOLDER "%s", target_name)); while (argc > 0) { nob_cmd_append(&cmd, nob_shift(argv, argc)); } @@ -259,7 +230,7 @@ int main(int argc, char **argv) { if (!build_target("test")) return 1; Nob_Cmd cmd = {0}; - nob_cmd_append(&cmd, exe_path("test")); + nob_cmd_append(&cmd, BUILD_FOLDER "test"); return nob_cmd_run(&cmd) ? 0 : 1; } diff --git a/stage0/spl_cli.c b/stage0/spl_cli.c index 21655cb..cc8bf84 100644 --- a/stage0/spl_cli.c +++ b/stage0/spl_cli.c @@ -29,6 +29,7 @@ typedef struct { int debug; int debug_cli; int trace; + int disasm; const char *entry; const char *path; /* file.sir */ const char **args; /* spl 程序参数(file.sir 之后) */ @@ -39,6 +40,7 @@ static void usage(void) { fprintf(stderr, "Usage: spl_cli [options] [args...]\n" " -d, --debug stack-canary checks\n" " -g, --debug-cli interactive debugger (REPL)\n" + " --disasm disasm dump sir\n" " --entry entry function (default: main)\n" " --trace print every instruction\n" " -h, --help show help\n"); @@ -63,6 +65,8 @@ static int parse_args(int argc, const char **argv, cli_opts_t *o) { o->debug_cli = 1; } else if (strcmp(a, "--trace") == 0) { o->trace = 1; + } else if (strcmp(a, "--disasm") == 0) { + o->disasm = 1; } else if (strcmp(a, "--entry") == 0) { if (i + 1 >= argc) { fprintf(stderr, "spl_cli: --entry needs a name\n"); @@ -624,6 +628,11 @@ int main(int argc, const char **argv) { fprintf(stderr, "spl_cli: cannot load '%s'\n", o.path); return 1; } + + if (o.disasm) { + spl_prog_dump(&prog); + return 0; + } spl_syscall_register(&prog); spl_vm_t vm; diff --git a/stage0/spl_disasm.c b/stage0/spl_disasm.c deleted file mode 100644 index 58c2679..0000000 --- a/stage0/spl_disasm.c +++ /dev/null @@ -1,76 +0,0 @@ -/* spl_disasm.c - SIR bytecode disassembler - * - * Usage: spl_disasm - */ - -#include "spl_mcode.h" -#include - -int main(int argc, const char **argv) { - if (argc < 2) { - fprintf(stderr, "Usage: spl_disasm \n"); - return 1; - } - - spl_prog_t prog; - if (spl_prog_load_from_file(argv[1], &prog) != 0) { - fprintf(stderr, "spl_disasm: cannot load '%s'\n", argv[1]); - return 1; - } - - printf(";; SPL bytecode dump: %s\n", argv[1]); - printf(";; ninsns=%zu nfuncs=%zu nnatives=%zu nstrs=%zu\n\n", vec_size(prog.insns), - vec_size(prog.funcs), vec_size(prog.natives), vec_size(prog.strtab)); - - if (vec_size(prog.funcs) > 0) { - printf(";; --- functions ---\n"); - for (usize i = 0; i < vec_size(prog.funcs); i++) { - spl_vm_func_t *f = &vec_at(prog.funcs, i); - printf(" %s nargs=%zu ninsns=%zu addr=%zu\n", f->name ? f->name : "(anon)", f->nargs, - f->ninsns, f->address); - } - printf("\n"); - } - - if (vec_size(prog.natives) > 0) { - printf(";; --- natives ---\n"); - for (int i = 0; i < (int)vec_size(prog.natives); i++) { - spl_vm_native_t *n = &vec_at(prog.natives, i); - printf(" %s\n", n->name ? n->name : "(anon)"); - } - printf("\n"); - } - - if (vec_size(prog.strtab) > 0) { - printf(";; --- string table ---\n"); - for (int i = 0; i < (int)vec_size(prog.strtab); i++) { - printf(" %d: \"%s\"\n", i, vec_at(prog.strtab, i)); - } - printf("\n"); - } - - printf(";; --- instructions ---\n"); - for (usize i = 0; i < vec_size(prog.insns); i++) { - spl_vm_ins_t *ins = &vec_at(prog.insns, i); - printf("%4zd: %s", i, spl_vm_opcode_name((spl_vm_opcode_t)ins->opcode)); - if (ins->type != SPL_VOID) - printf(" %s", spl_vm_type_kind_name((spl_vm_kind_t)ins->type)); - printf(" %zd", ins->imm); - - /* annotate jumps / calls */ - if (ins->opcode == SPL_JMP || ins->opcode == SPL_BZ || ins->opcode == SPL_BNZ) { - spl_vm_val_t target = i + 1 + ins->imm; - printf(" ; -> %zu", target); - } else if (ins->opcode == SPL_CALL) { - printf(" ; nargs=%zu, from stack", ins->imm); - } else if (ins->opcode == SPL_CALLI) { - printf(" ; indirect call"); - } else if (ins->opcode == SPL_GADDR) { - printf(" ; gdata[%zu]", ins->imm); - } - printf("\n"); - } - - spl_prog_drop(&prog); - return 0; -} diff --git a/stage0/spl_mcode.c b/stage0/spl_mcode.c index 249d15d..e7cdddf 100644 --- a/stage0/spl_mcode.c +++ b/stage0/spl_mcode.c @@ -43,6 +43,61 @@ void spl_prog_drop(spl_prog_t *prog) { prog->debug = NULL; } +void spl_prog_dump(spl_prog_t *prog) { + printf(";; SPL bytecode dump: \n"); + printf(";; ninsns=%zu nfuncs=%zu nnatives=%zu nstrs=%zu\n\n", vec_size(prog->insns), + vec_size(prog->funcs), vec_size(prog->natives), vec_size(prog->strtab)); + + if (vec_size(prog->funcs) > 0) { + printf(";; --- functions ---\n"); + for (usize i = 0; i < vec_size(prog->funcs); i++) { + spl_vm_func_t *f = &vec_at(prog->funcs, i); + printf(" %s nargs=%zu ninsns=%zu addr=%zu\n", f->name ? f->name : "(anon)", f->nargs, + f->ninsns, f->address); + } + printf("\n"); + } + + if (vec_size(prog->natives) > 0) { + printf(";; --- natives ---\n"); + for (int i = 0; i < (int)vec_size(prog->natives); i++) { + spl_vm_native_t *n = &vec_at(prog->natives, i); + printf(" %s\n", n->name ? n->name : "(anon)"); + } + printf("\n"); + } + + if (vec_size(prog->strtab) > 0) { + printf(";; --- string table ---\n"); + for (int i = 0; i < (int)vec_size(prog->strtab); i++) { + printf(" %d: \"%s\"\n", i, vec_at(prog->strtab, i)); + } + printf("\n"); + } + + printf(";; --- instructions ---\n"); + for (usize i = 0; i < vec_size(prog->insns); i++) { + spl_vm_ins_t *ins = &vec_at(prog->insns, i); + printf("%4zd: %s", i, spl_vm_opcode_name((spl_vm_opcode_t)ins->opcode)); + if (ins->type != SPL_VOID) + printf(" %s", spl_vm_type_kind_name((spl_vm_kind_t)ins->type)); + printf(" %zd", ins->imm); + + /* annotate jumps / calls */ + if (ins->opcode == SPL_JMP || ins->opcode == SPL_BZ || ins->opcode == SPL_BNZ) { + spl_vm_val_t target = i + 1 + ins->imm; + printf(" ; -> %zu", target); + } else if (ins->opcode == SPL_CALL) { + printf(" ; nargs=%zu, from stack", ins->imm); + } else if (ins->opcode == SPL_CALLI) { + printf(" ; indirect call"); + } else if (ins->opcode == SPL_GADDR) { + printf(" ; gdata[%zu]", ins->imm); + } + printf("\n"); + } +} + /* ---- LE read/write helpers ---- */ static inline spl_vm_val_t rd64(const unsigned char **p) { diff --git a/stage0/spl_mcode.h b/stage0/spl_mcode.h index c5bbeab..7ea8938 100644 --- a/stage0/spl_mcode.h +++ b/stage0/spl_mcode.h @@ -199,6 +199,7 @@ typedef struct spl_prog { void spl_prog_init(spl_prog_t *prog); void spl_prog_drop(spl_prog_t *prog); +void spl_prog_dump(spl_prog_t *prog); int spl_prog_load_from_file(const char *fname, spl_prog_t *prog); int spl_prog_store_to_file(const char *fname, spl_prog_t *prog); diff --git a/stage1/spl_ast.c b/stage1/spl_ast.c index 43a10a5..4c22f22 100644 --- a/stage1/spl_ast.c +++ b/stage1/spl_ast.c @@ -80,7 +80,7 @@ static spl_ast_node_ref_t mk_bin(parser_t *p, const spl_tok_t *loc, spl_ast_node /* 前向声明 */ static spl_ast_node_ref_t parse_expr(parser_t *p); static spl_ast_node_ref_vec_t parse_expr_list(parser_t *p); -static spl_ast_node_ref_vec_t parse_block(parser_t *p); +static spl_ast_node_ref_t parse_block(parser_t *p); static spl_ast_node_ref_t parse_type_expr(parser_t *p); static spl_ast_node_ref_t parse_type_base(parser_t *p); static spl_ast_node_ref_t parse_statement(parser_t *p); @@ -352,8 +352,7 @@ static spl_ast_node_ref_t parse_fn_decl(parser_t *p, spl_ast_node_ref_vec_t attr advance(p); spl_ast_node_ref_t type_expr = 0; - spl_ast_node_ref_vec_t block; - vec_init(block); + spl_ast_node_ref_t block = 0; int has_body = 0; t = peek(p); @@ -525,20 +524,20 @@ static spl_ast_node_ref_t parse_container_declaration(parser_t *p) { // 语句 -static spl_ast_node_ref_vec_t parse_block(parser_t *p) { +static spl_ast_node_ref_t parse_block(parser_t *p) { spl_ast_node_ref_vec_t vec; vec_init(vec); const spl_tok_t *t = peek(p); if (t == NULL || t->type != TOK_L_BRACE) { SPL_FATAL(t, "expected '{'"); - return vec; + return 0; } advance(p); while (!p->failed) { t = peek(p); if (!t || t->type == TOK_EOF) { SPL_FATAL(t, "block missing '}'"); - break; + return 0; } if (t->type == TOK_R_BRACE) { advance(p); @@ -565,7 +564,9 @@ static spl_ast_node_ref_vec_t parse_block(parser_t *p) { SPL_FATAL(t, "unrecognized statement"); } } - return vec; + spl_ast_node_ref_t block_expr_ref = new_node(p, SPL_AST_BLOCK_EXPR, t); // FIXME t not here + node_at(p->ast, block_expr_ref)->primary_expr.block_expr = vec; + return block_expr_ref; } static spl_ast_node_ref_t parse_statement(parser_t *p) { @@ -668,15 +669,18 @@ static spl_ast_node_ref_t parse_if(parser_t *p) { spl_ast_node_ref_t expr = parse_expr(p); p->stop_agg--; - spl_ast_node_ref_vec_t if_block = parse_block(p); - spl_ast_node_ref_vec_t else_block; - vec_init(else_block); + spl_ast_node_ref_t if_block = parse_block(p); + spl_ast_node_ref_t else_block = 0; t = peek(p); if (t && t->type == KW_ELSE) { advance(p); t = peek(p); if (t && t->type == KW_IF) { - vec_push(else_block, parse_if(p)); + spl_ast_node_ref_vec_t elseif_block; + vec_init(elseif_block); + vec_push(elseif_block, parse_if(p)); + else_block = new_node(p, SPL_AST_BLOCK_EXPR, t); // FIXME t not here + node_at(p->ast, else_block)->primary_expr.block_expr = elseif_block; } else { else_block = parse_block(p); } @@ -709,7 +713,7 @@ static spl_ast_node_ref_t parse_while(parser_t *p) { p->stop_agg++; spl_ast_node_ref_t expr = parse_expr(p); p->stop_agg--; - spl_ast_node_ref_vec_t block = parse_block(p); + spl_ast_node_ref_t block = parse_block(p); spl_ast_node_ref_t s = new_node(p, SPL_AST_WHILE_STATEMENT, kw); node_at(p->ast, s)->while_statement.expr = expr; node_at(p->ast, s)->while_statement.while_block = block; @@ -720,7 +724,7 @@ static spl_ast_node_ref_t parse_loop(parser_t *p) { const spl_tok_t *kw = peek(p); Assert(kw && kw->type == KW_LOOP); advance(p); - spl_ast_node_ref_vec_t block = parse_block(p); + spl_ast_node_ref_t block = parse_block(p); spl_ast_node_ref_t s = new_node(p, SPL_AST_LOOP_STATEMENT, kw); node_at(p->ast, s)->loop_statement.loop_block = block; return s; @@ -768,7 +772,7 @@ static spl_ast_node_ref_t parse_for(parser_t *p) { advance(p); vec_push(node_at(p->ast, s)->for_statement.ident_vec, sdupn(t->lexeme, t->len)); } - spl_ast_node_ref_vec_t fblock = parse_block(p); + spl_ast_node_ref_t fblock = parse_block(p); node_at(p->ast, s)->for_statement.block = fblock; return s; } @@ -810,7 +814,10 @@ static spl_ast_node_ref_t parse_match(parser_t *p) { spl_ast_node_ref_t s = new_node(p, SPL_AST_MATCH_STATEMENT, kw); node_at(p->ast, s)->match_statement.expr = expr; node_at(p->ast, s)->match_statement.paced_exprs = paced_vec; - node_at(p->ast, s)->match_statement.match_block = stmt_vec; + + spl_ast_node_ref_t stmt_block = new_node(p, SPL_AST_BLOCK_EXPR, t); // FIXME t not here + node_at(p->ast, stmt_block)->primary_expr.block_expr = stmt_vec; + node_at(p->ast, s)->match_statement.match_block = stmt_block; return s; } @@ -893,9 +900,7 @@ static int parse_match_arm(parser_t *p, spl_ast_node_ref_vec_t *paced_vec, return 0; } - spl_ast_node_ref_vec_t bvec = parse_block(p); - spl_ast_node_ref_t body = new_node(p, SPL_AST_BLOCK_EXPR, t); - node_at(p->ast, body)->primary_expr.block_expr = bvec; + spl_ast_node_ref_t body = parse_block(p); for (usize i = 0; i < modes.size; i++) { vec_push(*paced_vec, modes.data[i]); vec_push(*block_vec, body); @@ -949,8 +954,9 @@ static spl_ast_node_ref_t parse_defer(parser_t *p) { vec_init(vec); const spl_tok_t *t = peek(p); + // FIXME parse maybe error if (t && t->type == TOK_L_BRACE) { - vec = parse_block(p); + vec_push(vec, parse_block(p)); } else if (t && can_start_statement(t->type)) { spl_ast_node_ref_t st = parse_statement(p); if (st) @@ -992,7 +998,7 @@ static spl_ast_node_kind_t assign_op_of(spl_tok_type_t t) { case TOK_ASSIGN_L_SH: return SPL_AST_ASSIGN_LSHIFT_EXPR; case TOK_ASSIGN_R_SH: - return SPL_AST_ASSIGN_USHIFT_EXPR; + return SPL_AST_ASSIGN_RSHIFT_EXPR; default: return SPL_AST_COUNT; } @@ -1473,9 +1479,7 @@ static spl_ast_node_ref_t parse_primary(parser_t *p) { case TOK_L_BRACKET: return parse_array_literal(p); case TOK_L_BRACE: { - spl_ast_node_ref_vec_t bvec = parse_block(p); - spl_ast_node_ref_t pr = new_node(p, SPL_AST_BLOCK_EXPR, t); - node_at(p->ast, pr)->primary_expr.block_expr = bvec; + spl_ast_node_ref_t pr = parse_block(p); return pr; } default: @@ -1827,7 +1831,7 @@ void spl_ast_valid(spl_ast_t *ast) { } typedef VEC(char) dump_stack_t; -static void dump_node(spl_ast_t *ast, spl_ast_node_ref_t node_ref, dump_stack_t *stack, int last); +static void dump_node(spl_ast_t *ast, spl_ast_node_ref_t node_ref, dump_stack_t *stack, bool last); void spl_ast_dump(spl_ast_t *ast, spl_ast_node_ref_t node) { if (!ast || !node || node >= ast->node_buckets.size) @@ -1843,7 +1847,7 @@ void spl_ast_dump(spl_ast_t *ast, spl_ast_node_ref_t node) { vec_for(_vec, _i) { dump_node(_ast, vec_at(_vec, _i), _stack, _i + 1 == vec_size(_vec)); } \ } while (0) -static void dump_node(spl_ast_t *ast, spl_ast_node_ref_t node_ref, dump_stack_t *stack, int last) { +static void dump_node(spl_ast_t *ast, spl_ast_node_ref_t node_ref, dump_stack_t *stack, bool last) { spl_ast_node_t *node = &vec_at(ast->node_buckets, node_ref); for (usize i = 0; i < vec_size(*stack); i++) @@ -1869,36 +1873,36 @@ static void dump_node(spl_ast_t *ast, spl_ast_node_ref_t node_ref, dump_stack_t dump_vec(ast, node->fn_decl.attr_list, stack); dump_vec(ast, node->fn_decl.param_list, stack); if (node->fn_decl.type_expr) { - last = node->kind == SPL_AST_FN_DECL ? 1 : 0; + last = node->kind == SPL_AST_FN_DECL ? true : false; dump_node(ast, node->fn_decl.type_expr, stack, last); } - dump_vec(ast, node->fn_decl.block, stack); + dump_node(ast, node->fn_decl.block, stack, true); break; case SPL_AST_TYPE_DECL: if (node->type_decl.type_expr) - dump_node(ast, node->type_decl.type_expr, stack, 1); + dump_node(ast, node->type_decl.type_expr, stack, true); break; case SPL_AST_VAR_DECL: case SPL_AST_CONST_DECL: dump_vec(ast, node->var_const_decl.attr_list, stack); if (node->var_const_decl.type_expr) - dump_node(ast, node->var_const_decl.type_expr, stack, 0); + dump_node(ast, node->var_const_decl.type_expr, stack, false); if (node->var_const_decl.expr) - dump_node(ast, node->var_const_decl.expr, stack, 1); + dump_node(ast, node->var_const_decl.expr, stack, true); break; case SPL_AST_MEMBER_DECL: dump_vec(ast, node->member_decl.attr_list, stack); if (node->member_decl.type_expr) - dump_node(ast, node->member_decl.type_expr, stack, 1); + dump_node(ast, node->member_decl.type_expr, stack, true); break; case SPL_AST_PARAM_DECL: dump_vec(ast, node->param_decl.attr_list, stack); if (node->param_decl.type_expr) - dump_node(ast, node->param_decl.type_expr, stack, 1); + dump_node(ast, node->param_decl.type_expr, stack, true); break; case SPL_AST_ATTR_ITEM: @@ -1907,31 +1911,31 @@ static void dump_node(spl_ast_t *ast, spl_ast_node_ref_t node_ref, dump_stack_t case SPL_AST_ARGG_INIT_ITEM: if (node->aggregate_init_item.expr) - dump_node(ast, node->aggregate_init_item.expr, stack, 1); + dump_node(ast, node->aggregate_init_item.expr, stack, true); break; case SPL_AST_IF_STATEMENT: if (node->if_statement.expr) - dump_node(ast, node->if_statement.expr, stack, 0); - dump_vec(ast, node->if_statement.if_block, stack); - dump_vec(ast, node->if_statement.else_block, stack); + dump_node(ast, node->if_statement.expr, stack, false); + dump_node(ast, node->if_statement.if_block, stack, false); + dump_node(ast, node->if_statement.else_block, stack, true); break; case SPL_AST_IFVAR_STATEMENT: if (node->ifvar_statement.packed_expr) - dump_node(ast, node->ifvar_statement.packed_expr, stack, 0); - dump_vec(ast, node->ifvar_statement.if_block, stack); - dump_vec(ast, node->ifvar_statement.else_block, stack); + dump_node(ast, node->ifvar_statement.packed_expr, stack, false); + dump_node(ast, node->ifvar_statement.if_block, stack, false); + dump_node(ast, node->ifvar_statement.else_block, stack, true); break; case SPL_AST_WHILE_STATEMENT: if (node->while_statement.expr) - dump_node(ast, node->while_statement.expr, stack, 0); - dump_vec(ast, node->while_statement.while_block, stack); + dump_node(ast, node->while_statement.expr, stack, false); + dump_node(ast, node->while_statement.while_block, stack, true); break; case SPL_AST_LOOP_STATEMENT: - dump_vec(ast, node->loop_statement.loop_block, stack); + dump_node(ast, node->loop_statement.loop_block, stack, true); break; case SPL_AST_FOR_STATEMENT: @@ -1943,19 +1947,19 @@ static void dump_node(spl_ast_t *ast, spl_ast_node_ref_t node_ref, dump_stack_t i + 1 == vec_size(node->for_statement.ident_vec) ? "`-" : "|-", node->for_statement.ident_vec.data[i]); } - dump_vec(ast, node->for_statement.block, stack); + dump_node(ast, node->for_statement.block, stack, true); break; case SPL_AST_MATCH_STATEMENT: if (node->match_statement.expr) - dump_node(ast, node->match_statement.expr, stack, 0); + dump_node(ast, node->match_statement.expr, stack, false); dump_vec(ast, node->match_statement.paced_exprs, stack); - dump_vec(ast, node->match_statement.match_block, stack); + dump_node(ast, node->match_statement.match_block, stack, true); break; case SPL_AST_RET_STATEMENT: if (node->ret_statement.expr) - dump_node(ast, node->ret_statement.expr, stack, 1); + dump_node(ast, node->ret_statement.expr, stack, true); break; case SPL_AST_DEFER_STATEMENT: @@ -1964,7 +1968,7 @@ static void dump_node(spl_ast_t *ast, spl_ast_node_ref_t node_ref, dump_stack_t case SPL_AST_PACKED_EXPR: if (node->packed_expr.expr) - dump_node(ast, node->packed_expr.expr, stack, 1); + dump_node(ast, node->packed_expr.expr, stack, true); break; case SPL_AST_ASSIGN_EXPR: @@ -1977,7 +1981,7 @@ static void dump_node(spl_ast_t *ast, spl_ast_node_ref_t node_ref, dump_stack_t case SPL_AST_ASSIGN_OR_EXPR: case SPL_AST_ASSIGN_XOR_EXPR: case SPL_AST_ASSIGN_LSHIFT_EXPR: - case SPL_AST_ASSIGN_USHIFT_EXPR: + case SPL_AST_ASSIGN_RSHIFT_EXPR: case SPL_AST_BOOL_OR_EXPR: case SPL_AST_BOOL_AND_EXPR: case SPL_AST_BIT_OR_EXPR: @@ -1998,9 +2002,9 @@ static void dump_node(spl_ast_t *ast, spl_ast_node_ref_t node_ref, dump_stack_t case SPL_AST_DIV_EXPR: case SPL_AST_MOD_EXPR: if (node->op_expr.left) - dump_node(ast, node->op_expr.left, stack, 0); + dump_node(ast, node->op_expr.left, stack, false); if (node->op_expr.right) - dump_node(ast, node->op_expr.right, stack, 1); + dump_node(ast, node->op_expr.right, stack, true); break; case SPL_AST_MINUS_EXPR: @@ -2008,42 +2012,42 @@ static void dump_node(spl_ast_t *ast, spl_ast_node_ref_t node_ref, dump_stack_t case SPL_AST_BIT_NOT_EXPR: case SPL_AST_ADDRESS_EXPR: if (node->prefix_expr.postfix_expr) - dump_node(ast, node->prefix_expr.postfix_expr, stack, 1); + dump_node(ast, node->prefix_expr.postfix_expr, stack, true); break; case SPL_AST_CALL_EXPR: if (node->postfix_expr.primary_expr) - dump_node(ast, node->postfix_expr.primary_expr, stack, 0); + dump_node(ast, node->postfix_expr.primary_expr, stack, false); dump_vec(ast, node->postfix_expr.call_expr, stack); break; case SPL_AST_FIELD_EXPR: case SPL_AST_DEREF_EXPR: if (node->postfix_expr.primary_expr) - dump_node(ast, node->postfix_expr.primary_expr, stack, 1); + dump_node(ast, node->postfix_expr.primary_expr, stack, true); break; case SPL_AST_INDEX_EXPR: if (node->postfix_expr.primary_expr) - dump_node(ast, node->postfix_expr.primary_expr, stack, 0); + dump_node(ast, node->postfix_expr.primary_expr, stack, false); if (node->postfix_expr.index_expr) - dump_node(ast, node->postfix_expr.index_expr, stack, 1); + dump_node(ast, node->postfix_expr.index_expr, stack, true); break; case SPL_AST_SLICE_EXPR: if (node->postfix_expr.primary_expr) - dump_node(ast, node->postfix_expr.primary_expr, stack, 0); + dump_node(ast, node->postfix_expr.primary_expr, stack, false); if (node->postfix_expr.slice_expr.begin) - dump_node(ast, node->postfix_expr.slice_expr.begin, stack, 0); + dump_node(ast, node->postfix_expr.slice_expr.begin, stack, false); if (node->postfix_expr.slice_expr.end) - dump_node(ast, node->postfix_expr.slice_expr.end, stack, 1); + dump_node(ast, node->postfix_expr.slice_expr.end, stack, true); break; case SPL_AST_AS_EXPR: if (node->postfix_expr.primary_expr) - dump_node(ast, node->postfix_expr.primary_expr, stack, 0); + dump_node(ast, node->postfix_expr.primary_expr, stack, false); if (node->postfix_expr.type_expr) - dump_node(ast, node->postfix_expr.type_expr, stack, 1); + dump_node(ast, node->postfix_expr.type_expr, stack, true); break; case SPL_AST_EXPR_INTEGER_LIT: @@ -2063,12 +2067,12 @@ static void dump_node(spl_ast_t *ast, spl_ast_node_ref_t node_ref, dump_stack_t case SPL_AST_EXPR_EXPR: if (node->primary_expr.expr) - dump_node(ast, node->primary_expr.expr, stack, 1); + dump_node(ast, node->primary_expr.expr, stack, true); break; case SPL_AST_ARRAY_LIT: if (node->primary_expr.array_lit_expr.type_expr) - dump_node(ast, node->primary_expr.array_lit_expr.type_expr, stack, 0); + dump_node(ast, node->primary_expr.array_lit_expr.type_expr, stack, false); dump_vec(ast, node->primary_expr.array_lit_expr.expr_list, stack); break; @@ -2084,7 +2088,7 @@ static void dump_node(spl_ast_t *ast, spl_ast_node_ref_t node_ref, dump_stack_t dump_vec(ast, node->type_expr.attr_list, stack); dump_vec(ast, node->type_expr.fn_type.param_list, stack); if (node->type_expr.fn_type.type_expr) - dump_node(ast, node->type_expr.fn_type.type_expr, stack, 1); + dump_node(ast, node->type_expr.fn_type.type_expr, stack, true); break; case SPL_AST_BASE_TYPE_PATH: @@ -2094,21 +2098,21 @@ static void dump_node(spl_ast_t *ast, spl_ast_node_ref_t node_ref, dump_stack_t case SPL_AST_TYPE_POINTER: dump_vec(ast, node->type_expr.attr_list, stack); if (node->type_expr.pointer_type.pointee) - dump_node(ast, node->type_expr.pointer_type.pointee, stack, 1); + dump_node(ast, node->type_expr.pointer_type.pointee, stack, true); break; case SPL_AST_TYPE_SLICE: dump_vec(ast, node->type_expr.attr_list, stack); if (node->type_expr.slice_type.element) - dump_node(ast, node->type_expr.slice_type.element, stack, 1); + dump_node(ast, node->type_expr.slice_type.element, stack, true); break; case SPL_AST_TYPE_ARRAY: dump_vec(ast, node->type_expr.attr_list, stack); if (node->type_expr.array_type.element) - dump_node(ast, node->type_expr.array_type.element, stack, 0); + dump_node(ast, node->type_expr.array_type.element, stack, false); if (node->type_expr.array_type.size) - dump_node(ast, node->type_expr.array_type.size, stack, 1); + dump_node(ast, node->type_expr.array_type.size, stack, true); break; case SPL_AST_TYPE_STRUCT: diff --git a/stage1/spl_ast.h b/stage1/spl_ast.h index f4f5985..d48f4d8 100644 --- a/stage1/spl_ast.h +++ b/stage1/spl_ast.h @@ -46,7 +46,7 @@ X(SPL_AST_ASSIGN_OR_EXPR, V0, assign_or_expr) \ X(SPL_AST_ASSIGN_XOR_EXPR, V0, assign_xor_expr) \ X(SPL_AST_ASSIGN_LSHIFT_EXPR, V0, assign_lshift_expr) \ - X(SPL_AST_ASSIGN_USHIFT_EXPR, V0, assign_ushift_expr) \ + X(SPL_AST_ASSIGN_RSHIFT_EXPR, V0, assign_rshift_expr) \ X(SPL_AST_BOOL_OR_EXPR, V0, bool_or_expr) \ X(SPL_AST_BOOL_AND_EXPR, V0, bool_and_expr) \ X(SPL_AST_BIT_OR_EXPR, V0, bit_or_expr) \ @@ -152,14 +152,14 @@ struct spl_ast_node { } attr_item; struct { - spl_ast_node_ref_vec_t attr_list; /* attr_item */ + spl_ast_node_ref_vec_t attr_list; /* attr_item */ const char *name; spl_ast_node_ref_vec_t param_list; /* param_decl */ - spl_ast_node_ref_t type_expr; /* ret type expr */ - spl_ast_node_ref_vec_t block; /* 语句/尾表达式 */ + spl_ast_node_ref_t type_expr; /* ret type expr */ + spl_ast_node_ref_t block; /* block_expr */ } fn_decl; struct { - spl_ast_node_ref_vec_t attr_list; /* attr_item */ + spl_ast_node_ref_vec_t attr_list; /* attr_item */ const char *name; spl_ast_node_ref_t type_expr; } param_decl; @@ -181,33 +181,34 @@ struct spl_ast_node { spl_ast_node_ref_t expr; } var_const_decl; - /* 语句数据:kind 决定解释哪个成员 */ + /* statement */ + struct { spl_ast_node_ref_t expr; - spl_ast_node_ref_vec_t if_block; /* 语句 */ - spl_ast_node_ref_vec_t else_block; /* 语句 */ + spl_ast_node_ref_t if_block; /* block_expr */ + spl_ast_node_ref_t else_block; /* block_expr */ } if_statement; struct { spl_ast_node_ref_t packed_expr; - spl_ast_node_ref_vec_t if_block; /* 语句 */ - spl_ast_node_ref_vec_t else_block; /* 语句 */ + spl_ast_node_ref_t if_block; /* block_expr */ + spl_ast_node_ref_t else_block; /* block_expr */ } ifvar_statement; struct { spl_ast_node_ref_t expr; - spl_ast_node_ref_vec_t while_block; /* 语句 */ + spl_ast_node_ref_t while_block; /* block_expr */ } while_statement; struct { - spl_ast_node_ref_vec_t loop_block; /* 语句 */ + spl_ast_node_ref_t loop_block; /* block_expr */ } loop_statement; struct { spl_ast_node_ref_vec_t expr_vec; VEC(char *) ident_vec; - spl_ast_node_ref_vec_t block; /* 语句 */ + spl_ast_node_ref_t block; /* block_expr */ } for_statement; struct { spl_ast_node_ref_t expr; spl_ast_node_ref_vec_t paced_exprs; /* packed_expr */ - spl_ast_node_ref_vec_t match_block; /* 语句 */ + spl_ast_node_ref_t match_block; /* block_expr */ } match_statement; struct { spl_ast_node_ref_t expr; diff --git a/stage1/spl_ast2ir.c b/stage1/spl_ast2ir.c index b338f10..6d77c4a 100644 --- a/stage1/spl_ast2ir.c +++ b/stage1/spl_ast2ir.c @@ -10,8 +10,259 @@ static spl_type_id_t tid_from_def(const spl_sema_t *sema, spl_def_id_t def) { return d ? d->type_id : 0; } -static spl_ir_node_ref_t transit(spl_ir_builder_t *ir, const spl_sema_t *sema, - spl_ast_node_ref_t ref) { +static spl_ir_node_ref_t transit(spl_ast2ir_t *ctx, spl_ast_node_ref_t ref); + +static spl_ir_node_ref_t transit_op(spl_ir_builder_t *ir, spl_ast_node_kind_t kind, + spl_type_id_t tid, spl_ir_node_ref_t lref, + spl_ir_node_ref_t rref) { + spl_ir_node_ref_t ret = 0; + switch (kind) { + case SPL_AST_CMP_EQ_EXPR: { + ret = spl_ir_builder_cmp_eq(ir, tid, lref, rref); + } break; + case SPL_AST_CMP_NE_EXPR: { + ret = spl_ir_builder_cmp_ne(ir, tid, lref, rref); + } break; + case SPL_AST_CMP_LE_EXPR: { + ret = spl_ir_builder_cmp_le(ir, tid, lref, rref); + } break; + case SPL_AST_CMP_GE_EXPR: { + ret = spl_ir_builder_cmp_ge(ir, tid, lref, rref); + } break; + case SPL_AST_CMP_LT_EXPR: { + ret = spl_ir_builder_cmp_lt(ir, tid, lref, rref); + } break; + case SPL_AST_CMP_GT_EXPR: { + ret = spl_ir_builder_cmp_gt(ir, tid, lref, rref); + } break; + case SPL_AST_ASSIGN_EXPR: { + ret = rref; + } break; + case SPL_AST_ASSIGN_LSHIFT_EXPR: + case SPL_AST_LSHIFT_EXPR: { + ret = spl_ir_builder_arith_shl(ir, tid, lref, rref); + } break; + case SPL_AST_ASSIGN_RSHIFT_EXPR: + case SPL_AST_RSHIFT_EXPR: { + ret = spl_ir_builder_arith_shr(ir, tid, lref, rref); + } break; + case SPL_AST_ASSIGN_ADD_EXPR: + case SPL_AST_ADD_EXPR: { + ret = spl_ir_builder_arith_add(ir, tid, lref, rref); + } break; + case SPL_AST_SUB_EXPR: + case SPL_AST_ASSIGN_SUB_EXPR: { + ret = spl_ir_builder_arith_sub(ir, tid, lref, rref); + } break; + case SPL_AST_ASSIGN_MUL_EXPR: + case SPL_AST_MUL_EXPR: { + ret = spl_ir_builder_arith_mul(ir, tid, lref, rref); + } break; + case SPL_AST_DIV_EXPR: + case SPL_AST_ASSIGN_DIV_EXPR: { + ret = spl_ir_builder_arith_div(ir, tid, lref, rref); + } break; + case SPL_AST_ASSIGN_MOD_EXPR: + case SPL_AST_MOD_EXPR: { + ret = spl_ir_builder_arith_rem(ir, tid, lref, rref); + } break; + case SPL_AST_ASSIGN_AND_EXPR: + case SPL_AST_BIT_AND_EXPR: { + ret = spl_ir_builder_arith_and(ir, tid, lref, rref); + } break; + case SPL_AST_ASSIGN_OR_EXPR: + case SPL_AST_BIT_OR_EXPR: { + ret = spl_ir_builder_arith_or(ir, tid, lref, rref); + } break; + case SPL_AST_ASSIGN_XOR_EXPR: + case SPL_AST_BIT_XOR_EXPR: { + ret = spl_ir_builder_arith_xor(ir, tid, lref, rref); + } break; + default: + UNREACHABLE(); + break; + } + return ret; +} + +static spl_ir_node_ref_t transit_expr(spl_ast2ir_t *ctx, spl_ast_node_ref_t ref, bool is_lval) { + spl_ir_builder_t *ir = ctx->ir; + const spl_sema_t *sema = ctx->sema; + if (ref == 0) + return 0; + Assert(sema != NULL); + spl_ast_node_t *n = spl_ast_node(sema->ast, ref); + spl_ir_node_ref_t ret = 0; + Assert(n != NULL); + + switch (n->kind) { + case SPL_AST_PACKED_EXPR: { + TODO(); + } break; + case SPL_AST_ASSIGN_EXPR: { + spl_ir_node_ref_t rval = transit_expr(ctx, n->op_expr.right, false); + spl_ir_node_ref_t lval = transit_expr(ctx, n->op_expr.left, true); + ret = spl_ir_builder_mem_store(ir, n->resolved_type_id, lval, rval); + } break; + case SPL_AST_ASSIGN_ADD_EXPR: + case SPL_AST_ASSIGN_SUB_EXPR: + case SPL_AST_ASSIGN_MUL_EXPR: + case SPL_AST_ASSIGN_DIV_EXPR: + case SPL_AST_ASSIGN_MOD_EXPR: + case SPL_AST_ASSIGN_AND_EXPR: + case SPL_AST_ASSIGN_OR_EXPR: + case SPL_AST_ASSIGN_XOR_EXPR: + case SPL_AST_ASSIGN_LSHIFT_EXPR: + case SPL_AST_ASSIGN_RSHIFT_EXPR: { + spl_ir_node_ref_t rval = transit_expr(ctx, n->op_expr.right, false); + spl_ir_node_ref_t lval = transit_expr(ctx, n->op_expr.left, false); + rval = transit_op(ir, n->kind, n->resolved_type_id, lval, rval); + lval = transit_expr(ctx, n->op_expr.left, true); + ret = spl_ir_builder_mem_store(ir, n->resolved_type_id, lval, rval); + } break; + case SPL_AST_CMP_EQ_EXPR: + case SPL_AST_CMP_NE_EXPR: + case SPL_AST_CMP_LE_EXPR: + case SPL_AST_CMP_GE_EXPR: + case SPL_AST_CMP_LT_EXPR: + case SPL_AST_CMP_GT_EXPR: { + spl_ir_node_ref_t rval = transit_expr(ctx, n->op_expr.right, false); + spl_ir_node_ref_t lval = transit_expr(ctx, n->op_expr.left, false); + ret = transit_op(ir, n->kind, n->resolved_type_id, lval, rval); + } break; + case SPL_AST_RANGE_EXPR: { + TODO(); + } break; + case SPL_AST_BOOL_OR_EXPR: + case SPL_AST_BOOL_AND_EXPR: { + TODO(); + } break; + case SPL_AST_BIT_OR_EXPR: + case SPL_AST_BIT_XOR_EXPR: + case SPL_AST_BIT_AND_EXPR: + case SPL_AST_LSHIFT_EXPR: + case SPL_AST_RSHIFT_EXPR: + case SPL_AST_ADD_EXPR: + case SPL_AST_SUB_EXPR: + case SPL_AST_MUL_EXPR: + case SPL_AST_DIV_EXPR: + case SPL_AST_MOD_EXPR: { + spl_ir_node_ref_t rval = transit_expr(ctx, n->op_expr.right, false); + spl_ir_node_ref_t lval = transit_expr(ctx, n->op_expr.left, false); + // TODO assert type is bool + ret = transit_op(ir, n->kind, n->resolved_type_id, lval, rval); + } break; + case SPL_AST_MINUS_EXPR: { + ret = transit_expr(ctx, n->prefix_expr.postfix_expr, false); + ret = spl_ir_builder_arith_neg(ir, n->resolved_type_id, ret); + } break; + case SPL_AST_NOT_EXPR: { + ret = transit_expr(ctx, n->prefix_expr.postfix_expr, false); + ret = spl_ir_builder_arith_not(ir, n->resolved_type_id, ret); + TODO(); // return bool type + } break; + case SPL_AST_BIT_NOT_EXPR: { + ret = transit_expr(ctx, n->prefix_expr.postfix_expr, false); + ret = spl_ir_builder_arith_not(ir, n->resolved_type_id, ret); + } break; + case SPL_AST_ADDRESS_EXPR: { + TODO(); + } break; + case SPL_AST_CALL_EXPR: { + spl_ast_node_t *fn_sym = spl_ast_node(ctx->sema->ast, n->postfix_expr.primary_expr); + Assert(fn_sym != NULL); + spl_def_node_t *dn = spl_def_node(sema->type, fn_sym->resolved_def_id); + Assert(dn != NULL); + spl_ir_node_ref_t ir_ref = 0; + if (!map_get(ctx->def2ir_map, fn_sym->resolved_def_id, &ir_ref)) { + Panic("can't resolved ir map in def2ir"); + } + Assert(ir_ref != 0); + + VEC(spl_ir_node_ref_t) params; + vec_init(params); + vec_for(n->postfix_expr.call_expr, i) { + spl_ast_node_ref_t param_node = vec_at(n->postfix_expr.call_expr, i); + spl_ir_node_ref_t ref = transit_expr(ctx, param_node, false); + vec_push(params, ref); + } + spl_ir_node_ref_t call_ref = spl_ir_builder_control_call(ir, n->resolved_type_id, ir_ref); + vec_for(params, i) { spl_ir_builder_control_call_param(ir, call_ref, vec_at(params, i)); } + vec_free(params); + ret = call_ref; + } break; + case SPL_AST_FIELD_EXPR: + case SPL_AST_DEREF_EXPR: + case SPL_AST_INDEX_EXPR: + case SPL_AST_SLICE_EXPR: + case SPL_AST_AS_EXPR: + TODO(); + break; + case SPL_AST_EXPR_INTEGER_LIT: { + ret = spl_ir_builder_type_const_int(ir, n->resolved_type_id, n->primary_expr.integer_expr); + break; + } + case SPL_AST_EXPR_FLOAT_LIT: + case SPL_AST_EXPR_CHAR_LIT: + case SPL_AST_EXPR_STRING_LIT: { + TODO(); + } break; + case SPL_AST_EXPR_TRUE: { + return spl_ir_builder_type_const_bool( + ir, spl_type_builder_simple(sema->type, SPL_TYPE_BOOL), true); + } break; + case SPL_AST_EXPR_FALSE: { + return spl_ir_builder_type_const_bool( + ir, spl_type_builder_simple(sema->type, SPL_TYPE_BOOL), false); + } + case SPL_AST_EXPR_NULL: { + return spl_ir_builder_type_const_bool(ir, n->resolved_type_id, 0); + } break; + case SPL_AST_EXPR_UNDEFINED: + return 0; + case SPL_AST_EXPR_IDENT: { + spl_def_node_t *dn = spl_def_node(sema->type, n->resolved_def_id); + Assert(dn != NULL); + spl_ir_node_ref_t ir_ref = 0; + if (!map_get(ctx->def2ir_map, n->resolved_def_id, &ir_ref)) { + Panic("can't resolved ir map in def2ir"); + } + Assert(ir_ref != 0); + if (is_lval) { + return ir_ref; + } else { + return spl_ir_builder_mem_load(ir, dn->type_id, ir_ref); + } + } break; + case SPL_AST_ARGGREGATE_INIT: { + vec_for(n->primary_expr.aggregate_init.expr, i) { + transit_expr(ctx, vec_at(n->primary_expr.aggregate_init.expr, i), false); + } + } break; + case SPL_AST_EXPR_EXPR: { + transit_expr(ctx, n->primary_expr.expr, is_lval); + } break; + case SPL_AST_ARRAY_LIT: { + TODO(); + } break; + case SPL_AST_BUILTIN_EXPR: { + TODO(); + } break; + case SPL_AST_BLOCK_EXPR: { + vec_for(n->primary_expr.block_expr, i) { + transit(ctx, vec_at(n->primary_expr.block_expr, i)); + } + } break; + default: + UNREACHABLE(); + break; + } + return ret; +} + +static spl_ir_node_ref_t transit(spl_ast2ir_t *ctx, spl_ast_node_ref_t ref) { + spl_ir_builder_t *ir = ctx->ir; + const spl_sema_t *sema = ctx->sema; if (ref == 0) return 0; Assert(sema != NULL); @@ -24,7 +275,7 @@ static spl_ir_node_ref_t transit(spl_ir_builder_t *ir, const spl_sema_t *sema, UNREACHABLE(); break; case SPL_AST_CONTAINER_MEMBERS: { - vec_for(n->container_members, i) { transit(ir, sema, vec_at(n->container_members, i)); } + vec_for(n->container_members, i) { transit(ctx, vec_at(n->container_members, i)); } } break; case SPL_AST_FN_DECL: TODO(); @@ -34,26 +285,43 @@ static spl_ir_node_ref_t transit(spl_ir_builder_t *ir, const spl_sema_t *sema, spl_type_node_t *fn_type = spl_type_node(sema->type, tid); Assert(fn_type && fn_type->kind == SPL_TYPE_FN); // n->fn_decl.attr_list; TODO @extern(vm) using extern attribute - spl_ir_builder_fn_begin(ir, n->fn_decl.name, tid, (spl_ir_attr_t){0} /*TODO*/); - + spl_ir_func_ref_t fn_ref = + spl_ir_builder_fn_begin(ir, n->fn_decl.name, tid, (spl_ir_attr_t){0} /*TODO*/); + Assert(fn_ref != 0); spl_ir_builder_block_begin(ir); - vec_for(n->fn_decl.block, i) { transit(ir, sema, vec_at(n->fn_decl.block, i)); } + + map_put(ctx->def2ir_map, n->resolved_def_id, fn_ref); + vec_for(n->fn_decl.param_list, i) { + spl_ast_node_ref_t nref = vec_at(n->fn_decl.param_list, i); + spl_ast_node_t *n = spl_ast_node(sema->ast, nref); + spl_type_id_t tid = tid_from_def(sema, n->resolved_def_id); + spl_ir_node_ref_t idx_ref = spl_ir_const_comptime_int(ir, sema, i); + spl_ir_node_ref_t var_ref = spl_ir_builder_control_param(ir, tid, idx_ref); + map_put(ctx->def2ir_map, n->resolved_def_id, var_ref); + } + + transit(ctx, n->fn_decl.block); if (!ir->terminated) { + // FIXME spl_ir_builder_control_ret(ir, n->fn_decl.type_expr, 0); } spl_ir_builder_block_end(ir); spl_ir_builder_fn_end(ir); } break; - case SPL_AST_TYPE_DECL: - TODO(); - break; + case SPL_AST_TYPE_DECL: { + transit(ctx, n->type_decl.type_expr); + } break; case SPL_AST_VAR_DECL: { spl_type_id_t tid = tid_from_def(sema, n->resolved_def_id); spl_ir_node_ref_t var_ref = spl_ir_builder_mem_alloca(ir, tid, spl_ir_const_comptime_int(ir, sema, 1)); + map_put(ctx->def2ir_map, n->resolved_def_id, var_ref); if (n->var_const_decl.expr) { - spl_ir_builder_mem_store(ir, tid, var_ref, transit(ir, sema, n->var_const_decl.expr)); + spl_ir_node_ref_t expr_ref = transit_expr(ctx, n->var_const_decl.expr, false); + if (expr_ref != 0) { // 0 means undefined + spl_ir_builder_mem_store(ir, tid, var_ref, expr_ref); + } } } break; case SPL_AST_CONST_DECL: { @@ -64,31 +332,74 @@ static spl_ir_node_ref_t transit(spl_ir_builder_t *ir, const spl_sema_t *sema, break; case SPL_AST__COMPTIME_STMT: case SPL_AST__DIRECTIVE_BLOCK: - case SPL_AST_PARAM_DECL: - break; + case SPL_AST_PARAM_DECL: { + UNREACHABLE(); + } break; case SPL_AST_ATTR_ITEM: case SPL_AST_ARGG_INIT_ITEM: { TODO(); } break; case SPL_AST_IF_STATEMENT: { - spl_ir_node_ref_t ref = transit(ir, sema, n->if_statement.expr); + spl_ir_node_ref_t ref = transit_expr(ctx, n->if_statement.expr, false); ref = spl_ir_builder_control_br(ir, ref); spl_ir_builder_block_end(ir); + usize true_block = spl_ir_builder_block_begin(ir); + transit_expr(ctx, n->if_statement.if_block, false); + usize true_ref = spl_ir_builder_control_jmp(ir); + spl_ir_builder_block_end(ir); usize false_block = spl_ir_builder_block_begin(ir); + transit_expr(ctx, n->if_statement.else_block, false); + usize false_ref = spl_ir_builder_control_jmp(ir); + spl_ir_builder_block_end(ir); + + usize end_block = spl_ir_builder_block_begin(ir); + spl_ir_builder_control_jmp_fixup(ir, true_ref, end_block); + spl_ir_builder_control_jmp_fixup(ir, false_ref, end_block); spl_ir_builder_control_br_fixup(ir, ref, true_block, false_block); } break; - case SPL_AST_IFVAR_STATEMENT: - case SPL_AST_WHILE_STATEMENT: - case SPL_AST_LOOP_STATEMENT: + case SPL_AST_IFVAR_STATEMENT: { + TODO(); + } break; + case SPL_AST_WHILE_STATEMENT: { + spl_ir_node_ref_t end_ref = spl_ir_builder_control_jmp(ir); + spl_ir_builder_block_end(ir); + + usize cond_block = spl_ir_builder_block_begin(ir); + spl_ir_node_ref_t cond_expr_ref = transit_expr(ctx, n->while_statement.expr, false); + spl_ir_node_ref_t cond_ref = spl_ir_builder_control_br(ir, cond_expr_ref); + spl_ir_builder_block_end(ir); + + usize true_block = spl_ir_builder_block_begin(ir); + transit_expr(ctx, n->while_statement.while_block, false); + usize true_ref = spl_ir_builder_control_jmp(ir); + spl_ir_builder_block_end(ir); + + usize end_block = spl_ir_builder_block_begin(ir); + spl_ir_builder_control_jmp_fixup(ir, true_ref, cond_block); + spl_ir_builder_control_br_fixup(ir, cond_ref, true_block, end_block); + } break; + case SPL_AST_LOOP_STATEMENT: { + usize end_ref = spl_ir_builder_control_jmp(ir); + spl_ir_builder_block_end(ir); + + usize loop_block = spl_ir_builder_block_begin(ir); + spl_ir_node_ref_t loop_expr_ref = transit_expr(ctx, n->loop_statement.loop_block, false); + usize loop_ref = spl_ir_builder_control_jmp(ir); + spl_ir_builder_block_end(ir); + + usize end_block = spl_ir_builder_block_begin(ir); + spl_ir_builder_control_jmp_fixup(ir, end_ref, loop_block); + spl_ir_builder_control_jmp_fixup(ir, loop_ref, loop_block); + } break; case SPL_AST_FOR_STATEMENT: case SPL_AST_MATCH_STATEMENT: TODO(); break; case SPL_AST_RET_STATEMENT: { if (n->ret_statement.expr) { - ret = transit(ir, sema, n->ret_statement.expr); + ret = transit(ctx, n->ret_statement.expr); } ret = spl_ir_builder_control_ret(ir, n->resolved_type_id, ret); } break; @@ -99,6 +410,8 @@ static spl_ir_node_ref_t transit(spl_ir_builder_t *ir, const spl_sema_t *sema, case SPL_AST_CATCH_STATEMENT: case SPL_AST_ERRDEFER_STATEMEMT: case SPL_AST_EXPR_STATEMENT: + TODO(); + break; case SPL_AST_PACKED_EXPR: case SPL_AST_ASSIGN_EXPR: case SPL_AST_ASSIGN_ADD_EXPR: @@ -110,7 +423,7 @@ static spl_ir_node_ref_t transit(spl_ir_builder_t *ir, const spl_sema_t *sema, case SPL_AST_ASSIGN_OR_EXPR: case SPL_AST_ASSIGN_XOR_EXPR: case SPL_AST_ASSIGN_LSHIFT_EXPR: - case SPL_AST_ASSIGN_USHIFT_EXPR: + case SPL_AST_ASSIGN_RSHIFT_EXPR: case SPL_AST_BOOL_OR_EXPR: case SPL_AST_BOOL_AND_EXPR: case SPL_AST_BIT_OR_EXPR: @@ -140,55 +453,24 @@ static spl_ir_node_ref_t transit(spl_ir_builder_t *ir, const spl_sema_t *sema, case SPL_AST_INDEX_EXPR: case SPL_AST_SLICE_EXPR: case SPL_AST_AS_EXPR: - TODO(); - break; - case SPL_AST_EXPR_INTEGER_LIT: { - ret = spl_ir_builder_type_const_int(ir, n->resolved_type_id, n->primary_expr.integer_expr); - break; - } + case SPL_AST_EXPR_INTEGER_LIT: case SPL_AST_EXPR_FLOAT_LIT: case SPL_AST_EXPR_CHAR_LIT: - case SPL_AST_EXPR_STRING_LIT: { - TODO(); - } break; - case SPL_AST_EXPR_TRUE: { - return spl_ir_builder_type_const_bool( - ir, spl_type_builder_simple(sema->type, SPL_TYPE_BOOL), true); - } break; - case SPL_AST_EXPR_FALSE: { - return spl_ir_builder_type_const_bool( - ir, spl_type_builder_simple(sema->type, SPL_TYPE_BOOL), false); - } - case SPL_AST_EXPR_NULL: { - return spl_ir_builder_type_const_bool(ir, n->resolved_type_id, 0); - } break; + case SPL_AST_EXPR_STRING_LIT: + case SPL_AST_EXPR_TRUE: + case SPL_AST_EXPR_FALSE: + case SPL_AST_EXPR_NULL: case SPL_AST_EXPR_UNDEFINED: - break; - case SPL_AST_EXPR_IDENT: { - } break; - case SPL_AST_ARGGREGATE_INIT: { - vec_for(n->primary_expr.aggregate_init.expr, i) { - transit(ir, sema, vec_at(n->primary_expr.aggregate_init.expr, i)); - } - } break; - case SPL_AST_EXPR_EXPR: { - transit(ir, sema, n->primary_expr.expr); - } break; - case SPL_AST_ARRAY_LIT: { - TODO(); - } break; - case SPL_AST_BUILTIN_EXPR: { - TODO(); - } break; + case SPL_AST_EXPR_IDENT: + case SPL_AST_ARGGREGATE_INIT: + case SPL_AST_EXPR_EXPR: + case SPL_AST_ARRAY_LIT: + case SPL_AST_BUILTIN_EXPR: case SPL_AST_BLOCK_EXPR: { - vec_for(n->primary_expr.block_expr, i) { - transit(ir, sema, vec_at(n->primary_expr.block_expr, i)); - } - } break; + return transit_expr(ctx, ref, false); + } case SPL_AST_BASE_TYPE_FN: case SPL_AST_BASE_TYPE_PATH: - TODO(); - break; case SPL_AST_TYPE_POINTER: case SPL_AST_TYPE_ARRAY: case SPL_AST_TYPE_SLICE: @@ -213,20 +495,24 @@ static spl_ir_node_ref_t transit(spl_ir_builder_t *ir, const spl_sema_t *sema, case SPL_AST_TYPE__F64: case SPL_AST_TYPE_ANY: case SPL_AST_TYPE_IDENT: - break; - case SPL_AST_COUNT: + case SPL_AST_COUNT: { UNREACHABLE(); break; } + } return ret; } -void spl_ast2ir_init(spl_ast2ir_t *ast2ir, spl_ir_builder_t *ir, const spl_sema_t *sema) { - ast2ir->sema = sema; - ast2ir->ir = ir; - ast2ir->err_count = 0; +static usize hash_int(spl_def_id_t k) { return MAP_HASH_INT(k); } +static int cmp_int(spl_def_id_t k1, spl_def_id_t k2) { return MAP_CMP_INT(k1, k2); } + +void spl_ast2ir_init(spl_ast2ir_t *ctx, spl_ir_builder_t *ir, const spl_sema_t *sema) { + ctx->sema = sema; + ctx->ir = ir; + map_init(ctx->def2ir_map, hash_int, cmp_int); + ctx->err_count = 0; } -void spl_ast2ir_drop(spl_ast2ir_t *ast2ir) {} +void spl_ast2ir_drop(spl_ast2ir_t *ctx) { map_free(ctx->def2ir_map); } -void spl_ast2ir_run(spl_ast2ir_t *ctx) { transit(ctx->ir, ctx->sema, ctx->sema->ast->root); } +void spl_ast2ir_run(spl_ast2ir_t *ctx) { transit(ctx, ctx->sema->ast->root); } diff --git a/stage1/spl_ast2ir.h b/stage1/spl_ast2ir.h index dafcfd0..84542a9 100644 --- a/stage1/spl_ast2ir.h +++ b/stage1/spl_ast2ir.h @@ -4,9 +4,11 @@ #include "spl_ir.h" #include "spl_sema.h" +typedef MAP(spl_def_id_t, spl_ir_node_ref_t) spl_def2ir_map_t; typedef struct { const spl_sema_t *sema; spl_ir_builder_t *ir; + spl_def2ir_map_t def2ir_map; int err_count; } spl_ast2ir_t; diff --git a/stage1/spl_ir.c b/stage1/spl_ir.c index 3683292..327826d 100644 --- a/stage1/spl_ir.c +++ b/stage1/spl_ir.c @@ -113,12 +113,15 @@ static void ir_dump_node(const spl_type_t *ty, spl_ir_node_t *n) { case SPL_IR_ARITH_XOR: case SPL_IR_ARITH_SHL: case SPL_IR_ARITH_SHR: + ir_dump_type(ty, n->arith.tid); + ir_dump_ref(n->arith.left); + ir_dump_ref(n->arith.right); + break; case SPL_IR_ARITH_NEG: case SPL_IR_ARITH_ABS: case SPL_IR_ARITH_NOT: ir_dump_type(ty, n->arith.tid); ir_dump_ref(n->arith.left); - ir_dump_ref(n->arith.right); break; case SPL_IR_CMP_EQ: case SPL_IR_CMP_NE: @@ -272,7 +275,7 @@ void spl_ir_dump(spl_ir_t *ir, const spl_type_t *ty) { if (i == 0) continue; spl_ir_func_t *func = &vec_at(ir->funcs, i); - printf("func %s", func->name ? func->name : "?"); + printf("func %s %%%zu", func->name ? func->name : "?", i); printf(" tid="); spl_type_pure_dump((spl_type_t *)ty, func->fn_tid); printf("\n"); @@ -739,9 +742,9 @@ spl_ir_node_ref_t spl_ir_builder_control_call(spl_ir_builder_t *b, spl_type_id_t return ref; } -void spl_ir_builder_control_call_param(spl_ir_builder_t *b, spl_ir_node_ref_t node, +void spl_ir_builder_control_call_param(spl_ir_builder_t *b, spl_ir_node_ref_t call_node, spl_ir_node_ref_t arg) { - spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, node); + spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, call_node); Assert(n != NULL); vec_push(n->control_call.params, arg); } diff --git a/stage1/spl_ir.h b/stage1/spl_ir.h index 073dfc4..8b3f413 100644 --- a/stage1/spl_ir.h +++ b/stage1/spl_ir.h @@ -409,7 +409,7 @@ void spl_ir_builder_control_jmp_fixup(spl_ir_builder_t *b, spl_ir_node_ref_t ref usize target_block); spl_ir_node_ref_t spl_ir_builder_control_call(spl_ir_builder_t *b, spl_type_id_t tid, spl_ir_node_ref_t func); -void spl_ir_builder_control_call_param(spl_ir_builder_t *b, spl_ir_node_ref_t node, +void spl_ir_builder_control_call_param(spl_ir_builder_t *b, spl_ir_node_ref_t call_node, spl_ir_node_ref_t arg); spl_ir_node_ref_t spl_ir_builder_control_param(spl_ir_builder_t *b, spl_type_id_t tid, spl_ir_node_ref_t idx); diff --git a/stage1/spl_ir2vm.c b/stage1/spl_ir2vm.c index c749b67..b315ba8 100644 --- a/stage1/spl_ir2vm.c +++ b/stage1/spl_ir2vm.c @@ -1,1426 +1,75 @@ -/* spl_ir2vm.c IR SIR (spl_prog_t) 降级 - * - * ABI 约定spl_ir2vm.h。要点: - * - 布局(C ABI)唯一来源在此文件 * - 每个产生IR 节点 = 一vreg(locals 区按类型对齐的字节块* - * - 纯值节点(type.const / gdata.addr / mem.alloca / sizeof 折叠 / param * 不落 vreg,引用处重算 - * * - 聚合= 字节块,整体搬运NCALL vm_memcpy * - 聚合返回sret(隐*T 参数,最后一个) * - - * 两遍发射:先发指令记label→地址,回JMP/BZ/BNZ;全部函 * 生成后回const_fnref 的函数地址 */ - #include "spl_ir2vm.h" -/* VM 枚举 spl_type_t stage1 spl_type_t(struct)重名:局部重命名 */ -#define spl_type_t spl_vm_tag_t -#include "../stage0/spl_mcode.h" -#undef spl_type_t - -#include "../stage0/include/core_vec.h" - -#include -#include -#include - -static spl_type_node_t *tn(const spl_type_t *ty, spl_type_id_t tid) { - return spl_type_node((spl_type_t *)ty, tid); -} - -static spl_type_id_t under(const spl_type_t *ty, spl_type_id_t tid) { - spl_type_node_t *t = tn(ty, tid); - return (t && t->kind == SPL_TYPE_ID) ? t->type_id : tid; -} - -static usize align_up(usize v, usize a) { return (v + a - 1) & ~(a - 1); } - -static int is_agg(const spl_type_t *ty, spl_type_id_t tid) { - spl_type_node_t *t = tn(ty, under(ty, tid)); - return t && - (t->kind == SPL_TYPE_STRUCT || t->kind == SPL_TYPE_UNION || t->kind == SPL_TYPE_ENUM || - t->kind == SPL_TYPE_SLICE || t->kind == SPL_TYPE_RANGE || t->kind == SPL_TYPE_ARRAY); -} - -static usize type_align(const spl_type_t *ty, spl_type_id_t tid) { - spl_type_node_t *t = tn(ty, under(ty, tid)); - if (!t) - return 1; - switch (t->kind) { - case SPL_TYPE_VOID: - case SPL_TYPE_BOOL: - return 1; - case SPL_TYPE_INT: - return t->int_type.bits / 8; - case SPL_TYPE_FLOAT: - return t->float_type.bits / 8; - case SPL_TYPE_PTR: - case SPL_TYPE_FN: - case SPL_TYPE_SLICE: - case SPL_TYPE_RANGE: - case SPL_TYPE_ENUM: - return sizeof(usize); - case SPL_TYPE_ARRAY: - return type_align(ty, t->array_type.element); - case SPL_TYPE_STRUCT: - case SPL_TYPE_UNION: { - usize a = 1; - for (usize i = 0; i < t->agg_field_types.size; i++) { - usize fa = type_align(ty, t->agg_field_types.data[i]); - if (fa > a) - a = fa; - } - return a; - } - default: - return 1; - } -} - -static usize type_size(const spl_type_t *ty, spl_type_id_t tid) { - spl_type_node_t *t = tn(ty, under(ty, tid)); - if (!t) - return 0; - switch (t->kind) { - case SPL_TYPE_VOID: - return 0; - case SPL_TYPE_BOOL: - case SPL_TYPE_INT: - return t->kind == SPL_TYPE_BOOL ? 1 : t->int_type.bits / 8; - case SPL_TYPE_FLOAT: - return t->float_type.bits / 8; - case SPL_TYPE_PTR: - case SPL_TYPE_FN: - return sizeof(usize); - case SPL_TYPE_SLICE: - case SPL_TYPE_RANGE: - return sizeof(usize) * 2; - case SPL_TYPE_ARRAY: - return t->array_type.len * type_size(ty, t->array_type.element); - case SPL_TYPE_STRUCT: { - usize sz = 0; - for (usize i = 0; i < t->agg_field_types.size; i++) { - usize fa = type_align(ty, t->agg_field_types.data[i]); - sz = align_up(sz, fa); - sz += type_size(ty, t->agg_field_types.data[i]); - } - return align_up(sz, type_align(ty, tid)); /* 尾填*/ - } - case SPL_TYPE_UNION: { - usize sz = 0; - for (usize i = 0; i < t->agg_field_types.size; i++) { - usize fs = type_size(ty, t->agg_field_types.data[i]); - if (fs > sz) - sz = fs; - } - return align_up(sz, type_align(ty, tid)); - } - case SPL_TYPE_ENUM: { - usize payload = 0; - spl_type_id_t self = under(ty, tid); - for (usize i = 0; i < t->enum_type.variants.size; i++) { - spl_type_id_t v = under(ty, t->enum_type.variants.data[i]); - if (v == self) - continue; - usize vs = type_size(ty, v); - if (vs > payload) - payload = vs; - } - return align_up(sizeof(usize) + payload, sizeof(usize)); - } - default: - return 0; - } -} - -/* 聚合字段字节偏移(struct 顺序对齐;union 0;enum tag=0/payload=8 * slice/range = idx*8*/ -static usize field_offset(const spl_type_t *ty, spl_type_id_t agg_tid, isize idx) { - spl_type_node_t *t = tn(ty, under(ty, agg_tid)); - if (!t) - return 0; - switch (t->kind) { - case SPL_TYPE_SLICE: - case SPL_TYPE_RANGE: - return (usize)idx * sizeof(usize); - case SPL_TYPE_ARRAY: - return (usize)idx * type_size(ty, t->array_type.element); - case SPL_TYPE_ENUM: - return idx <= 0 ? 0 : sizeof(usize); - case SPL_TYPE_UNION: - return 0; - case SPL_TYPE_STRUCT: { - if (idx < 0 || (usize)idx >= t->agg_field_types.size) - return 0; - usize off = 0; - for (isize i = 0; i < idx; i++) { - usize fa = type_align(ty, t->agg_field_types.data[i]); - off = align_up(off, fa); - off += type_size(ty, t->agg_field_types.data[i]); - } - return align_up(off, type_align(ty, t->agg_field_types.data[idx])); - } - default: - return 0; - } -} - -/* 聚合字段类型(enum idx0=tag usize;idx1=payload 首个非自身变体) */ -static spl_type_id_t field_type(const spl_type_t *ty, spl_type_id_t agg_tid, isize idx) { - spl_type_node_t *t = tn(ty, under(ty, agg_tid)); - if (!t) - return 0; - switch (t->kind) { - case SPL_TYPE_SLICE: - if (idx == 0) - return spl_type_ptr((spl_type_t *)ty, t->slice_element); - if (idx == 1) - return spl_type_int((spl_type_t *)ty, sizeof(usize) * 8, 0); - return 0; - case SPL_TYPE_RANGE: - return t->range_element; - case SPL_TYPE_ARRAY: - return t->array_type.element; - case SPL_TYPE_ENUM: - if (idx <= 0) - return spl_type_int((spl_type_t *)ty, sizeof(usize) * 8, 0); - { - spl_type_id_t self = under(ty, agg_tid); - for (usize i = 0; i < t->enum_type.variants.size; i++) { - spl_type_id_t v = under(ty, t->enum_type.variants.data[i]); - if (v != self) - return v; - } - } - return spl_type_int((spl_type_t *)ty, sizeof(usize) * 8, 0); - default: - if (idx < 0 || (usize)idx >= t->agg_field_types.size) - return 0; - return t->agg_field_types.data[idx]; - } -} - -/* IR 类型 SIR 标量 tag;聚合返SPL_VOID */ -static spl_vm_tag_t vm_tag(const spl_type_t *ty, spl_type_id_t tid) { - spl_type_node_t *t = tn(ty, under(ty, tid)); - if (!t) - return SPL_VOID; - switch (t->kind) { - case SPL_TYPE_VOID: - return SPL_VOID; - case SPL_TYPE_BOOL: - return SPL_BOOL; - case SPL_TYPE_INT: - switch (t->int_type.bits / 8) { - case 1: - return t->int_type.is_signed ? SPL_I8 : SPL_U8; - case 2: - return t->int_type.is_signed ? SPL_I16 : SPL_U16; - case 4: - return t->int_type.is_signed ? SPL_I32 : SPL_U32; - default: - return t->int_type.is_signed ? SPL_I64 : SPL_U64; - } - case SPL_TYPE_FLOAT: - return t->float_type.bits == 32 ? SPL_F32 : SPL_F64; - case SPL_TYPE_PTR: - case SPL_TYPE_FN: - return SPL_PTR; - default: - return SPL_VOID; /* 聚合 */ - } -} - -/* 算术/比较 tag:bool I32(VM 的算术宏BOOL case,值已零扩展等价) */ -static spl_vm_tag_t arith_tag(const spl_type_t *ty, spl_type_id_t tid) { - spl_type_node_t *t = tn(ty, under(ty, tid)); - if (t && t->kind == SPL_TYPE_BOOL) - return SPL_I32; - return vm_tag(ty, tid); -} - -static int is_void(const spl_type_t *ty, spl_type_id_t tid) { - spl_type_node_t *t = tn(ty, under(ty, tid)); - return t && t->kind == SPL_TYPE_VOID; -} - -/* ================================================================ - * 发射上下 * ================================================================ */ - -typedef struct { - usize insn_idx; - isize target_node; /* >=0: IR label node0: 绝对地址 */ - isize abs_addr; - int is_call_pad; /* 0 = 跳转 = const_fnref PUSH 占位(imm=函数地址*/ - spl_ir_func_ref_t fn; -} fix_t; -typedef VEC(fix_t) fix_vec_t; - -typedef struct { - spl_ir2vm_t *pub; - spl_prog_t prog; - int err; - VEC(isize) func_addr; /* IR func id SIR 地址;native = -1 */ - VEC(isize) native_idx; /* IR func id native 表下标;native = -1 */ - VEC(usize) cstr_gdata; /* cstr 去重:字符串 prog.gdata 下标 */ - VEC(const char *) cstr_list; - fix_vec_t fnfixes; /* const_fnref PUSH 占位(函数地址回填*/ -} ctx_t; - -typedef struct { - ctx_t *c; - spl_ir_func_ref_t fid; - spl_ir_func_t *f; - spl_type_id_t ret_tid; - int sret; - usize sret_off; /* sret 参数在参数区字节偏移 */ - usize param_bytes; - usize *param_off; /* 每参数偏*/ - usize nparams; - usize *vreg_off; /* node ref locals 偏移 */ - usize nvreg; - isize *label_addr; /* node ref 指令地址1 未定 */ - usize nlabel; - usize locals_bytes; - usize temp_off; /* mem.set 计数器槽 */ - usize insn_base; - fix_vec_t fixes; -} fctx_t; - -static void diag(ctx_t *c, spl_ir_func_ref_t fid, spl_ir_node_ref_t ref, const char *msg) { - c->err++; - const spl_ir_t *ir = c->pub->ir; - const char *fname = - (fid && fid < ir->funcs.size && ir->funcs.data[fid].name) ? ir->funcs.data[fid].name : "?"; - LOG_ERROR("ir2vm: func @%s node %zu: %s", fname, ref, msg); -} - -/* ---- 指令发射 ---- */ - -static usize add_insn(fctx_t *fc, uint8_t opcode, uint8_t type, spl_val_t imm) { - return (usize)spl_prog_add_instr(&fc->c->prog, opcode, type, imm) - 1; -} - -static void emit_push(fctx_t *fc, spl_val_t imm) { add_insn(fc, SPL_PUSH, SPL_VOID, imm); } - -static void emit_load_insn(fctx_t *fc, spl_vm_tag_t tag) { add_insn(fc, SPL_LOAD, tag, 0); } - -static void emit_store_insn(fctx_t *fc, spl_vm_tag_t tag) { add_insn(fc, SPL_STORE, tag, 0); } - -static void emit_laddr(fctx_t *fc, usize byte_off) { add_insn(fc, SPL_LADDR, SPL_VOID, byte_off); } - -static void emit_gaddr(fctx_t *fc, usize idx) { add_insn(fc, SPL_GADDR, SPL_VOID, idx); } - -static void emit_arith(fctx_t *fc, spl_opcode_t op, spl_vm_tag_t tag) { add_insn(fc, op, tag, 0); } - -static void emit_jmp_fix(fctx_t *fc, isize target_node, isize abs_addr) { - usize idx = add_insn(fc, SPL_JMP, SPL_VOID, 0); - fix_t fx = {idx, target_node, abs_addr, 0, 0}; - vec_push(fc->fixes, fx); -} - -static void emit_bnz_fix(fctx_t *fc, isize target_node, isize abs_addr) { - usize idx = add_insn(fc, SPL_BNZ, SPL_VOID, 0); - fix_t fx = {idx, target_node, abs_addr, 0, 0}; - vec_push(fc->fixes, fx); -} - -/* ---- native 辅助:vm_memcpy ---- */ - -static isize native_index(ctx_t *c, const char *name) { - for (usize i = 0; i < c->prog.natives.size; i++) - if (c->prog.natives.data[i].name && strcmp(c->prog.natives.data[i].name, name) == 0) - return (isize)i; - return -1; -} - -static void emit_memcpy(fctx_t *fc, usize size) { - isize ni = native_index(fc->c, "vm_memcpy"); - if (ni < 0) - diag(fc->c, fc->fid, 0, "vm_memcpy native not registered"); - emit_push(fc, (spl_val_t)size); - emit_push(fc, (spl_val_t)ni); - add_insn(fc, SPL_NCALL, SPL_VOID, 3); -} - -/* ================================================================ - * 节点信息 - * ================================================================ */ - -static spl_ir_node_t *n_at(spl_ir_func_t *f, spl_ir_node_ref_t ref) { - if (!ref || ref >= f->nodes.size) - return NULL; - return &f->nodes.data[ref]; -} - -static spl_type_id_t fn_ret(const spl_type_t *ty, spl_type_id_t fn_tid) { - spl_type_node_t *t = tn(ty, under(ty, fn_tid)); - return (t && t->kind == SPL_TYPE_FN) ? t->fn_type.ret : 0; -} - -static spl_type_id_t node_type(const spl_ir_t *ir, const spl_type_t *ty, spl_ir_func_t *f, - spl_ir_node_ref_t ref) { - spl_ir_node_t *n = n_at(f, ref); - if (!n) - return 0; - switch (n->kind) { +static int emit_instr(spl_ir2vm_t *ctx, spl_ir_func_t *fn, spl_ir_node_t *node) { + int pos = 0; + switch (node->kind) { case SPL_IR_TYPE_CONST: - return n->type_const.tid; - case SPL_IR_ARITH_ADD: - case SPL_IR_ARITH_SUB: - case SPL_IR_ARITH_MUL: - case SPL_IR_ARITH_DIV: - case SPL_IR_ARITH_REM: - case SPL_IR_ARITH_NEG: - case SPL_IR_ARITH_ABS: - case SPL_IR_ARITH_AND: - case SPL_IR_ARITH_OR: - case SPL_IR_ARITH_XOR: - case SPL_IR_ARITH_SHL: - case SPL_IR_ARITH_SHR: - case SPL_IR_ARITH_NOT: - return n->arith.tid; - case SPL_IR_CMP_EQ: - case SPL_IR_CMP_NE: - case SPL_IR_CMP_LT: - case SPL_IR_CMP_LE: - case SPL_IR_CMP_GT: - case SPL_IR_CMP_GE: - return spl_type_bool((spl_type_t *)ty); - case SPL_IR_CAST_TRUNC: - case SPL_IR_CAST_ZEXT: - case SPL_IR_CAST_SEXT: - case SPL_IR_CAST_FEXT: - case SPL_IR_CAST_FTRUNC: - case SPL_IR_CAST_BITCAST: - case SPL_IR_CAST_PTR2INT: - case SPL_IR_CAST_INT2PTR: - case SPL_IR_CAST_BOOL2INT: - case SPL_IR_CASE_INT2FLOAT: - case SPL_IR_CASE_FLOAT2INT: - return n->cast.to_tid; - case SPL_IR_MEM_ALLOCA: - return spl_type_ptr((spl_type_t *)ty, n->mem_alloc.tid); - case SPL_IR_MEM_LOAD: - return n->mem_load.tid; - case SPL_IR_MEM_OFFSET: - return spl_type_ptr((spl_type_t *)ty, n->mem_offset.tid); - case SPL_IR_MEM_FIELD_PTR: - return spl_type_ptr((spl_type_t *)ty, field_type(ty, n->mem_field_ptr.tid, - (isize)n->mem_field_ptr.field_idx)); - case SPL_IR_MEM_GLOBAL_ALLOC: { - spl_type_id_t gt = 0; - if (ir && n->mem_global_alloc.const_node < ir->gdata.size) - gt = ir->gdata.data[n->mem_global_alloc.const_node].type_const.tid; - return spl_type_ptr((spl_type_t *)ty, gt); - } - case SPL_IR_AGG_CONSTRUCT: - return n->agg_construct.tid; - case SPL_IR_AGG_EXTRACT: - return n->agg_extract.field_tid; - case SPL_IR_AGG_INSERT: - return n->agg_insert.tid; - case SPL_IR_CONTROL_SELECT: - return n->control_select.tid; - case SPL_IR_CONTROL_CALL: - return fn_ret(ty, n->control_call.tid); - case SPL_IR_CONTROL_PARAM: - return n->control_param.tid; + break; case SPL_IR_CONTROL_RET: - return n->control_ret.tid; - case SPL_IR_TYPE_BITSIZEOF: - case SPL_IR_TYPE_SIZEOF: - case SPL_IR_TYPE_ALIGNOF: - case SPL_IR_TYPE_OFFSETOF: - case SPL_IR_TYPE_FIELD_COUNT: - return spl_type_int((spl_type_t *)ty, sizeof(usize) * 8, 0); - default: - return 0; - } -} - -/* 是否需vreg 槽(布局用)。const/gaddr/param/sizeof 折叠不落 vreg - * alloca 的槽即缓冲区本体,仍需分配*/ -static int needs_vreg_slot(spl_ir_func_t *f, spl_ir_node_ref_t ref) { - spl_ir_node_t *n = n_at(f, ref); - if (!n) - return 0; - switch (n->kind) { - case SPL_IR_TYPE_CONST: - case SPL_IR_MEM_GLOBAL_ALLOC: - case SPL_IR_CONTROL_PARAM: - case SPL_IR_TYPE_BITSIZEOF: - case SPL_IR_TYPE_SIZEOF: - case SPL_IR_TYPE_ALIGNOF: - case SPL_IR_TYPE_OFFSETOF: - case SPL_IR_TYPE_FIELD_COUNT: - return 0; - default: - return 1; - } -} - -/* ================================================================ - * 发射(emit_value / emit_node - * ================================================================ */ - -static int produces_value(spl_ir_kind_t k) { - switch (k) { - case SPL_IR_MEM_STORE: - case SPL_IR_MEM_COPY: - case SPL_IR_MEM_SET: - case SPL_IR_MEM_FENCE: - case SPL_IR_CONTROL_BR: - case SPL_IR_CONTROL_JMP: - case SPL_IR_CONTROL_RET: - case SPL_IR_CONTROL_UNREACHABLE: - case SPL_IR_CONTROL_TRAP: - case SPL_IR_DBG_BREAKPOINT: - case SPL_IR_DBG_DECLARE: - return 0; - default: - return 1; - } -} - -static spl_opcode_t arith_op(spl_ir_kind_t k, int is_signed); -static int is_signed_type(const spl_type_t *ty, spl_type_id_t tid); -static void emit_value(fctx_t *fc, spl_ir_node_ref_t ref); - -/* 整数字宽(bool = 1;其余取 int bits*/ -static usize int_bits(const spl_type_t *ty, spl_type_id_t tid) { - spl_type_node_t *t = tn(ty, under(ty, tid)); - if (!t) - return 0; - if (t->kind == SPL_TYPE_BOOL) - return 1; - if (t->kind == SPL_TYPE_INT) - return t->int_type.bits; - return 0; -} - -static void emit_store_vreg(fctx_t *fc, spl_ir_node_ref_t ref) { - const spl_type_t *ty = fc->c->pub->type; - spl_type_id_t tid = node_type(fc->c->pub->ir, ty, fc->f, ref); - if (!tid) - return; - if (is_agg(ty, tid)) { - /* 栈顶 = 聚合值地址;memcpy(栈顶 vreg(ref)) */ - emit_laddr(fc, fc->param_bytes + fc->vreg_off[ref]); - add_insn(fc, SPL_SWAP, SPL_VOID, 0); - emit_memcpy(fc, type_size(ty, tid)); - } else { - emit_laddr(fc, fc->param_bytes + fc->vreg_off[ref]); - add_insn(fc, SPL_SWAP, SPL_VOID, 0); - emit_store_insn(fc, vm_tag(ty, tid)); - } -} - -static void emit_const_push(fctx_t *fc, spl_ir_node_t *n) { - const spl_type_t *ty = fc->c->pub->type; - spl_type_id_t tid = n->type_const.tid; - spl_type_node_t *t = tn(ty, under(ty, tid)); - if (!t) { - diag(fc->c, fc->fid, 0, "bad const type"); - return; - } - switch (t->kind) { - case SPL_TYPE_INT: - emit_push(fc, (spl_val_t)(usize)n->type_const.int_lit); - return; - case SPL_TYPE_BOOL: - emit_push(fc, n->type_const.int_lit ? 1 : 0); - return; - case SPL_TYPE_FLOAT: { - double d = n->type_const.float_lit; - if (t->float_type.bits == 32) { - float f = (float)d; - spl_val_t b = 0; - memcpy(&b, &f, 4); - emit_push(fc, b); - } else { - spl_val_t b = 0; - memcpy(&b, &d, 8); - emit_push(fc, b); - } - return; - } - case SPL_TYPE_PTR: - if (n->type_const.cstr_lit) { - /* 字符串常量:gdata 条目地址 */ - isize gi = -1; - for (usize i = 0; i < fc->c->cstr_list.size; i++) - if (strcmp(fc->c->cstr_list.data[i], n->type_const.cstr_lit) == 0) { - gi = (isize)fc->c->cstr_gdata.data[i]; - break; - } - if (gi < 0) - diag(fc->c, fc->fid, 0, "string const not registered"); - emit_gaddr(fc, (usize)gi); - } else { - emit_push(fc, 0); - } - return; - case SPL_TYPE_FN: { - spl_ir_func_ref_t fn = n->type_const.fn; - if (fn && fn < fc->c->func_addr.size && fc->c->native_idx.data[fn] >= 0) { - diag(fc->c, fc->fid, 0, "native function used as value"); - emit_push(fc, 0); - return; - } - usize idx = add_insn(fc, SPL_PUSH, SPL_VOID, 0); - fix_t fx = {idx, -1, 0, 1, fn}; - vec_push(fc->c->fnfixes, fx); - return; - } - case SPL_TYPE_SLICE: - case SPL_TYPE_RANGE: - case SPL_TYPE_ARRAY: - case SPL_TYPE_STRUCT: - case SPL_TYPE_UNION: - case SPL_TYPE_ENUM: - diag(fc->c, fc->fid, 0, "aggregate const not supported"); - emit_push(fc, 0); - return; - default: - diag(fc->c, fc->fid, 0, "bad const kind"); - emit_push(fc, 0); - return; - } -} - -static void emit_value(fctx_t *fc, spl_ir_node_ref_t ref) { - const spl_ir_t *ir = fc->c->pub->ir; - const spl_type_t *ty = fc->c->pub->type; - spl_ir_node_t *n = n_at(fc->f, ref); - if (!n) { - diag(fc->c, fc->fid, ref, "bad operand"); - emit_push(fc, 0); - return; - } - switch (n->kind) { - case SPL_IR_TYPE_CONST: - emit_const_push(fc, n); - return; - case SPL_IR_MEM_GLOBAL_ALLOC: { - const spl_ir_t *ir2 = fc->c->pub->ir; - usize idx = n->mem_global_alloc.const_node; - if (idx >= ir2->gdata.size) { - diag(fc->c, fc->fid, ref, "unknown global symbol"); - emit_push(fc, 0); - } else { - emit_gaddr(fc, idx); - } - return; - } - case SPL_IR_MEM_ALLOCA: - emit_laddr(fc, fc->param_bytes + fc->vreg_off[ref]); - return; - case SPL_IR_CONTROL_PARAM: { - if (is_agg(ty, n->control_param.tid)) { - /* 聚合值参数:prologue 已 memcpy 到 param vreg,取 vreg 地址 */ - emit_laddr(fc, fc->param_bytes + fc->vreg_off[ref]); - } else { - usize po = fc->param_off ? fc->param_off[n->control_param.idx] : 0; - emit_laddr(fc, po); - emit_load_insn(fc, vm_tag(ty, n->control_param.tid)); - } - return; - } - case SPL_IR_TYPE_BITSIZEOF: - emit_push(fc, type_size(ty, n->bitsizeof.tid) * 8); - return; - case SPL_IR_TYPE_SIZEOF: - emit_push(fc, type_size(ty, n->ir_sizeof.tid)); - return; - case SPL_IR_TYPE_ALIGNOF: - emit_push(fc, type_align(ty, n->ir_alignof.tid)); - return; - case SPL_IR_TYPE_OFFSETOF: { - spl_ir_node_t *fi = n_at(fc->f, n->ir_offsetof.field_idx); - isize idx = 0; - if (fi && fi->kind == SPL_IR_TYPE_CONST) - idx = fi->type_const.int_lit; - emit_push(fc, field_offset(ty, n->ir_offsetof.tid, idx)); - return; - } - case SPL_IR_TYPE_FIELD_COUNT: { - spl_type_node_t *tt = tn(ty, under(ty, n->field_count.tid)); - usize cnt = 0; - if (tt && (tt->kind == SPL_TYPE_STRUCT || tt->kind == SPL_TYPE_UNION)) - cnt = tt->agg_field_types.size; - else if (tt && tt->kind == SPL_TYPE_ENUM) - cnt = tt->enum_type.variants.size; - emit_push(fc, cnt); - return; - } - default: { - spl_type_id_t tid = node_type(ir, ty, fc->f, ref); - if (!tid) { - diag(fc->c, fc->fid, ref, "value node has no type"); - emit_push(fc, 0); - return; - } - if (is_agg(ty, tid)) { - emit_laddr(fc, fc->param_bytes + fc->vreg_off[ref]); - } else { - emit_laddr(fc, fc->param_bytes + fc->vreg_off[ref]); - emit_load_insn(fc, vm_tag(ty, tid)); - } - return; - } - } -} - -static void emit_node(fctx_t *fc, spl_ir_node_ref_t ref); - -/* 记录 IR 块首 label 当前指令地址 */ -static void mark_label(fctx_t *fc, spl_ir_node_ref_t ref) { - if (ref >= fc->nlabel) - return; - if (fc->label_addr[ref] < 0) - fc->label_addr[ref] = (isize)fc->c->prog.insns.size; -} - -static void emit_node(fctx_t *fc, spl_ir_node_ref_t ref) { - const spl_ir_t *ir = fc->c->pub->ir; - const spl_type_t *ty = fc->c->pub->type; - spl_ir_node_t *n = n_at(fc->f, ref); - if (!n) - return; - mark_label(fc, ref); - switch (n->kind) { - case SPL_IR_TYPE_CONST: - case SPL_IR_MEM_GLOBAL_ALLOC: - case SPL_IR_MEM_ALLOCA: - case SPL_IR_CONTROL_PARAM: - case SPL_IR_TYPE_BITSIZEOF: - case SPL_IR_TYPE_SIZEOF: - case SPL_IR_TYPE_ALIGNOF: - case SPL_IR_TYPE_OFFSETOF: - case SPL_IR_TYPE_FIELD_COUNT: - return; /* 纯节点:引用时重*/ - - case SPL_IR_ARITH_ADD: - case SPL_IR_ARITH_SUB: - case SPL_IR_ARITH_MUL: - case SPL_IR_ARITH_DIV: - case SPL_IR_ARITH_REM: - case SPL_IR_ARITH_AND: - case SPL_IR_ARITH_OR: - case SPL_IR_ARITH_XOR: - case SPL_IR_ARITH_SHL: - case SPL_IR_ARITH_SHR: { - spl_type_id_t tid = n->arith.tid; - emit_value(fc, n->arith.left); - if (n->arith.right) - emit_value(fc, n->arith.right); - spl_opcode_t aop = arith_op(n->kind, is_signed_type(ty, tid)); - /* 浮点除法/取余:VM 的 DIV_S/REM_S 宏(DIV_REM_S)含 float 分支,DIV_U/REM_U 无 */ - spl_type_node_t *at = tn(ty, under(ty, tid)); - if (at && at->kind == SPL_TYPE_FLOAT) { - if (n->kind == SPL_IR_ARITH_DIV) - aop = SPL_DIV_S; - else if (n->kind == SPL_IR_ARITH_REM) - aop = SPL_REM_S; - } - emit_arith(fc, aop, arith_tag(ty, tid)); - emit_store_vreg(fc, ref); - return; - } - case SPL_IR_ARITH_NEG: { - emit_value(fc, n->arith.left); - emit_arith(fc, SPL_NEG, arith_tag(ty, n->arith.tid)); - emit_store_vreg(fc, ref); - return; - } - case SPL_IR_ARITH_NOT: { - emit_value(fc, n->arith.left); - emit_arith(fc, SPL_NOT, SPL_VOID); - emit_store_vreg(fc, ref); - return; - } - case SPL_IR_ARITH_ABS: { - spl_vm_tag_t tag = arith_tag(ty, n->arith.tid); - emit_value(fc, n->arith.left); /* x */ - emit_push(fc, 0); - emit_arith(fc, SPL_SLT, tag); /* x<0 */ - usize bz = add_insn(fc, SPL_BZ, SPL_VOID, 0); - emit_value(fc, n->arith.left); - emit_arith(fc, SPL_NEG, arith_tag(ty, n->arith.tid)); - usize jmp = add_insn(fc, SPL_JMP, SPL_VOID, 0); - usize pos_addr = fc->c->prog.insns.size; - fc->c->prog.insns.data[bz].imm = pos_addr - (bz + 1); - emit_value(fc, n->arith.left); - usize end_addr = fc->c->prog.insns.size; - fc->c->prog.insns.data[jmp].imm = end_addr - (jmp + 1); - emit_store_vreg(fc, ref); - return; - } - - case SPL_IR_CMP_EQ: - case SPL_IR_CMP_NE: - case SPL_IR_CMP_LT: - case SPL_IR_CMP_LE: - case SPL_IR_CMP_GT: - case SPL_IR_CMP_GE: { - spl_type_id_t tid = n->cmp.tid; - emit_value(fc, n->cmp.a); - emit_value(fc, n->cmp.b); - spl_opcode_t op; - /* 浮点顺序比较:VM 的 CMP_U 无 float 分支,须走 CMP_S(SLT/SLE/SGT/SGE 含 float case) */ - int is_f = 0; - spl_type_node_t *ct = tn(ty, under(ty, tid)); - if (ct && ct->kind == SPL_TYPE_FLOAT) - is_f = 1; - switch (n->kind) { - case SPL_IR_CMP_EQ: - op = SPL_EQ; - break; - case SPL_IR_CMP_NE: - op = SPL_NE; - break; - case SPL_IR_CMP_LT: - op = (is_signed_type(ty, tid) || is_f) ? SPL_SLT : SPL_ULT; - break; - case SPL_IR_CMP_LE: - op = (is_signed_type(ty, tid) || is_f) ? SPL_SLE : SPL_ULE; - break; - case SPL_IR_CMP_GT: - op = (is_signed_type(ty, tid) || is_f) ? SPL_SGT : SPL_UGT; + spl_type_node_t *tn = spl_type_node(ctx->type, node->control_ret.tid); + spl_ir_node_t *ret_node = &vec_at(fn->nodes, node->control_ret.val); + switch (tn->kind) { + case SPL_TYPE_INT: break; default: - op = (is_signed_type(ty, tid) || is_f) ? SPL_SGE : SPL_UGE; - break; + UNREACHABLE(); } - emit_arith(fc, op, arith_tag(ty, tid)); - emit_store_vreg(fc, ref); - return; - } + // if (is_agg(ty, tid)) { + // if (n->control_ret.val) { + // emit_value(fc, n->control_ret.val); + // emit_laddr(fc, fc->sret_off); + // emit_load_insn(fc, SPL_PTR); + // add_insn(fc, SPL_SWAP, SPL_VOID, 0); + // emit_memcpy(fc, type_size(ty, tid)); + // } + // add_insn(fc, SPL_RET, SPL_VOID, 0); + // } else if (!is_void(ty, tid)) { + // if (n->control_ret.val) + // emit_value(fc, n->control_ret.val); + // else + // emit_push(fc, 0); /* 空体函数:返回未定义0 */ + // add_insn(fc, SPL_RET, vm_tag(ty, tid), 0); + // } else { + // add_insn(fc, SPL_RET, SPL_VOID, 0); + // } - case SPL_IR_CAST_TRUNC: { - usize bits = int_bits(ty, n->cast.to_tid); - emit_value(fc, n->cast.val); - add_insn(fc, SPL_TRUNC, SPL_VOID, bits); - emit_store_vreg(fc, ref); - return; - } - case SPL_IR_CAST_SEXT: { - usize bits = int_bits(ty, n->cast.from_tid); - emit_value(fc, n->cast.val); - add_insn(fc, SPL_SEXT, SPL_VOID, bits); - emit_store_vreg(fc, ref); - return; - } - case SPL_IR_CAST_ZEXT: { - usize bits = int_bits(ty, n->cast.from_tid); - emit_value(fc, n->cast.val); - add_insn(fc, SPL_ZEXT, SPL_VOID, bits); - emit_store_vreg(fc, ref); - return; - } - case SPL_IR_CAST_BITCAST: - case SPL_IR_CAST_PTR2INT: - case SPL_IR_CAST_INT2PTR: - case SPL_IR_CAST_BOOL2INT: - emit_value(fc, n->cast.val); - emit_store_vreg(fc, ref); - return; - case SPL_IR_CAST_FEXT: - case SPL_IR_CAST_FTRUNC: - case SPL_IR_CASE_INT2FLOAT: - case SPL_IR_CASE_FLOAT2INT: - diag(fc->c, fc->fid, ref, "float/int conversion not implemented in ir2vm"); - emit_value(fc, n->cast.val); - emit_store_vreg(fc, ref); - return; - - case SPL_IR_MEM_LOAD: { - spl_type_id_t tid = n->mem_load.tid; - if (is_agg(ty, tid)) { - emit_value(fc, n->mem_load.ptr); /* [src] */ - emit_laddr(fc, fc->param_bytes + fc->vreg_off[ref]); - add_insn(fc, SPL_SWAP, SPL_VOID, 0); /* [dst, src] */ - emit_memcpy(fc, type_size(ty, tid)); - } else { - emit_value(fc, n->mem_load.ptr); - emit_load_insn(fc, vm_tag(ty, tid)); - emit_store_vreg(fc, ref); - } - return; - } - case SPL_IR_MEM_STORE: { - spl_type_id_t tid = n->mem_store.tid; - if (is_agg(ty, tid)) { - emit_value(fc, n->mem_store.ptr); /* [dst] */ - emit_value(fc, n->mem_store.val); /* [dst, src] */ - emit_memcpy(fc, type_size(ty, tid)); - } else { - emit_value(fc, n->mem_store.ptr); - emit_value(fc, n->mem_store.val); - emit_store_insn(fc, vm_tag(ty, tid)); - } - return; - } - case SPL_IR_MEM_OFFSET: { - emit_value(fc, n->mem_offset.ptr); - emit_value(fc, n->mem_offset.offset); - /* 指针运算(C 语义):*_(void 元素)看成整数,偏移即字节、不 scale; - * *T(非 void)偏移为元素索引,乘 sizeof(T)。 */ - spl_type_id_t ut = under(ty, n->mem_offset.tid); - if (!is_void(ty, ut)) { - emit_push(fc, type_size(ty, n->mem_offset.tid)); - emit_arith(fc, SPL_MUL, SPL_USIZE); - } - emit_arith(fc, SPL_ADD, SPL_USIZE); - emit_store_vreg(fc, ref); - return; - } - case SPL_IR_MEM_FIELD_PTR: { - emit_value(fc, n->mem_field_ptr.agg); - emit_push(fc, field_offset(ty, n->mem_field_ptr.tid, (isize)n->mem_field_ptr.field_idx)); - emit_arith(fc, SPL_ADD, SPL_USIZE); - emit_store_vreg(fc, ref); - return; - } - case SPL_IR_MEM_COPY: { - emit_value(fc, n->mem_copy.dst); - emit_value(fc, n->mem_copy.src); - emit_value(fc, n->mem_copy.size); - isize ni = native_index(fc->c, "vm_memcpy"); - emit_push(fc, (spl_val_t)ni); - add_insn(fc, SPL_NCALL, SPL_VOID, 3); - return; - } - case SPL_IR_MEM_SET: { - /* 字节填充循环:i=0; L: if i>=size goto E; dst[i]=val; i++; jmp L; E: */ - usize temp = fc->temp_off; - emit_laddr(fc, fc->param_bytes + temp); - emit_push(fc, 0); - emit_store_insn(fc, SPL_U64); - usize l1 = fc->c->prog.insns.size; - emit_laddr(fc, fc->param_bytes + temp); - emit_load_insn(fc, SPL_U64); - emit_value(fc, n->mem_set.size); - emit_arith(fc, SPL_ULT, SPL_USIZE); - usize bz = add_insn(fc, SPL_BZ, SPL_VOID, 0); - emit_value(fc, n->mem_set.dst); - emit_laddr(fc, fc->param_bytes + temp); - emit_load_insn(fc, SPL_U64); - emit_arith(fc, SPL_ADD, SPL_USIZE); - emit_value(fc, n->mem_set.val); - emit_store_insn(fc, SPL_U8); - emit_laddr(fc, fc->param_bytes + temp); - emit_load_insn(fc, SPL_U64); - emit_push(fc, 1); - emit_arith(fc, SPL_ADD, SPL_U64); - emit_store_insn(fc, SPL_U64); - usize jmp = add_insn(fc, SPL_JMP, SPL_VOID, 0); - usize e_addr = fc->c->prog.insns.size; - fc->c->prog.insns.data[bz].imm = e_addr - (bz + 1); - fc->c->prog.insns.data[jmp].imm = l1 - (jmp + 1); - return; - } - case SPL_IR_MEM_FENCE: - return; - - case SPL_IR_AGG_CONSTRUCT: { - spl_type_id_t agg_tid = n->agg_construct.tid; - for (usize i = 0; i < n->agg_construct.fields.size; i++) { - /* 字段实际类型取字段节点(enum payload 因变体而异*/ - spl_type_id_t ft = node_type(ir, ty, fc->f, n->agg_construct.fields.data[i]); - if (!ft) - ft = field_type(ty, agg_tid, (isize)i); - emit_laddr(fc, fc->param_bytes + fc->vreg_off[ref]); - usize foff = field_offset(ty, agg_tid, (isize)i); - if (foff) { - emit_push(fc, foff); - emit_arith(fc, SPL_ADD, SPL_USIZE); - } - emit_value(fc, n->agg_construct.fields.data[i]); - if (is_agg(ty, ft)) - emit_memcpy(fc, type_size(ty, ft)); - else - emit_store_insn(fc, vm_tag(ty, ft)); - } - return; - } - case SPL_IR_AGG_EXTRACT: { - spl_type_id_t agg_tid = n->agg_extract.tid; - isize idx = n->agg_extract.field_idx; - spl_type_id_t ft = n->agg_extract.field_tid; - if (!ft) - ft = field_type(ty, agg_tid, idx); - emit_value(fc, n->agg_extract.val); /* [val 地址] */ - usize foff = field_offset(ty, agg_tid, idx); - if (foff) { - emit_push(fc, foff); - emit_arith(fc, SPL_ADD, SPL_USIZE); - } - if (is_agg(ty, ft)) { - emit_laddr(fc, fc->param_bytes + fc->vreg_off[ref]); - add_insn(fc, SPL_SWAP, SPL_VOID, 0); - emit_memcpy(fc, type_size(ty, ft)); - } else { - emit_load_insn(fc, vm_tag(ty, ft)); - emit_store_vreg(fc, ref); - } - return; - } - case SPL_IR_AGG_INSERT: { - spl_type_id_t agg_tid = n->agg_insert.tid; - isize idx = n->agg_insert.field_idx; - spl_type_id_t ft = node_type(ir, ty, fc->f, n->agg_insert.field); - if (!ft) - ft = field_type(ty, agg_tid, idx); - emit_value(fc, n->agg_insert.agg); - emit_laddr(fc, fc->param_bytes + fc->vreg_off[ref]); - add_insn(fc, SPL_SWAP, SPL_VOID, 0); - emit_memcpy(fc, type_size(ty, agg_tid)); - emit_laddr(fc, fc->param_bytes + fc->vreg_off[ref]); - usize foff = field_offset(ty, agg_tid, idx); - if (foff) { - emit_push(fc, foff); - emit_arith(fc, SPL_ADD, SPL_USIZE); - } - emit_value(fc, n->agg_insert.field); - if (is_agg(ty, ft)) - emit_memcpy(fc, type_size(ty, ft)); - else - emit_store_insn(fc, vm_tag(ty, ft)); - return; - } - - case SPL_IR_CONTROL_SELECT: { - emit_value(fc, n->control_select.cond); - usize bz = add_insn(fc, SPL_BZ, SPL_VOID, 0); - emit_value(fc, n->control_select.true_val); - usize jmp = add_insn(fc, SPL_JMP, SPL_VOID, 0); - usize else_addr = fc->c->prog.insns.size; - fc->c->prog.insns.data[bz].imm = else_addr - (bz + 1); - emit_value(fc, n->control_select.false_val); - usize end_addr = fc->c->prog.insns.size; - fc->c->prog.insns.data[jmp].imm = end_addr - (jmp + 1); - emit_store_vreg(fc, ref); - return; - } - case SPL_IR_CONTROL_BR: { - emit_value(fc, n->control_br.cond); - emit_bnz_fix(fc, n->control_br.true_label, -1); - emit_jmp_fix(fc, n->control_br.false_label, -1); - return; - } - case SPL_IR_CONTROL_JMP: - emit_jmp_fix(fc, n->control_jmp.label, -1); - return; - case SPL_IR_CONTROL_CALL: { - spl_type_id_t fn_tid = n->control_call.tid; - spl_type_id_t ret = fn_ret(ty, fn_tid); - int sret = is_agg(ty, ret); - /* 槽数:标量 1 槽;聚合按 C ABI 块数;sret 地址 1 槽 */ - usize nargs = 0; - for (usize i = 0; i < n->control_call.params.size; i++) { - spl_type_id_t pt = node_type(ir, ty, fc->f, n->control_call.params.data[i]); - if (is_agg(ty, pt)) - nargs += align_up(type_size(ty, pt), 8) / 8; - else - nargs += 1; - } - if (sret) - nargs += 1; - for (usize i = 0; i < n->control_call.params.size; i++) { - spl_ir_node_ref_t pref = n->control_call.params.data[i]; - spl_type_id_t pt = node_type(ir, ty, fc->f, pref); - if (is_agg(ty, pt)) { - /* 聚合值按值:逐 8 字节块压栈(vreg 已 8 对齐) */ - usize sz = align_up(type_size(ty, pt), 8); - for (usize j = 0; j < sz / 8; j++) { - emit_laddr(fc, fc->param_bytes + fc->vreg_off[pref] + j * 8); - emit_load_insn(fc, SPL_U64); - } - } else { - emit_value(fc, pref); - } - } - if (sret) - emit_laddr(fc, fc->param_bytes + fc->vreg_off[ref]); - spl_ir_node_t *fn = n_at(fc->f, n->control_call.func); - if (fn && fn->kind == SPL_IR_TYPE_CONST && fn->type_const.fn && - fn->type_const.fn < fc->c->func_addr.size) { - spl_ir_func_ref_t fid = fn->type_const.fn; - if (fc->c->native_idx.data[fid] >= 0) { - emit_push(fc, (spl_val_t)fc->c->native_idx.data[fid]); - add_insn(fc, SPL_NCALL, SPL_VOID, nargs); - } else { - usize idx = add_insn(fc, SPL_PUSH, SPL_VOID, 0); - fix_t fx = {idx, -1, 0, 1, fid}; - vec_push(fc->c->fnfixes, fx); - add_insn(fc, SPL_CALL, SPL_VOID, nargs); - } - if (ret && !is_agg(ty, ret)) - emit_store_vreg(fc, ref); - } else { - /* 间接调用:栈 [args, nargs, func_addr] CALLI(VM: POP addr, POP nargs) - * 先 push 实参(上方循环),再 push nargs,最后 push func_addr */ - emit_push(fc, nargs); - emit_value(fc, n->control_call.func); - add_insn(fc, SPL_CALLI, SPL_VOID, 0); - /* 返回值留在栈顶,与直接调用一致:存入 vreg */ - if (ret && !is_agg(ty, ret)) - emit_store_vreg(fc, ref); - } - return; - } - case SPL_IR_CONTROL_RET: { - spl_type_id_t tid = n->control_ret.tid; - if (is_agg(ty, tid)) { - if (n->control_ret.val) { - emit_value(fc, n->control_ret.val); - emit_laddr(fc, fc->sret_off); - emit_load_insn(fc, SPL_PTR); - add_insn(fc, SPL_SWAP, SPL_VOID, 0); - emit_memcpy(fc, type_size(ty, tid)); - } - add_insn(fc, SPL_RET, SPL_VOID, 0); - } else if (!is_void(ty, tid)) { - if (n->control_ret.val) - emit_value(fc, n->control_ret.val); - else - emit_push(fc, 0); /* 空体函数:返回未定义0 */ - add_insn(fc, SPL_RET, vm_tag(ty, tid), 0); - } else { - add_insn(fc, SPL_RET, SPL_VOID, 0); - } - return; - } - case SPL_IR_CONTROL_UNREACHABLE: - add_insn(fc, SPL_HALT, SPL_VOID, 0); - return; - case SPL_IR_CONTROL_TRAP: - /* trap → halt 带非零退出码(assert 失败语义) */ - add_insn(fc, SPL_HALT, SPL_VOID, 1); - return; - case SPL_IR_DBG_BREAKPOINT: - add_insn(fc, SPL_BK, SPL_VOID, 0); - return; - case SPL_IR_DBG_DECLARE: - return; + spl_prog_add_instr(&ctx->prog, SPL_PUSH, SPL_I32, 0); + spl_prog_add_instr(&ctx->prog, SPL_RET, SPL_I32, 0); + break; default: - diag(fc->c, fc->fid, ref, "unsupported IR node"); - return; + break; } -} - -/* ---- 算术 opcode 映射 ---- */ -static spl_opcode_t arith_op(spl_ir_kind_t k, int is_signed) { - switch (k) { - case SPL_IR_ARITH_ADD: - return SPL_ADD; - case SPL_IR_ARITH_SUB: - return SPL_SUB; - case SPL_IR_ARITH_MUL: - return SPL_MUL; - case SPL_IR_ARITH_DIV: - return is_signed ? SPL_DIV_S : SPL_DIV_U; - case SPL_IR_ARITH_REM: - return is_signed ? SPL_REM_S : SPL_REM_U; - case SPL_IR_ARITH_AND: - return SPL_AND; - case SPL_IR_ARITH_OR: - return SPL_OR; - case SPL_IR_ARITH_XOR: - return SPL_XOR; - case SPL_IR_ARITH_SHL: - return SPL_SHL; - case SPL_IR_ARITH_SHR: - return is_signed ? SPL_SHR_S : SPL_SHR_U; - default: - return SPL_ADD; - } -} - -static int is_signed_type(const spl_type_t *ty, spl_type_id_t tid) { - spl_type_node_t *t = tn(ty, under(ty, tid)); - return t && t->kind == SPL_TYPE_INT && t->int_type.is_signed; -} - -/* ================================================================ - * 函数生成 + 主流 - * ================================================================ */ - -static void gdata_bytes(ctx_t *c, const spl_ir_node_t *g, unsigned char *out) { - const spl_type_t *ty = c->pub->type; - spl_type_id_t tid = g->type_const.tid; - usize sz = type_size(ty, tid); - memset(out, 0, sz); - spl_type_node_t *t = tn(ty, under(ty, tid)); - if (!t) - return; - if (t->kind == SPL_TYPE_INT || t->kind == SPL_TYPE_BOOL) { - isize v = (isize)g->type_const.int_lit; - usize n = sz < sizeof(isize) ? sz : sizeof(isize); - memcpy(out, &v, n); - } else if (t->kind == SPL_TYPE_FLOAT) { - if (t->float_type.bits == 32) { - float f = (float)g->type_const.float_lit; - memcpy(out, &f, sz < 4 ? sz : 4); - } else { - double d = g->type_const.float_lit; - memcpy(out, &d, sz < 8 ? sz : 8); - } - } -} - -static void gen_func(ctx_t *c, spl_ir_func_ref_t fid) { - const spl_ir_t *ir = c->pub->ir; - const spl_type_t *ty = c->pub->type; - fctx_t fc; - memset(&fc, 0, sizeof fc); - fc.c = c; - fc.fid = fid; - fc.f = &ir->funcs.data[fid]; - vec_init(fc.fixes); - - spl_type_id_t fn_tid = fc.f->fn_tid; - spl_type_node_t *ftn = tn(ty, under(ty, fn_tid)); - usize nparams = (ftn && ftn->kind == SPL_TYPE_FN) ? ftn->fn_type.params.size : 0; - - /* 参数布局(C ABI):标量 align8 一槽 8B;聚合 align8 + size 跨多槽 */ - usize off = 0; - fc.nparams = nparams; - fc.param_off = (usize *)malloc((nparams ? nparams : 1) * sizeof(usize)); - for (usize i = 0; i < nparams; i++) { - spl_type_id_t pt = ftn->fn_type.params.data[i]; - off = align_up(off, 8); - fc.param_off[i] = off; - if (is_agg(ty, pt)) - off += align_up(type_size(ty, pt), 8); - else - off += 8; - } - fc.ret_tid = (ftn && ftn->kind == SPL_TYPE_FN) ? ftn->fn_type.ret : 0; - fc.sret = is_agg(ty, fc.ret_tid); - fc.sret_off = align_up(off, 8); - if (fc.sret) - off = fc.sret_off + 8; - fc.param_bytes = off; - - /* vreg / label 布局*/ - fc.nvreg = fc.f->nodes.size; - fc.vreg_off = (usize *)calloc(fc.nvreg ? fc.nvreg : 1, sizeof(usize)); - fc.nlabel = fc.f->nodes.size; - fc.label_addr = (isize *)malloc((fc.nlabel ? fc.nlabel : 1) * sizeof(isize)); - for (usize i = 0; i < fc.nlabel; i++) - fc.label_addr[i] = -1; - - usize locals = 0; - for (usize ref = 1; ref < fc.f->nodes.size; ref++) { - spl_ir_node_t *rn = &fc.f->nodes.data[ref]; - /* 无条件分配(不按 produces_value 过滤):某些节点 produces_value 误报 0 但 - * 仍会被 emit_value 引用并 store_vreg(如聚合字段提取编译成的节点)。若跳过则 - * vreg_off 保持 calloc 的 0,多个节点共享槽 0 互相覆盖(指针偏移/写地址损坏根源)。 */ - spl_type_id_t tid = 0; - if (!needs_vreg_slot(fc.f, ref)) { - /* 聚合值参数:分配 vreg(prologue 从参数区 memcpy 进来) */ - if (rn->kind == SPL_IR_CONTROL_PARAM && is_agg(ty, rn->control_param.tid)) - tid = rn->control_param.tid; - else - continue; - } else { - tid = node_type(ir, ty, fc.f, ref); - /* alloca 的槽 = 缓冲区本体,大小为 mem_alloc.tid 而非 *T */ - if (rn->kind == SPL_IR_MEM_ALLOCA) - tid = rn->mem_alloc.tid; - } - if (!tid) { - /* tid 未解析(MEM_LOAD / BITCAST 未标 tid 等):占位一个 usize 槽, - * 否则 vreg_off 保持 0,多个节点共享槽 0 互相覆盖。 */ - fc.vreg_off[ref] = align_up(locals, 8); - locals = fc.vreg_off[ref] + 8; - continue; - } - usize sz = type_size(ty, tid); - usize al = type_align(ty, tid); - if (is_agg(ty, tid)) - al = align_up(al, 8); /* 聚合 vreg 8 对齐:聚合参数逐块压栈需 8 字节边界 */ - locals = align_up(locals, al); - fc.vreg_off[ref] = locals; - locals += sz; - } - fc.temp_off = align_up(locals, 8); - /* 临时区(bytes):表达式/调用的 PUSH/POP 堆叠、store/bnz 的弹栈会临时压低 sp, - * 若无此区 sp 会降入 vreg 槽区覆盖尚未使用的 vreg(大数组构造等深表达式)。 */ - locals = fc.temp_off + 8 + 1024 * 8; - fc.locals_bytes = locals; - - /* prologue:ALLOC + 聚合值参数 memcpy(参数区 → param vreg) */ - fc.insn_base = c->prog.insns.size; - usize k = (locals + 7) / 8; - add_insn(&fc, SPL_ALLOC, SPL_VOID, k); - for (usize ref = 1; ref < fc.f->nodes.size; ref++) { - spl_ir_node_t *rn = &fc.f->nodes.data[ref]; - if (rn->kind != SPL_IR_CONTROL_PARAM) - continue; - spl_type_id_t pt = rn->control_param.tid; - if (!is_agg(ty, pt)) - continue; - usize pidx = rn->control_param.idx; - emit_laddr(&fc, fc.param_off[pidx]); /* 参数区聚合起始 */ - emit_laddr(&fc, fc.param_bytes + fc.vreg_off[ref]); /* param vreg */ - add_insn(&fc, SPL_SWAP, SPL_VOID, 0); - emit_memcpy(&fc, type_size(ty, pt)); - } - - /* 节点发射 */ - for (usize ref = 1; ref < fc.f->nodes.size; ref++) - emit_node(&fc, ref); - - /* 末尾兜底:若最后不是终止指令,RET(void) */ - if (c->prog.insns.size) { - spl_ins_t *last = &c->prog.insns.data[c->prog.insns.size - 1]; - spl_opcode_t lop = (spl_opcode_t)last->opcode; - if (lop != SPL_RET && lop != SPL_JMP && lop != SPL_BZ && lop != SPL_BNZ && - lop != SPL_HALT) { - add_insn(&fc, SPL_RET, SPL_VOID, 0); - } - } - - /* 回填 IR label 跳转 */ - for (usize i = 0; i < fc.fixes.size; i++) { - fix_t *fx = &fc.fixes.data[i]; - isize addr = fx->target_node >= 0 ? fc.label_addr[fx->target_node] : fx->abs_addr; - if (addr < 0) { - diag(c, fid, 0, "unresolved branch target"); - continue; - } - c->prog.insns.data[fx->insn_idx].imm = (spl_val_t)(addr - (isize)(fx->insn_idx + 1)); - } - - /* func */ - spl_func_t sf; - memset(&sf, 0, sizeof sf); - sf.name = fc.f->name ? strdup(fc.f->name) : strdup("?"); - sf.nargs = (fc.param_bytes + 7) / 8; /* C ABI 参数区槽数(含 sret) */ - sf.ninsns = c->prog.insns.size - fc.insn_base; - sf.address = fc.insn_base; - sf.idx_of_strtab = 0; - spl_prog_add_func(&c->prog, &sf); - - free(fc.param_off); - free(fc.vreg_off); - free(fc.label_addr); - vec_free(fc.fixes); -} - -int spl_ir2vm_run(spl_ir2vm_t *ctx, const char *outpath) { - ctx_t c; - memset(&c, 0, sizeof c); - c.pub = ctx; - spl_prog_init(&c.prog); - vec_init(c.func_addr); - vec_init(c.native_idx); - vec_init(c.cstr_gdata); - vec_init(c.cstr_list); - vec_init(c.fnfixes); - - const spl_ir_t *ir = ctx->ir; - const spl_type_t *ty = ctx->type; - - for (usize i = 0; i < ir->funcs.size; i++) { - vec_push(c.func_addr, (isize)-1); - vec_push(c.native_idx, (isize)-1); - } - - /* 收集 native(nodes 为空IR func = @extern 声明*/ - for (usize fid = 1; fid < ir->funcs.size; fid++) { - spl_ir_func_t *f = &ir->funcs.data[fid]; - if (f->nodes.size == 0) { - spl_native_t nat; - memset(&nat, 0, sizeof nat); - nat.name = f->name ? strdup(f->name) : strdup("?"); - nat.idx_of_strtab = 0; - nat.impl_fn = NULL; - c.native_idx.data[fid] = spl_prog_add_native(&c.prog, &nat) - 1; - } - } - /* 辅助 native:聚合拷贝需vm_memcpy */ - if (native_index(&c, "vm_memcpy") < 0) { - spl_native_t nat; - memset(&nat, 0, sizeof nat); - nat.name = strdup("vm_memcpy"); - nat.impl_fn = NULL; - spl_prog_add_native(&c.prog, &nat); - } - - /* 全局 var/const gdata:value 节点(type.const)求值 → SIR blob */ - for (usize gi = 0; gi < ir->gdata.size; gi++) { - const spl_ir_node_t *g = &ir->gdata.data[gi]; - usize sz = type_size(ty, g->type_const.tid); - unsigned char *buf = (unsigned char *)malloc(sz ? sz : 1); - gdata_bytes(&c, g, buf); - spl_prog_add_data(&c.prog, buf, sz); - free(buf); - } - - /* 字符串常gdata(去重);仅 PTR 类型const 才可能是 cstr_lit */ - for (usize fid = 1; fid < ir->funcs.size; fid++) { - spl_ir_func_t *f = &ir->funcs.data[fid]; - for (usize r = 1; r < f->nodes.size; r++) { - spl_ir_node_t *n = &f->nodes.data[r]; - if (n->kind != SPL_IR_TYPE_CONST || !n->type_const.cstr_lit) - continue; - spl_type_node_t *ct = tn(ty, under(ty, n->type_const.tid)); - if (!ct || ct->kind != SPL_TYPE_PTR) - continue; - int dup = 0; - for (usize i = 0; i < c.cstr_list.size; i++) - if (strcmp(c.cstr_list.data[i], n->type_const.cstr_lit) == 0) { - dup = 1; - break; - } - if (dup) - continue; - vec_push(c.cstr_list, n->type_const.cstr_lit); - vec_push(c.cstr_gdata, c.prog.gdata.size); - spl_prog_add_data(&c.prog, (void *)n->type_const.cstr_lit, - strlen(n->type_const.cstr_lit) + 1); - } - } - - /* 生成普通函*/ - for (usize fid = 1; fid < ir->funcs.size; fid++) { - if (ir->funcs.data[fid].nodes.size == 0) - continue; - c.func_addr.data[fid] = (isize)c.prog.insns.size; - gen_func(&c, fid); - } - - /* 回填函数引用(const_fnref 函数地址*/ - for (usize i = 0; i < c.fnfixes.size; i++) { - fix_t *fx = &c.fnfixes.data[i]; - isize addr = (fx->fn && fx->fn < c.func_addr.size) ? c.func_addr.data[fx->fn] : -1; - if (addr < 0) { - diag(&c, fx->fn, 0, "function reference unresolved"); - continue; - } - c.prog.insns.data[fx->insn_idx].imm = (spl_val_t)addr; - } - - if (!c.err && outpath) - spl_prog_store_to_file(outpath, &c.prog); - if (c.err) - fprintf(stderr, "ir2vm errors=%d\n", c.err); - - /* 释放 native/func name(spl_prog_drop 会释放) */ - int rc = c.err; - spl_prog_drop(&c.prog); - vec_free(c.func_addr); - vec_free(c.native_idx); - vec_free(c.cstr_gdata); - vec_free(c.cstr_list); - vec_free(c.fnfixes); - return rc; + return pos; } void spl_ir2vm_init(spl_ir2vm_t *ctx, const spl_ir_t *ir, const spl_type_t *type) { ctx->ir = ir; ctx->type = type; + spl_prog_init(&ctx->prog); } void spl_ir2vm_drop(spl_ir2vm_t *ctx) { (void)ctx; } +int spl_ir2vm_run(spl_ir2vm_t *ctx) { + int addr = 0; + vec_for(ctx->ir->funcs, i) { + if (i == 0) { + continue; + } + spl_ir_func_t *fn = &vec_at(ctx->ir->funcs, i); + Assert(fn != NULL); + spl_vm_func_t vm_fn = {0}; + vm_fn.name = (char *)fn->name; // FIXME + vm_fn.address = addr; + vm_fn.nargs = 0; + vm_fn.ninsns = 0; + vec_for(fn->nodes, j) { + spl_ir_node_t *node = &vec_at(fn->nodes, j); + emit_instr(ctx, fn, node); + } + spl_prog_add_func(&ctx->prog, &vm_fn); + } + return 0; +} + void spl_ir2vm_dump(spl_ir2vm_t *ctx) { (void)ctx; } diff --git a/stage1/spl_ir2vm.h b/stage1/spl_ir2vm.h index f17451b..0c12908 100644 --- a/stage1/spl_ir2vm.h +++ b/stage1/spl_ir2vm.h @@ -4,98 +4,27 @@ #include "spl_ir.h" #include "spl_type.h" -/* - * ================================================================ - * SPL VM ABI (ir2vm 的正式约定;布局知识唯一来源) - * ================================================================ - * - * 栈值槽 spl_val_t = sizeof(usize) = 8 字节。 - * SIR 指令 type 只表达标量 tag(SPL_I8..SPL_PTR),聚合无 tag—— - * 聚合值在 vreg 中是字节块,整体搬运用 NCALL vm_memcpy。 - * - * ── 函数栈帧(字节坐标系,基址 = (char*)&stacks[fp])───────────── - * - * [canary] fp-8 .. 0 (VM CALL 自动插入,ir2vm 不触碰) - * [params 区] fp+0 .. fp+Na (Na = C ABI 参数区字节数) - * [locals / vreg] fp+Na .. fp+Na+L - * - * ALLOC ceil((Na+L)/8) 一条 prologue;epilogue 走 RET。 - * LADDR(imm) 的 imm 是字节偏移;canary 在 fp-1 槽,编译码不可见。 - * - * ── 参数区 = C ABI(聚合值按值) ───────────────────────────────── - * 标量参数:align_up(off,8) 后占 8 字节(一槽)。 - * 聚合参数:按聚合 size 排布跨多槽(align8 + size)。 - * 调用方:标量 ld/PUSH 一槽;聚合逐 8 字节块压栈(聚合 vreg 强制 8 对齐)。 - * 被调方:标量参数映射参数槽;聚合参数在 prologue memcpy 参数区 → param vreg, - * emit_value(param) 取 vreg 地址。参数槽数 = ceil(param_bytes/8) = CALL nargs。 - * - * ── locals = 虚拟寄存器区 ──────────────────────────────────────── - * 每个产生值的 IR 节点 = 一个 vreg(locals 区按类型对齐的字节块)。 - * 纯值节点(type.const / mem.global_alloc / mem.alloca / 折叠 sizeof 等)不落 vreg, - * 引用处重算(PUSH / GADDR / LADDR);其余产生值节点落 vreg,引用处 LOAD。 - * 聚合 vreg 引用处返回其地址(LADDR),搬运经 vm_memcpy。 - * mem.alloca(tid)(cnt) 的 vreg 槽即缓冲区本体,节点值 = LADDR(vreg_off)。 - * 所有运算走 load/store:ld A; ld B; op; st Dst;立即数直接 PUSH。 - * - * ── 调用 ────────────────────────────────────────────────────────── - * 调用方:逐参数压栈(标量一槽;聚合按 C ABI 逐 8 字节块)→ push fn_addr(或 - * native_idx) → CALL n / NCALL n。返回值落 call 节点 vreg。 - * 原生函数:IR 中 nodes 为空的函数(@extern 声明)→ 注册进 prog.natives, - * 加载时由 spl_syscall_register 填 impl;调用改 PUSH nat_idx + NCALL。 - * 变参 nargs = 实际参数槽数。 - * - * ── enum(不展开,直接保留)───────────────────────────────────── - * IR 层保留 enum 类型(不再展开为 struct)。enum 布局 = tag(usize, offset 0) - * + payload(offset 8,最大变体)。构造:agg.construct(enum)(tag, payload); - * match:先取 tag 判定变体,再 extract(enum, 1) 一跳取 payload, - * field_tid = 变体具体类型(由 ast2ir 传入)。 - * - * ── 返回 ────────────────────────────────────────────────────────── - * 标量:ld vreg(val); RET(tag)(RET 的 type 决定 VM 是否弹出返回值)。 - * 聚合返回 = sret(自展开,不改 VM): - * 被调函数签名尾部追加隐藏 *T 参数(最后一个);返回时把聚合 vreg - * memcpy 到 sret 地址,RET(void)。 - * 调用方在 locals 预留聚合槽(= call 节点 vreg),压其地址为最后实参; - * call 完成后聚合值已在该槽。 - * 返回 void:RET(SPL_VOID)。 - * - * ── 全局数据 ────────────────────────────────────────────────────── - * 任何聚合类型下(含 $root 顶层)的 var/const 属全局数据区。gdata 是 - * spl_ir_node_vec_t,每条 = 一个 value 节点(type.const:标量折叠值, - * 聚合/无 init 零)。ir2vm 遍历求值 → SIR gdata 条目(字节 blob)。 - * mem.global_alloc(tid, const_node) 的 const_node = gdata 向量索引, - * 降级为 GADDR(idx)。符号(def) → gdata 索引的解析在 ast2ir 收集期 - * (gdata_ref 表),ir2vm 按索引直接用。 - * - * ── 类型布局(C ABI,唯一实现处)──────────────────────────────── - * type_align / type_size / field_offset:标量按 bits/8 对齐; - * struct 顺序对齐 + 尾填充;union 取最大字段;enum = tag(8) + 最大 payload; - * slice/range = [ptr, len] 各 8 字节;array = len * elem。 - * - * ── 分支 ────────────────────────────────────────────────────────── - * control.br/jmp/select 的 label 是 IR node ref(基本块首指令)。两遍发射: - * 第一遍逐节点发指令并记录 label 节点 → 指令地址;第二遍回填 - * JMP/BZ/BNZ 相对偏移 imm = target_addr - (jmp_addr + 1)。 - * ================================================================ - */ +#include "../stage0/spl_mcode.h" -/* 调试映射:每函数 IR 节点 → 首条指令 ip(调试器显示当前 IR 节点用) */ typedef struct { spl_ir_func_ref_t fid; - VEC(usize) node_first_ip; /* 索引 = IR 节点 ref,值 = 该节点首指令绝对 ip */ + VEC(usize) node_first_ip; } spl_ir2vm_fdbg_t; typedef VEC(spl_ir2vm_fdbg_t) spl_ir2vm_fdbg_vec_t; +// MAP() typedef struct { const spl_ir_t *ir; const spl_type_t *type; - spl_ir2vm_fdbg_vec_t fdbg; /* ir2vm_run 后填充;splc0 -g 读取生成 debug 段 */ + spl_prog_t prog; + + // spl_ir2vm_fdbg_vec_t fdbg; /* ir2vm_run 后填充;splc0 -g 读取生成 debug 段 */ } spl_ir2vm_t; void spl_ir2vm_init(spl_ir2vm_t *ctx, const spl_ir_t *ir, const spl_type_t *type); void spl_ir2vm_drop(spl_ir2vm_t *ctx); -int spl_ir2vm_run(spl_ir2vm_t *ctx, const char *outpath); /* 返回错误数 */ +int spl_ir2vm_run(spl_ir2vm_t *ctx); void spl_ir2vm_dump(spl_ir2vm_t *ctx); #endif /* __SPL_IR2VM_H__ */ diff --git a/stage1/spl_sema.c b/stage1/spl_sema.c index b39fb56..434661b 100644 --- a/stage1/spl_sema.c +++ b/stage1/spl_sema.c @@ -341,7 +341,7 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { spl_type_id_t old_ret = sema->current_fn_ret_tid; sema->current_fn_ret_tid = ret_id; - vec_for(n->fn_decl.block, i) { sema_parse(sema, vec_at(n->fn_decl.block, i)); } + sema_parse(sema, n->fn_decl.block); sema->current_fn_ret_tid = old_ret; sema_pop_scope(sema); } break; @@ -478,23 +478,15 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { SPL_ERROR(&n->dbg, "if condition must be bool"); sema->error_count++; } - vec_for(n->if_statement.if_block, i) { - sema_parse(sema, vec_at(n->if_statement.if_block, i)); - } - vec_for(n->if_statement.else_block, i) { - sema_parse(sema, vec_at(n->if_statement.else_block, i)); - } + sema_parse(sema, n->if_statement.if_block); + sema_parse(sema, n->if_statement.else_block); } break; case SPL_AST_IFVAR_STATEMENT: { if (n->ifvar_statement.packed_expr) { sema_parse(sema, n->ifvar_statement.packed_expr); } - vec_for(n->ifvar_statement.if_block, i) { - sema_parse(sema, vec_at(n->ifvar_statement.if_block, i)); - } - vec_for(n->ifvar_statement.else_block, i) { - sema_parse(sema, vec_at(n->ifvar_statement.else_block, i)); - } + sema_parse(sema, n->ifvar_statement.if_block); + sema_parse(sema, n->ifvar_statement.else_block); } break; case SPL_AST_WHILE_STATEMENT: { if (!n->while_statement.expr) { @@ -506,14 +498,10 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { SPL_ERROR(&n->dbg, "while condition must be bool"); sema->error_count++; } - vec_for(n->while_statement.while_block, i) { - sema_parse(sema, vec_at(n->while_statement.while_block, i)); - } + sema_parse(sema, n->while_statement.while_block); } break; case SPL_AST_LOOP_STATEMENT: { - vec_for(n->loop_statement.loop_block, i) { - sema_parse(sema, vec_at(n->loop_statement.loop_block, i)); - } + sema_parse(sema, n->loop_statement.loop_block); } break; case SPL_AST_FOR_STATEMENT: { sema_push_scope(sema); @@ -531,7 +519,7 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { spl_scope_insert(sema->scope, sema->scope->current_scope, symbol); } } - vec_for(n->for_statement.block, j) { sema_parse(sema, vec_at(n->for_statement.block, j)); } + sema_parse(sema, n->for_statement.block); sema_pop_scope(sema); } break; case SPL_AST_MATCH_STATEMENT: { @@ -541,9 +529,7 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { vec_for(n->match_statement.paced_exprs, i) { sema_parse(sema, vec_at(n->match_statement.paced_exprs, i)); } - vec_for(n->match_statement.match_block, i) { - sema_parse(sema, vec_at(n->match_statement.match_block, i)); - } + sema_parse(sema, n->match_statement.match_block); } break; case SPL_AST_RET_STATEMENT: { if (n->ret_statement.expr) { @@ -596,7 +582,7 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { case SPL_AST_ASSIGN_OR_EXPR: case SPL_AST_ASSIGN_XOR_EXPR: case SPL_AST_ASSIGN_LSHIFT_EXPR: - case SPL_AST_ASSIGN_USHIFT_EXPR: { + case SPL_AST_ASSIGN_RSHIFT_EXPR: { spl_type_id_t lt = sema_parse(sema, n->op_expr.left); spl_type_id_t rt = sema_parse(sema, n->op_expr.right); if (lt == 0) { diff --git a/stage1/spl_type.c b/stage1/spl_type.c index 0e7a2bb..6a11ddc 100644 --- a/stage1/spl_type.c +++ b/stage1/spl_type.c @@ -377,13 +377,13 @@ void spl_type_drop(spl_type_t *type) { vec_free(type->def_table); } -spl_type_node_t *spl_type_node(spl_type_t *type, spl_type_id_t id) { +spl_type_node_t *spl_type_node(const spl_type_t *type, spl_type_id_t id) { if (!id || id >= vec_size(type->type_table)) return NULL; return &vec_at(type->type_table, id); } -spl_def_node_t *spl_def_node(spl_type_t *type, spl_def_id_t id) { +spl_def_node_t *spl_def_node(const spl_type_t *type, spl_def_id_t id) { if (!id || id >= vec_size(type->def_table)) return NULL; return &vec_at(type->def_table, id); diff --git a/stage1/spl_type.h b/stage1/spl_type.h index 04f0f1d..345a476 100644 --- a/stage1/spl_type.h +++ b/stage1/spl_type.h @@ -111,8 +111,8 @@ void spl_type_drop(spl_type_t *type); void spl_type_def_dump(spl_type_t *type, spl_def_id_t id); void spl_type_pure_dump(spl_type_t *type, spl_type_id_t id); -spl_type_node_t *spl_type_node(spl_type_t *type, spl_type_id_t id); -spl_def_node_t *spl_def_node(spl_type_t *type, spl_def_id_t id); +spl_type_node_t *spl_type_node(const spl_type_t *type, spl_type_id_t id); +spl_def_node_t *spl_def_node(const spl_type_t *type, spl_def_id_t id); spl_type_id_t spl_def_alloc(spl_type_t *type, spl_def_node_kind_t kind, const char *name, spl_dbg_node_t dbg, usize ast_node_ref); diff --git a/stage1/splc0.c b/stage1/splc0.c index 2ceec24..7912ab2 100644 --- a/stage1/splc0.c +++ b/stage1/splc0.c @@ -12,7 +12,7 @@ #include "spl_ast.h" #include "spl_ast2ir.h" -// #include "spl_ir2vm.h" +#include "spl_ir2vm.h" #include "spl_lexer.h" #include "spl_sema.h" #include "spl_tok.h" @@ -23,6 +23,7 @@ typedef enum { DUMP_AST, DUMP_SEMA, DUMP_IR, + DUMP_VM, } dump_t; static char *read_file(const char *path, long *out_len) { @@ -68,6 +69,8 @@ static void dump_tokens(spl_tok_vec_t toks) { static int compile_spl(const char *src, const char *fname, const char *outpath, int gen_debug, dump_t dump) { + (void)gen_debug; + spl_tok_vec_t toks = spl_lex(src, fname); if (dump == DUMP_TOKEN) { dump_tokens(toks); @@ -126,16 +129,25 @@ static int compile_spl(const char *src, const char *fname, const char *outpath, return 0; } - // spl_ir2vm_t ir2vm; - // spl_ir2vm_init(&ir2vm, &a2ir.ir, &sema.type); - // int rc = spl_ir2vm_run(&ir2vm, outpath); - // if (gen_debug && rc == 0) - // gen_debug_map(outpath, &ast, &a2ir.ir, &ir2vm); - // spl_ir2vm_drop(&ir2vm); - // spl_ast2ir_drop(&a2ir); - // spl_sema_drop(&sema); - // spl_ast_drop(&ast); - // return rc ? 1 : 0; + spl_ir2vm_t ir2vm; + spl_ir2vm_init(&ir2vm, &a2ir.ir->ir, sema.type); + int rc = spl_ir2vm_run(&ir2vm); + if (rc != 0) { + printf("ir2vm error %d", rc); + return rc; + } + if (dump == DUMP_VM) { + spl_prog_dump(&ir2vm.prog); + // memory leak + return 0; + } + + spl_prog_store_to_file(outpath, &ir2vm.prog); + + spl_ir2vm_drop(&ir2vm); + spl_ast2ir_drop(&a2ir); + spl_sema_drop(&sema); + spl_ast_drop(&ast); return 0; } @@ -146,7 +158,7 @@ int main(int argc, char **argv) { } if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0) { LOG_INFO("splc0 compile (.spl -> .sir, stage B)"); - LOG_INFO("splc0 --dump dump: lex,ast,sema,ir"); + LOG_INFO("splc0 --dump dump: lex,ast,sema,ir,vm,none"); return 0; } int argi = 1; @@ -165,15 +177,19 @@ int main(int argc, char **argv) { const char *flags = argv[argi + 1]; if (strstr(flags, "lex") != NULL) { dump = DUMP_TOKEN; - } - if (strstr(flags, "ast") != NULL) { + } else if (strstr(flags, "ast") != NULL) { dump = DUMP_AST; - } - if (strstr(flags, "sema") != NULL) { + } else if (strstr(flags, "sema") != NULL) { dump = DUMP_SEMA; - } - if (strstr(flags, "ir") != NULL) { + } else if (strstr(flags, "ir") != NULL) { dump = DUMP_IR; + } else if (strstr(flags, "vm") != NULL) { + dump = DUMP_VM; + } else if (strstr(flags, "none") != NULL) { + dump = DUMP_NONE; + } else { + Panic("--dump unknown flags"); + return 1; } argi += 2; }