stage1 使用切片表达字符串而非C字符串 提供属性系统

This commit is contained in:
zzy committed 2026-09-13 22:26:41 +08:00
1 parent a64a96f9a4
commit 72ae6d6994
14 files changed
+676 -1247

No files matched your search

+2 -1
View File
@@ -27,6 +27,7 @@ static const char *splc0_srcs[] = {
"stage1/spl_ast.c", "stage1/spl_ast.c",
"stage1/spl_dumptree.c", "stage1/spl_dumptree.c",
"stage1/spl_type.c", "stage1/spl_type.c",
"stage1/spl_attr.c",
"stage1/spl_sema.c", "stage1/spl_sema.c",
"stage1/spl_intrin.c", "stage1/spl_intrin.c",
"stage1/spl_ir.c", "stage1/spl_ir.c",
@@ -245,7 +246,7 @@ static bool test_once(const char *fname, void *user_data) {
parse_expect(fname, &expect); parse_expect(fname, &expect);
if (expect.exit_code != result.exit_code) { if (expect.exit_code != result.exit_code) {
nob_log(NOB_ERROR, "Expect code `%d`, Result code `%d`\n", expect.exit_code, nob_log(NOB_ERROR, "Expect code `%d`, Result code `%d`", expect.exit_code,
result.exit_code); result.exit_code);
return false; return false;
} }
+3
View File
@@ -20,6 +20,7 @@ void spl_prog_init(spl_prog_t *prog) {
vec_init(prog->strtab); vec_init(prog->strtab);
vec_init(prog->gdata); vec_init(prog->gdata);
map_init(prog->symtab, MAP_HASH_STR, MAP_CMP_STR); map_init(prog->symtab, MAP_HASH_STR, MAP_CMP_STR);
prog->debug = NULL;
} }
void spl_prog_drop(spl_prog_t *prog) { void spl_prog_drop(spl_prog_t *prog) {
@@ -39,7 +40,9 @@ void spl_prog_drop(spl_prog_t *prog) {
vec_for(prog->strtab, i) { free((void *)vec_at(prog->strtab, i)); } vec_for(prog->strtab, i) { free((void *)vec_at(prog->strtab, i)); }
vec_free(prog->strtab); vec_free(prog->strtab);
map_free(prog->symtab); map_free(prog->symtab);
if (prog->debug) {
free(prog->debug); free(prog->debug);
}
prog->debug = NULL; prog->debug = NULL;
} }
+12 -4
View File
@@ -92,6 +92,7 @@ static spl_ast_node_ref_t new_node(parser_t *p, spl_ast_node_kind_t kind, const
n.kind = kind; n.kind = kind;
n.resolved_def_id = 0; n.resolved_def_id = 0;
n.resolved_lang_tid = 0; n.resolved_lang_tid = 0;
vec_init(n.attrs);
if (tok) { if (tok) {
n.dbg.dbg_name = spl_ast_kind_name(kind); n.dbg.dbg_name = spl_ast_kind_name(kind);
n.dbg.fname = tok->fname; n.dbg.fname = tok->fname;
@@ -199,13 +200,15 @@ static char parse_char_literal(const spl_tok_t *t) {
return c; return c;
} }
static char *parse_string_literal(parser_t *p, const spl_tok_t *t) { static char *parse_string_literal(parser_t *p, const spl_tok_t *t, usize *out_len) {
const char *src = t->lexeme + 1; const char *src = t->lexeme + 1;
const char *end = t->lexeme + t->len - 1; const char *end = t->lexeme + t->len - 1;
usize cap = t->len + 1; usize cap = t->len + 1;
char *tmp = malloc(cap); char *tmp = malloc(cap);
if (!tmp) if (!tmp) {
*out_len = 0;
return NULL; return NULL;
}
char *dst = tmp; char *dst = tmp;
while (src < end) { while (src < end) {
char c; char c;
@@ -216,7 +219,7 @@ static char *parse_string_literal(parser_t *p, const spl_tok_t *t) {
src++; src++;
} }
} }
*dst = '\0'; *out_len = (usize)(dst - tmp);
char *interned = intern_string(p->ast, tmp, dst - tmp); char *interned = intern_string(p->ast, tmp, dst - tmp);
free(tmp); free(tmp);
return interned; return interned;
@@ -1402,7 +1405,11 @@ static spl_ast_node_ref_t parse_primary(parser_t *p) {
case TOK_STRING_LITERAL: { case TOK_STRING_LITERAL: {
advance(p); advance(p);
spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_STRING_LIT, t); spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_STRING_LIT, t);
node_at(p->ast, ref)->string_lit.data = parse_string_literal(p, t); usize len = 0;
const char *data = parse_string_literal(p, t, &len);
spl_ast_node_t *node = node_at(p->ast, ref);
node->string_lit.data = data;
node->string_lit.len = len;
return ref; return ref;
} }
case KW_TRUE: case KW_TRUE:
@@ -2234,6 +2241,7 @@ void spl_ast_drop(spl_ast_t *ast) {
return; return;
vec_for(ast->str_buckets, idx) { free(vec_at(ast->str_buckets, idx)); } vec_for(ast->str_buckets, idx) { free(vec_at(ast->str_buckets, idx)); }
vec_free(ast->str_buckets); vec_free(ast->str_buckets);
vec_for(ast->node_buckets, idx) { vec_free(vec_at(ast->node_buckets, idx).attrs); }
vec_free(ast->node_buckets); vec_free(ast->node_buckets);
vec_free(ast->input); vec_free(ast->input);
ast->parsed = 0; ast->parsed = 0;
+4
View File
@@ -6,6 +6,8 @@
#include "spl_lexer.h" #include "spl_lexer.h"
#include "spl_tok.h" #include "spl_tok.h"
#include "spl_attr.h"
/* clang-format off */ /* clang-format off */
#define SPL_AST_KIND_TABLE \ #define SPL_AST_KIND_TABLE \
X(SPL_AST_NONE, V0, none) \ X(SPL_AST_NONE, V0, none) \
@@ -154,6 +156,7 @@ struct spl_ast_node {
usize resolved_def_id; usize resolved_def_id;
usize resolved_lang_tid; usize resolved_lang_tid;
usize expected_lang_tid; usize expected_lang_tid;
spl_attr_id_vec_t attrs;
union { union {
/* SPL_AST_ROOT */ /* SPL_AST_ROOT */
@@ -299,6 +302,7 @@ struct spl_ast_node {
} char_lit; } char_lit;
struct { struct {
const char *data; const char *data;
usize len;
} string_lit; } string_lit;
struct { struct {
bool val; bool val;
+73 -6
View File
@@ -38,6 +38,26 @@ static spl_ir_node_ref_t ast2ir_intrin_call(spl_ast2ir_t *a, spl_ast_node_t *n,
static spl_ir_node_ref_t ast2ir_intrin_field(spl_ast2ir_t *a, spl_ast_node_t *n, spl_intrin_t in); static spl_ir_node_ref_t ast2ir_intrin_field(spl_ast2ir_t *a, spl_ast_node_t *n, spl_intrin_t in);
static spl_ir_node_ref_t ast2ir_intrin_len(spl_ast2ir_t *a, spl_ast_node_t *n); static spl_ir_node_ref_t ast2ir_intrin_len(spl_ast2ir_t *a, spl_ast_node_t *n);
static void copy_attrs_to_ir_node(spl_ast2ir_t *a, spl_ast_node_t *n, spl_ir_node_ref_t ir_ref) {
if (!ir_ref || !n || vec_size(n->attrs) == 0)
return;
spl_ir_node_t *irn = spl_ir_node(&a->ir->ir, a->ir->current_fn, ir_ref);
if (!irn)
return;
for (usize i = 0; i < vec_size(n->attrs); ++i)
vec_push(irn->attrs, vec_at(n->attrs, i));
}
static void copy_attrs_to_ir_func(spl_ast2ir_t *a, spl_ast_node_t *n, spl_ir_func_ref_t fn_ref) {
if (!fn_ref || !n || vec_size(n->attrs) == 0)
return;
spl_ir_func_t *irf = spl_ir_func(&a->ir->ir, fn_ref);
if (!irf)
return;
for (usize i = 0; i < vec_size(n->attrs); ++i)
vec_push(irf->attrs, vec_at(n->attrs, i));
}
static spl_ir_node_ref_t ast2ir_intrin_call(spl_ast2ir_t *a, spl_ast_node_t *n, spl_intrin_t in, static spl_ir_node_ref_t ast2ir_intrin_call(spl_ast2ir_t *a, spl_ast_node_t *n, spl_intrin_t in,
spl_ast_node_ref_vec_t *args) { spl_ast_node_ref_vec_t *args) {
switch (in) { switch (in) {
@@ -59,12 +79,37 @@ static spl_ir_node_ref_t ast2ir_intrin_call(spl_ast2ir_t *a, spl_ast_node_t *n,
spl_ir_node_ref_t br = spl_ir_builder_control_br(a->ir, notc); spl_ir_node_ref_t br = spl_ir_builder_control_br(a->ir, notc);
spl_ir_builder_block_end(a->ir); spl_ir_builder_block_end(a->ir);
usize trap_blk = spl_ir_builder_block_begin(a->ir); usize panic_blk = spl_ir_builder_block_begin(a->ir);
const char *fname = n->dbg.fname ? n->dbg.fname : "?";
const char *user_msg = NULL;
if (vec_size(*args) == 2) {
spl_ast_node_t *mn = spl_ast_node(a->sema->ast, vec_at(*args, 1));
if (mn && mn->kind == SPL_AST_EXPR_STRING_LIT && mn->string_lit.data)
user_msg = mn->string_lit.data;
}
char *msg;
int need;
if (user_msg) {
need = snprintf(NULL, 0, "%s:%d:%d: assert failed: %s", fname, n->dbg.line, n->dbg.col,
user_msg);
msg = malloc((usize)need + 1);
snprintf(msg, (usize)need + 1, "%s:%d:%d: assert failed: %s", fname, n->dbg.line,
n->dbg.col, user_msg);
} else {
need = snprintf(NULL, 0, "%s:%d:%d: assert failed", fname, n->dbg.line, n->dbg.col);
msg = malloc((usize)need + 1);
snprintf(msg, (usize)need + 1, "%s:%d:%d: assert failed", fname, n->dbg.line,
n->dbg.col);
}
spl_ir_builder_dbg_panic(a->ir, msg, (usize)need);
spl_ir_builder_control_trap(a->ir); spl_ir_builder_control_trap(a->ir);
spl_ir_builder_block_end(a->ir); spl_ir_builder_block_end(a->ir);
usize cont_blk = spl_ir_builder_block_begin(a->ir); usize cont_blk = spl_ir_builder_block_begin(a->ir);
spl_ir_builder_control_br_fixup(a->ir, br, trap_blk, cont_blk); spl_ir_builder_control_br_fixup(a->ir, br, panic_blk, cont_blk);
return 0; return 0;
} }
case SPL_INTRIN_BREAKPOINT: case SPL_INTRIN_BREAKPOINT:
@@ -259,6 +304,8 @@ static spl_ir_node_ref_t emit_expr(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
if (!n || n->expected_lang_tid == 0) if (!n || n->expected_lang_tid == 0)
return val; return val;
copy_attrs_to_ir_node(a, n, val);
spl_lang_type_id_t from = n->resolved_lang_tid; spl_lang_type_id_t from = n->resolved_lang_tid;
spl_lang_type_id_t to = n->expected_lang_tid; spl_lang_type_id_t to = n->expected_lang_tid;
if (!from || from == to) if (!from || from == to)
@@ -284,8 +331,27 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
return spl_ir_builder_type_const_float(a->ir, node_ir(a, n), n->float_lit.val); return spl_ir_builder_type_const_float(a->ir, node_ir(a, n), n->float_lit.val);
case SPL_AST_EXPR_CHAR_LIT: case SPL_AST_EXPR_CHAR_LIT:
return spl_ir_builder_type_const_char(a->ir, node_ir(a, n), n->char_lit.val); return spl_ir_builder_type_const_char(a->ir, node_ir(a, n), n->char_lit.val);
case SPL_AST_EXPR_STRING_LIT: case SPL_AST_EXPR_STRING_LIT: {
return spl_ir_builder_type_const_cstr(a->ir, node_ir(a, n), n->string_lit.data); usize len = n->string_lit.len;
spl_lang_type_id_t u8_lang = spl_lang_make_int(a->sema->type, 8, 0);
spl_type_id_t u8_ir = to_ir_type(a, u8_lang);
spl_type_id_t ptr_u8_ir = spl_type_builder_ptr(a->sema->type, u8_ir);
spl_lang_type_id_t usize_lang = spl_lang_make_int(a->sema->type, sizeof(void *) * 8, 0);
spl_type_id_t usize_ir = to_ir_type(a, usize_lang);
spl_lang_type_id_t arr_lang = spl_lang_make_array(a->sema->type, u8_lang, len);
spl_type_id_t arr_ir = to_ir_type(a, arr_lang);
spl_ir_node_ref_t raw =
spl_ir_builder_type_const_bytes(a->ir, arr_ir, n->string_lit.data, n->string_lit.len);
spl_ir_node_ref_t ptr = spl_ir_builder_mem_global_alloc(a->ir, ptr_u8_ir, raw);
spl_ir_node_ref_t len_c = spl_ir_builder_type_const_int(a->ir, usize_ir, len);
spl_type_id_t slice_ir = node_ir(a, n);
spl_ir_node_ref_t node = spl_ir_builder_agg_construct(a->ir, slice_ir);
spl_ir_builder_agg_construct_field(a->ir, node, ptr);
spl_ir_builder_agg_construct_field(a->ir, node, len_c);
return node;
}
case SPL_AST_EXPR_BOOL_LIT: case SPL_AST_EXPR_BOOL_LIT:
return spl_ir_builder_type_const_bool(a->ir, node_ir(a, n), n->bool_lit.val); return spl_ir_builder_type_const_bool(a->ir, node_ir(a, n), n->bool_lit.val);
case SPL_AST_EXPR_NULL_LIT: case SPL_AST_EXPR_NULL_LIT:
@@ -935,10 +1001,11 @@ static void emit_fn(spl_ast2ir_t *a, spl_ast_node_t *n) {
if (!fn_ir) if (!fn_ir)
return; return;
spl_ir_attr_t attr = {.kind = SPL_IR_ATTR_NONE}; spl_ir_func_ref_t fn_ref = spl_ir_builder_fn_begin(a->ir, n->fn_decl.name, fn_ir);
spl_ir_func_ref_t fn_ref = spl_ir_builder_fn_begin(a->ir, n->fn_decl.name, fn_ir, attr);
map_put(a->def2ir_map, n->resolved_def_id, (spl_ir_node_ref_t)fn_ref); map_put(a->def2ir_map, n->resolved_def_id, (spl_ir_node_ref_t)fn_ref);
copy_attrs_to_ir_func(a, n, fn_ref);
spl_lang_type_id_t saved_ret = a->cur_ret_lang; spl_lang_type_id_t saved_ret = a->cur_ret_lang;
a->cur_ret_lang = fn_ln->extra.fn.ret; a->cur_ret_lang = fn_ln->extra.fn.ret;
+152
View File
@@ -0,0 +1,152 @@
#include "spl_attr.h"
static spl_attr_info_t spl_builtin_attrs[] = {
{NULL, "extern", SPL_ATTR_STAGE_IR, SPL_ATTR_TARGET_DECL, SPL_ATTR_REQUIRED, 1, 1},
{NULL, "inline", SPL_ATTR_STAGE_OPT, SPL_ATTR_TARGET_DECL, SPL_ATTR_OPTIONAL, 0, 0},
{NULL, "noinline", SPL_ATTR_STAGE_OPT, SPL_ATTR_TARGET_DECL, SPL_ATTR_OPTIONAL, 0, 0},
{NULL, "align", SPL_ATTR_STAGE_LAYOUT, SPL_ATTR_TARGET_TYPE, SPL_ATTR_REQUIRED, 1, 1},
{NULL, "volatile", SPL_ATTR_STAGE_IR, SPL_ATTR_TARGET_EXPR, SPL_ATTR_REQUIRED, 0, 0},
{NULL, "atomic", SPL_ATTR_STAGE_IR, SPL_ATTR_TARGET_EXPR, SPL_ATTR_REQUIRED, 0, 1},
};
void spl_attr_init(spl_attr_t *ctx) {
vec_init(ctx->table);
vec_push(ctx->table, (spl_attr_node_t){0});
vec_init(ctx->registry);
spl_attr_register_builtins(ctx);
}
void spl_attr_drop(spl_attr_t *ctx) {
for (usize i = 1; i < vec_size(ctx->table); ++i)
vec_free(vec_at(ctx->table, i).args);
vec_free(ctx->table);
vec_free(ctx->registry);
}
spl_attr_id_t spl_attr_alloc(spl_attr_t *ctx, spl_attr_info_t *info, spl_attr_arg_vec_t args) {
spl_attr_node_t a = {0};
a.info = info;
a.args = args;
vec_push(ctx->table, a);
return vec_size(ctx->table) - 1;
}
spl_attr_node_t *spl_attr_node(const spl_attr_t *ctx, spl_attr_id_t id) {
if (!id || id >= vec_size(ctx->table))
return NULL;
return &vec_at(ctx->table, id);
}
void spl_attr_registry_add(spl_attr_t *ctx, spl_attr_info_t *info) {
vec_push(ctx->registry, info);
}
static int name_eq(const char *a, const char *b) {
if (a == NULL && b == NULL)
return 1;
if (a == NULL || b == NULL)
return 0;
return strcmp(a, b) == 0;
}
spl_attr_info_t *spl_attr_lookup(spl_attr_t *ctx, const char *ns, const char *name) {
for (usize i = 0; i < vec_size(ctx->registry); ++i) {
spl_attr_info_t *info = vec_at(ctx->registry, i);
if (name_eq(info->ns, ns) && strcmp(info->name, name) == 0)
return info;
}
return NULL;
}
void spl_attr_register_builtins(spl_attr_t *ctx) {
usize n = sizeof(spl_builtin_attrs) / sizeof(spl_builtin_attrs[0]);
for (usize i = 0; i < n; ++i)
spl_attr_registry_add(ctx, &spl_builtin_attrs[i]);
}
static const char *attr_stage_name(spl_attr_stage_t s) {
switch (s) {
case SPL_ATTR_STAGE_SEMA:
return "SEMA";
case SPL_ATTR_STAGE_LAYOUT:
return "LAYOUT";
case SPL_ATTR_STAGE_IR:
return "IR";
case SPL_ATTR_STAGE_OPT:
return "OPT";
case SPL_ATTR_STAGE_BACKEND:
return "BACKEND";
}
return "?";
}
static const char *attr_target_name(spl_attr_target_t t) {
switch (t) {
case SPL_ATTR_TARGET_DECL:
return "DECL";
case SPL_ATTR_TARGET_TYPE:
return "TYPE";
case SPL_ATTR_TARGET_EXPR:
return "EXPR";
case SPL_ATTR_TARGET_STMT:
return "STMT";
}
return "?";
}
static const char *attr_demand_name(spl_attr_demand_t d) {
return d == SPL_ATTR_REQUIRED ? "REQUIRED" : "OPTIONAL";
}
void spl_attr_dump_id(const spl_attr_t *ctx, spl_attr_id_t id) {
if (!ctx || !id) {
printf("?");
return;
}
spl_attr_node_t *a = spl_attr_node(ctx, id);
if (!a || !a->info) {
printf("?");
return;
}
printf("%s", a->info->name);
if (vec_size(a->args) > 0) {
printf("(");
for (usize i = 0; i < vec_size(a->args); ++i) {
if (i > 0)
printf(", ");
spl_attr_arg_t *arg = &vec_at(a->args, i);
switch (arg->kind) {
case SPL_ATTR_ARG_INT:
printf("%zd", arg->value.i);
break;
case SPL_ATTR_ARG_STR:
printf("\"%s\"", arg->value.s ? arg->value.s : "");
break;
case SPL_ATTR_ARG_DEF:
printf("def#%zu", arg->value.d);
break;
case SPL_ATTR_ARG_TYPE:
printf("type#%zu", arg->value.t);
break;
}
}
printf(")");
}
}
void spl_attr_dump(const spl_attr_t *ctx) {
if (!ctx)
return;
printf("AttrTable:\n");
for (usize i = 1; i < vec_size(ctx->table); ++i) {
spl_attr_node_t *a = &vec_at(ctx->table, i);
printf(" #%zu ", i);
spl_attr_dump_id(ctx, i);
if (a->info) {
printf(" [stage=%s target=%s demand=%s consumed=0x%x]", attr_stage_name(a->info->stage),
attr_target_name(a->info->target), attr_demand_name(a->info->demand),
a->consumed_mask);
}
printf("\n");
}
}
+84
View File
@@ -0,0 +1,84 @@
#ifndef __SPL_ATTR_H__
#define __SPL_ATTR_H__
#include "../stage0/include/utils.h"
typedef enum {
SPL_ATTR_STAGE_SEMA,
SPL_ATTR_STAGE_LAYOUT,
SPL_ATTR_STAGE_IR,
SPL_ATTR_STAGE_OPT,
SPL_ATTR_STAGE_BACKEND,
} spl_attr_stage_t;
typedef enum {
SPL_ATTR_TARGET_DECL,
SPL_ATTR_TARGET_TYPE,
SPL_ATTR_TARGET_EXPR,
SPL_ATTR_TARGET_STMT,
} spl_attr_target_t;
typedef enum {
SPL_ATTR_OPTIONAL,
SPL_ATTR_REQUIRED,
} spl_attr_demand_t;
typedef struct {
const char *ns;
const char *name;
spl_attr_stage_t stage;
spl_attr_target_t target;
spl_attr_demand_t demand;
int min_args;
int max_args;
} spl_attr_info_t;
typedef enum {
SPL_ATTR_ARG_INT,
SPL_ATTR_ARG_STR,
SPL_ATTR_ARG_DEF,
SPL_ATTR_ARG_TYPE,
} spl_attr_arg_kind_t;
typedef struct {
spl_attr_arg_kind_t kind;
union {
isize i;
const char *s;
usize d;
usize t;
} value;
} spl_attr_arg_t;
typedef VEC(spl_attr_arg_t) spl_attr_arg_vec_t;
typedef usize spl_attr_id_t;
typedef struct {
spl_attr_info_t *info;
spl_attr_arg_vec_t args;
uint32_t consumed_mask;
} spl_attr_node_t;
typedef VEC(spl_attr_node_t) spl_attr_node_vec_t;
typedef VEC(spl_attr_id_t) spl_attr_id_vec_t;
typedef VEC(spl_attr_info_t *) spl_attr_registry_t;
typedef struct {
spl_attr_node_vec_t table;
spl_attr_registry_t registry;
} spl_attr_t;
void spl_attr_init(spl_attr_t *ctx);
void spl_attr_drop(spl_attr_t *ctx);
spl_attr_id_t spl_attr_alloc(spl_attr_t *ctx, spl_attr_info_t *info, spl_attr_arg_vec_t args);
spl_attr_node_t *spl_attr_node(const spl_attr_t *ctx, spl_attr_id_t id);
void spl_attr_registry_add(spl_attr_t *ctx, spl_attr_info_t *info);
spl_attr_info_t *spl_attr_lookup(spl_attr_t *ctx, const char *ns, const char *name);
void spl_attr_register_builtins(spl_attr_t *ctx);
void spl_attr_dump(const spl_attr_t *ctx);
void spl_attr_dump_id(const spl_attr_t *ctx, spl_attr_id_t id);
#endif /* __SPL_ATTR_H__ */
+42 -10
View File
@@ -28,6 +28,9 @@ static void node_drop_vecs(spl_ir_node_t *n) {
case SPL_IR_CONTROL_CALL: case SPL_IR_CONTROL_CALL:
vec_free(n->control_call.params); vec_free(n->control_call.params);
break; break;
case SPL_IR_DBG_PANIC:
free((char *)n->dbg_panic.msg);
break;
default: default:
break; break;
} }
@@ -36,7 +39,11 @@ static void node_drop_vecs(spl_ir_node_t *n) {
void spl_ir_drop(spl_ir_t *ir) { void spl_ir_drop(spl_ir_t *ir) {
vec_for(ir->funcs, i) { vec_for(ir->funcs, i) {
spl_ir_func_t *f = &vec_at(ir->funcs, i); spl_ir_func_t *f = &vec_at(ir->funcs, i);
vec_for(f->nodes, j) { node_drop_vecs(&vec_at(f->nodes, j)); } vec_for(f->nodes, j) {
vec_free(vec_at(f->nodes, j).attrs);
node_drop_vecs(&vec_at(f->nodes, j));
}
vec_free(f->attrs);
vec_free(f->nodes); vec_free(f->nodes);
} }
vec_free(ir->funcs); vec_free(ir->funcs);
@@ -267,10 +274,25 @@ static void ir_dump_node(const spl_type_t *ty, spl_ir_node_t *n) {
case SPL_IR_CONTROL_TRAP: case SPL_IR_CONTROL_TRAP:
case SPL_IR_DBG_BREAKPOINT: case SPL_IR_DBG_BREAKPOINT:
break; break;
case SPL_IR_DBG_PANIC:
printf(" \"%.*s\"", (int)n->dbg_panic.len, n->dbg_panic.msg);
break;
} }
} }
void spl_ir_dump(spl_ir_t *ir, const spl_type_t *ty) { static void ir_dump_attr_list(const spl_attr_t *attr, spl_attr_id_vec_t *ids) {
if (!attr || !ids || vec_size(*ids) == 0)
return;
printf(" attrs=[");
for (usize i = 0; i < vec_size(*ids); ++i) {
if (i > 0)
printf(", ");
spl_attr_dump_id(attr, vec_at(*ids, i));
}
printf("]");
}
void spl_ir_dump(spl_ir_t *ir, const spl_type_t *ty, const spl_attr_t *attr) {
vec_for(ir->funcs, i) { vec_for(ir->funcs, i) {
if (i == 0) if (i == 0)
continue; continue;
@@ -278,7 +300,9 @@ void spl_ir_dump(spl_ir_t *ir, const spl_type_t *ty) {
printf("func %s %%%zu", func->name ? func->name : "?", i); printf("func %s %%%zu", func->name ? func->name : "?", i);
printf(" tid = "); printf(" tid = ");
spl_type_pure_dump((spl_type_t *)ty, func->fn_tid); spl_type_pure_dump((spl_type_t *)ty, func->fn_tid);
ir_dump_attr_list(attr, &func->attrs);
printf("\n"); printf("\n");
vec_for(func->nodes, j) { vec_for(func->nodes, j) {
if (j == 0) if (j == 0)
continue; continue;
@@ -286,10 +310,9 @@ void spl_ir_dump(spl_ir_t *ir, const spl_type_t *ty) {
printf(" #%zu ", j); printf(" #%zu ", j);
printf("%s", spl_ir_kind_name(node->kind)); printf("%s", spl_ir_kind_name(node->kind));
ir_dump_node(ty, node); ir_dump_node(ty, node);
ir_dump_attr_list(attr, &node->attrs);
printf("\n"); printf("\n");
} }
if (vec_size(func->nodes) == 0)
printf(" (extern)\n");
} }
// if (vec_size(ir->gdata) > 1) { // if (vec_size(ir->gdata) > 1) {
// printf("gdata:\n"); // printf("gdata:\n");
@@ -315,6 +338,7 @@ static spl_ir_node_ref_t builder_alloc_node(spl_ir_builder_t *b, spl_ir_kind_t k
spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref); spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref);
n->kind = kind; n->kind = kind;
n->dbg = b->dbg; n->dbg = b->dbg;
vec_init(n->attrs);
if (b->current_block >= vec_size(b->blocks)) { if (b->current_block >= vec_size(b->blocks)) {
Panic("unknown bblock"); Panic("unknown bblock");
@@ -345,14 +369,14 @@ void spl_ir_builder_drop(spl_ir_builder_t *b) {
} }
spl_ir_func_ref_t spl_ir_builder_fn_begin(spl_ir_builder_t *b, const char *name, spl_ir_func_ref_t spl_ir_builder_fn_begin(spl_ir_builder_t *b, const char *name,
spl_type_id_t fn_tid, spl_ir_attr_t attr) { spl_type_id_t fn_tid) {
if (b->current_fn) { if (b->current_fn) {
spl_ir_builder_fn_end(b); spl_ir_builder_fn_end(b);
} }
spl_ir_func_ref_t fid = spl_ir_alloc_fn(&b->ir); spl_ir_func_ref_t fid = spl_ir_alloc_fn(&b->ir);
spl_ir_func_t *f = spl_ir_func(&b->ir, fid); spl_ir_func_t *f = spl_ir_func(&b->ir, fid);
f->name = name; f->name = name;
f->attr = attr; vec_init(f->attrs);
f->fn_tid = fn_tid; f->fn_tid = fn_tid;
b->current_fn = fid; b->current_fn = fid;
@@ -587,13 +611,13 @@ spl_ir_node_ref_t spl_ir_builder_type_const_float(spl_ir_builder_t *b, spl_type_
return ref; return ref;
} }
spl_ir_node_ref_t spl_ir_builder_type_const_cstr(spl_ir_builder_t *b, spl_type_id_t tid, spl_ir_node_ref_t spl_ir_builder_type_const_bytes(spl_ir_builder_t *b, spl_type_id_t tid,
const char *val) { const void *data, usize len) {
(void)len;
spl_ir_node_ref_t ref = builder_alloc_node(b, SPL_IR_TYPE_CONST); spl_ir_node_ref_t ref = builder_alloc_node(b, SPL_IR_TYPE_CONST);
spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref); spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref);
n->type_const.tid = tid; n->type_const.tid = tid;
TODO(); n->type_const.ptr_lit = (void *)data;
// n->type_const.cstr_lit = val;
return ref; return ref;
} }
@@ -792,3 +816,11 @@ spl_ir_node_ref_t spl_ir_builder_control_trap(spl_ir_builder_t *b) {
spl_ir_node_ref_t spl_ir_builder_dbg_breakpoint(spl_ir_builder_t *b) { spl_ir_node_ref_t spl_ir_builder_dbg_breakpoint(spl_ir_builder_t *b) {
return builder_alloc_node(b, SPL_IR_DBG_BREAKPOINT); return builder_alloc_node(b, SPL_IR_DBG_BREAKPOINT);
} }
spl_ir_node_ref_t spl_ir_builder_dbg_panic(spl_ir_builder_t *b, const char *msg, usize len) {
spl_ir_node_ref_t ref = builder_alloc_node(b, SPL_IR_DBG_PANIC);
spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref);
n->dbg_panic.msg = msg;
n->dbg_panic.len = len;
return ref;
}
+15 -18
View File
@@ -5,6 +5,8 @@
#include "spl_dbg.h" #include "spl_dbg.h"
#include "spl_type.h" #include "spl_type.h"
#include "spl_attr.h"
/* clang-format off */ /* clang-format off */
#define SPL_IR_FN_TABLE \ #define SPL_IR_FN_TABLE \
X(arith.add, V0, SPL_IR_ARITH_ADD) \ X(arith.add, V0, SPL_IR_ARITH_ADD) \
@@ -63,6 +65,7 @@
X(control.unreachable, V0, SPL_IR_CONTROL_UNREACHABLE) \ X(control.unreachable, V0, SPL_IR_CONTROL_UNREACHABLE) \
X(control.trap, V0, SPL_IR_CONTROL_TRAP) \ X(control.trap, V0, SPL_IR_CONTROL_TRAP) \
X(dbg.breakpoint, V0, SPL_IR_DBG_BREAKPOINT) \ X(dbg.breakpoint, V0, SPL_IR_DBG_BREAKPOINT) \
X(dbg.panic, V0, SPL_IR_DBG_PANIC) \
typedef enum { typedef enum {
#ifdef X #ifdef X
@@ -82,6 +85,7 @@ typedef usize spl_ir_func_ref_t; /* 0 is error */
typedef struct { typedef struct {
spl_ir_kind_t kind; spl_ir_kind_t kind;
spl_dbg_node_t dbg; spl_dbg_node_t dbg;
spl_attr_id_vec_t attrs;
union { union {
spl_type_id_t tid; spl_type_id_t tid;
struct { struct {
@@ -211,26 +215,18 @@ typedef struct {
spl_type_id_t tid; spl_type_id_t tid;
spl_ir_node_ref_t val; spl_ir_node_ref_t val;
} control_ret; } control_ret;
struct {
const char *msg;
usize len;
} dbg_panic;
}; };
} spl_ir_node_t; } spl_ir_node_t;
typedef VEC(spl_ir_node_t) spl_ir_node_vec_t; typedef VEC(spl_ir_node_t) spl_ir_node_vec_t;
typedef struct {
enum {
SPL_IR_ATTR_NONE,
SPL_IR_ATTR_LINK, /* 不实现 */
SPL_IR_ATTR_ABI, /* 只有 C ABI 支持 */
SPL_IR_ATTR_SYMBOL, /* 不实现 */
SPL_IR_ATTR_NAKED, /* 不实现 */
SPL_IR_ATTR_NOINLINE, /* 不实现 */
SPL_IR_ATTR_ALWAYSINLINE, /* 不实现 */
} kind;
} spl_ir_attr_t;
typedef VEC(spl_ir_attr_t) spl_ir_attr_vec_t;
typedef struct { typedef struct {
const char *name; const char *name;
spl_ir_attr_t attr; spl_attr_id_vec_t attrs;
spl_type_id_t fn_tid; spl_type_id_t fn_tid;
spl_ir_node_vec_t nodes; spl_ir_node_vec_t nodes;
} spl_ir_func_t; } spl_ir_func_t;
@@ -259,7 +255,7 @@ spl_ir_func_ref_t spl_ir_alloc_fn(spl_ir_t *ir);
spl_ir_node_t *spl_ir_node(spl_ir_t *ir, spl_ir_func_ref_t fn_id, spl_ir_node_ref_t node_id); spl_ir_node_t *spl_ir_node(spl_ir_t *ir, spl_ir_func_ref_t fn_id, spl_ir_node_ref_t node_id);
spl_ir_func_t *spl_ir_func(spl_ir_t *ir, spl_ir_func_ref_t fn_id); spl_ir_func_t *spl_ir_func(spl_ir_t *ir, spl_ir_func_ref_t fn_id);
void spl_ir_dump(spl_ir_t *ir, const spl_type_t *ty); void spl_ir_dump(spl_ir_t *ir, const spl_type_t *ty, const spl_attr_t *attr);
const char *spl_ir_kind_name(spl_ir_kind_t kind); const char *spl_ir_kind_name(spl_ir_kind_t kind);
typedef struct { typedef struct {
@@ -312,7 +308,7 @@ void spl_ir_builder_init(spl_ir_builder_t *b);
void spl_ir_builder_drop(spl_ir_builder_t *b); void spl_ir_builder_drop(spl_ir_builder_t *b);
spl_ir_func_ref_t spl_ir_builder_fn_begin(spl_ir_builder_t *b, const char *name, spl_ir_func_ref_t spl_ir_builder_fn_begin(spl_ir_builder_t *b, const char *name,
spl_type_id_t fn_tid, spl_ir_attr_t attr); spl_type_id_t fn_tid);
void spl_ir_builder_fn_end(spl_ir_builder_t *b); void spl_ir_builder_fn_end(spl_ir_builder_t *b);
usize spl_ir_builder_block_begin(spl_ir_builder_t *b); usize spl_ir_builder_block_begin(spl_ir_builder_t *b);
@@ -370,8 +366,8 @@ spl_ir_node_ref_t spl_ir_builder_type_const_bool(spl_ir_builder_t *b, spl_type_i
spl_ir_node_ref_t spl_ir_builder_type_const_int(spl_ir_builder_t *b, spl_type_id_t tid, usize val); spl_ir_node_ref_t spl_ir_builder_type_const_int(spl_ir_builder_t *b, spl_type_id_t tid, usize val);
spl_ir_node_ref_t spl_ir_builder_type_const_float(spl_ir_builder_t *b, spl_type_id_t tid, spl_ir_node_ref_t spl_ir_builder_type_const_float(spl_ir_builder_t *b, spl_type_id_t tid,
double val); double val);
spl_ir_node_ref_t spl_ir_builder_type_const_cstr(spl_ir_builder_t *b, spl_type_id_t tid, spl_ir_node_ref_t spl_ir_builder_type_const_bytes(spl_ir_builder_t *b, spl_type_id_t tid,
const char *val); const void *data, usize len);
spl_ir_node_ref_t spl_ir_builder_type_const_char(spl_ir_builder_t *b, spl_type_id_t tid, char val); spl_ir_node_ref_t spl_ir_builder_type_const_char(spl_ir_builder_t *b, spl_type_id_t tid, char val);
spl_ir_node_ref_t spl_ir_builder_type_const_fn(spl_ir_builder_t *b, spl_type_id_t tid, spl_ir_node_ref_t spl_ir_builder_type_const_fn(spl_ir_builder_t *b, spl_type_id_t tid,
spl_ir_func_ref_t val); spl_ir_func_ref_t val);
@@ -419,5 +415,6 @@ spl_ir_node_ref_t spl_ir_builder_control_unreachable(spl_ir_builder_t *b);
spl_ir_node_ref_t spl_ir_builder_control_trap(spl_ir_builder_t *b); spl_ir_node_ref_t spl_ir_builder_control_trap(spl_ir_builder_t *b);
spl_ir_node_ref_t spl_ir_builder_dbg_breakpoint(spl_ir_builder_t *b); spl_ir_node_ref_t spl_ir_builder_dbg_breakpoint(spl_ir_builder_t *b);
spl_ir_node_ref_t spl_ir_builder_dbg_panic(spl_ir_builder_t *b, const char *msg, usize len);
#endif /* __SPL_IR_H__ */ #endif /* __SPL_IR_H__ */
+166 -59
View File
@@ -68,6 +68,41 @@ static usize ir_agg_field_off(spl_ir2vm_t *ctx, spl_type_id_t tid, usize idx) {
return 0; return 0;
} }
static int get_or_add_native(spl_ir2vm_t *ctx, const char *name) {
if (!name)
return -1;
for (usize i = 0; i < vec_size(ctx->prog.natives); ++i) {
spl_vm_native_t *n = &vec_at(ctx->prog.natives, i);
if (n->name && strcmp(n->name, name) == 0)
return (int)i;
}
spl_vm_native_t nat = {0};
nat.name = strdup(name);
nat.idx_of_strtab = 0;
nat.impl_fn = NULL;
vec_push(ctx->prog.natives, nat);
return (int)(vec_size(ctx->prog.natives) - 1);
}
static bool fn_check_extern(spl_ir2vm_t *ctx, spl_ir_func_t *f, const char **out_target) {
if (out_target)
*out_target = NULL;
if (!ctx->attr || !f)
return false;
for (usize i = 0; i < vec_size(f->attrs); ++i) {
spl_attr_node_t *a = spl_attr_node(ctx->attr, vec_at(f->attrs, i));
if (!a || !a->info)
continue;
if (strcmp(a->info->name, "extern") != 0)
continue;
a->consumed_mask |= (1u << SPL_ATTR_STAGE_IR);
if (out_target && vec_size(a->args) >= 1 && vec_at(a->args, 0).kind == SPL_ATTR_ARG_STR)
*out_target = vec_at(a->args, 0).value.s;
return true;
}
return false;
}
static uint8_t vm_kind_of(spl_ir2vm_t *ctx, spl_type_id_t tid) { static uint8_t vm_kind_of(spl_ir2vm_t *ctx, spl_type_id_t tid) {
spl_type_node_t *tn = spl_type_node(ctx->type, tid); spl_type_node_t *tn = spl_type_node(ctx->type, tid);
if (!tn) if (!tn)
@@ -217,17 +252,12 @@ static usize node_data_size(spl_ir2vm_t *ctx, const spl_ir_func_t *f, const spl_
if (ir_is_aggregate(ctx, node->mem_load.tid)) if (ir_is_aggregate(ctx, node->mem_load.tid))
return ir_type_size(ctx, node->mem_load.tid); return ir_type_size(ctx, node->mem_load.tid);
return 0; return 0;
case SPL_IR_DBG_PANIC:
return sizeof(spl_vm_val_t) * 4; /* TODO: fmt slice + msg slice */
case SPL_IR_CONTROL_CALL: case SPL_IR_CONTROL_CALL:
if (ir_is_aggregate(ctx, node->control_call.tid)) if (ir_is_aggregate(ctx, node->control_call.tid))
return ir_type_size(ctx, node->control_call.tid); return ir_type_size(ctx, node->control_call.tid);
return 0; return 0;
case SPL_IR_TYPE_CONST: {
spl_type_node_t *tn = spl_type_node(ctx->type, node->type_const.tid);
if (tn && (tn->kind == SPL_TYPE_STRUCT || tn->kind == SPL_TYPE_ARRAY ||
tn->kind == SPL_TYPE_UNION))
return ir_type_size(ctx, node->type_const.tid);
return 0;
}
default: default:
return 0; return 0;
} }
@@ -415,30 +445,17 @@ static void cg_const(cgen_t *cg, usize ref, const spl_ir_node_t *n) {
return; return;
if (tn->kind == SPL_TYPE_FN) { if (tn->kind == SPL_TYPE_FN) {
isize nat_idx = -1;
if (n->type_const.fn > 0)
map_get(ctx->extern_native, n->type_const.fn, &nat_idx);
if (nat_idx >= 0) {
CG_PUSH(cg, SPL_U64, (spl_vm_val_t)nat_idx);
} else {
usize idx = ip_of(cg); usize idx = ip_of(cg);
CG_PUSH(cg, SPL_PTR, 0); CG_PUSH(cg, SPL_PTR, 0);
cg_add_fix(cg, idx, FIX_FNADDR, 0, n->type_const.fn); cg_add_fix(cg, idx, FIX_FNADDR, 0, n->type_const.fn);
cg_store_slot(cg, ref, SPL_PTR);
return;
} }
if (tn->kind == SPL_TYPE_STRUCT || tn->kind == SPL_TYPE_ARRAY || tn->kind == SPL_TYPE_UNION) {
const char *bytes = (const char *)n->type_const.ptr_lit;
if (!bytes)
bytes = "";
usize len = strlen(bytes);
usize data_idx = (usize)spl_prog_add_data(&ctx->prog, (void *)bytes, len + 1);
usize base = vec_at(cg->frame.slots, ref).data_off;
usize ptr_off = ir_agg_field_off(ctx, tid, 0);
usize len_off = ir_agg_field_off(ctx, tid, 1);
CG_GADDR(cg, data_idx);
cg_store_at(cg, base + ptr_off, SPL_PTR);
CG_PUSH(cg, SPL_U64, len);
cg_store_at(cg, base + len_off, SPL_U64);
CG_LADDR(cg, base);
cg_store_slot(cg, ref, SPL_PTR); cg_store_slot(cg, ref, SPL_PTR);
return; return;
} }
@@ -506,6 +523,21 @@ static void cg_mem(cgen_t *cg, usize ref, const spl_ir_node_t *n) {
break; break;
} }
case SPL_IR_MEM_GLOBAL_ALLOC: {
const spl_ir_node_t *cn = &vec_at(cg->irf->nodes, n->mem_global_alloc.const_node);
int idx = 0;
if (cn->kind == SPL_IR_TYPE_CONST && cn->type_const.ptr_lit) {
usize size = ir_type_size(ctx, cn->type_const.tid);
idx = spl_prog_add_data(&ctx->prog, cn->type_const.ptr_lit, size);
}
if (idx > 0)
emit(cg, SPL_GADDR, SPL_VOID, (spl_vm_val_t)idx);
else
CG_PUSH(cg, SPL_PTR, 0);
cg_store_slot(cg, ref, SPL_PTR);
break;
}
case SPL_IR_MEM_LOAD: { case SPL_IR_MEM_LOAD: {
spl_type_id_t tid = n->mem_load.tid; spl_type_id_t tid = n->mem_load.tid;
if (ir_is_aggregate(ctx, tid)) { if (ir_is_aggregate(ctx, tid)) {
@@ -716,7 +748,21 @@ static void cg_control(cgen_t *cg, usize ref, const spl_ir_node_t *n) {
} }
case SPL_IR_CONTROL_CALL: { case SPL_IR_CONTROL_CALL: {
spl_ir_func_ref_t callee_ref = 0;
spl_ir_node_ref_t fref = n->control_call.func;
if (fref < vec_size(cg->irf->nodes)) {
const spl_ir_node_t *fn_node = &vec_at(cg->irf->nodes, fref);
if (fn_node->kind == SPL_IR_TYPE_CONST)
callee_ref = fn_node->type_const.fn;
}
isize nat_idx = -1;
if (callee_ref > 0)
map_get(ctx->extern_native, callee_ref, &nat_idx);
usize nargs = vec_size(n->control_call.params); usize nargs = vec_size(n->control_call.params);
if (nat_idx >= 0) {
for (usize i = 0; i < nargs; ++i) { for (usize i = 0; i < nargs; ++i) {
spl_ir_node_ref_t pref = vec_at(n->control_call.params, i); spl_ir_node_ref_t pref = vec_at(n->control_call.params, i);
const spl_ir_node_t *pn = &vec_at(cg->irf->nodes, pref); const spl_ir_node_t *pn = &vec_at(cg->irf->nodes, pref);
@@ -724,35 +770,26 @@ static void cg_control(cgen_t *cg, usize ref, const spl_ir_node_t *n) {
uint8_t pk = vm_kind_of(ctx, ptid); uint8_t pk = vm_kind_of(ctx, ptid);
cg_load_slot(cg, pref, pk); cg_load_slot(cg, pref, pk);
} }
CG_PUSH(cg, SPL_U64, (spl_vm_val_t)nat_idx);
emit(cg, SPL_NCALL, SPL_VOID, (spl_vm_val_t)nargs);
bool direct = false; uint8_t rk = vm_kind_of(ctx, n->control_call.tid);
spl_ir_node_ref_t fref = n->control_call.func; if (rk == SPL_VOID)
if (fref < vec_size(cg->irf->nodes)) { emit(cg, SPL_DROP, SPL_VOID, 0); /* NCALL 总是 push 一个结果 */
const spl_ir_node_t *fn_node = &vec_at(cg->irf->nodes, fref); else
if (fn_node->kind == SPL_IR_TYPE_CONST) { cg_store_slot(cg, ref, rk);
spl_type_node_t *ftn = spl_type_node(ctx->type, fn_node->type_const.tid);
if (ftn && ftn->kind == SPL_TYPE_FN) {
usize idx = ip_of(cg);
CG_PUSH(cg, SPL_PTR, 0);
cg_add_fix(cg, idx, FIX_FNADDR, 0, fn_node->type_const.fn);
emit(cg, SPL_CALL, SPL_VOID, nargs);
direct = true;
}
}
}
if (!direct)
emit(cg, SPL_HALT, SPL_VOID, 0);
spl_type_id_t rtid = n->control_call.tid;
if (ir_is_aggregate(ctx, rtid)) {
cg_store_slot(cg, ref, SPL_PTR);
usize data = vec_at(cg->frame.slots, ref).data_off;
cg_copy_agg(cg, ptr_slot(vec_at(cg->frame.slots, ref).result_off), direct_data(data),
rtid);
CG_LADDR(cg, data);
cg_store_slot(cg, ref, SPL_PTR);
} else { } else {
uint8_t rk = vm_kind_of(ctx, rtid); for (usize i = 0; i < nargs; ++i) {
spl_ir_node_ref_t pref = vec_at(n->control_call.params, i);
const spl_ir_node_t *pn = &vec_at(cg->irf->nodes, pref);
spl_type_id_t ptid = ir_result_tid(pn);
uint8_t pk = vm_kind_of(ctx, ptid);
cg_load_slot(cg, pref, pk);
}
cg_load_slot(cg, fref, SPL_PTR);
emit(cg, SPL_CALL, SPL_VOID, (spl_vm_val_t)nargs);
uint8_t rk = vm_kind_of(ctx, n->control_call.tid);
if (rk != SPL_VOID) if (rk != SPL_VOID)
cg_store_slot(cg, ref, rk); cg_store_slot(cg, ref, rk);
} }
@@ -761,7 +798,7 @@ static void cg_control(cgen_t *cg, usize ref, const spl_ir_node_t *n) {
case SPL_IR_CONTROL_UNREACHABLE: case SPL_IR_CONTROL_UNREACHABLE:
case SPL_IR_CONTROL_TRAP: case SPL_IR_CONTROL_TRAP:
emit(cg, SPL_HALT, SPL_VOID, 0); emit(cg, SPL_HALT, SPL_VOID, 1);
break; break;
default: default:
@@ -817,9 +854,18 @@ static void cg_node(cgen_t *cg, usize ref, const spl_ir_node_t *n) {
case SPL_IR_ARITH_NEG: case SPL_IR_ARITH_NEG:
cg_unop(cg, ref, n, SPL_NEG); cg_unop(cg, ref, n, SPL_NEG);
break; break;
case SPL_IR_ARITH_NOT: case SPL_IR_ARITH_NOT: {
spl_type_node_t *tn = spl_type_node(cg->ctx->type, n->arith.tid);
if (tn && tn->kind == SPL_TYPE_BOOL) {
cg_load_slot(cg, n->arith.left, SPL_BOOL);
CG_PUSH(cg, SPL_U8, 0);
CG_OP(cg, SPL_EQ, SPL_U8);
cg_store_slot(cg, ref, SPL_BOOL);
} else {
cg_unop(cg, ref, n, SPL_NOT); cg_unop(cg, ref, n, SPL_NOT);
}
break; break;
}
case SPL_IR_ARITH_ABS: case SPL_IR_ARITH_ABS:
break; break;
@@ -869,6 +915,7 @@ static void cg_node(cgen_t *cg, usize ref, const spl_ir_node_t *n) {
break; break;
case SPL_IR_MEM_ALLOCA: case SPL_IR_MEM_ALLOCA:
case SPL_IR_MEM_GLOBAL_ALLOC:
case SPL_IR_MEM_LOAD: case SPL_IR_MEM_LOAD:
case SPL_IR_MEM_STORE: case SPL_IR_MEM_STORE:
case SPL_IR_MEM_OFFSET: case SPL_IR_MEM_OFFSET:
@@ -898,6 +945,39 @@ static void cg_node(cgen_t *cg, usize ref, const spl_ir_node_t *n) {
cg_control(cg, ref, n); cg_control(cg, ref, n);
break; break;
case SPL_IR_DBG_PANIC: {
spl_ir2vm_t *ctx = cg->ctx;
usize data = vec_at(cg->frame.slots, ref).data_off;
int msg_idx = spl_prog_add_data(&ctx->prog, (void *)n->dbg_panic.msg, n->dbg_panic.len);
int fmt_idx = spl_prog_add_data(&ctx->prog, "%s", 2);
if (msg_idx <= 0 || fmt_idx <= 0)
break;
/* fmt slice = {ptr, len=2} 写到 data+0 */
CG_GADDR(cg, (spl_vm_val_t)fmt_idx);
cg_store_at(cg, data + 0, SPL_PTR);
CG_PUSH(cg, SPL_U64, 2);
cg_store_at(cg, data + 8, SPL_U64);
/* msg slice = {ptr, len} 写到 data+16 */
CG_GADDR(cg, (spl_vm_val_t)msg_idx);
cg_store_at(cg, data + 16, SPL_PTR);
CG_PUSH(cg, SPL_U64, n->dbg_panic.len);
cg_store_at(cg, data + 24, SPL_U64);
/* push fmt slice 指针,push msg slice 指针 */
CG_LADDR(cg, data + 0);
CG_LADDR(cg, data + 16);
/* NCALL vm_printf(2) */
int nat = get_or_add_native(ctx, "vm_printf");
CG_PUSH(cg, SPL_U64, (spl_vm_val_t)nat);
emit(cg, SPL_NCALL, SPL_VOID, 2);
emit(cg, SPL_DROP, SPL_VOID, 0); /* 丢弃返回值 */
break;
}
case SPL_IR_DBG_BREAKPOINT: case SPL_IR_DBG_BREAKPOINT:
emit(cg, SPL_BK, SPL_VOID, 0); emit(cg, SPL_BK, SPL_VOID, 0);
break; break;
@@ -963,13 +1043,23 @@ static usize translate_function(spl_ir2vm_t *ctx, spl_ir_func_ref_t fid, fix_vec
return func_ip; return func_ip;
} }
void spl_ir2vm_init(spl_ir2vm_t *ctx, const spl_ir_t *ir, const spl_type_t *type) { static usize spl_map_hash(usize k) { return MAP_HASH_INT(k); }
static int spl_map_cmp(usize a, usize b) { return MAP_CMP_INT(a, b); }
void spl_ir2vm_init(spl_ir2vm_t *ctx, const spl_ir_t *ir, const spl_type_t *type,
const spl_attr_t *attr) {
Assert(ir != NULL && type != NULL && attr != NULL);
ctx->ir = ir; ctx->ir = ir;
ctx->type = type; ctx->type = type;
ctx->attr = attr;
map_init(ctx->extern_native, spl_map_hash, spl_map_cmp);
spl_prog_init(&ctx->prog); spl_prog_init(&ctx->prog);
} }
void spl_ir2vm_drop(spl_ir2vm_t *ctx) { spl_prog_drop(&ctx->prog); } void spl_ir2vm_drop(spl_ir2vm_t *ctx) {
spl_prog_drop(&ctx->prog);
map_free(ctx->extern_native);
}
int spl_ir2vm_run_func(spl_ir2vm_t *ctx, spl_ir_func_ref_t ref) { int spl_ir2vm_run_func(spl_ir2vm_t *ctx, spl_ir_func_ref_t ref) {
fix_vec_t all_fixups; fix_vec_t all_fixups;
@@ -984,13 +1074,30 @@ int spl_ir2vm_run(spl_ir2vm_t *ctx) {
if (n <= 1) if (n <= 1)
return 0; return 0;
/* Pass 1:扫描所有 fn,把 extern 的登记到 map 里 */
for (spl_ir_func_ref_t i = 1; i < n; ++i) {
spl_ir_func_t *irf = spl_ir_func((spl_ir_t *)ctx->ir, i);
if (!irf)
continue;
if (fn_check_extern(ctx, irf, NULL)) {
int nat_idx = get_or_add_native(ctx, irf->name);
map_put(ctx->extern_native, i, (isize)nat_idx);
}
}
/* Pass 2:翻译非 extern 的函数 */
usize *fid_ip = calloc(n, sizeof(usize)); usize *fid_ip = calloc(n, sizeof(usize));
fix_vec_t all_fixups; fix_vec_t all_fixups;
vec_init(all_fixups); vec_init(all_fixups);
for (spl_ir_func_ref_t i = 1; i < n; ++i) for (spl_ir_func_ref_t i = 1; i < n; ++i) {
isize dummy = -1;
if (map_get(ctx->extern_native, i, &dummy))
continue;
fid_ip[i] = translate_function(ctx, i, &all_fixups); fid_ip[i] = translate_function(ctx, i, &all_fixups);
}
/* FNADDR 回填 */
for (usize i = 0; i < vec_size(all_fixups); ++i) { for (usize i = 0; i < vec_size(all_fixups); ++i) {
fix_t *fx = &vec_at(all_fixups, i); fix_t *fx = &vec_at(all_fixups, i);
if (fx->kind != FIX_FNADDR) if (fx->kind != FIX_FNADDR)
+5 -1
View File
@@ -12,16 +12,20 @@ typedef struct {
} spl_ir2vm_fdbg_t; } spl_ir2vm_fdbg_t;
typedef VEC(spl_ir2vm_fdbg_t) spl_ir2vm_fdbg_vec_t; typedef VEC(spl_ir2vm_fdbg_t) spl_ir2vm_fdbg_vec_t;
typedef MAP(spl_ir_func_ref_t, isize) spl_extern_idx_map_t;
// MAP() // MAP()
typedef struct { typedef struct {
const spl_ir_t *ir; const spl_ir_t *ir;
const spl_type_t *type; const spl_type_t *type;
const spl_attr_t *attr;
spl_extern_idx_map_t extern_native;
spl_prog_t prog; spl_prog_t prog;
// spl_ir2vm_fdbg_vec_t fdbg; /* ir2vm_run 后填充;splc0 -g 读取生成 debug 段 */ // spl_ir2vm_fdbg_vec_t fdbg; /* ir2vm_run 后填充;splc0 -g 读取生成 debug 段 */
} spl_ir2vm_t; } spl_ir2vm_t;
void spl_ir2vm_init(spl_ir2vm_t *ctx, const spl_ir_t *ir, const spl_type_t *type); void spl_ir2vm_init(spl_ir2vm_t *ctx, const spl_ir_t *ir, const spl_type_t *type,
const spl_attr_t *attr);
void spl_ir2vm_drop(spl_ir2vm_t *ctx); void spl_ir2vm_drop(spl_ir2vm_t *ctx);
int spl_ir2vm_run_func(spl_ir2vm_t *ctx, spl_ir_func_ref_t ref); int spl_ir2vm_run_func(spl_ir2vm_t *ctx, spl_ir_func_ref_t ref);
+106 -1144
View File
File diff suppressed because it is too large. Load diff
+5 -1
View File
@@ -4,6 +4,8 @@
#include "spl_ast.h" #include "spl_ast.h"
#include "spl_type.h" #include "spl_type.h"
#include "spl_attr.h"
typedef enum { typedef enum {
SPL_SYMBOL_KIND_ERROR, SPL_SYMBOL_KIND_ERROR,
SPL_SYMBOL_KIND_VAR, SPL_SYMBOL_KIND_VAR,
@@ -44,10 +46,12 @@ typedef struct {
spl_symbol_t root; spl_symbol_t root;
int error_count; int error_count;
spl_scope_id_t store_scope; spl_scope_id_t store_scope;
spl_attr_t *attr;
spl_type_id_t current_fn_ret_tid; // TODO spl_type_id_t current_fn_ret_tid; // TODO
} spl_sema_t; } spl_sema_t;
void spl_sema_init(spl_sema_t *sema, spl_ast_t *ast, spl_type_t *type, spl_scope_t *scope); void spl_sema_init(spl_sema_t *sema, spl_ast_t *ast, spl_type_t *type, spl_scope_t *scope,
spl_attr_t *attr);
void spl_sema_drop(spl_sema_t *sema); void spl_sema_drop(spl_sema_t *sema);
void spl_sema_run_module(spl_sema_t *sema, spl_ast_node_ref_t module_ref); void spl_sema_run_module(spl_sema_t *sema, spl_ast_node_ref_t module_ref);
+7 -3
View File
@@ -91,12 +91,15 @@ static int compile_spl(const char *src, const char *fname, const char *outpath,
// memory leak // memory leak
return 0; return 0;
} }
spl_attr_t attr;
spl_attr_init(&attr);
spl_sema_t sema; spl_sema_t sema;
spl_type_t type; spl_type_t type;
spl_scope_t scope; spl_scope_t scope;
spl_type_init(&type); spl_type_init(&type);
spl_scope_init(&scope); spl_scope_init(&scope);
spl_sema_init(&sema, &ast, &type, &scope); spl_sema_init(&sema, &ast, &type, &scope, &attr);
sema.ast = &ast; sema.ast = &ast;
spl_sema_run(&sema); spl_sema_run(&sema);
if (sema.error_count) { if (sema.error_count) {
@@ -124,13 +127,13 @@ static int compile_spl(const char *src, const char *fname, const char *outpath,
return 1; return 1;
} }
if (dump == DUMP_IR) { if (dump == DUMP_IR) {
spl_ir_dump(&ir_builder.ir, &type); spl_ir_dump(&ir_builder.ir, &type, &attr);
// memory leak // memory leak
return 0; return 0;
} }
spl_ir2vm_t ir2vm; spl_ir2vm_t ir2vm;
spl_ir2vm_init(&ir2vm, &a2ir.ir->ir, sema.type); spl_ir2vm_init(&ir2vm, &a2ir.ir->ir, &type, &attr);
int rc = spl_ir2vm_run(&ir2vm); int rc = spl_ir2vm_run(&ir2vm);
if (rc != 0) { if (rc != 0) {
printf("ir2vm error %d", rc); printf("ir2vm error %d", rc);
@@ -148,6 +151,7 @@ static int compile_spl(const char *src, const char *fname, const char *outpath,
spl_ast2ir_drop(&a2ir); spl_ast2ir_drop(&a2ir);
spl_sema_drop(&sema); spl_sema_drop(&sema);
spl_ast_drop(&ast); spl_ast_drop(&ast);
// memory leak
return 0; return 0;
} }