stage0 新增内存复制指令 重构vm交互

This commit is contained in:
zzy committed 2026-09-29 21:11:15 +08:00
1 parent 0b8f649818
commit 40cffa9cb5
22 files changed
+626 -158

No files matched your search

+128 -13
View File
@@ -279,14 +279,77 @@ fn variant_at(v: Vec, idx: usize): usize {
// ---- 模式绑定 ----
fn emit_pattern_bind(self: *Ast2Ir, pat_ref: usize, src_ptr: usize, tid: usize) {
fn pattern_has_ref(self: *Ast2Ir, pat_ref: usize): bool {
if pat_ref == 0 { ret false; }
var pat = Ast.node(self.ast, pat_ref);
if pat == null { ret false; }
match pat.body {
.PatternRef(_) => { ret true; },
.PatternList(x) => {
var i: usize = 0;
while i < x.items.len {
if pattern_has_ref(self, list_at(x.items, i)) { ret true; }
i = i + 1;
}
ret false;
},
.PatternTuple(x) => {
var i: usize = 0;
while i < x.items.len {
if pattern_has_ref(self, list_at(x.items, i)) { ret true; }
i = i + 1;
}
ret false;
},
.PatternDot(x) => { ret pattern_has_ref(self, x.sub_pattern); },
.PatternAggregate(x) => {
var i: usize = 0;
while i < x.items.len {
var f = Ast.node(self.ast, list_at(x.items, i));
if f != null {
match f.body {
.PatternField(pf) => {
if pattern_has_ref(self, pf.pattern) { ret true; }
},
_ => {},
}
}
i = i + 1;
}
ret false;
},
_ => { ret false; },
}
ret false;
}
fn emit_pattern_bind(self: *Ast2Ir, pat_ref: usize, src_ptr: usize, tid: usize, place_mode: bool) {
if pat_ref == 0 || src_ptr == 0 { ret; }
var pat = Ast.node(self.ast, pat_ref);
if pat == null { ret; }
match pat.body {
.PatternIdent(x) => {
if pat.resolved_def_id != 0 { ir_map_put(self, pat.resolved_def_id, src_ptr); }
if pat.resolved_def_id != 0 {
if place_mode {
var slot = IrBuilder.mem_alloca(self.ir, tid, const_usize(self, 1));
var v = IrBuilder.mem_load(self.ir, tid, src_ptr);
ignore_usize(IrBuilder.mem_store(self.ir, tid, slot, v));
ir_map_put(self, pat.resolved_def_id, slot);
} else {
ir_map_put(self, pat.resolved_def_id, src_ptr);
}
}
ret;
},
.PatternRef(x) => {
var in = Ast.node(self.ast, x.pat);
var ptr_tid: usize = 0;
if in != null { ptr_tid = node_ir(self, in); }
if ptr_tid == 0 { ptr_tid = TypeTable.make_ptr(&self.sema.types.ir, tid); }
var slot = IrBuilder.mem_alloca(self.ir, ptr_tid, const_usize(self, 1));
ignore_usize(IrBuilder.mem_store(self.ir, ptr_tid, slot, src_ptr));
emit_pattern_bind(self, x.pat, slot, ptr_tid, false);
ret;
},
.ExprIntLit(x) => { ret; },
@@ -299,7 +362,7 @@ fn emit_pattern_bind(self: *Ast2Ir, pat_ref: usize, src_ptr: usize, tid: usize)
.PatternList(x) => {
var i: usize = 0;
while i < x.items.len {
emit_pattern_bind(self, list_at(x.items, i), src_ptr, tid);
emit_pattern_bind(self, list_at(x.items, i), src_ptr, tid, place_mode);
i = i + 1;
}
ret;
@@ -316,7 +379,7 @@ fn emit_pattern_bind(self: *Ast2Ir, pat_ref: usize, src_ptr: usize, tid: usize)
while i < n {
var ft = variant_at(variants, i);
var fp = IrBuilder.mem_field(self.ir, tid, src_ptr, i);
emit_pattern_bind(self, list_at(x.items, i), fp, ft);
emit_pattern_bind(self, list_at(x.items, i), fp, ft, place_mode);
i = i + 1;
}
ret;
@@ -333,7 +396,7 @@ fn emit_pattern_bind(self: *Ast2Ir, pat_ref: usize, src_ptr: usize, tid: usize)
var payload_ir = variant_at(variants, vidx);
var pptr = IrBuilder.mem_field(self.ir, tid, src_ptr, vidx + 1);
if x.sub_pattern != 0 {
emit_pattern_bind(self, x.sub_pattern, pptr, payload_ir);
emit_pattern_bind(self, x.sub_pattern, pptr, payload_ir, place_mode);
}
ret;
},
@@ -357,7 +420,7 @@ fn emit_pattern_bind(self: *Ast2Ir, pat_ref: usize, src_ptr: usize, tid: usize)
var ft = variant_at(variants, idx);
var fp = IrBuilder.mem_field(self.ir, tid, src_ptr, idx);
if pf.pattern != 0 {
emit_pattern_bind(self, pf.pattern, fp, ft);
emit_pattern_bind(self, pf.pattern, fp, ft, place_mode);
}
}
},
@@ -429,7 +492,6 @@ fn match_check_literal(self: *Ast2Ir, pat_ref: usize, scrut_ir: usize, scrut_slo
fn emit_var_decl(self: *Ast2Ir, n: *Node): usize {
var var_ir = node_ir(self, n);
if var_ir == 0 { ret 0; }
var slot = IrBuilder.mem_alloca(self.ir, var_ir, const_usize(self, 1));
var iref: usize = 0;
var pat_ref: usize = 0;
@@ -438,11 +500,35 @@ fn emit_var_decl(self: *Ast2Ir, n: *Node): usize {
.ConstDecl(x) => { iref = x.init_expr; pat_ref = x.pattern; },
_ => {},
}
if pattern_has_ref(self, pat_ref) {
if iref == 0 {
Diag.err(self.diag, n.span, .NoLvalue,
"reference binding requires an initialized place");
ret 0;
}
var place = emit_lvalue(self, iref);
if place == 0 {
var in = Ast.node(self.ast, iref);
if in != null {
Diag.err(self.diag, in.span, .NoLvalue,
"cannot bind by reference: initializer is not an lvalue");
} else {
Diag.err(self.diag, n.span, .NoLvalue,
"cannot bind by reference: initializer is not an lvalue");
}
ret 0;
}
emit_pattern_bind(self, pat_ref, place, var_ir, true);
ret place;
}
var slot = IrBuilder.mem_alloca(self.ir, var_ir, const_usize(self, 1));
if iref != 0 {
var v = emit_expr(self, iref);
if v != 0 { IrBuilder.mem_store(self.ir, var_ir, slot, v); }
}
emit_pattern_bind(self, pat_ref, slot, var_ir);
emit_pattern_bind(self, pat_ref, slot, var_ir, false);
ret slot;
}
@@ -1428,10 +1514,39 @@ fn emit_match(self: *Ast2Ir, n: *Node, matched_ref: usize, arms: Vec): usize {
var matched_lang = node_lang(matched_node);
var matched_ir = to_ir_type(self, matched_lang);
if matched_ir == 0 { ret 0; }
var scrut_slot = IrBuilder.mem_alloca(self.ir, matched_ir, const_usize(self, 1));
var scrut_val = emit_expr(self, matched_ref);
if scrut_val == 0 { ret 0; }
ignore_usize(IrBuilder.mem_store(self.ir, matched_ir, scrut_slot, scrut_val));
var matched_place_mode = false;
var scan: usize = 0;
while scan < arms.len && !matched_place_mode {
var sa = Ast.node(self.ast, list_at(arms, scan));
if sa != null {
var spat: usize = 0;
match sa.body { .MatchArm(ma) => { spat = ma.pattern; }, _ => {} }
if pattern_has_ref(self, spat) { matched_place_mode = true; }
}
scan = scan + 1;
}
var scrut_slot: usize = 0;
if matched_place_mode {
scrut_slot = emit_lvalue(self, matched_ref);
if scrut_slot == 0 {
var mn = Ast.node(self.ast, matched_ref);
if mn != null {
Diag.err(self.diag, mn.span, .NoLvalue,
"cannot bind by reference: matched value is not an lvalue");
} else {
Diag.err(self.diag, n.span, .NoLvalue,
"cannot bind by reference: matched value is not an lvalue");
}
ret 0;
}
} else {
scrut_slot = IrBuilder.mem_alloca(self.ir, matched_ir, const_usize(self, 1));
var scrut_val = emit_expr(self, matched_ref);
if scrut_val == 0 { ret 0; }
ignore_usize(IrBuilder.mem_store(self.ir, matched_ir, scrut_slot, scrut_val));
}
var narms = arms.len;
var arm_branches = Vec.blank(@sizeof(usize), @alignof(usize));
@@ -1469,7 +1584,7 @@ fn emit_match(self: *Ast2Ir, n: *Node, matched_ref: usize, arms: Vec): usize {
var pat: usize = 0;
var body: usize = 0;
match arm.body { .MatchArm(ma) => { pat = ma.pattern; body = ma.body; }, _ => {} }
emit_pattern_bind(self, pat, scrut_slot, matched_ir);
emit_pattern_bind(self, pat, scrut_slot, matched_ir, matched_place_mode);
if body != 0 { ignore_usize(emit_expr(self, body)); }
}
var j: usize = 0;