优化代码
This commit is contained in:
parent
ab5320f19c
commit
f29e6eccb5
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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 —— 简单的线性扫描寄存器分配器(演示级实现)。
|
||||
* <p>
|
||||
* 该类用于为 IRFunction 中出现的所有虚拟寄存器(IRVirtualRegister)分配槽位编号。
|
||||
* 每个槽位编号对应虚拟机中的局部变量位置或栈槽。
|
||||
* </p>
|
||||
* <p>
|
||||
* 算法策略:顺序扫描所有 IR 指令,每遇到一个新的虚拟寄存器就分配一个递增编号。
|
||||
* 不考虑寄存器生存期重叠、重用或优化,仅做简单映射。
|
||||
* </p>
|
||||
*/
|
||||
public final class RegisterAllocator {
|
||||
|
||||
/** 虚拟寄存器 → 槽位编号 的映射表 */
|
||||
private final Map<IRVirtualRegister, Integer> map = new HashMap<>();
|
||||
|
||||
/**
|
||||
* 执行寄存器分配:将函数中所有虚拟寄存器映射为连续的整型槽位编号。
|
||||
*
|
||||
* @param fn 中间表示形式的函数(IRFunction)
|
||||
* @return 映射表(IRVirtualRegister → 槽位编号)
|
||||
*/
|
||||
public Map<IRVirtualRegister, Integer> allocate(IRFunction fn) {
|
||||
int next = 0;
|
||||
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++);
|
||||
// 若该指令有目标寄存器(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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 —— 虚拟机代码生成器。
|
||||
* <p>
|
||||
* 该类负责将中间表示(IRFunction)翻译为 SVM 虚拟机可执行的文本指令。
|
||||
* 当前支持:
|
||||
* - int32 类型的常量加载
|
||||
* - 加减乘除(+ - * /)的二元表达式
|
||||
* - 取负(一元 -)
|
||||
* - 函数返回(含 main 函数终止)
|
||||
* </p>
|
||||
* <p>
|
||||
* 每个虚拟寄存器通过 slotMap 分配一个槽位(int 索引),用于定位变量。
|
||||
* 生成的代码是一系列字符串,格式为汇编式:OPCODE 参数...
|
||||
* </p>
|
||||
*/
|
||||
public final class VMCodeGenerator {
|
||||
|
||||
/** 虚拟寄存器 → 栈槽编号的映射表(由编译器分配) */
|
||||
private final Map<IRVirtualRegister, Integer> slotMap;
|
||||
|
||||
/** 存储生成的指令 */
|
||||
private final List<String> code = new ArrayList<>();
|
||||
|
||||
private String currentFnName; // ← 当前正在生成的函数名
|
||||
/** 当前正在生成代码的函数名称 */
|
||||
private String currentFnName;
|
||||
|
||||
public VMCodeGenerator(Map<IRVirtualRegister, Integer> slotMap) {
|
||||
this.slotMap = slotMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 主入口:IR → 指令序列
|
||||
* 主入口:接收一个中间表示函数(IRFunction),输出对应的 VM 指令文本序列
|
||||
*
|
||||
* @param fn IRFunction,包含该函数的所有 IRInstruction
|
||||
* @return 指令字符串列表
|
||||
*/
|
||||
public List<String> 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);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user