refactor: 重构代码以提高可读性和可维护性

- 优化了方法结构,减少了冗余代码
- 提高了错误提示的详细程度
- 增加了类型前缀处理方法,简化了类型判断逻辑
- 调整了参数加载逻辑,提高了代码复用性
This commit is contained in:
Luke 2025-08-29 15:46:57 +08:00
parent 86a78bd1c6
commit 325ca67872

View File

@ -16,40 +16,62 @@ import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* {@code CallGenerator} 负责将 IR 层的 {@link CallInstruction} 生成对应的 VM 函数调用指令
* CallGenerator 负责将 IR 层的 CallInstruction 转换为 VM 层的函数调用指令
* <p>
* 支持 syscall普通函数调用一维/多维数组下标访问以及字符串常量池绑定等功能
* </p>
*
* 功能包括
* <ul>
* <li>syscall: 支持字符串常量与寄存器到子命令的绑定与解析</li>
* <li>数组下标访问: 支持所有主流基础类型 __index_b/s/i/l/f/d/r</li>
* <li>普通函数: 支持自动推断返回值类型与槽位类型</li>
* <li>处理系统调用syscall支持字符串常量池</li>
* <li>数组元素访问及赋值__index / __setindex 系列</li>
* <li>普通函数调用根据返回类型选择合适的 STORE 指令</li>
* </ul>
*/
public class CallGenerator implements InstructionGenerator<CallInstruction> {
/**
* 字符串常量池用于绑定虚拟寄存器 id 到字符串值 syscall 子命令使用
* <br>
* 使用 ConcurrentHashMap 保证并发安全所有 registerStringConst 的注册和读取都是线程安全的
* 字符串常量池用于 syscall 子命令的字符串存储
* 键为虚拟寄存器 ID值为字符串常量
*/
private static final Map<Integer, String> STRING_CONST_POOL = new ConcurrentHashMap<>();
/**
* 注册一个字符串常量绑定到虚拟寄存器 id
* 当前正在生成的函数名用于错误上下文
*/
private String fn;
/**
* 注册字符串常量到常量池
*
* @param regId 虚拟寄存器 id
* @param value 字符串常量
* @param regId 虚拟寄存器 ID
* @param value 字符串常量
*/
public static void registerStringConst(int regId, String value) {
STRING_CONST_POOL.put(regId, value);
}
/**
* 返回本生成器支持的 IR 指令类型
* 将语言层类型名映射为 VM 指令的类型前缀字符
*
* @return {@link CallInstruction} 类型的 Class 对象
* @param name 类型名称 "int", "double", "string"
* @return 对应的 VM 类型前缀'I','D','R'
*/
private static char normalizeTypePrefix(String name) {
if (name == null) return 'I';
String n = name.toLowerCase(Locale.ROOT);
return switch (n) {
case "byte" -> 'B';
case "short" -> 'S';
case "int", "integer", "bool", "boolean" -> 'I';
case "long" -> 'L';
case "float" -> 'F';
case "double" -> 'D';
case "string" -> 'R'; // 字符串为引用类型
case "void" -> 'V';
default -> 'R'; // 结构体自定义对象均视为引用类型
};
}
/**
* 返回本生成器支持的 IR 指令类型此处为 CallInstruction
*/
@Override
public Class<CallInstruction> supportedClass() {
@ -57,12 +79,12 @@ public class CallGenerator implements InstructionGenerator<CallInstruction> {
}
/**
* 生成指定的调用指令包括 syscall数组下标普通函数
* 核心生成方法根据函数名分发到 syscall数组操作或普通调用的处理逻辑
*
* @param ins IR 层的调用指令
* @param out VM 程序构建器
* @param slotMap 寄存器到槽位的映射
* @param currentFn 当前函数名
* @param ins 待转换的 IR 调用指令
* @param out VM 程序构建器用于输出指令
* @param slotMap IR 虚拟寄存器到 VM 本地槽位的映射
* @param currentFn 当前所在的函数名用于上下文传递
*/
@Override
public void generate(CallInstruction ins,
@ -71,91 +93,41 @@ public class CallGenerator implements InstructionGenerator<CallInstruction> {
String currentFn) {
String fn = ins.getFunctionName();
// 特殊处理 syscall 调用
// 处理特殊的 syscall 调用
if ("syscall".equals(fn) || fn.endsWith(".syscall")) {
generateSyscall(ins, out, slotMap, fn);
return;
}
// 各种一维数组类型byte/short/int/long/float/double/boolean读取
// 处理数组读取和写入的内置函数
switch (fn) {
case "__index_b" -> {
generateIndexInstruction(ins, out, slotMap, 'B');
return;
}
case "__index_s" -> {
generateIndexInstruction(ins, out, slotMap, 'S');
return;
}
case "__index_i" -> {
generateIndexInstruction(ins, out, slotMap, 'I');
return;
}
case "__index_l" -> {
generateIndexInstruction(ins, out, slotMap, 'L');
return;
}
case "__index_f" -> {
generateIndexInstruction(ins, out, slotMap, 'F');
return;
}
case "__index_d" -> {
generateIndexInstruction(ins, out, slotMap, 'D');
return;
}
case "__index_r" -> {
generateIndexInstruction(ins, out, slotMap, 'R');
return;
case "__index_b" -> { generateIndexInstruction(ins, out, slotMap, 'B'); return; }
case "__index_s" -> { generateIndexInstruction(ins, out, slotMap, 'S'); return; }
case "__index_i" -> { generateIndexInstruction(ins, out, slotMap, 'I'); return; }
case "__index_l" -> { generateIndexInstruction(ins, out, slotMap, 'L'); return; }
case "__index_f" -> { generateIndexInstruction(ins, out, slotMap, 'F'); return; }
case "__index_d" -> { generateIndexInstruction(ins, out, slotMap, 'D'); return; }
case "__index_r" -> { generateIndexInstruction(ins, out, slotMap, 'R'); return; }
case "__setindex_b" -> { generateSetIndexInstruction(ins, out, slotMap, 'B'); return; }
case "__setindex_s" -> { generateSetIndexInstruction(ins, out, slotMap, 'S'); return; }
case "__setindex_i" -> { generateSetIndexInstruction(ins, out, slotMap, 'I'); return; }
case "__setindex_l" -> { generateSetIndexInstruction(ins, out, slotMap, 'L'); return; }
case "__setindex_f" -> { generateSetIndexInstruction(ins, out, slotMap, 'F'); return; }
case "__setindex_d" -> { generateSetIndexInstruction(ins, out, slotMap, 'D'); return; }
case "__setindex_r" -> { generateSetIndexInstruction(ins, out, slotMap, 'R'); return; }
}
case "__setindex_b" -> {
generateSetIndexInstruction(ins, out, slotMap, 'B');
return;
}
case "__setindex_s" -> {
generateSetIndexInstruction(ins, out, slotMap, 'S');
return;
}
case "__setindex_i" -> {
generateSetIndexInstruction(ins, out, slotMap, 'I');
return;
}
case "__setindex_l" -> {
generateSetIndexInstruction(ins, out, slotMap, 'L');
return;
}
case "__setindex_f" -> {
generateSetIndexInstruction(ins, out, slotMap, 'F');
return;
}
case "__setindex_d" -> {
generateSetIndexInstruction(ins, out, slotMap, 'D');
return;
}
case "__setindex_r" -> {
generateSetIndexInstruction(ins, out, slotMap, 'R');
return;
}
}
// 普通函数调用
// 默认普通函数调用
generateNormalCall(ins, out, slotMap, fn);
}
// ========== 私有辅助方法 ==========
/**
* 生成数组元素赋值指令arr[idx] = value无返回值
* <p>
* 调用栈压栈顺序为arr (引用类型, R)idx (整型, I)value (元素类型, T)
* 执行 SYSCALL ARR_SET 指令以完成数组赋值操作
* </p>
* 生成数组元素赋值指令
*
* @param ins 当前的调用指令包含参数信息
* @param out VM 指令生成器用于输出 VM 指令
* @param slotMap 虚拟寄存器与槽位的映射表
* @param valType 待写入的 value 的类型标识'B': byte, 'S': short, 'I': int, 'L': long, 'F': float, 'D': double, 其余为引用类型'R'
* @throws IllegalStateException 如果参数数量不为3则抛出异常
* @param ins 调用 __setindex_* IR 指令
* @param out VM 指令构建器
* @param slotMap 寄存器到槽位映射
* @param valType 元素值的类型前缀 'I','R'
*/
private void generateSetIndexInstruction(CallInstruction ins,
VMProgramBuilder out,
@ -163,88 +135,175 @@ public class CallGenerator implements InstructionGenerator<CallInstruction> {
char valType) {
List<IRValue> args = ins.getArguments();
if (args.size() != 3) {
// 参数数量错误抛出异常并输出实际参数列表
throw new IllegalStateException(
"[CallGenerator] __setindex_* 需要三个参数(arr, idx, value),实际: " + args);
throw new IllegalStateException("[CallGenerator] __setindex_* 需要三个参数 (arr, idx, value),实际: " + args);
}
// 第一个参数为数组对象压入引用类型寄存器'R' arr
loadArgument(out, slotMap, args.get(0), 'R', ins.getFunctionName());
// 第二个参数为索引值压入整型寄存器'I' idx
loadArgument(out, slotMap, args.get(1), 'I', ins.getFunctionName());
// 第三个参数为待赋值元素根据元素类型压入相应类型寄存器
// 支持类型'B'(byte), 'S'(short), 'I'(int), 'L'(long), 'F'(float), 'D'(double)
// 其他情况如引用类型'R'处理
switch (valType) {
case 'B' -> loadArgument(out, slotMap, args.get(2), 'B', ins.getFunctionName());
case 'S' -> loadArgument(out, slotMap, args.get(2), 'S', ins.getFunctionName());
case 'I' -> loadArgument(out, slotMap, args.get(2), 'I', ins.getFunctionName());
case 'L' -> loadArgument(out, slotMap, args.get(2), 'L', ins.getFunctionName());
case 'F' -> loadArgument(out, slotMap, args.get(2), 'F', ins.getFunctionName());
case 'D' -> loadArgument(out, slotMap, args.get(2), 'D', ins.getFunctionName());
default -> loadArgument(out, slotMap, args.get(2), 'R', ins.getFunctionName());
loadArgument(out, slotMap, args.get(0), 'R', ins.getFunctionName()); // 数组引用
loadArgument(out, slotMap, args.get(1), 'I', ins.getFunctionName()); // 索引
loadArgument(out, slotMap, args.get(2), valType, ins.getFunctionName()); //
out.emit(VMOpCode.SYSCALL + " ARR_SET");
}
// 输出 VM 指令SYSCALL ARR_SET完成数组元素写入操作
out.emit(VMOpCode.SYSCALL + " " + "ARR_SET");
}
/**
* 解析 syscall 子命令第一个参数支持字符串常量与已绑定字符串的虚拟寄存器
* 生成数组元素读取指令
*
* @param arg 子命令参数应为字符串常量或寄存器
* @param fn 当前函数名仅用于报错信息
* @return 子命令大写字符串
* @throws IllegalStateException 如果参数不是字符串常量或已绑定寄存器
* @param ins 调用 __index_* IR 指令
* @param out VM 指令构建器
* @param slotMap 寄存器到槽位映射
* @param retType 返回值类型前缀
*/
private void generateIndexInstruction(CallInstruction ins,
VMProgramBuilder out,
Map<IRVirtualRegister, Integer> slotMap,
char retType) {
String fn = ins.getFunctionName();
List<IRValue> args = ins.getArguments();
if (args.size() != 2) {
throw new IllegalStateException("[CallGenerator] " + fn + " 需要两个参数 (arr, idx),实际: " + args);
}
loadArgument(out, slotMap, args.get(0), 'R', fn); // 数组引用
loadArgument(out, slotMap, args.get(1), 'I', fn); // 索引
out.emit(VMOpCode.SYSCALL + " ARR_GET");
IRVirtualRegister dest = ins.getDest();
if (dest == null) {
throw new IllegalStateException("[CallGenerator] " + fn + " 必须有返回值寄存器");
}
Integer destSlot = slotMap.get(dest);
if (destSlot == null) {
throw new IllegalStateException("[CallGenerator] " + fn + " 未找到目标槽位");
}
// 根据类型选择 STORE 指令
switch (retType) {
case 'B' -> out.emit(OpHelper.opcode("B_STORE") + " " + destSlot);
case 'S' -> out.emit(OpHelper.opcode("S_STORE") + " " + destSlot);
case 'I' -> out.emit(OpHelper.opcode("I_STORE") + " " + destSlot);
case 'L' -> out.emit(OpHelper.opcode("L_STORE") + " " + destSlot);
case 'F' -> out.emit(OpHelper.opcode("F_STORE") + " " + destSlot);
case 'D' -> out.emit(OpHelper.opcode("D_STORE") + " " + destSlot);
default -> out.emit(OpHelper.opcode("R_STORE") + " " + destSlot);
}
out.setSlotType(destSlot, retType);
}
/**
* 生成系统调用syscall指令
* 首个参数为子命令支持常量或寄存器引用其余参数均以引用形式加载
* 若存在返回寄存器则将结果存为整数类型
*
* @param ins syscall 对应的 IR 调用指令
* @param out VM 指令构建器
* @param slotMap 寄存器到槽位的映射
* @param fn 函数名"syscall" 或以 ".syscall" 结尾
*/
private void generateSyscall(CallInstruction ins,
VMProgramBuilder out,
Map<IRVirtualRegister, Integer> slotMap,
String fn) {
List<IRValue> args = ins.getArguments();
if (args.isEmpty()) {
throw new IllegalStateException("[CallGenerator] syscall 至少需要一个子命令");
}
String subcmd = resolveSyscallSubcmd(args.get(0), fn);
for (int i = 1; i < args.size(); i++) {
loadArgument(out, slotMap, args.get(i), 'R', fn);
}
out.emit(VMOpCode.SYSCALL + " " + subcmd);
IRVirtualRegister dest = ins.getDest();
if (dest != null) {
Integer slot = slotMap.get(dest);
if (slot == null) throw new IllegalStateException("[CallGenerator] syscall 未找到目标槽位");
out.emit(OpHelper.opcode("I_STORE") + " " + slot);
out.setSlotType(slot, 'I');
}
}
/**
* 解析 syscall 子命令字符串
* 若为 IRConstant则直接取字符串值
* 若为 IRVirtualRegister则从常量池中获取
* 最终返回大写子命令名称
*
* @param arg 第一个参数常量或虚拟寄存器
* @param fn 所属函数名用于错误提示
* @return 大写的子命令字符串
* @throws IllegalStateException 参数类型或常量池缺失时抛出
*/
private String resolveSyscallSubcmd(IRValue arg, String fn) {
switch (arg) {
case IRConstant(String s) -> {
if (arg instanceof IRConstant(Object value)) {
if (value instanceof String s) {
return s.toUpperCase(Locale.ROOT);
}
case IRConstant(Object value) -> throw new IllegalStateException(
"[CallGenerator] syscall 第一个参数必须是字符串常量 (function: %s, value: %s)"
.formatted(fn, value)
);
case IRVirtualRegister(int id) -> {
throw new IllegalStateException("[CallGenerator] syscall 子命令必须是字符串 (函数: " + fn + ")");
}
if (arg instanceof IRVirtualRegister(int id)) {
String s = STRING_CONST_POOL.get(id);
if (s == null) {
throw new IllegalStateException(
"[CallGenerator] 未找到 syscall 字符串常量绑定 (function: %s, regId: %d)"
.formatted(fn, id)
);
}
if (s == null) throw new IllegalStateException("[CallGenerator] 未注册的 syscall 字符串常量");
return s.toUpperCase(Locale.ROOT);
}
case null, default -> throw new IllegalStateException(
"[CallGenerator] syscall 第一个参数必须是字符串常量或已绑定字符串的寄存器 (function: %s, arg: %s)"
.formatted(fn, arg)
);
}
throw new IllegalStateException("[CallGenerator] syscall 子命令参数错误: " + arg);
}
/**
* 加载一个参数到栈支持指定默认类型如果未设置类型则采用默认类型
* 生成普通函数调用指令
* 参数均以引用形式压栈调用完成后若返回类型非 void
* 则选择合适的 STORE 指令保存结果
*
* @param out VM 程序构建器
* @param slotMap 寄存器到槽位的映射
* @param arg 参数值应为虚拟寄存器
* @param defaultType 默认类型
* @param fn 当前函数名用于错误提示
* @throws IllegalStateException 如果参数不是虚拟寄存器或槽位未找到
* @param ins 调用指令
* @param out 指令构建器
* @param slotMap 寄存器到槽位映射
* @param fn 被调用函数名称
*/
private void loadArgument(VMProgramBuilder out, Map<IRVirtualRegister, Integer> slotMap, IRValue arg, char defaultType, String fn) {
private void generateNormalCall(CallInstruction ins,
VMProgramBuilder out,
Map<IRVirtualRegister, Integer> slotMap,
String fn) {
String retTypeName = GlobalFunctionTable.getReturnType(fn);
char retType = normalizeTypePrefix(retTypeName);
for (IRValue arg : ins.getArguments()) {
loadArgument(out, slotMap, arg, 'R', fn);
}
out.emitCall(fn, ins.getArguments().size());
if ("void".equals(retTypeName)) {
return;
}
IRVirtualRegister dest = ins.getDest();
if (dest == null) {
throw new IllegalStateException("[CallGenerator] 普通调用缺少返回寄存器");
}
Integer slot = slotMap.get(dest);
if (slot == null) {
throw new IllegalStateException("[CallGenerator] 未找到返回槽位");
}
out.emit(OpHelper.opcode(retType + "_STORE") + " " + slot);
out.setSlotType(slot, retType);
}
/**
* 加载参数
* 验证为虚拟寄存器后获取槽位和类型
* 缺省时使用 defaultType然后发出 LOAD 指令
*
* @param out 指令构建器
* @param slotMap 寄存器到槽位映射
* @param arg IR 参数值
* @param defaultType 缺省类型前缀
* @param fn 所属函数名用于错误提示
*/
private void loadArgument(VMProgramBuilder out,
Map<IRVirtualRegister, Integer> slotMap,
IRValue arg,
char defaultType,
String fn) {
this.fn = fn;
if (!(arg instanceof IRVirtualRegister vr)) {
throw new IllegalStateException(
"[CallGenerator] 参数必须为虚拟寄存器 (function: %s, arg: %s)".formatted(fn, arg));
throw new IllegalStateException("[CallGenerator] 参数必须是 IRVirtualRegister");
}
Integer slot = slotMap.get(vr);
if (slot == null) {
throw new IllegalStateException(
"[CallGenerator] 未找到虚拟寄存器的槽位映射 (function: %s, reg: %s)".formatted(fn, vr));
throw new IllegalStateException("[CallGenerator] 未找到参数槽位");
}
char t = out.getSlotType(slot);
if (t == '\0') t = defaultType;
@ -252,175 +311,11 @@ public class CallGenerator implements InstructionGenerator<CallInstruction> {
}
/**
* 生成一维/多维数组的下标访问指令支持类型分派
* <p>
* 本方法用于将 IR 层的数组下标访问表达式 arr[idx]生成对应的 VM 指令序列
* 支持 byte/short/int/long/float/double/reference 等所有基础类型的数组元素访问
* </p>
* 返回最近一次处理的函数名可用于调试
*
* <ul>
* <li>1. 依次加载数组参数arr和下标参数idx到操作数栈</li>
* <li>2. 发出 ARR_GET 系统调用指令SYSCALL ARR_GET通过 VM 访问对应元素</li>
* <li>3. 根据元素声明类型将结果写入目标槽位支持类型分派B/S/I/L/F/D/R</li>
* <li>4. 若参数或返回寄存器缺失则抛出异常提示</li>
* </ul>
*
* @param ins 下标访问对应的 IR 调用指令函数名通常为 __index_x
* @param out VM 程序构建器用于发出 VM 指令
* @param slotMap IR 虚拟寄存器到 VM 槽位的映射表
* @param retType 元素类型标识'B' byte, 'S' short, 'I' int, 'L' long, 'F' float, 'D' double, 'R' ref/obj
* @throws IllegalStateException 参数个数不符缺少目标寄存器未找到槽位等情况
* @return 函数名字符串
*/
private void generateIndexInstruction(CallInstruction ins, VMProgramBuilder out, Map<IRVirtualRegister, Integer> slotMap, char retType) {
String fn = ins.getFunctionName();
List<IRValue> args = ins.getArguments();
if (args.size() != 2) {
throw new IllegalStateException(
"[CallGenerator] %s 需要两个参数(arr, idx),实际: %s".formatted(fn, args));
}
// 加载数组参数寄存器类型按 R/ref 处理默认对象槽位
loadArgument(out, slotMap, args.get(0), 'R', fn);
// 加载下标参数寄存器类型按 I/int 处理
loadArgument(out, slotMap, args.get(1), 'I', fn);
// 发出 ARR_GET 系统调用元素访问由 VM 完成类型分派
out.emit(VMOpCode.SYSCALL + " " + "ARR_GET");
// 保存返回值到目标寄存器
IRVirtualRegister dest = ins.getDest();
if (dest == null) {
throw new IllegalStateException(
"[CallGenerator] %s 需要有目标寄存器用于保存返回值".formatted(fn));
}
Integer destSlot = slotMap.get(dest);
if (destSlot == null) {
throw new IllegalStateException(
"[CallGenerator] %s 未找到目标寄存器的槽位映射 (dest: %s)".formatted(fn, dest));
}
// 按元素类型分派写入 VM 槽位
switch (retType) {
case 'B' -> {
out.emit(OpHelper.opcode("B_STORE") + " " + destSlot);
out.setSlotType(destSlot, 'B');
}
case 'S' -> {
out.emit(OpHelper.opcode("S_STORE") + " " + destSlot);
out.setSlotType(destSlot, 'S');
}
case 'I' -> {
out.emit(OpHelper.opcode("I_STORE") + " " + destSlot);
out.setSlotType(destSlot, 'I');
}
case 'L' -> {
out.emit(OpHelper.opcode("L_STORE") + " " + destSlot);
out.setSlotType(destSlot, 'L');
}
case 'F' -> {
out.emit(OpHelper.opcode("F_STORE") + " " + destSlot);
out.setSlotType(destSlot, 'F');
}
case 'D' -> {
out.emit(OpHelper.opcode("D_STORE") + " " + destSlot);
out.setSlotType(destSlot, 'D');
}
default -> {
out.emit(OpHelper.opcode("R_STORE") + " " + destSlot);
out.setSlotType(destSlot, 'R');
}
}
}
/**
* 生成 syscall 指令分支逻辑
* <ol>
* <li>解析 syscall 子命令</li>
* <li>压栈剩余参数</li>
* <li>发出 SYSCALL 指令</li>
* <li>若有返回值则保存至目标槽位</li>
* </ol>
*
* @param ins 调用指令
* @param out VM 程序构建器
* @param slotMap 寄存器到槽位映射
* @param fn 当前函数名
*/
private void generateSyscall(CallInstruction ins, VMProgramBuilder out, Map<IRVirtualRegister, Integer> slotMap, String fn) {
List<IRValue> args = ins.getArguments();
if (args.isEmpty()) {
throw new IllegalStateException(
"[CallGenerator] syscall 需要子命令参数 (function: %s)".formatted(fn));
}
// 0. 解析 syscall 子命令第一个参数
String subcmd = resolveSyscallSubcmd(args.getFirst(), fn);
// 1. 压栈其余 syscall 参数 index 1 开始
for (int i = 1; i < args.size(); i++) {
loadArgument(out, slotMap, args.get(i), 'R', fn);
}
// 2. 生成 SYSCALL 指令
out.emit(VMOpCode.SYSCALL + " " + subcmd);
// 3. 有返回值则保存到目标槽位
IRVirtualRegister dest = ins.getDest();
if (dest != null) {
Integer destSlot = slotMap.get(dest);
if (destSlot == null) {
throw new IllegalStateException(
"[CallGenerator] syscall 未找到目标寄存器的槽位映射 (function: %s, dest: %s)"
.formatted(fn, dest));
}
out.emit(OpHelper.opcode("I_STORE") + " " + destSlot);
out.setSlotType(destSlot, 'I');
}
}
/**
* 生成普通函数调用指令
* <ol>
* <li>推断返回值类型</li>
* <li>压栈所有参数</li>
* <li>生成 CALL 指令</li>
* <li>保存返回值若非 void</li>
* </ol>
*
* @param ins 调用指令
* @param out VM 程序构建器
* @param slotMap 寄存器到槽位映射
* @param fn 当前函数名
*/
private void generateNormalCall(CallInstruction ins, VMProgramBuilder out, Map<IRVirtualRegister, Integer> slotMap, String fn) {
// 1. 推断返回值类型首字母大写缺省为 'I'
String retTypeName = GlobalFunctionTable.getReturnType(fn);
char retType = (retTypeName != null && !retTypeName.isEmpty()) ? Character.toUpperCase(retTypeName.charAt(0)) : 'I';
// 2. 压栈所有参数
for (IRValue arg : ins.getArguments()) {
loadArgument(out, slotMap, arg, 'R', fn);
}
// 3. 发出 CALL 指令
out.emitCall(fn, ins.getArguments().size());
// 3.5 void 返回直接结束
if ("void".equals(retTypeName)) {
return;
}
// 4. 保存返回值到目标寄存器
IRVirtualRegister dest = ins.getDest();
if (dest == null) {
throw new IllegalStateException(
"[CallGenerator] 普通函数调用未找到目标寄存器 (function: %s)".formatted(fn));
}
Integer destSlot = slotMap.get(dest);
if (destSlot == null) {
throw new IllegalStateException(
"[CallGenerator] 普通函数调用未找到目标寄存器的槽位映射 (function: %s, dest: %s)".formatted(fn, dest));
}
out.emit(OpHelper.opcode(retType + "_STORE") + " " + destSlot);
out.setSlotType(destSlot, retType);
public String getFn() {
return fn;
}
}