diff --git a/libs/ast2ir/include/scc_ast2ir.h b/libs/ast2ir/include/scc_ast2ir.h index bb2c9f5..dded231 100644 --- a/libs/ast2ir/include/scc_ast2ir.h +++ b/libs/ast2ir/include/scc_ast2ir.h @@ -19,6 +19,10 @@ typedef struct { scc_ast_ctx_t *ast_ctx; } scc_ast2ir_ctx_t; +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, scc_ast_ctx_t *ast_ctx, scc_hir_cprog_t *cprog); void scc_ast2ir_ctx_drop(scc_ast2ir_ctx_t *ctx); diff --git a/libs/ast2ir/src/scc_ast2ir.c b/libs/ast2ir/src/scc_ast2ir.c index 01b31ef..f251faa 100644 --- a/libs/ast2ir/src/scc_ast2ir.c +++ b/libs/ast2ir/src/scc_ast2ir.c @@ -55,7 +55,7 @@ static void emit_array_initialization(scc_ast2ir_ctx_t *ctx, 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(&ctx->builder.cprog->module, elem_type_ref); + scc_hir_module_get_type(scc_ast2ir_mir_module(ctx), elem_type_ref); usize array_len = array_type->data.array.len; // 字符串字面量初始化:直接 memcpy @@ -124,8 +124,8 @@ static void emit_aggregate_initialization(scc_ast2ir_ctx_t *ctx, 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( - &ctx->builder.cprog->module, field_type_ref); + 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); @@ -149,68 +149,6 @@ static void emit_aggregate_initialization(scc_ast2ir_ctx_t *ctx, } // static inline void parse_struct_union_layout(scc_ast_qual_type_t *type) {} -usize scc_hir_type_size(scc_ast2ir_ctx_t *ctx, const scc_hir_type_t *type) { - switch (type->tag) { - case SCC_HIR_TYPE_void: - return 0; - case SCC_HIR_TYPE_i8: - return 1; - case SCC_HIR_TYPE_i16: - return 2; - case SCC_HIR_TYPE_i32: - return 4; - case SCC_HIR_TYPE_i64: - return 8; - case SCC_HIR_TYPE_i128: - return 16; - case SCC_HIR_TYPE_u8: - return 1; - case SCC_HIR_TYPE_u16: - return 2; - case SCC_HIR_TYPE_u32: - return 4; - case SCC_HIR_TYPE_u64: - return 8; - case SCC_HIR_TYPE_u128: - return 16; - case SCC_HIR_TYPE_f16: - return 2; - case SCC_HIR_TYPE_f32: - return 4; - case SCC_HIR_TYPE_f64: - return 8; - case SCC_HIR_TYPE_f128: - return 16; - - case SCC_HIR_TYPE_PTR: { - // 目标指针大小,可以定义为 8(64位)或从 ABI 获取 - // 假设你的目标架构是 64 位 - return 8; - } - - case SCC_HIR_TYPE_ARRAY: { - usize elem_size = scc_hir_type_size( - ctx, scc_hir_module_get_type(&ctx->builder.cprog->module, - type->data.array.base)); - return elem_size * type->data.array.len; - } - - case SCC_HIR_TYPE_FUNC: - // 函数类型大小一般是指针大小 - return 8; - - case SCC_HIR_TYPE_STRUCT: - case SCC_HIR_TYPE_UNION: - // 暂时无法计算,保守返回 0 或报错 - LOG_ERROR("Cannot compute size of struct/union without layout info"); - return 0; - - default: - LOG_ERROR("Unknown type tag %d", type->tag); - return 0; - } -} - // 辅助函数:计算数组实际长度(如果原长度为0) static void resolve_array_length(scc_ast2ir_ctx_t *ctx, const scc_hir_type_t *orig_array_type, @@ -334,7 +272,7 @@ scc_hir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx, // === 3. 直接添加到模块,不经过 builder 的 uniquing === // 因为此时我们不需要类型去重,只需要一个确定不移的引用 scc_hir_type_ref_t place_ref = - scc_hir_module_add_type(&ctx->builder.cprog->module, &placeholder); + scc_hir_module_add_type(scc_ast2ir_mir_module(ctx), &placeholder); // === 4. 将映射写入缓存(关键!必须在递归前) === scc_hashtable_set(&ctx->type_cache, canon, (void *)(usize)place_ref); @@ -357,7 +295,7 @@ scc_hir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx, // === 6. 将字段填入占位类型 === scc_hir_type_t *place_type = - scc_hir_module_get_type(&ctx->builder.cprog->module, place_ref); + scc_hir_module_get_type(scc_ast2ir_mir_module(ctx), place_ref); // 注意:scc_hir_type_init 已经为 struct/union 初始化了 fields 空向量 // 这里直接 push 即可(也可以先 scc_vec_free 再 init,看需要) scc_vec_foreach(fields, i) { @@ -895,13 +833,15 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, // 3. 确定转换模式(SEXT / ZEXT / TRUNC) // 这里用简单的启发式:根据大小变化决定 scc_hir_type_t *src_type = scc_hir_module_get_type_by_value( - &ctx->builder.cprog->module, operand); + scc_ast2ir_mir_module(ctx), operand); scc_hir_type_t *dst_type = - scc_hir_module_get_type(&ctx->builder.cprog->module, target_type); + scc_hir_module_get_type(scc_ast2ir_mir_module(ctx), target_type); - usize src_size = - scc_hir_type_size(ctx, src_type); // 你可能有这个函数,否则自行计算 - usize dst_size = scc_hir_type_size(ctx, dst_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) { @@ -923,8 +863,7 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, .data.conv.target_type = target_type, .data.conv.conv_type = conv_kind, }; - return scc_hir_module_add_value(&ctx->builder.cprog->module, - &conv_node); + return scc_hir_module_add_value(scc_ast2ir_mir_module(ctx), &conv_node); } case SCC_AST_EXPR_SIZE_OF: { // 1. 将 sizeof 的操作数(类型或表达式)转换为 IR 类型 @@ -939,7 +878,7 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_hir_value_ref_t dummy = scc_ast2ir_expr(ctx, expr->attr_of.expr, false); hir_type = - scc_hir_module_get_value(&ctx->builder.cprog->module, dummy) + scc_hir_module_get_value(scc_ast2ir_mir_module(ctx), dummy) ->type; } else { scc_ap_t val; @@ -951,8 +890,9 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, // 2. 计算大小 const scc_hir_type_t *type = - scc_hir_module_get_type(&ctx->builder.cprog->module, hir_type); - usize dst_size = scc_hir_type_size(ctx, 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; @@ -971,7 +911,7 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, 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(&ctx->builder.cprog->module, type_ref); + scc_hir_module_get_type(scc_ast2ir_mir_module(ctx), type_ref); // 2. 分配栈上临时存储 scc_hir_value_ref_t storage = @@ -1073,10 +1013,10 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, } else { // 右值:如果是数组类型,退化为指针(返回地址) scc_hir_type_t *ir_type = scc_hir_module_get_type_by_value( - &ctx->builder.cprog->module, in); + 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( - &ctx->builder.cprog->module, ir_type->data.pointer.base); + 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, @@ -1344,8 +1284,7 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, const scc_ast_decl_t *decl, const scc_hir_type_t *orig_type; SCC_HIR_BUILDER_BEGIN_BORROW( &ctx->builder, orig_type, - scc_hir_module_get_type(&ctx->builder.cprog->module, - orig_type_ref)); + scc_hir_module_get_type(scc_ast2ir_mir_module(ctx), orig_type_ref)); scc_hir_type_t final_type_desc = *orig_type; SCC_HIR_BUILDER_END_BORROW(&ctx->builder); @@ -1384,7 +1323,7 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, const scc_ast_decl_t *decl, const scc_hir_type_t *final_type; SCC_HIR_BUILDER_BEGIN_BORROW( &ctx->builder, final_type, - scc_hir_module_get_type(&ctx->builder.cprog->module, + scc_hir_module_get_type(scc_ast2ir_mir_module(ctx), final_type_ref)); scc_hir_type_t type = *final_type; SCC_HIR_BUILDER_END_BORROW(&ctx->builder); diff --git a/libs/ir/hir/include/scc_hir_builder.h b/libs/ir/hir/include/scc_hir_builder.h index b7cbb0c..a9c8fe1 100644 --- a/libs/ir/hir/include/scc_hir_builder.h +++ b/libs/ir/hir/include/scc_hir_builder.h @@ -131,6 +131,7 @@ scc_hir_value_ref_t scc_hir_builder_builtin_memcpy(scc_hir_builder_t *builder, static inline scc_hir_value_ref_t scc_hir_builder_integer(scc_hir_builder_t *builder, scc_hir_type_ref_t type, scc_ap_t *val) { + Assert(builder != nullptr && val != nullptr); scc_hir_value_t value; scc_hir_value_init(&value, nullptr, SCC_HIR_VALUE_TAG_INTEGER); // FIXME assign diff --git a/libs/ir/hir/include/scc_hir_module.h b/libs/ir/hir/include/scc_hir_module.h index 7ca3cf0..c41a1ed 100644 --- a/libs/ir/hir/include/scc_hir_module.h +++ b/libs/ir/hir/include/scc_hir_module.h @@ -38,6 +38,7 @@ scc_hir_bblock_t *scc_hir_module_get_bblock(scc_hir_module_t *ctx, scc_hir_bblock_ref_t ref); scc_hir_func_t *scc_hir_module_get_func(scc_hir_module_t *ctx, scc_hir_func_ref_t ref); +usize scc_hir_module_type_size(scc_hir_module_t *ctx, scc_hir_type_t *type); static inline scc_hir_type_t * scc_hir_module_get_type_by_value(scc_hir_module_t *ctx, diff --git a/libs/ir/hir/src/scc_hir_builder.c b/libs/ir/hir/src/scc_hir_builder.c index 303bc34..0653d7b 100644 --- a/libs/ir/hir/src/scc_hir_builder.c +++ b/libs/ir/hir/src/scc_hir_builder.c @@ -287,14 +287,8 @@ scc_hir_value_ref_t scc_hir_builder_const_string(scc_hir_builder_t *builder, scc_hir_builder_global_alloca(builder, array_type_ref, const_array_ref); // scc_hashtable_insert(builder); - scc_hir_value_ref_t pointer_to_global_value = scc_hir_module_add_value( - GET_MODULE(builder), - &(scc_hir_value_t){ - .tag = SCC_HIR_VALUE_TAG_GET_ELEM_PTR, - .data.get_elem_ptr.src_addr = global_value_ref, - .data.get_elem_ptr.index = SCC_HIR_VALUE_TAG_NULLPTR, - }); - scc_hir_builder_add_instr(builder, pointer_to_global_value); + scc_hir_value_ref_t pointer_to_global_value = scc_hir_builder_get_elem_ptr( + builder, global_value_ref, SCC_HIR_VALUE_TAG_NULLPTR); return pointer_to_global_value; } @@ -406,12 +400,18 @@ scc_hir_value_ref_t scc_hir_builder_global_alloca(scc_hir_builder_t *builder, scc_hir_type_ref_t type, scc_hir_value_ref_t value) { SCC_HIR_BUILDER_CHECK_NO_BORROW(builder); + // 全局变量的实际类型是指向 type 的指针 + scc_hir_type_t ptr_type = {.tag = SCC_HIR_TYPE_PTR, + .data.pointer.base = type}; + scc_hir_type_ref_t ptr_type_ref = scc_hir_builder_type(builder, &ptr_type); + + // FIXME char *name = scc_malloc(32); scc_hir_value_ref_t global_value_ref = scc_hir_module_add_value( GET_MODULE(builder), &(scc_hir_value_t){ .name = name, .tag = SCC_HIR_VALUE_TAG_GLOBAL_ALLOC, - .type = type, + .type = ptr_type_ref, // 类型是指针 .data.global_alloc.value = value, }); scc_snprintf(name, 32, "$G%u", global_value_ref); @@ -506,6 +506,12 @@ scc_hir_value_ref_t scc_hir_builder_get_elem_ptr(scc_hir_builder_t *builder, scc_hir_value_t get_ptr_node = {0}; get_ptr_node.tag = SCC_HIR_VALUE_TAG_GET_ELEM_PTR; get_ptr_node.data.get_elem_ptr.src_addr = target; + if (index == SCC_HIR_REF_nullptr) { + scc_ap_t ap = {.capacity = -1, .len = 0, .data.digit = 0}; + index = scc_hir_builder_integer(builder, + scc_hir_builder_type_u8(builder), &ap); + } + Assert(target != SCC_HIR_REF_nullptr && index != SCC_HIR_REF_nullptr); get_ptr_node.data.get_elem_ptr.index = index; // 借用类型信息 diff --git a/libs/ir/hir/src/scc_hir_module.c b/libs/ir/hir/src/scc_hir_module.c index 32854a2..2dcf1c4 100644 --- a/libs/ir/hir/src/scc_hir_module.c +++ b/libs/ir/hir/src/scc_hir_module.c @@ -126,3 +126,46 @@ scc_hir_func_t *scc_hir_module_get_func(scc_hir_module_t *ctx, scc_hir_func_ref_t ref) { return scc_cfg_module_unsafe_get_func(&ctx->cfg_module, ref); } + +usize scc_hir_module_type_size(scc_hir_module_t *ctx, scc_hir_type_t *type) { + Assert(type != nullptr); + switch (type->tag) { + case SCC_HIR_TYPE_unknown: + case SCC_HIR_TYPE_void: + return 0; + case SCC_HIR_TYPE_i8: + case SCC_HIR_TYPE_u8: + return 1; + case SCC_HIR_TYPE_i16: + case SCC_HIR_TYPE_u16: + return 2; + case SCC_HIR_TYPE_f32: + case SCC_HIR_TYPE_i32: + case SCC_HIR_TYPE_u32: + return 4; + case SCC_HIR_TYPE_f64: + case SCC_HIR_TYPE_i64: + case SCC_HIR_TYPE_u64: + return 8; + case SCC_HIR_TYPE_FUNC: + case SCC_HIR_TYPE_PTR: { + // TODO + // 目标指针大小,可以定义为 8(64位)或从 ABI 获取 + // 假设你的目标架构是 64 位 + return 8; + } + case SCC_HIR_TYPE_ARRAY: { + usize elem_size = scc_hir_module_type_size( + ctx, scc_hir_module_get_type(ctx, type->data.array.base)); + return elem_size * type->data.array.len; + } + case SCC_HIR_TYPE_STRUCT: + case SCC_HIR_TYPE_UNION: + // 暂时无法计算,保守返回 0 或报错 + LOG_ERROR("Cannot compute size of struct/union without layout info"); + return 0; + default: + LOG_ERROR("Unknown type tag %d", type->tag); + return 0; + } +} diff --git a/libs/ir/lir/include/scc_lir.h b/libs/ir/lir/include/scc_lir.h index d119bab..3331b30 100644 --- a/libs/ir/lir/include/scc_lir.h +++ b/libs/ir/lir/include/scc_lir.h @@ -41,26 +41,14 @@ typedef enum { SCC_LIR_INSTR_KIND_MEM, // 复杂地址表达式 (base + index*scale + offset) } scc_lir_instr_kind_t; -/** - * @brief 复杂地址表达式 - * base + index * scale + offset - */ -typedef struct scc_lir_addr { - int base; // 基址寄存器,-1 表示无 - int index; // 索引寄存器,-1 表示无 - int scale; // 比例因子 (1, 2, 4, 8) - i64 offset; // 常量偏移 -} scc_lir_addr_t; - typedef struct scc_lir_instr { scc_lir_instr_kind_t kind; union { int arg; - int reg; // VREG 或 PREG 索引 - scc_ap_t imm; // 整型立即数 - f64 fimm; // 浮点立即数 - const char *symbol; // 符号名 (生命周期由前端管理) - scc_lir_addr_t addr; // 复杂地址 + int reg; // VREG 或 PREG 索引 + scc_ap_t imm; // 整型立即数 + f64 fimm; // 浮点立即数 + const char *symbol; // 符号名 (生命周期由前端管理) } data; } scc_lir_val_t; @@ -74,8 +62,6 @@ typedef struct scc_lir_instr { ((scc_lir_val_t){.kind = SCC_LIR_INSTR_KIND_FIMM, .data.fimm = (v)}) #define SCC_LIR_SYMBOL(s) \ ((scc_lir_val_t){.kind = SCC_LIR_INSTR_KIND_SYMBOL, .data.symbol = (s)}) -#define SCC_LIR_ADDR(b, i, s, o) \ - ((scc_lir_val_t){.kind = SCC_LIR_INSTR_KIND_MEM, .data.addr = {b, i, s, o}}) #define SCC_LIR_ARG(n) \ ((scc_lir_val_t){.kind = SCC_LIR_INSTR_KIND_ARG, .data.arg = (n)}) @@ -97,7 +83,6 @@ typedef enum { SCC_LIR_LOAD, SCC_LIR_LOAD_ADDR, SCC_LIR_STORE, - SCC_LIR_STORE_ADDR, /* 整数算术 */ SCC_LIR_ADD, @@ -143,6 +128,9 @@ typedef enum { SCC_LIR_VA_ARG, SCC_LIR_VA_END, SCC_LIR_VA_COPY, + /* 内置方法 */ + SCC_LIR_MEMCPY, + SCC_LIR_MEMSET, /* 栈管理 */ SCC_LIR_ALLOCA, @@ -183,6 +171,12 @@ typedef struct scc_lir_ins { union { scc_lir_cond_t cond; + // base + index * scale + offset + struct scc_lir_addr { + int scale; // 比例因子 (1, 2, 4, 8) + i64 offset; // 常量偏移 + } addr; + struct scc_lir_br { scc_lir_bblock_id_t true_target; scc_lir_bblock_id_t false_target; @@ -240,6 +234,18 @@ typedef struct scc_lir_ins { scc_lir_val_t dest; scc_lir_val_t src; } va_copy; + + struct { + scc_lir_val_t dest; + scc_lir_val_t src; + scc_lir_val_t size; + } memcpy; + + struct { + scc_lir_val_t dest; + scc_lir_val_t value; + scc_lir_val_t size; + } memset; } metadata; } scc_lir_instr_t; @@ -259,17 +265,15 @@ typedef struct scc_lir_func_meta { typedef scc_cfg_symbol_id_t scc_lir_symbol_id_t; typedef scc_cfg_symbol_t scc_lir_symbol_t; -typedef struct scc_lir_symbol_meta { - union { - struct { - scc_lir_func_t *func; // 指向函数体(若为定义) - } func; - struct { - u8 *init_data; // 初始化数据(若为 NULL 则零初始化) - usize size; // 数据大小(字节) - int align; // 对齐要求 - } data; - }; +typedef union scc_lir_symbol_meta { + struct { + scc_lir_func_t *func; // 指向函数体(若为定义) + } func; + struct { + u8 *init_data; // 初始化数据(若为 NULL 则零初始化) + usize size; // 数据大小(字节) + int align; // 对齐要求 + } data; } scc_lir_symbol_meta_t; #define SCC_LIR_SYMBOL_META(symbol) ((scc_lir_symbol_meta_t *)(symbol)->meta) diff --git a/libs/ir/lir/src/scc_hir2lir.c b/libs/ir/lir/src/scc_hir2lir.c index 1a0d0d0..2adf746 100644 --- a/libs/ir/lir/src/scc_hir2lir.c +++ b/libs/ir/lir/src/scc_hir2lir.c @@ -79,6 +79,7 @@ static void ir_type_to_lir_size_ext(scc_hir_type_t *type, u8 *out_size, *out_size = SCC_LIR_SIZE_64; *out_ext = SCC_LIR_EXT_FLOAT; break; + case SCC_HIR_TYPE_ARRAY: case SCC_HIR_TYPE_PTR: *out_size = SCC_LIR_SIZE_64; *out_ext = SCC_LIR_EXT_NONE; @@ -126,9 +127,7 @@ static scc_lir_val_t ir_value_to_lir_operand(ir2lir_ctx_t *ctx, } case SCC_HIR_VALUE_TAG_GLOBAL_ALLOC: { // 全局变量地址作为符号 - scc_hir_value_t *global_val = scc_hir_module_get_value( - ctx->hir_module, val->data.global_alloc.value); - return SCC_LIR_SYMBOL(global_val->name); + return SCC_LIR_SYMBOL(val->name); } case SCC_HIR_VALUE_TAG_FUNC_ARG_REF: { // 函数参数:预先已分配 vreg @@ -240,6 +239,24 @@ static scc_lir_op_t map_binop(scc_hir_op_type_t op, cbool is_float) { return SCC_LIR_NOP; } +// 确保操作数是一个虚拟寄存器,如果不是则生成 MOV 并返回新 VREG 编号 +static int ensure_vreg(ir2lir_ctx_t *ctx, scc_lir_val_t *val) { + if (val->kind == SCC_LIR_INSTR_KIND_VREG) { + return val->data.reg; + } + // 分配新的虚拟寄存器 + 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, // 地址宽度 + .to = SCC_LIR_VREG(new_vreg), + .arg0 = *val}; + scc_lir_builder_add_instr(ctx, &mov); + // 将原操作数替换为 VREG,避免重复转换 + val->kind = SCC_LIR_INSTR_KIND_VREG; + val->data.reg = new_vreg; + return new_vreg; +} + static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value, scc_hir_value_ref_t value_ref) { // 防止重复翻译 @@ -254,8 +271,7 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value, } bool is_float = (ext == SCC_LIR_EXT_FLOAT); - // 为当前指令分配目标虚拟寄存器 - unsigned int dst_vreg = get_vreg_for_value(ctx, value_ref); + int dst_vreg = get_vreg_for_value(ctx, value_ref); switch (value->tag) { case SCC_HIR_VALUE_TAG_OP: { @@ -291,70 +307,60 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value, ir_value_to_lir_operand(ctx, value->data.store.value); scc_lir_val_t addr = ir_value_to_lir_operand(ctx, value->data.store.target); - scc_lir_instr_t instr = { - .op = SCC_LIR_STORE, .size = size, .arg0 = data, .arg1 = addr}; + ty = scc_hir_module_get_type_by_value(ctx->hir_module, + value->data.store.value); + ir_type_to_lir_size_ext(ty, &size, &ext); + scc_lir_instr_t instr = {.op = SCC_LIR_STORE, + .ext = ext, + .size = size, + .arg0 = data, + .arg1 = addr}; scc_lir_builder_add_instr(ctx, &instr); } break; case SCC_HIR_VALUE_TAG_GET_ELEM_PTR: { - // 将指针运算转换为 LEA + // 1. 获取基址和索引的 LIR 操作数 scc_lir_val_t base = ir_value_to_lir_operand(ctx, value->data.get_elem_ptr.src_addr); - scc_lir_val_t index = SCC_LIR_IMM(0); - if (value->data.get_elem_ptr.index) + scc_lir_val_t index = ir_value_to_lir_operand(ctx, value->data.get_elem_ptr.index); - // 计算元素大小 - scc_hir_type_t *ptr_ty = scc_hir_module_get_type_by_value( - ctx->hir_module, value->data.get_elem_ptr.src_addr); - scc_hir_type_t *elem_ty = nullptr; - if (ptr_ty->tag == SCC_HIR_TYPE_PTR) { - elem_ty = scc_hir_module_get_type(ctx->hir_module, - ptr_ty->data.pointer.base); - } else if (ptr_ty->tag == SCC_HIR_TYPE_ARRAY) { - elem_ty = scc_hir_module_get_type(ctx->hir_module, - ptr_ty->data.array.base); + // 2. 获取元素类型和大小 + scc_hir_type_t *ptr_type = + scc_hir_module_get_type(ctx->hir_module, value->type); + scc_hir_type_t *pointee = NULL; + if (ptr_type->tag == SCC_HIR_TYPE_PTR) { + pointee = scc_hir_module_get_type(ctx->hir_module, + ptr_type->data.pointer.base); + } else if (ptr_type->tag == SCC_HIR_TYPE_ARRAY) { + // 数组名退化为指针,元素类型为数组的元素类型 + pointee = scc_hir_module_get_type(ctx->hir_module, + ptr_type->data.array.base); + } else { + Panic("GET_ELEM_PTR on non-pointer/array type"); } - Assert(elem_ty != nullptr); - int elem_size = 0; - // 简化:仅处理基本类型 - if (elem_ty->tag == SCC_HIR_TYPE_i32 || - elem_ty->tag == SCC_HIR_TYPE_u32) - elem_size = 4; - else if (elem_ty->tag == SCC_HIR_TYPE_i64 || - elem_ty->tag == SCC_HIR_TYPE_u64) - elem_size = 8; - else if (elem_ty->tag == SCC_HIR_TYPE_i8 || - elem_ty->tag == SCC_HIR_TYPE_u8) - elem_size = 1; - else if (elem_ty->tag == SCC_HIR_TYPE_ARRAY) - elem_size = 8; // FIXME ptr size - else - Panic("unsupported element type for getelemptr"); + int elem_size = scc_hir_module_type_size(ctx->hir_module, pointee); - // 构造地址表达式:base + index * elem_size - scc_lir_val_t addr = - SCC_LIR_ADDR(dst_vreg, -1, index.data.reg, elem_size); - // 更简单的做法:使用 LEA 指令,参数为 base 和 index,由后端展开 - scc_lir_instr_t instr = {.op = SCC_LIR_LOAD_ADDR, - .size = SCC_LIR_SIZE_64, - .to = SCC_LIR_VREG(dst_vreg), - .arg0 = base, - .arg1 = index}; - // 实际需要将 index * elem_size 的信息编码,这里简化,假设后端处理 + 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, + .to = SCC_LIR_VREG(dst_vreg), + .arg0 = base, + .arg1 = index, + .metadata.addr.scale = elem_size, + .metadata.addr.offset = 0, + }; scc_lir_builder_add_instr(ctx, &instr); } break; case SCC_HIR_VALUE_TAG_ALLOC: { - // alloca 指令:分配栈空间 + Assert(ty != nullptr); scc_hir_type_t *alloc_ty = scc_hir_module_get_type(ctx->hir_module, ty->data.pointer.base); - // 计算大小和对齐(简化) - int alloc_size = 8; // 默认 - if (alloc_ty->tag == SCC_HIR_TYPE_i32) - alloc_size = 4; + int alloc_size = scc_hir_module_type_size(ctx->hir_module, alloc_ty); scc_lir_instr_t instr = {.op = SCC_LIR_ALLOCA, - .size = SCC_LIR_SIZE_64, + .size = alloc_size, .to = SCC_LIR_VREG(dst_vreg), - .metadata.alloca = {alloc_size, alloc_size}}; + .metadata.alloca = {alloc_size, 1}}; scc_lir_builder_add_instr(ctx, &instr); } break; case SCC_HIR_VALUE_TAG_CALL: { @@ -426,8 +432,90 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value, .arg0 = src}; scc_lir_builder_add_instr(ctx, &instr); } break; + case SCC_HIR_VALUE_TAG_BUILTIN: { + scc_hir_builtin_t *b = &value->data.builtin; + switch (b->tag) { + case SCC_HIR_BUILTIN_TAG_MEMCPY: { + scc_lir_val_t dest = + ir_value_to_lir_operand(ctx, b->func.memcpy.dest); + scc_lir_val_t src = + ir_value_to_lir_operand(ctx, b->func.memcpy.src); + scc_lir_val_t len = + ir_value_to_lir_operand(ctx, b->func.memcpy.size); + scc_lir_instr_t instr = {.op = SCC_LIR_MEMCPY, + .metadata.memcpy = {dest, src, len}}; + scc_lir_builder_add_instr(ctx, &instr); + break; + } + case SCC_HIR_BUILTIN_TAG_MEMSET: { + scc_lir_val_t dest = + ir_value_to_lir_operand(ctx, b->func.memset.dest); + scc_lir_val_t val = + ir_value_to_lir_operand(ctx, b->func.memset.value); + scc_lir_val_t len = + ir_value_to_lir_operand(ctx, b->func.memset.size); + scc_lir_instr_t instr = {.op = SCC_LIR_MEMSET, + .metadata.memset = {dest, val, len}}; + scc_lir_builder_add_instr(ctx, &instr); + break; + } + case SCC_HIR_BUILTIN_TAG_VA_START: { + scc_lir_val_t ap = + ir_value_to_lir_operand(ctx, b->func.va_start.ap); + scc_lir_val_t last = + ir_value_to_lir_operand(ctx, b->func.va_start.last); + scc_lir_instr_t instr = {.op = SCC_LIR_VA_START, + .metadata.va_start = {ap, last}}; + scc_lir_builder_add_instr(ctx, &instr); + break; + } + case SCC_HIR_BUILTIN_TAG_VA_ARG: { + // 需要从类型中获取大小和对齐以及是否为浮点 + scc_hir_type_t *ty = + scc_hir_module_get_type(ctx->hir_module, b->func.va_arg.type); + u8 size = 0; + scc_lir_ext_t ext = SCC_LIR_EXT_NONE; + ir_type_to_lir_size_ext(ty, &size, &ext); + bool is_float = (ext == SCC_LIR_EXT_FLOAT); + scc_lir_val_t ap = ir_value_to_lir_operand(ctx, b->func.va_arg.ap); + scc_lir_instr_t instr = { + .op = SCC_LIR_VA_ARG, + .to = SCC_LIR_VREG(dst_vreg), + .metadata.va_arg = {.ap = ap, + .type_size = size, + .type_align = + size, // 简化,实际应查询 ABI 对齐 + .is_float = is_float, + .to = SCC_LIR_VREG(dst_vreg)}}; + scc_lir_builder_add_instr(ctx, &instr); + break; + } + case SCC_HIR_BUILTIN_TAG_VA_END: { + scc_lir_val_t ap = ir_value_to_lir_operand(ctx, b->func.va_end.ap); + scc_lir_instr_t instr = {.op = SCC_LIR_VA_END, + .metadata.va_end = {ap}}; + scc_lir_builder_add_instr(ctx, &instr); + break; + } + case SCC_HIR_BUILTIN_TAG_VA_COPY: { + scc_lir_val_t dest = + ir_value_to_lir_operand(ctx, b->func.va_copy.dest); + scc_lir_val_t src = + ir_value_to_lir_operand(ctx, b->func.va_copy.src); + scc_lir_instr_t instr = {.op = SCC_LIR_VA_COPY, + .metadata.va_copy = {dest, src}}; + scc_lir_builder_add_instr(ctx, &instr); + break; + } + default: + TODO(); + } + } break; + case SCC_HIR_VALUE_TAG_FUNC_ARG_REF: + case SCC_HIR_VALUE_TAG_BLOCK_ARG_REF: + break; default: - // 不生成指令的节点(如 CONST_INT, FUNC_ARG_REF)不会调用本函数 + Panic("unsupported opcode %d", value->tag); break; } } diff --git a/libs/ir/lir/src/scc_lir_dump.c b/libs/ir/lir/src/scc_lir_dump.c index 2d2c6e4..67af87d 100644 --- a/libs/ir/lir/src/scc_lir_dump.c +++ b/libs/ir/lir/src/scc_lir_dump.c @@ -16,8 +16,8 @@ static const char *op_to_string(scc_lir_op_t op) { return "load.addr"; case SCC_LIR_STORE: return "store"; - case SCC_LIR_STORE_ADDR: - return "store.addr"; + // case SCC_LIR_STORE_ADDR: + // return "store.addr"; case SCC_LIR_ADD: return "add"; case SCC_LIR_SUB: @@ -86,6 +86,11 @@ static const char *op_to_string(scc_lir_op_t op) { return "va_copy"; case SCC_LIR_ALLOCA: return "alloca"; + + case SCC_LIR_MEMCPY: + return "memcpy"; + case SCC_LIR_MEMSET: + return "memset"; case SCC_LIR_NOP: return "nop"; default: @@ -160,29 +165,6 @@ static void dump_operand(scc_lir_dump_ctx_t *ctx, const scc_lir_val_t *op) { scc_tree_dump_append_fmt(td, "@%s", op->data.symbol ? op->data.symbol : ""); break; - case SCC_LIR_INSTR_KIND_MEM: { - const scc_lir_addr_t *addr = &op->data.addr; - scc_tree_dump_append(td, "["); - if (addr->base != -1) { - scc_tree_dump_append_fmt(td, "%%%d", addr->base); - } - if (addr->index != -1) { - scc_tree_dump_append_fmt(td, " + %%%d * %d", addr->index, - addr->scale); - } - if (addr->offset != 0) { - if (addr->offset > 0) - scc_tree_dump_append_fmt(td, " + %lld", - (long long)addr->offset); - else - scc_tree_dump_append_fmt(td, " - %lld", - -(long long)addr->offset); - } - if (addr->base == -1 && addr->index == -1 && addr->offset == 0) - scc_tree_dump_append(td, "0"); - scc_tree_dump_append(td, "]"); - break; - } default: scc_tree_dump_append(td, ""); } @@ -199,6 +181,8 @@ static void dump_size_ext(scc_lir_dump_ctx_t *ctx, u8 size, scc_lir_ext_t ext) { size_str = "32"; else if (size == SCC_LIR_SIZE_64) size_str = "64"; + else + size_str = "sz(?)"; const char *ext_str = ""; if (ext == SCC_LIR_EXT_SEXT) @@ -229,31 +213,40 @@ void scc_lir_dump_ins(scc_lir_dump_ctx_t *ctx, const scc_lir_instr_t *ins) { switch (ins->op) { case SCC_LIR_MOV: case SCC_LIR_LOAD: - case SCC_LIR_LOAD_ADDR: dump_operand(ctx, &ins->to); scc_tree_dump_append(td, " <- "); dump_operand(ctx, &ins->arg0); break; + case SCC_LIR_LOAD_ADDR: + // base + index * scale + offset + dump_operand(ctx, &ins->to); + scc_tree_dump_append(td, " <- ("); + dump_operand(ctx, &ins->arg0); // base + scc_tree_dump_append(td, " + "); + dump_operand(ctx, &ins->arg1); // index + scc_tree_dump_append_fmt(td, " * %d + %lld)", ins->metadata.addr.scale, + ins->metadata.addr.offset); + break; case SCC_LIR_NEG: case SCC_LIR_NOT: case SCC_LIR_FNEG: case SCC_LIR_FCVT: - case SCC_LIR_ALLOCA: dump_operand(ctx, &ins->to); - if (ins->op != SCC_LIR_ALLOCA) { - scc_tree_dump_append(td, ", "); - dump_operand(ctx, &ins->arg0); - // alloca 额外信息在 metadata 中,但通常只关注 to - } + scc_tree_dump_append(td, ", "); + dump_operand(ctx, &ins->arg0); 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); + dump_operand(ctx, &ins->to); + break; + // case SCC_LIR_STORE_ADDR: case SCC_LIR_STORE: - case SCC_LIR_STORE_ADDR: dump_operand(ctx, &ins->arg0); scc_tree_dump_append(td, " -> "); dump_operand(ctx, &ins->arg1); break; - case SCC_LIR_ADD: case SCC_LIR_SUB: case SCC_LIR_MUL: @@ -277,7 +270,6 @@ void scc_lir_dump_ins(scc_lir_dump_ctx_t *ctx, const scc_lir_instr_t *ins) { scc_tree_dump_append(td, ", "); dump_operand(ctx, &ins->arg1); break; - case SCC_LIR_CMP: dump_operand(ctx, &ins->to); scc_tree_dump_append_fmt(td, ", %s, ", @@ -286,22 +278,18 @@ void scc_lir_dump_ins(scc_lir_dump_ctx_t *ctx, const scc_lir_instr_t *ins) { scc_tree_dump_append(td, ", "); dump_operand(ctx, &ins->arg1); break; - case SCC_LIR_BR: dump_operand(ctx, &ins->arg0); scc_tree_dump_append_fmt(td, ", BB#%zu, BB#%zu", ins->metadata.br.true_target, ins->metadata.br.false_target); break; - case SCC_LIR_JMP: scc_tree_dump_append_fmt(td, "#BB%d", ins->metadata.jmp_target); break; - case SCC_LIR_JMP_INDIRECT: dump_operand(ctx, &ins->arg0); break; - case SCC_LIR_CALL: { const struct scc_lir_call *c = &ins->metadata.call; if (c->ret_vreg.kind != SCC_LIR_INSTR_KIND_NONE) { @@ -317,9 +305,7 @@ void scc_lir_dump_ins(scc_lir_dump_ctx_t *ctx, const scc_lir_instr_t *ins) { } scc_tree_dump_append_fmt(td, ") clobber=0x%llx", (unsigned long long)c->clobber_mask); - break; - } - + } break; case SCC_LIR_CALL_INDIRECT: { const struct scc_lir_call_indirect *c = &ins->metadata.call_indirect; if (c->ret_vreg.kind != SCC_LIR_INSTR_KIND_NONE) { @@ -336,15 +322,12 @@ void scc_lir_dump_ins(scc_lir_dump_ctx_t *ctx, const scc_lir_instr_t *ins) { } scc_tree_dump_append_fmt(td, ") clobber=0x%llx", (unsigned long long)c->clobber_mask); - break; - } - + } break; case SCC_LIR_RET: if (ins->metadata.ret_val.kind != SCC_LIR_INSTR_KIND_NONE) { dump_operand(ctx, &ins->metadata.ret_val); } break; - case SCC_LIR_PARALLEL_COPY: { const struct scc_lir_parallel_copy *pc = &ins->metadata.parallel_copy; scc_tree_dump_append(td, "["); @@ -358,13 +341,11 @@ void scc_lir_dump_ins(scc_lir_dump_ctx_t *ctx, const scc_lir_instr_t *ins) { scc_tree_dump_append(td, "]"); break; } - case SCC_LIR_VA_START: dump_operand(ctx, &ins->metadata.va_start.ap); scc_tree_dump_append(td, ", "); dump_operand(ctx, &ins->metadata.va_start.last); break; - case SCC_LIR_VA_ARG: dump_operand(ctx, &ins->metadata.va_arg.to); scc_tree_dump_append(td, " = va_arg "); @@ -373,17 +354,28 @@ void scc_lir_dump_ins(scc_lir_dump_ctx_t *ctx, const scc_lir_instr_t *ins) { td, ", size=%u, align=%u, float=%d", ins->metadata.va_arg.type_size, ins->metadata.va_arg.type_align, ins->metadata.va_arg.is_float); break; - case SCC_LIR_VA_END: dump_operand(ctx, &ins->metadata.va_end.ap); break; - case SCC_LIR_VA_COPY: dump_operand(ctx, &ins->metadata.va_copy.dest); scc_tree_dump_append(td, ", "); dump_operand(ctx, &ins->metadata.va_copy.src); break; - + case SCC_LIR_MEMCPY: + dump_operand(ctx, &ins->metadata.memcpy.dest); + scc_tree_dump_append(td, ", "); + dump_operand(ctx, &ins->metadata.memcpy.src); + scc_tree_dump_append(td, ", "); + dump_operand(ctx, &ins->metadata.memcpy.size); + break; + case SCC_LIR_MEMSET: + dump_operand(ctx, &ins->metadata.memset.dest); + scc_tree_dump_append(td, ", "); + dump_operand(ctx, &ins->metadata.memset.value); + scc_tree_dump_append(td, ", "); + dump_operand(ctx, &ins->metadata.memset.size); + break; case SCC_LIR_NOP: break; } @@ -451,7 +443,12 @@ void scc_lir_dump_module(scc_lir_dump_ctx_t *ctx) { &scc_vec_at(ctx->lir_module->cfg_module.symbols, i); scc_tree_dump_begin_line(ctx->dump_ctx); scc_tree_dump_node(ctx->dump_ctx, "symbol"); + scc_lir_symbol_meta_t *meta = SCC_LIR_SYMBOL_META(sym); scc_tree_dump_append_fmt(ctx->dump_ctx, " %s", sym->name); + if (sym->kind == SCC_CFG_SYMBOL_KIND_DATA) { + scc_tree_dump_append_fmt(ctx->dump_ctx, "(size=%zu)", + meta->data.size); + } } scc_vec_foreach(ctx->lir_module->cfg_module.funcs, i) { if (i == 0) diff --git a/libs/ir/mir/include/arch/scc_x86_isel.h b/libs/ir/mir/include/arch/scc_x86_isel.h index 4fea7e1..9a2d63e 100644 --- a/libs/ir/mir/include/arch/scc_x86_isel.h +++ b/libs/ir/mir/include/arch/scc_x86_isel.h @@ -19,8 +19,12 @@ void scc_isel_x86_64(scc_mir_module_t *mir_module, scc_x86_64_isel_t *isel); // Utils -void scc_x86_emit_move(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst, +void scc_x86_emit_move(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst_reg, scc_x86_operand_value_t src, u8 size); +void scc_x86_emit_load(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst, + scc_x86_operand_value_t src, u8 size); +void scc_x86_emit_store(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst, + scc_x86_operand_value_t src, u8 size); scc_x86_operand_value_t scc_x86_lir_val_to_mir_op(scc_x86_64_isel_t *isel, const scc_lir_val_t *val); static inline void emit_direct_call(scc_x86_64_isel_t *isel, @@ -52,16 +56,18 @@ static inline void emit_ret(scc_x86_64_isel_t *isel) { scc_vec_push((isel)->instrs, instr); \ } while (0) -#define add_instr_1(isel, iform, arg1) \ +#define add_instr_1(isel, iform, arg1, _size) \ do { \ scc_mir_x86_instr_t instr; \ + (arg1).size = (_size); \ scc_mir_x86_instr_1(&instr, (iform), (arg1), (isel)->pos); \ scc_vec_push((isel)->instrs, instr); \ } while (0) -#define add_instr_2(isel, iform, arg1, arg2) \ +#define add_instr_2(isel, iform, arg1, arg2, _size) \ do { \ scc_mir_x86_instr_t instr; \ + (arg1).size = (_size); \ scc_mir_x86_instr_2(&instr, (iform), (arg1), (arg2), (isel)->pos); \ scc_vec_push((isel)->instrs, instr); \ } while (0) diff --git a/libs/ir/mir/include/arch/scc_x86_mir.h b/libs/ir/mir/include/arch/scc_x86_mir.h index ebc3e8a..0de45dc 100644 --- a/libs/ir/mir/include/arch/scc_x86_mir.h +++ b/libs/ir/mir/include/arch/scc_x86_mir.h @@ -9,8 +9,11 @@ #include typedef struct { - int opcode; - uint8_t num_operands; + union { + int opcode; + scc_x86_iform_t iform; + }; + u8 num_operands; scc_x86_operand_value_t operands[6]; scc_pos_t src_loc; } scc_x86_instr_t; @@ -29,13 +32,17 @@ typedef SCC_VEC(scc_mir_x86_instr_t) scc_mir_x86_instr_vec_t; #define SCC_MIR_X86_BBLOCK_INSTRS_C(bb) \ ((const scc_mir_x86_instr_vec_t *)&bb->values) -// ── vreg 编码 ────────────────────────────────────────────────────────── -static inline bool scc_x86_op_is_vreg(const scc_x86_operand_value_t *op) { - return op->kind == SCC_X86_OPR_REG && - (int)op->reg >= (int)SCC_X86_REG_COUNT; +static inline cbool scc_x86_reg_is_vreg(scc_x86_reg_t reg) { + return reg >= SCC_X86_REG_COUNT; +} +static inline cbool scc_x86_op_is_vreg(const scc_x86_operand_value_t *op) { + return op->kind == SCC_X86_OPR_REG && scc_x86_reg_is_vreg(op->reg); +} +static inline int scc_x86_reg_get_vreg(scc_x86_reg_t reg) { + return (int)reg - (int)SCC_X86_REG_COUNT; } static inline int scc_x86_op_get_vreg(const scc_x86_operand_value_t *op) { - return (int)op->reg - (int)SCC_X86_REG_COUNT; + return scc_x86_reg_get_vreg(op->reg); } static inline void scc_x86_op_set_preg(scc_x86_operand_value_t *op, scc_x86_reg_t preg) { @@ -53,6 +60,7 @@ static inline scc_x86_operand_value_t scc_x86_op_slot(int slot_id) { o.mem.disp.displacement_bits = 0; return o; } + static inline bool scc_x86_op_is_slot(const scc_x86_operand_value_t *op) { return op->kind == SCC_X86_OPR_MEM && op->mem.base == SCC_X86_REG_INVALID; } diff --git a/libs/ir/mir/include/core_pass/scc_reg_alloc.h b/libs/ir/mir/include/core_pass/scc_reg_alloc.h index f2e2b79..abb9657 100644 --- a/libs/ir/mir/include/core_pass/scc_reg_alloc.h +++ b/libs/ir/mir/include/core_pass/scc_reg_alloc.h @@ -9,6 +9,12 @@ typedef enum { SCC_REG_ALLOC_OP_ACCESS_READWRITE = 2, } scc_reg_op_access_t; +typedef struct { + const scc_mir_instr_t *instr; + int op_idx; + int op_sub_idx; +} scc_reg_alloc_iter_t; + // 后端回调表 —— 框架通过回调获取/修改指令,不感知具体布局 typedef struct scc_reg_alloc_op { // ── 寄存器池 ── @@ -18,25 +24,21 @@ typedef struct scc_reg_alloc_op { void (*clean_mark_regs)(void *ctx); // ── 指令信息 ── - int (*instr_opcode)(const void *instr); - int (*instr_num_operands)(const void *instr); - bool (*op_is_vreg)(const void *instr, int idx); - int (*op_get_vreg)(const void *instr, int idx); - void (*op_set_preg)(void *instr, int idx, int preg); - void (*op_set_slot)(void *instr, int idx, int slot); + scc_reg_alloc_iter_t iter; + void (*alloc_iter_begin)(scc_reg_alloc_iter_t *iter); + cbool (*alloc_iter_next)(scc_reg_alloc_iter_t *iter, int *out_vreg, + int *out_size, scc_reg_op_access_t *out_access); + void (*alloc_iter_replace_preg)(scc_reg_alloc_iter_t *iter, int preg); + void (*alloc_iter_replace_slot)(scc_reg_alloc_iter_t *iter, int slot); + void (*alloc_iter_end)(scc_reg_alloc_iter_t *iter); + // 读写属性与隐式寄存器 - scc_reg_op_access_t (*get_operand_access)(void *ctx, int opcode, - int op_idx); void (*get_implicit_regs)(void *ctx, int opcode, const int **out_uses, const int **out_defs); - // ── 伪指令处理 ── - bool (*is_pseudo)(const void *instr); - void (*handle_pseudo)(scc_mir_func_t *func, void *instr, void *out); - // ── 溢出/重载(写入 out 向量) ── - void (*emit_spill)(void *out, int preg, int slot); - void (*emit_reload)(void *out, int preg, int slot); + void (*emit_spill)(void *out, int preg, int slot, int size); + void (*emit_reload)(void *out, int preg, int slot, int size); void (*emit_copy)(void *out, int dst_preg, int src_preg, int size); } scc_reg_alloc_op_t; diff --git a/libs/ir/mir/include/scc_mir_module.h b/libs/ir/mir/include/scc_mir_module.h index 6b663d8..e5fa3eb 100644 --- a/libs/ir/mir/include/scc_mir_module.h +++ b/libs/ir/mir/include/scc_mir_module.h @@ -5,10 +5,8 @@ #include typedef SCC_VEC(char) scc_mir_instr_vec_t; - -typedef struct { - -} scc_mir_symbol_t; +typedef scc_lir_symbol_meta_t scc_mir_symbol_meta_t; +#define SCC_MIR_SYMBOL_META(symbol) ((scc_mir_symbol_meta_t *)(symbol)->meta) typedef scc_lir_symbol_meta_vec_t scc_mir_symbol_meta_vec_t; typedef SCC_VEC(scc_mir_func_meta_t *) scc_mir_func_meta_vec_t; diff --git a/libs/ir/mir/src/arch/scc_x86_isel.c b/libs/ir/mir/src/arch/scc_x86_isel.c index 3de6bc8..02b7a07 100644 --- a/libs/ir/mir/src/arch/scc_x86_isel.c +++ b/libs/ir/mir/src/arch/scc_x86_isel.c @@ -9,7 +9,16 @@ static const char *preg_name(int preg_id) { return scc_x86_reg_table[preg_id].display_str; } -void scc_x86_instr_dump(scc_tree_dump_t *td, const scc_mir_x86_instr_t *instr) { +static inline void scc_x86_dump_reg(scc_tree_dump_t *td, + const scc_x86_reg_t reg) { + if (scc_x86_reg_is_vreg(reg)) + scc_tree_dump_append_fmt(td, "%%%d", scc_x86_reg_get_vreg(reg)); + else + scc_tree_dump_append_fmt(td, "$%s", preg_name(reg)); +} + +void scc_x86_instr_dump(scc_tree_dump_t *td, const scc_mir_func_t *func, + const scc_mir_x86_instr_t *instr) { if (instr->x86_instr.opcode >= SCC_X86_IFORM_COUNT || instr->x86_instr.opcode < 0) { scc_tree_dump_append_fmt(td, " ???"); @@ -26,24 +35,43 @@ void scc_x86_instr_dump(scc_tree_dump_t *td, const scc_mir_x86_instr_t *instr) { const scc_x86_operand_value_t *op = &instr->x86_instr.operands[i]; switch (op->kind) { case SCC_X86_OPR_REG: - if (scc_x86_op_is_vreg(op)) - scc_tree_dump_append_fmt(td, "%%%d", scc_x86_op_get_vreg(op)); - else - scc_tree_dump_append_fmt(td, "$%s", preg_name(op->reg)); + scc_x86_dump_reg(td, op->reg); break; case SCC_X86_OPR_IMM: scc_tree_dump_append_fmt(td, "%ld", op->imm0); break; case SCC_X86_OPR_MEM: - if (scc_x86_op_is_slot(op)) - scc_tree_dump_append_fmt(td, "[slot:%d]", - scc_x86_op_slot_id(op)); - else - scc_tree_dump_append_fmt( - td, "[sp %c %llu]", - op->mem.disp.displacement >= 0 ? '+' : '-', - op->mem.disp.displacement < 0 ? -op->mem.disp.displacement - : op->mem.disp.displacement); + if (scc_x86_op_is_slot(op)) { + int slot_id = scc_x86_op_slot_id(op); + scc_mir_stack_slot_t *slot = scc_mir_unsafe_slot(func, slot_id); + if (slot == nullptr) { + scc_tree_dump_append_fmt(td, "[slot:%d]", slot_id); + } else { + scc_tree_dump_append_fmt(td, "[slot:%d(of=%d,sz=%d,al=%d)]", + slot_id, slot->offset, slot->size, + slot->alignment); + } + } else { + scc_tree_dump_append(td, "("); + scc_x86_dump_reg(td, op->mem.base); + if (op->mem.index != SCC_X86_REG_INVALID) { + scc_tree_dump_append(td, "["); + scc_x86_dump_reg(td, op->mem.index); + scc_tree_dump_append(td, "]"); + } + if (op->mem.scale != 1) { + scc_tree_dump_append_fmt(td, "(x%d)", op->mem.scale); + } + if (op->mem.disp.displacement != 0) { + scc_tree_dump_append_fmt( + td, " %c %llu", + op->mem.disp.displacement >= 0 ? '+' : '-', + op->mem.disp.displacement < 0 + ? -op->mem.disp.displacement + : op->mem.disp.displacement); + } + scc_tree_dump_append(td, ")"); + } break; case SCC_X86_OPR_RELBR: scc_tree_dump_append(td, ""); @@ -62,8 +90,10 @@ void scc_x86_instr_dump(scc_tree_dump_t *td, const scc_mir_x86_instr_t *instr) { } break; default: + scc_tree_dump_append(td, ""); break; } + scc_tree_dump_append_fmt(td, "(%zu)", op->size); } } @@ -92,79 +122,54 @@ scc_x86_operand_value_t scc_x86_lir_val_to_mir_op(scc_x86_64_isel_t *isel, op = scc_x86_op_imm(*(i64 *)&val->data.fimm); break; case SCC_LIR_INSTR_KIND_SYMBOL: - // 默认作为绝对地址立即数(后续可优化为 RIP 相对) - op = scc_x86_op_reloc_global_imm(val->data.symbol, 0); + op = scc_x86_op_reloc_global_relrip(val->data.symbol, 0); break; case SCC_LIR_INSTR_KIND_ARG: Assert(isel->abi_lowering.lower_param); isel->abi_lowering.lower_param(isel, val, &op); break; default: - UNREACHABLE(); + Panic("unsupported lir instr kind %d", val->kind); + break; } return op; } +static scc_x86_operand_value_t build_mem_op(scc_x86_64_isel_t *isel, + scc_x86_operand_value_t base, + scc_x86_operand_value_t index, + int scale, i64 offset) { + (void)isel; + scc_x86_operand_value_t mem_op; + mem_op.kind = SCC_X86_OPR_MEM; + // base 必须为寄存器 + Assert(base.kind == SCC_X86_OPR_REG); + mem_op.mem.base = base.reg; + // index 可选 + if (index.kind == SCC_X86_OPR_REG) { + mem_op.mem.index = index.reg; + mem_op.mem.scale = scale; + } else { + mem_op.mem.index = SCC_X86_REG_INVALID; + mem_op.mem.scale = 1; + } + mem_op.mem.disp.displacement = offset; + mem_op.mem.disp.displacement_bits = 0; + return mem_op; +} + // 虚拟临时寄存器分配(简单递增) static scc_x86_operand_value_t new_vreg_temp(scc_x86_64_isel_t *isel) { return scc_x86_op_vreg(scc_mir_alloc_vreg(isel->func)); } -void scc_x86_emit_move(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst, - scc_x86_operand_value_t src, u8 size) { - scc_x86_operand_kind_t dst_kind = dst.kind; - if (dst_kind == SCC_X86_OPR_RELOC) { - dst_kind = dst.reloc.kind; - } - scc_x86_operand_kind_t src_kind = src.kind; - if (src_kind == SCC_X86_OPR_RELOC) { - src_kind = src.reloc.kind; - } - - if (dst_kind == SCC_X86_OPR_REG) { - if (src_kind == SCC_X86_OPR_REG) { - add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_GPRV_8B, dst, src); - } else if (src_kind == SCC_X86_OPR_IMM) { - add_instr_2(isel, - (size == 8) ? SCC_X86_IFORM_MOV_GPRV_IMMZ - : SCC_X86_IFORM_MOV_GPRV_IMMV, - dst, src); - } else if (src_kind == SCC_X86_OPR_IMM && src.imm0 == 0) { - // 特殊:符号作为立即数地址 - add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_IMMZ, dst, src); - } else if (src_kind == SCC_X86_OPR_MEM) { - add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_MEMV, dst, src); - } else { - UNREACHABLE(); - } - } else if (dst_kind == SCC_X86_OPR_MEM) { - if (src_kind == SCC_X86_OPR_REG) { - add_instr_2(isel, SCC_X86_IFORM_MOV_MEMV_GPRV, dst, src); - } else if (src_kind == SCC_X86_OPR_IMM) { - add_instr_2(isel, SCC_X86_IFORM_MOV_MEMV_IMMZ, dst, src); - } else if (src_kind == SCC_X86_OPR_IMM) { - scc_x86_operand_value_t temp = new_vreg_temp(isel); - add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_IMMZ, temp, src); - add_instr_2(isel, SCC_X86_IFORM_MOV_MEMV_GPRV, dst, temp); - } else if (src_kind == SCC_X86_OPR_MEM) { - scc_x86_operand_value_t temp = new_vreg_temp(isel); - scc_x86_emit_move(isel, temp, src, size); - scc_x86_emit_move(isel, dst, temp, size); - } else { - UNREACHABLE(); - } - } else { - UNREACHABLE(); - } -} - static void emit_compare(scc_x86_64_isel_t *isel, scc_x86_operand_value_t op0, scc_x86_operand_value_t op1, u8 size) { (void)size; if (scc_x86_op_is_vreg(&op0) && op1.kind == SCC_X86_OPR_IMM) { - add_instr_2(isel, SCC_X86_IFORM_CMP_GPRV_IMMZ, op0, op1); + add_instr_2(isel, SCC_X86_IFORM_CMP_GPRV_IMMZ, op0, op1, size); } else if (scc_x86_op_is_vreg(&op0) && scc_x86_op_is_vreg(&op1)) { - add_instr_2(isel, SCC_X86_IFORM_CMP_GPRV_GPRV_3B, op0, op1); + add_instr_2(isel, SCC_X86_IFORM_CMP_GPRV_GPRV_3B, op0, op1, size); } else { UNREACHABLE(); } @@ -213,6 +218,9 @@ static void emit_binary_op(scc_x86_64_isel_t *isel, scc_lir_op_t op, scc_x86_operand_value_t src1, u8 size) { (void)size; emit_copy_if_needed(isel, dst, src0, size); + dst.size = size; + src0.size = size; + src1.size = size; bool is_imm = (src1.kind == SCC_X86_OPR_IMM); scc_x86_iform_t iform; @@ -240,7 +248,155 @@ static void emit_binary_op(scc_x86_64_isel_t *isel, scc_lir_op_t op, default: UNREACHABLE(); } - add_instr_2(isel, iform, dst, src1); + add_instr_2(isel, iform, dst, src1, size); +} + +void scc_x86_emit_move(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst_reg, + scc_x86_operand_value_t src, u8 size) { + if (size == 0) { + size = dst_reg.size; + } + if (dst_reg.size != src.size) { + LOG_WARN("Mismatched register sizes for move %d != %d", dst_reg.size, + src.size); + } + Assert(dst_reg.kind == SCC_X86_OPR_REG); + if (src.kind == SCC_X86_OPR_REG) { + add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_GPRV_8B, dst_reg, src, size); + } else if (src.kind == SCC_X86_OPR_IMM) { + add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_IMMV, dst_reg, src, size); + } else if (src.kind == SCC_X86_OPR_MEM || + (src.kind == SCC_X86_OPR_RELOC && + src.reloc.target == SCC_X86_RELOC_TARGET_SYMBOL)) { + add_instr_2(isel, SCC_X86_IFORM_LEA_GPRV_AGEN, dst_reg, src, size); + } else { + Panic("emit_move: unsupported src kind %d", src.kind); + } +} + +void scc_x86_emit_load(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst, + scc_x86_operand_value_t src, u8 size) { + if (size == 0) { + size = dst.size; + } + if (dst.size != src.size) { + LOG_WARN("Mismatched register sizes for store %d != %d", dst.size, + src.size); + } + if (dst.kind != SCC_X86_OPR_REG) { + scc_x86_operand_value_t tmp_reg = new_vreg_temp(isel); + scc_x86_emit_move(isel, tmp_reg, dst, size); + dst = tmp_reg; + } + scc_x86_operand_value_t mem_op; + if (src.kind == SCC_X86_OPR_REG) { + // 地址在寄存器中 -> 构造 [reg] + mem_op = (scc_x86_operand_value_t){ + .kind = SCC_X86_OPR_MEM, + .mem = {.base = src.reg, + .index = SCC_X86_REG_INVALID, + .scale = 1, + .disp = {.displacement = 0, .displacement_bits = size * 8}}, + }; + } else if (src.kind == SCC_X86_OPR_MEM) { + mem_op = src; + } else { + Panic("emit_load: src must be REG or MEM"); + } + add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_MEMV, dst, mem_op, size); +} + +void scc_x86_emit_store(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst, + scc_x86_operand_value_t src, u8 size) { + if (size == 0) { + size = dst.size; + } + if (dst.size != src.size) { + LOG_WARN("Mismatched register sizes for store %d != %d", dst.size, + src.size); + } + if (src.kind != SCC_X86_OPR_REG) { + scc_x86_operand_value_t tmp_reg = new_vreg_temp(isel); + scc_x86_emit_move(isel, tmp_reg, src, size); + src = tmp_reg; + } + scc_x86_operand_value_t mem_op; + if (dst.kind == SCC_X86_OPR_REG) { + mem_op = (scc_x86_operand_value_t){ + .kind = SCC_X86_OPR_MEM, + .mem = {.base = dst.reg, + .index = SCC_X86_REG_INVALID, + .scale = 1, + .disp = {.displacement = 0, .displacement_bits = 0}}}; + } else if (dst.kind == SCC_X86_OPR_MEM) { + mem_op = dst; + } else { + Panic("emit_store: dst_addr must be REG or MEM"); + } + mem_op.size = size; + src.size = size; + add_instr_2(isel, SCC_X86_IFORM_MOV_MEMV_GPRV, mem_op, src, size); +} + +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; + // 前置断言:dst 必须是寄存器 + Assert(dst.kind == SCC_X86_OPR_REG); + // scale 必须是 1,2,4,8 之一 + Assert(scale == 1 || scale == 2 || scale == 4 || scale == 8); + + // ---- 处理 base ---- + scc_x86_operand_value_t base_reg = base; + if (base.kind != SCC_X86_OPR_REG) { + base_reg = new_vreg_temp(isel); + scc_x86_emit_move(isel, base_reg, base, 8); + } + + // ---- 处理 index * scale ---- + scc_x86_operand_value_t scaled_index = index; + Assert(index.kind != SCC_X86_OPR_NONE); + // 确保 index 在寄存器中 + if (index.kind != SCC_X86_OPR_REG) { + scc_x86_operand_value_t index_tmp = new_vreg_temp(isel); + scc_x86_emit_move(isel, index_tmp, index, 8); + index = index_tmp; + } + + // ---- 计算 base + scaled_index ---- + scc_x86_operand_value_t sum = base_reg; + if (base_reg.kind == SCC_X86_OPR_REG && + scaled_index.kind == SCC_X86_OPR_REG) { + if (dst.reg != base_reg.reg) { + scc_x86_emit_move(isel, dst, base_reg, 8); + sum = dst; + } + add_instr_2(isel, SCC_X86_IFORM_ADD_GPRV_GPRV_03, sum, scaled_index, + size); + } else if (base_reg.kind == SCC_X86_OPR_REG) { + if (dst.reg != base_reg.reg) + scc_x86_emit_move(isel, dst, base_reg, 8); + sum = dst; + } else if (scaled_index.kind == SCC_X86_OPR_REG) { + scc_x86_emit_move(isel, dst, scaled_index, 8); + sum = dst; + } else { + // base 和 index 都无效 => 结果为 0 + scc_x86_emit_move(isel, dst, scc_x86_op_imm(0), 8); + return; + } + + // ---- 加上 offset ---- + if (offset != 0) { + scc_x86_operand_value_t mem_op = build_mem_op( + isel, sum, (scc_x86_operand_value_t){.kind = SCC_X86_OPR_NONE}, 1, + offset); + scc_x86_emit_move(isel, dst, mem_op, 8); + } else if (sum.reg != dst.reg) { + scc_x86_emit_move(isel, dst, sum, 8); + } } static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) { @@ -252,33 +408,31 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) { u8 size = instr->size; switch (instr->op) { - /* ---- 数据移动 ---- */ - case SCC_LIR_MOV: - scc_x86_emit_move(isel, dst, src0, size); - break; + /* ---- 数据移动 ---- */ case SCC_LIR_LOAD: - // TODO check valid - scc_x86_emit_move(isel, dst, src0, size); + // src0 是地址(可能是寄存器或内存操作数),dst 是寄存器 + scc_x86_emit_load(isel, dst, src0, size); break; case SCC_LIR_STORE: - // TODO check valid - scc_x86_emit_move(isel, src1, src0, size); + // src0 是要存储的值(寄存器),src1 是目标地址 + scc_x86_emit_store(isel, src1, src0, size); break; - case SCC_LIR_STORE_ADDR: - TODO(); + case SCC_LIR_MOV: + // 纯粹的寄存器/立即数复制 + scc_x86_emit_move(isel, dst, src0, size); break; case SCC_LIR_LOAD_ADDR: - add_instr_2(isel, SCC_X86_IFORM_LEA_GPRV_AGEN, dst, src0); + // 计算地址,结果放入 dst(寄存器) + emit_load_addr(isel, dst, src0, src1, instr->metadata.addr.scale, + instr->metadata.addr.offset); break; - /* ---- 一元运算 ---- */ case SCC_LIR_NEG: - add_instr_1(isel, SCC_X86_IFORM_NEG_GPRV, dst); + add_instr_1(isel, SCC_X86_IFORM_NEG_GPRV, dst, size); break; case SCC_LIR_NOT: - add_instr_1(isel, SCC_X86_IFORM_NOT_GPRV, dst); + add_instr_1(isel, SCC_X86_IFORM_NOT_GPRV, dst, size); break; - /* ---- 算术/逻辑二元运算 ---- */ case SCC_LIR_ADD: case SCC_LIR_SUB: @@ -295,7 +449,7 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) { scc_x86_emit_move(isel, op, src1, size); src1 = op; } - add_instr_2(isel, SCC_X86_IFORM_IMUL_GPRV_GPRV, dst, src1); + add_instr_2(isel, SCC_X86_IFORM_IMUL_GPRV_GPRV, dst, src1, size); break; case SCC_LIR_SHL: @@ -318,7 +472,7 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) { default: UNREACHABLE(); } - add_instr_2(isel, iform, dst, src1); + add_instr_2(isel, iform, dst, src1, size); } else { scc_x86_operand_value_t cl = scc_x86_op_preg(SCC_X86_REG_CL); scc_x86_emit_move(isel, cl, src1, 1); @@ -336,7 +490,7 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) { default: UNREACHABLE(); } - add_instr_2(isel, iform, dst, cl); + add_instr_2(isel, iform, dst, cl, size); } } break; @@ -361,7 +515,7 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) { (instr->op == SCC_LIR_DIV_S || instr->op == SCC_LIR_REM_S) ? SCC_X86_IFORM_IDIV_GPRV : SCC_X86_IFORM_DIV_GPRV; - add_instr_1(isel, div_if, src1); + add_instr_1(isel, div_if, src1, size); if (instr->op == SCC_LIR_REM_S || instr->op == SCC_LIR_REM_U) scc_x86_emit_move(isel, dst, rdx, size); @@ -372,17 +526,17 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) { /* ---- 比较指令 ---- */ case SCC_LIR_CMP: { if (scc_x86_op_is_vreg(&src0) && src1.kind == SCC_X86_OPR_IMM) - add_instr_2(isel, SCC_X86_IFORM_CMP_GPRV_IMMZ, src0, src1); + add_instr_2(isel, SCC_X86_IFORM_CMP_GPRV_IMMZ, src0, src1, size); else if (scc_x86_op_is_vreg(&src0) && scc_x86_op_is_vreg(&src1)) - add_instr_2(isel, SCC_X86_IFORM_CMP_GPRV_GPRV_3B, src0, src1); + add_instr_2(isel, SCC_X86_IFORM_CMP_GPRV_GPRV_3B, src0, src1, size); else UNREACHABLE(); scc_x86_iform_t setcc = cond_to_setcc(instr->metadata.cond); - add_instr_1(isel, setcc, dst); + add_instr_1(isel, setcc, dst, size); if (size > 1) { scc_x86_operand_value_t one = scc_x86_op_imm(1); - add_instr_2(isel, SCC_X86_IFORM_AND_GPRV_IMMZ, dst, one); + add_instr_2(isel, SCC_X86_IFORM_AND_GPRV_IMMZ, dst, one, size); } } break; @@ -393,15 +547,15 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) { scc_x86_operand_value_t false_bb = scc_x86_op_reloc_block(instr->metadata.br.false_target, 0); - add_instr_2(isel, 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); + add_instr_2(isel, SCC_X86_IFORM_TEST_GPRV_GPRV, src0, src0, size); + add_instr_1(isel, SCC_X86_IFORM_JNZ_RELBRZ, true_bb, size); + add_instr_1(isel, SCC_X86_IFORM_JMP_RELBRZ, false_bb, size); } break; case SCC_LIR_JMP: { scc_x86_operand_value_t jmp_bb = scc_x86_op_reloc_block(instr->metadata.jmp_target, 0); - add_instr_1(isel, SCC_X86_IFORM_JMP_RELBRZ, jmp_bb); + add_instr_1(isel, SCC_X86_IFORM_JMP_RELBRZ, jmp_bb, size); } break; /* ---- 栈分配 ---- */ @@ -412,10 +566,14 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) { 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->size; - x86instr.instr.data.alloc.align = 0; + x86instr.instr.data.alloc.size = instr->metadata.alloca.size_bytes; + x86instr.instr.data.alloc.align = instr->metadata.alloca.align_bytes; scc_vec_push(isel->instrs, x86instr); - scc_mir_vreg_map2slot(isel->func, instr->to.data.reg, instr->size, 0); + 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 + : 8); break; } @@ -429,12 +587,43 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) { Assert(isel->abi_lowering.lower_call); isel->abi_lowering.lower_call(isel, instr); } break; + case SCC_LIR_CALL_INDIRECT: { + TODO(); + // 假设函数指针的 LIR 值在某个 vreg 中 + // scc_x86_operand_value_t func_ptr_op = + // scc_x86_lir_val_to_mir_op(isel, &func_ptr_val); + // scc_x86_operand_value_t temp_reg = new_vreg_temp(isel); + // scc_x86_emit_lea(isel, temp_reg, func_ptr_op); // 确保得到地址 + // emit_indirect_call(isel, temp_reg); + } break; case SCC_LIR_RET: { Assert(isel->abi_lowering.lower_ret); isel->abi_lowering.lower_ret(isel, instr); } break; + + case SCC_LIR_MEMCPY: { + scc_lir_val_t dest_val = instr->metadata.memcpy.dest; + scc_lir_val_t src_val = instr->metadata.memcpy.src; + + // 将 dest 的地址放入 RDI + scc_x86_operand_value_t dest_op = + scc_x86_lir_val_to_mir_op(isel, &dest_val); + scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_RDI), dest_op, 8); + + // 将 src 的地址放入 RSI + scc_x86_operand_value_t src_op = + scc_x86_lir_val_to_mir_op(isel, &src_val); + scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_RSI), src_op, 8); + + // 长度处理保持不变... + scc_x86_operand_value_t len_op = + scc_x86_lir_val_to_mir_op(isel, &instr->metadata.memcpy.size); + scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_RCX), len_op, 8); + + add_instr_0(isel, SCC_X86_IFORM_REP_MOVSB); + } break; default: { - UNREACHABLE(); + Panic("unsupported instruction %d", instr->op); } break; } } diff --git a/libs/ir/mir/src/arch/scc_x86_peephole.c b/libs/ir/mir/src/arch/scc_x86_peephole.c new file mode 100644 index 0000000..7a1c159 --- /dev/null +++ b/libs/ir/mir/src/arch/scc_x86_peephole.c @@ -0,0 +1,161 @@ +#include +#include + +static bool same_x86_operand(const scc_x86_operand_value_t *a, + const scc_x86_operand_value_t *b) { + if (a->kind != b->kind) + return false; + switch (a->kind) { + case SCC_X86_OPR_REG: + return a->reg == b->reg; + case SCC_X86_OPR_MEM: + return a->mem.base == b->mem.base && a->mem.index == b->mem.index && + a->mem.scale == b->mem.scale && + a->mem.disp.displacement == b->mem.disp.displacement; + case SCC_X86_OPR_IMM: + return a->imm0 == b->imm0; + default: + return false; + } +} + +static bool is_store_to_mem(const scc_mir_x86_instr_t *ins) { + int op = ins->x86_instr.opcode; + return op == SCC_X86_IFORM_MOV_MEMV_GPRV || + op == SCC_X86_IFORM_MOV_MEMV_IMMZ; +} + +static bool is_load_from_mem(const scc_mir_x86_instr_t *ins) { + int op = ins->x86_instr.opcode; + return op == SCC_X86_IFORM_MOV_GPRV_MEMV; +} + +static bool is_reg_reg_move(const scc_mir_x86_instr_t *ins) { + int op = ins->x86_instr.opcode; + return op == SCC_X86_IFORM_MOV_GPRV_GPRV_8B; +} + +void scc_x86_peephole_optimize(scc_mir_module_t *module) { + Assert(module != nullptr); + usize instr_size = module->instr_size; + + // 遍历函数 + scc_vec_foreach(module->cfg_module.funcs, i) { + if (i == 0) + continue; + scc_mir_func_t *func = &scc_vec_at(module->cfg_module.funcs, i); + + // 遍历基本块 + scc_vec_foreach(func->bblocks, j) { + scc_cfg_bblock_id_t bb_id = scc_vec_at(func->bblocks, j); + scc_cfg_bblock_t *bb = + scc_cfg_module_unsafe_get_bblock(&module->cfg_module, bb_id); + Assert(bb != nullptr); + + scc_mir_instr_vec_t *old_vec = SCC_MIR_BBLOCK_VALUES_PTR(bb); + if (scc_vec_size(*old_vec) == 0) + continue; + + size_t old_count = scc_vec_size(*old_vec); + // 构建新向量 + scc_mir_instr_vec_t new_vec; + scc_vec_init(new_vec); + + for (size_t k = 0; k < old_count;) { + if (k + 1 >= old_count) { + // 剩余不足2条,直接复制 + void *ins_ptr = + scc_vec_sized_at_ptr(*old_vec, instr_size, k); + scc_vec_sized_push(new_vec, instr_size, ins_ptr, + instr_size); + k++; + continue; + } + + scc_mir_x86_instr_t *i0 = + (scc_mir_x86_instr_t *)scc_vec_sized_at_ptr(*old_vec, + instr_size, k); + scc_mir_x86_instr_t *i1 = + (scc_mir_x86_instr_t *)scc_vec_sized_at_ptr( + *old_vec, instr_size, k + 1); + + int op0 = i0->x86_instr.opcode; + int op1 = i1->x86_instr.opcode; + + // 模式 A: store reg, mem 后紧跟 load mem, reg (同一 reg 和 mem) + if (is_store_to_mem(i0) && is_load_from_mem(i1) && + i0->x86_instr.num_operands >= 2 && + i1->x86_instr.num_operands >= 2) { + scc_x86_operand_value_t *store_dst = + &i0->x86_instr.operands[0]; // mem + scc_x86_operand_value_t *store_src = + &i0->x86_instr.operands[1]; // reg/imm + scc_x86_operand_value_t *load_dst = + &i1->x86_instr.operands[0]; // reg + scc_x86_operand_value_t *load_src = + &i1->x86_instr.operands[1]; // mem + + if (store_src->kind == SCC_X86_OPR_REG && + load_dst->kind == SCC_X86_OPR_REG && + same_x86_operand(store_dst, load_src) && + store_src->reg == load_dst->reg) { + // 两条指令相互抵消,都跳过 + k += 2; + continue; + } + } + + // 模式 B: load mem, reg 后紧跟 store reg, mem (同一 reg 和 mem) + if (is_load_from_mem(i0) && is_store_to_mem(i1) && + i0->x86_instr.num_operands >= 2 && + i1->x86_instr.num_operands >= 2) { + scc_x86_operand_value_t *load_dst = + &i0->x86_instr.operands[0]; // reg + scc_x86_operand_value_t *load_src = + &i0->x86_instr.operands[1]; // mem + scc_x86_operand_value_t *store_dst = + &i1->x86_instr.operands[0]; // mem + scc_x86_operand_value_t *store_src = + &i1->x86_instr.operands[1]; // reg + + if (store_src->kind == SCC_X86_OPR_REG && + load_dst->kind == SCC_X86_OPR_REG && + same_x86_operand(load_src, store_dst) && + load_dst->reg == store_src->reg) { + k += 2; + continue; + } + } + + // 模式 C: mov r1, r2 后跟 mov r2, r1 + if (is_reg_reg_move(i0) && is_reg_reg_move(i1) && + i0->x86_instr.num_operands >= 2 && + i1->x86_instr.num_operands >= 2) { + scc_x86_operand_value_t *dst0 = &i0->x86_instr.operands[0]; + scc_x86_operand_value_t *src0 = &i0->x86_instr.operands[1]; + scc_x86_operand_value_t *dst1 = &i1->x86_instr.operands[0]; + scc_x86_operand_value_t *src1 = &i1->x86_instr.operands[1]; + + if (dst0->kind == SCC_X86_OPR_REG && + src0->kind == SCC_X86_OPR_REG && + dst1->kind == SCC_X86_OPR_REG && + src1->kind == SCC_X86_OPR_REG && + dst0->reg == src1->reg && src0->reg == dst1->reg) { + // 保留第一条,删除第二条 + scc_vec_sized_push(new_vec, instr_size, i0, instr_size); + k += 2; + continue; + } + } + + // 未匹配,保留当前指令 + scc_vec_sized_push(new_vec, instr_size, i0, instr_size); + k++; + } + + // 替换基本块的指令向量 + scc_vec_free(*old_vec); + *old_vec = new_vec; + } + } +} 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 25c7602..578998e 100644 --- a/libs/ir/mir/src/arch/scc_x86_reg_alloc.c +++ b/libs/ir/mir/src/arch/scc_x86_reg_alloc.c @@ -4,71 +4,29 @@ #include #include -/* ========== 指令访问回调 ========== */ - -static int instr_opcode(const void *instr) { - return ((const scc_mir_x86_instr_t *)instr)->x86_instr.opcode; -} -static int instr_num_operands(const void *instr) { - return ((const scc_mir_x86_instr_t *)instr)->x86_instr.num_operands; -} -static bool op_is_vreg(const void *instr, int idx) { - return scc_x86_op_is_vreg( - &((const scc_mir_x86_instr_t *)instr)->x86_instr.operands[idx]); -} -static int op_get_vreg(const void *instr, int idx) { - return scc_x86_op_get_vreg( - &((const scc_mir_x86_instr_t *)instr)->x86_instr.operands[idx]); -} -static void op_set_preg(void *instr, int idx, int preg) { - scc_x86_op_set_preg( - &((scc_mir_x86_instr_t *)instr)->x86_instr.operands[idx], - (scc_x86_reg_t)preg); -} -static void op_set_slot(void *instr, int idx, int slot) { - ((scc_mir_x86_instr_t *)instr)->x86_instr.operands[idx] = - scc_x86_op_slot(slot); -} - -/* ========== 伪指令处理 ========== */ - -static bool is_pseudo(const void *instr) { - return ((const scc_mir_x86_instr_t *)instr)->x86_instr.opcode < 0; -} - -static void handle_pseudo(scc_mir_func_t *func, void *instr, void *out) { - scc_mir_x86_instr_t *ins = instr; - scc_mir_x86_instr_vec_t *out_vec = out; - if (ins->x86_instr.opcode == SCC_MIR_PSEUDO_ALLOCA) { - // // 指令选择时已分配 slot,直接替换为 slot 操作数 - // if (scc_x86_op_is_vreg(&ins->x86_instr.operands[0])) { - // int vreg = scc_x86_op_get_vreg(&ins->x86_instr.operands[0]); - // int slot = scc_mir_vreg_map2slot(func, vreg, 8, 8); - // ins->x86_instr.operands[0] = scc_x86_op_slot(slot); - // } - // scc_vec_push(*out_vec, *ins); - } else { - scc_vec_push(*out_vec, *ins); - } -} - -/* ========== Spill / Reload / Copy ========== */ - -static void emit_spill(void *out, int preg, int slot) { +static void emit_spill(void *out, int preg, int slot, int size) { scc_mir_x86_instr_vec_t *vec = out; + scc_x86_operand_value_t val_slot = scc_x86_op_slot(slot); + scc_x86_operand_value_t val_preg = scc_x86_op_preg(preg); + val_slot.size = size; + val_preg.size = size; scc_mir_x86_instr_t ins = { .x86_instr.opcode = SCC_X86_IFORM_MOV_MEMV_GPRV, .x86_instr.num_operands = 2, - .x86_instr.operands = {scc_x86_op_slot(slot), scc_x86_op_preg(preg)}}; + .x86_instr.operands = {val_slot, val_preg}, + }; scc_vec_push(*vec, ins); } -static void emit_reload(void *out, int preg, int slot) { +static void emit_reload(void *out, int preg, int slot, int size) { + scc_x86_operand_value_t val_slot = scc_x86_op_slot(slot); + scc_x86_operand_value_t val_preg = scc_x86_op_preg(preg); + val_slot.size = size; + val_preg.size = size; scc_mir_x86_instr_vec_t *vec = out; - scc_mir_x86_instr_t ins = { - .x86_instr.opcode = SCC_X86_IFORM_MOV_GPRV_MEMV, - .x86_instr.num_operands = 2, - .x86_instr.operands = {scc_x86_op_preg(preg), scc_x86_op_slot(slot)}}; + scc_mir_x86_instr_t ins = {.x86_instr.opcode = SCC_X86_IFORM_MOV_GPRV_MEMV, + .x86_instr.num_operands = 2, + .x86_instr.operands = {val_preg, val_slot}}; scc_vec_push(*vec, ins); } @@ -83,11 +41,7 @@ static void emit_copy(void *out, int dst_preg, int src_preg, int size) { scc_vec_push(*vec, ins); } -/* ========== 操作数读写属性 ========== */ - -static scc_reg_op_access_t get_operand_access(void *ctx, int opcode, - int op_idx) { - (void)ctx; +static scc_reg_op_access_t get_operand_access(int opcode, int op_idx) { if (opcode >= 0 && opcode < SCC_X86_IFORM_COUNT) { const scc_x86_iform_info_t *info = &scc_x86_iform_table[opcode]; if (op_idx >= info->num_ops || op_idx < 0) @@ -174,7 +128,111 @@ static void clean_mark_regs(void *ctx) { reg_mask = 0; } -/* ========== 注册全部 x86 回调 ========== */ +static void x86_alloc_iter_begin(scc_reg_alloc_iter_t *iter) { + iter->op_idx = 0; + iter->op_sub_idx = 0; +} + +static cbool x86_alloc_iter_next(scc_reg_alloc_iter_t *iter, int *out_vreg, + int *out_size, + scc_reg_op_access_t *out_access) { + const scc_mir_x86_instr_t *ins = (const scc_mir_x86_instr_t *)iter->instr; + int opcode = ins->x86_instr.opcode; + int num_ops = ins->x86_instr.num_operands; + + while (iter->op_idx < num_ops) { + const scc_x86_operand_value_t *op = + &ins->x86_instr.operands[iter->op_idx]; + scc_reg_op_access_t base_access = + get_operand_access(opcode, iter->op_idx); + + *out_size = op->size; + 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); + *out_access = base_access; + iter->op_sub_idx++; + return true; + } + iter->op_idx++; + iter->op_sub_idx = 0; + continue; + } else if (op->kind == SCC_X86_OPR_MEM) { + const scc_x86_mem_t *mem = &op->mem; + // 子索引 0: 基址寄存器 + if (iter->op_sub_idx == 0) { + if (mem->base != SCC_X86_REG_INVALID && + scc_x86_reg_is_vreg(mem->base)) { + *out_vreg = scc_x86_reg_get_vreg(mem->base); + *out_access = + SCC_REG_ALLOC_OP_ACCESS_READ; // 地址寄存器只读 + iter->op_sub_idx++; + return true; + } + iter->op_sub_idx++; + } + // 子索引 1: 索引寄存器 + if (iter->op_sub_idx == 1) { + if (mem->index != SCC_X86_REG_INVALID && + scc_x86_reg_is_vreg(mem->index)) { + *out_vreg = scc_x86_reg_get_vreg(mem->index); + *out_access = SCC_REG_ALLOC_OP_ACCESS_READ; + iter->op_sub_idx++; + return true; + } + iter->op_sub_idx++; + } + // 没有更多子部分 + iter->op_idx++; + iter->op_sub_idx = 0; + continue; + } + + // 其他操作数类型(立即数、slot 等)直接跳过 + iter->op_idx++; + iter->op_sub_idx = 0; + } + return false; +} + +static void x86_alloc_iter_replace_preg(scc_reg_alloc_iter_t *iter, int preg) { + scc_mir_x86_instr_t *ins = (scc_mir_x86_instr_t *)iter->instr; + int op_idx = iter->op_idx; + int sub_idx = iter->op_sub_idx; + + if (op_idx >= ins->x86_instr.num_operands) + return; + + scc_x86_operand_value_t *op = &ins->x86_instr.operands[op_idx]; + + if (op->kind == SCC_X86_OPR_REG) { + // 普通寄存器操作数 + scc_x86_op_set_preg(op, (scc_x86_reg_t)preg); + } else if (op->kind == SCC_X86_OPR_MEM) { + scc_x86_mem_t *mem = &op->mem; + if (sub_idx == 1) { + // 基址寄存器 + mem->base = (scc_x86_reg_t)preg; + } else if (sub_idx == 2) { + // 索引寄存器 + mem->index = (scc_x86_reg_t)preg; + } + } +} + +static void x86_alloc_iter_replace_slot(scc_reg_alloc_iter_t *iter, int slot) { + scc_mir_x86_instr_t *ins = (scc_mir_x86_instr_t *)iter->instr; + int op_idx = iter->op_idx; + if (op_idx < ins->x86_instr.num_operands && iter->op_sub_idx == 0) { + ins->x86_instr.operands[op_idx] = scc_x86_op_slot(slot); + } else { + Panic("x86_alloc_iter_replace_slot: invalid op_idx"); + } +} + +static void x86_alloc_iter_end(scc_reg_alloc_iter_t *iter) { + (void)iter; // 无需清理 +} void scc_reg_alloc_fill_arch_x86(scc_reg_alloc_op_t *ops) { ops->acquire_reg = acquire_reg; @@ -182,19 +240,13 @@ void scc_reg_alloc_fill_arch_x86(scc_reg_alloc_op_t *ops) { ops->mark_reg_used = mark_reg_used; ops->clean_mark_regs = clean_mark_regs; - ops->instr_opcode = instr_opcode; - ops->instr_num_operands = instr_num_operands; - ops->op_is_vreg = op_is_vreg; - ops->op_get_vreg = op_get_vreg; - ops->op_set_preg = op_set_preg; - ops->op_set_slot = op_set_slot; - - ops->get_operand_access = get_operand_access; + ops->alloc_iter_begin = x86_alloc_iter_begin; + ops->alloc_iter_next = x86_alloc_iter_next; + ops->alloc_iter_replace_preg = x86_alloc_iter_replace_preg; + ops->alloc_iter_replace_slot = x86_alloc_iter_replace_slot; + ops->alloc_iter_end = x86_alloc_iter_end; ops->get_implicit_regs = get_implicit_regs; - ops->is_pseudo = is_pseudo; - ops->handle_pseudo = handle_pseudo; - ops->emit_spill = emit_spill; ops->emit_reload = emit_reload; ops->emit_copy = emit_copy; diff --git a/libs/ir/mir/src/reg_alloc/reg_alloc.c b/libs/ir/mir/src/reg_alloc/reg_alloc.c index 66fb68a..6ef0d8a 100644 --- a/libs/ir/mir/src/reg_alloc/reg_alloc.c +++ b/libs/ir/mir/src/reg_alloc/reg_alloc.c @@ -6,8 +6,11 @@ static void alloc_instr(scc_reg_alloc_ctx_t *ctx, scc_mir_instr_t *instr) { const scc_reg_alloc_op_t *ops = &ctx->ops; usize instr_size = ctx->module->instr_size; - if (ops->is_pseudo(instr)) { - ops->handle_pseudo(ctx->func, (void *)instr, instr_vec); + + if (instr->opcode < 0) { + if (instr->opcode != SCC_MIR_PSEUDO_ALLOCA) { + scc_vec_sized_push(*instr_vec, instr_size, instr, instr_size); + } return; } @@ -17,69 +20,69 @@ static void alloc_instr(scc_reg_alloc_ctx_t *ctx, SCC_VEC(int) allocated; scc_vec_init(allocated); - int opcode = ops->instr_opcode(instr); - - // 标记隐式寄存器 + // 获取隐式寄存器 const int *implicit_uses, *implicit_defs; - ops->get_implicit_regs(ctx, opcode, &implicit_uses, &implicit_defs); + ops->get_implicit_regs(ctx, instr->opcode, &implicit_uses, &implicit_defs); for (const int *p = implicit_uses; *p != -1; p++) ops->mark_reg_used(ctx, *p); for (const int *p = implicit_defs; *p != -1; p++) ops->mark_reg_used(ctx, *p); - int num_ops = ops->instr_num_operands(instr); - for (int op_i = 0; op_i < num_ops; op_i++) { - if (!ops->op_is_vreg(instr, op_i)) - continue; + // 初始化迭代器 + scc_reg_alloc_iter_t iter; + iter.instr = instr; + ops->alloc_iter_begin(&iter); - int vreg = ops->op_get_vreg(instr, op_i); + int vreg; + int size; + scc_reg_op_access_t access; + while (ops->alloc_iter_next(&iter, &vreg, &size, &access)) { int id = 0; int mapping = scc_mir_vreg_lookup(ctx->func, vreg, &id); int preg = id, slot = id; if (mapping == 1) { - // 已预着色 ops->mark_reg_used(ctx, preg); - ops->op_set_preg(instr, op_i, preg); + ops->alloc_iter_replace_preg(&iter, preg); continue; } - if (mapping == 0) - slot = scc_mir_vreg_map2slot(ctx->func, vreg, 8, 8); - + slot = scc_mir_vreg_map2slot(ctx->func, vreg, size, 8); preg = ops->acquire_reg(ctx); scc_vec_push(allocated, preg); - scc_reg_op_access_t acc = ops->get_operand_access(ctx, opcode, op_i); - if (acc == SCC_REG_ALLOC_OP_ACCESS_READ || - acc == SCC_REG_ALLOC_OP_ACCESS_READWRITE) - ops->emit_reload(&before, preg, slot); - if (acc == SCC_REG_ALLOC_OP_ACCESS_WRITE || - acc == SCC_REG_ALLOC_OP_ACCESS_READWRITE) - ops->emit_spill(&after, preg, slot); + if (access == SCC_REG_ALLOC_OP_ACCESS_READ || + access == SCC_REG_ALLOC_OP_ACCESS_READWRITE) + ops->emit_reload(&before, preg, slot, size); + if (access == SCC_REG_ALLOC_OP_ACCESS_WRITE || + access == SCC_REG_ALLOC_OP_ACCESS_READWRITE) + ops->emit_spill(&after, preg, slot, size); - ops->op_set_preg(instr, op_i, preg); + ops->alloc_iter_replace_preg(&iter, preg); + } + ops->alloc_iter_end(&iter); + + // 合并 before / instr / after + for (size_t i = 0; i < scc_vec_size(before); i++) { + void *p = scc_vec_sized_at_ptr(before, instr_size, i); + scc_vec_sized_push(*instr_vec, instr_size, p, instr_size); + } + scc_vec_sized_push(*instr_vec, instr_size, instr, instr_size); + for (size_t i = 0; i < scc_vec_size(after); i++) { + void *p = scc_vec_sized_at_ptr(after, instr_size, i); + scc_vec_sized_push(*instr_vec, instr_size, p, instr_size); } - // 合并指令流 - scc_vec_foreach(before, i) scc_vec_sized_push( - *instr_vec, instr_size, scc_vec_sized_at_ptr(before, instr_size, i), - instr_size); - scc_vec_sized_push(*instr_vec, instr_size, instr, instr_size); - scc_vec_foreach(after, i) scc_vec_sized_push( - *instr_vec, instr_size, scc_vec_sized_at_ptr(after, instr_size, i), - instr_size); - - // 清理隐式寄存器 + // 释放隐式寄存器 for (const int *p = implicit_defs; *p != -1; p++) - ops->mark_reg_used(ctx, *p); + ops->release_reg(ctx, *p); for (const int *p = implicit_uses; *p != -1; p++) ops->release_reg(ctx, *p); scc_vec_free(before); scc_vec_free(after); - scc_vec_foreach(allocated, l) - ops->release_reg(ctx, scc_vec_at(allocated, l)); + for (size_t i = 0; i < scc_vec_size(allocated); i++) + ops->release_reg(ctx, scc_vec_at(allocated, i)); scc_vec_free(allocated); } @@ -99,7 +102,6 @@ void scc_reg_alloc(scc_reg_alloc_ctx_t *ctx, scc_mir_module_t *module) { scc_cfg_bblock_id_t bb_id = scc_vec_at(func->bblocks, j); scc_cfg_bblock_t *bb = scc_cfg_module_unsafe_get_bblock(&module->cfg_module, bb_id); - scc_mir_instr_vec_t *old_instrs = SCC_MIR_BBLOCK_VALUES_PTR(bb); scc_mir_instr_vec_t new_instrs; scc_vec_init(new_instrs); @@ -114,4 +116,4 @@ void scc_reg_alloc(scc_reg_alloc_ctx_t *ctx, scc_mir_module_t *module) { *old_instrs = new_instrs; } } -} +} \ No newline at end of file diff --git a/libs/ir/mir/src/scc_mir_dump.c b/libs/ir/mir/src/scc_mir_dump.c index 89b14d5..76c90af 100644 --- a/libs/ir/mir/src/scc_mir_dump.c +++ b/libs/ir/mir/src/scc_mir_dump.c @@ -1,8 +1,10 @@ #include #include -void scc_x86_instr_dump(scc_tree_dump_t *td, const scc_mir_x86_instr_t *instr); -void scc_mir_dump_bblock(scc_mir_dump_ctx_t *ctx, const scc_mir_bblock_t *bb) { +void scc_x86_instr_dump(scc_tree_dump_t *td, const scc_mir_func_t *func, + const scc_mir_x86_instr_t *instr); +void scc_mir_dump_bblock(scc_mir_dump_ctx_t *ctx, const scc_mir_func_t *func, + const scc_mir_bblock_t *bb) { Assert(ctx != nullptr && bb != nullptr); scc_tree_dump_t *td = ctx->dump_ctx; @@ -27,7 +29,7 @@ void scc_mir_dump_bblock(scc_mir_dump_ctx_t *ctx, const scc_mir_bblock_t *bb) { break; } } else { - scc_x86_instr_dump(td, (void *)instr); + scc_x86_instr_dump(td, func, (void *)instr); } } } @@ -44,7 +46,7 @@ void scc_mir_dump_func(scc_mir_dump_ctx_t *ctx, const scc_mir_func_t *func) { scc_cfg_bblock_id_t id = scc_vec_at(func->bblocks, i); const scc_cfg_bblock_t *bb = scc_cfg_module_unsafe_get_bblock(&ctx->mir_module->cfg_module, id); - scc_mir_dump_bblock(ctx, bb); + scc_mir_dump_bblock(ctx, func, bb); } } diff --git a/libs/ir/mir/src/scc_mir_pass.c b/libs/ir/mir/src/scc_mir_pass.c index ec3a1d8..a9efc08 100644 --- a/libs/ir/mir/src/scc_mir_pass.c +++ b/libs/ir/mir/src/scc_mir_pass.c @@ -65,6 +65,9 @@ void scc_mir_pass(scc_mir_module_t *mir_module, scc_mir_pass_stage_t stage) { return; } + void scc_x86_peephole_optimize(scc_mir_module_t * module); + // scc_x86_peephole_optimize(mir_module); + scc_frame_layout_t frame_layout_ctx = {0}; scc_win_pc_x64_frame_alloc_init(&frame_layout_ctx); scc_frame_layout(&frame_layout_ctx, mir_module); diff --git a/libs/ir/mir/src/target/win64_abi.c b/libs/ir/mir/src/target/win64_abi.c index 678c526..2ef07dd 100644 --- a/libs/ir/mir/src/target/win64_abi.c +++ b/libs/ir/mir/src/target/win64_abi.c @@ -155,7 +155,7 @@ static void lower_call(void *userdata, const scc_lir_instr_t *instr) { add_instr_1(isel, op.kind == SCC_X86_OPR_REG ? SCC_X86_IFORM_PUSH_GPRV_50 : SCC_X86_IFORM_PUSH_IMMZ, - op); + op, 8); break; } } diff --git a/libs/ir2mcode/src/scc_ir2mcode.c b/libs/ir2mcode/src/scc_ir2mcode.c index 939e1b9..78725ba 100644 --- a/libs/ir2mcode/src/scc_ir2mcode.c +++ b/libs/ir2mcode/src/scc_ir2mcode.c @@ -8,6 +8,20 @@ #include #include +scc_x86_reg_t mir_x86_trans_gpr(scc_x86_reg_t reg, u8 size) { + size *= 8; + if (size == 0) { + return reg; + } + for (scc_x86_reg_t i = 0; i < SCC_X86_REG_COUNT; i += 1) { + if (scc_x86_reg_table[i].max_enclosing == reg && + scc_x86_reg_table[i].width == size) { + return i; + } + } + return reg; +} + void mir_x86_to_mcode(scc_mcode_t *mcode, scc_reloc_vec_t *relocs, const scc_mir_x86_instr_t *_ins) { Assert(mcode != nullptr && _ins != nullptr); @@ -24,15 +38,21 @@ void mir_x86_to_mcode(scc_mcode_t *mcode, scc_reloc_vec_t *relocs, Panic("can't convert vreg to mcode"); if (scc_x86_op_is_slot(op_ptr)) Panic("can't convert unresolved slot to mcode"); - ops[i] = *op_ptr; if (op_ptr->kind == SCC_X86_OPR_RELOC) { ops[i].kind = op_ptr->reloc.kind; switch (op_ptr->reloc.kind) { case SCC_X86_OPR_RELBR: - ops[i].imm0 = 0; + ops[i].brdisp = 0; + break; + case SCC_X86_OPR_MEM: + ops[i].mem.base = SCC_X86_REG_RIP; + ops[i].mem.index = SCC_X86_REG_INVALID; + ops[i].mem.scale = 1; + ops[i].mem.disp.displacement = 0; + ops[i].mem.disp.displacement_bits = 32; break; default: - TODO(); + Panic("unsupported reloc type %d", op_ptr->reloc.kind); break; } if (skip_reloc) { @@ -55,8 +75,14 @@ void mir_x86_to_mcode(scc_mcode_t *mcode, scc_reloc_vec_t *relocs, } else { TODO(); } + } 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); + } else { + ops[i] = *op_ptr; } } + scc_x86_encode_inst(mcode, ins->opcode, ops); if (!skip_reloc && reloc.target_kind != SCC_RELOC_TARGET_NONE) { reloc.offset = scc_mcode_size(mcode); diff --git a/libs/ir2mcode/src/scc_ir2sccf.c b/libs/ir2mcode/src/scc_ir2sccf.c index de247b4..5c50671 100644 --- a/libs/ir2mcode/src/scc_ir2sccf.c +++ b/libs/ir2mcode/src/scc_ir2sccf.c @@ -31,10 +31,18 @@ static inline void scc_ir_sym_to_sccf_sym(const scc_cfg_symbol_t *symbol, static inline void scc_ir_symbol_to_sect_data(const scc_cfg_symbol_t *symbol, sccf_sect_data_t *sect_data) { - // scc_vec_foreach(value->data.const_array.fields, j) { - // scc_vec_push(ctx->sect_data, - // scc_vec_at(value->data.const_array.fields, j)); - // } + if (symbol->kind != SCC_CFG_SYMBOL_KIND_DATA) { + return; + } + scc_mir_symbol_meta_t *meta = SCC_MIR_SYMBOL_META(symbol); + for (usize i = 0; i < meta->data.size; i += 1) { + scc_vec_push(*sect_data, meta->data.init_data[i]); + } + // struct { + // u8 *init_data; // 初始化数据(若为 NULL 则零初始化) + // usize size; // 数据大小(字节) + // int align; // 对齐要求 + // } data; } static void emit_mir_module(sccf_builder_t *builder, scc_mcode_t *mcode, @@ -122,14 +130,16 @@ void scc_ir2sccf(sccf_builder_t *builder, scc_mir_module_t *mir_module) { continue; } - sccf_sym_t sym = (sccf_sym_t){ - .sccf_sect_offset = scc_vec_size(sect_data), - .sccf_sym_size = - 4, // FIXME on windows using rel32, on linux using ? - }; - + sccf_sym_t sym = {0}; scc_ir_sym_to_sccf_sym(symbol, &sym); - scc_ir_symbol_to_sect_data(symbol, §_data); + + // FIXME 区分只读 + if (sym.sccf_sect_type == SCCF_SECT_DATA || + sym.sccf_sect_type == SCCF_SECT_RODATA) { + sym.sccf_sect_offset = scc_vec_size(sect_data); + scc_ir_symbol_to_sect_data(symbol, §_data); + sym.sccf_sym_size = scc_vec_size(sect_data) - sym.sccf_sect_offset; + } usize sym_idx = sccf_builder_add_symbol(builder, symbol->name, &sym); Assert(sym_idx != 0); diff --git a/libs/mcode/include/scc_mcode.h b/libs/mcode/include/scc_mcode.h index 7c2242f..f3543be 100644 --- a/libs/mcode/include/scc_mcode.h +++ b/libs/mcode/include/scc_mcode.h @@ -12,76 +12,76 @@ typedef SCC_VEC(u8) scc_mcode_buff_t; typedef struct { cbool is_littel_endian; scc_mcode_arch_t arch; - scc_mcode_buff_t mcode; + scc_mcode_buff_t code; } scc_mcode_t; static inline void scc_mcode_init(scc_mcode_t *mcode, scc_mcode_arch_t arch) { - scc_vec_init(mcode->mcode); + scc_vec_init(mcode->code); mcode->arch = arch; mcode->is_littel_endian = true; } static inline char *scc_mcode_unsafe_data(scc_mcode_t *mcode) { - return (char *)scc_vec_unsafe_get_data(mcode->mcode); + return (char *)scc_vec_unsafe_get_data(mcode->code); } static inline usize scc_mcode_size(scc_mcode_t *mcode) { - return scc_vec_size(mcode->mcode); + return scc_vec_size(mcode->code); } static inline void scc_mcode_drop(scc_mcode_t *mcode) { - scc_vec_free(mcode->mcode); + scc_vec_free(mcode->code); mcode->arch = SCC_MCODE_ARCH_NONE; mcode->is_littel_endian = true; } static inline void scc_mcode_add_u8(scc_mcode_t *mcode, u8 data) { - scc_vec_push(mcode->mcode, data); + scc_vec_push(mcode->code, data); } static inline void scc_mcode_add_u16(scc_mcode_t *mcode, u16 data) { if (mcode->is_littel_endian) { - scc_vec_push(mcode->mcode, (u8)(data & 0xFF)); - scc_vec_push(mcode->mcode, (u8)(data >> 8)); + scc_vec_push(mcode->code, (u8)(data & 0xFF)); + scc_vec_push(mcode->code, (u8)(data >> 8)); } else { - scc_vec_push(mcode->mcode, (u8)(data >> 8)); - scc_vec_push(mcode->mcode, (u8)(data & 0xFF)); + scc_vec_push(mcode->code, (u8)(data >> 8)); + scc_vec_push(mcode->code, (u8)(data & 0xFF)); } } static inline void scc_mcode_add_u32(scc_mcode_t *mcode, u32 data) { if (mcode->is_littel_endian) { - scc_vec_push(mcode->mcode, (u8)(data & 0xFF)); - scc_vec_push(mcode->mcode, (u8)(data >> 8)); - scc_vec_push(mcode->mcode, (u8)(data >> 16)); - scc_vec_push(mcode->mcode, (u8)(data >> 24)); + scc_vec_push(mcode->code, (u8)(data & 0xFF)); + scc_vec_push(mcode->code, (u8)(data >> 8)); + scc_vec_push(mcode->code, (u8)(data >> 16)); + scc_vec_push(mcode->code, (u8)(data >> 24)); } else { - scc_vec_push(mcode->mcode, (u8)(data >> 24)); - scc_vec_push(mcode->mcode, (u8)(data >> 16)); - scc_vec_push(mcode->mcode, (u8)(data >> 8)); - scc_vec_push(mcode->mcode, (u8)(data & 0xFF)); + scc_vec_push(mcode->code, (u8)(data >> 24)); + scc_vec_push(mcode->code, (u8)(data >> 16)); + scc_vec_push(mcode->code, (u8)(data >> 8)); + scc_vec_push(mcode->code, (u8)(data & 0xFF)); } } static inline void scc_mcode_add_u64(scc_mcode_t *mcode, uint64_t data) { if (mcode->is_littel_endian) { - scc_vec_push(mcode->mcode, (u8)(data & 0xFF)); - scc_vec_push(mcode->mcode, (u8)(data >> 8)); - scc_vec_push(mcode->mcode, (u8)(data >> 16)); - scc_vec_push(mcode->mcode, (u8)(data >> 24)); - scc_vec_push(mcode->mcode, (u8)(data >> 32)); - scc_vec_push(mcode->mcode, (u8)(data >> 40)); - scc_vec_push(mcode->mcode, (u8)(data >> 48)); - scc_vec_push(mcode->mcode, (u8)(data >> 56)); + scc_vec_push(mcode->code, (u8)(data & 0xFF)); + scc_vec_push(mcode->code, (u8)(data >> 8)); + scc_vec_push(mcode->code, (u8)(data >> 16)); + scc_vec_push(mcode->code, (u8)(data >> 24)); + scc_vec_push(mcode->code, (u8)(data >> 32)); + scc_vec_push(mcode->code, (u8)(data >> 40)); + scc_vec_push(mcode->code, (u8)(data >> 48)); + scc_vec_push(mcode->code, (u8)(data >> 56)); } else { - scc_vec_push(mcode->mcode, (u8)(data >> 56)); - scc_vec_push(mcode->mcode, (u8)(data >> 48)); - scc_vec_push(mcode->mcode, (u8)(data >> 40)); - scc_vec_push(mcode->mcode, (u8)(data >> 32)); - scc_vec_push(mcode->mcode, (u8)(data >> 24)); - scc_vec_push(mcode->mcode, (u8)(data >> 16)); - scc_vec_push(mcode->mcode, (u8)(data >> 8)); - scc_vec_push(mcode->mcode, (u8)(data & 0xFF)); + scc_vec_push(mcode->code, (u8)(data >> 56)); + scc_vec_push(mcode->code, (u8)(data >> 48)); + scc_vec_push(mcode->code, (u8)(data >> 40)); + scc_vec_push(mcode->code, (u8)(data >> 32)); + scc_vec_push(mcode->code, (u8)(data >> 24)); + scc_vec_push(mcode->code, (u8)(data >> 16)); + scc_vec_push(mcode->code, (u8)(data >> 8)); + scc_vec_push(mcode->code, (u8)(data & 0xFF)); } } diff --git a/libs/mcode/include/x86/scc_x86_encode.h b/libs/mcode/include/x86/scc_x86_encode.h index fc888cd..9fc9895 100644 --- a/libs/mcode/include/x86/scc_x86_encode.h +++ b/libs/mcode/include/x86/scc_x86_encode.h @@ -45,16 +45,21 @@ typedef struct { scc_x86_mem_t mem; scc_x86_reloc_op_t reloc; }; + usize size; } scc_x86_operand_value_t; static inline scc_x86_operand_value_t scc_x86_op_preg(scc_x86_reg_t reg) { scc_x86_operand_value_t o = {.kind = SCC_X86_OPR_REG, .reg = reg}; 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) { scc_x86_operand_value_t o = { .kind = SCC_X86_OPR_REG, - .reg = (scc_x86_reg_t)((int)SCC_X86_REG_COUNT + vreg)}; + .reg = scc_x86_op_vreg_reg(vreg), + }; return o; } static inline scc_x86_operand_value_t scc_x86_op_relbr(i32 rel) { @@ -81,6 +86,16 @@ scc_x86_op_reloc_global_imm(const char *sym, i64 addend) { return op; } +static inline scc_x86_operand_value_t +scc_x86_op_reloc_global_relrip(const char *sym, i64 addend) { + scc_x86_operand_value_t op = {.kind = SCC_X86_OPR_RELOC}; + op.reloc.kind = SCC_X86_OPR_MEM; + op.reloc.target = SCC_X86_RELOC_TARGET_SYMBOL; + op.reloc.global_name = sym; + op.reloc.addend = addend; + return op; +} + // 2. 全局符号重定位(相对跳转/调用:CALL/JMP rel32) static inline scc_x86_operand_value_t scc_x86_op_reloc_global_relbr(const char *sym, i64 addend) { diff --git a/libs/mcode/include/x86/scc_x86_patch.h b/libs/mcode/include/x86/scc_x86_patch.h index a918181..c632aa9 100644 --- a/libs/mcode/include/x86/scc_x86_patch.h +++ b/libs/mcode/include/x86/scc_x86_patch.h @@ -23,8 +23,6 @@ static inline void patch_bytes(scc_mcode_t *mcode, usize offset, scc_memcpy(buf + offset, data, size); } -/* ---------- 实现补丁接口 ---------- */ - static inline int scc_x86_patch_disp(scc_mcode_t *mcode, usize offset, scc_x86_disp_t disp) { if (!mcode || disp.displacement_bits == 0) diff --git a/libs/mcode/src/scc_x86_encode.c b/libs/mcode/src/scc_x86_encode.c index e284a75..21cc42b 100644 --- a/libs/mcode/src/scc_x86_encode.c +++ b/libs/mcode/src/scc_x86_encode.c @@ -37,11 +37,19 @@ static inline int scc_reg_ordinal(scc_x86_reg_t reg) { static int reg_low3(scc_x86_reg_t reg) { if (reg == SCC_X86_REG_INVALID) return 0; + // RIP/EIP/IP 必须返回 5,否则无法编码 RIP 相对寻址 + if (reg == SCC_X86_REG_RIP || reg == SCC_X86_REG_EIP || + reg == SCC_X86_REG_IP) + return 5; return scc_reg_ordinal(reg) & 7; } static int reg_rex_bit(scc_x86_reg_t reg) { if (reg == SCC_X86_REG_INVALID) return 0; + // RIP 不需要 REX 扩展 + if (reg == SCC_X86_REG_RIP || reg == SCC_X86_REG_EIP || + reg == SCC_X86_REG_IP) + return 0; if (reg >= SCC_X86_REG_AH && reg <= SCC_X86_REG_DH) return 0; return (scc_reg_ordinal(reg) >= 8) ? 1 : 0; @@ -138,9 +146,11 @@ static void emit_legacy_prefixes(scc_mcode_t *m, const scc_x86_encoding_t *enc, static void emit_rex(scc_mcode_t *m, const scc_x86_encoding_t *enc, scc_x86_reg_t reg_op, scc_x86_reg_t rm_op, - scc_x86_reg_t base, scc_x86_reg_t idx) { + scc_x86_reg_t base, scc_x86_reg_t idx, + int op_width) { // 新增 op_width 参数 int rex = 0x40; - if (need_rexw(enc, reg_op, rm_op, base, idx)) + // 仅当 op_width == 64 时才考虑 REX.W + if (op_width == 64 && need_rexw(enc, reg_op, rm_op, base, idx)) rex |= 8; if (reg_op != SCC_X86_REG_INVALID && reg_rex_bit(reg_op)) rex |= 4; @@ -154,7 +164,6 @@ static void emit_rex(scc_mcode_t *m, const scc_x86_encoding_t *enc, emit_u8(m, (uint8_t)rex); } } - static void emit_escape_map(scc_mcode_t *m, const scc_x86_encoding_t *enc) { if (enc->map == 1) { emit_u8(m, 0x0F); @@ -196,15 +205,17 @@ static int scale_to_enc(uint8_t scale) { } } +/* 修正:位移大小只由数值范围决定,与基址寄存器无关 */ static int disp_size(int32_t disp, scc_x86_reg_t base) { - if (disp == 0 && base != SCC_X86_REG_RBP && base != SCC_X86_REG_R13) + (void)base; + if (disp == 0) return 0; if (disp >= -128 && disp <= 127) return 8; return 32; } -/* ---------- 立即数发射(独立函数) ---------- */ +/* ---------- 立即数发射 ---------- */ static void emit_immediate(scc_mcode_t *m, const scc_x86_encoding_t *enc, const scc_x86_operand_t *tmpl, int imm_idx, int64_t imm_val, int op_width) { @@ -285,17 +296,58 @@ static void emit_modrm_sib_disp(scc_mcode_t *m, scc_reg_ordinal(reg_r), reg_b, scc_reg_ordinal(reg_b)); uint8_t modrm = 0; + if (has_mem) { + // ========== RIP 相对寻址特殊处理 ========== + if (memdesc.base == SCC_X86_REG_RIP && + memdesc.index == SCC_X86_REG_INVALID) { + // RIP 相对:mod=00, r/m=101,位移固定 32 位 + if (reg_r != SCC_X86_REG_INVALID) + modrm |= (reg_low3(reg_r) & 7) << 3; + else if (enc->modrm_reg_fix >= 0) + modrm |= (enc->modrm_reg_fix & 7) << 3; + modrm |= 0x05; // r/m = 101 + emit_u8(m, modrm); + // 写入 32 位位移(小端) + int32_t disp32 = (int32_t)memdesc.disp.displacement; + emit_u32(m, (uint32_t)disp32); + // 处理立即数(如果有) + if (imm_idx >= 0) { + emit_immediate(m, enc, tmpl, imm_idx, imm_val, op_width); + } + return; // 已处理完,跳过后续 SIB/位移逻辑 + } + // ========================================== + if (reg_r != SCC_X86_REG_INVALID) modrm |= (reg_low3(reg_r) & 7) << 3; else if (enc->modrm_reg_fix >= 0) modrm |= (enc->modrm_reg_fix & 7) << 3; int32_t disp = memdesc.disp.displacement; - int dsize = disp_size(disp, memdesc.base); - modrm |= (dsize == 0) ? 0 : (dsize == 8) ? 0x40 : 0x80; + // 优先使用用户指定的 displacement_bits,转换为字节数 + int dsize = 0; + if (memdesc.disp.displacement_bits != 0) { + dsize = memdesc.disp.displacement_bits / 8; + if (dsize != 1 && dsize != 2 && dsize != 4 && dsize != 8) + dsize = 0; // 无效则回退 + } + if (dsize == 0) { + // 使用自动计算:disp_size 返回位数,除以 8 得字节数 + int bits = disp_size(disp, memdesc.base); + dsize = bits / 8; + } + + // 设置 ModRM 的 mod 字段 + if (dsize == 0) + modrm |= 0x00; + else if (dsize == 1) + modrm |= 0x40; + else if (dsize == 2 || dsize == 4 || dsize == 8) + modrm |= 0x80; // 2/4/8 字节位移均使用 mod=10b if (memdesc.index != SCC_X86_REG_INVALID) { + // SIB 寻址 modrm |= 4; int idx_ord = scc_reg_ordinal(memdesc.index); int base_ord = scc_reg_ordinal(memdesc.base); @@ -306,45 +358,57 @@ static void emit_modrm_sib_disp(scc_mcode_t *m, (base_ord & 7)); emit_u8(m, modrm); emit_u8(m, sib); - if (dsize == 8) + if (dsize == 1) emit_u8(m, (uint8_t)disp); - else if (dsize == 32) + else if (dsize == 2) + emit_u16(m, (uint16_t)disp); + else if (dsize == 4) emit_u32(m, (uint32_t)disp); + else if (dsize == 8) + emit_u64(m, (uint64_t)disp); } else if (memdesc.base == SCC_X86_REG_INVALID) { + // 绝对地址:mod=00, r/m=101,位移 32 位 modrm |= 5; emit_u8(m, modrm); emit_u32(m, (uint32_t)disp); } else { + // 一般基址寻址 int base_ord = scc_reg_ordinal(memdesc.base); if (memdesc.base == SCC_X86_REG_RSP || memdesc.base == SCC_X86_REG_R12) { + // 需要 SIB(基址为 RSP/R12 时强制) modrm |= 4; uint8_t sib = (uint8_t)((base_ord & 7) | (4 << 3)); emit_u8(m, modrm); emit_u8(m, sib); - if (dsize == 8) + if (dsize == 1) emit_u8(m, (uint8_t)disp); - else if (dsize == 32) + else if (dsize == 2) + emit_u16(m, (uint16_t)disp); + else if (dsize == 4) emit_u32(m, (uint32_t)disp); + else if (dsize == 8) + emit_u64(m, (uint64_t)disp); } else { modrm |= (base_ord & 7); emit_u8(m, modrm); - if (dsize == 8) + if (dsize == 1) emit_u8(m, (uint8_t)disp); - else if (dsize == 32) + else if (dsize == 2) + emit_u16(m, (uint16_t)disp); + else if (dsize == 4) emit_u32(m, (uint32_t)disp); + else if (dsize == 8) + emit_u64(m, (uint64_t)disp); } } } else { - // 特殊情况:只有一个显式寄存器操作数,且 reg_fix/rm_fix 均未指定,且 - // mod_fix == 3 此时操作数应放在 rm 字段,reg 字段固定为 0(例如 SETZ - // 指令) + // 没有内存操作数:寄存器-寄存器或单个寄存器 int is_single_reg_op = (info->num_explicit_ops == 1 && enc->modrm_reg_fix == -1 && enc->modrm_rm_fix == -1 && enc->mod_fix == 3); if (is_single_reg_op && reg_r != SCC_X86_REG_INVALID && reg_b == SCC_X86_REG_INVALID) { - // 操作数作为 rm,reg 部分为 0 modrm = 0xC0 | (reg_low3(reg_r) & 7); emit_u8(m, modrm); LOG_INFO("[MODRM] single reg operand treated as rm, emit 0x%02x", @@ -369,28 +433,126 @@ static void emit_modrm_sib_disp(scc_mcode_t *m, emit_u8(m, modrm); } } + LOG_INFO("[MODRM] emit byte 0x%02x", modrm); - /* 立即数在 ModRM 后发射 */ + // 立即数在 ModRM 后发射 if (imm_idx >= 0) { emit_immediate(m, enc, tmpl, imm_idx, imm_val, op_width); } } +static scc_x86_iform_t adapt_iform_to_8bit(scc_x86_iform_t iform, + const scc_x86_operand_value_t *ops, + int num_ops) { + // 只处理第一个操作数是 8 + // 位寄存器的情况(大多数指令的目标或源是第一个寄存器) + if (num_ops > 0 && ops[0].kind == SCC_X86_OPR_REG && + scc_reg_width(ops[0].reg) == 8) { + switch (iform) { + // ---- MOV 类 ---- + case SCC_X86_IFORM_MOV_GPRV_IMMV: + case SCC_X86_IFORM_MOV_GPRV_IMMZ: + return SCC_X86_IFORM_MOV_GPR8_IMMB_B0; + case SCC_X86_IFORM_MOV_GPRV_GPRV_89: // mov r/m, r + return SCC_X86_IFORM_MOV_GPR8_GPR8_88; + case SCC_X86_IFORM_MOV_GPRV_GPRV_8B: // mov r, r/m + return SCC_X86_IFORM_MOV_GPR8_GPR8_8A; + case SCC_X86_IFORM_MOV_GPRV_MEMV: // mov r, mem + return SCC_X86_IFORM_MOV_GPR8_MEMB; + case SCC_X86_IFORM_MOV_MEMV_GPRV: // mov mem, r + return SCC_X86_IFORM_MOV_MEMB_GPR8; + // ---- ADD ---- + case SCC_X86_IFORM_ADD_GPRV_IMMB: + case SCC_X86_IFORM_ADD_GPRV_IMMZ: + return SCC_X86_IFORM_ADD_GPR8_IMMB_80R0; + case SCC_X86_IFORM_ADD_GPRV_GPRV_01: // add r/m, r + return SCC_X86_IFORM_ADD_GPR8_GPR8_00; + case SCC_X86_IFORM_ADD_GPRV_GPRV_03: // add r, r/m + return SCC_X86_IFORM_ADD_GPR8_GPR8_02; + // ---- SUB ---- + case SCC_X86_IFORM_SUB_GPRV_IMMB: + case SCC_X86_IFORM_SUB_GPRV_IMMZ: + return SCC_X86_IFORM_SUB_GPR8_IMMB_80R5; + case SCC_X86_IFORM_SUB_GPRV_GPRV_29: + return SCC_X86_IFORM_SUB_GPR8_GPR8_28; + case SCC_X86_IFORM_SUB_GPRV_GPRV_2B: + return SCC_X86_IFORM_SUB_GPR8_GPR8_2A; + // ---- CMP ---- + case SCC_X86_IFORM_CMP_GPRV_IMMB: + case SCC_X86_IFORM_CMP_GPRV_IMMZ: + return SCC_X86_IFORM_CMP_GPR8_IMMB_80R7; + case SCC_X86_IFORM_CMP_GPRV_GPRV_39: + return SCC_X86_IFORM_CMP_GPR8_GPR8_38; + case SCC_X86_IFORM_CMP_GPRV_GPRV_3B: + return SCC_X86_IFORM_CMP_GPR8_GPR8_3A; + // ---- AND ---- + case SCC_X86_IFORM_AND_GPRV_IMMB: + case SCC_X86_IFORM_AND_GPRV_IMMZ: + return SCC_X86_IFORM_AND_GPR8_IMMB_80R4; + case SCC_X86_IFORM_AND_GPRV_GPRV_21: + return SCC_X86_IFORM_AND_GPR8_GPR8_20; + // ---- OR ---- + case SCC_X86_IFORM_OR_GPRV_IMMB: + case SCC_X86_IFORM_OR_GPRV_IMMZ: + return SCC_X86_IFORM_OR_GPR8_IMMB_80R1; + case SCC_X86_IFORM_OR_GPRV_GPRV_09: + return SCC_X86_IFORM_OR_GPR8_GPR8_08; + // ---- XOR ---- + case SCC_X86_IFORM_XOR_GPRV_IMMB: + case SCC_X86_IFORM_XOR_GPRV_IMMZ: + return SCC_X86_IFORM_XOR_GPR8_IMMB_80R6; + case SCC_X86_IFORM_XOR_GPRV_GPRV_31: + return SCC_X86_IFORM_XOR_GPR8_GPR8_30; + // ---- TEST ---- + case SCC_X86_IFORM_TEST_GPRV_GPRV: + return SCC_X86_IFORM_TEST_GPR8_GPR8; + case SCC_X86_IFORM_TEST_GPRV_IMMZ_F7R0: + return SCC_X86_IFORM_TEST_GPR8_IMMB_F6R0; + // ---- INC/DEC ---- + case SCC_X86_IFORM_INC_GPRV_40: + case SCC_X86_IFORM_INC_GPRV_FFR0: + return SCC_X86_IFORM_INC_GPR8; + case SCC_X86_IFORM_DEC_GPRV_48: + case SCC_X86_IFORM_DEC_GPRV_FFR1: + return SCC_X86_IFORM_DEC_GPR8; + // ---- NEG/NOT ---- + case SCC_X86_IFORM_NEG_GPRV: + return SCC_X86_IFORM_NEG_GPR8; + case SCC_X86_IFORM_NOT_GPRV: + return SCC_X86_IFORM_NOT_GPR8; + // ---- 移位操作 ---- + case SCC_X86_IFORM_SHL_GPRV_ONE_D1R4: + return SCC_X86_IFORM_SHL_GPR8_ONE_D0R4; + case SCC_X86_IFORM_SHR_GPRV_ONE: + return SCC_X86_IFORM_SHR_GPR8_ONE; + case SCC_X86_IFORM_SAR_GPRV_ONE: + return SCC_X86_IFORM_SAR_GPR8_ONE; + // ---- 其他(根据需求继续添加)---- + default: + break; + } + } + return iform; +} + /* ---------- 主编码入口 ---------- */ int scc_x86_encode_inst(scc_mcode_t *mcode, scc_x86_iform_t iform, const scc_x86_operand_value_t *ops) { if (!mcode || !ops) return -1; - - if (iform >= SCC_X86_IFORM_COUNT || iform < 0) + if (iform >= SCC_X86_IFORM_COUNT) Panic("invalid iform %d", iform); const scc_x86_iform_info_t *info = &scc_x86_iform_table[iform]; + int num_ops = info->num_explicit_ops; + // FIXME 自动适配 8 位操作数 + iform = adapt_iform_to_8bit(iform, ops, num_ops); + // FIXME 重新获取 info 因为 iform 可能变了 + info = &scc_x86_iform_table[iform]; + const scc_x86_encoding_t *enc = &info->encode; const scc_x86_operand_t *tmpl = info->ops; - int num_ops = info->num_explicit_ops; - LOG_INFO("[IFORM] %s, explicit_ops=%d (total=%d)", info->iform_name, num_ops, info->num_ops); @@ -399,7 +561,6 @@ int scc_x86_encode_inst(scc_mcode_t *mcode, scc_x86_iform_t iform, scc_x86_reg_t base_reg = SCC_X86_REG_INVALID; scc_x86_reg_t idx_reg = SCC_X86_REG_INVALID; - /* ---------- 收集立即数信息(用于无 ModRM 指令) ---------- */ int64_t imm_val = 0; int imm_idx = -1; for (int i = 0; i < num_ops; i++) { @@ -407,16 +568,15 @@ int scc_x86_encode_inst(scc_mcode_t *mcode, scc_x86_iform_t iform, if (ops[i].kind == SCC_X86_OPR_REG) { if (scc_strcmp(tname, "REG0") == 0) { if (enc->modrm_reg_fix >= 0) - rm_field = ops[i].reg; // reg固定 → REG0为rm + rm_field = ops[i].reg; else - reg_field = ops[i].reg; // 否则为reg + reg_field = ops[i].reg; } else if (scc_strcmp(tname, "REG1") == 0) { if (enc->modrm_rm_fix >= 0) - reg_field = ops[i].reg; // rm固定 → REG1为reg + reg_field = ops[i].reg; else - rm_field = ops[i].reg; // 否则为rm + rm_field = ops[i].reg; } else { - // 未命名的寄存器,按先 reg 后 rm 填充 if (reg_field == SCC_X86_REG_INVALID) reg_field = ops[i].reg; else if (rm_field == SCC_X86_REG_INVALID) @@ -432,38 +592,33 @@ int scc_x86_encode_inst(scc_mcode_t *mcode, scc_x86_iform_t iform, } } - // ===== 新增:特殊处理 SETZ 类指令(只有一个寄存器操作数,mod_fix=3 且 - // reg_fix/rm_fix 未指定)===== + // 特殊处理 SETZ 等单寄存器指令 if (enc->has_modrm && info->num_explicit_ops == 1 && enc->modrm_reg_fix == -1 && enc->modrm_rm_fix == -1 && enc->mod_fix == 3) { if (reg_field != SCC_X86_REG_INVALID && rm_field == SCC_X86_REG_INVALID) { - // 将操作数从 reg_field 移到 rm_field rm_field = reg_field; reg_field = SCC_X86_REG_INVALID; } } - // ======================================================================== int op_width = infer_operand_width(info, ops); LOG_INFO("[OPWIDTH] %d bits", op_width); - // +++ 新增:无 ModRM 时,寄存器用 REX.B 扩展 +++ if (!enc->has_modrm) { rm_field = reg_field; reg_field = SCC_X86_REG_INVALID; } emit_legacy_prefixes(mcode, enc, reg_field, rm_field, base_reg, idx_reg); - emit_rex(mcode, enc, reg_field, rm_field, base_reg, idx_reg); + emit_rex(mcode, enc, reg_field, rm_field, base_reg, idx_reg, op_width); emit_escape_map(mcode, enc); if (enc->has_modrm) { emit_opcode(mcode, enc, rm_field, base_reg); emit_modrm_sib_disp(mcode, info, ops, op_width); } else { - // 无 ModRM:opcode 中的寄存器来自 rm_field emit_opcode(mcode, enc, rm_field, base_reg); if (imm_idx >= 0) { emit_immediate(mcode, enc, tmpl, imm_idx, imm_val, op_width); @@ -471,4 +626,4 @@ int scc_x86_encode_inst(scc_mcode_t *mcode, scc_x86_iform_t iform, } return 0; -} +} \ No newline at end of file diff --git a/libs/target/sccf2target/src/sccf2pe.c b/libs/target/sccf2target/src/sccf2pe.c index a343248..d38d650 100644 --- a/libs/target/sccf2target/src/sccf2pe.c +++ b/libs/target/sccf2target/src/sccf2pe.c @@ -230,9 +230,8 @@ void sccf2pe(scc_pe_builder_t *builder, const sccf_t *sccf) { // if (reloc->reloc_type == SCCF_RELOC_TYPE_ABS) { // TODO(); // } - scc_x86_patch(&mcode, SCC_X86_PATCH_PC32, - code_range.virual_address + reloc->offset + reloc->addend, - rva); + 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;