diff --git a/stage1/spl_ast2ir.c b/stage1/spl_ast2ir.c index e1e5ac6..9b209b2 100644 --- a/stage1/spl_ast2ir.c +++ b/stage1/spl_ast2ir.c @@ -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; }