优化代码

This commit is contained in:
Luke 2025-05-09 09:54:31 +08:00
parent ab5320f19c
commit f29e6eccb5
3 changed files with 175 additions and 44 deletions

View File

@ -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 虚拟机操作码字符串形式的映射器
* <p>
* 本类用于编译器后端阶段将中间表示中的操作类型 ADD_I32转换为
* 虚拟机指令集中的具体指令 "I_ADD"用于代码生成输出
* </p>
* <p>
* 注意该类只做一一映射不处理操作数或参数传递逻辑
* 若未来有更多数据类型或扩展语义可在此处集中管理
* </p>
*/
public final class IROpCodeMapper {
/** 存储映射关系的枚举映射表(使用 EnumMap 提高性能) */
private static final Map<IROpCode, String> 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;
}
}

View File

@ -1,5 +1,3 @@
//
// file: compiler/backend/RegisterAllocator.java
package org.jcnc.snow.compiler.backend; package org.jcnc.snow.compiler.backend;
import org.jcnc.snow.compiler.ir.core.IRFunction; 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.HashMap;
import java.util.Map; import java.util.Map;
/** 线性扫描寄存器分配(演示级) */ /**
* RegisterAllocator 简单的线性扫描寄存器分配器演示级实现
* <p>
* 该类用于为 IRFunction 中出现的所有虚拟寄存器IRVirtualRegister分配槽位编号
* 每个槽位编号对应虚拟机中的局部变量位置或栈槽
* </p>
* <p>
* 算法策略顺序扫描所有 IR 指令每遇到一个新的虚拟寄存器就分配一个递增编号
* 不考虑寄存器生存期重叠重用或优化仅做简单映射
* </p>
*/
public final class RegisterAllocator { public final class RegisterAllocator {
private final Map<IRVirtualRegister,Integer> map = new HashMap<>();
public Map<IRVirtualRegister,Integer> allocate(IRFunction fn){ /** 虚拟寄存器 → 槽位编号 的映射表 */
int next = 0; private final Map<IRVirtualRegister, Integer> map = new HashMap<>();
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++); *
* @param fn 中间表示形式的函数IRFunction
* @return 映射表IRVirtualRegister 槽位编号
*/
public Map<IRVirtualRegister, Integer> 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; return map;
} }
} }

View File

