feat(compiler): 实现HIR到LIR的函数定义标记和直接/间接调用区分

- 在HIR函数元数据中添加defined字段来标记函数是否已定义
- 在AST到IR转换过程中设置函数定义状态
- 修改LIR模块函数声明接口以支持定义状态参数
- 实现直接调用和间接调用的区别处理,通过符号查找确定调用类型
- 更新LIR调用指令结构以支持直接和间接调用的不同表示方式
- 调整x86后端指令选择以正确处理不同类型的调用

fix(x86-isel): 优化x86指令发射和操作数大小处理

- 移除move/load/store函数中的size参数,改由操作数本身携带大小信息
- 简化x86指令操作数结构,减少操作数数量限制
- 添加专门的mov系列表单选择函数,根据操作数类型和大小自动选择正确的指令形式
- 修正间接调用的指令形式为CALL_NEAR_MEMV而非GPRV
- 添加向量版本的load/store/move发射函数

refactor(reg-alloc): 更新寄存器分配迭代器接口

- 为分配迭代器的替换方法添加size参数,以便正确处理不同大小的寄存器
This commit is contained in:
zzy
2026-05-23 15:33:54 +08:00
parent d78b91894e
commit ea553718f0
21 changed files with 495 additions and 444 deletions

View File

@@ -60,7 +60,14 @@ static int infer_operand_width(const scc_x86_iform_info_t *info,
const scc_x86_operand_value_t ops[]) {
for (int i = 0; i < info->num_explicit_ops; i++) {
if (ops[i].kind == SCC_X86_OPR_REG && !info->ops[i].is_implicit) {
uint16_t w = scc_reg_width(ops[i].reg);
uint16_t w;
if (ops[i].size > 0 && ops[i].reg >= SCC_X86_REG_R8 &&
ops[i].reg <= SCC_X86_REG_R15) {
/* R8-R15宽度由 size 字段推导 */
w = ops[i].size * 8;
} else {
w = scc_reg_width(ops[i].reg);
}
if (w > 0)
return w;
}
@@ -177,7 +184,8 @@ static void emit_escape_map(scc_mcode_t *m, const scc_x86_encoding_t *enc) {
}
static void emit_opcode(scc_mcode_t *m, const scc_x86_encoding_t *enc,
scc_x86_reg_t rm_reg, scc_x86_reg_t base_reg) {
scc_x86_reg_t rm_reg, scc_x86_reg_t base_reg,
int op_width) {
for (int i = 0; i < enc->opcode_len; i++) {
uint8_t byte = enc->opcode[i];
if (enc->partial_opcode && i == enc->opcode_len - 1) {
@@ -186,6 +194,9 @@ static void emit_opcode(scc_mcode_t *m, const scc_x86_encoding_t *enc,
if (target != SCC_X86_REG_INVALID)
byte |= (reg_low3(target) & 7);
}
/* MOV r8, imm8: B8-BF → B0-B7 */
if (op_width == 8 && (byte & 0xF8) == 0xB8)
byte -= 8;
emit_u8(m, byte);
}
}
@@ -442,100 +453,6 @@ static void emit_modrm_sib_disp(scc_mcode_t *m,
}
}
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) {
@@ -546,15 +463,9 @@ int scc_x86_encode_inst(scc_mcode_t *mcode, scc_x86_iform_t 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;
LOG_INFO("[IFORM] %s, explicit_ops=%d (total=%d)", info->iform_name,
num_ops, info->num_ops);
LOG_INFO("[ENCODE] %s", info->iform_name);
scc_x86_reg_t reg_field = SCC_X86_REG_INVALID;
scc_x86_reg_t rm_field = SCC_X86_REG_INVALID;
@@ -616,10 +527,10 @@ int scc_x86_encode_inst(scc_mcode_t *mcode, scc_x86_iform_t iform,
emit_escape_map(mcode, enc);
if (enc->has_modrm) {
emit_opcode(mcode, enc, rm_field, base_reg);
emit_opcode(mcode, enc, rm_field, base_reg, op_width);
emit_modrm_sib_disp(mcode, info, ops, op_width);
} else {
emit_opcode(mcode, enc, rm_field, base_reg);
emit_opcode(mcode, enc, rm_field, base_reg, op_width);
if (imm_idx >= 0) {
emit_immediate(mcode, enc, tmpl, imm_idx, imm_val, op_width);
}