stage1 实现短路逻辑

This commit is contained in:
zzy committed 2026-09-17 19:37:33 +08:00
1 parent b8e2bba140
commit 73c9a40abd
1 file changed
+39 -10
+39 -10
View File
@@ -765,6 +765,7 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
}
case SPL_AST_EXPR_BINARY: {
spl_binary_op_t op = n->binary.op;
if (op == SPL_OP_ASSIGN) {
spl_ir_node_ref_t ptr = emit_lvalue(a, n->binary.left);
spl_ir_node_ref_t v = emit_expr(a, n->binary.right);
@@ -775,6 +776,7 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
spl_ir_builder_mem_store(a->ir, t, ptr, v);
return v;
}
if (op >= SPL_OP_ASSIGN_ADD && op <= SPL_OP_ASSIGN_RSHIFT) {
spl_ir_node_ref_t ptr = emit_lvalue(a, n->binary.left);
if (!ptr)
@@ -825,6 +827,43 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
spl_ir_builder_mem_store(a->ir, t, ptr, res);
return res;
}
if (op == SPL_OP_BOOL_OR || op == SPL_OP_BOOL_AND) {
spl_lang_type_id_t b_lang = spl_lang_make_bool(a->sema->type);
spl_type_id_t b_ir = to_ir_type(a, b_lang);
spl_ir_node_ref_t slot = spl_ir_builder_mem_alloca(a->ir, b_ir, const_usize(a, 1));
spl_ir_node_ref_t l = emit_expr(a, n->binary.left);
if (!l)
return 0;
spl_ir_builder_mem_store(a->ir, b_ir, slot, l);
spl_ir_node_ref_t br = spl_ir_builder_control_br(a->ir, l);
spl_ir_builder_block_end(a->ir);
usize rhs_blk = spl_ir_builder_block_begin(a->ir);
spl_ir_node_ref_t r = emit_expr(a, n->binary.right);
if (r)
spl_ir_builder_mem_store(a->ir, b_ir, slot, r);
/* 右侧可能以 ret / trap 终止,此时不能再补 jmp */
spl_ir_node_ref_t rhs_end = 0;
if (!a->ir->terminated)
rhs_end = spl_ir_builder_control_jmp(a->ir);
spl_ir_builder_block_end(a->ir);
usize end_blk = spl_ir_builder_block_begin(a->ir);
/* control.br: cond != 0 -> true_label。AND 左侧真才进 rhs,
OR 左侧假才进 rhs,所以 true/false 标签顺序相反。 */
if (op == SPL_OP_BOOL_AND)
spl_ir_builder_control_br_fixup(a->ir, br, rhs_blk, end_blk);
else
spl_ir_builder_control_br_fixup(a->ir, br, end_blk, rhs_blk);
if (rhs_end)
spl_ir_builder_control_jmp_fixup(a->ir, rhs_end, end_blk);
return spl_ir_builder_mem_load(a->ir, b_ir, slot);
}
spl_ir_node_ref_t l = emit_expr(a, n->binary.left);
spl_ir_node_ref_t r = emit_expr(a, n->binary.right);
if (!l || !r)
@@ -893,16 +932,6 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
return 0;
}
}
case SPL_OP_BOOL_OR: {
spl_ast_node_t *bmln = spl_ast_node(a->ast, n->binary.left);
spl_type_id_t op_tid = bmln ? node_ir(a, bmln) : 0;
return spl_ir_builder_arith_or(a->ir, op_tid, l, r);
}
case SPL_OP_BOOL_AND: {
spl_ast_node_t *bmln = spl_ast_node(a->ast, n->binary.left);
spl_type_id_t op_tid = bmln ? node_ir(a, bmln) : 0;
return spl_ir_builder_arith_and(a->ir, op_tid, l, r);
}
default:
return 0;
}