stage0 新增内存复制指令 重构vm交互
This commit is contained in:
1 parent
0b8f649818
commit
40cffa9cb5
22 files changed
+626
-158
No files matched your search
+128
-13
@@ -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;
|
||||
|
||||
Reference in new issue
Block a user