#include #include #include #include #include #include // 判断是否为算术类型(整数或浮点) static cbool is_arithmetic_type(const scc_hir_type_t *type) { Assert(type != nullptr); switch (type->tag) { case SCC_HIR_TYPE_i8: case SCC_HIR_TYPE_i16: case SCC_HIR_TYPE_i32: case SCC_HIR_TYPE_i64: case SCC_HIR_TYPE_i128: case SCC_HIR_TYPE_u8: case SCC_HIR_TYPE_u16: case SCC_HIR_TYPE_u32: case SCC_HIR_TYPE_u64: case SCC_HIR_TYPE_u128: case SCC_HIR_TYPE_f16: case SCC_HIR_TYPE_f32: case SCC_HIR_TYPE_f64: case SCC_HIR_TYPE_f128: return true; default: return false; } } static inline bool scc_hir_type_is_signed(scc_hir_type_tag_t tag) { switch (tag) { case SCC_HIR_TYPE_i8: case SCC_HIR_TYPE_i16: case SCC_HIR_TYPE_i32: case SCC_HIR_TYPE_i64: case SCC_HIR_TYPE_i128: return true; case SCC_HIR_TYPE_u8: case SCC_HIR_TYPE_u16: case SCC_HIR_TYPE_u32: case SCC_HIR_TYPE_u64: case SCC_HIR_TYPE_u128: return false; default: // 指针可以视作无符号整数 return false; } } scc_hir_value_ref_t scc_ast2ir_logical_expr(scc_ast2ir_ctx_t *ctx, const scc_ast_expr_t *expr) { // scc_hir_bblock_ref_t start_block = // scc_hir_builder_current_bblock(&ctx->builder); scc_hir_value_ref_t right_block = scc_hir_builder_create_bblock(&ctx->builder, "logic_right"); scc_hir_value_ref_t end_block = scc_hir_builder_create_bblock(&ctx->builder, "logic_end"); // 为结果创建临时存储空间 scc_hir_type_ref_t int32_type = scc_hir_builder_type_i32(&ctx->builder); scc_hir_value_ref_t result_var = scc_hir_builder_alloca(&ctx->builder, int32_type, "logic_result"); // 计算左操作数 scc_hir_value_ref_t left_val = scc_ast2ir_expr(ctx, expr->binary.lhs, false); scc_ap_t zero_ap; scc_ap_set_int(&zero_ap, 0); scc_ap_t one_ap; scc_ap_set_int(&one_ap, 1); scc_hir_value_ref_t zero_val = scc_hir_builder_integer(&ctx->builder, int32_type, &zero_ap); scc_hir_value_ref_t one_val = scc_hir_builder_integer(&ctx->builder, int32_type, &one_ap); if (expr->binary.op == SCC_AST_OP_LOGICAL_AND) { // a && b scc_hir_value_ref_t false_block = scc_hir_builder_create_bblock(&ctx->builder, "and_false"); // 如果左操作数为0,结果为0(短路) scc_hir_value_ref_t is_left_zero = scc_hir_builder_binop( &ctx->builder, SCC_HIR_OP_EQ, left_val, zero_val); scc_hir_builder_branch(&ctx->builder, is_left_zero, false_block, right_block); // false_block: 左边为0,结果为0 scc_hir_builder_append_bblock(&ctx->builder, false_block); scc_hir_builder_set_current_bblock(&ctx->builder, false_block); scc_hir_builder_store(&ctx->builder, result_var, zero_val); scc_hir_builder_jump(&ctx->builder, end_block); // right_block: 左边非0,计算右边 scc_hir_builder_append_bblock(&ctx->builder, right_block); scc_hir_builder_set_current_bblock(&ctx->builder, right_block); scc_hir_value_ref_t right_val = scc_ast2ir_expr(ctx, expr->binary.rhs, false); scc_hir_value_ref_t is_right_zero = scc_hir_builder_binop( &ctx->builder, SCC_HIR_OP_EQ, right_val, zero_val); scc_hir_value_ref_t result = scc_hir_builder_binop(&ctx->builder, SCC_HIR_OP_XOR, is_right_zero, one_val); // !right == 0 ? 1 : 0 scc_hir_builder_store(&ctx->builder, result_var, result); scc_hir_builder_jump(&ctx->builder, end_block); } else { // SCC_AST_OP_LOGICAL_OR // a || b scc_hir_value_ref_t true_block = scc_hir_builder_create_bblock(&ctx->builder, "or_true"); // 如果左操作数非0,结果为1(短路) scc_hir_value_ref_t is_left_nonzero = scc_hir_builder_binop( &ctx->builder, SCC_HIR_OP_NEQ, left_val, zero_val); scc_hir_builder_branch(&ctx->builder, is_left_nonzero, true_block, right_block); // true_block: 左边非0,结果为1 scc_hir_builder_append_bblock(&ctx->builder, true_block); scc_hir_builder_set_current_bblock(&ctx->builder, true_block); scc_hir_builder_store(&ctx->builder, result_var, one_val); scc_hir_builder_jump(&ctx->builder, end_block); // right_block: 左边为0,计算右边 scc_hir_builder_append_bblock(&ctx->builder, right_block); scc_hir_builder_set_current_bblock(&ctx->builder, right_block); scc_hir_value_ref_t right_val = scc_ast2ir_expr(ctx, expr->binary.rhs, false); scc_hir_value_ref_t is_right_zero = scc_hir_builder_binop( &ctx->builder, SCC_HIR_OP_EQ, right_val, zero_val); scc_hir_value_ref_t result = scc_hir_builder_binop(&ctx->builder, SCC_HIR_OP_XOR, is_right_zero, one_val); // !right == 0 ? 1 : 0 scc_hir_builder_store(&ctx->builder, result_var, result); scc_hir_builder_jump(&ctx->builder, end_block); } // 设置结束块为当前块,并返回结果 scc_hir_builder_append_bblock(&ctx->builder, end_block); scc_hir_builder_set_current_bblock(&ctx->builder, end_block); return scc_hir_builder_load(&ctx->builder, result_var); } /** * @brief * * @param ctx * @param expr * @return scc_hir_value_ref_t */ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, const scc_ast_expr_t *expr, cbool is_lvalue) { if (ctx == nullptr || expr == nullptr) { LOG_ERROR("args is nullptr"); return 0; } LOG_DEBUG("expr type=%d is_lvalue=%d", expr->base.type, (int)is_lvalue); cbool is_assign = true; switch (expr->base.type) { case SCC_AST_EXPR_BINARY: { LOG_DEBUG(" binary op=%d", expr->binary.op); scc_ast_expr_t tmp_expr; scc_hir_value_ref_t lhs = SCC_HIR_REF_nullptr, rhs = SCC_HIR_REF_nullptr; switch (expr->binary.op) { case SCC_AST_OP_ASSIGN: // = rhs = scc_ast2ir_expr(ctx, expr->binary.rhs, false); break; case SCC_AST_OP_ASSIGN_ADD: // += scc_ast_expr_binary_init(&tmp_expr, SCC_AST_OP_ADD, expr->binary.lhs, expr->binary.rhs, expr->base.loc); rhs = scc_ast2ir_expr(ctx, &tmp_expr, false); break; case SCC_AST_OP_ASSIGN_SUB: // -= scc_ast_expr_binary_init(&tmp_expr, SCC_AST_OP_SUB, expr->binary.lhs, expr->binary.rhs, expr->base.loc); rhs = scc_ast2ir_expr(ctx, &tmp_expr, false); break; case SCC_AST_OP_ASSIGN_MUL: // *= scc_ast_expr_binary_init(&tmp_expr, SCC_AST_OP_MUL, expr->binary.lhs, expr->binary.rhs, expr->base.loc); rhs = scc_ast2ir_expr(ctx, &tmp_expr, false); break; case SCC_AST_OP_ASSIGN_DIV: // /= scc_ast_expr_binary_init(&tmp_expr, SCC_AST_OP_DIV, expr->binary.lhs, expr->binary.rhs, expr->base.loc); rhs = scc_ast2ir_expr(ctx, &tmp_expr, false); break; case SCC_AST_OP_ASSIGN_MOD: // %= scc_ast_expr_binary_init(&tmp_expr, SCC_AST_OP_MOD, expr->binary.lhs, expr->binary.rhs, expr->base.loc); rhs = scc_ast2ir_expr(ctx, &tmp_expr, false); break; case SCC_AST_OP_ASSIGN_AND: // &= scc_ast_expr_binary_init(&tmp_expr, SCC_AST_OP_BITWISE_AND, expr->binary.lhs, expr->binary.rhs, expr->base.loc); rhs = scc_ast2ir_expr(ctx, &tmp_expr, false); break; case SCC_AST_OP_ASSIGN_XOR: // ^= scc_ast_expr_binary_init(&tmp_expr, SCC_AST_OP_BITWISE_XOR, expr->binary.lhs, expr->binary.rhs, expr->base.loc); rhs = scc_ast2ir_expr(ctx, &tmp_expr, false); break; case SCC_AST_OP_ASSIGN_OR: // |= scc_ast_expr_binary_init(&tmp_expr, SCC_AST_OP_BITWISE_OR, expr->binary.lhs, expr->binary.rhs, expr->base.loc); rhs = scc_ast2ir_expr(ctx, &tmp_expr, false); break; case SCC_AST_OP_ASSIGN_LSHIFT: // <<= scc_ast_expr_binary_init(&tmp_expr, SCC_AST_OP_LEFT_SHIFT, expr->binary.lhs, expr->binary.rhs, expr->base.loc); rhs = scc_ast2ir_expr(ctx, &tmp_expr, false); break; case SCC_AST_OP_ASSIGN_RSHIFT: // >>= scc_ast_expr_binary_init(&tmp_expr, SCC_AST_OP_RIGHT_SHIFT, expr->binary.lhs, expr->binary.rhs, expr->base.loc); rhs = scc_ast2ir_expr(ctx, &tmp_expr, false); break; default: is_assign = false; break; } if (is_assign) { Assert(rhs != SCC_HIR_REF_nullptr); lhs = scc_ast2ir_expr(ctx, expr->binary.lhs, true); // 将 RHS 转换为 LHS 指向的类型(C11 6.5.16.1 简单赋值) scc_hir_type_t *lhs_ptr_type = scc_hir_module_get_type_by_value( scc_ast2ir_mir_module(ctx), lhs); if (lhs_ptr_type->tag == SCC_HIR_TYPE_PTR && is_arithmetic_type( scc_hir_module_get_type(scc_ast2ir_mir_module(ctx), lhs_ptr_type->data.pointer.base))) { rhs = scc_ast2ir_emit_conversion( ctx, rhs, lhs_ptr_type->data.pointer.base); } scc_hir_builder_store(&ctx->builder, lhs, rhs); return rhs; } if (expr->binary.op == SCC_AST_OP_LOGICAL_AND || expr->binary.op == SCC_AST_OP_LOGICAL_OR) { // TODO 类型提升 return scc_ast2ir_logical_expr(ctx, expr); } if (expr->binary.op == SCC_AST_OP_COMMA) { lhs = scc_ast2ir_expr(ctx, expr->binary.lhs, false); rhs = scc_ast2ir_expr(ctx, expr->binary.rhs, false); } else { rhs = scc_ast2ir_expr(ctx, expr->binary.rhs, false); lhs = scc_ast2ir_expr(ctx, expr->binary.lhs, false); } // 类型提升:对算术类型二元操作应用寻常算术转换(C11 6.3.1.8) // 移位操作符不适用(仅对每个操作数单独整数提升) cbool is_shift = (expr->binary.op == SCC_AST_OP_LEFT_SHIFT || expr->binary.op == SCC_AST_OP_RIGHT_SHIFT); scc_hir_type_ref_t common_type = 0; if (!is_shift && expr->binary.op != SCC_AST_OP_COMMA) { scc_hir_module_t *module = scc_ast2ir_mir_module(ctx); scc_hir_type_ref_t lhs_type_ref = scc_hir_module_get_value(module, lhs)->type; scc_hir_type_ref_t rhs_type_ref = scc_hir_module_get_value(module, rhs)->type; Assert(lhs_type_ref != 0 && rhs_type_ref != 0); scc_hir_type_t *lhs_type = scc_hir_module_get_type(module, lhs_type_ref); scc_hir_type_t *rhs_type = scc_hir_module_get_type(module, rhs_type_ref); if (is_arithmetic_type(lhs_type) && is_arithmetic_type(rhs_type)) { common_type = scc_ast2ir_usual_arithmetic_conversion( ctx, lhs_type_ref, rhs_type_ref); if (common_type != 0) { lhs = scc_ast2ir_emit_conversion(ctx, lhs, common_type); rhs = scc_ast2ir_emit_conversion(ctx, rhs, common_type); } } } else if (is_shift) { // 移位操作符:只进行整数提升(C11 6.5.7) scc_hir_module_t *module = scc_ast2ir_mir_module(ctx); scc_hir_type_ref_t lhs_type_ref = scc_hir_module_get_value(module, lhs)->type; scc_hir_type_ref_t promoted = scc_ast2ir_integer_promotion(ctx, lhs_type_ref); if (promoted != 0) lhs = scc_ast2ir_emit_conversion(ctx, lhs, promoted); } // 映射操作符 scc_hir_op_type_t op; switch (expr->binary.op) { /* clang-format off */ case SCC_AST_OP_ADD: op = SCC_HIR_OP_ADD; break; case SCC_AST_OP_SUB: op = SCC_HIR_OP_SUB; break; case SCC_AST_OP_MUL: op = SCC_HIR_OP_MUL; break; case SCC_AST_OP_DIV: op = SCC_HIR_OP_DIV; break; case SCC_AST_OP_MOD: op = SCC_HIR_OP_MOD; break; case SCC_AST_OP_BITWISE_AND: op = SCC_HIR_OP_AND; break; case SCC_AST_OP_BITWISE_OR: op = SCC_HIR_OP_OR; break; case SCC_AST_OP_BITWISE_XOR: op = SCC_HIR_OP_XOR; break; case SCC_AST_OP_LEFT_SHIFT: op = SCC_HIR_OP_SHL; break; case SCC_AST_OP_RIGHT_SHIFT: { scc_hir_module_t *module = scc_ast2ir_mir_module(ctx); scc_hir_type_ref_t type_ref = scc_hir_module_get_value(module, lhs)->type; scc_hir_type_t *type = scc_hir_module_get_type(module, type_ref); op = scc_hir_type_is_signed(type->tag) ? SCC_HIR_OP_SAR : SCC_HIR_OP_SHR; break; } case SCC_AST_OP_EQUAL: op = SCC_HIR_OP_EQ; break; case SCC_AST_OP_NOT_EQUAL: op = SCC_HIR_OP_NEQ; break; case SCC_AST_OP_LESS: { scc_hir_module_t *module = scc_ast2ir_mir_module(ctx); scc_hir_type_ref_t tr = common_type ? common_type : scc_hir_module_get_value(module, lhs)->type; scc_hir_type_t *t = scc_hir_module_get_type(module, tr); op = scc_hir_type_is_signed(t->tag) ? SCC_HIR_OP_LT : SCC_HIR_OP_ULT; break; } case SCC_AST_OP_LESS_EQUAL: { scc_hir_module_t *module = scc_ast2ir_mir_module(ctx); scc_hir_type_ref_t tr = common_type ? common_type : scc_hir_module_get_value(module, lhs)->type; scc_hir_type_t *t = scc_hir_module_get_type(module, tr); op = scc_hir_type_is_signed(t->tag) ? SCC_HIR_OP_LE : SCC_HIR_OP_ULE; break; } case SCC_AST_OP_GREATER: { scc_hir_module_t *module = scc_ast2ir_mir_module(ctx); scc_hir_type_ref_t tr = common_type ? common_type : scc_hir_module_get_value(module, lhs)->type; scc_hir_type_t *t = scc_hir_module_get_type(module, tr); op = scc_hir_type_is_signed(t->tag) ? SCC_HIR_OP_GT : SCC_HIR_OP_UGT; break; } case SCC_AST_OP_GREATER_EQUAL: { scc_hir_module_t *module = scc_ast2ir_mir_module(ctx); scc_hir_type_ref_t tr = common_type ? common_type : scc_hir_module_get_value(module, lhs)->type; scc_hir_type_t *t = scc_hir_module_get_type(module, tr); op = scc_hir_type_is_signed(t->tag) ? SCC_HIR_OP_GE : SCC_HIR_OP_UGE; break; } case SCC_AST_OP_COMMA: { // 逗号运算符:计算左表达式,丢弃结果,返回右表达式 return rhs; } /* 逻辑操作符 */ case SCC_AST_OP_LOGICAL_OR: // || case SCC_AST_OP_LOGICAL_AND: // && UNREACHABLE(); return 0; /* clang-format on */ default: LOG_FATAL("Unsupported binary operator: %d", expr->binary.op); return 0; } // 创建操作节点 return scc_hir_builder_binop(&ctx->builder, op, lhs, rhs); } break; case SCC_AST_EXPR_UNARY: { LOG_DEBUG(" unary op=%d", expr->unary.op); if (expr->unary.op == SCC_AST_OP_ADDRESS_OF) { return scc_ast2ir_expr(ctx, expr->unary.operand, true); } else if (expr->unary.op == SCC_AST_OP_INDIRECTION) { // 从地址取值 scc_hir_value_ref_t ptr = scc_ast2ir_expr(ctx, expr->unary.operand, false); if (is_lvalue) { // 作为左值使用(如 *ptr = ...),直接返回指针值(地址) return ptr; } else { // 作为右值使用(如 x = *ptr),加载指针指向的值 return scc_hir_builder_load(&ctx->builder, ptr); } } scc_hir_value_ref_t operand = scc_ast2ir_expr(ctx, expr->unary.operand, is_lvalue); switch (expr->unary.op) { case SCC_AST_OP_UNARY_PLUS: /* just pass */ return operand; case SCC_AST_OP_UNARY_MINUS: { // 负号 // 实现为0 - operand scc_hir_type_ref_t type_ref = scc_hir_builder_type_i32(&ctx->builder); scc_ap_t value; scc_ap_set_int(&value, 0); scc_hir_value_ref_t zero_ref = scc_hir_builder_integer(&ctx->builder, type_ref, &value); return scc_hir_builder_binop(&ctx->builder, SCC_HIR_OP_SUB, zero_ref, operand); } case SCC_AST_OP_ADDRESS_OF: case SCC_AST_OP_INDIRECTION: UNREACHABLE(); break; case SCC_AST_OP_BITWISE_NOT: // 按位取反 return scc_hir_builder_binop(&ctx->builder, SCC_HIR_OP_NOT, operand, 0); case SCC_AST_OP_LOGICAL_NOT: { // 逻辑非 // 实现为与0比较 scc_hir_type_ref_t type_ref = scc_hir_builder_type_i32(&ctx->builder); scc_ap_t value; scc_ap_set_int(&value, 0); scc_hir_value_ref_t zero_ref = scc_hir_builder_integer(&ctx->builder, type_ref, &value); return scc_hir_builder_binop(&ctx->builder, SCC_HIR_OP_EQ, zero_ref, operand); } case SCC_AST_OP_PREFIX_INCREMENT: case SCC_AST_OP_PREFIX_DECREMENT: { // 获取左值地址 scc_hir_value_ref_t addr = scc_ast2ir_expr(ctx, expr->unary.operand, true); scc_hir_value_ref_t old_val = scc_hir_builder_load(&ctx->builder, addr); scc_hir_type_ref_t old_type = scc_hir_module_get_value( scc_hir_builder_get_module(&ctx->builder), old_val) ->type; // 整数提升:C11 6.3.1.1,对 short/char 等类型提升为 int scc_hir_type_ref_t promoted_type_ref = scc_ast2ir_integer_promotion(ctx, old_type); scc_hir_value_ref_t promoted = old_val; if (promoted_type_ref != 0) { promoted = scc_ast2ir_emit_conversion(ctx, old_val, promoted_type_ref); } else { promoted_type_ref = old_type; } scc_hir_value_ref_t one = scc_hir_builder_integer( &ctx->builder, promoted_type_ref, &(scc_ap_t){.data.digit = 1, .capacity = -1}); scc_hir_op_type_t op = (expr->unary.op == SCC_AST_OP_PREFIX_INCREMENT) ? SCC_HIR_OP_ADD : SCC_HIR_OP_SUB; scc_hir_value_ref_t new_val = scc_hir_builder_binop(&ctx->builder, op, promoted, one); // 如果原类型不是提升后的类型,需要截断回原类型再存储 scc_hir_value_ref_t stored_val = new_val; if (promoted_type_ref != old_type) { stored_val = scc_ast2ir_emit_conversion(ctx, new_val, old_type); } scc_hir_builder_store(&ctx->builder, addr, stored_val); Assert(new_val != SCC_HIR_REF_nullptr); return new_val; // 表达式的值是提升后的新值(符合 C 标准) } break; case SCC_AST_OP_POSTFIX_INCREMENT: case SCC_AST_OP_POSTFIX_DECREMENT: { // 获取左值地址 scc_hir_value_ref_t addr = scc_ast2ir_expr(ctx, expr->unary.operand, true); scc_hir_value_ref_t old_val = scc_hir_builder_load(&ctx->builder, addr); scc_hir_type_ref_t old_type = scc_hir_module_get_value( scc_hir_builder_get_module(&ctx->builder), old_val) ->type; // 整数提升(C11 6.3.1.1) scc_hir_type_ref_t promoted_type_ref = scc_ast2ir_integer_promotion(ctx, old_type); scc_hir_value_ref_t promoted = old_val; if (promoted_type_ref != 0) { promoted = scc_ast2ir_emit_conversion(ctx, old_val, promoted_type_ref); } else { promoted_type_ref = old_type; } scc_hir_value_ref_t one = scc_hir_builder_integer( &ctx->builder, promoted_type_ref, &(scc_ap_t){.data.digit = 1, .capacity = -1}); scc_hir_op_type_t op = (expr->unary.op == SCC_AST_OP_POSTFIX_INCREMENT) ? SCC_HIR_OP_ADD : SCC_HIR_OP_SUB; scc_hir_value_ref_t new_val = scc_hir_builder_binop(&ctx->builder, op, promoted, one); scc_hir_value_ref_t stored_val = new_val; if (promoted_type_ref != old_type) { stored_val = scc_ast2ir_emit_conversion(ctx, new_val, old_type); } scc_hir_builder_store(&ctx->builder, addr, stored_val); // 后缀返回旧值的提升后版本(C11 6.5.2.4) return promoted; } break; default: LOG_FATAL("Unsupported unary operator: %d", expr->unary.op); return 0; } UNREACHABLE(); } break; case SCC_AST_EXPR_COND: { LOG_DEBUG(" ternary conditional"); scc_hir_type_ref_t true_type = SCC_HIR_REF_nullptr; scc_hir_type_ref_t false_type = SCC_HIR_REF_nullptr; scc_hir_value_ref_t true_block = scc_hir_builder_bblock(&ctx->builder, "cond_true"); scc_hir_value_ref_t false_block = scc_hir_builder_bblock(&ctx->builder, "cond_false"); scc_hir_value_ref_t merge_block = scc_hir_builder_bblock(&ctx->builder, "cond_merge"); scc_hir_value_ref_t cond_node = scc_ast2ir_expr(ctx, expr->cond.cond, false); scc_hir_builder_branch(&ctx->builder, cond_node, true_block, false_block); // 生成true分支 scc_hir_builder_set_current_bblock(&ctx->builder, true_block); scc_hir_value_ref_t true_val = scc_ast2ir_expr(ctx, expr->cond.then_expr, false); true_type = scc_hir_module_get_value( scc_hir_builder_get_module(&ctx->builder), true_val) ->type; Assert(true_type != SCC_HIR_REF_nullptr); scc_hir_value_ref_t result_slot = scc_hir_builder_alloca(&ctx->builder, true_type, "cond_result"); scc_hir_builder_store(&ctx->builder, result_slot, true_val); scc_hir_builder_jump(&ctx->builder, merge_block); // 生成false分支 scc_hir_builder_set_current_bblock(&ctx->builder, false_block); scc_hir_value_ref_t false_val = scc_ast2ir_expr(ctx, expr->cond.else_expr, false); false_type = scc_hir_module_get_value( scc_hir_builder_get_module(&ctx->builder), false_val) ->type; Assert(false_type != SCC_HIR_REF_nullptr); scc_hir_builder_store(&ctx->builder, result_slot, false_val); scc_hir_builder_jump(&ctx->builder, merge_block); // 合并并返回 scc_hir_builder_set_current_bblock(&ctx->builder, merge_block); if (true_type != false_type) { LOG_ERROR("Type mismatch in conditional expression"); // FIXME need panic } return scc_hir_builder_load(&ctx->builder, result_slot); } break; case SCC_AST_EXPR_CALL: { LOG_DEBUG(" call '%s'", expr->call.callee->identifier._target ? expr->call.callee->identifier._target->name : "?"); scc_hir_value_ref_vec_t args; scc_vec_init(args); // 获取函数类型信息用于参数转换。 scc_hir_func_ref_t callee_func = (scc_hir_func_ref_t)(usize)scc_hashtable_get( &ctx->symtab, expr->call.callee->identifier._target->name); scc_hir_type_ref_t func_type_ref = SCC_HIR_REF_nullptr; cbool is_variadic = false; int fixed_count = 0; Assert(callee_func != SCC_HIR_REF_nullptr); scc_hir_func_t *hir_func = scc_hir_module_get_func(scc_ast2ir_mir_module(ctx), callee_func); scc_hir_func_meta_t *meta = SCC_HIR_FUNC_META(hir_func); is_variadic = meta->is_variadic; func_type_ref = meta->type; if (func_type_ref != SCC_HIR_REF_nullptr) { const scc_hir_type_t *ft = scc_hir_module_get_type( scc_ast2ir_mir_module(ctx), func_type_ref); if (ft != nullptr && ft->tag == SCC_HIR_TYPE_FUNC) fixed_count = (int)ft->data.function.params.size; } scc_vec_foreach(expr->call.args, i) { scc_ast_expr_t *arg_expr = scc_vec_at(expr->call.args, i); scc_hir_value_ref_t arg_node; arg_node = scc_ast2ir_expr(ctx, arg_expr, false); if ((int)i < fixed_count) { // 固定参数:转换为形参类型 // 每次迭代重新获取指针(scc_ast2ir_expr 可能触发 types 向量 // realloc) scc_hir_module_t *module = scc_ast2ir_mir_module(ctx); const scc_hir_type_t *ft = scc_hir_module_get_type(module, func_type_ref); scc_hir_type_ref_t param_type = scc_vec_at(ft->data.function.params, i); arg_node = scc_ast2ir_emit_conversion(ctx, arg_node, param_type); } else if (is_variadic) { // 可变参数:只应用默认参数提升(C11 6.5.2.2) // 整数提升:char/short → int scc_hir_module_t *module = scc_ast2ir_mir_module(ctx); scc_hir_value_t *arg_value = scc_hir_module_get_value(module, arg_node); Assert(arg_value != nullptr); scc_hir_type_ref_t arg_type_ref = arg_value->type; Assert(arg_type_ref != 0); scc_hir_type_tag_t arg_tag = scc_hir_module_get_type(module, arg_type_ref)->tag; scc_hir_type_ref_t promoted = scc_ast2ir_integer_promotion(ctx, arg_type_ref); if (promoted != 0) { arg_node = scc_ast2ir_emit_conversion(ctx, arg_node, promoted); } else if (arg_tag == SCC_HIR_TYPE_f32) { // float → double(默认参数提升) scc_hir_type_t f64_desc; scc_hir_type_init(&f64_desc, SCC_HIR_TYPE_f64); scc_hir_type_ref_t f64_ref = scc_hir_builder_type(&ctx->builder, &f64_desc); arg_node = scc_ast2ir_emit_conversion(ctx, arg_node, f64_ref); } // 指针、i32/i64 等保持不变 } scc_vec_push(args, arg_node); } // 创建调用节点(需要查找函数定义) if (!callee_func) { LOG_ERROR("Function %s not found", expr->call.callee->identifier._target->name); } scc_hir_value_ref_t node = scc_hir_builder_call( &ctx->builder, callee_func, args.data, args.size); scc_vec_free(args); return node; } case SCC_AST_EXPR_ARRAY_SUBSCRIPT: { LOG_DEBUG(" array subscript"); scc_hir_value_ref_t base_ptr = scc_ast2ir_expr(ctx, expr->subscript.array, true); // 2. 计算下标值 scc_hir_value_ref_t index = scc_ast2ir_expr(ctx, expr->subscript.index, false); // 保证 index 至少 64 位,防止后端寄存器分配时宽度错误 scc_hir_type_ref_t idx_type = scc_hir_module_get_value(scc_ast2ir_mir_module(ctx), index)->type; if (idx_type != SCC_CFG_ID_nullptr && scc_hir_module_type_size(scc_ast2ir_mir_module(ctx), idx_type) < sizeof(void *) * 8) { scc_hir_type_t ptrw_desc; scc_hir_type_init(&ptrw_desc, SCC_HIR_TYPE_u64); scc_hir_type_ref_t ptrw_ref = scc_hir_builder_type(&ctx->builder, &ptrw_desc); index = scc_ast2ir_emit_conversion(ctx, index, ptrw_ref); } // 3. 生成 getptr(GEP) scc_hir_value_ref_t elem_ptr = scc_hir_builder_get_elem_ptr(&ctx->builder, base_ptr, index); // 4. 根据左值/右值返回 if (is_lvalue) { return elem_ptr; // 作为左值:返回地址 } else { return scc_hir_builder_load(&ctx->builder, elem_ptr); // 作为右值:加载值 } } case SCC_AST_EXPR_MEMBER: { LOG_DEBUG(" member access field_idx=%zu", expr->member._target_idx); scc_hir_value_ref_t base_ptr = scc_ast2ir_expr(ctx, expr->member.base, true); // 2. 通过偏移生成字段地址 // 需要基对象类型来计算索引:假设 sema 填好了 _target_idx usize field_idx = expr->member._target_idx; scc_ap_t idx_ap; scc_ap_set_int(&idx_ap, field_idx); scc_hir_value_ref_t idx_val = scc_hir_builder_integer( &ctx->builder, scc_hir_builder_type_u64(&ctx->builder), &idx_ap); scc_hir_value_ref_t field_ptr = scc_hir_builder_get_elem_ptr(&ctx->builder, base_ptr, idx_val); if (is_lvalue) return field_ptr; else return scc_hir_builder_load(&ctx->builder, field_ptr); } case SCC_AST_EXPR_PTR_MEMBER: { LOG_DEBUG(" ptr member access"); scc_hir_value_ref_t obj_ptr = scc_ast2ir_expr(ctx, expr->member.base, false); // 2. 解引用得到对象地址,再访问成员 // 但更简单:先 load 出对象值?不对:obj // 是指向结构体的指针,我们需要指针的地址? 实际上,obj->field 相当于 // (*(obj)).field,所以可以直接用 obj 作为基地址进行 get_elem_ptr // 因为 get_elem_ptr 接收一个指针,obj 本身就是指向结构体的指针。 usize field_idx = expr->member._target_idx; scc_ap_t idx_ap; scc_ap_set_int(&idx_ap, field_idx); scc_hir_value_ref_t idx_val = scc_hir_builder_integer( &ctx->builder, scc_hir_builder_type_u64(&ctx->builder), &idx_ap); scc_hir_value_ref_t field_ptr = scc_hir_builder_get_elem_ptr(&ctx->builder, obj_ptr, idx_val); if (is_lvalue) return field_ptr; else return scc_hir_builder_load(&ctx->builder, field_ptr); } case SCC_AST_EXPR_CAST: { // 1. 转换操作数(右值) scc_hir_value_ref_t operand = scc_ast2ir_expr(ctx, expr->cast.expr, false); // 2. 转换目标类型为 IR 类型 scc_hir_type_ref_t target_type = scc_ast2ir_type(ctx, expr->cast.type); // 3. 确定转换模式(SEXT / ZEXT / TRUNC) // 这里用简单的启发式:根据大小变化决定 scc_hir_type_t *src_type = scc_hir_module_get_type_by_value( scc_ast2ir_mir_module(ctx), operand); usize src_size = scc_hir_module_type_size(scc_ast2ir_mir_module(ctx), operand); usize dst_size = scc_hir_module_type_size(scc_ast2ir_mir_module(ctx), target_type); int conv_kind; if (dst_size > src_size) { // 目标更大,需要扩展。根据源类型有无符号决定符号扩展还是零扩展 conv_kind = scc_hir_type_is_signed(src_type->tag) ? SCC_HIR_CONV_SEXT : SCC_HIR_CONV_ZEXT; } else if (dst_size < src_size) { conv_kind = SCC_HIR_CONV_TRUNC; } else { // 同大小,可以视为 NOP 转换,或者直接返回操作数 return operand; // 或创建一个 CONV_SEXT 也没问题 } // 4. 构造转换节点 scc_hir_value_t conv_node = { .tag = SCC_HIR_VALUE_TAG_CONV, .type = target_type, .data.conv.operand = operand, .data.conv.target_type = target_type, .data.conv.conv_type = conv_kind, }; return scc_hir_module_add_value(scc_ast2ir_mir_module(ctx), &conv_node); } case SCC_AST_EXPR_SIZE_OF: { // 1. 将 sizeof 的操作数(类型或表达式)转换为 IR 类型 scc_hir_type_ref_t hir_type; if (expr->attr_of.type) { // sizeof(type) hir_type = scc_ast2ir_type(ctx, expr->attr_of.type); } else if (expr->attr_of.expr) { // sizeof expression:计算表达式类型 // 注意:sizeof // 不对表达式求值,只需类型,这里假设语义分析已经标注了类型 scc_hir_value_ref_t dummy = scc_ast2ir_expr(ctx, expr->attr_of.expr, false); hir_type = scc_hir_module_get_value(scc_ast2ir_mir_module(ctx), dummy) ->type; } else { scc_ap_t val; val.data.digit = 0; LOG_ERROR("[ast2ir] unsupported"); return scc_hir_builder_integer( &ctx->builder, scc_hir_builder_type_u64(&ctx->builder), &val); } // 2. 计算大小 usize dst_size = scc_hir_module_type_size(scc_ast2ir_mir_module(ctx), hir_type); scc_ap_t val; val.data.digit = dst_size / 8; return scc_hir_builder_integer( &ctx->builder, scc_hir_builder_type_u64(&ctx->builder), &val); } case SCC_AST_EXPR_ALIGN_OF: { TODO(); // return scc_hir_builder_integer( // &ctx->builder, scc_hir_builder_type_u64(&ctx->builder), val); } case SCC_AST_EXPR_COMPOUND: { // 1. 从 base 子节点取得类型(base 一定是 SCC_AST_EXPR_LVALUE) Assert(expr->compound.base != nullptr); Assert(expr->compound.base->base.type == SCC_AST_EXPR_LVALUE); scc_ast_qual_type_t *ast_type = expr->compound.base->lvalue.type; scc_hir_type_ref_t type_ref = scc_ast2ir_type(ctx, ast_type); const scc_hir_type_t *type = scc_hir_module_get_type(scc_ast2ir_mir_module(ctx), type_ref); // 2. 分配栈上临时存储 scc_hir_value_ref_t storage = scc_hir_builder_alloca(&ctx->builder, type_ref, "compound_literal"); // 3. 根据类型调用对应的初始化函数 if (type->tag == SCC_HIR_TYPE_ARRAY) { emit_array_initialization(ctx, storage, type, expr); } else if (type->tag == SCC_HIR_TYPE_STRUCT || type->tag == SCC_HIR_TYPE_UNION) { emit_aggregate_initialization(ctx, storage, type, expr); } else { // 标量:取初始化列表的第一个值 Assert(expr->compound.rhs_exprs.size > 0); scc_ast_expr_t *init_expr = scc_vec_at(expr->compound.rhs_exprs, 0); scc_hir_value_ref_t val = scc_ast2ir_expr(ctx, init_expr, false); scc_hir_builder_store(&ctx->builder, storage, val); } // 4. 根据左值 / 右值返回 if (is_lvalue) { return storage; // 左值 } else { // 右值:数组退化为首元素指针,结构体暂时返回地址 if (type->tag == SCC_HIR_TYPE_ARRAY) { return scc_hir_builder_get_elem_ptr(&ctx->builder, storage, SCC_HIR_REF_nullptr); } else if (type->tag == SCC_HIR_TYPE_STRUCT || type->tag == SCC_HIR_TYPE_UNION) { return storage; // 调用者会 memcpy } else { return scc_hir_builder_load(&ctx->builder, storage); } } } break; case SCC_AST_EXPR_LVALUE: { UNREACHABLE(); // should only appear as compound.base } break; case SCC_AST_EXPR_BUILTIN: { TODO(); } break; case SCC_AST_EXPR_INT_LITERAL: { // FIXME maybe using some array to int; scc_hir_type_ref_t type_ref = scc_hir_builder_type_i32(&ctx->builder); scc_ap_t value; scc_ap_from_cstr(&value, expr->literal.lexme, 0); return scc_hir_builder_integer(&ctx->builder, type_ref, &value); } // SCC_AST_EXPR_FLOAT_LITERAL, // 浮点字面量 case SCC_AST_EXPR_CHAR_LITERAL: { // FIXME just 'a' '\n' const char *lexme = expr->literal.lexme; Assert(lexme[0] == '\''); i8 int_lit = 0; if (lexme[1] == '\\') { switch (lexme[2]) { case 'a': int_lit = '\a'; break; case 'b': int_lit = '\b'; break; case 'f': int_lit = '\f'; break; case 'n': int_lit = '\n'; break; case 'r': int_lit = '\r'; } } else { int_lit = lexme[1]; } scc_ap_t value; // FIXME i32 maybe false, we need i8 or u8 scc_hir_type_ref_t type_ref = scc_hir_builder_type_i32(&ctx->builder); scc_ap_set_int(&value, int_lit); return scc_hir_builder_integer(&ctx->builder, type_ref, &value); } case SCC_AST_EXPR_STRING_LITERAL: { // const_string 返回指向常量区字符串的指针,左右值都返回此指针 scc_hir_value_ref_t value = scc_hir_builder_const_string(&ctx->builder, expr->literal.lexme, scc_strlen(expr->literal.lexme)); return value; } case SCC_AST_EXPR_IDENTIFIER: { if (expr->identifier._target == nullptr) { LOG_ERROR("unknown identifier %s", expr->identifier.name); } // FIXME hack hashtable scc_hir_value_ref_t in = (scc_hir_value_ref_t)(usize)scc_hashtable_get( &ctx->ast2ir_cache, expr->identifier._target); Assert(in != 0); if (is_lvalue) { return in; } else { // 右值:如果是数组类型,退化为指针(返回地址) scc_hir_type_t *ir_type = scc_hir_module_get_type_by_value( scc_ast2ir_mir_module(ctx), in); if (ir_type->tag == SCC_HIR_TYPE_PTR) { scc_hir_type_t *target_type = scc_hir_module_get_type( scc_ast2ir_mir_module(ctx), ir_type->data.pointer.base); if (target_type->tag == SCC_HIR_TYPE_ARRAY) { // 生成 getptr 获取数组首地址 return scc_hir_builder_get_elem_ptr(&ctx->builder, in, SCC_HIR_REF_nullptr); } else { // 标量类型:加载值 return scc_hir_builder_load(&ctx->builder, in); } } else { return in; } } } default: LOG_FATAL("Unsupported expression type: %d", expr->base.type); return 0; } UNREACHABLE(); }