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:
@@ -45,33 +45,52 @@ typedef struct {
|
||||
scc_x86_mem_t mem;
|
||||
scc_x86_reloc_op_t reloc;
|
||||
};
|
||||
usize size;
|
||||
u8 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};
|
||||
static inline scc_x86_operand_value_t scc_x86_op_preg(scc_x86_reg_t reg,
|
||||
u8 size) {
|
||||
scc_x86_operand_value_t o = {
|
||||
.kind = SCC_X86_OPR_REG,
|
||||
.reg = reg,
|
||||
.size = size,
|
||||
};
|
||||
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) {
|
||||
static inline scc_x86_operand_value_t scc_x86_op_vreg(int vreg, u8 size) {
|
||||
scc_x86_operand_value_t o = {
|
||||
.kind = SCC_X86_OPR_REG,
|
||||
.reg = scc_x86_op_vreg_reg(vreg),
|
||||
.size = size,
|
||||
};
|
||||
return o;
|
||||
}
|
||||
static inline scc_x86_operand_value_t scc_x86_op_relbr(i32 rel) {
|
||||
scc_x86_operand_value_t o = {.kind = SCC_X86_OPR_RELBR, .brdisp = rel};
|
||||
scc_x86_operand_value_t o = {
|
||||
.kind = SCC_X86_OPR_RELBR,
|
||||
.brdisp = rel,
|
||||
.size = 4,
|
||||
};
|
||||
return o;
|
||||
}
|
||||
static inline scc_x86_operand_value_t scc_x86_op_imm(i64 imm) {
|
||||
scc_x86_operand_value_t o = {.kind = SCC_X86_OPR_IMM, .simm0 = imm};
|
||||
static inline scc_x86_operand_value_t scc_x86_op_imm(i64 imm, u8 size) {
|
||||
scc_x86_operand_value_t o = {
|
||||
.kind = SCC_X86_OPR_IMM,
|
||||
.simm0 = imm,
|
||||
.size = size,
|
||||
};
|
||||
return o;
|
||||
}
|
||||
static inline scc_x86_operand_value_t scc_x86_op_mem(scc_x86_mem_t mem) {
|
||||
scc_x86_operand_value_t o = {.kind = SCC_X86_OPR_MEM, .mem = mem};
|
||||
static inline scc_x86_operand_value_t scc_x86_op_mem(scc_x86_mem_t mem,
|
||||
u8 size) {
|
||||
scc_x86_operand_value_t o = {
|
||||
.kind = SCC_X86_OPR_MEM,
|
||||
.mem = mem,
|
||||
.size = size,
|
||||
};
|
||||
return o;
|
||||
}
|
||||
|
||||
@@ -83,6 +102,7 @@ scc_x86_op_reloc_global_imm(const char *sym, i64 addend) {
|
||||
op.reloc.target = SCC_X86_RELOC_TARGET_SYMBOL;
|
||||
op.reloc.global_name = sym;
|
||||
op.reloc.addend = addend;
|
||||
op.size = 0;
|
||||
return op;
|
||||
}
|
||||
|
||||
@@ -93,6 +113,7 @@ scc_x86_op_reloc_global_relrip(const char *sym, i64 addend) {
|
||||
op.reloc.target = SCC_X86_RELOC_TARGET_SYMBOL;
|
||||
op.reloc.global_name = sym;
|
||||
op.reloc.addend = addend;
|
||||
op.size = 4;
|
||||
return op;
|
||||
}
|
||||
|
||||
@@ -104,6 +125,7 @@ scc_x86_op_reloc_global_relbr(const char *sym, i64 addend) {
|
||||
op.reloc.target = SCC_X86_RELOC_TARGET_SYMBOL;
|
||||
op.reloc.global_name = sym;
|
||||
op.reloc.addend = addend;
|
||||
op.size = 4;
|
||||
return op;
|
||||
}
|
||||
|
||||
@@ -115,6 +137,7 @@ static inline scc_x86_operand_value_t scc_x86_op_reloc_block(int bid,
|
||||
op.reloc.target = SCC_X86_RELOC_TARGET_BBLOCK;
|
||||
op.reloc.bblock_id = bid;
|
||||
op.reloc.addend = addend;
|
||||
op.size = 4;
|
||||
return op;
|
||||
}
|
||||
|
||||
@@ -128,11 +151,15 @@ scc_x86_op_reloc_global_mem(const char *sym, i64 addend) {
|
||||
op.reloc.global_name = sym;
|
||||
op.reloc.addend = addend;
|
||||
// 编码时需生成 RIP 相对寻址的 ModRM/SIB
|
||||
op.size = 0;
|
||||
return op;
|
||||
}
|
||||
|
||||
/* 按 iform 发射一条指令,ops 数组长度需与 iform 定义的操作数数目一致 */
|
||||
int scc_x86_encode_inst(scc_mcode_t *mcode, scc_x86_iform_t iform,
|
||||
const scc_x86_operand_value_t *ops);
|
||||
scc_x86_iform_t scc_x86_iclass_to_iform(scc_x86_iclass_t iclass,
|
||||
const scc_x86_operand_value_t *ops,
|
||||
int num_ops);
|
||||
|
||||
#endif /* __SCC_X86_ENCODE_H__ */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user