feat: 改进 IR 指令生成逻辑并支持浮点数

- 新增对 long、float 和 double 类型常量加载的支持
- 优化二元运算指令生成,支持不同类型的操作数
- 实现基于变量类型的 move 指令,提高类型兼容性
- 简化控制流指令的生成逻辑
- 优化代码结构,提高可读性和可维护性
This commit is contained in:
Luke 2025-08-26 14:01:19 +08:00
parent 1f8176d15e
commit 1c86c1dce7

View File

@ -6,23 +6,16 @@ import org.jcnc.snow.compiler.ir.value.IRConstant;
import org.jcnc.snow.compiler.ir.value.IRVirtualRegister; import org.jcnc.snow.compiler.ir.value.IRVirtualRegister;
/** /**
* InstructionFactory 统一生成并注册 IR 指令的工厂类 * IR 指令统一生成工厂类负责封装常量加载二元运算赋值控制流等指令生成逻辑
* <p> * 提高 IR 生成阶段的可维护性与复用性
* 该类封装了常见的 IR 指令生成方式包括常量加载二元运算赋值控制流等
* 统一简化指令插入和寄存器分配逻辑提升 IR 生成阶段的代码可维护性和复用性
* </p>
*/ */
public class InstructionFactory { public class InstructionFactory {
/* ====================================================================== */
/* 常量 / 通用二元运算(新寄存器) */
/* ====================================================================== */
/** /**
* 加载整数常量将其写入一个新分配的虚拟寄存器并返回该寄存器 * 加载整数常量将其写入一个新分配的虚拟寄存器并返回该寄存器
* *
* @param ctx 当前 IR 上下文用于分配寄存器与添加指令 * @param ctx 当前 IR 上下文
* @param value 要加载的整数常量值 * @param value 整数常量值
* @return 存储该常量的新虚拟寄存器 * @return 存储该常量的新虚拟寄存器
*/ */
public static IRVirtualRegister loadConst(IRContext ctx, int value) { public static IRVirtualRegister loadConst(IRContext ctx, int value) {
@ -31,88 +24,150 @@ public class InstructionFactory {
return r; return r;
} }
/**
* 加载 long 类型常量到新寄存器
*
* @param ctx 当前 IR 上下文
* @param value long 类型常量值
* @return 存储该常量的新虚拟寄存器
*/
public static IRVirtualRegister loadConst(IRContext ctx, long value) {
IRVirtualRegister r = ctx.newRegister();
ctx.addInstruction(new LoadConstInstruction(r, new IRConstant(value)));
return r;
}
/**
* 加载 float 类型常量到新寄存器
*
* @param ctx 当前 IR 上下文
* @param value float 类型常量值
* @return 存储该常量的新虚拟寄存器
*/
public static IRVirtualRegister loadConst(IRContext ctx, float value) {
IRVirtualRegister r = ctx.newRegister();
ctx.addInstruction(new LoadConstInstruction(r, new IRConstant(value)));
return r;
}
/**
* 加载 double 类型常量到新寄存器
*
* @param ctx 当前 IR 上下文
* @param value double 类型常量值
* @return 存储该常量的新虚拟寄存器
*/
public static IRVirtualRegister loadConst(IRContext ctx, double value) {
IRVirtualRegister r = ctx.newRegister();
ctx.addInstruction(new LoadConstInstruction(r, new IRConstant(value)));
return r;
}
/** /**
* 执行二元运算如加法减法等结果写入新分配的虚拟寄存器并返回该寄存器 * 执行二元运算如加法减法等结果写入新分配的虚拟寄存器并返回该寄存器
* *
* @param ctx 当前 IR 上下文 * @param ctx 当前 IR 上下文
* @param op 运算类型IROpCode 枚举 ADD_I32 * @param op 二元运算操作码
* @param a 第一个操作数寄存器 * @param a 操作数寄存器
* @param b 第二个操作数寄存器 * @param b 操作数寄存器
* @return 保存运算结果的新虚拟寄存器 * @return 存储结果的新虚拟寄存器
*/ */
public static IRVirtualRegister binOp(IRContext ctx, IROpCode op, public static IRVirtualRegister binOp(IRContext ctx, IROpCode op, IRVirtualRegister a, IRVirtualRegister b) {
IRVirtualRegister a, IRVirtualRegister b) {
IRVirtualRegister dest = ctx.newRegister(); IRVirtualRegister dest = ctx.newRegister();
ctx.addInstruction(new BinaryOperationInstruction(op, dest, a, b)); ctx.addInstruction(new BinaryOperationInstruction(op, dest, a, b));
return dest; return dest;
} }
/* ====================================================================== */
/* 直接写入指定寄存器 */
/* ====================================================================== */
/** /**
* 加载整数常量到指定虚拟寄存器 * 加载常量到指定寄存器
* *
* @param ctx 当前 IR 上下文 * @param ctx 当前 IR 上下文
* @param dest 目标寄存器 * @param dest 目标虚拟寄存器
* @param value 要加载的整数常量 * @param value IR 常量值
*/ */
public static void loadConstInto(IRContext ctx, IRVirtualRegister dest, IRConstant value) { public static void loadConstInto(IRContext ctx, IRVirtualRegister dest, IRConstant value) {
ctx.addInstruction(new LoadConstInstruction(dest, value)); ctx.addInstruction(new LoadConstInstruction(dest, value));
} }
/** /**
* 对两个寄存器执行二元运算将结果写入指定目标寄存器 * 执行二元运算将结果写入指定寄存器
* *
* @param ctx 当前 IR 上下文 * @param ctx 当前 IR 上下文
* @param op 运算类型IROpCode 枚举 * @param op 二元运算操作码
* @param a 第一个操作数寄存器 * @param a 操作数寄存器
* @param b 第二个操作数寄存器 * @param b 操作数寄存器
* @param dest 运算结果目标寄存器 * @param dest 目标虚拟寄存器
*/ */
public static void binOpInto(IRContext ctx, IROpCode op, public static void binOpInto(IRContext ctx, IROpCode op, IRVirtualRegister a, IRVirtualRegister b, IRVirtualRegister dest) {
IRVirtualRegister a, IRVirtualRegister b,
IRVirtualRegister dest) {
ctx.addInstruction(new BinaryOperationInstruction(op, dest, a, b)); ctx.addInstruction(new BinaryOperationInstruction(op, dest, a, b));
} }
/** /**
* Move 指令src dest若寄存器相同也安全 * 生成值拷贝语义src dest
* <p> * 若类型无法推断默认采用 int 方案ADD_I32, src+0
* 实现方式: dest = src + 0即加上常量 0
* </p>
* *
* @param ctx 当前 IR 上下文 * @param ctx 当前 IR 上下文
* @param src 源寄存器 * @param src 源寄存器
* @param dest 目标寄存器 * @param dest 目标寄存器
*/ */
public static void move(IRContext ctx, IRVirtualRegister src, IRVirtualRegister dest) { public static void move(IRContext ctx, IRVirtualRegister src, IRVirtualRegister dest) {
// 自赋值无需任何操作避免生成多余的常量 0 寄存器
if (src == dest) { if (src == dest) {
return; return;
} }
// 回退实现: dest = src + 0 String varType = ctx.getVarType(); // 需要 IRContext 提供
IRVirtualRegister zero = loadConst(ctx, 0); char suffix = '\0';
ctx.addInstruction(new BinaryOperationInstruction(IROpCode.ADD_I32, dest, src, zero)); if (varType != null) {
switch (varType) {
case "byte" -> suffix = 'b';
case "short" -> suffix = 's';
case "int" -> suffix = 'i';
case "long" -> suffix = 'l';
case "float" -> suffix = 'f';
case "double" -> suffix = 'd';
}
}
IRVirtualRegister zero;
IROpCode op = switch (suffix) {
case 'd' -> {
zero = loadConst(ctx, 0.0);
yield IROpCode.ADD_D64;
}
case 'f' -> {
zero = loadConst(ctx, 0.0f);
yield IROpCode.ADD_F32;
}
case 'l' -> {
zero = loadConst(ctx, 0L);
yield IROpCode.ADD_L64;
}
case 's' -> {
zero = loadConst(ctx, 0);
yield IROpCode.ADD_S16;
}
case 'b' -> {
zero = loadConst(ctx, 0);
yield IROpCode.ADD_B8;
}
default -> {
zero = loadConst(ctx, 0);
yield IROpCode.ADD_I32;
}
};
ctx.addInstruction(new BinaryOperationInstruction(op, dest, src, zero));
} }
/* ====================================================================== */
/* 控制流指令 */
/* ====================================================================== */
/** /**
* 生成无条件跳转JMP指令跳转到指定标签 * 生成无条件跳转指令
* *
* @param ctx 当前 IR 上下文 * @param ctx 当前 IR 上下文
* @param label 目标标签名 * @param label 跳转目标标签
*/ */
public static void jmp(IRContext ctx, String label) { public static void jmp(IRContext ctx, String label) {
ctx.addInstruction(new IRJumpInstruction(label)); ctx.addInstruction(new IRJumpInstruction(label));
} }
/** /**
* IR 中插入一个标签Label * IR 中插入标签
* *
* @param ctx 当前 IR 上下文 * @param ctx 当前 IR 上下文
* @param label 标签名 * @param label 标签名
@ -122,22 +177,18 @@ public class InstructionFactory {
} }
/** /**
* 比较跳转 if a < b goto label根据条件跳转到目标标签 * 比较两个寄存器并根据结果跳转到指定标签
* *
* @param ctx 当前 IR 上下文 * @param ctx 当前 IR 上下文
* @param cmp 比较操作码 IROpCode.LT_I32 * @param cmp 比较操作码
* @param a 第一个操作数寄存器 * @param a 操作数寄存器
* @param b 第二个操作数寄存器 * @param b 操作数寄存器
* @param targetLabel 跳转目标标签 * @param targetLabel 跳转目标标签
*/ */
public static void cmpJump(IRContext ctx, IROpCode cmp, public static void cmpJump(IRContext ctx, IROpCode cmp, IRVirtualRegister a, IRVirtualRegister b, String targetLabel) {
IRVirtualRegister a, IRVirtualRegister b,
String targetLabel) {
ctx.addInstruction(new IRCompareJumpInstruction(cmp, a, b, targetLabel)); ctx.addInstruction(new IRCompareJumpInstruction(cmp, a, b, targetLabel));
} }
/* ---------------- 返回 ---------------- */
/** /**
* 生成返回指令带返回值 * 生成返回指令带返回值
* *
@ -149,7 +200,7 @@ public class InstructionFactory {
} }
/** /**
* 生成无返回值 return 指令 void 函数 * 生成无返回值void返回指令
* *
* @param ctx 当前 IR 上下文 * @param ctx 当前 IR 上下文
*/ */