@ -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.instruction.UnaryOperationInstruction;
import org.jcnc.snow.compiler.ir.value.IRConstant; import org.jcnc.snow.compiler.ir.value.IRConstant;
import org.jcnc.snow.compiler.ir.value.IRVirtualRegister; import org.jcnc.snow.compiler.ir.value.IRVirtualRegister;
import org.jcnc.snow.vm.engine.VMOpCode;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.ArrayList; import java.util.ArrayList;
@ -16,107 +15,143 @@ import java.util.List;
import java.util.Map; import java.util.Map;
/** /**
* IRFunction 转译为 SVM 指令文本 * VMCodeGenerator 虚拟机代码生成器
* 目前支持int32 常量+ - * /一元 -return * <p>
* 该类负责将中间表示IRFunction翻译为 SVM 虚拟机可执行的文本指令
* 当前支持
* - int32 类型的常量加载
* - 加减乘除+ - * /的二元表达式
* - 取负一元 -
* - 函数返回 main 函数终止
* </p>
* <p>
* 每个虚拟寄存器通过 slotMap 分配一个槽位int 索引用于定位变量
* 生成的代码是一系列字符串格式为汇编式OPCODE 参数...
* </p>
*/ */
public final class VMCodeGenerator { public final class VMCodeGenerator {
/** 虚拟寄存器 → 栈槽编号的映射表(由编译器分配) */
private final Map<IRVirtualRegister, Integer> slotMap; private final Map<IRVirtualRegister, Integer> slotMap;
/** 存储生成的指令 */
private final List<String> code = new ArrayList<>(); private final List<String> code = new ArrayList<>();
private String currentFnName; // 当前正在生成的函数名 /** 当前正在生成代码的函数名称 */
private String currentFnName;
public VMCodeGenerator(Map<IRVirtualRegister, Integer> slotMap) { public VMCodeGenerator(Map<IRVirtualRegister, Integer> slotMap) {
this.slotMap = slotMap; this.slotMap = slotMap;
} }
/** /**
* 主入口IR 指令序列 * 主入口接收一个中间表示函数IRFunction输出对应的 VM 指令文本序列
*
* @param fn IRFunction包含该函数的所有 IRInstruction
* @return 指令字符串列表
*/ */
public List<String> generate(IRFunction fn) { public List<String> generate(IRFunction fn) {
currentFnName = fn.name(); // 保存函数名 currentFnName = fn.name();
for (IRInstruction inst : fn.body()) { for (IRInstruction inst : fn.body()) {
switch (inst) { switch (inst) {
case LoadConstInstruction c -> genLoadConst(c); case LoadConstInstruction c -> genLoadConst(c); // 常量加载
case BinaryOperationInstruction b -> genBinOp(b); case BinaryOperationInstruction b -> genBinOp(b); // 二元操作
case UnaryOperationInstruction u -> genUnary(u); case UnaryOperationInstruction u -> genUnary(u); // 一元操作
case ReturnInstruction r -> genRet(r); case ReturnInstruction r -> genRet(r); // 返回语句
default -> throw new IllegalStateException("Unsupported IR: " + inst); default -> throw new IllegalStateException("不支持的 IR 指令类型: " + inst);
} }
} }
/* 注意:不再额外添加 HALT结束行为由 genRet 决定 */
return code; return code;
} }
/* ───────────── 指令生成 ───────────── */ /**
* 生成常量加载指令I_PUSH 常量 I_STORE 寄存器槽位
*/
private void genLoadConst(LoadConstInstruction c) { 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_PUSH"), k.value().toString());
emit(op("I_STORE"), slot(c.dest()) + ""); emit(op("I_STORE"), slot(c.dest()) + "");
} }
/**
* 生成二元运算+ - * /
*/
private void genBinOp(BinaryOperationInstruction b) { private void genBinOp(BinaryOperationInstruction b) {
emit(op("I_LOAD"), slot((IRVirtualRegister) b.operands().get(0)) + ""); emit(op("I_LOAD"), slot((IRVirtualRegister) b.operands().get(0)) + "");
emit(op("I_LOAD"), slot((IRVirtualRegister) b.operands().get(1)) + ""); emit(op("I_LOAD"), slot((IRVirtualRegister) b.operands().get(1)) + "");
String opcode = switch (b.op()) { // 通过 IROpCode VM 指令映射表获取实际指令
case ADD_I32 -> "I_ADD"; String opcode = IROpCodeMapper.toVMOp(b.op());
case SUB_I32 -> "I_SUB";
case MUL_I32 -> "I_MUL";
case DIV_I32 -> "I_DIV";
default -> throw new IllegalStateException("Unsupported bin op " + b.op());
};
emit(op(opcode)); emit(op(opcode));
emit(op("I_STORE"), slot(b.dest()) + ""); emit(op("I_STORE"), slot(b.dest()) + "");
} }
/**
* 生成一元运算如取负
*/
private void genUnary(UnaryOperationInstruction u) { private void genUnary(UnaryOperationInstruction u) {
emit(op("I_LOAD"), slot((IRVirtualRegister) u.operands().get(0)) + ""); emit(op("I_LOAD"), slot((IRVirtualRegister) u.operands().get(0)) + "");
String opcode = switch (u.op()) { String opcode = IROpCodeMapper.toVMOp(u.op());
case NEG_I32 -> "I_NEG";
default -> throw new IllegalStateException("Unsupported unary op " + u.op());
};
emit(op(opcode)); emit(op(opcode));
emit(op("I_STORE"), slot(u.dest()) + ""); emit(op("I_STORE"), slot(u.dest()) + "");
} }
/**
* 生成返回语句
* - 对于 main 函数使用 HALT 表示程序终止
* - 其他函数使用 RET 指令返回调用者
*/
private void genRet(ReturnInstruction r) { private void genRet(ReturnInstruction r) {
/* — 主函数:加载返回值(若有) → HALT — */
if ("main".equals(currentFnName)) { if ("main".equals(currentFnName)) {
if (r.value() != null) { if (r.value() != null) {
emit(op("I_LOAD"), slot(r.value()) + ""); emit(op("I_LOAD"), slot(r.value()) + "");
} }
emit(op("HALT")); // 结束整个程序 emit(op("HALT"));
return; return;
} }
/* — 普通函数LOAD (可选) → RET — */
if (r.value() != null) { if (r.value() != null) {
emit(op("I_LOAD"), slot(r.value()) + ""); emit(op("I_LOAD"), slot(r.value()) + "");
} }
emit(op("RET")); emit(op("RET"));
} }
/* ───────────── 工具函数 ───────────── */ /**
* 获取某个虚拟寄存器映射到的槽位索引
*
* @param r 虚拟寄存器
* @return 槽位编号
*/
private int slot(IRVirtualRegister r) { private int slot(IRVirtualRegister r) {
Integer s = slotMap.get(r); Integer s = slotMap.get(r);
if (s == null) throw new IllegalStateException("Register " + r + " 未映射槽位"); if (s == null) throw new IllegalStateException("寄存器 " + r + " 未映射槽位");
return s; return s;
} }
/**
* 通过反射方式获取 VMOpCode 中定义的静态常量值字符串形式
*
* @param name VM 指令名 "I_ADD"
* @return 指令码文本
*/
private String op(String name) { private String op(String name) {
try { try {
Field f = VMOpCode.class.getField(name); Field f = Class.forName("org.jcnc.snow.vm.engine.VMOpCode").getField(name);
return f.get(null).toString(); return f.get(null).toString();
} catch (Exception e) { } 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) { private void emit(String opcode, String... args) {
StringBuilder sb = new StringBuilder(opcode); StringBuilder sb = new StringBuilder(opcode);
for (String a : args) sb.append(' ').append(a); for (String a : args) sb.append(' ').append(a);