refactor: 重复的类型提升逻辑提取到 TypePromoteUtils 工具类

This commit is contained in:
zhangxun 2025-07-10 17:31:44 +08:00
parent 609e380664
commit e66a5a3078
3 changed files with 122 additions and 145 deletions

View File

@ -4,6 +4,7 @@ import org.jcnc.snow.compiler.backend.builder.VMProgramBuilder;
import org.jcnc.snow.compiler.backend.core.InstructionGenerator;
import org.jcnc.snow.compiler.backend.utils.IROpCodeMapper;
import org.jcnc.snow.compiler.backend.utils.OpHelper;
import org.jcnc.snow.compiler.backend.utils.TypePromoteUtils;
import org.jcnc.snow.compiler.ir.core.IRValue;
import org.jcnc.snow.compiler.ir.instruction.BinaryOperationInstruction;
import org.jcnc.snow.compiler.ir.value.IRConstant;
@ -41,38 +42,12 @@ public class BinaryOpGenerator implements InstructionGenerator<BinaryOperationIn
return fn + "$" + tag + "$" + COUNTER.getAndIncrement();
}
/**
* 类型优先级D &gt; F &gt; L &gt; I &gt; S &gt; B
*/
private static int rank(char p) {
return switch (p) {
case 'D' -> 6;
case 'F' -> 5;
case 'L' -> 4;
case 'I' -> 3;
case 'S' -> 2;
case 'B' -> 1;
default -> 0;
};
}
/**
* 返回优先级更高的类型字符
*/
private static char promote(char a, char b) {
return rank(a) >= rank(b) ? a : b;
}
/**
* 单字符转字符串
*/
private static String str(char p) {
return String.valueOf(p);
}
/**
* 判断常量值是否等于 0
* 仅支持 Java 原生数值类型
*
* @param v 常量值
* @return 等于 0 返回 true否则 false
*/
private static boolean isZero(Object v) {
if (v == null) return false;
@ -87,31 +62,6 @@ public class BinaryOpGenerator implements InstructionGenerator<BinaryOperationIn
};
}
/**
* 获取从类型 {@code from} {@code to} 的转换指令名
* 相同类型或无显式转换需求返回 {@code null}
*/
private static String convert(char from, char to) {
if (from == to) return null;
return switch ("" + from + to) {
case "IL" -> "I2L";
case "ID" -> "I2D";
case "IF" -> "I2F";
case "LI" -> "L2I";
case "LD" -> "L2D";
case "LF" -> "L2F";
case "FI" -> "F2I";
case "FL" -> "F2L";
case "FD" -> "F2D";
case "DI" -> "D2I";
case "DL" -> "D2L";
case "DF" -> "D2F";
case "SI" -> "S2I";
case "BI" -> "B2I";
default -> null;
};
}
/* -------------------- 接口实现 -------------------- */
@Override
@ -161,16 +111,16 @@ public class BinaryOpGenerator implements InstructionGenerator<BinaryOperationIn
char lType = out.getSlotType(lSlot); // 未登记默认 'I'
char rType = out.getSlotType(rSlot);
char tType = promote(lType, rType); // 类型提升结果
String tPre = str(tType);
char tType = TypePromoteUtils.promote(lType, rType); // 类型提升结果
String tPre = TypePromoteUtils.str(tType);
/* ---------- 2. 加载并做类型转换 ---------- */
out.emit(OpHelper.opcode(str(lType) + "_LOAD") + " " + lSlot);
String cvt = convert(lType, tType);
out.emit(OpHelper.opcode(TypePromoteUtils.str(lType) + "_LOAD") + " " + lSlot);
String cvt = TypePromoteUtils.convert(lType, tType);
if (cvt != null) out.emit(OpHelper.opcode(cvt));
out.emit(OpHelper.opcode(str(rType) + "_LOAD") + " " + rSlot);
cvt = convert(rType, tType);
out.emit(OpHelper.opcode(TypePromoteUtils.str(rType) + "_LOAD") + " " + rSlot);
cvt = TypePromoteUtils.convert(rType, tType);
if (cvt != null) out.emit(OpHelper.opcode(cvt));
/* ---------- 3. 区分算术 / 比较 ---------- */
@ -186,7 +136,7 @@ public class BinaryOpGenerator implements InstructionGenerator<BinaryOperationIn
}
/* === 3-B. CMP_* —— 生成布尔结果 === */
String branchOp = OpHelper.opcode(IROpCodeMapper.toVMOp(ins.op())); // IC_E / IC_NE
String branchOp = OpHelper.opcode(IROpCodeMapper.toVMOp(ins.op())); // I_CE / I_CNE
String lblTrue = fresh(currentFn, "true");
String lblEnd = fresh(currentFn, "end");

View File

