diff --git a/src/main/java/org/jcnc/snow/compiler/backend/generator/CmpJumpGenerator.java b/src/main/java/org/jcnc/snow/compiler/backend/generator/CmpJumpGenerator.java index 0f10d64..96cfaa7 100644 --- a/src/main/java/org/jcnc/snow/compiler/backend/generator/CmpJumpGenerator.java +++ b/src/main/java/org/jcnc/snow/compiler/backend/generator/CmpJumpGenerator.java @@ -10,18 +10,26 @@ import org.jcnc.snow.compiler.ir.value.IRVirtualRegister; import java.util.Map; /** - * 条件比较跳转指令生成器 + * 条件比较跳转指令生成器 *

- * 该类实现了 {@link InstructionGenerator} 接口,用于将 IR 中的条件比较跳转指令 - * 转换为虚拟机可执行的指令序列。主要流程是先将比较操作数加载到虚拟机栈中,生成比较操作码, - * 并发出跳转到目标标签的指令。 + * 该类实现了 {@link InstructionGenerator} 接口, + * 负责将 IR 中的 {@link IRCompareJumpInstruction}(条件比较并跳转指令) + * 转换为目标虚拟机(VM)可执行的指令序列。 + *

+ * + * 主要功能 + * */ public class CmpJumpGenerator implements InstructionGenerator { /** - * 返回该生成器所支持的指令类型。 + * 返回本生成器支持的 IR 指令类型。 * - * @return {@link IRCompareJumpInstruction} 的类对象 + * @return IRCompareJumpInstruction 的类对象 */ @Override public Class supportedClass() { @@ -29,7 +37,19 @@ public class CmpJumpGenerator implements InstructionGenerator类型宽度优先级:D > F > L > I > S > B + *
    + *
  • D(double):6
  • + *
  • F(float):5
  • + *
  • L(long):4
  • + *
  • I(int):3
  • + *
  • S(short):2
  • + *
  • B(byte):1
  • + *
  • 未识别类型:0
  • + *
+ * + * @param p 类型标记字符 + * @return 优先级数值(越大类型越宽) */ private static int rank(char p) { return switch (p) { @@ -39,27 +59,40 @@ public class CmpJumpGenerator implements InstructionGenerator 3; case 'S' -> 2; case 'B' -> 1; - default -> 0; + default -> 0; }; } /** - * 返回优先级更高的类型字符 + * 返回更“宽”的公共类型(即优先级高的类型)。 + * + * @param a 类型标记字符 1 + * @param b 类型标记字符 2 + * @return 宽度更高的类型标记字符 */ private static char promote(char a, char b) { return rank(a) >= rank(b) ? a : b; } /** - * 单字符转字符串 + * 单字符类型标记转字符串。 + * + * @param p 类型标记字符 + * @return 类型字符串 */ private static String str(char p) { return String.valueOf(p); } /** - * 获取从类型 {@code from} 到 {@code to} 的转换指令名。 - * 相同类型或无显式转换需求返回 {@code null}。 + * 获取 {@code from → to} 的类型转换指令名(如不需转换则返回 {@code null})。 + *

+ * 仅覆盖目前常见的整数与浮点类型提升与转换,后续有新类型可补充。 + *

+ * + * @param from 源类型标记字符 + * @param to 目标类型标记字符 + * @return 转换指令名,如“L2I”;无转换返回 {@code null} */ private static String convert(char from, char to) { if (from == to) return null; @@ -78,46 +111,64 @@ public class CmpJumpGenerator implements InstructionGenerator "D2F"; case "SI" -> "S2I"; case "BI" -> "B2I"; - default -> null; + default -> null; }; } /** - * 生成条件比较跳转相关的虚拟机指令。 + * 生成 IR 条件比较跳转指令的 VM 指令序列。 + *
    + *
  1. 确定左右操作数的槽位及静态类型
  2. + *
  3. 加载并按需类型提升转换
  4. + *
  5. 根据公共类型调整比较指令前缀
  6. + *
  7. 发出最终比较和跳转指令
  8. + *
* - * @param ins 需要生成的条件比较跳转中间指令(IR) - * @param out 虚拟机程序构建器,用于输出生成的指令 - * @param slotMap 虚拟寄存器到实际槽(slot)编号的映射表 - * @param currentFn 当前处理的函数名(可用于调试或作用域标识) + * @param ins IR 条件比较跳转指令 + * @param out VMProgramBuilder:用于发出 VM 指令 + * @param slotMap 虚拟寄存器到 VM 槽位的映射表 + * @param currentFn 当前处理的函数名(调试用,当前未使用) */ @Override - public void generate(IRCompareJumpInstruction ins, - VMProgramBuilder out, - Map slotMap, - String currentFn) { - // 获取左操作数所在的寄存器槽编号 - int leftSlot = slotMap.get(ins.left()); - // 获取右操作数所在的寄存器槽编号 - int rightSlot = slotMap.get(ins.right()); + public void generate(IRCompareJumpInstruction ins, + VMProgramBuilder out, + Map slotMap, + String currentFn) { - char lType = out.getSlotType(leftSlot); // 未登记默认 'I' - char rType = out.getSlotType(rightSlot); + // 1. 获取左右操作数的槽位与静态类型 + int leftSlot = slotMap.get(ins.left()); + int rightSlot = slotMap.get(ins.right()); + char lType = out.getSlotType(leftSlot); // 若未登记则默认 'I' + char rType = out.getSlotType(rightSlot); + char tType = promote(lType, rType); // 公共类型提升 - char tType = promote(lType, rType); // 类型提升结果 - - // 加载左操作数到虚拟机栈 + // 2. 加载左右操作数并按需类型转换 + // 左操作数 out.emit(OpHelper.opcode(str(lType) + "_LOAD") + " " + leftSlot); String cvt = convert(lType, tType); - if (cvt != null) out.emit(OpHelper.opcode(cvt)); + if (cvt != null) { + out.emit(OpHelper.opcode(cvt)); + } - // 加载右操作数到虚拟机栈 + // 右操作数 out.emit(OpHelper.opcode(str(rType) + "_LOAD") + " " + rightSlot); cvt = convert(rType, tType); - if (cvt != null) out.emit(OpHelper.opcode(cvt)); + if (cvt != null) { + out.emit(OpHelper.opcode(cvt)); + } - // 获取与当前比较操作对应的虚拟机操作码 + // 3. 选择正确的比较指令前缀 String cmpOp = IROpCodeMapper.toVMOp(ins.op()); - // 生成分支跳转指令,如果比较成立则跳转到目标标签 + /* + * 修正指令前缀(如 int 类型要用 IC_*, long 类型要用 LC_*) + */ + if (tType == 'I' && cmpOp.startsWith("LC_")) { + cmpOp = "IC_" + cmpOp.substring(3); + } else if (tType == 'L' && cmpOp.startsWith("IC_")) { + cmpOp = "LC_" + cmpOp.substring(3); + } + + // 4. 发出比较与跳转指令 out.emitBranch(OpHelper.opcode(cmpOp), ins.label()); } }