feat: 改进 IR 指令生成逻辑并支持浮点数
- 新增对 long、float 和 double 类型常量加载的支持 - 优化二元运算指令生成,支持不同类型的操作数 - 实现基于变量类型的 move 指令,提高类型兼容性 - 简化控制流指令的生成逻辑 - 优化代码结构,提高可读性和可维护性
This commit is contained in:
parent
1f8176d15e
commit
1c86c1dce7
@ -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 上下文
|
||||||
*/
|
*/
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user