stage1 使用切片表达字符串而非C字符串 提供属性系统
This commit is contained in:
1 parent
a64a96f9a4
commit
72ae6d6994
14 files changed
+685
-1256
No files matched your search
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-1
@@ -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);
|
||||||
free(prog->debug);
|
if (prog->debug) {
|
||||||
|
free(prog->debug);
|
||||||
|
}
|
||||||
prog->debug = NULL;
|
prog->debug = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+12
-4
@@ -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;
|
||||||
|
|||||||
@@ -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
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
@@ -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
@@ -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__ */
|
||||||
+174
-67
@@ -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) {
|
||||||
usize idx = ip_of(cg);
|
isize nat_idx = -1;
|
||||||
CG_PUSH(cg, SPL_PTR, 0);
|
if (n->type_const.fn > 0)
|
||||||
cg_add_fix(cg, idx, FIX_FNADDR, 0, n->type_const.fn);
|
map_get(ctx->extern_native, n->type_const.fn, &nat_idx);
|
||||||
cg_store_slot(cg, ref, SPL_PTR);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tn->kind == SPL_TYPE_STRUCT || tn->kind == SPL_TYPE_ARRAY || tn->kind == SPL_TYPE_UNION) {
|
if (nat_idx >= 0) {
|
||||||
const char *bytes = (const char *)n->type_const.ptr_lit;
|
CG_PUSH(cg, SPL_U64, (spl_vm_val_t)nat_idx);
|
||||||
if (!bytes)
|
} else {
|
||||||
bytes = "";
|
usize idx = ip_of(cg);
|
||||||
usize len = strlen(bytes);
|
CG_PUSH(cg, SPL_PTR, 0);
|
||||||
usize data_idx = (usize)spl_prog_add_data(&ctx->prog, (void *)bytes, len + 1);
|
cg_add_fix(cg, idx, FIX_FNADDR, 0, n->type_const.fn);
|
||||||
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,43 +748,48 @@ 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: {
|
||||||
usize nargs = vec_size(n->control_call.params);
|
spl_ir_func_ref_t callee_ref = 0;
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool direct = false;
|
|
||||||
spl_ir_node_ref_t fref = n->control_call.func;
|
spl_ir_node_ref_t fref = n->control_call.func;
|
||||||
if (fref < vec_size(cg->irf->nodes)) {
|
if (fref < vec_size(cg->irf->nodes)) {
|
||||||
const spl_ir_node_t *fn_node = &vec_at(cg->irf->nodes, fref);
|
const spl_ir_node_t *fn_node = &vec_at(cg->irf->nodes, fref);
|
||||||
if (fn_node->kind == SPL_IR_TYPE_CONST) {
|
if (fn_node->kind == SPL_IR_TYPE_CONST)
|
||||||
spl_type_node_t *ftn = spl_type_node(ctx->type, fn_node->type_const.tid);
|
callee_ref = fn_node->type_const.fn;
|
||||||
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;
|
isize nat_idx = -1;
|
||||||
if (ir_is_aggregate(ctx, rtid)) {
|
if (callee_ref > 0)
|
||||||
cg_store_slot(cg, ref, SPL_PTR);
|
map_get(ctx->extern_native, callee_ref, &nat_idx);
|
||||||
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),
|
usize nargs = vec_size(n->control_call.params);
|
||||||
rtid);
|
|
||||||
CG_LADDR(cg, data);
|
if (nat_idx >= 0) {
|
||||||
cg_store_slot(cg, ref, SPL_PTR);
|
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_PUSH(cg, SPL_U64, (spl_vm_val_t)nat_idx);
|
||||||
|
emit(cg, SPL_NCALL, SPL_VOID, (spl_vm_val_t)nargs);
|
||||||
|
|
||||||
|
uint8_t rk = vm_kind_of(ctx, n->control_call.tid);
|
||||||
|
if (rk == SPL_VOID)
|
||||||
|
emit(cg, SPL_DROP, SPL_VOID, 0); /* NCALL 总是 push 一个结果 */
|
||||||
|
else
|
||||||
|
cg_store_slot(cg, ref, rk);
|
||||||
} 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: {
|
||||||
cg_unop(cg, ref, n, SPL_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);
|
||||||
|
}
|
||||||
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
@@ -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
File diff suppressed because it is too large.
Load diff
+5
-1
@@ -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
@@ -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 = *
|
sema.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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user