feat: 增强 LoadConstGenerator 功能并优化代码结构

- 优化类注释,明确类的功能和额外支持的特性
- 重构 generate 方法,提高代码可读性和维护性- 增加对字符串常量的处理,支持 syscall 降级场景
- 完善类型前缀处理,增加 'R' 前缀用于字符串常量
This commit is contained in:
Luke 2025-07-21 17:09:26 +08:00
parent 3aef7cd906
commit 6a339149f1

View File

@ -10,16 +10,18 @@ import org.jcnc.snow.compiler.ir.value.IRVirtualRegister;
import java.util.Map; import java.util.Map;
/** /**
* 常量加载指令生成器 * <b>LoadConstGenerator - IR {@code LoadConstInstruction} 生成 VM 指令</b>
* 该类用于生成将常量加载到虚拟机寄存器的指令包括 PUSH 常量值和 STORE 到指定槽位 *
* 并为每个槽位设置正确的类型前缀 'I', 'L', 'F' * <p>
* 本类负责将 IR 层的常量加载指令 {@link LoadConstInstruction} 转换为对应的虚拟机指令
* 额外支持如果常量类型为 {@code String}会同步登记到
* {@link CallGenerator} 的字符串常量池方便 syscall 降级场景使用
* </p>
*/ */
public class LoadConstGenerator implements InstructionGenerator<LoadConstInstruction> { public class LoadConstGenerator implements InstructionGenerator<LoadConstInstruction> {
/** /**
* 返回本生成器支持的指令类型 LoadConstInstruction * 指定本生成器支持的 IR 指令类型LoadConstInstruction
*
* @return 支持的指令类型的 Class 对象
*/ */
@Override @Override
public Class<LoadConstInstruction> supportedClass() { public Class<LoadConstInstruction> supportedClass() {
@ -27,49 +29,49 @@ public class LoadConstGenerator implements InstructionGenerator<LoadConstInstruc
} }
/** /**
* 生成一条常量加载指令的目标虚拟机代码 * 生成 VM 指令主流程
* *
* @param ins 当前要生成的 LoadConstInstruction 指令 * @param ins 当前常量加载指令
* @param out VMProgramBuilder用于输出生成的虚拟机指令 * @param out 指令输出构建器
* @param slotMap IR 虚拟寄存器到实际槽位编号的映射表 * @param slotMap 虚拟寄存器与物理槽位映射
* @param currentFn 当前函数名如有需要可使用 * @param currentFn 当前函数名
*/ */
@Override @Override
public void generate(LoadConstInstruction ins, public void generate(LoadConstInstruction ins,
VMProgramBuilder out, VMProgramBuilder out,
Map<IRVirtualRegister, Integer> slotMap, Map<IRVirtualRegister, Integer> slotMap,
String currentFn) { String currentFn) {
// 1. 获取常量值第一个操作数必为常量
/* 1. 获取常量值 */
IRConstant constant = (IRConstant) ins.operands().getFirst(); IRConstant constant = (IRConstant) ins.operands().getFirst();
Object value = constant.value(); Object value = constant.value();
// 2. 生成 PUSH 指令将常量值推入操作数栈 /* 2. 生成 PUSH 指令,将常量值入栈 */
// 通过 OpHelper 辅助方法获取合适的数据类型前缀 out.emit(OpHelper.pushOpcodeFor(value) + " " + value);
String pushOp = OpHelper.pushOpcodeFor(value);
out.emit(pushOp + " " + value);
// 3. 生成 STORE 指令将栈顶的值存入对应槽位寄存器 /* 3. STORE 到目标槽位 */
// 同样通过 OpHelper 获取对应类型的 STORE 指令
String storeOp = OpHelper.storeOpcodeFor(value);
// 获取目标虚拟寄存器对应的槽位编号
int slot = slotMap.get(ins.dest()); int slot = slotMap.get(ins.dest());
out.emit(storeOp + " " + slot); out.emit(OpHelper.storeOpcodeFor(value) + " " + slot);
// 4. 根据常量的 Java 类型为槽位设置正确的前缀字符 /* 4. 标记槽位数据类型(用于后续类型推断和 LOAD/STORE 指令选择) */
// 这样在后续类型检查/运行时可用常见前缀如 'I', 'L', 'F', 'D', 'S', 'B'
char prefix = switch (value) { char prefix = switch (value) {
case Integer _ -> 'I'; // 整型 case Integer _ -> 'I'; // 整型
case Long _ -> 'L'; // 长整型 case Long _ -> 'L'; // 长整型
case Short _ -> 'S'; // 短整型 case Short _ -> 'S'; // 短整型
case Byte _ -> 'B'; // 字节型 case Byte _ -> 'B'; // 字节型
case Double _ -> 'D'; // 双精度浮点型 case Double _ -> 'D'; // 双精度
case Float _ -> 'F'; // 单精度浮点型 case Float _ -> 'F'; // 单精度
case Boolean _ -> 'I'; // 布尔作为 0/1 整型存储 case Boolean _ -> 'I'; // 布尔类型用 I 处理
case null, default -> case String _ -> 'R'; // 字符串常量
throw new IllegalStateException("Unknown const type: " + (value != null ? value.getClass() : null)); case null, default -> // 其它类型异常
throw new IllegalStateException("未知的常量类型: "
+ (value != null ? value.getClass() : null));
}; };
// 写入槽位类型映射表
out.setSlotType(slot, prefix); out.setSlotType(slot, prefix);
/* 5. 如果是字符串常量,则登记到 CallGenerator 的常量池,便于 syscall 字符串降级使用 */
if (value instanceof String s) {
CallGenerator.registerStringConst(ins.dest().id(), s);
}
} }
} }