stage2 修复大量AI生成的风格问题 stage1 修复对于vm abi的错误生成

This commit is contained in:
zzy committed 2026-10-03 15:05:55 +08:00
1 parent 0e38858785
commit 76f980654c
40 files changed
+619 -938

No files matched your search

+135 -158
View File
@@ -1,8 +1,7 @@
// Expect retcode = 0
// AST -> SIR(移植自 stage1/spl_ast2ir.c)。两遍:先 reserve 所有函数(拿稳定
// func ref),再发射函数体。def2ir_map 记录 def -> IR 槽位(变量=内存指针,
// 函数=func ref)。loop_stack/defer_stack 驱动 break/continue/ret 的收尾。
// AST -> IR。两遍:先 reserve 所有函数拿稳定 func ref,再发射函数体;def2ir_map
// 记录 def -> 槽位(变量=内存指针,函数=func ref)。
type .{ .Error } = @import("utils/error.spl");
type .{ .Vec } = @import("utils/vec.spl");
@@ -52,7 +51,6 @@ cur_defer_base: usize,
diag: *Diag,
owned: Vec, // ByteBuffer:为 dbg.panic 消息提供稳定存储
// ---- 小工具 ----
fn list_at(v: Vec, i: usize): usize {
if i >= v.len { ret 0; }
@@ -60,7 +58,7 @@ fn list_at(v: Vec, i: usize): usize {
}
fn push_u(v: *Vec, x: usize) {
match Vec.push(v, &x as *u8) { .Ok => {}, .Err(e) => {} }
Vec.push(v, &x as *u8);
}
fn irt(self: *Ast2Ir, id: usize): *TypeEntry {
@@ -103,7 +101,7 @@ fn ir_map_get(self: *Ast2Ir, def_id: usize, out: *usize): bool {
}
fn ir_map_put(self: *Ast2Ir, def_id: usize, val: usize) {
match Map.put(&self.def2ir_map, &def_id as *u8, &val as *u8) { .Ok => {}, .Err(e) => {} }
Map.put(&self.def2ir_map, &def_id as *u8, &val as *u8);
}
fn glob_get(self: *Ast2Ir, def_id: usize, out: *usize): bool {
@@ -115,7 +113,7 @@ fn glob_get(self: *Ast2Ir, def_id: usize, out: *usize): bool {
}
fn glob_put(self: *Ast2Ir, def_id: usize, val: usize) {
match Map.put(&self.glob_gidx, &def_id as *u8, &val as *u8) { .Ok => {}, .Err(e) => {} }
Map.put(&self.glob_gidx, &def_id as *u8, &val as *u8);
}
// 顶层 var/const → 模块全局(alloc 于静态存储;引用是 *T 指针常量)。
@@ -141,7 +139,7 @@ fn emit_global_var(self: *Ast2Ir, d: *Node) {
match inode.body {
.ExprIntLit(bi) => {
var v: u64 = 0;
match BigInt.to_u64(&v, bi.value) { .Ok => {}, .Err(e) => {} }
BigInt.to_u64(&v, bi.value);
var bits = LangType.int_bits(&self.sema.types, ir);
var size = bits / 8;
if size != 0 {
@@ -149,7 +147,7 @@ fn emit_global_var(self: *Ast2Ir, d: *Node) {
var i: usize = 0;
while i < size {
var b = ((v >> (8 * i)) & 255) as u8;
match Vec.push(&bytes, &b as *u8) { .Ok => {}, .Err(e) => {} }
Vec.push(&bytes, &b as *u8);
i = i + 1;
}
}
@@ -184,7 +182,7 @@ fn int_lit_u64(n: *Node): u64 {
match n.body {
.ExprIntLit(&x) => {
var out: u64 = 0;
match BigInt.to_u64(&out, x.value) { .Ok => {}, .Err(e) => {} }
BigInt.to_u64(&out, x.value);
ret out;
},
_ => {},
@@ -198,7 +196,6 @@ fn ir_kind_of(self: *Ast2Ir, ref: usize): IrKind {
ret e.kind;
}
// ---- 零值 ----
fn emit_zero_value(self: *Ast2Ir, tid: usize): usize {
var tn = irt(self, tid);
@@ -277,7 +274,6 @@ fn variant_at(v: Vec, idx: usize): usize {
ret m.type_id;
}
// ---- 模式绑定 ----
fn pattern_has_ref(self: *Ast2Ir, pat_ref: usize): bool {
if pat_ref == 0 { ret false; }
@@ -334,7 +330,7 @@ fn emit_pattern_bind(self: *Ast2Ir, pat_ref: usize, src_ptr: usize, tid: usize,
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));
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);
@@ -348,7 +344,7 @@ fn emit_pattern_bind(self: *Ast2Ir, pat_ref: usize, src_ptr: usize, tid: usize,
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));
IrBuilder.mem_store(self.ir, ptr_tid, slot, src_ptr);
emit_pattern_bind(self, x.pat, slot, ptr_tid, false);
ret;
},
@@ -539,7 +535,7 @@ fn copy_attrs_node(self: *Ast2Ir, n: *Node, ir_ref: usize) {
var i: usize = 0;
while i < n.attrs.len {
var a = list_at(n.attrs, i);
match Vec.push(&irn.attrs, &a as *u8) { .Ok => {}, .Err(e) => {} }
Vec.push(&irn.attrs, &a as *u8);
i = i + 1;
}
}
@@ -551,12 +547,11 @@ fn copy_attrs_func(self: *Ast2Ir, n: *Node, fn_ref: usize) {
var i: usize = 0;
while i < n.attrs.len {
var a = list_at(n.attrs, i);
match Vec.push(&irf.attrs, &a as *u8) { .Ok => {}, .Err(e) => {} }
Vec.push(&irf.attrs, &a as *u8);
i = i + 1;
}
}
// ---- intrinsic ----
fn ast2ir_intrin_cast(self: *Ast2Ir, n: *Node, in: Intrin, args: Vec): usize {
if args.len < 1 {
@@ -579,38 +574,39 @@ fn ast2ir_intrin_cast(self: *Ast2Ir, n: *Node, in: Intrin, args: Vec): usize {
}
fn ast2ir_intrin_call(self: *Ast2Ir, n: *Node, in: Intrin, args: Vec): usize {
if @enum2int(in) == @enum2int(Intrin.BitSizeof) {
var arg = Ast.node(self.ast, list_at(args, 0));
ret IrBuilder.type_bitsizeof(self.ir, node_ir(self, arg));
}
if @enum2int(in) == @enum2int(Intrin.Sizeof) {
var arg = Ast.node(self.ast, list_at(args, 0));
ret IrBuilder.type_sizeof(self.ir, node_ir(self, arg));
}
if @enum2int(in) == @enum2int(Intrin.Alignof) {
var arg = Ast.node(self.ast, list_at(args, 0));
ret IrBuilder.type_alignof(self.ir, node_ir(self, arg));
}
if @enum2int(in) == @enum2int(Intrin.Enum2Int) {
var src = Ast.node(self.ast, list_at(args, 0));
var v = emit_expr(self, list_at(args, 0));
if v == 0 { ret 0; }
var agg_t = node_ir(self, src);
var tag_t = node_ir(self, n);
if agg_t == 0 || tag_t == 0 { ret 0; }
ret IrBuilder.agg_extract(self.ir, agg_t, tag_t, 0, v);
}
if @enum2int(in) == @enum2int(Intrin.FieldCount) {
var arg = Ast.node(self.ast, list_at(args, 0));
ret IrBuilder.type_field_count(self.ir, node_ir(self, arg));
}
if @enum2int(in) == @enum2int(Intrin.OffsetOf) {
var arg = Ast.node(self.ast, list_at(args, 0));
var agg_t = node_ir(self, arg);
if agg_t == 0 { ret 0; }
var fnode = Ast.node(self.ast, list_at(args, 1));
var idx: usize = 0;
if fnode != null {
match in {
.BitSizeof => {
var arg = Ast.node(self.ast, list_at(args, 0));
ret IrBuilder.type_bitsizeof(self.ir, node_ir(self, arg));
},
.Sizeof => {
var arg = Ast.node(self.ast, list_at(args, 0));
ret IrBuilder.type_sizeof(self.ir, node_ir(self, arg));
},
.Alignof => {
var arg = Ast.node(self.ast, list_at(args, 0));
ret IrBuilder.type_alignof(self.ir, node_ir(self, arg));
},
.Enum2Int => {
var src = Ast.node(self.ast, list_at(args, 0));
var v = emit_expr(self, list_at(args, 0));
if v == 0 { ret 0; }
var agg_t = node_ir(self, src);
var tag_t = node_ir(self, n);
if agg_t == 0 || tag_t == 0 { ret 0; }
ret IrBuilder.agg_extract(self.ir, agg_t, tag_t, 0, v);
},
.FieldCount => {
var arg = Ast.node(self.ast, list_at(args, 0));
ret IrBuilder.type_field_count(self.ir, node_ir(self, arg));
},
.OffsetOf => {
var arg = Ast.node(self.ast, list_at(args, 0));
var agg_t = node_ir(self, arg);
if agg_t == 0 { ret 0; }
var fnode = Ast.node(self.ast, list_at(args, 1));
if fnode == null { ret 0; }
var idx: usize = 0;
match fnode.body {
.ExprIntLit(x) => { idx = int_lit_u64(fnode) as usize; },
.ExprIdent(e) => {
@@ -618,29 +614,16 @@ fn ast2ir_intrin_call(self: *Ast2Ir, n: *Node, in: Intrin, args: Vec): usize {
},
_ => { ret 0; },
}
} else {
ret 0;
}
var idx_node = const_usize(self, idx);
ret IrBuilder.type_offsetof(self.ir, agg_t, idx_node);
}
if @enum2int(in) == @enum2int(Intrin.Assert) {
ret ast2ir_intrin_assert(self, n, args);
}
if @enum2int(in) == @enum2int(Intrin.IntCast) ||
@enum2int(in) == @enum2int(Intrin.Truncate) ||
@enum2int(in) == @enum2int(Intrin.BitCast) ||
@enum2int(in) == @enum2int(Intrin.FloatCast) ||
@enum2int(in) == @enum2int(Intrin.Float2Int) ||
@enum2int(in) == @enum2int(Intrin.Int2Float) ||
@enum2int(in) == @enum2int(Intrin.Bool2Int) ||
@enum2int(in) == @enum2int(Intrin.Ptr2Int) ||
@enum2int(in) == @enum2int(Intrin.Int2Ptr) ||
@enum2int(in) == @enum2int(Intrin.PtrCast) {
ret ast2ir_intrin_cast(self, n, in, args);
}
if @enum2int(in) == @enum2int(Intrin.Breakpoint) {
ret IrBuilder.dbg_breakpoint(self.ir);
var idx_node = const_usize(self, idx);
ret IrBuilder.type_offsetof(self.ir, agg_t, idx_node);
},
.Assert => { ret ast2ir_intrin_assert(self, n, args); },
.IntCast, .Truncate, .BitCast, .FloatCast, .Float2Int, .Int2Float,
.Bool2Int, .Ptr2Int, .Int2Ptr, .PtrCast => {
ret ast2ir_intrin_cast(self, n, in, args);
},
.Breakpoint => { ret IrBuilder.dbg_breakpoint(self.ir); },
_ => { ret 0; },
}
ret 0;
}
@@ -665,22 +648,22 @@ fn ast2ir_intrin_assert(self: *Ast2Ir, n: *Node, args: Vec): usize {
if self.sema.sources != null && n.span.file != no_file() {
var src = set_at(self.sema.sources, n.span.file);
if src != null {
ignore_bool(append_bytes(&msg, ByteView.as_slice(src.fname)));
append_bytes(&msg, ByteView.as_slice(src.fname));
var pos = Source.line_col(src.*, n.span.start);
ignore_bool(append_bytes(&msg, ":"));
ignore_bool(append_num(&msg, pos.line));
ignore_bool(append_bytes(&msg, ":"));
ignore_bool(append_num(&msg, pos.col));
append_bytes(&msg, ":");
append_num(&msg, pos.line);
append_bytes(&msg, ":");
append_num(&msg, pos.col);
}
}
ignore_bool(append_bytes(&msg, ": assert failed"));
append_bytes(&msg, ": assert failed");
if args.len == 2 {
var mn = Ast.node(self.ast, list_at(args, 1));
if mn != null {
match mn.body {
.ExprStringLit(sl) => {
ignore_bool(append_bytes(&msg, ": "));
ignore_bool(append_bytes(&msg, ByteView.as_slice(sl.data)));
append_bytes(&msg, ": ");
append_bytes(&msg, ByteView.as_slice(sl.data));
},
_ => {},
}
@@ -688,8 +671,8 @@ fn ast2ir_intrin_assert(self: *Ast2Ir, n: *Node, args: Vec): usize {
}
var msg_view = ByteView.from_slice(ByteBuffer.as_slice(msg));
@assert(msg_view.len == 0 || msg_view.ptr != null, "panic message bytes must be non-null");
ignore_usize(IrBuilder.dbg_panic(self.ir, msg_view));
ignore_usize(IrBuilder.control_trap(self.ir));
IrBuilder.dbg_panic(self.ir, msg_view);
IrBuilder.control_trap(self.ir);
IrBuilder.block_end(self.ir);
var cont_blk = IrBuilder.block_begin(self.ir);
@@ -707,7 +690,6 @@ fn append_num(buf: *ByteBuffer, v: usize): bool {
ret false;
}
fn ignore_bool(b: bool) {}
fn ast2ir_intrin_field(self: *Ast2Ir, n: *Node, in: Intrin): usize {
if @enum2int(in) == @enum2int(Intrin.Len) { ret ast2ir_intrin_len(self, n); }
@@ -742,7 +724,6 @@ fn ast2ir_intrin_len(self: *Ast2Ir, n: *Node): usize {
ret 0;
}
// ---- 左值 ----
fn emit_lvalue(self: *Ast2Ir, ref: usize): usize {
var n = Ast.node(self.ast, ref);
@@ -857,33 +838,32 @@ fn extra_elem(e: LangEntry): usize {
ret 0;
}
fn ignore_usize(x: usize) {}
// ---- 转换 ----
fn ast2ir_emit_cast_builtin(self: *Ast2Ir, n: *Node, in: Intrin, ft: usize, tt: usize,
v: usize): usize {
if @enum2int(in) == @enum2int(Intrin.IntCast) {
var fs = irt(self, ft);
if fs != null {
match fs.node {
.Int(x) => { if x.is_signed { ret IrBuilder.cast_sext(self.ir, ft, tt, v); } },
_ => {},
match in {
.IntCast => {
var fs = irt(self, ft);
if fs != null {
match fs.node {
.Int(x) => { if x.is_signed { ret IrBuilder.cast_sext(self.ir, ft, tt, v); } },
_ => {},
}
}
}
ret IrBuilder.cast_zext(self.ir, ft, tt, v);
ret IrBuilder.cast_zext(self.ir, ft, tt, v);
},
.Truncate => { ret IrBuilder.cast_trunc(self.ir, ft, tt, v); },
.BitCast => { ret IrBuilder.cast_bitcast(self.ir, ft, tt, v); },
.FloatCast => { ret ir_float_cast(self, ft, tt, v); },
.Float2Int => { ret IrBuilder.case_float2int(self.ir, ft, tt, v); },
.Int2Float => { ret IrBuilder.case_int2float(self.ir, ft, tt, v); },
.Bool2Int => { ret IrBuilder.cast_bool2int(self.ir, ft, tt, v); },
.Ptr2Int => { ret IrBuilder.cast_ptr2int(self.ir, ft, tt, v); },
.Int2Ptr => { ret IrBuilder.cast_int2ptr(self.ir, ft, tt, v); },
.PtrCast => { ret IrBuilder.cast_bitcast(self.ir, ft, tt, v); },
_ => {},
}
if @enum2int(in) == @enum2int(Intrin.Truncate) { ret IrBuilder.cast_trunc(self.ir, ft, tt, v); }
if @enum2int(in) == @enum2int(Intrin.BitCast) { ret IrBuilder.cast_bitcast(self.ir, ft, tt, v); }
if @enum2int(in) == @enum2int(Intrin.FloatCast) {
ret ir_float_cast(self, ft, tt, v);
}
if @enum2int(in) == @enum2int(Intrin.Float2Int) { ret IrBuilder.case_float2int(self.ir, ft, tt, v); }
if @enum2int(in) == @enum2int(Intrin.Int2Float) { ret IrBuilder.case_int2float(self.ir, ft, tt, v); }
if @enum2int(in) == @enum2int(Intrin.Bool2Int) { ret IrBuilder.cast_bool2int(self.ir, ft, tt, v); }
if @enum2int(in) == @enum2int(Intrin.Ptr2Int) { ret IrBuilder.cast_ptr2int(self.ir, ft, tt, v); }
if @enum2int(in) == @enum2int(Intrin.Int2Ptr) { ret IrBuilder.cast_int2ptr(self.ir, ft, tt, v); }
if @enum2int(in) == @enum2int(Intrin.PtrCast) { ret IrBuilder.cast_bitcast(self.ir, ft, tt, v); }
Diag.err(self.diag, n.span, .Internal, "ast2ir: unknown cast builtin");
ret 0;
}
@@ -968,19 +948,18 @@ fn ast2ir_enum_variant(self: *Ast2Ir, n: *Node): usize {
var eptr = IrBuilder.mem_alloca(self.ir, t, const_usize(self, 1));
var tptr = IrBuilder.mem_field(self.ir, t, eptr, 0);
var tag_val = IrBuilder.type_const_int(self.ir, tag_ir, vidx);
ignore_usize(IrBuilder.mem_store(self.ir, tag_ir, tptr, tag_val));
IrBuilder.mem_store(self.ir, tag_ir, tptr, tag_val);
if vidx < variants.len {
var payload_ir = variant_at(variants, vidx);
if payload_ir != 0 {
var pptr = IrBuilder.mem_field(self.ir, t, eptr, vidx + 1);
var zero = emit_zero_value(self, payload_ir);
ignore_usize(IrBuilder.mem_store(self.ir, payload_ir, pptr, zero));
IrBuilder.mem_store(self.ir, payload_ir, pptr, zero);
}
}
ret eptr;
}
// ---- 表达式 ----
fn emit_expr(self: *Ast2Ir, ref: usize): usize {
var val = emit_expr_raw(self, ref);
@@ -1120,7 +1099,7 @@ fn emit_binary(self: *Ast2Ir, n: *Node, op: Punct, left: usize, right: usize): u
if ptr == 0 || v == 0 { ret 0; }
var ln = Ast.node(self.ast, left);
var t = node_ir(self, ln);
ignore_usize(IrBuilder.mem_store(self.ir, t, ptr, v));
IrBuilder.mem_store(self.ir, t, ptr, v);
ret v;
}
if is_assign_arith(op) { ret emit_assign_arith(self, op, left, right); }
@@ -1199,7 +1178,7 @@ fn emit_assign_arith(self: *Ast2Ir, op: Punct, left: usize, right: usize): usize
else if punct_is(op, .RShAssign) { res = IrBuilder.arith_shr(self.ir, t, lv, rv); }
else { ret 0; }
if res == 0 { ret 0; }
ignore_usize(IrBuilder.mem_store(self.ir, t, ptr, res));
IrBuilder.mem_store(self.ir, t, ptr, res);
ret res;
}
@@ -1210,14 +1189,14 @@ fn emit_short_circuit(self: *Ast2Ir, op: Punct, left: usize, right: usize): usiz
var l = emit_expr(self, left);
if l == 0 { ret 0; }
ignore_usize(IrBuilder.mem_store(self.ir, b_ir, slot, l));
IrBuilder.mem_store(self.ir, b_ir, slot, l);
var br = IrBuilder.control_br(self.ir, l);
IrBuilder.block_end(self.ir);
var rhs_blk = IrBuilder.block_begin(self.ir);
var r = emit_expr(self, right);
if r != 0 { ignore_usize(IrBuilder.mem_store(self.ir, b_ir, slot, r)); }
if r != 0 { IrBuilder.mem_store(self.ir, b_ir, slot, r); }
var rhs_end: usize = 0;
if !self.ir.terminated { rhs_end = IrBuilder.control_jmp(self.ir); }
IrBuilder.block_end(self.ir);
@@ -1371,7 +1350,7 @@ fn emit_array_to_slice(self: *Ast2Ir, n: *Node, t: usize, elems: Vec, elem_lang:
var fptr = IrBuilder.mem_field(self.ir, arr_ir, slot, i);
var v = emit_expr(self, list_at(elems, i));
if v == 0 { ret 0; }
ignore_usize(IrBuilder.mem_store(self.ir, elem_ir, fptr, v));
IrBuilder.mem_store(self.ir, elem_ir, fptr, v);
i = i + 1;
}
base = IrBuilder.mem_field(self.ir, arr_ir, slot, 0);
@@ -1413,13 +1392,13 @@ fn emit_aggregate_lit(self: *Ast2Ir, n: *Node, type_name: ByteView, fields: Vec)
var eptr = IrBuilder.mem_alloca(self.ir, t, const_usize(self, 1));
var tptr = IrBuilder.mem_field(self.ir, t, eptr, 0);
var tag_val = IrBuilder.type_const_int(self.ir, tag_ir, vidx);
ignore_usize(IrBuilder.mem_store(self.ir, tag_ir, tptr, tag_val));
IrBuilder.mem_store(self.ir, tag_ir, tptr, tag_val);
if iexpr != 0 {
var payload_ir = variant_at(variants, vidx);
var pptr = IrBuilder.mem_field(self.ir, t, eptr, vidx + 1);
var payload = emit_expr(self, iexpr);
if payload == 0 { ret 0; }
ignore_usize(IrBuilder.mem_store(self.ir, payload_ir, pptr, payload));
IrBuilder.mem_store(self.ir, payload_ir, pptr, payload);
}
ret eptr;
}
@@ -1474,7 +1453,7 @@ fn emit_aggregate_lit(self: *Ast2Ir, n: *Node, type_name: ByteView, fields: Vec)
}
fn set_u(v: *Vec, i: usize, x: usize) {
match Vec.set(v, i, &x as *u8) { .Ok => {}, .Err(e) => {} }
Vec.set(v, i, &x as *u8);
}
fn emit_deferred_until(self: *Ast2Ir, base: usize) {
@@ -1545,7 +1524,7 @@ fn emit_match(self: *Ast2Ir, n: *Node, matched_ref: usize, arms: Vec): usize {
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));
IrBuilder.mem_store(self.ir, matched_ir, scrut_slot, scrut_val);
}
var narms = arms.len;
@@ -1567,7 +1546,7 @@ fn emit_match(self: *Ast2Ir, n: *Node, matched_ref: usize, arms: Vec): usize {
push_u(&arm_branches, IrBuilder.control_jmp(self.ir));
}
IrBuilder.block_end(self.ir);
if i + 1 < narms { ignore_usize(IrBuilder.block_begin(self.ir)); }
if i + 1 < narms { IrBuilder.block_begin(self.ir); }
i = i + 1;
}
var no_match_blk = IrBuilder.block_begin(self.ir);
@@ -1585,7 +1564,7 @@ fn emit_match(self: *Ast2Ir, n: *Node, matched_ref: usize, arms: Vec): usize {
var body: usize = 0;
match arm.body { .MatchArm(ma) => { pat = ma.pattern; body = ma.body; }, _ => {} }
emit_pattern_bind(self, pat, scrut_slot, matched_ir, matched_place_mode);
if body != 0 { ignore_usize(emit_expr(self, body)); }
if body != 0 { emit_expr(self, body); }
}
var j: usize = 0;
if !self.ir.terminated { j = IrBuilder.control_jmp(self.ir); }
@@ -1600,12 +1579,14 @@ fn emit_match(self: *Ast2Ir, n: *Node, matched_ref: usize, arms: Vec): usize {
if branch != 0 {
var bk = ir_kind_of(self, branch);
var body_blk = list_at(body_blks, i);
if @enum2int(bk) == @enum2int(IrKind.ControlBr) {
var next_blk = no_match_blk;
if i + 1 < narms { next_blk = list_at(cond_blks, i + 1); }
IrBuilder.control_br_fixup(self.ir, branch, body_blk, next_blk);
} else if @enum2int(bk) == @enum2int(IrKind.ControlJmp) {
IrBuilder.control_jmp_fixup(self.ir, branch, body_blk);
match bk {
.ControlBr => {
var next_blk = no_match_blk;
if i + 1 < narms { next_blk = list_at(cond_blks, i + 1); }
IrBuilder.control_br_fixup(self.ir, branch, body_blk, next_blk);
},
.ControlJmp => { IrBuilder.control_jmp_fixup(self.ir, branch, body_blk); },
_ => {},
}
}
i = i + 1;
@@ -1682,7 +1663,6 @@ fn emit_slice(self: *Ast2Ir, n: *Node, obj_ref: usize, begin_ref: usize, end_ref
ret node;
}
// ---- if / loop ----
fn emit_if_like(self: *Ast2Ir, ref: usize): usize {
var n = Ast.node(self.ast, ref);
@@ -1729,7 +1709,7 @@ fn emit_if_like(self: *Ast2Ir, ref: usize): usize {
var then_v: usize = 0;
if then_ref != 0 { then_v = emit_expr(self, then_ref); }
if result_slot != 0 && then_v != 0 {
ignore_usize(IrBuilder.mem_store(self.ir, result_t, result_slot, then_v));
IrBuilder.mem_store(self.ir, result_t, result_slot, then_v);
}
var then_end: usize = 0;
if !self.ir.terminated { then_end = IrBuilder.control_jmp(self.ir); }
@@ -1739,7 +1719,7 @@ fn emit_if_like(self: *Ast2Ir, ref: usize): usize {
var else_v: usize = 0;
if else_ref != 0 { else_v = emit_expr(self, else_ref); }
if result_slot != 0 && else_v != 0 {
ignore_usize(IrBuilder.mem_store(self.ir, result_t, result_slot, else_v));
IrBuilder.mem_store(self.ir, result_t, result_slot, else_v);
}
var else_end: usize = 0;
if !self.ir.terminated { else_end = IrBuilder.control_jmp(self.ir); }
@@ -1815,9 +1795,9 @@ fn emit_loop_like(self: *Ast2Ir, ref: usize): usize {
}
}
if label_ref != 0 { ctx.label = label_name_of(self, label_ref); }
match Vec.push(&self.loop_stack, &ctx as *u8) { .Ok => {}, .Err(e) => {} }
Vec.push(&self.loop_stack, &ctx as *u8);
if body_ref != 0 { ignore_usize(emit_expr(self, body_ref)); }
if body_ref != 0 { emit_expr(self, body_ref); }
var body_end: usize = 0;
if !self.ir.terminated { body_end = IrBuilder.control_jmp(self.ir); }
@@ -1827,7 +1807,7 @@ fn emit_loop_like(self: *Ast2Ir, ref: usize): usize {
var else_v: usize = 0;
if is_while && else_ref != 0 { else_v = emit_expr(self, else_ref); }
if result_slot != 0 && else_v != 0 {
ignore_usize(IrBuilder.mem_store(self.ir, result_t, result_slot, else_v));
IrBuilder.mem_store(self.ir, result_t, result_slot, else_v);
}
if pre_jmp != 0 { IrBuilder.control_jmp_fixup(self.ir, pre_jmp, cont_blk); }
if br != 0 { IrBuilder.control_br_fixup(self.ir, br, body_blk, after_blk); }
@@ -1858,7 +1838,7 @@ fn pop_loop(self: *Ast2Ir) {
.cont_blk = 0, .defer_base = 0, .label = ByteView.empty(),
.breaks = Vec.blank(@sizeof(usize), @alignof(usize)), .result_slot = 0, .result_tid = 0,
};
match Vec.pop(&self.loop_stack, &out as *u8) { .Ok => {}, .Err(e) => {} }
Vec.pop(&self.loop_stack, &out as *u8);
}
fn label_name_of(self: *Ast2Ir, ref: usize): ByteView {
@@ -1896,7 +1876,7 @@ fn emit_break_stmt(self: *Ast2Ir, n: *Node): usize {
if expr_ref != 0 && target.result_slot != 0 {
var bv = emit_expr(self, expr_ref);
if bv != 0 {
ignore_usize(IrBuilder.mem_store(self.ir, target.result_tid, target.result_slot, bv));
IrBuilder.mem_store(self.ir, target.result_tid, target.result_slot, bv);
}
}
emit_deferred_until(self, target.defer_base);
@@ -1907,7 +1887,6 @@ fn emit_break_stmt(self: *Ast2Ir, n: *Node): usize {
ret 0;
}
// ---- 语句 / 声明 ----
fn emit_stmt(self: *Ast2Ir, ref: usize) {
var n = Ast.node(self.ast, ref);
@@ -1918,20 +1897,20 @@ fn emit_stmt(self: *Ast2Ir, ref: usize) {
var v: usize = 0;
if x.expr != 0 { v = emit_expr(self, x.expr); }
emit_deferred_until(self, self.cur_defer_base);
if !self.ir.terminated { ignore_usize(IrBuilder.control_ret(self.ir, ret_ir, v)); }
if !self.ir.terminated { IrBuilder.control_ret(self.ir, ret_ir, v); }
},
.StatementDefer(&x) => { if x.body != 0 { push_u(&self.defer_stack, x.body); } },
.StatementComptime(&x) => { if x.body != 0 { ignore_usize(emit_expr(self, x.body)); } },
.StatementComptime(&x) => { if x.body != 0 { emit_expr(self, x.body); } },
.StatementDecl(&x) => { if x.decl != 0 { emit_decl(self, x.decl); } },
.StatementExpr(&x) => { if x.expr != 0 { ignore_usize(emit_expr(self, x.expr)); } },
.ExprIf(&x) => { ignore_usize(emit_if_like(self, ref)); },
.ExprIfvar(&x) => { ignore_usize(emit_if_like(self, ref)); },
.ExprWhile(&x) => { ignore_usize(emit_loop_like(self, ref)); },
.ExprLoop(&x) => { ignore_usize(emit_loop_like(self, ref)); },
.StatementBreak(&x) => { ignore_usize(emit_break_stmt(self, n)); },
.StatementExpr(&x) => { if x.expr != 0 { emit_expr(self, x.expr); } },
.ExprIf(&x) => { emit_if_like(self, ref); },
.ExprIfvar(&x) => { emit_if_like(self, ref); },
.ExprWhile(&x) => { emit_loop_like(self, ref); },
.ExprLoop(&x) => { emit_loop_like(self, ref); },
.StatementBreak(&x) => { emit_break_stmt(self, n); },
.StatementContinue(&x) => { emit_continue_stmt(self, n); },
.ExprBlock(&x) => { ignore_usize(emit_expr(self, ref)); },
_ => { ignore_usize(emit_expr(self, ref)); },
.ExprBlock(&x) => { emit_expr(self, ref); },
_ => { emit_expr(self, ref); },
}
}
@@ -1957,8 +1936,8 @@ fn emit_decl(self: *Ast2Ir, ref: usize) {
var n = Ast.node(self.ast, ref);
if n == null { ret; }
match n.body {
.VarDecl(&x) => { if self.ir.current_fn != 0 { ignore_usize(emit_var_decl(self, n)); } },
.ConstDecl(&x) => { if self.ir.current_fn != 0 { ignore_usize(emit_var_decl(self, n)); } },
.VarDecl(&x) => { if self.ir.current_fn != 0 { emit_var_decl(self, n); } },
.ConstDecl(&x) => { if self.ir.current_fn != 0 { emit_var_decl(self, n); } },
_ => {},
}
}
@@ -1989,8 +1968,8 @@ fn fn_name_of(n: *Node): ByteView {
fn diag_name(self: *Ast2Ir, span: Span, code: Code, prefix: []u8, name: ByteView) {
var b = ByteBuffer.new();
defer { ByteBuffer.drop(&b); }
match ByteBuffer.append(&b, prefix) { .Ok => {}, .Err(e) => {} }
match ByteBuffer.append(&b, ByteView.as_slice(name)) { .Ok => {}, .Err(e) => {} }
ByteBuffer.append(&b, prefix);
ByteBuffer.append(&b, ByteView.as_slice(name));
Diag.err(self.diag, span, code, ByteBuffer.as_slice(b));
}
@@ -2014,7 +1993,7 @@ fn emit_fn_body(self: *Ast2Ir, n: *Node) {
var defer_base = self.cur_defer_base;
var loop_base = self.loop_stack.len;
ignore_usize(IrBuilder.block_begin(self.ir));
IrBuilder.block_begin(self.ir);
var params = Vec.blank(@sizeof(usize), @alignof(usize));
var body_ref: usize = 0;
@@ -2031,23 +2010,23 @@ fn emit_fn_body(self: *Ast2Ir, n: *Node) {
var pv = IrBuilder.control_param(self.ir, p_ir, idx);
var one = const_usize(self, 1);
var slot = IrBuilder.mem_alloca(self.ir, p_ir, one);
ignore_usize(IrBuilder.mem_store(self.ir, p_ir, slot, pv));
IrBuilder.mem_store(self.ir, p_ir, slot, pv);
ir_map_put(self, pd.resolved_def_id, slot);
}
}
i = i + 1;
}
if body_ref != 0 { ignore_usize(emit_expr(self, body_ref)); }
if body_ref != 0 { emit_expr(self, body_ref); }
if !self.ir.terminated { emit_deferred_until(self, defer_base); }
if !self.ir.terminated {
if ret_is_unit {
ignore_usize(IrBuilder.control_ret(self.ir, ret_ir, 0));
IrBuilder.control_ret(self.ir, ret_ir, 0);
} else if ret_ir != 0 {
var zero = emit_zero_value(self, ret_ir);
ignore_usize(IrBuilder.control_ret(self.ir, ret_ir, zero));
IrBuilder.control_ret(self.ir, ret_ir, zero);
} else {
ignore_usize(IrBuilder.control_unreachable(self.ir));
IrBuilder.control_unreachable(self.ir);
}
}
@@ -2077,7 +2056,7 @@ fn emit_aggregate_fns_reserve(self: *Ast2Ir, te: *Node) {
var mn = Ast.node(self.ast, list_at(members, i));
if mn != null {
match mn.body {
.FnDecl(x) => { ignore_usize(emit_fn_reserve(self, mn)); },
.FnDecl(x) => { emit_fn_reserve(self, mn); },
.MemberDecl(md) => {
if md.type_expr != 0 {
var mt = Ast.node(self.ast, md.type_expr);
@@ -2138,7 +2117,7 @@ fn emit_container_reserve(self: *Ast2Ir, ref: usize) {
var d = Ast.node(self.ast, dref);
if d != null {
match d.body {
.FnDecl(x) => { ignore_usize(emit_fn_reserve(self, d)); },
.FnDecl(x) => { emit_fn_reserve(self, d); },
.TypeDecl(td) => {
var tpat = Ast.node(self.ast, td.pattern);
if tpat != null && is_pattern_ident(tpat) {
@@ -2251,7 +2230,6 @@ fn emit_implicit_cast(self: *Ast2Ir, n: *Node, ft: usize, tt: usize, v: usize):
ret 0;
}
// ---- 驱动 ----
fn new(builder: *IrBuilder, sema: *Sema, diag: *Diag): Ast2Ir {
ret Ast2Ir {
@@ -2330,6 +2308,5 @@ fn list_ptr(v: Vec, i: usize): *Ast {
ret null;
}
// ---- 测试 ----
fn main() {}