Files
scc/libs/ast2ir/src/scc_ast2ir_expr.c
zzy 88846d7479 refactor(log): 统一日志系统并添加链接器实现
- 为所有模块添加统一的 scc_*_log.h 日志头文件,删除旧的 lexer_log.h/c
- 将运行时日志从 scc_utils 迁移到 scc_core 目录,统一日志管理
- 在解析器表达式/语句/类型解析中添加 LOG_TRACE 调试日志
- 实现 SCCF 链接器 (sccf_linker) 支持多目标文件链接
- 重构 CLI 主程序 (main.c/config.c),新增 cmd_log.h 调试支持
- 优化 x86 指令编码操作数对齐检查
- 修复预处理器的指令处理和宏展开逻辑
2026-06-05 13:07:41 +08:00

929 lines
40 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include <scc_ast2ir_log.h>
#include <scc_ast2ir.h>
#include <scc_ast_def.h>
#include <scc_ast_utils.h>
#include <scc_hir_builder.h>
#include <scc_hir_def.h>
// 判断是否为算术类型(整数或浮点)
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. 生成 getptrGEP
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();
}