stage1 实现更多ast2ir 修复bug 提供内置操作
This commit is contained in:
1 parent
ab6e99c958
commit
49ccdec3dd
10 files changed
+396
-76
No files matched your search
+154
-11
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user