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.core.InstructionGenerator;
|
||||||
import org.jcnc.snow.compiler.backend.utils.IROpCodeMapper;
|
import org.jcnc.snow.compiler.backend.utils.IROpCodeMapper;
|
||||||
import org.jcnc.snow.compiler.backend.utils.OpHelper;
|
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.core.IRValue;
|
||||||
import org.jcnc.snow.compiler.ir.instruction.BinaryOperationInstruction;
|
import org.jcnc.snow.compiler.ir.instruction.BinaryOperationInstruction;
|
||||||
import org.jcnc.snow.compiler.ir.value.IRConstant;
|
import org.jcnc.snow.compiler.ir.value.IRConstant;
|
||||||
@ -41,38 +42,12 @@ public class BinaryOpGenerator implements InstructionGenerator<BinaryOperationIn
|
|||||||
return fn + "$" + tag + "$" + COUNTER.getAndIncrement();
|
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。
|
* 判断常量值是否等于 0。
|
||||||
* 仅支持 Java 原生数值类型。
|
* 仅支持 Java 原生数值类型。
|
||||||
|
*
|
||||||
|
* @param v 常量值
|
||||||
|
* @return 等于 0 返回 true,否则 false
|
||||||
*/
|
*/
|
||||||
private static boolean isZero(Object v) {
|
private static boolean isZero(Object v) {
|
||||||
if (v == null) return false;
|
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
|
@Override
|
||||||
@ -161,16 +111,16 @@ public class BinaryOpGenerator implements InstructionGenerator<BinaryOperationIn
|
|||||||
char lType = out.getSlotType(lSlot); // 未登记默认 'I'
|
char lType = out.getSlotType(lSlot); // 未登记默认 'I'
|
||||||
char rType = out.getSlotType(rSlot);
|
char rType = out.getSlotType(rSlot);
|
||||||
|
|
||||||
char tType = promote(lType, rType); // 类型提升结果
|
char tType = TypePromoteUtils.promote(lType, rType); // 类型提升结果
|
||||||
String tPre = str(tType);
|
String tPre = TypePromoteUtils.str(tType);
|
||||||
|
|
||||||
/* ---------- 2. 加载并做类型转换 ---------- */
|
/* ---------- 2. 加载并做类型转换 ---------- */
|
||||||
out.emit(OpHelper.opcode(str(lType) + "_LOAD") + " " + lSlot);
|
out.emit(OpHelper.opcode(TypePromoteUtils.str(lType) + "_LOAD") + " " + lSlot);
|
||||||
String cvt = convert(lType, tType);
|
String cvt = TypePromoteUtils.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") + " " + rSlot);
|
out.emit(OpHelper.opcode(TypePromoteUtils.str(rType) + "_LOAD") + " " + rSlot);
|
||||||
cvt = convert(rType, tType);
|
cvt = TypePromoteUtils.convert(rType, tType);
|
||||||
if (cvt != null) out.emit(OpHelper.opcode(cvt));
|
if (cvt != null) out.emit(OpHelper.opcode(cvt));
|
||||||
|
|
||||||
/* ---------- 3. 区分算术 / 比较 ---------- */
|
/* ---------- 3. 区分算术 / 比较 ---------- */
|
||||||
@ -186,7 +136,7 @@ public class BinaryOpGenerator implements InstructionGenerator<BinaryOperationIn
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* === 3-B. CMP_* —— 生成布尔结果 === */
|
/* === 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 lblTrue = fresh(currentFn, "true");
|
||||||
String lblEnd = fresh(currentFn, "end");
|
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.utils.OpHelper;
|
||||||
import org.jcnc.snow.compiler.backend.builder.VMProgramBuilder;
|
import org.jcnc.snow.compiler.backend.builder.VMProgramBuilder;
|
||||||
import org.jcnc.snow.compiler.backend.core.InstructionGenerator;
|
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.instruction.IRCompareJumpInstruction;
|
||||||
import org.jcnc.snow.compiler.ir.value.IRVirtualRegister;
|
import org.jcnc.snow.compiler.ir.value.IRVirtualRegister;
|
||||||
|
|
||||||
@ -36,85 +37,6 @@ public class CmpJumpGenerator implements InstructionGenerator<IRCompareJumpInstr
|
|||||||
return IRCompareJumpInstruction.class;
|
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 指令序列。
|
* 生成 IR 条件比较跳转指令的 VM 指令序列。
|
||||||
* <ol>
|
* <ol>
|
||||||
@ -140,19 +62,19 @@ public class CmpJumpGenerator implements InstructionGenerator<IRCompareJumpInstr
|
|||||||
int rightSlot = slotMap.get(ins.right());
|
int rightSlot = slotMap.get(ins.right());
|
||||||
char lType = out.getSlotType(leftSlot); // 若未登记则默认 'I'
|
char lType = out.getSlotType(leftSlot); // 若未登记则默认 'I'
|
||||||
char rType = out.getSlotType(rightSlot);
|
char rType = out.getSlotType(rightSlot);
|
||||||
char tType = promote(lType, rType); // 公共类型提升
|
char tType = TypePromoteUtils.promote(lType, rType); // 公共类型提升
|
||||||
|
|
||||||
// 2. 加载左右操作数并按需类型转换
|
// 2. 加载左右操作数并按需类型转换
|
||||||
// 左操作数
|
// 左操作数
|
||||||
out.emit(OpHelper.opcode(str(lType) + "_LOAD") + " " + leftSlot);
|
out.emit(OpHelper.opcode(TypePromoteUtils.str(lType) + "_LOAD") + " " + leftSlot);
|
||||||
String cvt = convert(lType, tType);
|
String cvt = TypePromoteUtils.convert(lType, tType);
|
||||||
if (cvt != null) {
|
if (cvt != null) {
|
||||||
out.emit(OpHelper.opcode(cvt));
|
out.emit(OpHelper.opcode(cvt));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 右操作数
|
// 右操作数
|
||||||
out.emit(OpHelper.opcode(str(rType) + "_LOAD") + " " + rightSlot);
|
out.emit(OpHelper.opcode(TypePromoteUtils.str(rType) + "_LOAD") + " " + rightSlot);
|
||||||
cvt = convert(rType, tType);
|
cvt = TypePromoteUtils.convert(rType, tType);
|
||||||
if (cvt != null) {
|
if (cvt != null) {
|
||||||
out.emit(OpHelper.opcode(cvt));
|
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