stage0 新增内存复制指令 重构vm交互
This commit is contained in:
1 parent
0b8f649818
commit
40cffa9cb5
22 files changed
+626
-158
No files matched your search
+119
-17
@@ -51,7 +51,8 @@ static void emit_deferred_until(spl_ast2ir_t *a, usize base) {
|
||||
static void emit_decl(spl_ast2ir_t *a, spl_ast_node_ref_t ref);
|
||||
static spl_ir_node_ref_t emit_var_decl(spl_ast2ir_t *a, spl_ast_node_t *n);
|
||||
static void emit_pattern_bind(spl_ast2ir_t *a, spl_ast_node_ref_t pat_ref,
|
||||
spl_ir_node_ref_t src_ptr, spl_type_id_t tid);
|
||||
spl_ir_node_ref_t src_ptr, spl_type_id_t tid, int place_mode);
|
||||
static int pattern_has_ref(spl_ast2ir_t *a, spl_ast_node_ref_t pat_ref);
|
||||
static spl_ir_node_ref_t emit_match_check(spl_ast2ir_t *a, spl_ast_node_ref_t pat_ref,
|
||||
spl_type_id_t scrut_ir, spl_ir_node_ref_t scrut_slot);
|
||||
|
||||
@@ -140,14 +141,52 @@ static spl_ir_node_ref_t emit_zero_value(spl_ast2ir_t *a, spl_type_id_t tid) {
|
||||
}
|
||||
}
|
||||
|
||||
/* 判断 pattern 是否包含 `&` 引用绑定(PATTERN_REF)。 */
|
||||
static int pattern_has_ref(spl_ast2ir_t *a, spl_ast_node_ref_t pat_ref) {
|
||||
if (!pat_ref)
|
||||
return 0;
|
||||
spl_ast_node_t *pat = spl_ast_node(a->ast, pat_ref);
|
||||
if (!pat)
|
||||
return 0;
|
||||
switch (pat->kind) {
|
||||
case SPL_AST_PATTERN_REF:
|
||||
return 1;
|
||||
case SPL_AST_PATTERN_LIST:
|
||||
for (usize i = 0; i < vec_size(pat->pattern_list.patterns); ++i)
|
||||
if (pattern_has_ref(a, vec_at(pat->pattern_list.patterns, i)))
|
||||
return 1;
|
||||
return 0;
|
||||
case SPL_AST_PATTERN_TUPLE:
|
||||
for (usize i = 0; i < vec_size(pat->pattern_tuple.patterns); ++i)
|
||||
if (pattern_has_ref(a, vec_at(pat->pattern_tuple.patterns, i)))
|
||||
return 1;
|
||||
return 0;
|
||||
case SPL_AST_PATTERN_DOT:
|
||||
return pattern_has_ref(a, pat->pattern_dot.sub_pattern);
|
||||
case SPL_AST_PATTERN_AGGREGATE:
|
||||
for (usize i = 0; i < vec_size(pat->pattern_aggregate.fields); ++i) {
|
||||
spl_ast_node_t *f =
|
||||
spl_ast_node(a->ast, vec_at(pat->pattern_aggregate.fields, i));
|
||||
if (f && f->kind == SPL_AST_PATTERN_FIELD &&
|
||||
pattern_has_ref(a, f->pattern_field.pattern))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* 把 pattern 里的 ident 绑到 src_ptr 指向内存的对应位置。
|
||||
- PATTERN_IDENT: def2ir_map[def_id] = src_ptr
|
||||
- PATTERN_IDENT: def2ir_map[def_id] = src_ptr(place_mode=0,值绑定别名源);
|
||||
place_mode=1 时强制拷贝到新 slot(源为真实左值,值绑定必须拷贝)。
|
||||
- PATTERN_REF: src_ptr 是该子位置的地址;分配 *T slot 存该地址,内层名绑到 slot。
|
||||
- PATTERN_DOT: src_ptr 指向 enum,payload 在 mem_field(tid, src_ptr, vidx+1)
|
||||
- PATTERN_TUPLE / PATTERN_AGGREGATE: 递归 mem_field
|
||||
UB 语义:不做 tag 检查,调用者保证变体正确。
|
||||
*/
|
||||
static void emit_pattern_bind(spl_ast2ir_t *a, spl_ast_node_ref_t pat_ref,
|
||||
spl_ir_node_ref_t src_ptr, spl_type_id_t tid) {
|
||||
spl_ir_node_ref_t src_ptr, spl_type_id_t tid, int place_mode) {
|
||||
if (!pat_ref || !src_ptr)
|
||||
return;
|
||||
spl_ast_node_t *pat = spl_ast_node(a->ast, pat_ref);
|
||||
@@ -156,8 +195,30 @@ static void emit_pattern_bind(spl_ast2ir_t *a, spl_ast_node_ref_t pat_ref,
|
||||
|
||||
switch (pat->kind) {
|
||||
case SPL_AST_PATTERN_IDENT: {
|
||||
if (pat->resolved_def_id)
|
||||
if (!pat->resolved_def_id)
|
||||
return;
|
||||
if (place_mode) {
|
||||
spl_ir_node_ref_t slot =
|
||||
spl_ir_builder_mem_alloca(a->ir, tid, const_usize(a, 1));
|
||||
spl_ir_node_ref_t v = spl_ir_builder_mem_load(a->ir, tid, src_ptr);
|
||||
spl_ir_builder_mem_store(a->ir, tid, slot, v);
|
||||
map_put(a->def2ir_map, pat->resolved_def_id, slot);
|
||||
} else {
|
||||
map_put(a->def2ir_map, pat->resolved_def_id, src_ptr);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case SPL_AST_PATTERN_REF: {
|
||||
spl_ast_node_ref_t inner = pat->pattern_ref.pat;
|
||||
spl_ast_node_t *in = spl_ast_node(a->ast, inner);
|
||||
spl_type_id_t ptr_tid = in ? node_ir(a, in) : 0;
|
||||
if (!ptr_tid)
|
||||
ptr_tid = spl_type_builder_ptr(&a->sema->type->ir, tid);
|
||||
spl_ir_node_ref_t slot =
|
||||
spl_ir_builder_mem_alloca(a->ir, ptr_tid, const_usize(a, 1));
|
||||
spl_ir_builder_mem_store(a->ir, ptr_tid, slot, src_ptr);
|
||||
emit_pattern_bind(a, inner, slot, ptr_tid, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -174,7 +235,7 @@ static void emit_pattern_bind(spl_ast2ir_t *a, spl_ast_node_ref_t pat_ref,
|
||||
|
||||
case SPL_AST_PATTERN_LIST:
|
||||
for (usize i = 0; i < vec_size(pat->pattern_list.patterns); ++i)
|
||||
emit_pattern_bind(a, vec_at(pat->pattern_list.patterns, i), src_ptr, tid);
|
||||
emit_pattern_bind(a, vec_at(pat->pattern_list.patterns, i), src_ptr, tid, place_mode);
|
||||
return;
|
||||
|
||||
case SPL_AST_PATTERN_TUPLE: {
|
||||
@@ -188,7 +249,7 @@ static void emit_pattern_bind(spl_ast2ir_t *a, spl_ast_node_ref_t pat_ref,
|
||||
for (usize i = 0; i < n; ++i) {
|
||||
spl_type_id_t ft = vec_at(tn->agg_type.variants, i).type_id;
|
||||
spl_ir_node_ref_t fp = spl_ir_builder_mem_field(a->ir, tid, src_ptr, i);
|
||||
emit_pattern_bind(a, vec_at(pat->pattern_tuple.patterns, i), fp, ft);
|
||||
emit_pattern_bind(a, vec_at(pat->pattern_tuple.patterns, i), fp, ft, place_mode);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -206,7 +267,7 @@ static void emit_pattern_bind(spl_ast2ir_t *a, spl_ast_node_ref_t pat_ref,
|
||||
spl_type_id_t payload_ir = vec_at(tn->agg_type.variants, vidx).type_id;
|
||||
spl_ir_node_ref_t pptr = spl_ir_builder_mem_field(a->ir, tid, src_ptr, vidx + 1);
|
||||
if (pat->pattern_dot.sub_pattern)
|
||||
emit_pattern_bind(a, pat->pattern_dot.sub_pattern, pptr, payload_ir);
|
||||
emit_pattern_bind(a, pat->pattern_dot.sub_pattern, pptr, payload_ir, place_mode);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -224,7 +285,7 @@ static void emit_pattern_bind(spl_ast2ir_t *a, spl_ast_node_ref_t pat_ref,
|
||||
spl_type_id_t ft = vec_at(tn->agg_type.variants, idx).type_id;
|
||||
spl_ir_node_ref_t fp = spl_ir_builder_mem_field(a->ir, tid, src_ptr, idx);
|
||||
if (f->pattern_field.pattern)
|
||||
emit_pattern_bind(a, f->pattern_field.pattern, fp, ft);
|
||||
emit_pattern_bind(a, f->pattern_field.pattern, fp, ft, place_mode);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -297,12 +358,32 @@ static spl_ir_node_ref_t emit_match_check(spl_ast2ir_t *a, spl_ast_node_ref_t pa
|
||||
}
|
||||
|
||||
/* 分配 slot → store init 值 → bind pattern。
|
||||
返回指向变量内存的指针(*tid),调用者可用于读取初值。 */
|
||||
返回指向变量内存的指针(*tid),调用者可用于读取初值。
|
||||
若 pattern 含 `&` 引用绑定:源必须是可寻址左值,直接在源 place 上绑定
|
||||
(值绑定拷贝子值,引用绑定取子位置地址),返回该 place。 */
|
||||
static spl_ir_node_ref_t emit_var_decl(spl_ast2ir_t *a, spl_ast_node_t *n) {
|
||||
spl_type_id_t var_ir = node_ir(a, n);
|
||||
if (!var_ir)
|
||||
return 0;
|
||||
|
||||
spl_ast_node_ref_t pat_ref = n->var_const_decl.pattern;
|
||||
if (pattern_has_ref(a, pat_ref)) {
|
||||
if (!n->var_const_decl.init_expr) {
|
||||
spl_diag_error(a->diag, SPL_DIAG_KIND_NO_LVALUE, &n->dbg,
|
||||
"reference binding requires an initialized place");
|
||||
return 0;
|
||||
}
|
||||
spl_ir_node_ref_t place = emit_lvalue(a, n->var_const_decl.init_expr);
|
||||
if (!place) {
|
||||
spl_ast_node_t *in = spl_ast_node(a->ast, n->var_const_decl.init_expr);
|
||||
spl_diag_error(a->diag, SPL_DIAG_KIND_NO_LVALUE, in ? &in->dbg : &n->dbg,
|
||||
"cannot bind by reference: initializer is not an lvalue");
|
||||
return 0;
|
||||
}
|
||||
emit_pattern_bind(a, pat_ref, place, var_ir, 1);
|
||||
return place;
|
||||
}
|
||||
|
||||
spl_ir_node_ref_t slot = spl_ir_builder_mem_alloca(a->ir, var_ir, const_usize(a, 1));
|
||||
|
||||
if (n->var_const_decl.init_expr) {
|
||||
@@ -311,7 +392,7 @@ static spl_ir_node_ref_t emit_var_decl(spl_ast2ir_t *a, spl_ast_node_t *n) {
|
||||
spl_ir_builder_mem_store(a->ir, var_ir, slot, v);
|
||||
}
|
||||
|
||||
emit_pattern_bind(a, n->var_const_decl.pattern, slot, var_ir);
|
||||
emit_pattern_bind(a, pat_ref, slot, var_ir, 0);
|
||||
return slot;
|
||||
}
|
||||
|
||||
@@ -1396,12 +1477,32 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
|
||||
if (!matched_ir)
|
||||
return 0;
|
||||
|
||||
spl_ir_node_ref_t scrut_slot =
|
||||
spl_ir_builder_mem_alloca(a->ir, matched_ir, const_usize(a, 1));
|
||||
spl_ir_node_ref_t scrut_val = emit_expr(a, matched_ref);
|
||||
if (!scrut_val)
|
||||
return 0;
|
||||
spl_ir_builder_mem_store(a->ir, matched_ir, scrut_slot, scrut_val);
|
||||
spl_ir_node_ref_t scrut_slot = 0;
|
||||
int matched_place_mode = 0;
|
||||
for (usize i = 0; i < vec_size(n->match_expr.arms); ++i) {
|
||||
spl_ast_node_t *arm = spl_ast_node(a->ast, vec_at(n->match_expr.arms, i));
|
||||
if (arm && arm->kind == SPL_AST_MATCH_ARM &&
|
||||
pattern_has_ref(a, arm->match_arm.pattern)) {
|
||||
matched_place_mode = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (matched_place_mode) {
|
||||
scrut_slot = emit_lvalue(a, matched_ref);
|
||||
if (!scrut_slot) {
|
||||
spl_diag_error(a->diag, SPL_DIAG_KIND_NO_LVALUE,
|
||||
matched_node ? &matched_node->dbg : &n->dbg,
|
||||
"cannot bind by reference: matched value is not an lvalue");
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
scrut_slot = spl_ir_builder_mem_alloca(a->ir, matched_ir, const_usize(a, 1));
|
||||
spl_ir_node_ref_t scrut_val = emit_expr(a, matched_ref);
|
||||
if (!scrut_val)
|
||||
return 0;
|
||||
spl_ir_builder_mem_store(a->ir, matched_ir, scrut_slot, scrut_val);
|
||||
}
|
||||
|
||||
usize narms = vec_size(n->match_expr.arms);
|
||||
spl_ir_node_ref_vec_t arm_branches;
|
||||
@@ -1448,7 +1549,8 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
|
||||
|
||||
spl_ast_node_t *arm = spl_ast_node(a->ast, vec_at(n->match_expr.arms, i));
|
||||
if (arm && arm->kind == SPL_AST_MATCH_ARM) {
|
||||
emit_pattern_bind(a, arm->match_arm.pattern, scrut_slot, matched_ir);
|
||||
emit_pattern_bind(a, arm->match_arm.pattern, scrut_slot, matched_ir,
|
||||
matched_place_mode);
|
||||
if (arm->match_arm.body)
|
||||
emit_expr(a, arm->match_arm.body);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user