refactor: 重复的类型提升逻辑提取到 TypePromoteUtils 工具类
This commit is contained in:
parent
609e380664
commit
e66a5a3078
@ -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 > F > L > I > S > 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");
|
||||
|
||||
|
||||
@ -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>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) {
|
||||
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));
|
||||
}
|
||||
|
||||
@ -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>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) {
|
||||
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;
|
||||
};
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user