diff --git a/src/main/java/org/jcnc/snow/compiler/backend/IROpCodeMapper.java b/src/main/java/org/jcnc/snow/compiler/backend/IROpCodeMapper.java
new file mode 100644
index 0000000..c6cb9e4
--- /dev/null
+++ b/src/main/java/org/jcnc/snow/compiler/backend/IROpCodeMapper.java
@@ -0,0 +1,70 @@
+package org.jcnc.snow.compiler.backend;
+
+import org.jcnc.snow.compiler.ir.core.IROpCode;
+
+import java.util.EnumMap;
+import java.util.Map;
+
+/**
+ * IROpCodeMapper —— IR 操作码(IROpCode)到 VM 虚拟机操作码(字符串形式)的映射器。
+ *
+ * 本类用于编译器后端阶段,将中间表示中的操作类型(如 ADD_I32)转换为
+ * 虚拟机指令集中的具体指令(如 "I_ADD"),用于代码生成输出。
+ *
+ *
+ * 注意:该类只做一一映射,不处理操作数或参数传递逻辑。
+ * 若未来有更多数据类型或扩展语义,可在此处集中管理。
+ *
+ */
+public final class IROpCodeMapper {
+
+ /** 存储映射关系的枚举映射表(使用 EnumMap 提高性能) */
+ private static final Map opcodeMap = new EnumMap<>(IROpCode.class);
+
+ // 初始化静态映射表
+ static {
+ // ───── 算术运算 ─────
+ opcodeMap.put(IROpCode.ADD_I32, "I_ADD");
+ opcodeMap.put(IROpCode.SUB_I32, "I_SUB");
+ opcodeMap.put(IROpCode.MUL_I32, "I_MUL");
+ opcodeMap.put(IROpCode.DIV_I32, "I_DIV");
+ opcodeMap.put(IROpCode.NEG_I32, "I_NEG");
+
+ // ───── 逻辑比较运算 ─────
+ opcodeMap.put(IROpCode.CMP_EQ, "IC_EQ");
+ opcodeMap.put(IROpCode.CMP_NE, "IC_NE");
+ opcodeMap.put(IROpCode.CMP_LT, "IC_L");
+ opcodeMap.put(IROpCode.CMP_GT, "IC_G");
+ opcodeMap.put(IROpCode.CMP_LE, "IC_LE");
+ opcodeMap.put(IROpCode.CMP_GE, "IC_GE");
+
+ // ───── 数据操作 ─────
+ opcodeMap.put(IROpCode.LOAD, "I_LOAD");
+ opcodeMap.put(IROpCode.STORE, "I_STORE");
+ opcodeMap.put(IROpCode.CONST, "I_PUSH");
+
+ // ───── 控制流 ─────
+ opcodeMap.put(IROpCode.JUMP, "JMP");
+ opcodeMap.put(IROpCode.JUMP_IF_ZERO, "JZ");
+ opcodeMap.put(IROpCode.LABEL, "LABEL");
+
+ // ───── 函数调用 ─────
+ opcodeMap.put(IROpCode.CALL, "CALL");
+ opcodeMap.put(IROpCode.RET, "RET");
+ }
+
+ /**
+ * 将给定的 IR 操作码转换为对应的 VM 指令名(字符串)。
+ *
+ * @param irOp IROpCode 中的操作码
+ * @return 对应的 VM opcode 字符串
+ * @throws IllegalArgumentException 若操作码未被映射
+ */
+ public static String toVMOp(IROpCode irOp) {
+ String code = opcodeMap.get(irOp);
+ if (code == null) {
+ throw new IllegalArgumentException("未映射的 IR 操作码: " + irOp);
+ }
+ return code;
+ }
+}
diff --git a/src/main/java/org/jcnc/snow/compiler/backend/RegisterAllocator.java b/src/main/java/org/jcnc/snow/compiler/backend/RegisterAllocator.java
index 970ea1e..4bd906c 100644
--- a/src/main/java/org/jcnc/snow/compiler/backend/RegisterAllocator.java
+++ b/src/main/java/org/jcnc/snow/compiler/backend/RegisterAllocator.java
@@ -1,5 +1,3 @@
-// ──────────────────────────────────────────
-// file: compiler/backend/RegisterAllocator.java
package org.jcnc.snow.compiler.backend;
import org.jcnc.snow.compiler.ir.core.IRFunction;
@@ -10,17 +8,45 @@ import org.jcnc.snow.compiler.ir.value.IRVirtualRegister;
import java.util.HashMap;
import java.util.Map;
-/** 线性扫描寄存器分配(演示级) */
+/**
+ * RegisterAllocator —— 简单的线性扫描寄存器分配器(演示级实现)。
+ *
+ * 该类用于为 IRFunction 中出现的所有虚拟寄存器(IRVirtualRegister)分配槽位编号。
+ * 每个槽位编号对应虚拟机中的局部变量位置或栈槽。
+ *
+ *
+ * 算法策略:顺序扫描所有 IR 指令,每遇到一个新的虚拟寄存器就分配一个递增编号。
+ * 不考虑寄存器生存期重叠、重用或优化,仅做简单映射。
+ *
+ */
public final class RegisterAllocator {
- private final Map map = new HashMap<>();
- public Map allocate(IRFunction fn){
- int next = 0;
- for (IRInstruction i : fn.body()){
- if(i.dest()!=null && !map.containsKey(i.dest())) map.put(i.dest(), next++);
- for(IRValue v : i.operands())
- if(v instanceof IRVirtualRegister r && !map.containsKey(r)) map.put(r, next++);
+ /** 虚拟寄存器 → 槽位编号 的映射表 */
+ private final Map map = new HashMap<>();
+
+ /**
+ * 执行寄存器分配:将函数中所有虚拟寄存器映射为连续的整型槽位编号。
+ *
+ * @param fn 中间表示形式的函数(IRFunction)
+ * @return 映射表(IRVirtualRegister → 槽位编号)
+ */
+ public Map allocate(IRFunction fn) {
+ int next = 0; // 当前可分配的下一个槽位编号
+
+ for (IRInstruction i : fn.body()) {
+ // 若该指令有目标寄存器(dest),且尚未分配槽位 → 分配一个
+ if (i.dest() != null && !map.containsKey(i.dest())) {
+ map.put(i.dest(), next++);
+ }
+
+ // 遍历指令的所有操作数(operand),若是寄存器也进行分配
+ for (IRValue v : i.operands()) {
+ if (v instanceof IRVirtualRegister r && !map.containsKey(r)) {
+ map.put(r, next++);
+ }
+ }
}
+
return map;
}
}
diff --git a/src/main/java/org/jcnc/snow/compiler/backend/VMCodeGenerator.java b/src/main/java/org/jcnc/snow/compiler/backend/VMCodeGenerator.java
index 7ec94c8..6864c59 100644
--- a/src/main/java/org/jcnc/snow/compiler/backend/VMCodeGenerator.java
+++ b/src/main/java/org/jcnc/snow/compiler/backend/VMCodeGenerator.java
@@ -8,7 +8,6 @@ import org.jcnc.snow.compiler.ir.instruction.ReturnInstruction;
import org.jcnc.snow.compiler.ir.instruction.UnaryOperationInstruction;
import org.jcnc.snow.compiler.ir.value.IRConstant;
import org.jcnc.snow.compiler.ir.value.IRVirtualRegister;
-import org.jcnc.snow.vm.engine.VMOpCode;
import java.lang.reflect.Field;
import java.util.ArrayList;
@@ -16,107 +15,143 @@ import java.util.List;
import java.util.Map;
/**
- * 将 IRFunction 转译为 SVM 指令文本。
- * 目前支持:int32 常量、+ - * /、一元 -、return。
+ * VMCodeGenerator —— 虚拟机代码生成器。
+ *
+ * 该类负责将中间表示(IRFunction)翻译为 SVM 虚拟机可执行的文本指令。
+ * 当前支持:
+ * - int32 类型的常量加载
+ * - 加减乘除(+ - * /)的二元表达式
+ * - 取负(一元 -)
+ * - 函数返回(含 main 函数终止)
+ *
+ *
+ * 每个虚拟寄存器通过 slotMap 分配一个槽位(int 索引),用于定位变量。
+ * 生成的代码是一系列字符串,格式为汇编式:OPCODE 参数...
+ *
*/
public final class VMCodeGenerator {
+ /** 虚拟寄存器 → 栈槽编号的映射表(由编译器分配) */
private final Map slotMap;
+
+ /** 存储生成的指令 */
private final List code = new ArrayList<>();
- private String currentFnName; // ← 当前正在生成的函数名
+ /** 当前正在生成代码的函数名称 */
+ private String currentFnName;
public VMCodeGenerator(Map slotMap) {
this.slotMap = slotMap;
}
/**
- * 主入口:IR → 指令序列
+ * 主入口:接收一个中间表示函数(IRFunction),输出对应的 VM 指令文本序列
+ *
+ * @param fn IRFunction,包含该函数的所有 IRInstruction
+ * @return 指令字符串列表
*/
public List generate(IRFunction fn) {
- currentFnName = fn.name(); // ← 保存函数名
+ currentFnName = fn.name();
for (IRInstruction inst : fn.body()) {
switch (inst) {
- case LoadConstInstruction c -> genLoadConst(c);
- case BinaryOperationInstruction b -> genBinOp(b);
- case UnaryOperationInstruction u -> genUnary(u);
- case ReturnInstruction r -> genRet(r);
- default -> throw new IllegalStateException("Unsupported IR: " + inst);
+ case LoadConstInstruction c -> genLoadConst(c); // 常量加载
+ case BinaryOperationInstruction b -> genBinOp(b); // 二元操作
+ case UnaryOperationInstruction u -> genUnary(u); // 一元操作
+ case ReturnInstruction r -> genRet(r); // 返回语句
+ default -> throw new IllegalStateException("不支持的 IR 指令类型: " + inst);
}
}
- /* 注意:不再额外添加 HALT,结束行为由 genRet 决定 */
+
return code;
}
- /* ───────────── 指令生成 ───────────── */
-
+ /**
+ * 生成常量加载指令:I_PUSH 常量 → I_STORE 寄存器槽位
+ */
private void genLoadConst(LoadConstInstruction c) {
- IRConstant k = (IRConstant) c.operands().get(0);
+ IRConstant k = (IRConstant) c.operands().getFirst();
emit(op("I_PUSH"), k.value().toString());
emit(op("I_STORE"), slot(c.dest()) + "");
}
+ /**
+ * 生成二元运算(+ - * /)
+ */
private void genBinOp(BinaryOperationInstruction b) {
emit(op("I_LOAD"), slot((IRVirtualRegister) b.operands().get(0)) + "");
emit(op("I_LOAD"), slot((IRVirtualRegister) b.operands().get(1)) + "");
- String opcode = switch (b.op()) {
- case ADD_I32 -> "I_ADD";
- case SUB_I32 -> "I_SUB";
- case MUL_I32 -> "I_MUL";
- case DIV_I32 -> "I_DIV";
- default -> throw new IllegalStateException("Unsupported bin op " + b.op());
- };
+ // 通过 IROpCode → VM 指令映射表获取实际指令
+ String opcode = IROpCodeMapper.toVMOp(b.op());
emit(op(opcode));
emit(op("I_STORE"), slot(b.dest()) + "");
}
+ /**
+ * 生成一元运算(如取负)
+ */
private void genUnary(UnaryOperationInstruction u) {
emit(op("I_LOAD"), slot((IRVirtualRegister) u.operands().get(0)) + "");
- String opcode = switch (u.op()) {
- case NEG_I32 -> "I_NEG";
- default -> throw new IllegalStateException("Unsupported unary op " + u.op());
- };
+ String opcode = IROpCodeMapper.toVMOp(u.op());
emit(op(opcode));
emit(op("I_STORE"), slot(u.dest()) + "");
}
+ /**
+ * 生成返回语句:
+ * - 对于 main 函数,使用 HALT 表示程序终止
+ * - 其他函数使用 RET 指令返回调用者
+ */
private void genRet(ReturnInstruction r) {
- /* — 主函数:加载返回值(若有) → HALT — */
if ("main".equals(currentFnName)) {
if (r.value() != null) {
emit(op("I_LOAD"), slot(r.value()) + "");
}
- emit(op("HALT")); // 结束整个程序
+ emit(op("HALT"));
return;
}
- /* — 普通函数:LOAD (可选) → RET — */
if (r.value() != null) {
emit(op("I_LOAD"), slot(r.value()) + "");
}
emit(op("RET"));
}
- /* ───────────── 工具函数 ───────────── */
-
+ /**
+ * 获取某个虚拟寄存器映射到的槽位索引
+ *
+ * @param r 虚拟寄存器
+ * @return 槽位编号
+ */
private int slot(IRVirtualRegister r) {
Integer s = slotMap.get(r);
- if (s == null) throw new IllegalStateException("Register " + r + " 未映射槽位");
+ if (s == null) throw new IllegalStateException("寄存器 " + r + " 未映射槽位");
return s;
}
+ /**
+ * 通过反射方式获取 VMOpCode 中定义的静态常量值(字符串形式)
+ *
+ * @param name VM 指令名(如 "I_ADD")
+ * @return 指令码文本
+ */
private String op(String name) {
try {
- Field f = VMOpCode.class.getField(name);
+ Field f = Class.forName("org.jcnc.snow.vm.engine.VMOpCode").getField(name);
return f.get(null).toString();
} catch (Exception e) {
- throw new RuntimeException("Unknown opcode " + name, e);
+ throw new RuntimeException("未知的 opcode: " + name, e);
}
}
+ /**
+ * 输出一条指令到代码列表中
+ *
+ * @param opcode 指令名
+ * @param args 参数(可选)
+ */
private void emit(String opcode, String... args) {
StringBuilder sb = new StringBuilder(opcode);
for (String a : args) sb.append(' ').append(a);