增加注释
This commit is contained in:
parent
089e629187
commit
48b7418b03
@ -6,31 +6,29 @@ import java.util.EnumMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IROpCodeMapper —— IR 操作码(IROpCode)到 VM 虚拟机操作码(字符串形式)的映射器。
|
* 提供 IR 操作码({@link IROpCode})到虚拟机指令名({@code String})的一一映射工具类。
|
||||||
* <p>
|
* <p>
|
||||||
* 本类用于编译器后端阶段,将中间表示中的操作类型(如 ADD_I32)转换为
|
* 本类在编译器后端负责将中间表示中的操作码转换为对应的 VM 指令,用于最终的代码生成。
|
||||||
* 虚拟机指令集中的具体指令(如 "I_ADD"),用于代码生成输出。
|
* 不负责操作数或参数传递的逻辑,仅做纯映射处理。
|
||||||
* </p>
|
* </p>
|
||||||
* <p>
|
* <p>
|
||||||
* 注意:该类只做一一映射,不处理操作数或参数传递逻辑。
|
* 如需扩展更多操作码或新增指令语义,可在此集中管理映射关系。
|
||||||
* 若未来有更多数据类型或扩展语义,可在此处集中管理。
|
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
public final class IROpCodeMapper {
|
public final class IROpCodeMapper {
|
||||||
|
|
||||||
/** 存储映射关系的枚举映射表(使用 EnumMap 提高性能) */
|
/**
|
||||||
|
* IR 操作码到 VM 指令名的映射表,基于 {@code EnumMap} 实现以提升性能。
|
||||||
|
*/
|
||||||
private static final Map<IROpCode, String> opcodeMap = new EnumMap<>(IROpCode.class);
|
private static final Map<IROpCode, String> opcodeMap = new EnumMap<>(IROpCode.class);
|
||||||
|
|
||||||
// 初始化静态映射表
|
|
||||||
static {
|
static {
|
||||||
// ───── 算术运算 ─────
|
|
||||||
opcodeMap.put(IROpCode.ADD_I32, "I_ADD");
|
opcodeMap.put(IROpCode.ADD_I32, "I_ADD");
|
||||||
opcodeMap.put(IROpCode.SUB_I32, "I_SUB");
|
opcodeMap.put(IROpCode.SUB_I32, "I_SUB");
|
||||||
opcodeMap.put(IROpCode.MUL_I32, "I_MUL");
|
opcodeMap.put(IROpCode.MUL_I32, "I_MUL");
|
||||||
opcodeMap.put(IROpCode.DIV_I32, "I_DIV");
|
opcodeMap.put(IROpCode.DIV_I32, "I_DIV");
|
||||||
opcodeMap.put(IROpCode.NEG_I32, "I_NEG");
|
opcodeMap.put(IROpCode.NEG_I32, "I_NEG");
|
||||||
|
|
||||||
// ───── 逻辑比较运算 ─────
|
|
||||||
opcodeMap.put(IROpCode.CMP_EQ, "IC_EQ");
|
opcodeMap.put(IROpCode.CMP_EQ, "IC_EQ");
|
||||||
opcodeMap.put(IROpCode.CMP_NE, "IC_NE");
|
opcodeMap.put(IROpCode.CMP_NE, "IC_NE");
|
||||||
opcodeMap.put(IROpCode.CMP_LT, "IC_L");
|
opcodeMap.put(IROpCode.CMP_LT, "IC_L");
|
||||||
@ -38,33 +36,35 @@ public final class IROpCodeMapper {
|
|||||||
opcodeMap.put(IROpCode.CMP_LE, "IC_LE");
|
opcodeMap.put(IROpCode.CMP_LE, "IC_LE");
|
||||||
opcodeMap.put(IROpCode.CMP_GE, "IC_GE");
|
opcodeMap.put(IROpCode.CMP_GE, "IC_GE");
|
||||||
|
|
||||||
// ───── 数据操作 ─────
|
|
||||||
opcodeMap.put(IROpCode.LOAD, "I_LOAD");
|
opcodeMap.put(IROpCode.LOAD, "I_LOAD");
|
||||||
opcodeMap.put(IROpCode.STORE, "I_STORE");
|
opcodeMap.put(IROpCode.STORE, "I_STORE");
|
||||||
opcodeMap.put(IROpCode.CONST, "I_PUSH");
|
opcodeMap.put(IROpCode.CONST, "I_PUSH");
|
||||||
|
|
||||||
// ───── 控制流 ─────
|
|
||||||
opcodeMap.put(IROpCode.JUMP, "JMP");
|
opcodeMap.put(IROpCode.JUMP, "JMP");
|
||||||
opcodeMap.put(IROpCode.JUMP_IF_ZERO, "JZ");
|
opcodeMap.put(IROpCode.JUMP_IF_ZERO, "JZ");
|
||||||
opcodeMap.put(IROpCode.LABEL, "LABEL");
|
opcodeMap.put(IROpCode.LABEL, "LABEL");
|
||||||
|
|
||||||
// ───── 函数调用 ─────
|
|
||||||
opcodeMap.put(IROpCode.CALL, "CALL");
|
opcodeMap.put(IROpCode.CALL, "CALL");
|
||||||
opcodeMap.put(IROpCode.RET, "RET");
|
opcodeMap.put(IROpCode.RET, "RET");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将给定的 IR 操作码转换为对应的 VM 指令名(字符串)。
|
* 将给定的 IR 操作码转换为对应的 VM 指令名。
|
||||||
*
|
*
|
||||||
* @param irOp IROpCode 中的操作码
|
* @param irOp 需转换的 IR 操作码
|
||||||
* @return 对应的 VM opcode 字符串
|
* @return 与 IR 操作码对应的 VM 指令名称
|
||||||
* @throws IllegalArgumentException 若操作码未被映射
|
* @throws IllegalArgumentException 若 {@code irOp} 未在映射表中定义
|
||||||
*/
|
*/
|
||||||
public static String toVMOp(IROpCode irOp) {
|
public static String toVMOp(IROpCode irOp) {
|
||||||
String code = opcodeMap.get(irOp);
|
String vmCode = opcodeMap.get(irOp);
|
||||||
if (code == null) {
|
if (vmCode == null) {
|
||||||
throw new IllegalArgumentException("未映射的 IR 操作码: " + irOp);
|
throw new IllegalArgumentException("未映射的 IR 操作码: " + irOp);
|
||||||
}
|
}
|
||||||
return code;
|
return vmCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 私有构造函数,防止实例化
|
||||||
|
private IROpCodeMapper() {
|
||||||
|
// 不允许实例化
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,52 +1,55 @@
|
|||||||
package org.jcnc.snow.compiler.backend;
|
package org.jcnc.snow.compiler.backend;
|
||||||
|
|
||||||
import org.jcnc.snow.compiler.ir.core.*;
|
import org.jcnc.snow.compiler.ir.core.IRFunction;
|
||||||
|
import org.jcnc.snow.compiler.ir.core.IRInstruction;
|
||||||
|
import org.jcnc.snow.compiler.ir.core.IRValue;
|
||||||
import org.jcnc.snow.compiler.ir.value.IRVirtualRegister;
|
import org.jcnc.snow.compiler.ir.value.IRVirtualRegister;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A <em>very</em> simple linear-scan register allocator.
|
* 线性扫描寄存器分配器。
|
||||||
*
|
* <p>
|
||||||
* <p>Strategy:</p>
|
* 分配策略:
|
||||||
* <ol>
|
* <ol>
|
||||||
* <li>Assign <strong>formal parameters</strong> to slots
|
* <li>将函数的形式参数按照声明顺序分配到槽编号 0 到 n-1。</li>
|
||||||
* 0 .. n-1 (in declaration order).</li>
|
* <li>随后扫描函数体中的指令列表,每遇到尚未分配槽号的虚拟寄存器,
|
||||||
* <li>Scan the instruction list; every unseen virtual register
|
* 即为其分配下一个可用的槽编号。</li>
|
||||||
* gets the next free slot number.</li>
|
|
||||||
* </ol>
|
* </ol>
|
||||||
* <p>No liveness analysis, no spilling – demo-grade only.</p>
|
|
||||||
*/
|
*/
|
||||||
public final class RegisterAllocator {
|
public final class RegisterAllocator {
|
||||||
|
|
||||||
private final Map<IRVirtualRegister,Integer> map = new HashMap<>();
|
/**
|
||||||
|
* 存储虚拟寄存器到物理槽的映射表。
|
||||||
|
* 键为虚拟寄存器,值为分配的槽编号。
|
||||||
|
*/
|
||||||
|
private final Map<IRVirtualRegister, Integer> map = new HashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Computes a register→slot mapping for the given function.
|
* 为指定的 IR 函数计算寄存器到槽的映射关系。
|
||||||
|
* <p>
|
||||||
|
* 先为函数的形式参数分配槽号,再为函数体中出现的其他虚拟寄存器依次分配。
|
||||||
|
* </p>
|
||||||
*
|
*
|
||||||
* @param fn IRFunction to allocate
|
* @param fn 需要进行寄存器分配的中间表示函数
|
||||||
* @return mapping table (immutable)
|
* @return 一个不可变的映射表,表示每个虚拟寄存器对应的槽编号
|
||||||
*/
|
*/
|
||||||
public Map<IRVirtualRegister,Integer> allocate(IRFunction fn) {
|
public Map<IRVirtualRegister, Integer> allocate(IRFunction fn) {
|
||||||
|
|
||||||
int next = 0;
|
int next = 0;
|
||||||
|
|
||||||
/* ---------- 1) parameters first ---------- */
|
// 1. 为形式参数分配槽编号
|
||||||
for (IRVirtualRegister param : fn.parameters()) {
|
for (IRVirtualRegister param : fn.parameters()) {
|
||||||
map.put(param, next++);
|
map.put(param, next++);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------- 2) then all remaining VRegs ---------- */
|
// 2. 扫描函数体,分配其他虚拟寄存器的槽编号
|
||||||
for (IRInstruction inst : fn.body()) {
|
for (IRInstruction inst : fn.body()) {
|
||||||
|
|
||||||
if (inst.dest() != null && !map.containsKey(inst.dest())) {
|
if (inst.dest() != null && !map.containsKey(inst.dest())) {
|
||||||
map.put(inst.dest(), next++);
|
map.put(inst.dest(), next++);
|
||||||
}
|
}
|
||||||
|
for (IRValue operand : inst.operands()) {
|
||||||
for (IRValue v : inst.operands()) {
|
if (operand instanceof IRVirtualRegister vr && !map.containsKey(vr)) {
|
||||||
if (v instanceof IRVirtualRegister vr &&
|
|
||||||
!map.containsKey(vr)) {
|
|
||||||
map.put(vr, next++);
|
map.put(vr, next++);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,50 +1,95 @@
|
|||||||
package org.jcnc.snow.compiler.backend;
|
package org.jcnc.snow.compiler.backend;
|
||||||
|
|
||||||
import org.jcnc.snow.compiler.ir.core.*;
|
import org.jcnc.snow.compiler.ir.core.IRFunction;
|
||||||
import org.jcnc.snow.compiler.ir.instruction.*;
|
import org.jcnc.snow.compiler.ir.core.IRInstruction;
|
||||||
import org.jcnc.snow.compiler.ir.value.*;
|
import org.jcnc.snow.compiler.ir.core.IRValue;
|
||||||
|
import org.jcnc.snow.compiler.ir.instruction.BinaryOperationInstruction;
|
||||||
|
import org.jcnc.snow.compiler.ir.instruction.CallInstruction;
|
||||||
|
import org.jcnc.snow.compiler.ir.instruction.LoadConstInstruction;
|
||||||
|
import org.jcnc.snow.compiler.ir.instruction.ReturnInstruction;
|
||||||
|
import org.jcnc.snow.compiler.ir.instruction.UnaryOperationInstruction;
|
||||||
|
import org.jcnc.snow.compiler.ir.value.IRVirtualRegister;
|
||||||
|
import org.jcnc.snow.compiler.ir.value.IRConstant;
|
||||||
import org.jcnc.snow.vm.engine.VMOpCode;
|
import org.jcnc.snow.vm.engine.VMOpCode;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates VM code for a single IRFunction.
|
* 为单个 {@link IRFunction} 生成对应的虚拟机指令序列。
|
||||||
|
* <p>
|
||||||
|
* 本类依据中间表示函数的指令列表,调用 {@link VMProgramBuilder} 输出相应的 VM 操作码,
|
||||||
|
* 包括常量加载、算术运算、函数调用和返回等指令生成逻辑。
|
||||||
|
* </p>
|
||||||
*/
|
*/
|
||||||
public final class VMCodeGenerator {
|
public final class VMCodeGenerator {
|
||||||
|
|
||||||
private final Map<IRVirtualRegister,Integer> slotMap;
|
/**
|
||||||
|
* 虚拟寄存器到槽编号的映射表,用于确定加载和存储的目标槽。
|
||||||
|
*/
|
||||||
|
private final Map<IRVirtualRegister, Integer> slotMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* VM 指令输出器,用于构建最终的指令流。
|
||||||
|
*/
|
||||||
private final VMProgramBuilder out;
|
private final VMProgramBuilder out;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前正在生成代码的函数名称,用于在返回指令处区分主函数与其他函数。
|
||||||
|
*/
|
||||||
private String currentFn;
|
private String currentFn;
|
||||||
|
|
||||||
public VMCodeGenerator(Map<IRVirtualRegister,Integer> slotMap,
|
/**
|
||||||
|
* 构造 VMCodeGenerator 实例。
|
||||||
|
*
|
||||||
|
* @param slotMap 虚拟寄存器与槽编号的映射表
|
||||||
|
* @param out 用于输出 VM 指令的构建器
|
||||||
|
*/
|
||||||
|
public VMCodeGenerator(Map<IRVirtualRegister, Integer> slotMap,
|
||||||
VMProgramBuilder out) {
|
VMProgramBuilder out) {
|
||||||
this.slotMap = slotMap;
|
this.slotMap = slotMap;
|
||||||
this.out = out;
|
this.out = out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 为指定的 IR 函数生成完整的 VM 指令流。
|
||||||
|
*
|
||||||
|
* @param fn 目标 IRFunction 实例
|
||||||
|
* @throws IllegalStateException 若遇到不支持的 IR 指令类型
|
||||||
|
*/
|
||||||
public void generate(IRFunction fn) {
|
public void generate(IRFunction fn) {
|
||||||
currentFn = fn.name();
|
currentFn = fn.name();
|
||||||
out.beginFunction(currentFn);
|
out.beginFunction(currentFn);
|
||||||
|
|
||||||
for (IRInstruction inst : fn.body()) switch (inst) {
|
for (IRInstruction inst : fn.body()) {
|
||||||
|
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 CallInstruction c -> genCall(c);
|
case CallInstruction c -> genCall(c);
|
||||||
case ReturnInstruction r -> genRet(r);
|
case ReturnInstruction r -> genRet(r);
|
||||||
default -> throw new IllegalStateException("Unsupported IR: "+inst);
|
default -> throw new IllegalStateException("Unsupported IR: " + inst);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------- helpers ---------- */
|
/**
|
||||||
|
* 生成常量加载指令序列:将常量推入栈并存入目标寄存器槽。
|
||||||
|
*
|
||||||
|
* @param c 常量加载指令
|
||||||
|
*/
|
||||||
private void genLoadConst(LoadConstInstruction c) {
|
private void genLoadConst(LoadConstInstruction c) {
|
||||||
IRConstant k = (IRConstant) c.operands().getFirst();
|
IRConstant constant = (IRConstant) c.operands().getFirst();
|
||||||
emit(op("I_PUSH"), k.value().toString());
|
emit(op("I_PUSH"), constant.value().toString());
|
||||||
emit(op("I_STORE"), slot(c.dest()));
|
emit(op("I_STORE"), slot(c.dest()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成二元算术或比较运算指令序列:
|
||||||
|
* 依次加载两个操作数,执行运算,并存回目标寄存器槽。
|
||||||
|
*
|
||||||
|
* @param b 二元操作指令
|
||||||
|
*/
|
||||||
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)));
|
||||||
@ -52,15 +97,24 @@ public final class VMCodeGenerator {
|
|||||||
emit(op("I_STORE"), slot(b.dest()));
|
emit(op("I_STORE"), slot(b.dest()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成一元运算指令序列:加载操作数,执行运算,并存回目标寄存器槽。
|
||||||
|
*
|
||||||
|
* @param u 一元操作指令
|
||||||
|
*/
|
||||||
private void genUnary(UnaryOperationInstruction u) {
|
private void genUnary(UnaryOperationInstruction u) {
|
||||||
emit(op("I_LOAD"), slot((IRVirtualRegister) u.operands().getFirst()));
|
emit(op("I_LOAD"), slot((IRVirtualRegister) u.operands().getFirst()));
|
||||||
emit(op(IROpCodeMapper.toVMOp(u.op())));
|
emit(op(IROpCodeMapper.toVMOp(u.op())));
|
||||||
emit(op("I_STORE"), slot(u.dest()));
|
emit(op("I_STORE"), slot(u.dest()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Generates CALL addr nArgs */
|
/**
|
||||||
|
* 生成函数调用指令序列:
|
||||||
|
* 按参数顺序加载每个参数,执行调用,并将返回值存入目标寄存器槽。
|
||||||
|
*
|
||||||
|
* @param c 调用指令
|
||||||
|
*/
|
||||||
private void genCall(CallInstruction c) {
|
private void genCall(CallInstruction c) {
|
||||||
/* push arguments in IR order (already left-to-right) */
|
|
||||||
for (IRValue arg : c.getArguments()) {
|
for (IRValue arg : c.getArguments()) {
|
||||||
emit(op("I_LOAD"), slot((IRVirtualRegister) arg));
|
emit(op("I_LOAD"), slot((IRVirtualRegister) arg));
|
||||||
}
|
}
|
||||||
@ -69,28 +123,56 @@ public final class VMCodeGenerator {
|
|||||||
emit(op("I_STORE"), slot(c.getDest()));
|
emit(op("I_STORE"), slot(c.getDest()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成返回指令序列:可选地加载返回值,然后根据是否为主函数选择 HALT 或 RET。
|
||||||
|
*
|
||||||
|
* @param r 返回指令
|
||||||
|
*/
|
||||||
private void genRet(ReturnInstruction r) {
|
private void genRet(ReturnInstruction r) {
|
||||||
if (r.value() != null)
|
if (r.value() != null) {
|
||||||
emit(op("I_LOAD"), slot(r.value()));
|
emit(op("I_LOAD"), slot(r.value()));
|
||||||
emit("main".equals(currentFn) ? op("HALT") : op("RET"));
|
}
|
||||||
|
String opcode = "main".equals(currentFn) ? op("HALT") : op("RET");
|
||||||
|
out.emit(opcode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造并输出一条 VM 指令。
|
||||||
|
*
|
||||||
|
* @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);
|
||||||
|
}
|
||||||
out.emit(sb.toString());
|
out.emit(sb.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将虚拟寄存器映射为对应的槽编号字符串。
|
||||||
|
*
|
||||||
|
* @param r 虚拟寄存器
|
||||||
|
* @return 目标槽编号的字符串形式
|
||||||
|
*/
|
||||||
private String slot(IRVirtualRegister r) {
|
private String slot(IRVirtualRegister r) {
|
||||||
return slotMap.get(r).toString();
|
return slotMap.get(r).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据 VMOpCode 常量名反射获取对应的操作码字符串。
|
||||||
|
*
|
||||||
|
* @param name VMOpCode 常量字段名
|
||||||
|
* @return 对应的操作码字符串
|
||||||
|
* @throws RuntimeException 若未找到指定操作码字段
|
||||||
|
*/
|
||||||
private String op(String name) {
|
private String op(String name) {
|
||||||
try {
|
try {
|
||||||
Field f = VMOpCode.class.getField(name);
|
Field field = VMOpCode.class.getField(name);
|
||||||
return f.get(null).toString();
|
return field.get(null).toString();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException("Unknown opcode: "+name, e);
|
throw new RuntimeException("Unknown opcode: " + name, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user