stage1 实现更多ast2ir 修复bug 提供内置操作

This commit is contained in:
zzy committed 2026-09-11 19:26:48 +08:00
1 parent ab6e99c958
commit 49ccdec3dd
10 files changed
+396 -76

No files matched your search

+154 -11
View File
@@ -1,5 +1,5 @@
#include "spl_ast2ir.h"
#include <string.h>
#include "spl_intrin.h"
static spl_type_id_t to_ir_type(spl_ast2ir_t *a, spl_lang_type_id_t lang) {
if (!lang)
@@ -32,6 +32,70 @@ static void emit_fn(spl_ast2ir_t *a, spl_ast_node_t *n);
static void emit_container(spl_ast2ir_t *a, spl_ast_node_ref_t ref);
static spl_ir_node_ref_t emit_cast(spl_ast2ir_t *a, spl_ast_node_t *n);
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_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_call(spl_ast2ir_t *a, spl_ast_node_t *n, spl_intrin_t in) {
switch (in) {
case SPL_INTRIN_SIZEOF: {
spl_ast_node_t *arg = spl_ast_node(a->sema->ast, vec_at(n->call.args, 0));
return spl_ir_builder_type_sizeof(a->ir, node_ir(a, arg));
}
case SPL_INTRIN_ALIGNOF: {
spl_ast_node_t *arg = spl_ast_node(a->sema->ast, vec_at(n->call.args, 0));
return spl_ir_builder_type_alignof(a->ir, node_ir(a, arg));
}
case SPL_INTRIN_ASSERT: {
/* 目前 SEMA 只做类型检查,emit 阶段留空,
@assert 展开需待 control.trap 语义明确后再实现 */
return 0;
}
default:
UNREACHABLE();
}
return 0;
}
static spl_ir_node_ref_t ast2ir_intrin_field(spl_ast2ir_t *a, spl_ast_node_t *n, spl_intrin_t in) {
switch (in) {
case SPL_INTRIN_LEN:
return ast2ir_intrin_len(a, n);
default:
UNREACHABLE();
}
return 0;
}
static spl_ir_node_ref_t ast2ir_intrin_len(spl_ast2ir_t *a, spl_ast_node_t *n) {
spl_ast_node_t *obj = spl_ast_node(a->sema->ast, n->field.obj);
spl_lang_type_id_t recv_lang = node_lang(a, obj);
spl_lang_type_node_t *recv = spl_lang_type_node(a->sema->type, recv_lang);
if (!recv)
return 0;
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);
switch (recv->kind) {
case SPL_LANG_TYPE_ARRAY: {
spl_type_node_t *arr = spl_type_node(a->sema->type, recv->ir_type_id);
if (!arr)
return 0;
return spl_ir_builder_type_const_int(a->ir, usize_ir, arr->array_type.len);
}
case SPL_LANG_TYPE_SLICE: {
spl_ir_node_ref_t slice_val = emit_expr(a, n->field.obj);
if (!slice_val)
return 0;
return spl_ir_builder_agg_extract(a->ir, usize_ir, usize_ir, SPL_SLICE_LEN_FIELD_IDX,
slice_val);
}
default:
return 0;
}
}
static spl_ir_node_ref_t emit_lvalue(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
spl_ast_node_t *n = spl_ast_node(a->sema->ast, ref);
if (!n)
@@ -55,6 +119,8 @@ static spl_ir_node_ref_t emit_lvalue(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
spl_lang_type_node_t *obj_ln = spl_lang_type_node(a->sema->type, obj_lang);
if (!obj_ln)
return 0;
if (spl_intrin_lookup_field(obj_ln->kind, n->field.field) != SPL_INTRIN_NONE)
return 0; /* 内建字段不是左值 */
spl_ir_node_ref_t base = 0;
spl_lang_type_id_t agg_lang = 0;
@@ -97,9 +163,20 @@ static spl_ir_node_ref_t emit_lvalue(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
if (obj_ln->kind == SPL_LANG_TYPE_PTR) {
base = emit_expr(a, n->index.obj);
elem_lang = obj_ln->extra.elem;
} else if (obj_ln->kind == SPL_LANG_TYPE_ARRAY || obj_ln->kind == SPL_LANG_TYPE_SLICE) {
} else if (obj_ln->kind == SPL_LANG_TYPE_ARRAY) {
base = emit_lvalue(a, n->index.obj);
elem_lang = obj_ln->extra.elem;
} else if (obj_ln->kind == SPL_LANG_TYPE_SLICE) {
/* 切片:取出切片值,再 agg_extract 出 ptr 字段 */
spl_ir_node_ref_t slice_val = emit_expr(a, n->index.obj);
if (!slice_val)
return 0;
spl_lang_type_id_t elem = obj_ln->extra.elem;
spl_type_id_t ptr_ir = spl_type_builder_ptr(a->sema->type, to_ir_type(a, elem));
spl_ir_node_ref_t ptr = spl_ir_builder_agg_extract(a->ir, ptr_ir, ptr_ir,
SPL_SLICE_PTR_FIELD_IDX, slice_val);
base = ptr;
elem_lang = elem;
} else {
return 0;
}
@@ -315,6 +392,13 @@ static spl_ir_node_ref_t emit_expr(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
}
}
case SPL_AST_EXPR_CALL: {
spl_ast_node_t *callee = spl_ast_node(a->sema->ast, n->call.callee);
if (callee && callee->kind == SPL_AST_EXPR_IDENT) {
spl_intrin_t in = spl_intrin_lookup_call(callee->ident.name);
if (in != SPL_INTRIN_NONE)
return ast2ir_intrin_call(a, n, in);
}
spl_ir_node_ref_t fn = emit_expr(a, n->call.callee);
if (!fn)
return 0;
@@ -331,6 +415,14 @@ static spl_ir_node_ref_t emit_expr(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
return call;
}
case SPL_AST_EXPR_FIELD: {
spl_ast_node_t *obj = spl_ast_node(a->sema->ast, n->field.obj);
spl_lang_type_id_t obj_lang = node_lang(a, obj);
spl_lang_type_node_t *obj_ln = spl_lang_type_node(a->sema->type, obj_lang);
if (obj_ln) {
spl_intrin_t in = spl_intrin_lookup_field(obj_ln->kind, n->field.field);
if (in != SPL_INTRIN_NONE)
return ast2ir_intrin_field(a, n, in);
}
spl_ir_node_ref_t ptr = emit_lvalue(a, ref);
if (!ptr)
return 0;
@@ -436,7 +528,56 @@ static spl_ir_node_ref_t emit_expr(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
emit_stmt(a, ref);
return 0;
}
case SPL_AST_EXPR_SLICE: {
spl_ast_node_t *obj = spl_ast_node(a->sema->ast, n->slice.obj);
spl_lang_type_id_t obj_lang = node_lang(a, obj);
spl_lang_type_node_t *obj_ln = spl_lang_type_node(a->sema->type, obj_lang);
if (!obj_ln)
return 0;
/* 目前只处理数组->切片的完整形式 arr[..](无 begin / end)
或 arr[begin..end] 的通用形式。简化实现只做完整切片。 */
spl_type_id_t slice_ir = node_ir(a, n); /* struct{ptr, len} */
if (!slice_ir)
return 0;
spl_ir_node_ref_t node = spl_ir_builder_agg_construct(a->ir, slice_ir);
if (!node)
return 0;
/* 取数组元素指针 */
spl_ir_node_ref_t base = emit_lvalue(a, n->slice.obj);
if (!base)
return 0;
spl_type_id_t ptr_ir =
spl_type_builder_ptr(a->sema->type, to_ir_type(a, obj_ln->extra.elem));
/* 字段 0:ptr */
spl_ir_builder_agg_construct_field(a->ir, node, base);
/* 字段 1:len —— 数组取 len,切片取原切片 len */
spl_ir_node_ref_t len = 0;
if (obj_ln->kind == SPL_LANG_TYPE_ARRAY) {
spl_type_node_t *arr = spl_type_node(a->sema->type, obj_ln->ir_type_id);
spl_lang_type_id_t usize = spl_lang_make_int(a->sema->type, sizeof(void *) * 8, 0);
len = spl_ir_builder_type_const_int(a->ir, to_ir_type(a, usize), arr->array_type.len);
} else if (obj_ln->kind == SPL_LANG_TYPE_SLICE) {
spl_ir_node_ref_t slice_val = emit_expr(a, n->slice.obj);
spl_lang_type_id_t usize = spl_lang_make_int(a->sema->type, sizeof(void *) * 8, 0);
len = spl_ir_builder_agg_extract(a->ir, to_ir_type(a, usize), to_ir_type(a, usize),
SPL_SLICE_LEN_FIELD_IDX, slice_val);
} else {
return 0;
}
spl_ir_builder_agg_construct_field(a->ir, node, len);
return node;
}
case SPL_AST_EXPR_COMPTIME_CALL:
// TODO
return 0;
default:
TODO();
return 0;
}
}
@@ -449,18 +590,15 @@ static void emit_stmt(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
switch (n->kind) {
case SPL_AST_STATEMENT_RET: {
while (vec_size(a->defer_stack) > 0) {
spl_ast_node_ref_t d = vec_at(a->defer_stack, vec_size(a->defer_stack) - 1);
vec_pop(a->defer_stack);
spl_ast_node_ref_t d = vec_pop(a->defer_stack);
emit_stmt(a, d);
}
spl_type_id_t ret_ir = to_ir_type(a, a->cur_ret_lang);
if (n->statement_ret.expr) {
spl_ast_node_t *en = spl_ast_node(a->sema->ast, n->statement_ret.expr);
spl_ir_node_ref_t v = emit_expr(a, n->statement_ret.expr);
spl_type_id_t t = node_ir(a, en);
spl_ir_builder_control_ret(a->ir, t, v);
spl_ir_builder_control_ret(a->ir, ret_ir, v);
} else {
spl_lang_type_id_t rt = a->sema->current_fn_ret_tid;
spl_ir_builder_control_ret(a->ir, to_ir_type(a, rt), 0);
spl_ir_builder_control_ret(a->ir, ret_ir, 0);
}
return;
}
@@ -722,6 +860,9 @@ static void emit_fn(spl_ast2ir_t *a, spl_ast_node_t *n) {
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);
spl_lang_type_id_t saved_ret = a->cur_ret_lang;
a->cur_ret_lang = fn_ln->extra.fn.ret;
usize defer_base = vec_size(a->defer_stack);
usize loop_base = vec_size(a->loop_stack);
@@ -753,7 +894,6 @@ static void emit_fn(spl_ast2ir_t *a, spl_ast_node_t *n) {
emit_expr(a, n->fn_decl.body);
if (!a->ir->terminated) {
/* 隐式返回路径:先跑 defer(LIFO),再 ret/unreachable */
while (vec_size(a->defer_stack) > defer_base) {
spl_ast_node_ref_t d = vec_pop(a->defer_stack);
emit_stmt(a, d);
@@ -783,6 +923,8 @@ static void emit_fn(spl_ast2ir_t *a, spl_ast_node_t *n) {
vec_pop(a->loop_stack);
}
a->cur_ret_lang = saved_ret;
spl_ir_builder_block_end(a->ir);
spl_ir_builder_fn_end(a->ir);
}
@@ -827,6 +969,7 @@ void spl_ast2ir_init(spl_ast2ir_t *ast2ir, spl_ir_builder_t *ir, const spl_sema_
vec_init(ast2ir->loop_stack);
vec_init(ast2ir->defer_stack);
ast2ir->err_count = 0;
ast2ir->cur_ret_lang = 0;
}
void spl_ast2ir_drop(spl_ast2ir_t *ast2ir) {
@@ -845,4 +988,4 @@ void spl_ast2ir_run(spl_ast2ir_t *ast2ir) {
if (!root || root->kind != SPL_AST_ROOT)
return;
emit_container(ast2ir, root->root.members);
}
}