@ -4,6 +4,7 @@ import org.jcnc.snow.compiler.backend.utils.IROpCodeMapper;
import org.jcnc.snow.compiler.backend.utils.OpHelper;
import org.jcnc.snow.compiler.backend.builder.VMProgramBuilder;
import org.jcnc.snow.compiler.backend.core.InstructionGenerator;
import org.jcnc.snow.compiler.backend.utils.TypePromoteUtils;
import org.jcnc.snow.compiler.ir.instruction.IRCompareJumpInstruction;
import org.jcnc.snow.compiler.ir.value.IRVirtualRegister;
@ -36,85 +37,6 @@ public class CmpJumpGenerator implements InstructionGenerator<IRCompareJumpInstr
return IRCompareJumpInstruction.class;
}
/**
* <b>类型宽度优先级</b>D > F > L > I > S > B
* <ul>
* <li>Ddouble6</li>
* <li>Ffloat5</li>
* <li>Llong4</li>
* <li>Iint3</li>
* <li>Sshort2</li>
* <li>Bbyte1</li>
* <li>未识别类型0</li>
* </ul>
*
* @param p 类型标记字符
* @return 优先级数值越大类型越宽
*/
private static int rank(char p) {
return switch (p) {
case 'D' -> 6;
case 'F' -> 5;
case 'L' -> 4;
case 'I' -> 3;
case 'S' -> 2;
case 'B' -> 1;
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 to} 的类型转换指令名如不需转换则返回 {@code null}
* <p>
* 仅覆盖目前常见的整数与浮点类型提升与转换后续有新类型可补充
* </p>
*
* @param from 源类型标记字符
* @param to 目标类型标记字符
* @return 转换指令名L2I无转换返回 {@code null}
*/
private static String convert(char from, char to) {
if (from == to) return null;
return switch ("" + from + to) {
case "IL" -> "I2L";
case "ID" -> "I2D";
case "IF" -> "I2F";
case "LI" -> "L2I";
case "LD" -> "L2D";
case "LF" -> "L2F";
case "FI" -> "F2I";
case "FL" -> "F2L";
case "FD" -> "F2D";
case "DI" -> "D2I";
case "DL" -> "D2L";
case "DF" -> "D2F";
case "SI" -> "S2I";
case "BI" -> "B2I";
default -> null;
};
}
/**
* 生成 IR 条件比较跳转指令的 VM 指令序列
* <ol>
@ -140,19 +62,19 @@ public class CmpJumpGenerator implements InstructionGenerator<IRCompareJumpInstr
int rightSlot = slotMap.get(ins.right());
char lType = out.getSlotType(leftSlot); // 若未登记则默认 'I'
char rType = out.getSlotType(rightSlot);
char tType = promote(lType, rType); // 公共类型提升
char tType = TypePromoteUtils.promote(lType, rType); // 公共类型提升
// 2. 加载左右操作数并按需类型转换
// 左操作数
out.emit(OpHelper.opcode(str(lType) + "_LOAD") + " " + leftSlot);
String cvt = convert(lType, tType);
out.emit(OpHelper.opcode(TypePromoteUtils.str(lType) + "_LOAD") + " " + leftSlot);
String cvt = TypePromoteUtils.convert(lType, tType);
if (cvt != null) {
out.emit(OpHelper.opcode(cvt));
}
// 右操作数
out.emit(OpHelper.opcode(str(rType) + "_LOAD") + " " + rightSlot);
cvt = convert(rType, tType);
out.emit(OpHelper.opcode(TypePromoteUtils.str(rType) + "_LOAD") + " " + rightSlot);
cvt = TypePromoteUtils.convert(rType, tType);
if (cvt != null) {
out.emit(OpHelper.opcode(cvt));
}

View File

@ -0,0 +1,105 @@
package org.jcnc.snow.compiler.backend.utils;
/**
* 基本数值类型提升工具
* 类型优先级低的类型转为优先级高的类型去参与比较计算等等,
* 比如 int + long那么结果的类型应为 long
*/
public class TypePromoteUtils {
/**
* <b>类型宽度优先级</b>D > F > L > I > S > B
* <ul>
* <li>Ddouble6</li>
* <li>Ffloat5</li>
* <li>Llong4</li>
* <li>Iint3</li>
* <li>Sshort2</li>
* <li>Bbyte1</li>
* <li>未识别类型0</li>
* </ul>
*
* @param p 类型标记字符
* @return 优先级数值越大类型越宽
*/
private static int rank(char p) {
return switch (p) {
case 'D' -> 6;
case 'F' -> 5;
case 'L' -> 4;
case 'I' -> 3;
case 'S' -> 2;
case 'B' -> 1;
default -> 0;
};
}
/**
* 返回更的公共类型即优先级高的类型
*
* @param a 类型标记字符 1
* @param b 类型标记字符 2
* @return 宽度更高的类型标记字符
*/
public static char promote(char a, char b) {
return rank(a) >= rank(b) ? a : b;
}
/**
* 单字符类型标记转字符串
*
* @param p 类型标记字符
* @return 类型字符串
*/
public static String str(char p) {
return String.valueOf(p);
}
/**
* 获取 {@code from to} 的类型转换指令名如不需转换则返回 {@code null}
*
* @param from 源类型标记字符
* @param to 目标类型标记字符
* @return 转换指令名L2I无转换返回 {@code null}
*/
public static String convert(char from, char to) {
if (from == to) return null;
return switch ("" + from + to) {
case "BS" -> "B2S";
case "BI" -> "B2I";
case "BL" -> "B2L";
case "BF" -> "B2F";
case "BD" -> "B2D";
case "SB" -> "S2B";
case "SI" -> "S2I";
case "SL" -> "S2L";
case "SF" -> "S2F";
case "SD" -> "S2D";
case "IB" -> "I2B";
case "IS" -> "I2S";
case "IL" -> "I2L";
case "IF" -> "I2F";
case "ID" -> "I2D";
case "LB" -> "L2B";
case "LS" -> "L2S";
case "LI" -> "L2I";
case "LF" -> "L2F";
case "LD" -> "L2D";
case "FB" -> "F2B";
case "FS" -> "F2S";
case "FI" -> "F2I";
case "FL" -> "F2L";
case "FD" -> "F2D";
case "DB" -> "D2B";
case "DS" -> "D2S";
case "DI" -> "D2I";
case "DL" -> "D2L";
case "DF" -> "D2F";
default -> null;
};
}
}