diff --git a/libs/ast/include/scc_ast_def.h b/libs/ast/include/scc_ast_def.h index ebf0272..5fa660a 100644 --- a/libs/ast/include/scc_ast_def.h +++ b/libs/ast/include/scc_ast_def.h @@ -323,7 +323,7 @@ struct scc_ast_expr { scc_ast_expr_t *expr; } cast; // sizeof / _Alignof / ... - union { + struct { scc_ast_qual_type_t *type; scc_ast_expr_t *expr; } attr_of; diff --git a/libs/ast2ir/cbuild.toml b/libs/ast2ir/cbuild.toml index 3809437..067c9fb 100644 --- a/libs/ast2ir/cbuild.toml +++ b/libs/ast2ir/cbuild.toml @@ -7,6 +7,7 @@ description = "" dependencies = [ { name = "scc_ast", path = "../ast" }, { name = "scc_hir", path = "../ir/hir" }, + { name = "type_abi", path = "../target/type_abi" }, ] # features = {} # default_features = [] diff --git a/libs/ast2ir/include/scc_ast2ir.h b/libs/ast2ir/include/scc_ast2ir.h index eb640f6..228317c 100644 --- a/libs/ast2ir/include/scc_ast2ir.h +++ b/libs/ast2ir/include/scc_ast2ir.h @@ -12,8 +12,7 @@ typedef struct { scc_hashtable_t continue_cache; ///< continue cache scc_hashtable_t symtab; ///< symbol to ir_ref scc_hashtable_t type_cache; ///< scc_ast_canon_type_t* -> scc_hir_type_ref_t - // scc_strpool_t strpool; ///< string pool - const scc_abi_type_calc_t *abi; + const scc_type_abi_t *type_abi; cbool hint_using_value; // 转换时尽可能使用value而不是alloc scc_ast_module_t *ast_module; @@ -23,7 +22,7 @@ static inline scc_hir_module_t *scc_ast2ir_mir_module(scc_ast2ir_ctx_t *ctx) { return &ctx->builder.cprog->module; } -void scc_ast2ir_ctx_init(scc_ast2ir_ctx_t *ctx, const scc_abi_type_calc_t *abi, +void scc_ast2ir_ctx_init(scc_ast2ir_ctx_t *ctx, const scc_type_abi_t *type_abi, scc_ast_module_t *ast_module, scc_hir_cprog_t *cprog); void scc_ast2ir_ctx_drop(scc_ast2ir_ctx_t *ctx); @@ -42,6 +41,38 @@ scc_hir_type_ref_t scc_ast2ir_parse_base_type(scc_ast2ir_ctx_t *ctx, const scc_ast_qual_type_t *ast_type); +// Utils + +// 判断 AST 参数是否为 ... 生成的假 VA_LIST 参数 +static cbool is_variadic_marker(const scc_ast_decl_t *decl_param) { + return decl_param->name == nullptr && + decl_param->param.type->base.type == SCC_AST_TYPE_BUILTIN && + scc_ast_canon_type(decl_param->param.type)->builtin.type == + SCC_AST_BUILTIN_TYPE_VA_LIST; +} + +// 计算函数类型中的固定参数个数(去掉尾部的 ... 标记) +static int fixed_param_count(const scc_ast_canon_type_t *canon) { + int n = (int)scc_vec_size(canon->function.params); + if (n > 0) { + const scc_ast_decl_t *last = + scc_vec_at(canon->function.params, (usize)(n - 1)); + if (is_variadic_marker(last)) + return n - 1; + } + return n; +} + +void emit_array_initialization(scc_ast2ir_ctx_t *ctx, + scc_hir_value_ref_t array_ptr, + const scc_hir_type_t *array_type, + const scc_ast_expr_t *init_expr); + +void emit_aggregate_initialization(scc_ast2ir_ctx_t *ctx, + scc_hir_value_ref_t base_ptr, + const scc_hir_type_t *type, + const scc_ast_expr_t *init_expr); + // ====== 类型提升(Type Promotion)接口 ====== /** diff --git a/libs/ast2ir/include/scc_type_abi.h b/libs/ast2ir/include/scc_type_abi.h deleted file mode 100644 index 3776475..0000000 --- a/libs/ast2ir/include/scc_type_abi.h +++ /dev/null @@ -1,106 +0,0 @@ -/** - * @file scc_abi_type.h - * @brief 目标无关的类型布局描述接口 - * @note 本模块仅定义接口。 - */ - -#ifndef __SCC_ABI_TYPE_H__ -#define __SCC_ABI_TYPE_H__ - -#include - -/** - * @brief ABI 基础类型类别枚举。 - * - * 用于快速查询目标预定义的基本类型属性。复杂类型(指针、数组、结构体) - * 通过组合与递归计算。 - */ -typedef enum scc_abi_base_type_kind { - SCC_ABI_TYPE_VOID, - SCC_ABI_TYPE_VA_LIST, - SCC_ABI_TYPE_CHAR, - SCC_ABI_TYPE_I_CHAR, - SCC_ABI_TYPE_U_CHAR, - SCC_ABI_TYPE_I_SHORT, - SCC_ABI_TYPE_U_SHORT, - SCC_ABI_TYPE_I_INT, - SCC_ABI_TYPE_U_INT, - SCC_ABI_TYPE_I_LONG, - SCC_ABI_TYPE_U_LONG, - SCC_ABI_TYPE_I_LONG_LONG, - SCC_ABI_TYPE_U_LONG_LONG, - SCC_ABI_TYPE_PTR, - SCC_ABI_TYPE_FLOAT, - SCC_ABI_TYPE_DOUBLE, - SCC_ABI_TYPE_USIZE, - SCC_ABI_TYPE_ISIZE, - /* 可扩展:I128, F16, F128, VECTOR, ... */ -} scc_abi_base_type_kind_t; - -/** - * @brief 单个类型的布局信息。 - */ -typedef struct scc_abi_type_layout { - int size; /**< 类型占用的字节数 */ - int alignment; /**< 类型的对齐要求(字节边界) */ -} scc_abi_type_layout_t; - -typedef struct { - scc_abi_base_type_kind_t kind; - scc_abi_type_layout_t layout; -} scc_abi_base_type_impl_t; -#define SCC_ABI_BASE_TYPE_IMPL(type, bytes_size, alians) \ - [type] = { \ - .kind = type, \ - .layout.size = bytes_size, \ - .layout.alignment = alians, \ - } - -/** - * @brief 单个结构体字段的布局信息。 - * 由目标布局算法填充,用于 IR 的 getelementptr 常量索引计算。 - */ -typedef struct scc_abi_field_layout { - int offset; /**< 字段相对于结构体基址的字节偏移 */ - int size; /**< 字段自身大小 */ - int alignment; /**< 字段的对齐要求 */ -} scc_abi_field_layout_t; - -typedef SCC_VEC(scc_abi_field_layout_t) scc_abi_field_layout_vec_t; - -/** - * @brief 获取基本类型的布局信息。 - * - * 目标必须实现此函数,为每个 scc_abi_base_type_kind_t 返回正确的 - * size/alignment。 - * - * @param kind 基本类型类别 - * @param layout 输出参数,存放布局信息 - * @return 成功返回 0,若 kind 不支持则返回 -1 - */ -static inline void -scc_abi_get_base_type_layout(const scc_abi_base_type_impl_t *impls, - scc_abi_base_type_kind_t kind, - scc_abi_type_layout_t *layout) { - if (impls[kind].kind != kind) - Panic("invalid base type kind"); - *layout = impls[kind].layout; -} - -typedef struct scc_abi_type_calc scc_abi_type_calc_t; - -void scc_abi_compute_ast_type_layout(const scc_abi_type_calc_t *ctx, void *type, - scc_abi_type_layout_t *layout); - -typedef struct scc_abi_type_calc { - void *ctx; - const scc_abi_base_type_impl_t *impls; - /// @brief 可以是系统内置的结构,比如 struct int128_t - void (*compute_type_layout)(const scc_abi_type_calc_t *ctx, void *type, - scc_abi_type_layout_t *layout); - /// @brief - void (*compute_field_layout)(const scc_abi_type_calc_t *ctx, void *type, - scc_abi_field_layout_vec_t *field_layouts); -} scc_abi_type_calc_t; - -#endif /* __SCC_ABI_TYPE_H__ */ diff --git a/libs/ast2ir/include/target/scc_abi_dummy.h b/libs/ast2ir/include/target/scc_abi_dummy.h deleted file mode 100644 index aa17d66..0000000 --- a/libs/ast2ir/include/target/scc_abi_dummy.h +++ /dev/null @@ -1,4 +0,0 @@ -#ifndef __SCC_ABI_DUMMY_H__ -#define __SCC_ABI_DUMMY_H__ - -#endif /* __SCC_ABI_DUMMY_H__ */ diff --git a/libs/ast2ir/include/target/scc_abi_win_x64_pc.h b/libs/ast2ir/include/target/scc_abi_win_x64_pc.h deleted file mode 100644 index 8ca7e26..0000000 --- a/libs/ast2ir/include/target/scc_abi_win_x64_pc.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef __SCC_ABI_WIN_X64_PC_H__ -#define __SCC_ABI_WIN_X64_PC_H__ -/** - * @brief Windows x64 ABI Type - * @details - * https://learn.microsoft.com/zh-cn/cpp/build/x64-software-conventions?view=msvc-180 - */ - -#include "../scc_type_abi.h" - -static const scc_abi_base_type_impl_t scc_abi_base_type_impls[] = { - /** - * @brief - * https://learn.microsoft.com/zh-cn/cpp/build/x64-calling-convention?view=msvc-180#varargs - * 如果通过 vararg (例如省略号参数) 传递参数,则需遵守常规寄存器参数传递约定. - * 该约定规定了将第 5个及后面的参数溢出到堆栈中. - * 被调用方负责转储带有其地址的参数. - * (仅适用于浮点值)如果被调用方希望在整数寄存器中使用浮点值,则整数寄存器和浮点数寄存器都必须包含该值. - */ - SCC_ABI_BASE_TYPE_IMPL(SCC_ABI_TYPE_VA_LIST, 4, 4), - SCC_ABI_BASE_TYPE_IMPL(SCC_ABI_TYPE_VOID, 0, 0), - SCC_ABI_BASE_TYPE_IMPL(SCC_ABI_TYPE_CHAR, 1, 1), - SCC_ABI_BASE_TYPE_IMPL(SCC_ABI_TYPE_I_CHAR, 1, 1), - SCC_ABI_BASE_TYPE_IMPL(SCC_ABI_TYPE_U_CHAR, 1, 1), - SCC_ABI_BASE_TYPE_IMPL(SCC_ABI_TYPE_I_SHORT, 2, 2), - SCC_ABI_BASE_TYPE_IMPL(SCC_ABI_TYPE_U_SHORT, 2, 2), - SCC_ABI_BASE_TYPE_IMPL(SCC_ABI_TYPE_I_INT, 4, 4), - SCC_ABI_BASE_TYPE_IMPL(SCC_ABI_TYPE_U_INT, 4, 4), - SCC_ABI_BASE_TYPE_IMPL(SCC_ABI_TYPE_I_LONG, 4, 4), - SCC_ABI_BASE_TYPE_IMPL(SCC_ABI_TYPE_U_LONG, 4, 4), - SCC_ABI_BASE_TYPE_IMPL(SCC_ABI_TYPE_I_LONG_LONG, 8, 8), - SCC_ABI_BASE_TYPE_IMPL(SCC_ABI_TYPE_U_LONG_LONG, 8, 8), - SCC_ABI_BASE_TYPE_IMPL(SCC_ABI_TYPE_PTR, 8, 8), - SCC_ABI_BASE_TYPE_IMPL(SCC_ABI_TYPE_FLOAT, 4, 4), - SCC_ABI_BASE_TYPE_IMPL(SCC_ABI_TYPE_DOUBLE, 8, 8), - SCC_ABI_BASE_TYPE_IMPL(SCC_ABI_TYPE_USIZE, 8, 8), - SCC_ABI_BASE_TYPE_IMPL(SCC_ABI_TYPE_ISIZE, 8, 8), -}; - -static const scc_abi_type_calc_t scc_ast_abi_impl = { - .impls = scc_abi_base_type_impls, - .ctx = nullptr, - .compute_type_layout = scc_abi_compute_ast_type_layout, - .compute_field_layout = nullptr, -}; -#ifdef SCC_ABI_IMPLIMENT -#endif - -#endif /* __SCC_ABI_WIN_X64_PC_H__ */ diff --git a/libs/ast2ir/src/scc_ast2ir.c b/libs/ast2ir/src/scc_ast2ir.c index bef5181..6e2feb2 100644 --- a/libs/ast2ir/src/scc_ast2ir.c +++ b/libs/ast2ir/src/scc_ast2ir.c @@ -4,170 +4,6 @@ #include #include -// 判断 AST 参数是否为 ... 生成的假 VA_LIST 参数 -static cbool is_variadic_marker(const scc_ast_decl_t *decl_param) { - return decl_param->name == nullptr && - decl_param->param.type->base.type == SCC_AST_TYPE_BUILTIN && - scc_ast_canon_type(decl_param->param.type)->builtin.type == - SCC_AST_BUILTIN_TYPE_VA_LIST; -} - -// 计算函数类型中的固定参数个数(去掉尾部的 ... 标记) -static int fixed_param_count(const scc_ast_canon_type_t *canon) { - int n = (int)scc_vec_size(canon->function.params); - if (n > 0) { - const scc_ast_decl_t *last = - scc_vec_at(canon->function.params, (usize)(n - 1)); - if (is_variadic_marker(last)) - return n - 1; - } - return n; -} - -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; - } -} - -// 判断是否为算术类型(整数或浮点) -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 void emit_array_initialization(scc_ast2ir_ctx_t *ctx, - scc_hir_value_ref_t array_ptr, - const scc_hir_type_t *array_type, - const scc_ast_expr_t *init_expr) { - Assert(array_type->tag == SCC_HIR_TYPE_ARRAY); - scc_hir_type_ref_t elem_type_ref = array_type->data.array.base; - const scc_hir_type_t *elem_type = - scc_hir_module_get_type(scc_ast2ir_mir_module(ctx), elem_type_ref); - usize array_len = array_type->data.array.len; - - // 字符串字面量初始化:直接 memcpy - if (init_expr->base.type == SCC_AST_EXPR_STRING_LITERAL) { - scc_hir_value_ref_t str_val = scc_ast2ir_expr(ctx, init_expr, false); - scc_ap_t len_ap; - scc_ap_set_int(&len_ap, array_len); - scc_hir_value_ref_t len_ref = scc_hir_builder_integer( - &ctx->builder, scc_hir_builder_type_u64(&ctx->builder), &len_ap); - scc_hir_builder_builtin_memcpy(&ctx->builder, array_ptr, str_val, - len_ref); - return; - } - - // 复合初始化:逐个元素 store - if (init_expr->base.type != SCC_AST_EXPR_COMPOUND) { - Panic("unsupported initializer for array"); - } - - // 遍历初始化列表 - usize idx = 0; - scc_vec_foreach(init_expr->compound.rhs_exprs, i) { - scc_ast_expr_t *elem_expr = - scc_vec_at(init_expr->compound.rhs_exprs, i); - Assert(elem_expr != nullptr); - if (idx >= array_len) - break; // 防止溢出 - - // 生成元素地址:array_ptr + idx * elem_size - scc_ap_t offset_ap; - scc_ap_set_int(&offset_ap, idx); - scc_hir_value_ref_t idx_val = scc_hir_builder_integer( - &ctx->builder, scc_hir_builder_type_u64(&ctx->builder), &offset_ap); - scc_hir_value_ref_t elem_ptr = - scc_hir_builder_get_elem_ptr(&ctx->builder, array_ptr, idx_val); - - // 递归处理:如果元素本身是数组且初始化表达式是复合初始化,需要嵌套处理 - if (elem_type->tag == SCC_HIR_TYPE_ARRAY && - elem_expr->base.type == SCC_AST_EXPR_COMPOUND) { - // 递归调用自身,但注意 elem_ptr 已经是子数组的首地址 - emit_array_initialization(ctx, elem_ptr, elem_type, elem_expr); - } else { - // 标量元素:计算右值并 store - scc_hir_value_ref_t val = scc_ast2ir_expr(ctx, elem_expr, false); - scc_hir_builder_store(&ctx->builder, elem_ptr, val); - } - idx++; - } - // 如果初始化列表元素少于数组长度,剩余元素默认零初始化(C 标准要求) - // 这里简单忽略,实际可生成 memset 循环,但为简化暂不处理 -} - -static void emit_aggregate_initialization(scc_ast2ir_ctx_t *ctx, - scc_hir_value_ref_t base_ptr, - const scc_hir_type_t *type, - const scc_ast_expr_t *init_expr) { - Assert(type->tag == SCC_HIR_TYPE_STRUCT || type->tag == SCC_HIR_TYPE_UNION); - if (init_expr->base.type != SCC_AST_EXPR_COMPOUND) { - Panic("expected compound initializer"); - } - usize idx = 0; - scc_vec_foreach(init_expr->compound.rhs_exprs, i) { - if (idx >= type->data.aggregate.fields.size) - break; - scc_ast_expr_t *field_init = - scc_vec_at(init_expr->compound.rhs_exprs, i); - scc_hir_type_ref_t field_type_ref = - scc_vec_at(type->data.aggregate.fields, idx); - const scc_hir_type_t *field_type = - scc_hir_module_get_type(scc_ast2ir_mir_module(ctx), field_type_ref); - - scc_ap_t idx_ap; - scc_ap_set_int(&idx_ap, 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 (field_type->tag == SCC_HIR_TYPE_ARRAY) { - emit_array_initialization(ctx, field_ptr, field_type, field_init); - } else if (field_type->tag == SCC_HIR_TYPE_STRUCT || - field_type->tag == SCC_HIR_TYPE_UNION) { - emit_aggregate_initialization(ctx, field_ptr, field_type, - field_init); - } else { - scc_hir_value_ref_t val = scc_ast2ir_expr(ctx, field_init, false); - scc_hir_builder_store(&ctx->builder, field_ptr, val); - } - idx++; - } -} // static inline void parse_struct_union_layout(scc_ast_qual_type_t *type) {} // 辅助函数:计算数组实际长度(如果原长度为0) @@ -345,884 +181,6 @@ scc_hir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx, return scc_hir_builder_type(&ctx->builder, &ir_type); } -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; - } - - cbool is_assign = true; - switch (expr->base.type) { - case SCC_AST_EXPR_BINARY: { - 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: { - 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: { - 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: { - // 转换参数 - 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: { - // 1. 计算数组/指针基址(右值,得到地址) - 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_t *idx_type = - scc_hir_module_get_type_by_value(scc_ast2ir_mir_module(ctx), index); - if (idx_type != nullptr && - scc_hir_module_type_size(scc_ast2ir_mir_module(ctx), idx_type) < - sizeof(void *)) { - 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: { - // 1. 获取基对象的左值(地址) - 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: { - // 1. 计算指针值(obj->field 等价于 (*obj).field) - 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); - scc_hir_type_t *dst_type = - scc_hir_module_get_type(scc_ast2ir_mir_module(ctx), target_type); - - usize src_size = scc_hir_module_type_size( - scc_ast2ir_mir_module(ctx), - src_type); // 你可能有这个函数,否则自行计算 - usize dst_size = - scc_hir_module_type_size(scc_ast2ir_mir_module(ctx), dst_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. 计算大小 - const scc_hir_type_t *type = - scc_hir_module_get_type(scc_ast2ir_mir_module(ctx), hir_type); - usize dst_size = - scc_hir_module_type_size(scc_ast2ir_mir_module(ctx), type); - - scc_ap_t val; - val.data.digit = dst_size; - 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: { - // FIXME - scc_hir_value_ref_t value = - scc_hir_builder_const_string(&ctx->builder, expr->literal.lexme, - scc_strlen(expr->literal.lexme)); - if (is_lvalue) - TODO(); - 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(); -} - /** * @brief * @@ -1461,17 +419,35 @@ void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, const scc_ast_stmt_t *stmt) { break; } case SCC_AST_STMT_GOTO: { - // scc_hir_bblock_ref_t target = (usize)scc_hashtable_get( - // &ctx->ast2ir_cache, (void *)stmt->goto_stmt._target); - // Assert(target != SCC_HIR_REF_nullptr); - // scc_hir_builder_jump(&ctx->builder, target); + scc_ast_stmt_t *target_label = stmt->goto_stmt._target; + Assert(target_label != nullptr); + scc_hir_bblock_ref_t target = + (usize)scc_hashtable_get(&ctx->ast2ir_cache, (void *)target_label); + if (target == SCC_HIR_REF_nullptr) { + // 前向引用:预创建块,等 label handler 复用 + target = + scc_hir_builder_create_bblock(&ctx->builder, "goto_target"); + scc_hashtable_set(&ctx->ast2ir_cache, (void *)target_label, + (void *)target); + } + scc_hir_builder_jump(&ctx->builder, target); } break; case SCC_AST_STMT_LABEL: { - scc_hir_value_ref_t label_block = - scc_hir_builder_bblock(&ctx->builder, stmt->label_stmt.label); + scc_ast_stmt_t *label_stmt = stmt->label_stmt.stmt; + scc_hir_bblock_ref_t label_block = + (usize)scc_hashtable_get(&ctx->ast2ir_cache, (void *)stmt); + if (label_block == SCC_HIR_REF_nullptr) { + // goto 未预先创建,新建立即追加 + label_block = + scc_hir_builder_bblock(&ctx->builder, stmt->label_stmt.label); + } else { + // goto 已预创建,只需追加 + scc_hir_builder_append_bblock(&ctx->builder, label_block); + } scc_hir_builder_set_current_bblock(&ctx->builder, label_block); - scc_hashtable_set(&ctx->ast2ir_cache, stmt, (void *)label_block); - scc_ast2ir_stmt(ctx, stmt->label_stmt.stmt); + scc_hashtable_set(&ctx->ast2ir_cache, (void *)stmt, + (void *)label_block); + scc_ast2ir_stmt(ctx, label_stmt); } break; default: LOG_FATAL("Unsupported statement type: %d", stmt->base.type); @@ -1520,12 +496,19 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, const scc_ast_decl_t *decl, // 3. 分配变量(栈或全局) scc_hir_value_ref_t alloc_val_node; if (is_global) { - // 全局变量:需要生成全局分配,当前代码暂未实现,保留 TODO - // alloc_val_node = scc_hir_builder_global_alloca(&ctx->builder, - // final_type_ref, decl->name); - // scc_vec_push(builder->cprog->global_vals, alloc_val_node); - // 这里先返回,后续补充 - return; + scc_hir_value_ref_t init_val = SCC_HIR_REF_nullptr; + if (decl->var.init) { + if (final_type_desc.tag == SCC_HIR_TYPE_ARRAY || + final_type_desc.tag == SCC_HIR_TYPE_STRUCT || + final_type_desc.tag == SCC_HIR_TYPE_UNION) { + // TODO: 聚合类型全局初始化(需生成 .data 段数据) + } else { + init_val = scc_ast2ir_expr(ctx, decl->var.init, false); + } + } + alloc_val_node = scc_hir_builder_global_alloca( + &ctx->builder, final_type_ref, init_val); + scc_vec_push(ctx->builder.cprog->global_vals, alloc_val_node); } else { alloc_val_node = scc_hir_builder_alloca(&ctx->builder, final_type_ref, decl->name); @@ -1533,8 +516,8 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, const scc_ast_decl_t *decl, scc_hashtable_set(&ctx->ast2ir_cache, decl, (void *)(usize)alloc_val_node); - // 4. 处理初始化 - if (decl->var.init) { + // 4. 处理初始化(全局变量由 global_alloca 的 init_val 处理,跳过) + if (!is_global && decl->var.init) { // 再次借用 final_type 以判断是否为数组 const scc_hir_type_t *final_type; SCC_HIR_BUILDER_BEGIN_BORROW( @@ -1698,13 +681,13 @@ void scc_ast2ir_run(scc_ast2ir_ctx_t *ctx, } } -void scc_ast2ir_ctx_init(scc_ast2ir_ctx_t *ctx, const scc_abi_type_calc_t *abi, +void scc_ast2ir_ctx_init(scc_ast2ir_ctx_t *ctx, const scc_type_abi_t *type_abi, scc_ast_module_t *ast_module, scc_hir_cprog_t *cprog) { Assert(ctx != nullptr); - Assert(abi != nullptr); + Assert(type_abi != nullptr); Assert(ast_module != nullptr); Assert(cprog != nullptr); - ctx->abi = abi; + ctx->type_abi = type_abi; ctx->ast_module = ast_module; scc_hir_builder_init(&ctx->builder, cprog); scc_hashtable_usize_init(&ctx->ast2ir_cache); diff --git a/libs/ast2ir/src/scc_ast2ir_const.c b/libs/ast2ir/src/scc_ast2ir_const.c index 08ee055..5033368 100644 --- a/libs/ast2ir/src/scc_ast2ir_const.c +++ b/libs/ast2ir/src/scc_ast2ir_const.c @@ -1,6 +1,7 @@ #include #include #include +#include /* ---------- internal helpers ---------- */ @@ -54,9 +55,8 @@ static cbool apply_integer_truncation(scc_ast2ir_ctx_t *ctx, scc_ap_t *val, if (!is_ast_integer_type(target_type)) return false; - scc_abi_type_layout_t layout; - ctx->abi->compute_type_layout(ctx->abi, (void *)target_type, &layout); - int bits = layout.size * 8; + scc_hir_type_ref_t tref = scc_ast2ir_type(ctx, target_type); + int bits = scc_hir_type_size(scc_ast2ir_mir_module(ctx), tref, ctx->type_abi); if (bits >= (int)sizeof(scc_ap_digit) * 8) return true; /* no truncation needed */ @@ -342,34 +342,31 @@ cbool scc_ast2ir_eval_constant_int(scc_ast2ir_ctx_t *ctx, scc_ap_t *result, } case SCC_AST_EXPR_SIZE_OF: { - scc_abi_type_layout_t layout; if (expr->attr_of.type) { - ctx->abi->compute_type_layout(ctx->abi, (void *)expr->attr_of.type, - &layout); + scc_hir_type_ref_t tref = scc_ast2ir_type(ctx, expr->attr_of.type); + int size = scc_hir_type_size(scc_ast2ir_mir_module(ctx), tref, + ctx->type_abi); + scc_ap_set_int(result, size / 8); + return true; } else if (expr->attr_of.expr) { - /* sizeof expression: try to get the type through the ABI */ - /* For constant expressions, sema should have annotated the type */ - /* TODO: handle sizeof(expr) where expr is not a type */ return false; } else { return false; } - scc_ap_set_int(result, layout.size); - return true; } case SCC_AST_EXPR_ALIGN_OF: { - scc_abi_type_layout_t layout; if (expr->attr_of.type) { - ctx->abi->compute_type_layout(ctx->abi, (void *)expr->attr_of.type, - &layout); + scc_hir_type_ref_t tref = scc_ast2ir_type(ctx, expr->attr_of.type); + int align = scc_hir_type_align(scc_ast2ir_mir_module(ctx), tref, + ctx->type_abi); + scc_ap_set_int(result, align / 8); + return true; } else if (expr->attr_of.expr) { return false; } else { return false; } - scc_ap_set_int(result, layout.alignment); - return true; } case SCC_AST_EXPR_IDENTIFIER: diff --git a/libs/ast2ir/src/scc_ast2ir_expr.c b/libs/ast2ir/src/scc_ast2ir_expr.c new file mode 100644 index 0000000..c7521f7 --- /dev/null +++ b/libs/ast2ir/src/scc_ast2ir_expr.c @@ -0,0 +1,925 @@ +#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; + } + + cbool is_assign = true; + switch (expr->base.type) { + case SCC_AST_EXPR_BINARY: { + 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: { + 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: { + 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: { + // 转换参数 + 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: { + // 1. 计算数组/指针基址(右值,得到地址) + 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_t *idx_type = + scc_hir_module_get_type_by_value(scc_ast2ir_mir_module(ctx), index); + if (idx_type != 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: { + // 1. 获取基对象的左值(地址) + 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: { + // 1. 计算指针值(obj->field 等价于 (*obj).field) + 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); + scc_hir_type_t *dst_type = + scc_hir_module_get_type(scc_ast2ir_mir_module(ctx), target_type); + + usize src_size = scc_hir_module_type_size( + scc_ast2ir_mir_module(ctx), + src_type); // 你可能有这个函数,否则自行计算 + usize dst_size = + scc_hir_module_type_size(scc_ast2ir_mir_module(ctx), dst_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. 计算大小 + const scc_hir_type_t *type = + scc_hir_module_get_type(scc_ast2ir_mir_module(ctx), hir_type); + usize dst_size = + scc_hir_module_type_size(scc_ast2ir_mir_module(ctx), 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(); +} diff --git a/libs/ast2ir/src/scc_ast2ir_type.c b/libs/ast2ir/src/scc_ast2ir_type.c index 3ab7a51..fd56384 100644 --- a/libs/ast2ir/src/scc_ast2ir_type.c +++ b/libs/ast2ir/src/scc_ast2ir_type.c @@ -1,76 +1,106 @@ #include -scc_hir_type_ref_t -scc_ast2ir_parse_base_type(scc_ast2ir_ctx_t *ctx, - const scc_ast_qual_type_t *ast_type) { - scc_abi_type_layout_t layout; - // 映射内置类型 - ctx->abi->compute_type_layout(ctx->abi, (void *)ast_type, &layout); - switch (scc_ast_canon_type(ast_type)->builtin.type) { - // FIXME it not a void - case SCC_AST_BUILTIN_TYPE_VA_LIST: +static int ast_base_type_size(const scc_type_abi_t *abi, + scc_ast_builtin_type_t bt) { + switch (bt) { case SCC_AST_BUILTIN_TYPE_VOID: - return scc_hir_builder_type_void(&ctx->builder); + return 0; + case SCC_AST_BUILTIN_TYPE_VA_LIST: + return abi->va_list_size; case SCC_AST_BUILTIN_TYPE_BOOL: + return 1; + case SCC_AST_BUILTIN_TYPE_CHAR: case SCC_AST_BUILTIN_TYPE_SIGNED_CHAR: + case SCC_AST_BUILTIN_TYPE_UNSIGNED_CHAR: + return abi->char_size; case SCC_AST_BUILTIN_TYPE_SHORT: case SCC_AST_BUILTIN_TYPE_SIGNED_SHORT: + case SCC_AST_BUILTIN_TYPE_UNSIGNED_SHORT: + return abi->short_size; case SCC_AST_BUILTIN_TYPE_INT: case SCC_AST_BUILTIN_TYPE_SIGNED_INT: + case SCC_AST_BUILTIN_TYPE_UNSIGNED_INT: + return abi->int_size; case SCC_AST_BUILTIN_TYPE_LONG: case SCC_AST_BUILTIN_TYPE_SIGNED_LONG: + case SCC_AST_BUILTIN_TYPE_UNSIGNED_LONG: + return abi->long_size; case SCC_AST_BUILTIN_TYPE_LONG_LONG: case SCC_AST_BUILTIN_TYPE_SIGNED_LONG_LONG: - switch (layout.size) { - case 1: - return scc_hir_builder_type_i8(&ctx->builder); - case 2: - return scc_hir_builder_type_i16(&ctx->builder); - case 4: - return scc_hir_builder_type_i32(&ctx->builder); - case 8: - return scc_hir_builder_type_i64(&ctx->builder); - break; - default: - break; - } - break; - case SCC_AST_BUILTIN_TYPE_CHAR: - // TODO CHAR TO BE UNSIGNED CHAR + case SCC_AST_BUILTIN_TYPE_UNSIGNED_LONG_LONG: + return abi->long_long_size; + case SCC_AST_BUILTIN_TYPE_FLOAT: + return abi->float_size; + case SCC_AST_BUILTIN_TYPE_DOUBLE: + return abi->double_size; + case SCC_AST_BUILTIN_TYPE_LONG_DOUBLE: + return abi->long_double_size; + default: + Panic("Unsupported AST builtin type: %d", bt); + return 0; + } +} + +static cbool is_signed_builtin(scc_ast_builtin_type_t bt) { + switch (bt) { + case SCC_AST_BUILTIN_TYPE_BOOL: case SCC_AST_BUILTIN_TYPE_UNSIGNED_CHAR: case SCC_AST_BUILTIN_TYPE_UNSIGNED_SHORT: case SCC_AST_BUILTIN_TYPE_UNSIGNED_INT: case SCC_AST_BUILTIN_TYPE_UNSIGNED_LONG: case SCC_AST_BUILTIN_TYPE_UNSIGNED_LONG_LONG: - switch (layout.size) { - case 1: - return scc_hir_builder_type_u8(&ctx->builder); - case 2: - return scc_hir_builder_type_u16(&ctx->builder); - case 4: - return scc_hir_builder_type_u32(&ctx->builder); - case 8: - return scc_hir_builder_type_u64(&ctx->builder); - break; - default: - break; - } - break; + return false; + default: + return true; + } +} + +scc_hir_type_ref_t +scc_ast2ir_parse_base_type(scc_ast2ir_ctx_t *ctx, + const scc_ast_qual_type_t *ast_type) { + scc_ast_builtin_type_t bt = scc_ast_canon_type(ast_type)->builtin.type; + int size = ast_base_type_size(ctx->type_abi, bt); + + if (bt == SCC_AST_BUILTIN_TYPE_VOID || + bt == SCC_AST_BUILTIN_TYPE_VA_LIST) { + return scc_hir_builder_type_void(&ctx->builder); + } + + cbool is_signed = is_signed_builtin(bt); + + // 浮点类型 + switch (bt) { case SCC_AST_BUILTIN_TYPE_FLOAT: case SCC_AST_BUILTIN_TYPE_DOUBLE: - switch (layout.size) { + case SCC_AST_BUILTIN_TYPE_LONG_DOUBLE: + switch (size) { case 4: return scc_hir_builder_type_f32(&ctx->builder); case 8: return scc_hir_builder_type_f64(&ctx->builder); - break; default: - break; + Panic("Unsupported float size: %d", size); } default: - Panic("Unsupported AST type: %d", - scc_ast_canon_type(ast_type)->builtin.type); break; } - return SCC_HIR_REF_nullptr; + + // 整数类型 + switch (size) { + case 1: + return is_signed ? scc_hir_builder_type_i8(&ctx->builder) + : scc_hir_builder_type_u8(&ctx->builder); + case 2: + return is_signed ? scc_hir_builder_type_i16(&ctx->builder) + : scc_hir_builder_type_u16(&ctx->builder); + case 4: + return is_signed ? scc_hir_builder_type_i32(&ctx->builder) + : scc_hir_builder_type_u32(&ctx->builder); + case 8: + return is_signed ? scc_hir_builder_type_i64(&ctx->builder) + : scc_hir_builder_type_u64(&ctx->builder); + default: + Panic("Unsupported integer size: %d", size); + return SCC_HIR_REF_nullptr; + } } diff --git a/libs/ast2ir/src/scc_ast2ir_utils.c b/libs/ast2ir/src/scc_ast2ir_utils.c new file mode 100644 index 0000000..fd5dc1d --- /dev/null +++ b/libs/ast2ir/src/scc_ast2ir_utils.c @@ -0,0 +1,102 @@ +#include + +// 辅助函数:生成数组初始化代码 +void emit_array_initialization(scc_ast2ir_ctx_t *ctx, + scc_hir_value_ref_t array_ptr, + const scc_hir_type_t *array_type, + const scc_ast_expr_t *init_expr) { + Assert(array_type->tag == SCC_HIR_TYPE_ARRAY); + scc_hir_type_ref_t elem_type_ref = array_type->data.array.base; + const scc_hir_type_t *elem_type = + scc_hir_module_get_type(scc_ast2ir_mir_module(ctx), elem_type_ref); + usize array_len = array_type->data.array.len; + + // 字符串字面量初始化:直接 memcpy + if (init_expr->base.type == SCC_AST_EXPR_STRING_LITERAL) { + scc_hir_value_ref_t str_val = scc_ast2ir_expr(ctx, init_expr, false); + scc_ap_t len_ap; + scc_ap_set_int(&len_ap, array_len); + scc_hir_value_ref_t len_ref = scc_hir_builder_integer( + &ctx->builder, scc_hir_builder_type_u64(&ctx->builder), &len_ap); + scc_hir_builder_builtin_memcpy(&ctx->builder, array_ptr, str_val, + len_ref); + return; + } + + // 复合初始化:逐个元素 store + if (init_expr->base.type != SCC_AST_EXPR_COMPOUND) { + Panic("unsupported initializer for array"); + } + + // 遍历初始化列表 + usize idx = 0; + scc_vec_foreach(init_expr->compound.rhs_exprs, i) { + scc_ast_expr_t *elem_expr = + scc_vec_at(init_expr->compound.rhs_exprs, i); + Assert(elem_expr != nullptr); + if (idx >= array_len) + break; // 防止溢出 + + // 生成元素地址:array_ptr + idx * elem_size + scc_ap_t offset_ap; + scc_ap_set_int(&offset_ap, idx); + scc_hir_value_ref_t idx_val = scc_hir_builder_integer( + &ctx->builder, scc_hir_builder_type_u64(&ctx->builder), &offset_ap); + scc_hir_value_ref_t elem_ptr = + scc_hir_builder_get_elem_ptr(&ctx->builder, array_ptr, idx_val); + + // 递归处理:如果元素本身是数组且初始化表达式是复合初始化,需要嵌套处理 + if (elem_type->tag == SCC_HIR_TYPE_ARRAY && + elem_expr->base.type == SCC_AST_EXPR_COMPOUND) { + // 递归调用自身,但注意 elem_ptr 已经是子数组的首地址 + emit_array_initialization(ctx, elem_ptr, elem_type, elem_expr); + } else { + // 标量元素:计算右值并 store + scc_hir_value_ref_t val = scc_ast2ir_expr(ctx, elem_expr, false); + scc_hir_builder_store(&ctx->builder, elem_ptr, val); + } + idx++; + } + // 如果初始化列表元素少于数组长度,剩余元素默认零初始化(C 标准要求) + // 这里简单忽略,实际可生成 memset 循环,但为简化暂不处理 +} + +void emit_aggregate_initialization(scc_ast2ir_ctx_t *ctx, + scc_hir_value_ref_t base_ptr, + const scc_hir_type_t *type, + const scc_ast_expr_t *init_expr) { + Assert(type->tag == SCC_HIR_TYPE_STRUCT || type->tag == SCC_HIR_TYPE_UNION); + if (init_expr->base.type != SCC_AST_EXPR_COMPOUND) { + Panic("expected compound initializer"); + } + usize idx = 0; + scc_vec_foreach(init_expr->compound.rhs_exprs, i) { + if (idx >= type->data.aggregate.fields.size) + break; + scc_ast_expr_t *field_init = + scc_vec_at(init_expr->compound.rhs_exprs, i); + scc_hir_type_ref_t field_type_ref = + scc_vec_at(type->data.aggregate.fields, idx); + const scc_hir_type_t *field_type = + scc_hir_module_get_type(scc_ast2ir_mir_module(ctx), field_type_ref); + + scc_ap_t idx_ap; + scc_ap_set_int(&idx_ap, 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 (field_type->tag == SCC_HIR_TYPE_ARRAY) { + emit_array_initialization(ctx, field_ptr, field_type, field_init); + } else if (field_type->tag == SCC_HIR_TYPE_STRUCT || + field_type->tag == SCC_HIR_TYPE_UNION) { + emit_aggregate_initialization(ctx, field_ptr, field_type, + field_init); + } else { + scc_hir_value_ref_t val = scc_ast2ir_expr(ctx, field_init, false); + scc_hir_builder_store(&ctx->builder, field_ptr, val); + } + idx++; + } +} diff --git a/libs/ast2ir/src/scc_type_abi.c b/libs/ast2ir/src/scc_type_abi.c deleted file mode 100644 index a46efea..0000000 --- a/libs/ast2ir/src/scc_type_abi.c +++ /dev/null @@ -1,76 +0,0 @@ -#include -#include -#include - -void scc_abi_compute_ast_type_layout(const scc_abi_type_calc_t *ctx, void *type, - scc_abi_type_layout_t *layout) { - scc_ast_qual_type_t *ast_type = type; - scc_abi_base_type_kind_t kind = SCC_ABI_TYPE_VOID; - switch (scc_ast_canon_type(ast_type)->builtin.type) { - case SCC_AST_BUILTIN_TYPE_VA_LIST: - kind = SCC_ABI_TYPE_VA_LIST; - break; - case SCC_AST_BUILTIN_TYPE_BOOL: - kind = SCC_ABI_TYPE_I_INT; - break; - case SCC_AST_BUILTIN_TYPE_VOID: - kind = SCC_ABI_TYPE_VOID; - break; - case SCC_AST_BUILTIN_TYPE_CHAR: - kind = SCC_ABI_TYPE_CHAR; - break; - case SCC_AST_BUILTIN_TYPE_UNSIGNED_CHAR: - kind = SCC_ABI_TYPE_U_CHAR; - break; - case SCC_AST_BUILTIN_TYPE_SIGNED_CHAR: - kind = SCC_ABI_TYPE_I_CHAR; - break; - case SCC_AST_BUILTIN_TYPE_SHORT: - kind = SCC_ABI_TYPE_I_SHORT; - break; - case SCC_AST_BUILTIN_TYPE_SIGNED_SHORT: - kind = SCC_ABI_TYPE_I_SHORT; - break; - case SCC_AST_BUILTIN_TYPE_UNSIGNED_SHORT: - kind = SCC_ABI_TYPE_U_SHORT; - break; - case SCC_AST_BUILTIN_TYPE_INT: - kind = SCC_ABI_TYPE_I_INT; - break; - case SCC_AST_BUILTIN_TYPE_SIGNED_INT: - kind = SCC_ABI_TYPE_I_INT; - break; - case SCC_AST_BUILTIN_TYPE_UNSIGNED_INT: - kind = SCC_ABI_TYPE_U_INT; - break; - case SCC_AST_BUILTIN_TYPE_LONG: - kind = SCC_ABI_TYPE_I_LONG; - break; - case SCC_AST_BUILTIN_TYPE_SIGNED_LONG: - kind = SCC_ABI_TYPE_I_LONG; - break; - case SCC_AST_BUILTIN_TYPE_UNSIGNED_LONG: - kind = SCC_ABI_TYPE_U_LONG; - break; - case SCC_AST_BUILTIN_TYPE_LONG_LONG: - kind = SCC_ABI_TYPE_I_LONG_LONG; - break; - case SCC_AST_BUILTIN_TYPE_SIGNED_LONG_LONG: - kind = SCC_ABI_TYPE_I_LONG_LONG; - break; - case SCC_AST_BUILTIN_TYPE_UNSIGNED_LONG_LONG: - kind = SCC_ABI_TYPE_U_LONG_LONG; - break; - case SCC_AST_BUILTIN_TYPE_FLOAT: - kind = SCC_ABI_TYPE_FLOAT; - break; - case SCC_AST_BUILTIN_TYPE_DOUBLE: - kind = SCC_ABI_TYPE_DOUBLE; - break; - default: - Panic("Unsupported AST type: %d", - scc_ast_canon_type(ast_type)->builtin.type); - break; - } - scc_abi_get_base_type_layout(ctx->impls, kind, layout); -} diff --git a/libs/ir/hir/cbuild.toml b/libs/ir/hir/cbuild.toml index b26f9a4..44ee570 100644 --- a/libs/ir/hir/cbuild.toml +++ b/libs/ir/hir/cbuild.toml @@ -8,6 +8,7 @@ dependencies = [ { name = "scc_cfg", path = "../cfg" }, { name = "scc_utils", path = "../../../runtime/scc_utils" }, { name = "tree_dump", path = "../../tree_dump" }, + { name = "type_abi", path = "../../target/type_abi" }, ] # dependencies = [] # features = {} diff --git a/libs/ir/hir/include/scc_hir_layout.h b/libs/ir/hir/include/scc_hir_layout.h new file mode 100644 index 0000000..d74a832 --- /dev/null +++ b/libs/ir/hir/include/scc_hir_layout.h @@ -0,0 +1,39 @@ +#ifndef __SCC_HIR_LAYOUT_H__ +#define __SCC_HIR_LAYOUT_H__ + +#include +#include + +#define SCC_ALIGN_UP(x, align) (((x) + (align)-1) & ~((align)-1)) + +/// 结构体/联合体字段布局 +typedef struct scc_hir_field_layout { + int offset; + int size; + int align; +} scc_hir_field_layout_t; + +/// 聚合体布局结果 (FLEX) +typedef struct scc_hir_aggregate_layout { + int size; + int align; + int field_count; + scc_hir_field_layout_t fields[]; +} scc_hir_aggregate_layout_t; + +int scc_hir_type_size(scc_hir_module_t *mod, scc_hir_type_ref_t type, + const scc_type_abi_t *abi); + +int scc_hir_type_align(scc_hir_module_t *mod, scc_hir_type_ref_t type, + const scc_type_abi_t *abi); + +int scc_hir_field_offset(scc_hir_module_t *mod, scc_hir_type_ref_t type, + int field_idx, const scc_type_abi_t *abi); + +scc_hir_aggregate_layout_t * +scc_hir_aggregate_layout(scc_hir_module_t *mod, scc_hir_type_ref_t type, + const scc_type_abi_t *abi); + +void scc_hir_aggregate_layout_free(scc_hir_aggregate_layout_t *layout); + +#endif /* __SCC_HIR_LAYOUT_H__ */ diff --git a/libs/ir/hir/src/scc_hir_builder.c b/libs/ir/hir/src/scc_hir_builder.c index 11c3abc..379c8a6 100644 --- a/libs/ir/hir/src/scc_hir_builder.c +++ b/libs/ir/hir/src/scc_hir_builder.c @@ -334,6 +334,9 @@ scc_hir_value_ref_t scc_hir_builder_const_string(scc_hir_builder_t *builder, case '"': scc_str_append_ch(&buf, '"'); break; + case '0': + scc_str_append_ch(&buf, '\0'); + break; default: LOG_WARN("Unknown escape sequence: \\%c", str[i]); scc_str_append_ch(&buf, str[i]); diff --git a/libs/ir/hir/src/scc_hir_layout.c b/libs/ir/hir/src/scc_hir_layout.c new file mode 100644 index 0000000..e08a783 --- /dev/null +++ b/libs/ir/hir/src/scc_hir_layout.c @@ -0,0 +1,249 @@ +#include + +int scc_hir_type_align(scc_hir_module_t *mod, scc_hir_type_ref_t ref, + const scc_type_abi_t *abi) { + scc_hir_type_t *type = scc_hir_module_get_type(mod, ref); + if (!type) + return 0; + + switch (type->tag) { + case SCC_HIR_TYPE_void: + case SCC_HIR_TYPE_FUNC: + case SCC_HIR_TYPE_unknown: + return 1; // void/func 不占空间, 对齐为 1 + + case SCC_HIR_TYPE_i8: + case SCC_HIR_TYPE_u8: + return scc_type_abi_get_type_align(abi, 1) * 8; + case SCC_HIR_TYPE_i16: + case SCC_HIR_TYPE_u16: + case SCC_HIR_TYPE_f16: + return scc_type_abi_get_type_align(abi, 2) * 8; + case SCC_HIR_TYPE_i32: + case SCC_HIR_TYPE_u32: + case SCC_HIR_TYPE_f32: + return scc_type_abi_get_type_align(abi, 4) * 8; + case SCC_HIR_TYPE_i64: + case SCC_HIR_TYPE_u64: + case SCC_HIR_TYPE_f64: + return scc_type_abi_get_type_align(abi, 8) * 8; + case SCC_HIR_TYPE_i128: + case SCC_HIR_TYPE_u128: + case SCC_HIR_TYPE_f128: + return scc_type_abi_get_type_align(abi, 16) * 8; + + case SCC_HIR_TYPE_PTR: + return abi->ptr_align * 8; + + case SCC_HIR_TYPE_ARRAY: { + return scc_hir_type_align(mod, type->data.array.base, abi); + } + + case SCC_HIR_TYPE_STRUCT: { + int max_align_bits = 0; + for (usize i = 0; i < scc_vec_size(type->data.aggregate.fields); i++) { + scc_hir_type_ref_t fr = scc_vec_at(type->data.aggregate.fields, i); + int fa_bits = scc_hir_type_align(mod, fr, abi); + int fs_bits = scc_hir_type_size(mod, fr, abi); + int fa2_bits = scc_type_abi_get_field_align(abi, fs_bits / 8, fa_bits / 8) * 8; + if (fa2_bits > max_align_bits) + max_align_bits = fa2_bits; + } + return scc_type_abi_get_aggregate_align(abi, max_align_bits / 8) * 8; + } + + case SCC_HIR_TYPE_UNION: { + int max_align_bits = 0; + for (usize i = 0; i < scc_vec_size(type->data.aggregate.fields); i++) { + scc_hir_type_ref_t fr = scc_vec_at(type->data.aggregate.fields, i); + int fs_bits = scc_hir_type_size(mod, fr, abi); + int fa_bits = scc_hir_type_align(mod, fr, abi); + (void)fs_bits; + if (fa_bits > max_align_bits) + max_align_bits = fa_bits; + } + return scc_type_abi_get_aggregate_align(abi, max_align_bits / 8) * 8; + } + + default: + return 1; + } +} + +int scc_hir_type_size(scc_hir_module_t *mod, scc_hir_type_ref_t ref, + const scc_type_abi_t *abi) { + scc_hir_type_t *type = scc_hir_module_get_type(mod, ref); + if (!type) + return 0; + + switch (type->tag) { + case SCC_HIR_TYPE_void: + case SCC_HIR_TYPE_FUNC: + case SCC_HIR_TYPE_unknown: + return 0; + + case SCC_HIR_TYPE_i8: + case SCC_HIR_TYPE_u8: + return 8; + case SCC_HIR_TYPE_i16: + case SCC_HIR_TYPE_u16: + case SCC_HIR_TYPE_f16: + return 16; + case SCC_HIR_TYPE_i32: + case SCC_HIR_TYPE_u32: + case SCC_HIR_TYPE_f32: + return 32; + case SCC_HIR_TYPE_i64: + case SCC_HIR_TYPE_u64: + case SCC_HIR_TYPE_f64: + return 64; + case SCC_HIR_TYPE_i128: + case SCC_HIR_TYPE_u128: + case SCC_HIR_TYPE_f128: + return 128; + + case SCC_HIR_TYPE_PTR: + return abi->ptr_size * 8; + + case SCC_HIR_TYPE_ARRAY: { + int es_bits = scc_hir_type_size(mod, type->data.array.base, abi); + return es_bits * (int)type->data.array.len; + } + + case SCC_HIR_TYPE_STRUCT: { + int offset_bits = 0, max_align_bits = 0; + for (usize i = 0; i < scc_vec_size(type->data.aggregate.fields); i++) { + scc_hir_type_ref_t fr = scc_vec_at(type->data.aggregate.fields, i); + int fs_bits = scc_hir_type_size(mod, fr, abi); + int fa_bits = scc_hir_type_align(mod, fr, abi); + int fa2_bits = scc_type_abi_get_field_align(abi, fs_bits / 8, fa_bits / 8) * 8; + offset_bits = SCC_ALIGN_UP(offset_bits, fa2_bits); + offset_bits += fs_bits; + if (fa2_bits > max_align_bits) + max_align_bits = fa2_bits; + } + return SCC_ALIGN_UP(offset_bits, + scc_type_abi_get_aggregate_align(abi, max_align_bits / 8) * 8); + } + + case SCC_HIR_TYPE_UNION: { + int max_size_bits = 0, max_align_bits = 0; + for (usize i = 0; i < scc_vec_size(type->data.aggregate.fields); i++) { + scc_hir_type_ref_t fr = scc_vec_at(type->data.aggregate.fields, i); + int fs_bits = scc_hir_type_size(mod, fr, abi); + int fa_bits = scc_hir_type_align(mod, fr, abi); + if (fs_bits > max_size_bits) + max_size_bits = fs_bits; + if (fa_bits > max_align_bits) + max_align_bits = fa_bits; + } + return SCC_ALIGN_UP(max_size_bits, + scc_type_abi_get_aggregate_align(abi, max_align_bits / 8) * 8); + } + + default: + return 0; + } +} + +int scc_hir_field_offset(scc_hir_module_t *mod, scc_hir_type_ref_t ref, + int field_idx, const scc_type_abi_t *abi) { + scc_hir_type_t *type = scc_hir_module_get_type(mod, ref); + if (!type || (type->tag != SCC_HIR_TYPE_STRUCT && + type->tag != SCC_HIR_TYPE_UNION)) + return 0; + + if (type->tag == SCC_HIR_TYPE_UNION) + return 0; // union 所有字段偏移为 0 + + int offset_bits = 0; + int count = (int)scc_vec_size(type->data.aggregate.fields); + if (field_idx >= count) + return 0; + + for (int i = 0; i < count; i++) { + scc_hir_type_ref_t fr = scc_vec_at(type->data.aggregate.fields, (usize)i); + int fs_bits = scc_hir_type_size(mod, fr, abi); + int fa_bits = scc_hir_type_align(mod, fr, abi); + int fa2_bits = scc_type_abi_get_field_align(abi, fs_bits / 8, fa_bits / 8) * 8; + offset_bits = SCC_ALIGN_UP(offset_bits, fa2_bits); + if (i == field_idx) + return offset_bits; + offset_bits += fs_bits; + } + return 0; +} + +scc_hir_aggregate_layout_t * +scc_hir_aggregate_layout(scc_hir_module_t *mod, scc_hir_type_ref_t ref, + const scc_type_abi_t *abi) { + scc_hir_type_t *type = scc_hir_module_get_type(mod, ref); + if (!type || (type->tag != SCC_HIR_TYPE_STRUCT && + type->tag != SCC_HIR_TYPE_UNION)) + return NULL; + + int fc = (int)scc_vec_size(type->data.aggregate.fields); + + if (type->tag == SCC_HIR_TYPE_UNION) { + int max_size_bits = 0, max_align_bits = 0; + for (usize i = 0; i < scc_vec_size(type->data.aggregate.fields); i++) { + scc_hir_type_ref_t fr = scc_vec_at(type->data.aggregate.fields, i); + int fs_bits = scc_hir_type_size(mod, fr, abi); + int fa_bits = scc_hir_type_align(mod, fr, abi); + if (fs_bits > max_size_bits) + max_size_bits = fs_bits; + if (fa_bits > max_align_bits) + max_align_bits = fa_bits; + } + + scc_hir_aggregate_layout_t *al = + scc_malloc(sizeof(scc_hir_aggregate_layout_t) + + (usize)fc * sizeof(scc_hir_field_layout_t)); + al->size = SCC_ALIGN_UP(max_size_bits, max_align_bits); + al->align = max_align_bits; + al->field_count = fc; + for (int i = 0; i < fc; i++) { + scc_hir_type_ref_t fr = + scc_vec_at(type->data.aggregate.fields, (usize)i); + int fs_bits = scc_hir_type_size(mod, fr, abi); + int fa_bits = scc_hir_type_align(mod, fr, abi); + al->fields[i].offset = 0; + al->fields[i].size = fs_bits; + al->fields[i].align = fa_bits; + } + return al; + } + + // STRUCT + scc_hir_aggregate_layout_t *al = + scc_malloc(sizeof(scc_hir_aggregate_layout_t) + + (usize)fc * sizeof(scc_hir_field_layout_t)); + al->field_count = fc; + + int offset_bits = 0, max_align_bits = 0; + for (int i = 0; i < fc; i++) { + scc_hir_type_ref_t fr = + scc_vec_at(type->data.aggregate.fields, (usize)i); + int fs_bits = scc_hir_type_size(mod, fr, abi); + int fa_bits = scc_hir_type_align(mod, fr, abi); + int fa2_bits = scc_type_abi_get_field_align(abi, fs_bits / 8, fa_bits / 8) * 8; + offset_bits = SCC_ALIGN_UP(offset_bits, fa2_bits); + + al->fields[i].offset = offset_bits; + al->fields[i].size = fs_bits; + al->fields[i].align = fa_bits; + + offset_bits += fs_bits; + if (fa2_bits > max_align_bits) + max_align_bits = fa2_bits; + } + + al->size = SCC_ALIGN_UP(offset_bits, + scc_type_abi_get_aggregate_align(abi, max_align_bits / 8) * 8); + al->align = scc_type_abi_get_aggregate_align(abi, max_align_bits / 8) * 8; + return al; +} + +void scc_hir_aggregate_layout_free(scc_hir_aggregate_layout_t *layout) { + scc_free(layout); +} diff --git a/libs/ir/hir/src/scc_hir_module.c b/libs/ir/hir/src/scc_hir_module.c index 995df71..87d2a19 100644 --- a/libs/ir/hir/src/scc_hir_module.c +++ b/libs/ir/hir/src/scc_hir_module.c @@ -134,24 +134,24 @@ usize scc_hir_module_type_size(scc_hir_module_t *ctx, scc_hir_type_t *type) { return 0; case SCC_HIR_TYPE_i8: case SCC_HIR_TYPE_u8: - return 1; + return 8; case SCC_HIR_TYPE_i16: case SCC_HIR_TYPE_u16: - return 2; + return 16; case SCC_HIR_TYPE_f32: case SCC_HIR_TYPE_i32: case SCC_HIR_TYPE_u32: - return 4; + return 32; case SCC_HIR_TYPE_f64: case SCC_HIR_TYPE_i64: case SCC_HIR_TYPE_u64: - return 8; + return 64; case SCC_HIR_TYPE_FUNC: case SCC_HIR_TYPE_PTR: { // TODO - // 目标指针大小,可以定义为 8(64位)或从 ABI 获取 + // 目标指针大小,可以定义为 64(64位)或从 ABI 获取 // 假设你的目标架构是 64 位 - return 8; + return 64; } case SCC_HIR_TYPE_ARRAY: { usize elem_size = scc_hir_module_type_size( diff --git a/libs/ir/lir/include/scc_lir.h b/libs/ir/lir/include/scc_lir.h index ae02b63..6345ae8 100644 --- a/libs/ir/lir/include/scc_lir.h +++ b/libs/ir/lir/include/scc_lir.h @@ -65,10 +65,10 @@ typedef struct scc_lir_instr { #define SCC_LIR_ARG(n) \ ((scc_lir_val_t){.kind = SCC_LIR_INSTR_KIND_ARG, .data.arg = (n)}) -#define SCC_LIR_SIZE_8 1 -#define SCC_LIR_SIZE_16 2 -#define SCC_LIR_SIZE_32 4 -#define SCC_LIR_SIZE_64 8 +#define SCC_LIR_SIZE_8 8 +#define SCC_LIR_SIZE_16 16 +#define SCC_LIR_SIZE_32 32 +#define SCC_LIR_SIZE_64 64 typedef enum { SCC_LIR_EXT_NONE, @@ -163,7 +163,7 @@ typedef enum { typedef scc_cfg_bblock_id_t scc_lir_bblock_id_t; typedef struct scc_lir_ins { scc_lir_op_t op; - u8 size; + u8 size_bits; scc_lir_ext_t ext; scc_lir_val_t to; scc_lir_val_t arg0; @@ -207,12 +207,12 @@ typedef struct scc_lir_ins { } parallel_copy; struct scc_lir_alloca { - int size_bytes; - int align_bytes; + int size_bits; + int align_bits; } alloca; struct scc_lir_extend { - int from_size; // 源类型宽度(字节) + int from_size_bits; // 源类型宽度(位) } extend; struct { diff --git a/libs/ir/lir/src/scc_hir2lir.c b/libs/ir/lir/src/scc_hir2lir.c index 2e04f06..43c135f 100644 --- a/libs/ir/lir/src/scc_hir2lir.c +++ b/libs/ir/lir/src/scc_hir2lir.c @@ -294,7 +294,7 @@ static int ensure_vreg(ir2lir_ctx_t *ctx, scc_lir_val_t *val) { // 分配新的虚拟寄存器 int new_vreg = ++(SCC_LIR_FUNC_META(ctx->current_func)->vregs_count); scc_lir_instr_t mov = {.op = SCC_LIR_MOV, - .size = SCC_LIR_SIZE_64, // 地址宽度 + .size_bits = SCC_LIR_SIZE_64, // 地址宽度 .to = SCC_LIR_VREG(new_vreg), .arg0 = *val}; scc_lir_builder_add_instr(ctx, &mov); @@ -311,10 +311,10 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value, return; scc_hir_type_t *ty = scc_hir_module_get_type(ctx->hir_module, value->type); - u8 size = 0; + u8 size_bits = 0; scc_lir_ext_t ext = SCC_LIR_EXT_NONE; if (ty != nullptr) { - ir_type_to_lir_size_ext(ty, &size, &ext); + ir_type_to_lir_size_ext(ty, &size_bits, &ext); } bool is_float = (ext == SCC_LIR_EXT_FLOAT); @@ -331,7 +331,7 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value, scc_lir_instr_t instr = { .op = op, - .size = size, + .size_bits = size_bits, .ext = ext, .to = SCC_LIR_VREG(dst_vreg), .arg0 = lhs, @@ -346,7 +346,7 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value, scc_lir_val_t addr = ir_value_to_lir_operand(ctx, value->data.load.target); scc_lir_instr_t instr = {.op = SCC_LIR_LOAD, - .size = size, + .size_bits = size_bits, .ext = ext, .to = SCC_LIR_VREG(dst_vreg), .arg0 = addr}; @@ -363,15 +363,15 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value, if (ptr_type && ptr_type->tag == SCC_HIR_TYPE_PTR) { scc_hir_type_t *elem_type = scc_hir_module_get_type( ctx->hir_module, ptr_type->data.pointer.base); - ir_type_to_lir_size_ext(elem_type, &size, &ext); + ir_type_to_lir_size_ext(elem_type, &size_bits, &ext); } else { ty = scc_hir_module_get_type_by_value(ctx->hir_module, value->data.store.value); - ir_type_to_lir_size_ext(ty, &size, &ext); + ir_type_to_lir_size_ext(ty, &size_bits, &ext); } scc_lir_instr_t instr = {.op = SCC_LIR_STORE, .ext = ext, - .size = size, + .size_bits = size_bits, .arg0 = data, .arg1 = addr}; scc_lir_builder_add_instr(ctx, &instr); @@ -397,16 +397,17 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value, } else { Panic("GET_ELEM_PTR on non-pointer/array type"); } - int elem_size = scc_hir_module_type_size(ctx->hir_module, pointee); + int elem_size_bits = scc_hir_module_type_size(ctx->hir_module, pointee); int dst_vreg = get_vreg_for_value(ctx, value_ref); scc_lir_instr_t instr = { .op = SCC_LIR_LOAD_ADDR, - .size = SCC_LIR_SIZE_64, + .size_bits = SCC_LIR_SIZE_64, .to = SCC_LIR_VREG(dst_vreg), .arg0 = base, .arg1 = index, - .metadata.addr.scale = elem_size, + // FIXME + .metadata.addr.scale = elem_size_bits / 8, .metadata.addr.offset = 0, }; scc_lir_builder_add_instr(ctx, &instr); @@ -415,11 +416,13 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value, Assert(ty != nullptr); scc_hir_type_t *alloc_ty = scc_hir_module_get_type(ctx->hir_module, ty->data.pointer.base); - int alloc_size = scc_hir_module_type_size(ctx->hir_module, alloc_ty); + int alloc_size_bits = + scc_hir_module_type_size(ctx->hir_module, alloc_ty); scc_lir_instr_t instr = {.op = SCC_LIR_ALLOCA, - .size = alloc_size, + .size_bits = SCC_LIR_SIZE_64, .to = SCC_LIR_VREG(dst_vreg), - .metadata.alloca = {alloc_size, 1}}; + // FIXME + .metadata.alloca = {alloc_size_bits, 8}}; scc_lir_builder_add_instr(ctx, &instr); } break; case SCC_HIR_VALUE_TAG_CALL: { @@ -440,7 +443,7 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value, int is_direct_call = sym->kind == SCC_CFG_SYMBOL_KIND_FUNC; scc_lir_instr_t instr = (scc_lir_instr_t){ .op = is_direct_call ? SCC_LIR_CALL : SCC_LIR_CALL_INDIRECT, - .size = size, + .size_bits = size_bits, .to = SCC_LIR_VREG(dst_vreg), .metadata.call = {.args = lir_args, .arg_count = arg_count, @@ -497,7 +500,7 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value, // TRUNC 用 SCC_LIR_MOV 截断 if (value->data.conv.conv_type == SCC_HIR_CONV_TRUNC) { scc_lir_instr_t instr = {.op = SCC_LIR_MOV, - .size = size, + .size_bits = size_bits, .to = SCC_LIR_VREG(dst_vreg), .arg0 = src}; scc_lir_builder_add_instr(ctx, &instr); @@ -507,13 +510,15 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value, ctx->hir_module, scc_hir_module_get_value( ctx->hir_module, value->data.conv.operand) ->type); - int from_size = scc_hir_module_type_size(ctx->hir_module, src_type); + int from_size_bits = + scc_hir_module_type_size(ctx->hir_module, src_type); scc_lir_instr_t instr = {.op = SCC_LIR_EXTEND, - .size = size, + .size_bits = size_bits, .ext = conv_ext, .to = SCC_LIR_VREG(dst_vreg), .arg0 = src, - .metadata.extend.from_size = from_size}; + .metadata.extend.from_size_bits = + from_size_bits}; scc_lir_builder_add_instr(ctx, &instr); } } break; diff --git a/libs/ir/lir/src/scc_lir_dump.c b/libs/ir/lir/src/scc_lir_dump.c index 3643fba..33656fe 100644 --- a/libs/ir/lir/src/scc_lir_dump.c +++ b/libs/ir/lir/src/scc_lir_dump.c @@ -135,7 +135,7 @@ void scc_lir_dump_ins(scc_lir_dump_ctx_t *ctx, const scc_lir_instr_t *ins) { scc_tree_dump_node(td, "%s", op_to_string(ins->op)); // 输出宽度和扩展标志 - dump_size_ext(ctx, ins->size, ins->ext); + dump_size_ext(ctx, ins->size_bits, ins->ext); scc_tree_dump_append(td, " "); switch (ins->op) { @@ -165,8 +165,8 @@ void scc_lir_dump_ins(scc_lir_dump_ctx_t *ctx, const scc_lir_instr_t *ins) { break; case SCC_LIR_ALLOCA: scc_tree_dump_append_fmt(td, "(sz=%zd,al=%zd) => ", - ins->metadata.alloca.size_bytes, - ins->metadata.alloca.align_bytes); + ins->metadata.alloca.size_bits, + ins->metadata.alloca.align_bits); dump_operand(ctx, &ins->to); break; case SCC_LIR_EXTEND: { @@ -182,8 +182,8 @@ void scc_lir_dump_ins(scc_lir_dump_ctx_t *ctx, const scc_lir_instr_t *ins) { ext_name = "ext"; break; } - scc_tree_dump_append_fmt(td, "%s(%d<-%d) ", ext_name, ins->size * 8, - ins->metadata.extend.from_size * 8); + scc_tree_dump_append_fmt(td, "%s(%d<-%d) ", ext_name, ins->size_bits, + ins->metadata.extend.from_size_bits); dump_operand(ctx, &ins->to); scc_tree_dump_append(td, " <- "); dump_operand(ctx, &ins->arg0); diff --git a/libs/ir/mir/include/arch/scc_x86_mir.h b/libs/ir/mir/include/arch/scc_x86_mir.h index e8f6f7c..fce07de 100644 --- a/libs/ir/mir/include/arch/scc_x86_mir.h +++ b/libs/ir/mir/include/arch/scc_x86_mir.h @@ -52,7 +52,7 @@ static inline scc_x86_operand_value_t scc_x86_op_slot(int slot_id, u8 size) { o.mem.scale = 1; o.mem.disp.displacement = slot_id; o.mem.disp.displacement_bits = 0; - o.size = size; + o.size_bits = size; return o; } diff --git a/libs/ir/mir/include/scc_mir.h b/libs/ir/mir/include/scc_mir.h index 437a731..95fe881 100644 --- a/libs/ir/mir/include/scc_mir.h +++ b/libs/ir/mir/include/scc_mir.h @@ -14,8 +14,8 @@ typedef struct scc_mir_instr { int opcode; union { struct { - int size; - int align; + int size_bits; + int align_bits; int vreg; } alloc; } data; diff --git a/libs/ir/mir/src/arch/scc_x86_isel.c b/libs/ir/mir/src/arch/scc_x86_isel.c index 1e02098..4f44aeb 100644 --- a/libs/ir/mir/src/arch/scc_x86_isel.c +++ b/libs/ir/mir/src/arch/scc_x86_isel.c @@ -98,34 +98,34 @@ void scc_x86_instr_dump(scc_tree_dump_t *td, const scc_mir_func_t *func, scc_tree_dump_append(td, ""); break; } - scc_tree_dump_append_fmt(td, ".(%zu)", op->size); + scc_tree_dump_append_fmt(td, ".(%zu)", op->size_bits); } } // 将 LIR 值转换为 x86 操作数 scc_x86_operand_value_t scc_x86_lir_val_to_mir_op(scc_x86_64_isel_t *isel, const scc_lir_val_t *val, - u8 size) { + u8 size_bits) { scc_x86_operand_value_t op = {0}; switch (val->kind) { case SCC_LIR_INSTR_KIND_NONE: op.kind = SCC_X86_OPR_NONE; break; case SCC_LIR_INSTR_KIND_VREG: - op = scc_x86_op_vreg(val->data.reg, size); + op = scc_x86_op_vreg(val->data.reg, size_bits); int id = 0; int ret = scc_mir_vreg_lookup(isel->func, val->data.reg, &id); if (ret > 0) { - op = scc_x86_op_preg(id, size); + op = scc_x86_op_preg(id, size_bits); } else if (ret < 0) { - op = scc_x86_op_slot(id, size); + op = scc_x86_op_slot(id, size_bits); } break; case SCC_LIR_INSTR_KIND_IMM: - op = scc_x86_op_imm(val->data.imm.data.digit, size); + op = scc_x86_op_imm(val->data.imm.data.digit, size_bits); break; case SCC_LIR_INSTR_KIND_FIMM: - op = scc_x86_op_imm(*(i64 *)&val->data.fimm, size); + op = scc_x86_op_imm(*(i64 *)&val->data.fimm, size_bits); break; case SCC_LIR_INSTR_KIND_SYMBOL: op = scc_x86_op_reloc_global_relrip(val->data.symbol, 0); @@ -133,7 +133,7 @@ scc_x86_operand_value_t scc_x86_lir_val_to_mir_op(scc_x86_64_isel_t *isel, case SCC_LIR_INSTR_KIND_ARG: Assert(isel->abi_lowering.lower_param); isel->abi_lowering.lower_param(isel, val, &op); - op.size = size; + op.size_bits = size_bits; break; default: Panic("unsupported lir instr kind %d", val->kind); @@ -144,15 +144,15 @@ scc_x86_operand_value_t scc_x86_lir_val_to_mir_op(scc_x86_64_isel_t *isel, // 虚拟临时寄存器分配(简单递增) static scc_x86_operand_value_t new_vreg_temp(scc_x86_64_isel_t *isel, - int size) { - return scc_x86_op_vreg(scc_mir_alloc_vreg(isel->func), size); + int size_bits) { + return scc_x86_op_vreg(scc_mir_alloc_vreg(isel->func), size_bits); } /* 确保操作数为寄存器: IMM → 加载到临时虚拟寄存器 */ static scc_x86_operand_value_t ensure_reg(scc_x86_64_isel_t *isel, scc_x86_operand_value_t op) { if (op.kind == SCC_X86_OPR_IMM) { - scc_x86_operand_value_t tmp = new_vreg_temp(isel, op.size); + scc_x86_operand_value_t tmp = new_vreg_temp(isel, op.size_bits); scc_x86_emit_move(isel, tmp, op); return tmp; } @@ -202,8 +202,8 @@ static void emit_binary_op(scc_x86_64_isel_t *isel, scc_lir_op_t op, scc_x86_operand_value_t src1) { emit_copy_if_needed(isel, dst, src0); - Assert(src0.size == src1.size); - int is_8b = src0.size == 1; + Assert(src0.size_bits == src1.size_bits); + // int is_8b = src0.size_bits == 8; int is_imm = src1.kind == SCC_X86_OPR_IMM; scc_x86_iform_t opcode; switch (op) { @@ -242,7 +242,7 @@ void scc_x86_emit_load(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst, scc_x86_operand_value_t src) { scc_x86_operand_value_t tmp_reg = dst; if (dst.kind != SCC_X86_OPR_REG) { - tmp_reg = new_vreg_temp(isel, src.size); + tmp_reg = new_vreg_temp(isel, src.size_bits); } scc_x86_emit_load_to_vec(&isel->instrs, tmp_reg, src); if (dst.kind != SCC_X86_OPR_REG) { @@ -253,7 +253,7 @@ void scc_x86_emit_load(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst, void scc_x86_emit_store(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst, scc_x86_operand_value_t src) { if (src.kind == SCC_X86_OPR_MEM) { - scc_x86_operand_value_t tmp_reg = new_vreg_temp(isel, src.size); + scc_x86_operand_value_t tmp_reg = new_vreg_temp(isel, src.size_bits); scc_x86_emit_load(isel, tmp_reg, src); src = tmp_reg; } @@ -264,8 +264,8 @@ static void emit_load_addr(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst, scc_x86_operand_value_t base, scc_x86_operand_value_t index, int scale, i64 offset) { - usize size = dst.size; - Assert(size == 8); + usize size_bits = dst.size_bits; + Assert(size_bits == 64); // 前置断言:dst 必须是寄存器 Assert(dst.kind == SCC_X86_OPR_REG); // scale 必须是 1,2,4,8 之一 @@ -279,11 +279,11 @@ static void emit_load_addr(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst, } break; case SCC_X86_OPR_RELOC: { Assert(base.reloc.target == SCC_X86_RELOC_TARGET_SYMBOL); - base_reg = new_vreg_temp(isel, 8); + base_reg = new_vreg_temp(isel, 64); scc_x86_emit_move(isel, base_reg, base); } break; case SCC_X86_OPR_MEM: { - base_reg = new_vreg_temp(isel, 8); + base_reg = new_vreg_temp(isel, 64); scc_x86_emit_move(isel, base_reg, base); } break; default: { @@ -298,15 +298,15 @@ static void emit_load_addr(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst, } break; case SCC_X86_OPR_RELOC: { Assert(index.reloc.target == SCC_X86_RELOC_TARGET_SYMBOL); - index_reg = new_vreg_temp(isel, 8); + index_reg = new_vreg_temp(isel, 64); scc_x86_emit_move(isel, index_reg, index); } break; case SCC_X86_OPR_MEM: { - index_reg = new_vreg_temp(isel, 8); + index_reg = new_vreg_temp(isel, 64); scc_x86_emit_move(isel, index_reg, index); } break; case SCC_X86_OPR_IMM: { - index_reg = new_vreg_temp(isel, index.size); + index_reg = new_vreg_temp(isel, index.size_bits); scc_x86_emit_move(isel, index_reg, index); } break; default: { @@ -320,18 +320,18 @@ static void emit_load_addr(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst, .scale = scale, .disp.displacement = offset, .disp.displacement_bits = 8}, - size); + size_bits); scc_x86_emit_move(isel, dst, mem_op); } static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) { - u8 size = instr->size; + u8 size_bits = instr->size_bits; scc_x86_operand_value_t dst = - scc_x86_lir_val_to_mir_op(isel, &instr->to, size); + scc_x86_lir_val_to_mir_op(isel, &instr->to, size_bits); scc_x86_operand_value_t src0 = - scc_x86_lir_val_to_mir_op(isel, &instr->arg0, size); + scc_x86_lir_val_to_mir_op(isel, &instr->arg0, size_bits); scc_x86_operand_value_t src1 = - scc_x86_lir_val_to_mir_op(isel, &instr->arg1, size); + scc_x86_lir_val_to_mir_op(isel, &instr->arg1, size_bits); switch (instr->op) { /* ---- 数据移动 ---- */ @@ -373,7 +373,7 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) { case SCC_LIR_MUL: emit_copy_if_needed(isel, dst, src0); if (src1.kind == SCC_X86_OPR_IMM) { - scc_x86_operand_value_t op = new_vreg_temp(isel, size); + scc_x86_operand_value_t op = new_vreg_temp(isel, size_bits); scc_x86_emit_move(isel, op, src1); src1 = op; } @@ -401,7 +401,7 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) { } add_instr_2(isel, iform, dst, src1); } else { - scc_x86_operand_value_t cl = scc_x86_op_preg(SCC_X86_REG_CL, 1); + scc_x86_operand_value_t cl = scc_x86_op_preg(SCC_X86_REG_CL, 8); scc_x86_emit_move(isel, cl, src1); scc_x86_iform_t iform; switch (instr->op) { @@ -426,14 +426,16 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) { case SCC_LIR_DIV_U: case SCC_LIR_REM_S: case SCC_LIR_REM_U: { - scc_x86_operand_value_t rax = scc_x86_op_preg(SCC_X86_REG_RAX, size); - scc_x86_operand_value_t rdx = scc_x86_op_preg(SCC_X86_REG_RDX, size); + scc_x86_operand_value_t rax = + scc_x86_op_preg(SCC_X86_REG_RAX, size_bits); + scc_x86_operand_value_t rdx = + scc_x86_op_preg(SCC_X86_REG_RDX, size_bits); if (instr->op == SCC_LIR_DIV_S || instr->op == SCC_LIR_REM_S) { - if (size < 8) { + if (size_bits < 64) { // TODO 可能需要在lir进行size对齐 scc_x86_operand_value_t rax64 = - scc_x86_op_preg(SCC_X86_REG_RAX, 8); + scc_x86_op_preg(SCC_X86_REG_RAX, 64); add_instr_2(isel, SCC_X86_IFORM_MOVSXD_GPRV_GPRZ, rax64, src0); } else { scc_x86_emit_move(isel, rax, src0); @@ -441,7 +443,7 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) { add_instr_0(isel, SCC_X86_IFORM_CQO); } else { scc_x86_emit_move(isel, rax, src0); - scc_x86_operand_value_t zero = scc_x86_op_imm(0, size); + scc_x86_operand_value_t zero = scc_x86_op_imm(0, size_bits); scc_x86_emit_move(isel, rdx, zero); } @@ -451,7 +453,7 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) { : SCC_X86_IFORM_DIV_GPRV; scc_x86_operand_value_t divisor = src1; if (src1.kind == SCC_X86_OPR_IMM) { - divisor = new_vreg_temp(isel, size); + divisor = new_vreg_temp(isel, size_bits); scc_x86_emit_move(isel, divisor, src1); } add_instr_1(isel, div_if, divisor); @@ -464,33 +466,34 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) { /* ---- 比较指令 ---- */ case SCC_LIR_CMP: { - Assert(src0.size == src1.size); + Assert(src0.size_bits == src1.size_bits); if (src0.kind == SCC_X86_OPR_IMM) { - scc_x86_operand_value_t tmp_reg = new_vreg_temp(isel, src0.size); + scc_x86_operand_value_t tmp_reg = + new_vreg_temp(isel, src0.size_bits); scc_x86_emit_move(isel, tmp_reg, src0); src0 = tmp_reg; } if (scc_x86_op_is_vreg(&src0) && src1.kind == SCC_X86_OPR_IMM) // SCC_X86_IFORM_CMP_GPR8_IMMB_82R7 历史遗留指令在amd64中已不再使用 add_instr_2(isel, - src0.size == 1 ? SCC_X86_IFORM_CMP_GPR8_IMMB_80R7 - : SCC_X86_IFORM_CMP_GPRV_IMMZ, + src0.size_bits == 8 ? SCC_X86_IFORM_CMP_GPR8_IMMB_80R7 + : SCC_X86_IFORM_CMP_GPRV_IMMZ, src0, src1); else if (scc_x86_op_is_vreg(&src0) && scc_x86_op_is_vreg(&src1)) add_instr_2(isel, - src0.size == 1 ? SCC_X86_IFORM_CMP_GPR8_GPR8_3A - : SCC_X86_IFORM_CMP_GPRV_GPRV_3B, + src0.size_bits == 8 ? SCC_X86_IFORM_CMP_GPR8_GPR8_3A + : SCC_X86_IFORM_CMP_GPRV_GPRV_3B, src0, src1); else UNREACHABLE(); scc_x86_iform_t setcc = cond_to_setcc(instr->metadata.cond); add_instr_1(isel, setcc, dst); - if (size > 1) { - scc_x86_operand_value_t one = scc_x86_op_imm(1, size); + if (size_bits > 8) { + scc_x86_operand_value_t one = scc_x86_op_imm(1, size_bits); add_instr_2(isel, - src1.size == 1 ? SCC_X86_IFORM_AND_GPR8_IMMB_82R4 - : SCC_X86_IFORM_AND_GPRV_IMMZ, + src1.size_bits == 8 ? SCC_X86_IFORM_AND_GPR8_IMMB_82R4 + : SCC_X86_IFORM_AND_GPRV_IMMZ, dst, one); } } break; @@ -501,11 +504,11 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) { scc_x86_op_reloc_block(instr->metadata.br.true_target, 0); scc_x86_operand_value_t false_bb = scc_x86_op_reloc_block(instr->metadata.br.false_target, 0); - true_bb.size = instr->size; - false_bb.size = instr->size; + true_bb.size_bits = instr->size_bits; + false_bb.size_bits = instr->size_bits; add_instr_2(isel, - src0.size == 1 ? SCC_X86_IFORM_TEST_GPR8_GPR8 - : SCC_X86_IFORM_TEST_GPRV_GPRV, + src0.size_bits == 8 ? SCC_X86_IFORM_TEST_GPR8_GPR8 + : SCC_X86_IFORM_TEST_GPRV_GPRV, src0, src0); add_instr_1(isel, SCC_X86_IFORM_JNZ_RELBRZ, true_bb); add_instr_1(isel, SCC_X86_IFORM_JMP_RELBRZ, false_bb); @@ -520,49 +523,50 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) { /* ---- 栈分配 ---- */ case SCC_LIR_ALLOCA: { scc_x86_operand_value_t op = - scc_x86_lir_val_to_mir_op(isel, &instr->to, instr->size); + scc_x86_lir_val_to_mir_op(isel, &instr->to, instr->size_bits); scc_mir_x86_instr_t x86instr; x86instr.instr.opcode = SCC_MIR_PSEUDO_ALLOCA; Assert(op.kind == SCC_X86_OPR_REG); x86instr.instr.data.alloc.vreg = op.reg; - x86instr.instr.data.alloc.size = instr->metadata.alloca.size_bytes; - x86instr.instr.data.alloc.align = instr->metadata.alloca.align_bytes; + x86instr.instr.data.alloc.size_bits = instr->metadata.alloca.size_bits; + x86instr.instr.data.alloc.align_bits = + instr->metadata.alloca.align_bits; scc_vec_push(isel->instrs, x86instr); scc_mir_vreg_map2slot(isel->func, instr->to.data.reg, - instr->metadata.alloca.size_bytes, - instr->metadata.alloca.align_bytes - ? instr->metadata.alloca.align_bytes + instr->metadata.alloca.size_bits, + instr->metadata.alloca.align_bits + ? instr->metadata.alloca.align_bits : 8); break; } /* ---- 类型扩展 ---- */ case SCC_LIR_EXTEND: { - int from_size = instr->metadata.extend.from_size; + int from_size_bits = instr->metadata.extend.from_size_bits; scc_x86_operand_value_t ext_src = - scc_x86_lir_val_to_mir_op(isel, &instr->arg0, from_size); + scc_x86_lir_val_to_mir_op(isel, &instr->arg0, from_size_bits); ext_src = ensure_reg(isel, ext_src); if (instr->ext == SCC_LIR_EXT_ZEXT) { - if (from_size == 4) { + if (from_size_bits == 32) { // 32→64: x86-64 写32位寄存器自动零扩展到64位 scc_x86_emit_move(isel, dst, ext_src); } else { - scc_x86_iform_t iform = (from_size == 1) + scc_x86_iform_t iform = (from_size_bits == 8) ? SCC_X86_IFORM_MOVZX_GPRV_GPR8 : SCC_X86_IFORM_MOVZX_GPRV_GPR16; add_instr_2(isel, iform, dst, ext_src); } } else if (instr->ext == SCC_LIR_EXT_SEXT) { scc_x86_iform_t iform; - switch (from_size) { - case 1: + switch (from_size_bits) { + case 8: iform = SCC_X86_IFORM_MOVSX_GPRV_GPR8; break; - case 2: + case 16: iform = SCC_X86_IFORM_MOVSX_GPRV_GPR16; break; - case 4: + case 32: iform = SCC_X86_IFORM_MOVSXD_GPRV_GPRZ; break; default: @@ -600,18 +604,18 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) { // 将 dest 的地址放入 RDI scc_x86_operand_value_t dest_op = - scc_x86_lir_val_to_mir_op(isel, &dest_val, 8); - scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_RDI, 8), dest_op); + scc_x86_lir_val_to_mir_op(isel, &dest_val, 64); + scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_RDI, 64), dest_op); // 将 src 的地址放入 RSI scc_x86_operand_value_t src_op = - scc_x86_lir_val_to_mir_op(isel, &src_val, 8); - scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_RSI, 8), src_op); + scc_x86_lir_val_to_mir_op(isel, &src_val, 64); + scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_RSI, 64), src_op); // 长度处理保持不变... scc_x86_operand_value_t len_op = - scc_x86_lir_val_to_mir_op(isel, &instr->metadata.memcpy.size, 8); - scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_RCX, 8), len_op); + scc_x86_lir_val_to_mir_op(isel, &instr->metadata.memcpy.size, 64); + scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_RCX, 64), len_op); add_instr_0(isel, SCC_X86_IFORM_REP_MOVSB); } break; @@ -632,9 +636,9 @@ static void sel_func(const scc_lir_module_t *lir_module, scc_lir_instr_vec_t *instrs = SCC_LIR_BBLOCK_VALUES(bb); scc_vec_foreach(*instrs, i) { scc_lir_instr_t *ins = &scc_vec_at(*instrs, i); - // HACK BR size + // HACK BR size_bits if (ins->op == SCC_LIR_BR) { - ins->size = scc_vec_at(*instrs, i - 1).size; + ins->size_bits = scc_vec_at(*instrs, i - 1).size_bits; } sel_mir(isel, ins); } diff --git a/libs/ir/mir/src/arch/scc_x86_mir.c b/libs/ir/mir/src/arch/scc_x86_mir.c index 8667d85..608b341 100644 --- a/libs/ir/mir/src/arch/scc_x86_mir.c +++ b/libs/ir/mir/src/arch/scc_x86_mir.c @@ -3,63 +3,64 @@ static inline scc_x86_iform_t scc_mir_x86_mov_reg_mem(scc_x86_operand_value_t op0, scc_x86_operand_value_t op1) { - Assert(op0.size == op1.size); + Assert(op0.size_bits == op1.size_bits); Assert(op0.kind == SCC_X86_OPR_REG && op1.kind == SCC_X86_OPR_MEM); - return op0.size == 1 ? SCC_X86_IFORM_MOV_GPR8_MEMB - : SCC_X86_IFORM_MOV_GPRV_MEMV; + return op0.size_bits == 8 ? SCC_X86_IFORM_MOV_GPR8_MEMB + : SCC_X86_IFORM_MOV_GPRV_MEMV; } static inline scc_x86_iform_t scc_mir_x86_mov_reg_reg(scc_x86_operand_value_t op0, scc_x86_operand_value_t op1) { - Assert(op0.size == op1.size); + Assert(op0.size_bits == op1.size_bits); Assert(op0.kind == SCC_X86_OPR_REG && op1.kind == SCC_X86_OPR_REG); - return op0.size == 1 ? SCC_X86_IFORM_MOV_GPR8_GPR8_8A - : SCC_X86_IFORM_MOV_GPRV_GPRV_8B; + return op0.size_bits == 8 ? SCC_X86_IFORM_MOV_GPR8_GPR8_8A + : SCC_X86_IFORM_MOV_GPRV_GPRV_8B; } static inline scc_x86_iform_t scc_mir_x86_mov_reg_imm(scc_x86_operand_value_t op0, scc_x86_operand_value_t op1) { - Assert(op0.size == op1.size); + Assert(op0.size_bits == op1.size_bits); Assert(op0.kind == SCC_X86_OPR_REG && op1.kind == SCC_X86_OPR_IMM); - return op0.size == 1 ? SCC_X86_IFORM_MOV_GPR8_IMMB_B0 - : SCC_X86_IFORM_MOV_GPRV_IMMV; + return op0.size_bits == 8 ? SCC_X86_IFORM_MOV_GPR8_IMMB_B0 + : SCC_X86_IFORM_MOV_GPRV_IMMV; } static inline scc_x86_iform_t scc_mir_x86_mov_mem_reg(scc_x86_operand_value_t op0, scc_x86_operand_value_t op1) { - Assert(op0.size == op1.size); + Assert(op0.size_bits == op1.size_bits); Assert(op0.kind == SCC_X86_OPR_MEM && op1.kind == SCC_X86_OPR_REG); - return op0.size == 1 ? SCC_X86_IFORM_MOV_MEMB_GPR8 - : SCC_X86_IFORM_MOV_MEMV_GPRV; + return op0.size_bits == 8 ? SCC_X86_IFORM_MOV_MEMB_GPR8 + : SCC_X86_IFORM_MOV_MEMV_GPRV; } + static inline scc_x86_iform_t scc_mir_x86_mov_mem_imm(scc_x86_operand_value_t op0, scc_x86_operand_value_t op1) { - Assert(op0.size == op1.size); + Assert(op0.size_bits == op1.size_bits); Assert(op0.kind == SCC_X86_OPR_MEM && op1.kind == SCC_X86_OPR_IMM); - return op0.size == 1 ? SCC_X86_IFORM_MOV_MEMB_IMMB - : SCC_X86_IFORM_MOV_MEMV_IMMZ; + return op0.size_bits == 8 ? SCC_X86_IFORM_MOV_MEMB_IMMB + : SCC_X86_IFORM_MOV_MEMV_IMMZ; } -static inline u8 get_op_size(scc_x86_operand_value_t op, cbool get_value) { +static inline u8 get_op_size_bits(scc_x86_operand_value_t op, cbool get_value) { if (get_value) { - return op.size; + return op.size_bits; } if (op.kind == SCC_X86_OPR_MEM) { - return 8; + return 64; } if (op.kind == SCC_X86_OPR_RELOC && op.reloc.kind == SCC_X86_OPR_MEM) { - return 8; + return 64; } - return op.size; + return op.size_bits; } void scc_x86_emit_move_to_vec(scc_mir_x86_instr_vec_t *vec, scc_x86_operand_value_t dst, scc_x86_operand_value_t src) { - u8 dst_size = get_op_size(dst, false); - u8 src_size = get_op_size(src, false); + u8 dst_size = get_op_size_bits(dst, false); + u8 src_size = get_op_size_bits(src, false); if (dst_size != src_size) { LOG_FATAL("Mismatched register sizes for move %d != %d", dst_size, src_size); @@ -75,7 +76,7 @@ void scc_x86_emit_move_to_vec(scc_mir_x86_instr_vec_t *vec, } else if (src.kind == SCC_X86_OPR_MEM || (src.kind == SCC_X86_OPR_RELOC && src.reloc.target == SCC_X86_RELOC_TARGET_SYMBOL)) { - Assert(dst_size == 8); + Assert(dst_size == 64); scc_mir_x86_instr_2(&ins, SCC_X86_IFORM_LEA_GPRV_AGEN, dst, src, scc_pos_create()); } else { @@ -100,8 +101,8 @@ void scc_x86_emit_move_to_vec(scc_mir_x86_instr_vec_t *vec, void scc_x86_emit_load_to_vec(scc_mir_x86_instr_vec_t *vec, scc_x86_operand_value_t dst, scc_x86_operand_value_t src_addr) { - u8 dst_size = get_op_size(dst, false); - u8 src_addr_size = get_op_size(src_addr, true); + u8 dst_size = get_op_size_bits(dst, false); + u8 src_addr_size = get_op_size_bits(src_addr, true); if (dst_size != src_addr_size) { LOG_FATAL("Mismatched sizes for load %d != %d", dst_size, src_addr_size); @@ -117,9 +118,9 @@ void scc_x86_emit_load_to_vec(scc_mir_x86_instr_vec_t *vec, .index = SCC_X86_REG_INVALID, .scale = 1, .disp.displacement = 0, - .disp.displacement_bits = src_addr_size * 8, + .disp.displacement_bits = src_addr_size, }, - .size = src_addr_size, + .size_bits = src_addr_size, }; } else if (src_addr.kind == SCC_X86_OPR_MEM) { mem_op = src_addr; @@ -135,8 +136,8 @@ void scc_x86_emit_load_to_vec(scc_mir_x86_instr_vec_t *vec, void scc_x86_emit_store_to_vec(scc_mir_x86_instr_vec_t *vec, scc_x86_operand_value_t dst_addr, scc_x86_operand_value_t src) { - u8 dst_addr_size = get_op_size(dst_addr, true); - u8 src_size = get_op_size(src, false); + u8 dst_addr_size = get_op_size_bits(dst_addr, true); + u8 src_size = get_op_size_bits(src, false); if (dst_addr_size != src_size) { LOG_FATAL("Mismatched sizes for store %d != %d", dst_addr_size, src_size); @@ -151,9 +152,9 @@ void scc_x86_emit_store_to_vec(scc_mir_x86_instr_vec_t *vec, .index = SCC_X86_REG_INVALID, .scale = 1, .disp.displacement = 0, - .disp.displacement_bits = dst_addr_size * 8, + .disp.displacement_bits = dst_addr_size, }, - .size = dst_addr_size, + .size_bits = dst_addr_size, }; } else if (dst_addr.kind == SCC_X86_OPR_MEM) { mem_op = dst_addr; diff --git a/libs/ir/mir/src/arch/scc_x86_reg_alloc.c b/libs/ir/mir/src/arch/scc_x86_reg_alloc.c index 11e25c5..878629c 100644 --- a/libs/ir/mir/src/arch/scc_x86_reg_alloc.c +++ b/libs/ir/mir/src/arch/scc_x86_reg_alloc.c @@ -179,7 +179,7 @@ static void x86_alloc_iter_begin(scc_reg_alloc_iter_t *iter) { } static cbool x86_alloc_iter_next(scc_reg_alloc_iter_t *iter, int *out_vreg, - int *out_size, + int *out_size_bits, scc_reg_op_access_t *out_access) { const scc_mir_x86_instr_t *ins = (const scc_mir_x86_instr_t *)iter->instr; scc_x86_iform_t opcode = ins->x86_instr.opcode; @@ -191,7 +191,7 @@ static cbool x86_alloc_iter_next(scc_reg_alloc_iter_t *iter, int *out_vreg, scc_reg_op_access_t base_access = get_operand_access(opcode, iter->op_idx); - *out_size = op->size; + *out_size_bits = op->size_bits; if (op->kind == SCC_X86_OPR_REG) { if (iter->op_sub_idx == 0 && scc_x86_op_is_vreg(op)) { *out_vreg = scc_x86_op_get_vreg(op); @@ -204,7 +204,7 @@ static cbool x86_alloc_iter_next(scc_reg_alloc_iter_t *iter, int *out_vreg, continue; } else if (op->kind == SCC_X86_OPR_MEM) { const scc_x86_mem_t *mem = &op->mem; - *out_size = 8; + *out_size_bits = 64; // 子索引 0: 基址寄存器 if (iter->op_sub_idx == 0) { if (mem->base != SCC_X86_REG_INVALID && diff --git a/libs/ir/mir/src/scc_mir_dump.c b/libs/ir/mir/src/scc_mir_dump.c index 76c90af..d65c8ce 100644 --- a/libs/ir/mir/src/scc_mir_dump.c +++ b/libs/ir/mir/src/scc_mir_dump.c @@ -23,7 +23,7 @@ void scc_mir_dump_bblock(scc_mir_dump_ctx_t *ctx, const scc_mir_func_t *func, switch (instr->opcode) { case SCC_MIR_PSEUDO_ALLOCA: scc_tree_dump_append_fmt(td, " alloca(%d)", - instr->data.alloc.size); + instr->data.alloc.size_bits); break; default: break; diff --git a/libs/ir/mir/src/target/win64_abi.c b/libs/ir/mir/src/target/win64_abi.c index 6d54cca..3d312cb 100644 --- a/libs/ir/mir/src/target/win64_abi.c +++ b/libs/ir/mir/src/target/win64_abi.c @@ -41,7 +41,7 @@ static void frame_layout_impl(scc_frame_layout_t *ctx, .index = SCC_X86_REG_INVALID, .scale = 1, }, - op->size); + op->size_bits); } } } @@ -82,7 +82,7 @@ static void frame_layout_impl(scc_frame_layout_t *ctx, .index = SCC_X86_REG_INVALID, .scale = 1, }, - op->size); + op->size_bits); } } } @@ -118,7 +118,7 @@ static void prologue(scc_mir_instr_vec_t *userdata, /// FILL to shadow space } - u8 size = 8; + u8 size = 64; // sub rsp, frame_size if (frame_size > 0) { scc_mir_x86_instr_2(&instr, SCC_X86_IFORM_SUB_GPRV_IMMZ, @@ -141,7 +141,7 @@ static void epilogue(scc_mir_instr_vec_t *userdata, */ scc_mir_func_meta_t *meta = SCC_MIR_FUNC_META(func); int frame_size = meta->frame_size; - u8 size = 8; + u8 size = 64; // add rsp, frame_size if (frame_size > 0) { scc_mir_x86_instr_2(&instr, SCC_X86_IFORM_ADD_GPRV_IMMZ, @@ -178,7 +178,7 @@ https://learn.microsoft.com/zh-cn/cpp/build/x64-calling-convention?view=msvc-180 static void lower_call(void *userdata, const scc_lir_instr_t *instr) { scc_x86_64_isel_t *isel = userdata; - u8 size = 8; + u8 size = 64; scc_mir_func_meta_t *meta = SCC_MIR_FUNC_META(isel->func); int call_stack_size = instr->metadata.call.arg_count * 8; if (meta->frame_size < call_stack_size) { @@ -233,7 +233,7 @@ static void lower_call(void *userdata, const scc_lir_instr_t *instr) { Panic("unhandled opcode"); } - int ret_size = instr->size; + int ret_size = instr->size_bits; scc_x86_operand_value_t ret_reg = scc_x86_lir_val_to_mir_op(isel, &instr->to, ret_size); if (ret_reg.kind != SCC_X86_OPR_NONE && ret_size != 0) { @@ -265,7 +265,7 @@ static void lower_param(void *userdata, const scc_lir_val_t *val, void *out_op) { scc_x86_operand_value_t *out = out_op; Assert(val->kind == SCC_LIR_INSTR_KIND_ARG); - u8 size = 8; + u8 size = 64; switch (val->data.arg) { case 0: *out = scc_x86_op_preg(SCC_X86_REG_RCX, size); @@ -292,10 +292,10 @@ static void lower_ret(void *userdata, const scc_lir_instr_t *instr) { scc_x86_64_isel_t *isel = userdata; scc_lir_val_t ret_val = instr->metadata.ret_val; u8 size = 0; - if (instr->size) { - size = instr->size; + if (instr->size_bits) { + size = instr->size_bits; } else { - size = 8; + size = 64; } if (ret_val.kind != SCC_LIR_INSTR_KIND_NONE) { scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_RAX, size), diff --git a/libs/ir2mcode/src/scc_ir2mcode.c b/libs/ir2mcode/src/scc_ir2mcode.c index 65563ce..6e5e2c8 100644 --- a/libs/ir2mcode/src/scc_ir2mcode.c +++ b/libs/ir2mcode/src/scc_ir2mcode.c @@ -9,7 +9,6 @@ #include scc_x86_reg_t mir_x86_trans_gpr(scc_x86_reg_t reg, u8 size) { - size *= 8; if (size == 0) { return reg; } @@ -77,7 +76,7 @@ void mir_x86_to_mcode(scc_mcode_t *mcode, scc_reloc_vec_t *relocs, } } else if (op_ptr->kind == SCC_X86_OPR_REG) { ops[i].kind = SCC_X86_OPR_REG; - ops[i].reg = mir_x86_trans_gpr(op_ptr->reg, op_ptr->size); + ops[i].reg = mir_x86_trans_gpr(op_ptr->reg, op_ptr->size_bits); } else { ops[i] = *op_ptr; } diff --git a/libs/lexer/include/scc_lexer.h b/libs/lexer/include/scc_lexer.h index 787473a..6f45dfe 100644 --- a/libs/lexer/include/scc_lexer.h +++ b/libs/lexer/include/scc_lexer.h @@ -21,10 +21,14 @@ typedef struct scc_lexer { scc_lexer_tok_ring_t ring; int ring_ref_count; int jump_macro; + int max_token_len; /**< 最大 token 长度, 0=不限制 */ } scc_lexer_t; void scc_lexer_init(scc_lexer_t *lexer, scc_sstream_ring_t *stream_ref); +/** @brief 设置最大 token 长度限制, 超过时报错。0=不限制(默认) */ +void scc_lexer_set_max_token_len(scc_lexer_t *lexer, int max_len); + /** * @brief 获取原始token * @param[in] lexer 词法分析器实例 diff --git a/libs/lexer/src/lexer.c b/libs/lexer/src/lexer.c index 0e9fd25..ab62c58 100644 --- a/libs/lexer/src/lexer.c +++ b/libs/lexer/src/lexer.c @@ -44,6 +44,11 @@ void scc_lexer_init(scc_lexer_t *lexer, scc_sstream_ring_t *stream_ref) { lexer->stream_ref = stream_ref; lexer->ring_ref_count = 0; lexer->jump_macro = false; + lexer->max_token_len = 0; /* 0=不限制, 兼容旧行为 */ +} + +void scc_lexer_set_max_token_len(scc_lexer_t *lexer, int max_len) { + lexer->max_token_len = max_len; } static inline cbool is_whitespace(int ch) { @@ -80,6 +85,11 @@ static inline cbool next_char(scc_lexer_t *lexer, scc_str_t *lexeme, scc_ring_next(*lexer->stream_ref, *out, ok); if (!ok) return false; + if (lexer->max_token_len > 0 && + scc_str_len(lexeme) >= (usize)lexer->max_token_len) { + LOG_ERROR("token exceeds maximum length (%d)", lexer->max_token_len); + return false; + } scc_str_append_ch(lexeme, out->character); return true; } diff --git a/libs/mcode/include/scc_mcode.h b/libs/mcode/include/scc_mcode.h index f3543be..284e681 100644 --- a/libs/mcode/include/scc_mcode.h +++ b/libs/mcode/include/scc_mcode.h @@ -35,6 +35,42 @@ static inline void scc_mcode_drop(scc_mcode_t *mcode) { mcode->is_littel_endian = true; } +/** + * @brief 接管一个现有缓冲区的所有权作为 mcode 的代码数据 + * + * 释放 mcode 原有的 code 缓冲区, 然后将 buf 的内部指针/容量/大小 + * 转移到 mcode->code。调用后 buf 被重新初始化(空向量)。 + * 避免拷贝大块代码数据。 + */ +static inline void scc_mcode_adopt_buf(scc_mcode_t *mcode, + scc_mcode_buff_t *buf) { + scc_vec_free(mcode->code); + mcode->code.size = buf->size; + mcode->code.cap = buf->cap; + mcode->code.data = buf->data; + buf->size = 0; + buf->cap = 0; + buf->data = NULL; +} + +/** + * @brief 释放 mcode 内部 code 缓冲区的所有权到目标向量 + * + * 将 mcode->code 的数据指针/容量/大小转移到 out 向量, + * 然后 mcode->code 被重新初始化(空向量)。 + * 避免拷贝大块代码数据。 + */ +static inline void scc_mcode_disown_buf(scc_mcode_t *mcode, + scc_mcode_buff_t *out) { + scc_vec_free(*out); + out->size = mcode->code.size; + out->cap = mcode->code.cap; + out->data = mcode->code.data; + mcode->code.size = 0; + mcode->code.cap = 0; + mcode->code.data = NULL; +} + static inline void scc_mcode_add_u8(scc_mcode_t *mcode, u8 data) { scc_vec_push(mcode->code, data); } diff --git a/libs/mcode/include/x86/scc_x86_encode.h b/libs/mcode/include/x86/scc_x86_encode.h index 4e592f4..f432669 100644 --- a/libs/mcode/include/x86/scc_x86_encode.h +++ b/libs/mcode/include/x86/scc_x86_encode.h @@ -45,26 +45,26 @@ typedef struct { scc_x86_mem_t mem; scc_x86_reloc_op_t reloc; }; - u8 size; + u8 size_bits; } scc_x86_operand_value_t; static inline scc_x86_operand_value_t scc_x86_op_preg(scc_x86_reg_t reg, - u8 size) { + u8 size_bits) { scc_x86_operand_value_t o = { .kind = SCC_X86_OPR_REG, .reg = reg, - .size = size, + .size_bits = size_bits, }; return o; } static inline scc_x86_reg_t scc_x86_op_vreg_reg(int vreg) { return (int)SCC_X86_REG_COUNT + vreg; } -static inline scc_x86_operand_value_t scc_x86_op_vreg(int vreg, u8 size) { +static inline scc_x86_operand_value_t scc_x86_op_vreg(int vreg, u8 size_bits) { scc_x86_operand_value_t o = { .kind = SCC_X86_OPR_REG, .reg = scc_x86_op_vreg_reg(vreg), - .size = size, + .size_bits = size_bits, }; return o; } @@ -72,24 +72,24 @@ static inline scc_x86_operand_value_t scc_x86_op_relbr(i32 rel) { scc_x86_operand_value_t o = { .kind = SCC_X86_OPR_RELBR, .brdisp = rel, - .size = 4, + .size_bits = 32, }; return o; } -static inline scc_x86_operand_value_t scc_x86_op_imm(i64 imm, u8 size) { +static inline scc_x86_operand_value_t scc_x86_op_imm(i64 imm, u8 size_bits) { scc_x86_operand_value_t o = { .kind = SCC_X86_OPR_IMM, .simm0 = imm, - .size = size, + .size_bits = size_bits, }; return o; } static inline scc_x86_operand_value_t scc_x86_op_mem(scc_x86_mem_t mem, - u8 size) { + u8 size_bits) { scc_x86_operand_value_t o = { .kind = SCC_X86_OPR_MEM, .mem = mem, - .size = size, + .size_bits = size_bits, }; return o; } @@ -102,7 +102,7 @@ scc_x86_op_reloc_global_imm(const char *sym, i64 addend) { op.reloc.target = SCC_X86_RELOC_TARGET_SYMBOL; op.reloc.global_name = sym; op.reloc.addend = addend; - op.size = 0; + op.size_bits = 0; return op; } @@ -113,7 +113,7 @@ scc_x86_op_reloc_global_relrip(const char *sym, i64 addend) { op.reloc.target = SCC_X86_RELOC_TARGET_SYMBOL; op.reloc.global_name = sym; op.reloc.addend = addend; - op.size = 4; + op.size_bits = 32; return op; } @@ -125,7 +125,7 @@ scc_x86_op_reloc_global_relbr(const char *sym, i64 addend) { op.reloc.target = SCC_X86_RELOC_TARGET_SYMBOL; op.reloc.global_name = sym; op.reloc.addend = addend; - op.size = 4; + op.size_bits = 32; return op; } @@ -137,7 +137,7 @@ static inline scc_x86_operand_value_t scc_x86_op_reloc_block(int bid, op.reloc.target = SCC_X86_RELOC_TARGET_BBLOCK; op.reloc.bblock_id = bid; op.reloc.addend = addend; - op.size = 4; + op.size_bits = 32; return op; } @@ -151,7 +151,7 @@ scc_x86_op_reloc_global_mem(const char *sym, i64 addend) { op.reloc.global_name = sym; op.reloc.addend = addend; // 编码时需生成 RIP 相对寻址的 ModRM/SIB - op.size = 0; + op.size_bits = 0; return op; } diff --git a/libs/mcode/src/scc_x86_encode.c b/libs/mcode/src/scc_x86_encode.c index d212032..018406f 100644 --- a/libs/mcode/src/scc_x86_encode.c +++ b/libs/mcode/src/scc_x86_encode.c @@ -61,10 +61,10 @@ static int infer_operand_width(const scc_x86_iform_info_t *info, for (int i = 0; i < info->num_explicit_ops; i++) { if (ops[i].kind == SCC_X86_OPR_REG && !info->ops[i].is_implicit) { uint16_t w; - if (ops[i].size > 0 && ops[i].reg >= SCC_X86_REG_R8 && + if (ops[i].size_bits > 0 && ops[i].reg >= SCC_X86_REG_R8 && ops[i].reg <= SCC_X86_REG_R15) { - /* R8-R15:宽度由 size 字段推导 */ - w = ops[i].size * 8; + /* R8-R15:宽度由 size_bits 字段推导(单位:bit) */ + w = ops[i].size_bits; } else { w = scc_reg_width(ops[i].reg); } diff --git a/libs/target/elf/cbuild.toml b/libs/target/elf/cbuild.toml new file mode 100644 index 0000000..4b56a87 --- /dev/null +++ b/libs/target/elf/cbuild.toml @@ -0,0 +1,9 @@ +[package] +name = "scc_elf" +version = "0.1.0" +authors = [] +description = "" + +dependencies = [{ name = "scc_utils", path = "../../../runtime/scc_utils" }] +# features = {} +# default_features = [] diff --git a/libs/target/pe/src/scc_pe_builder.c b/libs/target/pe/src/scc_pe_builder.c index 3097fa5..2792e45 100644 --- a/libs/target/pe/src/scc_pe_builder.c +++ b/libs/target/pe/src/scc_pe_builder.c @@ -23,6 +23,11 @@ static u32 reserve_file(scc_pe_builder_t *builder, u32 len, u32 align) { builder->file_offset = reserve_align(builder->file_offset, align); u32 offset = builder->file_offset; + /* TODO overflow check: u32 溢出保护, 设计未定暂用简单检查 */ + if (builder->file_offset + len < builder->file_offset) { + LOG_FATAL("reserve_file: u32 overflow (offset=%u len=%u)", + builder->file_offset, len); + } builder->file_offset += len; LOG_INFO("reserve_file %u bytes at %u [%u]", len, offset, builder->file_offset); @@ -35,6 +40,11 @@ static u32 reserve_virtual(scc_pe_builder_t *builder, u32 len, u32 align) { } u32 offset = builder->virtual_offset; + /* TODO overflow check: u32 溢出保护, 设计未定暂用简单检查 */ + if (builder->virtual_offset + len < builder->virtual_offset) { + LOG_FATAL("reserve_virtual: u32 overflow (offset=%u len=%u)", + builder->virtual_offset, len); + } builder->virtual_offset += len; builder->virtual_offset = reserve_align(builder->virtual_offset, align); LOG_INFO("reserve_virtual %u bytes at %u [%u]", len, offset, diff --git a/libs/target/pe/src/scc_pe_idata.c b/libs/target/pe/src/scc_pe_idata.c index 1abab55..49c98ca 100644 --- a/libs/target/pe/src/scc_pe_idata.c +++ b/libs/target/pe/src/scc_pe_idata.c @@ -63,13 +63,19 @@ void scc_pe_idata_builder_init(scc_pe_idata_builder_t *builder, } u32 scc_pe_reserve_idata(scc_pe_idata_builder_t *builder) { + /* TODO overflow check: idata_size 为 u32, 乘法可能溢出, + 设计未定暂不插入 stdint 类型, 仅做简单防护 */ u32 idata_size = (scc_vec_size(builder->idata_libs) + 1) * sizeof(IMAGE_IMPORT_DESCRIPTOR); scc_vec_foreach(builder->idata_libs, i) { scc_pe_idata_lib_t *lib = &scc_vec_at(builder->idata_libs, i); - idata_size += (scc_vec_size(lib->symbol_names) + 1) * 2 * - sizeof(IMAGE_THUNK_DATA64); + u32 thunk_size = (scc_vec_size(lib->symbol_names) + 1) * 2 * + sizeof(IMAGE_THUNK_DATA64); + if (idata_size + thunk_size < idata_size) { + LOG_FATAL("scc_pe_reserve_idata: u32 overflow"); + } + idata_size += thunk_size; scc_winpe_hnt_builder_push(&builder->hnt_builder, lib->name, 0); scc_vec_foreach(lib->symbol_names, j) { @@ -78,6 +84,9 @@ u32 scc_pe_reserve_idata(scc_pe_idata_builder_t *builder) { } } builder->hnt_builder.section_offset = idata_size; + if (idata_size + scc_vec_size(builder->hnt_builder.data) < idata_size) { + LOG_FATAL("scc_pe_reserve_idata: u32 overflow on hnt data"); + } idata_size += scc_vec_size(builder->hnt_builder.data); scc_vec_realloc(builder->buffer, idata_size); diff --git a/libs/target/sccf2target/src/sccf2pe.c b/libs/target/sccf2target/src/sccf2pe.c index 4e5a0fe..5a395a5 100644 --- a/libs/target/sccf2target/src/sccf2pe.c +++ b/libs/target/sccf2target/src/sccf2pe.c @@ -212,8 +212,7 @@ void sccf2pe(scc_pe_builder_t *builder, const sccf_t *sccf) { scc_mcode_t mcode; scc_mcode_init(&mcode, SCC_MCODE_ARCH_X86_64); - // FIXME hack - mcode.code = *(scc_mcode_buff_t *)code_data; + scc_mcode_adopt_buf(&mcode, (scc_mcode_buff_t *)code_data); scc_vec_foreach(relocs, i) { sccf_reloc_t *reloc = &scc_vec_at(relocs, i); if (reloc->reloc_type == SCCF_RELOC_TYPE_EMPTY) { @@ -243,7 +242,7 @@ void sccf2pe(scc_pe_builder_t *builder, const sccf_t *sccf) { scc_x86_patch(&mcode, SCC_X86_PATCH_PC32, reloc->offset + reloc->addend, (i64)rva - (i64)code_range.virual_address); } - *(scc_mcode_buff_t *)code_data = mcode.code; + scc_mcode_disown_buf(&mcode, (scc_mcode_buff_t *)code_data); scc_pe_write_header(builder, &config); if (code_data != nullptr) { diff --git a/libs/target/sccf2target/tests/test_sccf2pe_run.c b/libs/target/sccf2target/tests/test_sccf2pe_run.c index a56ea79..f51c2b5 100644 --- a/libs/target/sccf2target/tests/test_sccf2pe_run.c +++ b/libs/target/sccf2target/tests/test_sccf2pe_run.c @@ -2,6 +2,7 @@ #include #include #include +#include int main() { char data[] = "Hello, World from SCC PE Builder!\n\0"; @@ -56,13 +57,13 @@ int main() { .offset = 7, .sect_type = SCCF_SECT_CODE, .sym_idx = str_idx, - .reloc_type = SCCF_RELOC_TYPE_REL}); + .reloc_type = SCC_X86_OPR_RELBR}); sccf_builder_add_reloc(&builder, (sccf_reloc_t){.addend = 4, .offset = 13, .sect_type = SCCF_SECT_CODE, .sym_idx = puts_idx, - .reloc_type = SCCF_RELOC_TYPE_REL}); + .reloc_type = SCC_X86_OPR_RELBR}); const sccf_t *sccf = sccf_builder_to_sccf(&builder); scc_pe_builder_t pe_builder; diff --git a/libs/target/type_abi/cbuild.toml b/libs/target/type_abi/cbuild.toml new file mode 100644 index 0000000..c6ce883 --- /dev/null +++ b/libs/target/type_abi/cbuild.toml @@ -0,0 +1,9 @@ +[package] +name = "type_abi" +version = "0.1.0" +authors = [] +description = "" + +dependencies = [ + { name = "scc_core", path = "../../../runtime/scc_core" }, +] diff --git a/libs/target/type_abi/include/scc_type_abi.h b/libs/target/type_abi/include/scc_type_abi.h new file mode 100644 index 0000000..5f43b2d --- /dev/null +++ b/libs/target/type_abi/include/scc_type_abi.h @@ -0,0 +1,53 @@ +#ifndef __SCC_TYPE_ABI_H__ +#define __SCC_TYPE_ABI_H__ + +#include + +/// 类型布局的三个本质可变点 +typedef struct scc_type_abi scc_type_abi_t; + +struct scc_type_abi { + int ptr_size; + int ptr_align; + int endian; // 0 = little, 1 = big + + // C 类型大小 (AST → HIR 时需要) + int char_size; + int short_size; + int int_size; + int long_size; + int long_long_size; + int float_size; + int double_size; + int long_double_size; + int va_list_size; + + // byte_size → 对齐。NULL = 自然对齐 (return byte_size) + int (*type_align)(int byte_size); + + // 字段对齐覆盖。NULL = 用 type_align 的值 + int (*field_align)(int field_size, int natural_align); + + // 聚合体总对齐。NULL = max 字段 align + int (*aggregate_align)(int max_field_align); +}; + +static inline int scc_type_abi_get_type_align(const scc_type_abi_t *abi, + int byte_size) { + return abi->type_align ? abi->type_align(byte_size) : byte_size; +} + +static inline int scc_type_abi_get_field_align(const scc_type_abi_t *abi, + int field_size, + int natural_align) { + return abi->field_align ? abi->field_align(field_size, natural_align) + : natural_align; +} + +static inline int scc_type_abi_get_aggregate_align(const scc_type_abi_t *abi, + int max_field_align) { + return abi->aggregate_align ? abi->aggregate_align(max_field_align) + : max_field_align; +} + +#endif /* __SCC_TYPE_ABI_H__ */ diff --git a/libs/target/type_abi/include/scc_type_abi_systemv_x64.h b/libs/target/type_abi/include/scc_type_abi_systemv_x64.h new file mode 100644 index 0000000..bf510fa --- /dev/null +++ b/libs/target/type_abi/include/scc_type_abi_systemv_x64.h @@ -0,0 +1,27 @@ +#ifndef __SCC_TYPE_ABI_SYSTEMV_X64_H__ +#define __SCC_TYPE_ABI_SYSTEMV_X64_H__ + +#include "scc_type_abi.h" + +/// SystemV x86-64: long = 8, long_double = 16, 全部自然对齐 +static const scc_type_abi_t SCC_TYPE_ABI_SYSTEMV_X64 = { + .ptr_size = 8, + .ptr_align = 8, + .endian = 0, + + .char_size = 1, + .short_size = 2, + .int_size = 4, + .long_size = 8, // SysV: long = 8 bytes + .long_long_size = 8, + .float_size = 4, + .double_size = 8, + .long_double_size = 16, // SysV x86-64: long double = 80-bit extended precision, padded to 16 + .va_list_size = 8, + + .type_align = NULL, + .field_align = NULL, + .aggregate_align = NULL, +}; + +#endif /* __SCC_TYPE_ABI_SYSTEMV_X64_H__ */ diff --git a/libs/target/type_abi/include/scc_type_abi_win_x64.h b/libs/target/type_abi/include/scc_type_abi_win_x64.h new file mode 100644 index 0000000..fb4cee4 --- /dev/null +++ b/libs/target/type_abi/include/scc_type_abi_win_x64.h @@ -0,0 +1,35 @@ +#ifndef __SCC_TYPE_ABI_WIN_X64_H__ +#define __SCC_TYPE_ABI_WIN_X64_H__ + +#include "scc_type_abi.h" + +/// Win64: ≥16B 类型在 struct 中对齐到 8 而非 16 +int scc_win64_field_align(int field_size, int natural_align); +#ifdef __SCC_TYPE_ABI_WIN_X64_IMPL__ +int scc_win64_field_align(int field_size, int natural_align) { + (void)field_size; + return natural_align >= 16 ? 8 : natural_align; +} +#endif + +static const scc_type_abi_t SCC_TYPE_ABI_WIN_X64 = { + .ptr_size = 8, + .ptr_align = 8, + .endian = 0, + + .char_size = 1, + .short_size = 2, + .int_size = 4, + .long_size = 4, // Win64: long = 4 bytes + .long_long_size = 8, + .float_size = 4, + .double_size = 8, + .long_double_size = 8, + .va_list_size = 4, + + .type_align = NULL, + .field_align = scc_win64_field_align, + .aggregate_align = NULL, +}; + +#endif /* __SCC_TYPE_ABI_WIN_X64_H__ */ diff --git a/runtime/scc_core/include/scc_core_impl.h b/runtime/scc_core/include/scc_core_impl.h index b668ffe..c76d1db 100644 --- a/runtime/scc_core/include/scc_core_impl.h +++ b/runtime/scc_core/include/scc_core_impl.h @@ -4,9 +4,12 @@ #include "scc_core_pal.h" #include "scc_core_type.h" -#define scc_malloc scc_pal_malloc -#define scc_calloc scc_pal_calloc -#define scc_realloc scc_pal_realloc +void *__scc_malloc(size_t size); +void *__scc_calloc(size_t count, size_t size); +void *__scc_realloc(void *ptr, size_t new_size); +#define scc_malloc __scc_malloc +#define scc_calloc __scc_calloc +#define scc_realloc __scc_realloc #define scc_free scc_pal_free #define scc_exit scc_pal_exit #define scc_abort scc_pal_abort diff --git a/runtime/scc_core/src/core_impl.c b/runtime/scc_core/src/core_impl.c index 27dbe6a..8a1ce4c 100644 --- a/runtime/scc_core/src/core_impl.c +++ b/runtime/scc_core/src/core_impl.c @@ -5,6 +5,30 @@ #define __SCC_LOG_IMPL_IMPORT_SRC__ #include +void *__scc_malloc(size_t size) { + void *p = scc_pal_malloc(size); + if (!p) { + LOG_FATAL("__scc_malloc: allocation failed (%zu bytes)", size); + } + return p; +} + +void *__scc_calloc(size_t count, size_t size) { + void *p = scc_pal_calloc(count, size); + if (!p) { + LOG_FATAL("__scc_calloc: allocation failed (%zu x %zu)", count, size); + } + return p; +} + +void *__scc_realloc(void *ptr, size_t new_size) { + void *p = scc_pal_realloc(ptr, new_size); + if (!p) { + LOG_FATAL("__scc_realloc: allocation failed (%zu bytes)", new_size); + } + return p; +} + void putchar_(char ch) { (void)ch; LOG_FATAL("you can't use printf.c directly"); diff --git a/src/main.c b/src/main.c index 50bc1b0..197cfec 100644 --- a/src/main.c +++ b/src/main.c @@ -17,6 +17,9 @@ #include #include +#define __SCC_TYPE_ABI_WIN_X64_IMPL__ +#include + #include "config.h" void init_platform(void); #define GET_VALID_FP(fp) (fp == nullptr ? scc_stdout : fp) @@ -240,10 +243,10 @@ sstream_drop: } scc_ast2ir_ctx_t ast2ir_ctx; -#include scc_hir_cprog_t cprog; scc_hir_cprog_init(&cprog); - scc_ast2ir_ctx_init(&ast2ir_ctx, &scc_ast_abi_impl, &ast_module, &cprog); + scc_ast2ir_ctx_init(&ast2ir_ctx, &SCC_TYPE_ABI_WIN_X64, &ast_module, + &cprog); scc_ast2ir_run(&ast2ir_ctx, translation_unit); scc_ast2ir_ctx_drop(&ast2ir_ctx);