stage1 支持tuple 修复悬垂指针问题

This commit is contained in:
zzy committed 2026-09-14 19:01:33 +08:00
1 parent a621e34d51
commit 3175e04e6e
2 files changed
+158 -58

No files matched your search

+108 -43
View File
@@ -44,7 +44,8 @@ static spl_ir_node_ref_t emit_zero_value(spl_ast2ir_t *a, spl_type_id_t tid) {
spl_type_node_t *tn = spl_type_node(a->sema->type, tid);
if (!tn)
return 0;
switch (tn->kind) {
spl_type_node_kind_t tk = tn->kind;
switch (tk) {
case SPL_TYPE_BOOL:
return spl_ir_builder_type_const_bool(a->ir, tid, false);
case SPL_TYPE_INT:
@@ -55,9 +56,11 @@ static spl_ir_node_ref_t emit_zero_value(spl_ast2ir_t *a, spl_type_id_t tid) {
case SPL_TYPE_FN:
return spl_ir_builder_type_const_ptr(a->ir, tid, NULL);
case SPL_TYPE_ARRAY: {
usize arr_len = tn->array_type.len;
spl_type_id_t arr_elem = tn->array_type.element;
spl_ir_node_ref_t node = spl_ir_builder_agg_construct(a->ir, tid);
for (usize i = 0; i < tn->array_type.len; ++i) {
spl_ir_node_ref_t f = emit_zero_value(a, tn->array_type.element);
for (usize i = 0; i < arr_len; ++i) {
spl_ir_node_ref_t f = emit_zero_value(a, arr_elem);
if (!f)
return 0;
spl_ir_builder_agg_construct_field(a->ir, node, f);
@@ -66,20 +69,31 @@ static spl_ir_node_ref_t emit_zero_value(spl_ast2ir_t *a, spl_type_id_t tid) {
}
case SPL_TYPE_STRUCT:
case SPL_TYPE_SHAPE: {
usize nfield = vec_size(tn->agg_type.variants);
spl_type_id_vec_t field_tids;
vec_init(field_tids);
for (usize i = 0; i < nfield; ++i)
vec_push(field_tids, vec_at(tn->agg_type.variants, i).type_id);
spl_ir_node_ref_t node = spl_ir_builder_agg_construct(a->ir, tid);
for (usize i = 0; i < vec_size(tn->agg_type.variants); ++i) {
spl_ir_node_ref_t f = emit_zero_value(a, vec_at(tn->agg_type.variants, i).type_id);
if (!f)
for (usize i = 0; i < nfield; ++i) {
spl_ir_node_ref_t f = emit_zero_value(a, vec_at(field_tids, i));
if (!f) {
vec_free(field_tids);
return 0;
}
spl_ir_builder_agg_construct_field(a->ir, node, f);
}
vec_free(field_tids);
return node;
}
case SPL_TYPE_UNION: {
usize nfield = vec_size(tn->agg_type.variants);
if (nfield == 0)
return spl_ir_builder_agg_construct(a->ir, tid);
spl_type_id_t first_tid = vec_at(tn->agg_type.variants, 0).type_id;
spl_ir_node_ref_t node = spl_ir_builder_agg_construct(a->ir, tid);
if (vec_size(tn->agg_type.variants) == 0)
return node;
spl_ir_node_ref_t f = emit_zero_value(a, vec_at(tn->agg_type.variants, 0).type_id);
spl_ir_node_ref_t f = emit_zero_value(a, first_tid);
if (!f)
return 0;
spl_ir_builder_agg_construct_field(a->ir, node, f);
@@ -89,7 +103,6 @@ static spl_ir_node_ref_t emit_zero_value(spl_ast2ir_t *a, spl_type_id_t tid) {
return 0;
}
}
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;
@@ -234,14 +247,17 @@ 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)
spl_lang_type_kind_t obj_kind = obj_ln->kind;
spl_lang_type_id_t obj_elem = (obj_kind == SPL_LANG_TYPE_PTR) ? obj_ln->extra.elem : 0;
if (spl_intrin_lookup_field(obj_kind, n->field.field) != SPL_INTRIN_NONE)
return 0; /* 内建字段不是左值 */
spl_ir_node_ref_t base = 0;
spl_lang_type_id_t agg_lang = 0;
if (obj_ln->kind == SPL_LANG_TYPE_PTR) {
if (obj_kind == SPL_LANG_TYPE_PTR) {
base = emit_expr(a, n->field.obj);
agg_lang = obj_ln->extra.elem;
agg_lang = obj_elem;
} else {
base = emit_lvalue(a, n->field.obj);
agg_lang = obj_lang;
@@ -272,25 +288,43 @@ static spl_ir_node_ref_t emit_lvalue(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
if (!obj_ln)
return 0;
spl_lang_type_kind_t obj_kind = obj_ln->kind;
spl_lang_type_id_t obj_elem = 0;
if (obj_kind == SPL_LANG_TYPE_PTR || obj_kind == SPL_LANG_TYPE_ARRAY ||
obj_kind == SPL_LANG_TYPE_SLICE)
obj_elem = obj_ln->extra.elem;
if (obj_kind == SPL_LANG_TYPE_TUPLE) {
spl_ast_node_t *idx_node = spl_ast_node(a->sema->ast, n->index.index);
if (!idx_node || idx_node->kind != SPL_AST_EXPR_INT_LIT)
return 0;
usize i = (usize)idx_node->int_lit.val;
spl_ir_node_ref_t base = emit_lvalue(a, n->index.obj);
if (!base)
return 0;
spl_type_id_t tuple_ir = to_ir_type(a, obj_lang);
if (!tuple_ir)
return 0;
return spl_ir_builder_mem_field(a->ir, tuple_ir, base, i);
}
spl_ir_node_ref_t base = 0;
spl_lang_type_id_t elem_lang = 0;
if (obj_ln->kind == SPL_LANG_TYPE_PTR) {
if (obj_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) {
elem_lang = obj_elem;
} else if (obj_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 字段 */
elem_lang = obj_elem;
} else if (obj_kind == SPL_LANG_TYPE_SLICE) {
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_type_id_t ptr_ir = spl_type_builder_ptr(a->sema->type, to_ir_type(a, obj_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;
elem_lang = obj_elem;
} else {
return 0;
}
@@ -673,7 +707,9 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
if (!tn)
Panic("aggregate type node missing");
if (tn->kind == SPL_TYPE_ENUM) {
spl_type_node_kind_t tn_kind = tn->kind;
if (tn_kind == SPL_TYPE_ENUM) {
if (vec_size(n->aggregate_literal.fields) != 1)
Panic("enum literal must have exactly one variant");
spl_ast_node_t *item =
@@ -686,25 +722,30 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
Panic("enum variant `%s` not found (sema should have caught this)",
item->struct_init_item.name);
spl_type_id_t tag_ir = tn->agg_type.tag_type;
spl_type_id_t payload_ir = vec_at(tn->agg_type.variants, vidx).type_id;
spl_ir_node_ref_t eptr = spl_ir_builder_mem_alloca(a->ir, t, const_usize(a, 1));
spl_type_id_t tag_ir = tn->agg_type.tag_type;
spl_ir_node_ref_t tptr =
spl_ir_builder_mem_field(a->ir, t, eptr, SPL_ENUM_TAG_FIELD_IDX);
spl_ir_node_ref_t tag_val = spl_ir_builder_type_const_int(a->ir, tag_ir, vidx);
spl_ir_builder_mem_store(a->ir, tag_ir, tptr, tag_val);
spl_type_id_t ftid = vec_at(tn->agg_type.variants, vidx).type_id;
spl_ir_node_ref_t pptr = spl_ir_builder_mem_field(a->ir, t, eptr, vidx + 1);
spl_ir_node_ref_t payload = emit_expr(a, item->struct_init_item.expr);
if (!payload)
Panic("enum payload emit failed");
spl_ir_builder_mem_store(a->ir, ftid, pptr, payload);
spl_ir_builder_mem_store(a->ir, payload_ir, pptr, payload);
return eptr;
}
usize nfields = vec_size(tn->agg_type.variants);
spl_type_id_vec_t field_tids;
vec_init(field_tids);
for (usize i = 0; i < nfields; ++i)
vec_push(field_tids, vec_at(tn->agg_type.variants, i).type_id);
spl_ir_node_ref_vec_t fields;
vec_init(fields);
@@ -730,24 +771,34 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
for (usize i = 0; i < nfields; ++i) {
if (!vec_at(fields, i)) {
spl_type_id_t ftid = vec_at(tn->agg_type.variants, i).type_id;
spl_ir_node_ref_t f = emit_zero_value(a, ftid);
if (!f)
spl_ir_node_ref_t f = emit_zero_value(a, vec_at(field_tids, i));
if (!f) {
vec_free(field_tids);
vec_free(fields);
Panic("cannot zero-init aggregate field #%zu", i);
}
vec_at(fields, i) = f;
}
}
spl_ir_node_ref_t node = spl_ir_builder_agg_construct(a->ir, t);
if (!node)
if (!node) {
vec_free(field_tids);
vec_free(fields);
Panic("agg_construct failed for aggregate literal");
}
for (usize i = 0; i < nfields; ++i) {
spl_ir_node_ref_t f = vec_at(fields, i);
if (!f)
if (!f) {
vec_free(field_tids);
vec_free(fields);
Panic("aggregate field #%zu missing (sema should have caught this)", i);
}
spl_ir_builder_agg_construct_field(a->ir, node, f);
}
vec_free(field_tids);
vec_free(fields);
return node;
}
@@ -772,11 +823,15 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
if (!obj_ln)
return 0;
spl_lang_type_kind_t obj_kind = obj_ln->kind;
spl_lang_type_id_t obj_elem = obj_ln->extra.elem;
spl_type_id_t obj_ir = obj_ln->ir_type_id;
spl_type_id_t slice_ir = node_ir(a, n);
if (!slice_ir)
return 0;
spl_lang_type_id_t elem_lang = obj_ln->extra.elem;
spl_lang_type_id_t elem_lang = obj_elem;
spl_type_id_t elem_ir = to_ir_type(a, elem_lang);
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);
@@ -800,13 +855,16 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
spl_ir_node_ref_t end_v = 0;
if (n->slice.end) {
end_v = emit_expr(a, n->slice.end);
} else if (obj_ln->kind == SPL_LANG_TYPE_ARRAY) {
spl_type_node_t *arr = spl_type_node(a->sema->type, obj_ln->ir_type_id);
end_v = spl_ir_builder_type_const_int(a->ir, usize_ir, arr->array_type.len);
} else if (obj_ln->kind == SPL_LANG_TYPE_SLICE) {
} else if (obj_kind == SPL_LANG_TYPE_ARRAY) {
spl_type_node_t *arr = spl_type_node(a->sema->type, obj_ir);
if (!arr)
return 0;
usize arr_len = arr->array_type.len;
end_v = spl_ir_builder_type_const_int(a->ir, usize_ir, arr_len);
} else if (obj_kind == SPL_LANG_TYPE_SLICE) {
spl_ir_node_ref_t slice_val = emit_expr(a, n->slice.obj);
end_v = spl_ir_builder_agg_extract(a->ir, obj_ln->ir_type_id, usize_ir,
SPL_SLICE_LEN_FIELD_IDX, slice_val);
end_v = spl_ir_builder_agg_extract(a->ir, obj_ir, usize_ir, SPL_SLICE_LEN_FIELD_IDX,
slice_val);
} else {
return 0;
}
@@ -1124,10 +1182,15 @@ static void emit_fn_body(spl_ast2ir_t *a, spl_ast_node_t *n) {
if (!fn_ln || fn_ln->kind != SPL_LANG_TYPE_FN)
return;
spl_lang_type_id_t ret_lang = fn_ln->extra.fn.ret;
spl_type_id_t ret_ir = to_ir_type(a, ret_lang);
spl_lang_type_node_t *ret_ln = spl_lang_type_node(a->sema->type, ret_lang);
int ret_is_unit = (ret_ln && ret_ln->kind == SPL_LANG_TYPE_UNIT) ? 1 : 0;
spl_ir_builder_fn_begin_at(a->ir, fn_ref);
spl_lang_type_id_t saved_ret = a->cur_ret_lang;
a->cur_ret_lang = fn_ln->extra.fn.ret;
a->cur_ret_lang = ret_lang;
usize defer_base = vec_size(a->defer_stack);
usize loop_base = vec_size(a->loop_stack);
@@ -1164,10 +1227,12 @@ static void emit_fn_body(spl_ast2ir_t *a, spl_ast_node_t *n) {
spl_ast_node_ref_t d = vec_pop(a->defer_stack);
emit_stmt(a, d);
}
spl_lang_type_id_t ret_lang = fn_ln->extra.fn.ret;
spl_lang_type_node_t *ret_ln = spl_lang_type_node(a->sema->type, ret_lang);
if (ret_ln && ret_ln->kind == SPL_LANG_TYPE_UNIT) {
spl_ir_builder_control_ret(a->ir, to_ir_type(a, ret_lang), 0);
if (ret_is_unit) {
spl_ir_builder_control_ret(a->ir, ret_ir, 0);
} else if (ret_ir) {
spl_ir_node_ref_t zero = emit_zero_value(a, ret_ir);
spl_ir_builder_control_ret(a->ir, ret_ir, zero);
} else {
spl_ir_builder_control_unreachable(a->ir);
}