fix:更正 int 与 long 操作数的比较跳转前缀
This commit is contained in:
parent
c7a953995a
commit
db80395159
@ -10,18 +10,26 @@ import org.jcnc.snow.compiler.ir.value.IRVirtualRegister;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 条件比较跳转指令生成器
|
* <b>条件比较跳转指令生成器</b>
|
||||||
* <p>
|
* <p>
|
||||||
* 该类实现了 {@link InstructionGenerator} 接口,用于将 IR 中的条件比较跳转指令
|
* 该类实现了 {@link InstructionGenerator} 接口,
|
||||||
* 转换为虚拟机可执行的指令序列。主要流程是先将比较操作数加载到虚拟机栈中,生成比较操作码,
|
* 负责将 IR 中的 {@link IRCompareJumpInstruction}(条件比较并跳转指令)
|
||||||
* 并发出跳转到目标标签的指令。
|
* 转换为目标虚拟机(VM)可执行的指令序列。
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <b>主要功能</b>
|
||||||
|
* <ul>
|
||||||
|
* <li>根据 IR 比较指令左右操作数的类型,自动进行类型提升与转换</li>
|
||||||
|
* <li>生成相应的 VM 加载、类型转换、比较与跳转指令</li>
|
||||||
|
* <li>保证指令的类型前缀与操作数类型一致,提升兼容性与正确性</li>
|
||||||
|
* </ul>
|
||||||
*/
|
*/
|
||||||
public class CmpJumpGenerator implements InstructionGenerator<IRCompareJumpInstruction> {
|
public class CmpJumpGenerator implements InstructionGenerator<IRCompareJumpInstruction> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 返回该生成器所支持的指令类型。
|
* 返回本生成器支持的 IR 指令类型。
|
||||||
*
|
*
|
||||||
* @return {@link IRCompareJumpInstruction} 的类对象
|
* @return IRCompareJumpInstruction 的类对象
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Class<IRCompareJumpInstruction> supportedClass() {
|
public Class<IRCompareJumpInstruction> supportedClass() {
|
||||||
@ -29,7 +37,19 @@ public class CmpJumpGenerator implements InstructionGenerator<IRCompareJumpInstr
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 类型优先级:D > F > L > I > S > B
|
* <b>类型宽度优先级</b>:D > F > L > I > S > B
|
||||||
|
* <ul>
|
||||||
|
* <li>D(double):6</li>
|
||||||
|
* <li>F(float):5</li>
|
||||||
|
* <li>L(long):4</li>
|
||||||
|
* <li>I(int):3</li>
|
||||||
|
* <li>S(short):2</li>
|
||||||
|
* <li>B(byte):1</li>
|
||||||
|
* <li>未识别类型:0</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @param p 类型标记字符
|
||||||
|
* @return 优先级数值(越大类型越宽)
|
||||||
*/
|
*/
|
||||||
private static int rank(char p) {
|
private static int rank(char p) {
|
||||||
return switch (p) {
|
return switch (p) {
|
||||||
@ -39,27 +59,40 @@ public class CmpJumpGenerator implements InstructionGenerator<IRCompareJumpInstr
|
|||||||
case 'I' -> 3;
|
case 'I' -> 3;
|
||||||
case 'S' -> 2;
|
case 'S' -> 2;
|
||||||
case 'B' -> 1;
|
case 'B' -> 1;
|
||||||
default -> 0;
|
default -> 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 返回优先级更高的类型字符
|
* 返回更“宽”的公共类型(即优先级高的类型)。
|
||||||
|
*
|
||||||
|
* @param a 类型标记字符 1
|
||||||
|
* @param b 类型标记字符 2
|
||||||
|
* @return 宽度更高的类型标记字符
|
||||||
*/
|
*/
|
||||||
private static char promote(char a, char b) {
|
private static char promote(char a, char b) {
|
||||||
return rank(a) >= rank(b) ? a : b;
|
return rank(a) >= rank(b) ? a : b;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 单字符转字符串
|
* 单字符类型标记转字符串。
|
||||||
|
*
|
||||||
|
* @param p 类型标记字符
|
||||||
|
* @return 类型字符串
|
||||||
*/
|
*/
|
||||||
private static String str(char p) {
|
private static String str(char p) {
|
||||||
return String.valueOf(p);
|
return String.valueOf(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取从类型 {@code from} 到 {@code to} 的转换指令名。
|
* 获取 {@code from → to} 的类型转换指令名(如不需转换则返回 {@code null})。
|
||||||
* 相同类型或无显式转换需求返回 {@code null}。
|
* <p>
|
||||||
|
* 仅覆盖目前常见的整数与浮点类型提升与转换,后续有新类型可补充。
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param from 源类型标记字符
|
||||||
|
* @param to 目标类型标记字符
|
||||||
|
* @return 转换指令名,如“L2I”;无转换返回 {@code null}
|
||||||
*/
|
*/
|
||||||
private static String convert(char from, char to) {
|
private static String convert(char from, char to) {
|
||||||
if (from == to) return null;
|
if (from == to) return null;
|
||||||
@ -78,46 +111,64 @@ public class CmpJumpGenerator implements InstructionGenerator<IRCompareJumpInstr
|
|||||||
case "DF" -> "D2F";
|
case "DF" -> "D2F";
|
||||||
case "SI" -> "S2I";
|
case "SI" -> "S2I";
|
||||||
case "BI" -> "B2I";
|
case "BI" -> "B2I";
|
||||||
default -> null;
|
default -> null;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 生成条件比较跳转相关的虚拟机指令。
|
* 生成 IR 条件比较跳转指令的 VM 指令序列。
|
||||||
|
* <ol>
|
||||||
|
* <li>确定左右操作数的槽位及静态类型</li>
|
||||||
|
* <li>加载并按需类型提升转换</li>
|
||||||
|
* <li>根据公共类型调整比较指令前缀</li>
|
||||||
|
* <li>发出最终比较和跳转指令</li>
|
||||||
|
* </ol>
|
||||||
*
|
*
|
||||||
* @param ins 需要生成的条件比较跳转中间指令(IR)
|
* @param ins IR 条件比较跳转指令
|
||||||
* @param out 虚拟机程序构建器,用于输出生成的指令
|
* @param out VMProgramBuilder:用于发出 VM 指令
|
||||||
* @param slotMap 虚拟寄存器到实际槽(slot)编号的映射表
|
* @param slotMap 虚拟寄存器到 VM 槽位的映射表
|
||||||
* @param currentFn 当前处理的函数名(可用于调试或作用域标识)
|
* @param currentFn 当前处理的函数名(调试用,当前未使用)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void generate(IRCompareJumpInstruction ins,
|
public void generate(IRCompareJumpInstruction ins,
|
||||||
VMProgramBuilder out,
|
VMProgramBuilder out,
|
||||||
Map<IRVirtualRegister, Integer> slotMap,
|
Map<IRVirtualRegister,Integer> slotMap,
|
||||||
String currentFn) {
|
String currentFn) {
|
||||||
// 获取左操作数所在的寄存器槽编号
|
|
||||||
int leftSlot = slotMap.get(ins.left());
|
|
||||||
// 获取右操作数所在的寄存器槽编号
|
|
||||||
int rightSlot = slotMap.get(ins.right());
|
|
||||||
|
|
||||||
char lType = out.getSlotType(leftSlot); // 未登记默认 'I'
|
// 1. 获取左右操作数的槽位与静态类型
|
||||||
char rType = out.getSlotType(rightSlot);
|
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);
|
out.emit(OpHelper.opcode(str(lType) + "_LOAD") + " " + leftSlot);
|
||||||
String cvt = convert(lType, tType);
|
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);
|
out.emit(OpHelper.opcode(str(rType) + "_LOAD") + " " + rightSlot);
|
||||||
cvt = convert(rType, tType);
|
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());
|
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());
|
out.emitBranch(OpHelper.opcode(cmpOp), ins.label());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user